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,
219 'slice_attributes': 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': 10,
235 'keys_per_person': 2,
236 'slice_attributes': 10,
239 'interfaces_per_node': 1,
243 'slices_per_site': 10,
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_attribute_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_attributes'],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.AddSliceAttributes(params['attributes_per_slice'])
318 self.UpdateAddressTypes()
319 self.UpdateAddresses()
322 self.UpdateTagTypes()
323 self.UpdateNodeGroups()
325 self.UpdateInterfaces()
327 self.UpdateConfFiles()
329 self.UpdateSliceAttributes()
332 self.DeleteSliceAttributes()
335 self.DeleteConfFiles()
338 self.DeleteInterfaces()
341 self.DeleteNodeGroups()
342 self.DeleteTagTypes()
343 self.DeleteAddresses()
344 self.DeleteAddressTypes()
347 def AddSites(self, n = 10):
349 Add a number of random sites.
354 site_fields = random_site()
355 site_id = self.api.AddSite(site_fields)
357 # Should return a unique site_id
358 assert site_id not in self.site_ids
359 self.site_ids.append(site_id)
361 # Enable slice creation
362 site_fields['max_slices'] = randint(1, 10)
363 self.api.UpdateSite(site_id, site_fields)
367 site = self.api.GetSites([site_id])[0]
368 for field in site_fields:
369 assert site[field] == site_fields[field]
372 print "Added site", site_id
374 def UpdateSites(self):
376 Make random changes to any sites we may have added.
379 for site_id in self.site_ids:
381 site_fields = random_site()
382 # Do not change login_base
383 if 'login_base' in site_fields:
384 del site_fields['login_base']
385 self.api.UpdateSite(site_id, site_fields)
389 site = self.api.GetSites([site_id])[0]
390 for field in site_fields:
391 assert site[field] == site_fields[field]
394 print "Updated site", site_id
396 def DeleteSites(self):
398 Delete any random sites we may have added.
401 for site_id in self.site_ids:
402 self.api.DeleteSite(site_id)
405 assert not self.api.GetSites([site_id])
408 print "Deleted site", site_id
411 assert not self.api.GetSites(self.site_ids)
415 def AddAddressTypes(self, n = 2):
417 Add a number of random address types.
421 address_type_fields = random_address_type()
422 address_type_id = self.api.AddAddressType(address_type_fields)
424 # Should return a unique address_type_id
425 assert address_type_id not in self.address_type_ids
426 self.address_type_ids.append(address_type_id)
430 address_type = self.api.GetAddressTypes([address_type_id])[0]
431 for field in address_type_fields:
432 assert address_type[field] == address_type_fields[field]
435 print "Added address type", address_type_id
437 def UpdateAddressTypes(self):
439 Make random changes to any address types we may have added.
442 for address_type_id in self.address_type_ids:
443 # Update address_type
444 address_type_fields = random_address_type()
445 self.api.UpdateAddressType(address_type_id, address_type_fields)
449 address_type = self.api.GetAddressTypes([address_type_id])[0]
450 for field in address_type_fields:
451 assert address_type[field] == address_type_fields[field]
454 print "Updated address_type", address_type_id
456 def DeleteAddressTypes(self):
458 Delete any random address types we may have added.
461 for address_type_id in self.address_type_ids:
462 self.api.DeleteAddressType(address_type_id)
465 assert not self.api.GetAddressTypes([address_type_id])
468 print "Deleted address type", address_type_id
471 assert not self.api.GetAddressTypes(self.address_type_ids)
473 self.address_type_ids = []
475 def AddAddresses(self, per_site = 2):
477 Add a number of random addresses to each site.
480 for site_id in self.site_ids:
481 for i in range(per_site):
482 address_fields = random_address()
483 address_id = self.api.AddSiteAddress(site_id, address_fields)
485 # Should return a unique address_id
486 assert address_id not in self.address_ids
487 self.address_ids.append(address_id)
489 # Add random address type
490 if self.address_type_ids:
491 for address_type_id in random.sample(self.address_type_ids, 1):
492 self.api.AddAddressTypeToAddress(address_type_id, address_id)
496 address = self.api.GetAddresses([address_id])[0]
497 for field in address_fields:
498 assert address[field] == address_fields[field]
501 print "Added address", address_id, "to site", site_id
503 def UpdateAddresses(self):
505 Make random changes to any addresses we may have added.
508 for address_id in self.address_ids:
510 address_fields = random_address()
511 self.api.UpdateAddress(address_id, address_fields)
515 address = self.api.GetAddresses([address_id])[0]
516 for field in address_fields:
517 assert address[field] == address_fields[field]
520 print "Updated address", address_id
522 def DeleteAddresses(self):
524 Delete any random addresses we may have added.
527 for address_id in self.address_ids:
528 # Remove address types
529 address = self.api.GetAddresses([address_id])[0]
530 for address_type_id in address['address_type_ids']:
531 self.api.DeleteAddressTypeFromAddress(address_type_id, address_id)
534 address = self.api.GetAddresses([address_id])[0]
535 assert not address['address_type_ids']
537 self.api.DeleteAddress(address_id)
540 assert not self.api.GetAddresses([address_id])
543 print "Deleted address", address_id
546 assert not self.api.GetAddresses(self.address_ids)
548 self.address_ids = []
550 def AddPersons(self, per_site = 10):
552 Add a number of random users to each site.
555 for site_id in self.site_ids:
556 for i in range(per_site):
558 person_fields = random_person()
559 person_id = self.api.AddPerson(person_fields)
561 # Should return a unique person_id
562 assert person_id not in self.person_ids
563 self.person_ids.append(person_id)
567 person = self.api.GetPersons([person_id])[0]
568 for field in person_fields:
569 if field != 'password':
570 assert person[field] == person_fields[field]
572 auth = {'AuthMethod': "password",
573 'Username': person_fields['email'],
574 'AuthString': person_fields['password']}
577 # Check that user is disabled
579 assert not self.api.AuthCheck(auth)
583 # Add random set of roles
584 role_ids = random.sample([20, 30, 40], randint(1, 3))
585 for role_id in role_ids:
586 self.api.AddRoleToPerson(role_id, person_id)
589 person = self.api.GetPersons([person_id])[0]
590 assert set(role_ids) == set(person['role_ids'])
593 self.api.UpdatePerson(person_id, {'enabled': True})
596 # Check that user is enabled
597 assert self.api.AuthCheck(auth)
599 # Associate user with site
600 self.api.AddPersonToSite(person_id, site_id)
601 self.api.SetPersonPrimarySite(person_id, site_id)
604 person = self.api.GetPersons([person_id])[0]
605 assert person['site_ids'][0] == site_id
608 print "Added user", person_id, "to site", site_id
610 def UpdatePersons(self):
612 Make random changes to any users we may have added.
615 for person_id in self.person_ids:
617 person_fields = random_person()
619 person_fields['enabled'] = True
620 self.api.UpdatePerson(person_id, person_fields)
624 person = self.api.GetPersons([person_id])[0]
625 for field in person_fields:
626 if field != 'password':
627 assert person[field] == person_fields[field]
630 print "Updated person", person_id
632 person = self.api.GetPersons([person_id])[0]
634 # Associate user with a random set of sites
635 site_ids = random.sample(self.site_ids, randint(0, len(self.site_ids)))
636 for site_id in (set(site_ids) - set(person['site_ids'])):
637 self.api.AddPersonToSite(person_id, site_id)
638 for site_id in (set(person['site_ids']) - set(site_ids)):
639 self.api.DeletePersonFromSite(person_id, site_id)
642 self.api.SetPersonPrimarySite(person_id, site_ids[0])
645 person = self.api.GetPersons([person_id])[0]
646 assert set(site_ids) == set(person['site_ids'])
649 print "Updated person", person_id, "to sites", site_ids
651 def DeletePersons(self):
653 Delete any random users we may have added.
656 for person_id in self.person_ids:
658 person = self.api.GetPersons([person_id])[0]
659 for site_id in person['site_ids']:
660 self.api.DeletePersonFromSite(person_id, site_id)
663 person = self.api.GetPersons([person_id])[0]
664 assert not person['site_ids']
667 for role_id in person['role_ids']:
668 self.api.DeleteRoleFromPerson(role_id, person_id)
671 person = self.api.GetPersons([person_id])[0]
672 assert not person['role_ids']
675 self.api.UpdatePerson(person_id, {'enabled': False})
678 person = self.api.GetPersons([person_id])[0]
679 assert not person['enabled']
682 self.api.DeletePerson(person_id)
685 assert not self.api.GetPersons([person_id])
688 print "Deleted user", person_id
691 assert not self.api.GetPersons(self.person_ids)
695 def AddKeys(self, per_person = 2):
697 Add a number of random keys to each user.
700 key_types = self.api.GetKeyTypes()
702 raise Exception, "No key types"
704 for person_id in self.person_ids:
705 for i in range(per_person):
707 key_fields = random_key(key_types)
708 key_id = self.api.AddPersonKey(person_id, key_fields)
710 # Should return a unique key_id
711 assert key_id not in self.key_ids
712 self.key_ids.append(key_id)
716 key = self.api.GetKeys([key_id])[0]
717 for field in key_fields:
718 assert key[field] == key_fields[field]
720 # Add and immediately blacklist a key
721 key_fields = random_key(key_types)
722 key_id = self.api.AddPersonKey(person_id, key_fields)
724 self.api.BlacklistKey(key_id)
726 # Is effectively deleted
727 assert not self.api.GetKeys([key_id])
729 # Cannot be added again
731 key_id = self.api.AddPersonKey(person_id, key_fields)
737 print "Added key", key_id, "to user", person_id
739 def UpdateKeys(self):
741 Make random changes to any keys we may have added.
744 key_types = self.api.GetKeyTypes()
746 raise Exception, "No key types"
748 for key_id in self.key_ids:
750 key_fields = random_key(key_types)
751 self.api.UpdateKey(key_id, key_fields)
755 key = self.api.GetKeys([key_id])[0]
756 for field in key_fields:
757 assert key[field] == key_fields[field]
760 print "Updated key", key_id
762 def DeleteKeys(self):
764 Delete any random keys we may have added.
767 for key_id in self.key_ids:
768 self.api.DeleteKey(key_id)
771 assert not self.api.GetKeys([key_id])
774 print "Deleted key", key_id
777 assert not self.api.GetKeys(self.key_ids)
781 def AddNodeGroups(self, n = 10):
783 Add a number of random node groups.
788 tag_type_id = self.nodegroup_type_ids[i]
789 tagname=self.api.GetTagTypes([tag_type_id])[0]['tagname']
792 groupname = random_nodegroup() ['groupname']
794 nodegroup_id = self.api.AddNodeGroup(groupname, tagname, tagvalue)
796 # Should return a unique nodegroup_id
797 assert nodegroup_id not in self.nodegroup_ids
798 self.nodegroup_ids.append(nodegroup_id)
802 nodegroup = self.api.GetNodeGroups([nodegroup_id])[0]
803 assert nodegroup['groupname'] == groupname
804 assert nodegroup['tagname'] == tagname
805 assert nodegroup['tagvalue'] == tagvalue
808 print "Added node group", nodegroup_id
810 def UpdateNodeGroups(self):
812 Make random changes to any node groups we may have added.
815 for nodegroup_id in self.nodegroup_ids:
817 groupname = random_nodegroup()['groupname']
818 # cannot change tagname
819 nodegroup_fields = { 'groupname':groupname }
820 self.api.UpdateNodeGroup(nodegroup_id, nodegroup_fields)
824 nodegroup = self.api.GetNodeGroups([nodegroup_id])[0]
825 for field in nodegroup_fields:
826 assert nodegroup[field] == nodegroup_fields[field]
829 print "Updated node group", nodegroup_id
831 def DeleteNodeGroups(self):
833 Delete any random node groups we may have added.
836 for nodegroup_id in self.nodegroup_ids:
837 self.api.DeleteNodeGroup(nodegroup_id)
840 assert not self.api.GetNodeGroups([nodegroup_id])
843 print "Deleted node group", nodegroup_id
846 assert not self.api.GetNodeGroups(self.nodegroup_ids)
848 self.nodegroup_ids = []
850 def AddNodes(self, per_site = 2):
852 Add a number of random nodes to each site. Each node will also
853 be added to a random node group if AddNodeGroups() was
857 boot_states = self.api.GetBootStates()
859 raise Exception, "No boot states"
861 for site_id in self.site_ids:
862 for i in range(per_site):
864 node_fields = random_node(boot_states)
865 node_id = self.api.AddNode(site_id, node_fields)
867 # Should return a unique node_id
868 assert node_id not in self.node_ids
869 self.node_ids.append(node_id)
871 # Add to a random set of node groups
872 nodegroup_ids = random.sample(self.nodegroup_ids, randint(0, len(self.nodegroup_ids)))
873 for nodegroup_id in nodegroup_ids:
874 tagname = self.api.GetNodeGroups([nodegroup_id])[0]['tagname']
875 self.api.AddNodeTag( node_id, tagname, 'yes' )
879 node = self.api.GetNodes([node_id])[0]
880 for field in node_fields:
881 assert node[field] == node_fields[field]
884 print "Added node", node_id
886 def UpdateNodes(self):
888 Make random changes to any nodes we may have added.
891 boot_states = self.api.GetBootStates()
893 raise Exception, "No boot states"
895 for node_id in self.node_ids:
897 node_fields = random_node(boot_states)
898 self.api.UpdateNode(node_id, node_fields)
900 node = self.api.GetNodes([node_id])[0]
902 # Add to a random set of node groups
903 nodegroup_ids = random.sample(self.nodegroup_ids, randint(0, len(self.nodegroup_ids)))
904 for nodegroup_id in (set(nodegroup_ids) - set(node['nodegroup_ids'])):
905 nodegroup = self.api.GetNodeGroups([nodegroup_id])[0]
906 tagname = nodegroup['tagname']
907 node_tags = self.api.GetNodeTags({'node_id':node_id,'tagname':tagname})
909 self.api.AddNodeTag(node_id,tagname,'yes')
911 node_tag=node_tags[0]
912 self.api.UpdateNodeTag(node_tag['node_tag_id'],'yes')
913 for nodegroup_id in (set(node['nodegroup_ids']) - set(nodegroup_ids)):
914 nodegroup = self.api.GetNodeGroups([nodegroup_id])[0]
915 tagname = nodegroup['tagname']
916 node_tags = self.api.GetNodeTags({'node_id':node_id,'tagname':tagname})
918 self.api.AddNodeTag(node_id,tagname,'no')
920 node_tag=node_tags[0]
921 self.api.UpdateNodeTag(node_tag['node_tag_id'],'no')
925 node = self.api.GetNodes([node_id])[0]
926 for field in node_fields:
927 assert node[field] == node_fields[field]
928 assert set(nodegroup_ids) == set(node['nodegroup_ids'])
931 print "Updated node", node_id
933 def DeleteNodes(self):
935 Delete any random nodes we may have added.
938 for node_id in self.node_ids:
939 # Remove from node groups
940 node = self.api.GetNodes([node_id])[0]
941 for node_tag in GetNodeTags ( {'node_id': node_id} ):
942 self.api.UpdateNodeTag(node_tag['node_tag_id'],'')
945 node = self.api.GetNodes([node_id])[0]
946 assert not node['nodegroup_ids']
948 self.api.DeleteNode(node_id)
951 assert not self.api.GetNodes([node_id])
954 print "Deleted node", node_id
957 assert not self.api.GetNodes(self.node_ids)
961 def AddInterfaces(self, per_node = 1):
963 Add a number of random network interfaces to each node.
966 network_methods = self.api.GetNetworkMethods()
967 if not network_methods:
968 raise Exception, "No network methods"
970 network_types = self.api.GetNetworkTypes()
971 if not network_types:
972 raise Exception, "No network types"
974 for node_id in self.node_ids:
975 for i in range(per_node):
976 method = random.sample(network_methods, 1)[0]
977 type = random.sample(network_types, 1)[0]
980 interface_fields = random_interface(method, type)
981 interface_id = self.api.AddInterface(node_id, interface_fields)
983 # Should return a unique interface_id
984 assert interface_id not in self.interface_ids
985 self.interface_ids.append(interface_id)
989 interface = self.api.GetInterfaces([interface_id])[0]
990 for field in interface_fields:
991 assert interface[field] == interface_fields[field]
994 print "Added interface", interface_id, "to node", node_id
996 def UpdateInterfaces(self):
998 Make random changes to any network interfaces we may have added.
1001 network_methods = self.api.GetNetworkMethods()
1002 if not network_methods:
1003 raise Exception, "No network methods"
1005 network_types = self.api.GetNetworkTypes()
1006 if not network_types:
1007 raise Exception, "No network types"
1009 for interface_id in self.interface_ids:
1010 method = random.sample(network_methods, 1)[0]
1011 type = random.sample(network_types, 1)[0]
1014 interface_fields = random_interface(method, type)
1015 self.api.UpdateInterface(interface_id, interface_fields)
1019 interface = self.api.GetInterfaces([interface_id])[0]
1020 for field in interface_fields:
1021 assert interface[field] == interface_fields[field]
1024 print "Updated interface", interface_id
1026 def DeleteInterfaces(self):
1028 Delete any random network interfaces we may have added.
1031 for interface_id in self.interface_ids:
1032 self.api.DeleteInterface(interface_id)
1035 assert not self.api.GetInterfaces([interface_id])
1038 print "Deleted interface", interface_id
1041 assert not self.api.GetInterfaces(self.interface_ids)
1043 self.interface_ids = []
1045 def AddIlinks (self, n):
1047 Add random links between interfaces.
1051 src = random.sample(self.interface_ids,1)
1052 dst = random.sample(self.interface_ids,1)
1053 ilink_id = self.api.AddIlink (src,dst,
1054 self.ilink_type_ids[i],
1057 assert ilink_id not in self.ilink_ids
1058 self.ilink_ids.append(ilink_id)
1061 print 'ilink',ilink_id,'attached interface',src,'to',dst
1064 retrieve=GetIlinks({'src_interface_id':src,'dst_interface_id':dst,
1065 'tag_type_id':self.ilink_type_ids[i]})
1066 assert ilink_id=retrieve
1069 def DeleteIlinks (self):
1070 for ilink_id in self.ilink_ids:
1071 self.api.DeleteIlink(ilink_id)
1074 assert not self.api.GetIlinks({'ilink_id':ilink_id})
1077 print 'Deleted Ilink',ilink_id
1080 assert not self.api.GetIlinks(self.ilink_ids)
1085 def AddPCUs(self, per_site = 1):
1087 Add a number of random PCUs to each site. Each node at the
1088 site will be added to a port on the PCU if AddNodes() was
1092 for site_id in self.site_ids:
1093 for i in range(per_site):
1095 pcu_fields = random_pcu()
1096 pcu_id = self.api.AddPCU(site_id, pcu_fields)
1098 # Should return a unique pcu_id
1099 assert pcu_id not in self.pcu_ids
1100 self.pcu_ids.append(pcu_id)
1102 # Add each node at this site to a different port on this PCU
1103 site = self.api.GetSites([site_id])[0]
1104 port = randint(1, 10)
1105 for node_id in site['node_ids']:
1106 self.api.AddNodeToPCU(node_id, pcu_id, port)
1111 pcu = self.api.GetPCUs([pcu_id])[0]
1112 for field in pcu_fields:
1113 assert pcu[field] == pcu_fields[field]
1116 print "Added PCU", pcu_id, "to site", site_id
1118 def UpdatePCUs(self):
1120 Make random changes to any PCUs we may have added.
1123 for pcu_id in self.pcu_ids:
1125 pcu_fields = random_pcu()
1126 self.api.UpdatePCU(pcu_id, pcu_fields)
1130 pcu = self.api.GetPCUs([pcu_id])[0]
1131 for field in pcu_fields:
1132 assert pcu[field] == pcu_fields[field]
1135 print "Updated PCU", pcu_id
1137 def DeletePCUs(self):
1139 Delete any random nodes we may have added.
1142 for pcu_id in self.pcu_ids:
1143 # Remove nodes from PCU
1144 pcu = self.api.GetPCUs([pcu_id])[0]
1145 for node_id in pcu['node_ids']:
1146 self.api.DeleteNodeFromPCU(node_id, pcu_id)
1149 pcu = self.api.GetPCUs([pcu_id])[0]
1150 assert not pcu['node_ids']
1152 self.api.DeletePCU(pcu_id)
1155 assert not self.api.GetPCUs([pcu_id])
1158 print "Deleted PCU", pcu_id
1161 assert not self.api.GetPCUs(self.pcu_ids)
1165 def AddConfFiles(self, n = 10):
1167 Add a number of random global configuration files.
1173 # Add a random configuration file
1174 conf_files.append(random_conf_file())
1177 # Add a nodegroup override file
1178 nodegroup_conf_file = conf_files[0].copy()
1179 nodegroup_conf_file['source'] = randpath(255)
1180 conf_files.append(nodegroup_conf_file)
1182 # Add a node override file
1183 node_conf_file = conf_files[0].copy()
1184 node_conf_file['source'] = randpath(255)
1185 conf_files.append(node_conf_file)
1187 for conf_file_fields in conf_files:
1188 conf_file_id = self.api.AddConfFile(conf_file_fields)
1190 # Should return a unique conf_file_id
1191 assert conf_file_id not in self.conf_file_ids
1192 self.conf_file_ids.append(conf_file_id)
1195 if conf_file_fields == nodegroup_conf_file and self.nodegroup_ids:
1196 nodegroup_id = random.sample(self.nodegroup_ids, 1)[0]
1197 self.api.AddConfFileToNodeGroup(conf_file_id, nodegroup_id)
1202 if conf_file_fields == node_conf_file and self.node_ids:
1203 node_id = random.sample(self.node_ids, 1)[0]
1204 self.api.AddConfFileToNode(conf_file_id, node_id)
1209 # Check configuration file
1210 conf_file = self.api.GetConfFiles([conf_file_id])[0]
1211 for field in conf_file_fields:
1212 assert conf_file[field] == conf_file_fields[field]
1215 print "Added configuration file", conf_file_id,
1216 if nodegroup_id is not None:
1217 print "to node group", nodegroup_id,
1218 elif node_id is not None:
1219 print "to node", node_id,
1222 def UpdateConfFiles(self):
1224 Make random changes to any configuration files we may have added.
1227 for conf_file_id in self.conf_file_ids:
1228 # Update configuration file
1229 conf_file_fields = random_conf_file()
1230 # Do not update dest so that it remains an override if set
1231 if 'dest' in conf_file_fields:
1232 del conf_file_fields['dest']
1233 self.api.UpdateConfFile(conf_file_id, conf_file_fields)
1236 # Check configuration file
1237 conf_file = self.api.GetConfFiles([conf_file_id])[0]
1238 for field in conf_file_fields:
1239 assert conf_file[field] == conf_file_fields[field]
1242 print "Updated configuration file", conf_file_id
1244 def DeleteConfFiles(self):
1246 Delete any random configuration files we may have added.
1249 for conf_file_id in self.conf_file_ids:
1250 self.api.DeleteConfFile(conf_file_id)
1253 assert not self.api.GetConfFiles([conf_file_id])
1256 print "Deleted configuration file", conf_file_id
1259 assert not self.api.GetConfFiles(self.conf_file_ids)
1261 self.conf_file_ids = []
1263 def AddTagTypes(self,n_sa,n_ng,n_il):
1265 Add as many tag types as there are nodegroups,
1266 will use tagvalue=yes for each nodegroup
1269 roles = self.api.GetRoles()
1271 raise Exception, "No roles"
1272 role_ids = [role['role_id'] for role in roles]
1274 for i in range (n_sa + n_ng + n_il):
1275 tag_type_fields = random_tag_type (role_ids)
1276 tag_type_id = self.api.AddTagType (tag_type_fields)
1278 assert tag_type_id not in \
1279 self.slice_type_ids + \
1280 self.nodegroup_type_ids + \
1284 self.slice_type_ids.append(tag_type_id)
1285 elif i < n_sa+n_ng :
1286 self.nodegroup_type_ids.append(tag_type_id)
1288 self.ilink_type_ids.append(tag_type_id)
1291 tag_type = self.api.GetTagTypes([tag_type_id])[0]
1292 for field in tag_type_fields:
1293 assert tag_type[field] == tag_type_fields[field]
1295 print "Updated slice attribute type", tag_type_id, \
1296 " tagname=", tag_type_fields['tagname']
1298 def UpdateTagTypes(self):
1300 Make random changes to any slice attribute types we may have added.
1303 roles = self.api.GetRoles()
1305 raise Exception, "No roles"
1306 role_ids = [role['role_id'] for role in roles]
1308 for tag_type_id in self.slice_type_ids + self.nodegroup_type_ids + self.ilink_type_ids:
1309 # Update slice attribute type
1310 tag_type_fields = random_tag_type(role_ids)
1311 self.api.UpdateTagType(tag_type_id, tag_type_fields)
1314 # Check slice attribute type
1315 tag_type = self.api.GetTagTypes([tag_type_id])[0]
1316 for field in tag_type_fields:
1317 assert tag_type[field] == tag_type_fields[field]
1319 print "Updated slice attribute type", tag_type_id
1321 def DeleteTagTypes(self):
1323 Delete any random slice attribute types we may have added.
1326 for tag_type_id in self.slice_type_ids + self.nodegroup_type_ids + self.ilink_type_ids:
1327 self.api.DeleteTagType(tag_type_id)
1330 assert not self.api.GetTagTypes([tag_type_id])
1333 print "Deleted slice attribute type", tag_type_id
1336 assert not self.api.GetTagTypes(self.slice_type_ids+self.nodegroup_type_ids+self.ilink_type_ids)
1338 self.slice_type_ids = []
1339 self.nodegroup_type_ids = []
1341 def AddSlices(self, per_site = 10):
1343 Add a number of random slices per site.
1346 for site in self.api.GetSites(self.site_ids):
1347 for i in range(min(per_site, site['max_slices'])):
1349 slice_fields = random_slice(site['login_base'])
1350 slice_id = self.api.AddSlice(slice_fields)
1352 # Should return a unique slice_id
1353 assert slice_id not in self.slice_ids
1354 self.slice_ids.append(slice_id)
1356 # Add slice to a random set of nodes
1357 node_ids = random.sample(self.node_ids, randint(0, len(self.node_ids)))
1359 self.api.AddSliceToNodes(slice_id, node_ids)
1361 # Add random set of site users to slice
1362 person_ids = random.sample(site['person_ids'], randint(0, len(site['person_ids'])))
1363 for person_id in person_ids:
1364 self.api.AddPersonToSlice(person_id, slice_id)
1368 slice = self.api.GetSlices([slice_id])[0]
1369 for field in slice_fields:
1370 assert slice[field] == slice_fields[field]
1372 assert set(node_ids) == set(slice['node_ids'])
1373 assert set(person_ids) == set(slice['person_ids'])
1376 print "Added slice", slice_id, "to site", site['site_id'],
1378 print "and nodes", node_ids,
1381 print "Added users", site['person_ids'], "to slice", slice_id
1383 def UpdateSlices(self):
1385 Make random changes to any slices we may have added.
1388 for slice_id in self.slice_ids:
1390 slice_fields = random_slice("unused")
1391 # Cannot change slice name
1392 if 'name' in slice_fields:
1393 del slice_fields['name']
1394 self.api.UpdateSlice(slice_id, slice_fields)
1396 slice = self.api.GetSlices([slice_id])[0]
1398 # Add slice to a random set of nodes
1399 node_ids = random.sample(self.node_ids, randint(0, len(self.node_ids)))
1400 self.api.AddSliceToNodes(slice_id, list(set(node_ids) - set(slice['node_ids'])))
1401 self.api.DeleteSliceFromNodes(slice_id, list(set(slice['node_ids']) - set(node_ids)))
1403 # Add random set of users to slice
1404 person_ids = random.sample(self.person_ids, randint(0, len(self.person_ids)))
1405 for person_id in (set(person_ids) - set(slice['person_ids'])):
1406 self.api.AddPersonToSlice(person_id, slice_id)
1407 for person_id in (set(slice['person_ids']) - set(person_ids)):
1408 self.api.DeletePersonFromSlice(person_id, slice_id)
1411 slice = self.api.GetSlices([slice_id])[0]
1412 for field in slice_fields:
1413 assert slice[field] == slice_fields[field]
1414 assert set(node_ids) == set(slice['node_ids'])
1415 assert set(person_ids) == set(slice['person_ids'])
1418 print "Updated slice", slice_id
1419 print "Added nodes", node_ids, "to slice", slice_id
1420 print "Added persons", person_ids, "to slice", slice_id
1422 def DeleteSlices(self):
1424 Delete any random slices we may have added.
1427 for slice_id in self.slice_ids:
1428 self.api.DeleteSlice(slice_id)
1431 assert not self.api.GetSlices([slice_id])
1434 print "Deleted slice", slice_id
1437 assert not self.api.GetSlices(self.slice_ids)
1441 def AddSliceAttributes(self, per_slice = 2):
1443 Add a number of random slices per site.
1446 if not self.slice_type_ids:
1449 for slice_id in self.slice_ids:
1450 slice = self.api.GetSlices([slice_id])[0]
1452 for i in range(per_slice):
1453 # Set a random slice/sliver attribute
1454 for tag_type_id in random.sample(self.slice_type_ids, 1):
1455 value = randstr(16, letters + '_' + digits)
1456 # Make it a sliver attribute with 50% probability
1457 if slice['node_ids']:
1458 node_id = random.sample(slice['node_ids'] + [None] * len(slice['node_ids']), 1)[0]
1462 # Add slice attribute
1464 slice_attribute_id = self.api.AddSliceAttribute(slice_id, tag_type_id, value)
1466 slice_attribute_id = self.api.AddSliceAttribute(slice_id, tag_type_id, value, node_id)
1468 # Should return a unique slice_attribute_id
1469 assert slice_attribute_id not in self.slice_attribute_ids
1470 self.slice_attribute_ids.append(slice_attribute_id)
1473 # Check slice attribute
1474 slice_attribute = self.api.GetSliceAttributes([slice_attribute_id])[0]
1475 for field in 'tag_type_id', 'slice_id', 'node_id', 'slice_attribute_id', 'value':
1476 assert slice_attribute[field] == locals()[field]
1479 print "Added slice attribute", slice_attribute_id, "of type", tag_type_id,
1480 if node_id is not None:
1481 print "to node", node_id,
1484 def UpdateSliceAttributes(self):
1486 Make random changes to any slice attributes we may have added.
1489 for slice_attribute_id in self.slice_attribute_ids:
1490 # Update slice attribute
1491 value = randstr(16, letters + '_' + digits)
1492 self.api.UpdateSliceAttribute(slice_attribute_id, value)
1494 # Check slice attribute again
1495 slice_attribute = self.api.GetSliceAttributes([slice_attribute_id])[0]
1496 assert slice_attribute['value'] == value
1499 print "Updated slice attribute", slice_attribute_id
1501 def DeleteSliceAttributes(self):
1503 Delete any random slice attributes we may have added.
1506 for slice_attribute_id in self.slice_attribute_ids:
1507 self.api.DeleteSliceAttribute(slice_attribute_id)
1510 assert not self.api.GetSliceAttributes([slice_attribute_id])
1513 print "Deleted slice attribute", slice_attribute_id
1516 assert not self.api.GetSliceAttributes(self.slice_attribute_ids)
1518 self.slice_attribute_ids = []
1521 parser = OptionParser()
1522 parser.add_option("-c", "--check", action = "store_true", default = False,
1523 help = "Check most actions (default: %default)")
1524 parser.add_option("-q", "--quiet", action = "store_true", default = False,
1525 help = "Be quiet (default: %default)")
1526 parser.add_option("-p","--preserve", action="store_true", default =False,
1527 help = "Do not delete created objects")
1528 parser.add_option("-t", "--tiny", action = "store_true", default = False,
1529 help = "Run a tiny test (default: %default)")
1530 (options, args) = parser.parse_args()
1532 test = Test(api = Shell(),
1533 check = options.check,
1534 verbose = not options.quiet,
1535 preserve = options.preserve)
1540 params = Test.default
1544 if __name__ == "__main__":