3 # Test script utility class
5 # Mark Huang <mlhuang@cs.princeton.edu>
6 # Copyright (C) 2006 The Trustees of Princeton University
11 from pprint import pprint
12 from string import letters, digits, punctuation
13 from traceback import print_exc
14 from optparse import OptionParser
21 from PLC.Shell import Shell
23 from random import Random
26 def randfloat(min = 0.0, max = 1.0):
27 return float(min) + (random.random() * (float(max) - float(min)))
29 def randint(min = 0, max = 1):
30 return int(randfloat(min, max + 1))
32 # See "2.2 Characters" in the XML specification:
34 # #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD]
36 # [#x7F-#x84], [#x86-#x9F], [#xFDD0-#xFDDF]
39 ascii_xml_chars = map(unichr, [0x9, 0xA])
40 # xmlrpclib uses xml.parsers.expat, which always converts either '\r'
41 # (#xD) or '\n' (#xA) to '\n'. So avoid using '\r', too, if this is
43 if xmlrpclib.loads(xmlrpclib.dumps(('\r',)))[0][0] == '\r':
44 ascii_xml_chars.append('\r')
45 ascii_xml_chars += map(unichr, xrange(0x20, 0x7F - 1))
46 low_xml_chars = list(ascii_xml_chars)
47 low_xml_chars += map(unichr, xrange(0x84 + 1, 0x86 - 1))
48 low_xml_chars += map(unichr, xrange(0x9F + 1, 0xFF))
49 valid_xml_chars = list(low_xml_chars)
50 valid_xml_chars += map(unichr, xrange(0xFF + 1, 0xD7FF))
51 valid_xml_chars += map(unichr, xrange(0xE000, 0xFDD0 - 1))
52 valid_xml_chars += map(unichr, xrange(0xFDDF + 1, 0xFFFD))
54 def randstr(length, pool = valid_xml_chars, encoding = "utf-8"):
55 sample = random.sample(pool, min(length, len(pool)))
58 bytes = len(s.encode(encoding))
62 sample += random.sample(pool, min(length - bytes, len(pool)))
63 random.shuffle(sample)
69 # 1. Each part begins and ends with a letter or number.
70 # 2. Each part except the last can contain letters, numbers, or hyphens.
71 # 3. Each part is between 1 and 64 characters, including the trailing dot.
72 # 4. At least two parts.
73 # 5. Last part can only contain between 2 and 6 letters.
74 hostname = 'a' + randstr(61, letters + digits + '-') + '1.' + \
75 'b' + randstr(61, letters + digits + '-') + '2.' + \
76 'c' + randstr(5, letters)
81 for i in range(randint(1, 10)):
82 parts.append(randstr(randint(1, 30), ascii_xml_chars))
83 return u'/'.join(parts)[0:length]
86 return (randstr(100, letters + digits) + "@" + randhostname()).lower()
88 def randkey(bits = 2048):
89 ssh_key_types = ["ssh-dss", "ssh-rsa"]
90 key_type = random.sample(ssh_key_types, 1)[0]
91 return ' '.join([key_type,
92 base64.b64encode(''.join(randstr(bits / 8).encode("utf-8"))),
98 'abbreviated_name': randstr(50),
99 'login_base': randstr(20, letters).lower(),
100 'latitude': int(randfloat(-90.0, 90.0) * 1000) / 1000.0,
101 'longitude': int(randfloat(-180.0, 180.0) * 1000) / 1000.0,
104 def random_address_type():
107 'description': randstr(254),
110 def random_address():
112 'line1': randstr(254),
113 'line2': randstr(254),
114 'line3': randstr(254),
115 'city': randstr(254),
116 'state': randstr(254),
117 'postalcode': randstr(64),
118 'country': randstr(128),
123 'first_name': randstr(128),
124 'last_name': randstr(128),
125 'email': randemail(),
127 # Accounts are disabled by default
129 'password': randstr(254),
132 def random_key(key_types):
134 'key_type': random.sample(key_types, 1)[0],
138 def random_tag_type (role_ids):
139 return {'tagname': randstr(12),
140 'category':randstr(8),
141 'min_role_id': random.sample(role_ids, 1)[0],
142 'description' : randstr(128),
145 def random_nodegroup():
146 return {'groupname' : randstr(50) }
148 def random_node(boot_states):
150 'hostname': randhostname(),
151 'boot_state': random.sample(boot_states, 1)[0],
152 'model': randstr(255),
153 'version': randstr(64),
156 def random_interface(method, type):
160 'bwlimit': randint(500000, 10000000),
164 ip = randint(0, 0xffffffff)
165 netmask = (0xffffffff << randint(2, 31)) & 0xffffffff
166 network = ip & netmask
167 broadcast = ((ip & netmask) | ~netmask) & 0xffffffff
168 gateway = randint(network + 1, broadcast - 1)
169 dns1 = randint(0, 0xffffffff)
171 for field in 'ip', 'netmask', 'network', 'broadcast', 'gateway', 'dns1':
172 interface_fields[field] = socket.inet_ntoa(struct.pack('>L', locals()[field]))
174 return interface_fields
181 'hostname': randhostname(),
182 'ip': socket.inet_ntoa(struct.pack('>L', randint(0, 0xffffffff))),
183 'protocol': randstr(16),
184 'username': randstr(254),
185 'password': randstr(254),
186 'notes': randstr(254),
187 'model': randstr(32),
190 def random_conf_file():
192 'enabled': bool(randint()),
193 'source': randpath(255),
194 'dest': randpath(255),
195 'file_permissions': "%#o" % randint(0, 512),
196 'file_owner': randstr(32, letters + '_' + digits),
197 'file_group': randstr(32, letters + '_' + digits),
198 'preinstall_cmd': randpath(100),
199 'postinstall_cmd': randpath(100),
200 'error_cmd': randpath(100),
201 'ignore_cmd_errors': bool(randint()),
202 'always_update': bool(randint()),
205 def random_slice(login_base):
207 'name': login_base + "_" + randstr(11, letters).lower(),
208 'url': "http://" + randhostname() + "/",
209 'description': randstr(2048),
216 'addresses_per_site': 1,
217 'persons_per_site': 1,
218 'keys_per_person': 1,
222 'interfaces_per_node': 1,
226 'slices_per_site': 1,
227 'attributes_per_slice': 1,
233 'addresses_per_site': 2,
234 'persons_per_site': 4,
235 'keys_per_person': 2,
239 'interfaces_per_node': 1,
243 'slices_per_site': 4,
244 'attributes_per_slice': 2,
247 def __init__(self, api, check = True, verbose = True, preserve = False):
250 self.verbose = verbose
251 self.preserve = preserve
254 self.address_type_ids = []
255 self.address_ids = []
258 self.slice_type_ids = []
259 self.nodegroup_type_ids = []
260 self.ilink_type_ids = []
261 self.nodegroup_ids = []
263 self.interface_ids = []
266 self.conf_file_ids = []
268 self.slice_tag_ids = []
270 def Run(self, **kwds):
272 Run a complete database and API consistency test. Populates
273 the database with a set of random entities, updates them, then
274 deletes them. Examples:
276 test.Run() # Defaults
277 test.Run(**Test.default) # Defaults
278 test.Run(**Test.tiny) # Tiny set
279 test.Run(sites = 123, slices_per_site = 4) # Defaults with overrides
285 print 'Preserving - delete skipped'
289 def Add(self, **kwds):
291 Populate the database with a set of random entities. Examples:
293 test.populate() # Defaults
294 test.populate(Test.tiny) # Tiny set
295 test.populate(sites = 123, slices_per_site = 4) # Defaults with overrides
298 params = self.default.copy()
301 self.AddSites(params['sites'])
302 self.AddAddressTypes(params['address_types'])
303 self.AddAddresses(params['addresses_per_site'])
304 self.AddPersons(params['persons_per_site'])
305 self.AddKeys(params['keys_per_person'])
306 self.AddTagTypes(params['slice_tags'],params['nodegroups'],params['ilinks'])
307 self.AddNodeGroups(params['nodegroups'])
308 self.AddNodes(params['nodes_per_site'])
309 self.AddInterfaces(params['interfaces_per_node'])
310 self.AddIlinks (params['ilinks'])
311 self.AddPCUs(params['pcus_per_site'])
312 self.AddConfFiles(params['conf_files'])
313 self.AddSlices(params['slices_per_site'])
314 self.AddSliceTags(params['attributes_per_slice'])
318 self.UpdateAddressTypes()
319 self.UpdateAddresses()
322 self.UpdateTagTypes()
323 self.UpdateNodeGroups()
325 self.UpdateInterfaces()
328 self.UpdateConfFiles()
330 self.UpdateSliceTags()
333 self.DeleteSliceTags()
336 self.DeleteConfFiles()
339 self.DeleteInterfaces()
342 self.DeleteNodeGroups()
343 self.DeleteTagTypes()
344 self.DeleteAddresses()
345 self.DeleteAddressTypes()
348 def AddSites(self, n = 10):
350 Add a number of random sites.
355 site_fields = random_site()
356 site_id = self.api.AddSite(site_fields)
358 # Should return a unique site_id
359 assert site_id not in self.site_ids
360 self.site_ids.append(site_id)
362 # Enable slice creation
363 site_fields['max_slices'] = randint(1, 10)
364 self.api.UpdateSite(site_id, site_fields)
368 site = self.api.GetSites([site_id])[0]
369 for field in site_fields:
370 assert site[field] == site_fields[field]
373 print "Added site", site_id
375 def UpdateSites(self):
377 Make random changes to any sites we may have added.
380 for site_id in self.site_ids:
382 site_fields = random_site()
383 # Do not change login_base
384 if 'login_base' in site_fields:
385 del site_fields['login_base']
386 self.api.UpdateSite(site_id, site_fields)
390 site = self.api.GetSites([site_id])[0]
391 for field in site_fields:
392 assert site[field] == site_fields[field]
395 print "Updated site", site_id
397 def DeleteSites(self):
399 Delete any random sites we may have added.
402 for site_id in self.site_ids:
403 self.api.DeleteSite(site_id)
406 assert not self.api.GetSites([site_id])
409 print "Deleted site", site_id
412 assert not self.api.GetSites(self.site_ids)
416 def AddAddressTypes(self, n = 2):
418 Add a number of random address types.
422 address_type_fields = random_address_type()
423 address_type_id = self.api.AddAddressType(address_type_fields)
425 # Should return a unique address_type_id
426 assert address_type_id not in self.address_type_ids
427 self.address_type_ids.append(address_type_id)
431 address_type = self.api.GetAddressTypes([address_type_id])[0]
432 for field in address_type_fields:
433 assert address_type[field] == address_type_fields[field]
436 print "Added address type", address_type_id
438 def UpdateAddressTypes(self):
440 Make random changes to any address types we may have added.
443 for address_type_id in self.address_type_ids:
444 # Update address_type
445 address_type_fields = random_address_type()
446 self.api.UpdateAddressType(address_type_id, address_type_fields)
450 address_type = self.api.GetAddressTypes([address_type_id])[0]
451 for field in address_type_fields:
452 assert address_type[field] == address_type_fields[field]
455 print "Updated address_type", address_type_id
457 def DeleteAddressTypes(self):
459 Delete any random address types we may have added.
462 for address_type_id in self.address_type_ids:
463 self.api.DeleteAddressType(address_type_id)
466 assert not self.api.GetAddressTypes([address_type_id])
469 print "Deleted address type", address_type_id
472 assert not self.api.GetAddressTypes(self.address_type_ids)
474 self.address_type_ids = []
476 def AddAddresses(self, per_site = 2):
478 Add a number of random addresses to each site.
481 for site_id in self.site_ids:
482 for i in range(per_site):
483 address_fields = random_address()
484 address_id = self.api.AddSiteAddress(site_id, address_fields)
486 # Should return a unique address_id
487 assert address_id not in self.address_ids
488 self.address_ids.append(address_id)
490 # Add random address type
491 if self.address_type_ids:
492 for address_type_id in random.sample(self.address_type_ids, 1):
493 self.api.AddAddressTypeToAddress(address_type_id, address_id)
497 address = self.api.GetAddresses([address_id])[0]
498 for field in address_fields:
499 assert address[field] == address_fields[field]
502 print "Added address", address_id, "to site", site_id
504 def UpdateAddresses(self):
506 Make random changes to any addresses we may have added.
509 for address_id in self.address_ids:
511 address_fields = random_address()
512 self.api.UpdateAddress(address_id, address_fields)
516 address = self.api.GetAddresses([address_id])[0]
517 for field in address_fields:
518 assert address[field] == address_fields[field]
521 print "Updated address", address_id
523 def DeleteAddresses(self):
525 Delete any random addresses we may have added.
528 for address_id in self.address_ids:
529 # Remove address types
530 address = self.api.GetAddresses([address_id])[0]
531 for address_type_id in address['address_type_ids']:
532 self.api.DeleteAddressTypeFromAddress(address_type_id, address_id)
535 address = self.api.GetAddresses([address_id])[0]
536 assert not address['address_type_ids']
538 self.api.DeleteAddress(address_id)
541 assert not self.api.GetAddresses([address_id])
544 print "Deleted address", address_id
547 assert not self.api.GetAddresses(self.address_ids)
549 self.address_ids = []
551 def AddPersons(self, per_site = 10):
553 Add a number of random users to each site.
556 for site_id in self.site_ids:
557 for i in range(per_site):
559 person_fields = random_person()
560 person_id = self.api.AddPerson(person_fields)
562 # Should return a unique person_id
563 assert person_id not in self.person_ids
564 self.person_ids.append(person_id)
568 person = self.api.GetPersons([person_id])[0]
569 for field in person_fields:
570 if field != 'password':
571 assert person[field] == person_fields[field]
573 auth = {'AuthMethod': "password",
574 'Username': person_fields['email'],
575 'AuthString': person_fields['password']}
578 # Check that user is disabled
580 assert not self.api.AuthCheck(auth)
584 # Add random set of roles
585 role_ids = random.sample([20, 30, 40], randint(1, 3))
586 for role_id in role_ids:
587 self.api.AddRoleToPerson(role_id, person_id)
590 person = self.api.GetPersons([person_id])[0]
591 assert set(role_ids) == set(person['role_ids'])
594 self.api.UpdatePerson(person_id, {'enabled': True})
597 # Check that user is enabled
598 assert self.api.AuthCheck(auth)
600 # Associate user with site
601 self.api.AddPersonToSite(person_id, site_id)
602 self.api.SetPersonPrimarySite(person_id, site_id)
605 person = self.api.GetPersons([person_id])[0]
606 assert person['site_ids'][0] == site_id
609 print "Added user", person_id, "to site", site_id
611 def UpdatePersons(self):
613 Make random changes to any users we may have added.
616 for person_id in self.person_ids:
618 person_fields = random_person()
620 person_fields['enabled'] = True
621 self.api.UpdatePerson(person_id, person_fields)
625 person = self.api.GetPersons([person_id])[0]
626 for field in person_fields:
627 if field != 'password':
628 assert person[field] == person_fields[field]
631 print "Updated person", person_id
633 person = self.api.GetPersons([person_id])[0]
635 # Associate user with a random set of sites
636 site_ids = random.sample(self.site_ids, randint(0, len(self.site_ids)))
637 for site_id in (set(site_ids) - set(person['site_ids'])):
638 self.api.AddPersonToSite(person_id, site_id)
639 for site_id in (set(person['site_ids']) - set(site_ids)):
640 self.api.DeletePersonFromSite(person_id, site_id)
643 self.api.SetPersonPrimarySite(person_id, site_ids[0])
646 person = self.api.GetPersons([person_id])[0]
647 assert set(site_ids) == set(person['site_ids'])
650 print "Updated person", person_id, "to sites", site_ids
652 def DeletePersons(self):
654 Delete any random users we may have added.
657 for person_id in self.person_ids:
659 person = self.api.GetPersons([person_id])[0]
660 for site_id in person['site_ids']:
661 self.api.DeletePersonFromSite(person_id, site_id)
664 person = self.api.GetPersons([person_id])[0]
665 assert not person['site_ids']
668 for role_id in person['role_ids']:
669 self.api.DeleteRoleFromPerson(role_id, person_id)
672 person = self.api.GetPersons([person_id])[0]
673 assert not person['role_ids']
676 self.api.UpdatePerson(person_id, {'enabled': False})
679 person = self.api.GetPersons([person_id])[0]
680 assert not person['enabled']
683 self.api.DeletePerson(person_id)
686 assert not self.api.GetPersons([person_id])
689 print "Deleted user", person_id
692 assert not self.api.GetPersons(self.person_ids)
696 def AddKeys(self, per_person = 2):
698 Add a number of random keys to each user.
701 key_types = self.api.GetKeyTypes()
703 raise Exception, "No key types"
705 for person_id in self.person_ids:
706 for i in range(per_person):
708 key_fields = random_key(key_types)
709 key_id = self.api.AddPersonKey(person_id, key_fields)
711 # Should return a unique key_id
712 assert key_id not in self.key_ids
713 self.key_ids.append(key_id)
717 key = self.api.GetKeys([key_id])[0]
718 for field in key_fields:
719 assert key[field] == key_fields[field]
721 # Add and immediately blacklist a key
722 key_fields = random_key(key_types)
723 key_id = self.api.AddPersonKey(person_id, key_fields)
725 self.api.BlacklistKey(key_id)
727 # Is effectively deleted
728 assert not self.api.GetKeys([key_id])
730 # Cannot be added again
732 key_id = self.api.AddPersonKey(person_id, key_fields)
738 print "Added key", key_id, "to user", person_id
740 def UpdateKeys(self):
742 Make random changes to any keys we may have added.
745 key_types = self.api.GetKeyTypes()
747 raise Exception, "No key types"
749 for key_id in self.key_ids:
751 key_fields = random_key(key_types)
752 self.api.UpdateKey(key_id, key_fields)
756 key = self.api.GetKeys([key_id])[0]
757 for field in key_fields:
758 assert key[field] == key_fields[field]
761 print "Updated key", key_id
763 def DeleteKeys(self):
765 Delete any random keys we may have added.
768 for key_id in self.key_ids:
769 self.api.DeleteKey(key_id)
772 assert not self.api.GetKeys([key_id])
775 print "Deleted key", key_id
778 assert not self.api.GetKeys(self.key_ids)
782 def AddNodeGroups(self, n = 10):
784 Add a number of random node groups.
789 tag_type_id = self.nodegroup_type_ids[i]
790 tagname=self.api.GetTagTypes([tag_type_id])[0]['tagname']
793 groupname = random_nodegroup() ['groupname']
795 nodegroup_id = self.api.AddNodeGroup(groupname, tagname, tagvalue)
797 # Should return a unique nodegroup_id
798 assert nodegroup_id not in self.nodegroup_ids
799 self.nodegroup_ids.append(nodegroup_id)
803 nodegroup = self.api.GetNodeGroups([nodegroup_id])[0]
804 assert nodegroup['groupname'] == groupname
805 assert nodegroup['tagname'] == tagname
806 assert nodegroup['tagvalue'] == tagvalue
809 print "Added node group", nodegroup_id
811 def UpdateNodeGroups(self):
813 Make random changes to any node groups we may have added.
816 for nodegroup_id in self.nodegroup_ids:
818 groupname = random_nodegroup()['groupname']
819 # cannot change tagname
820 nodegroup_fields = { 'groupname':groupname }
821 self.api.UpdateNodeGroup(nodegroup_id, nodegroup_fields)
825 nodegroup = self.api.GetNodeGroups([nodegroup_id])[0]
826 for field in nodegroup_fields:
827 assert nodegroup[field] == nodegroup_fields[field]
830 print "Updated node group", nodegroup_id
832 def DeleteNodeGroups(self):
834 Delete any random node groups we may have added.
837 for nodegroup_id in self.nodegroup_ids:
838 self.api.DeleteNodeGroup(nodegroup_id)
841 assert not self.api.GetNodeGroups([nodegroup_id])
844 print "Deleted node group", nodegroup_id
847 assert not self.api.GetNodeGroups(self.nodegroup_ids)
849 self.nodegroup_ids = []
851 def AddNodes(self, per_site = 2):
853 Add a number of random nodes to each site. Each node will also
854 be added to a random node group if AddNodeGroups() was
858 boot_states = self.api.GetBootStates()
860 raise Exception, "No boot states"
862 for site_id in self.site_ids:
863 for i in range(per_site):
865 node_fields = random_node(boot_states)
866 node_id = self.api.AddNode(site_id, node_fields)
868 # Should return a unique node_id
869 assert node_id not in self.node_ids
870 self.node_ids.append(node_id)
872 # Add to a random set of node groups
873 nodegroup_ids = random.sample(self.nodegroup_ids, randint(0, len(self.nodegroup_ids)))
874 for nodegroup_id in nodegroup_ids:
875 tagname = self.api.GetNodeGroups([nodegroup_id])[0]['tagname']
876 self.api.AddNodeTag( node_id, tagname, 'yes' )
880 node = self.api.GetNodes([node_id])[0]
881 for field in node_fields:
882 assert node[field] == node_fields[field]
885 print "Added node", node_id
887 def UpdateNodes(self):
889 Make random changes to any nodes we may have added.
892 boot_states = self.api.GetBootStates()
894 raise Exception, "No boot states"
896 for node_id in self.node_ids:
898 node_fields = random_node(boot_states)
899 self.api.UpdateNode(node_id, node_fields)
901 node = self.api.GetNodes([node_id])[0]
903 # Add to a random set of node groups
904 nodegroup_ids = random.sample(self.nodegroup_ids, randint(0, len(self.nodegroup_ids)))
905 for nodegroup_id in (set(nodegroup_ids) - set(node['nodegroup_ids'])):
906 nodegroup = self.api.GetNodeGroups([nodegroup_id])[0]
907 tagname = nodegroup['tagname']
908 node_tags = self.api.GetNodeTags({'node_id':node_id,'tagname':tagname})
910 self.api.AddNodeTag(node_id,tagname,'yes')
912 node_tag=node_tags[0]
913 self.api.UpdateNodeTag(node_tag['node_tag_id'],'yes')
914 for nodegroup_id in (set(node['nodegroup_ids']) - set(nodegroup_ids)):
915 nodegroup = self.api.GetNodeGroups([nodegroup_id])[0]
916 tagname = nodegroup['tagname']
917 node_tags = self.api.GetNodeTags({'node_id':node_id,'tagname':tagname})
919 self.api.AddNodeTag(node_id,tagname,'no')
921 node_tag=node_tags[0]
922 self.api.UpdateNodeTag(node_tag['node_tag_id'],'no')
926 node = self.api.GetNodes([node_id])[0]
927 for field in node_fields:
928 assert node[field] == node_fields[field]
929 assert set(nodegroup_ids) == set(node['nodegroup_ids'])
932 print "Updated node", node_id
934 def DeleteNodes(self):
936 Delete any random nodes we may have added.
939 for node_id in self.node_ids:
940 # Remove from node groups
941 node = self.api.GetNodes([node_id])[0]
942 for node_tag in GetNodeTags ( {'node_id': node_id} ):
943 self.api.UpdateNodeTag(node_tag['node_tag_id'],'')
946 node = self.api.GetNodes([node_id])[0]
947 assert not node['nodegroup_ids']
949 self.api.DeleteNode(node_id)
952 assert not self.api.GetNodes([node_id])
955 print "Deleted node", node_id
958 assert not self.api.GetNodes(self.node_ids)
962 def AddInterfaces(self, per_node = 1):
964 Add a number of random network interfaces to each node.
967 network_methods = self.api.GetNetworkMethods()
968 if not network_methods:
969 raise Exception, "No network methods"
971 network_types = self.api.GetNetworkTypes()
972 if not network_types:
973 raise Exception, "No network types"
975 for node_id in self.node_ids:
976 for i in range(per_node):
977 method = random.sample(network_methods, 1)[0]
978 type = random.sample(network_types, 1)[0]
981 interface_fields = random_interface(method, type)
982 interface_id = self.api.AddInterface(node_id, interface_fields)
984 # Should return a unique interface_id
985 assert interface_id not in self.interface_ids
986 self.interface_ids.append(interface_id)
990 interface = self.api.GetInterfaces([interface_id])[0]
991 for field in interface_fields:
992 assert interface[field] == interface_fields[field]
995 print "Added interface", interface_id, "to node", node_id
997 def UpdateInterfaces(self):
999 Make random changes to any network interfaces we may have added.
1002 network_methods = self.api.GetNetworkMethods()
1003 if not network_methods:
1004 raise Exception, "No network methods"
1006 network_types = self.api.GetNetworkTypes()
1007 if not network_types:
1008 raise Exception, "No network types"
1010 for interface_id in self.interface_ids:
1011 method = random.sample(network_methods, 1)[0]
1012 type = random.sample(network_types, 1)[0]
1015 interface_fields = random_interface(method, type)
1016 self.api.UpdateInterface(interface_id, interface_fields)
1020 interface = self.api.GetInterfaces([interface_id])[0]
1021 for field in interface_fields:
1022 assert interface[field] == interface_fields[field]
1025 print "Updated interface", interface_id
1027 def DeleteInterfaces(self):
1029 Delete any random network interfaces we may have added.
1032 for interface_id in self.interface_ids:
1033 self.api.DeleteInterface(interface_id)
1036 assert not self.api.GetInterfaces([interface_id])
1039 print "Deleted interface", interface_id
1042 assert not self.api.GetInterfaces(self.interface_ids)
1044 self.interface_ids = []
1046 def AddIlinks (self, n):
1048 Add random links between interfaces.
1052 src = random.sample(self.interface_ids,1)[0]
1053 dst = random.sample(self.interface_ids,1)[0]
1054 ilink_id = self.api.AddIlink (src,dst,
1055 self.ilink_type_ids[i],
1058 assert ilink_id not in self.ilink_ids
1059 self.ilink_ids.append(ilink_id)
1062 print 'Added Ilink',ilink_id,' - attached interface',src,'to',dst
1065 retrieve=GetIlinks({'src_interface_id':src,'dst_interface_id':dst,
1066 'tag_type_id':self.ilink_type_ids[i]})
1067 assert ilink_id==retrieve[0]['ilink_id']
1070 def UpdateIlinks (self):
1072 for ilink_id in self.ilink_ids:
1073 new_value=random_ilink()
1074 self.api.UpdateIlink(ilink_id,new_value)
1077 ilink=self.api.GetIlinks([ilink_id])[0]
1078 assert ilink['value'] == new_value
1081 print 'Updated Ilink',ilink_id
1083 def DeleteIlinks (self):
1084 for ilink_id in self.ilink_ids:
1085 self.api.DeleteIlink(ilink_id)
1088 assert not self.api.GetIlinks({'ilink_id':ilink_id})
1091 print 'Deleted Ilink',ilink_id
1094 assert not self.api.GetIlinks(self.ilink_ids)
1099 def AddPCUs(self, per_site = 1):
1101 Add a number of random PCUs to each site. Each node at the
1102 site will be added to a port on the PCU if AddNodes() was
1106 for site_id in self.site_ids:
1107 for i in range(per_site):
1109 pcu_fields = random_pcu()
1110 pcu_id = self.api.AddPCU(site_id, pcu_fields)
1112 # Should return a unique pcu_id
1113 assert pcu_id not in self.pcu_ids
1114 self.pcu_ids.append(pcu_id)
1116 # Add each node at this site to a different port on this PCU
1117 site = self.api.GetSites([site_id])[0]
1118 port = randint(1, 10)
1119 for node_id in site['node_ids']:
1120 self.api.AddNodeToPCU(node_id, pcu_id, port)
1125 pcu = self.api.GetPCUs([pcu_id])[0]
1126 for field in pcu_fields:
1127 assert pcu[field] == pcu_fields[field]
1130 print "Added PCU", pcu_id, "to site", site_id
1132 def UpdatePCUs(self):
1134 Make random changes to any PCUs we may have added.
1137 for pcu_id in self.pcu_ids:
1139 pcu_fields = random_pcu()
1140 self.api.UpdatePCU(pcu_id, pcu_fields)
1144 pcu = self.api.GetPCUs([pcu_id])[0]
1145 for field in pcu_fields:
1146 assert pcu[field] == pcu_fields[field]
1149 print "Updated PCU", pcu_id
1151 def DeletePCUs(self):
1153 Delete any random nodes we may have added.
1156 for pcu_id in self.pcu_ids:
1157 # Remove nodes from PCU
1158 pcu = self.api.GetPCUs([pcu_id])[0]
1159 for node_id in pcu['node_ids']:
1160 self.api.DeleteNodeFromPCU(node_id, pcu_id)
1163 pcu = self.api.GetPCUs([pcu_id])[0]
1164 assert not pcu['node_ids']
1166 self.api.DeletePCU(pcu_id)
1169 assert not self.api.GetPCUs([pcu_id])
1172 print "Deleted PCU", pcu_id
1175 assert not self.api.GetPCUs(self.pcu_ids)
1179 def AddConfFiles(self, n = 10):
1181 Add a number of random global configuration files.
1187 # Add a random configuration file
1188 conf_files.append(random_conf_file())
1191 # Add a nodegroup override file
1192 nodegroup_conf_file = conf_files[0].copy()
1193 nodegroup_conf_file['source'] = randpath(255)
1194 conf_files.append(nodegroup_conf_file)
1196 # Add a node override file
1197 node_conf_file = conf_files[0].copy()
1198 node_conf_file['source'] = randpath(255)
1199 conf_files.append(node_conf_file)
1201 for conf_file_fields in conf_files:
1202 conf_file_id = self.api.AddConfFile(conf_file_fields)
1204 # Should return a unique conf_file_id
1205 assert conf_file_id not in self.conf_file_ids
1206 self.conf_file_ids.append(conf_file_id)
1209 if conf_file_fields == nodegroup_conf_file and self.nodegroup_ids:
1210 nodegroup_id = random.sample(self.nodegroup_ids, 1)[0]
1211 self.api.AddConfFileToNodeGroup(conf_file_id, nodegroup_id)
1216 if conf_file_fields == node_conf_file and self.node_ids:
1217 node_id = random.sample(self.node_ids, 1)[0]
1218 self.api.AddConfFileToNode(conf_file_id, node_id)
1223 # Check configuration file
1224 conf_file = self.api.GetConfFiles([conf_file_id])[0]
1225 for field in conf_file_fields:
1226 assert conf_file[field] == conf_file_fields[field]
1229 print "Added configuration file", conf_file_id,
1230 if nodegroup_id is not None:
1231 print "to node group", nodegroup_id,
1232 elif node_id is not None:
1233 print "to node", node_id,
1236 def UpdateConfFiles(self):
1238 Make random changes to any configuration files we may have added.
1241 for conf_file_id in self.conf_file_ids:
1242 # Update configuration file
1243 conf_file_fields = random_conf_file()
1244 # Do not update dest so that it remains an override if set
1245 if 'dest' in conf_file_fields:
1246 del conf_file_fields['dest']
1247 self.api.UpdateConfFile(conf_file_id, conf_file_fields)
1250 # Check configuration file
1251 conf_file = self.api.GetConfFiles([conf_file_id])[0]
1252 for field in conf_file_fields:
1253 assert conf_file[field] == conf_file_fields[field]
1256 print "Updated configuration file", conf_file_id
1258 def DeleteConfFiles(self):
1260 Delete any random configuration files we may have added.
1263 for conf_file_id in self.conf_file_ids:
1264 self.api.DeleteConfFile(conf_file_id)
1267 assert not self.api.GetConfFiles([conf_file_id])
1270 print "Deleted configuration file", conf_file_id
1273 assert not self.api.GetConfFiles(self.conf_file_ids)
1275 self.conf_file_ids = []
1277 def AddTagTypes(self,n_sa,n_ng,n_il):
1279 Add as many tag types as there are nodegroups,
1280 will use tagvalue=yes for each nodegroup
1283 roles = self.api.GetRoles()
1285 raise Exception, "No roles"
1286 role_ids = [role['role_id'] for role in roles]
1288 for i in range (n_sa + n_ng + n_il):
1289 tag_type_fields = random_tag_type (role_ids)
1290 tag_type_id = self.api.AddTagType (tag_type_fields)
1292 assert tag_type_id not in \
1293 self.slice_type_ids + \
1294 self.nodegroup_type_ids + \
1298 self.slice_type_ids.append(tag_type_id)
1299 elif i < n_sa+n_ng :
1300 self.nodegroup_type_ids.append(tag_type_id)
1302 self.ilink_type_ids.append(tag_type_id)
1305 tag_type = self.api.GetTagTypes([tag_type_id])[0]
1306 for field in tag_type_fields:
1307 assert tag_type[field] == tag_type_fields[field]
1309 print "Updated slice attribute type", tag_type_id
1311 def UpdateTagTypes(self):
1313 Make random changes to any slice attribute types we may have added.
1316 roles = self.api.GetRoles()
1318 raise Exception, "No roles"
1319 role_ids = [role['role_id'] for role in roles]
1321 for tag_type_id in self.slice_type_ids + self.nodegroup_type_ids + self.ilink_type_ids:
1322 # Update slice attribute type
1323 tag_type_fields = random_tag_type(role_ids)
1324 self.api.UpdateTagType(tag_type_id, tag_type_fields)
1327 # Check slice attribute type
1328 tag_type = self.api.GetTagTypes([tag_type_id])[0]
1329 for field in tag_type_fields:
1330 assert tag_type[field] == tag_type_fields[field]
1332 print "Updated slice attribute type", tag_type_id
1334 def DeleteTagTypes(self):
1336 Delete any random slice attribute types we may have added.
1339 for tag_type_id in self.slice_type_ids + self.nodegroup_type_ids + self.ilink_type_ids:
1340 self.api.DeleteTagType(tag_type_id)
1343 assert not self.api.GetTagTypes([tag_type_id])
1346 print "Deleted slice attribute type", tag_type_id
1349 assert not self.api.GetTagTypes(self.slice_type_ids+self.nodegroup_type_ids+self.ilink_type_ids)
1351 self.slice_type_ids = []
1352 self.nodegroup_type_ids = []
1354 def AddSlices(self, per_site = 10):
1356 Add a number of random slices per site.
1359 for site in self.api.GetSites(self.site_ids):
1360 for i in range(min(per_site, site['max_slices'])):
1362 slice_fields = random_slice(site['login_base'])
1363 slice_id = self.api.AddSlice(slice_fields)
1365 # Should return a unique slice_id
1366 assert slice_id not in self.slice_ids
1367 self.slice_ids.append(slice_id)
1369 # Add slice to a random set of nodes
1370 node_ids = random.sample(self.node_ids, randint(0, len(self.node_ids)))
1372 self.api.AddSliceToNodes(slice_id, node_ids)
1374 # Add random set of site users to slice
1375 person_ids = random.sample(site['person_ids'], randint(0, len(site['person_ids'])))
1376 for person_id in person_ids:
1377 self.api.AddPersonToSlice(person_id, slice_id)
1381 slice = self.api.GetSlices([slice_id])[0]
1382 for field in slice_fields:
1383 assert slice[field] == slice_fields[field]
1385 assert set(node_ids) == set(slice['node_ids'])
1386 assert set(person_ids) == set(slice['person_ids'])
1389 print "Added slice", slice_id, "to site", site['site_id'],
1391 print "and nodes", node_ids,
1394 print "Added users", site['person_ids'], "to slice", slice_id
1396 def UpdateSlices(self):
1398 Make random changes to any slices we may have added.
1401 for slice_id in self.slice_ids:
1403 slice_fields = random_slice("unused")
1404 # Cannot change slice name
1405 if 'name' in slice_fields:
1406 del slice_fields['name']
1407 self.api.UpdateSlice(slice_id, slice_fields)
1409 slice = self.api.GetSlices([slice_id])[0]
1411 # Add slice to a random set of nodes
1412 node_ids = random.sample(self.node_ids, randint(0, len(self.node_ids)))
1413 self.api.AddSliceToNodes(slice_id, list(set(node_ids) - set(slice['node_ids'])))
1414 self.api.DeleteSliceFromNodes(slice_id, list(set(slice['node_ids']) - set(node_ids)))
1416 # Add random set of users to slice
1417 person_ids = random.sample(self.person_ids, randint(0, len(self.person_ids)))
1418 for person_id in (set(person_ids) - set(slice['person_ids'])):
1419 self.api.AddPersonToSlice(person_id, slice_id)
1420 for person_id in (set(slice['person_ids']) - set(person_ids)):
1421 self.api.DeletePersonFromSlice(person_id, slice_id)
1424 slice = self.api.GetSlices([slice_id])[0]
1425 for field in slice_fields:
1426 assert slice[field] == slice_fields[field]
1427 assert set(node_ids) == set(slice['node_ids'])
1428 assert set(person_ids) == set(slice['person_ids'])
1431 print "Updated slice", slice_id
1432 print "Added nodes", node_ids, "to slice", slice_id
1433 print "Added persons", person_ids, "to slice", slice_id
1435 def DeleteSlices(self):
1437 Delete any random slices we may have added.
1440 for slice_id in self.slice_ids:
1441 self.api.DeleteSlice(slice_id)
1444 assert not self.api.GetSlices([slice_id])
1447 print "Deleted slice", slice_id
1450 assert not self.api.GetSlices(self.slice_ids)
1454 def AddSliceTags(self, per_slice = 2):
1456 Add a number of random slices per site.
1459 if not self.slice_type_ids:
1462 for slice_id in self.slice_ids:
1463 slice = self.api.GetSlices([slice_id])[0]
1465 for i in range(per_slice):
1466 # Set a random slice/sliver attribute
1467 for tag_type_id in random.sample(self.slice_type_ids, 1):
1468 value = randstr(16, letters + '_' + digits)
1469 # Make it a sliver attribute with 50% probability
1470 if slice['node_ids']:
1471 node_id = random.sample(slice['node_ids'] + [None] * len(slice['node_ids']), 1)[0]
1475 # Add slice attribute
1477 slice_tag_id = self.api.AddSliceTag(slice_id, tag_type_id, value)
1479 slice_tag_id = self.api.AddSliceTag(slice_id, tag_type_id, value, node_id)
1481 # Should return a unique slice_tag_id
1482 assert slice_tag_id not in self.slice_tag_ids
1483 self.slice_tag_ids.append(slice_tag_id)
1486 # Check slice attribute
1487 slice_tag = self.api.GetSliceTags([slice_tag_id])[0]
1488 for field in 'tag_type_id', 'slice_id', 'node_id', 'slice_tag_id', 'value':
1489 assert slice_tag[field] == locals()[field]
1492 print "Added slice attribute", slice_tag_id, "of type", tag_type_id,
1493 if node_id is not None:
1494 print "to node", node_id,
1497 def UpdateSliceTags(self):
1499 Make random changes to any slice attributes we may have added.
1502 for slice_tag_id in self.slice_tag_ids:
1503 # Update slice attribute
1504 value = randstr(16, letters + '_' + digits)
1505 self.api.UpdateSliceTag(slice_tag_id, value)
1507 # Check slice attribute again
1508 slice_tag = self.api.GetSliceTags([slice_tag_id])[0]
1509 assert slice_tag['value'] == value
1512 print "Updated slice attribute", slice_tag_id
1514 def DeleteSliceTags(self):
1516 Delete any random slice attributes we may have added.
1519 for slice_tag_id in self.slice_tag_ids:
1520 self.api.DeleteSliceTag(slice_tag_id)
1523 assert not self.api.GetSliceTags([slice_tag_id])
1526 print "Deleted slice attribute", slice_tag_id
1529 assert not self.api.GetSliceTags(self.slice_tag_ids)
1531 self.slice_tag_ids = []
1534 parser = OptionParser()
1535 parser.add_option("-c", "--check", action = "store_true", default = False,
1536 help = "Check most actions (default: %default)")
1537 parser.add_option("-q", "--quiet", action = "store_true", default = False,
1538 help = "Be quiet (default: %default)")
1539 parser.add_option("-p","--preserve", action="store_true", default =False,
1540 help = "Do not delete created objects")
1541 parser.add_option("-t", "--tiny", action = "store_true", default = False,
1542 help = "Run a tiny test (default: %default)")
1543 (options, args) = parser.parse_args()
1545 test = Test(api = Shell(),
1546 check = options.check,
1547 verbose = not options.quiet,
1548 preserve = options.preserve)
1553 params = Test.default
1557 if __name__ == "__main__":