3 # Test script utility class
5 # Mark Huang <mlhuang@cs.princeton.edu>
6 # Copyright (C) 2006 The Trustees of Princeton University
8 # $Id: Test.py,v 1.1 2007/01/11 21:27:49 mlhuang Exp $
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_nodegroup():
141 'description': randstr(200),
144 def random_node(boot_states):
146 'hostname': randhostname(),
147 'boot_state': random.sample(boot_states, 1)[0],
148 'model': randstr(255),
149 'version': randstr(64),
152 def random_nodenetwork(method, type):
153 nodenetwork_fields = {
156 'bwlimit': randint(500000, 10000000),
160 ip = randint(0, 0xffffffff)
161 netmask = (0xffffffff << randint(2, 31)) & 0xffffffff
162 network = ip & netmask
163 broadcast = ((ip & netmask) | ~netmask) & 0xffffffff
164 gateway = randint(network + 1, broadcast - 1)
165 dns1 = randint(0, 0xffffffff)
167 for field in 'ip', 'netmask', 'network', 'broadcast', 'gateway', 'dns1':
168 nodenetwork_fields[field] = socket.inet_ntoa(struct.pack('>L', locals()[field]))
170 return nodenetwork_fields
174 'hostname': randhostname(),
175 'ip': socket.inet_ntoa(struct.pack('>L', randint(0, 0xffffffff))),
176 'protocol': randstr(16),
177 'username': randstr(254),
178 'password': randstr(254),
179 'notes': randstr(254),
180 'model': randstr(32),
183 def random_conf_file():
185 'enabled': bool(randint()),
186 'source': randpath(255),
187 'dest': randpath(255),
188 'file_permissions': "%#o" % randint(0, 512),
189 'file_owner': randstr(32, letters + '_' + digits),
190 'file_group': randstr(32, letters + '_' + digits),
191 'preinstall_cmd': randpath(100),
192 'postinstall_cmd': randpath(100),
193 'error_cmd': randpath(100),
194 'ignore_cmd_errors': bool(randint()),
195 'always_update': bool(randint()),
198 def random_attribute_type(role_ids):
200 'name': randstr(100),
201 'description': randstr(254),
202 'min_role_id': random.sample(role_ids, 1)[0],
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,
221 'nodenetworks_per_node': 1,
224 'attribute_types': 1,
225 'slices_per_site': 1,
226 'attributes_per_slice': 1,
232 'addresses_per_site': 2,
233 'persons_per_site': 10,
234 'keys_per_person': 2,
237 'nodenetworks_per_node': 1,
240 'attribute_types': 10,
241 'slices_per_site': 10,
242 'attributes_per_slice': 2,
245 def __init__(self, api, check = True, verbose = True):
248 self.verbose = verbose
251 self.address_type_ids = []
252 self.address_ids = []
255 self.nodegroup_ids = []
257 self.nodenetwork_ids = []
259 self.conf_file_ids = []
260 self.attribute_type_ids = []
262 self.slice_attribute_ids = []
264 def Run(self, **kwds):
266 Run a complete database and API consistency test. Populates
267 the database with a set of random entities, updates them, then
268 deletes them. Examples:
270 test.Run() # Defaults
271 test.Run(**Test.default) # Defaults
272 test.Run(**Test.tiny) # Tiny set
273 test.Run(sites = 123, slices_per_site = 4) # Defaults with overrides
282 def Add(self, **kwds):
284 Populate the database with a set of random entities. Examples:
286 test.populate() # Defaults
287 test.populate(Test.tiny) # Tiny set
288 test.populate(sites = 123, slices_per_site = 4) # Defaults with overrides
291 params = self.default.copy()
294 self.AddSites(params['sites'])
295 self.AddAddressTypes(params['address_types'])
296 self.AddAddresses(params['addresses_per_site'])
297 self.AddPersons(params['persons_per_site'])
298 self.AddKeys(params['keys_per_person'])
299 self.AddNodeGroups(params['nodegroups'])
300 self.AddNodes(params['nodes_per_site'])
301 self.AddNodeNetworks(params['nodenetworks_per_node'])
302 self.AddPCUs(params['pcus_per_site'])
303 self.AddConfFiles(params['conf_files'])
304 self.AddSliceAttributeTypes(params['attribute_types'])
305 self.AddSlices(params['slices_per_site'])
306 self.AddSliceAttributes(params['attributes_per_slice'])
310 self.UpdateAddressTypes()
311 self.UpdateAddresses()
314 self.UpdateNodeGroups()
316 self.UpdateNodeNetworks()
318 self.UpdateConfFiles()
319 self.UpdateSliceAttributeTypes()
321 self.UpdateSliceAttributes()
324 self.DeleteSliceAttributes()
326 self.DeleteSliceAttributeTypes()
328 self.DeleteConfFiles()
330 self.DeleteNodeNetworks()
333 self.DeleteNodeGroups()
334 self.DeleteAddresses()
335 self.DeleteAddressTypes()
338 def AddSites(self, n = 10):
340 Add a number of random sites.
345 site_fields = random_site()
346 site_id = self.api.AddSite(site_fields)
348 # Should return a unique site_id
349 assert site_id not in self.site_ids
350 self.site_ids.append(site_id)
352 # Enable slice creation
353 site_fields['max_slices'] = randint(1, 10)
354 self.api.UpdateSite(site_id, site_fields)
358 site = self.api.GetSites([site_id])[0]
359 for field in site_fields:
360 assert site[field] == site_fields[field]
363 print "Added site", site_id
365 def UpdateSites(self):
367 Make random changes to any sites we may have added.
370 for site_id in self.site_ids:
372 site_fields = random_site()
373 # Do not change login_base
374 del site_fields['login_base']
375 self.api.UpdateSite(site_id, site_fields)
379 site = self.api.GetSites([site_id])[0]
380 for field in site_fields:
381 assert site[field] == site_fields[field]
384 print "Updated site", site_id
386 def DeleteSites(self):
388 Delete any random sites we may have added.
391 for site_id in self.site_ids:
392 self.api.DeleteSite(site_id)
395 assert not self.api.GetSites([site_id])
398 print "Deleted site", site_id
401 assert not self.api.GetSites(self.site_ids)
405 def AddAddressTypes(self, n = 2):
407 Add a number of random address types.
411 address_type_fields = random_address_type()
412 address_type_id = self.api.AddAddressType(address_type_fields)
414 # Should return a unique address_type_id
415 assert address_type_id not in self.address_type_ids
416 self.address_type_ids.append(address_type_id)
420 address_type = self.api.GetAddressTypes([address_type_id])[0]
421 for field in address_type_fields:
422 assert address_type[field] == address_type_fields[field]
425 print "Added address type", address_type_id
427 def UpdateAddressTypes(self):
429 Make random changes to any address types we may have added.
432 for address_type_id in self.address_type_ids:
433 # Update address_type
434 address_type_fields = random_address_type()
435 self.api.UpdateAddressType(address_type_id, address_type_fields)
439 address_type = self.api.GetAddressTypes([address_type_id])[0]
440 for field in address_type_fields:
441 assert address_type[field] == address_type_fields[field]
444 print "Updated address_type", address_type_id
446 def DeleteAddressTypes(self):
448 Delete any random address types we may have added.
451 for address_type_id in self.address_type_ids:
452 self.api.DeleteAddressType(address_type_id)
455 assert not self.api.GetAddressTypes([address_type_id])
458 print "Deleted address type", address_type_id
461 assert not self.api.GetAddressTypes(self.address_type_ids)
463 self.address_type_ids = []
465 def AddAddresses(self, per_site = 2):
467 Add a number of random addresses to each site.
470 for site_id in self.site_ids:
471 for i in range(per_site):
472 address_fields = random_address()
473 address_id = self.api.AddSiteAddress(site_id, address_fields)
475 # Should return a unique address_id
476 assert address_id not in self.address_ids
477 self.address_ids.append(address_id)
479 # Add random address type
480 if self.address_type_ids:
481 for address_type_id in random.sample(self.address_type_ids, 1):
482 self.api.AddAddressTypeToAddress(address_type_id, address_id)
486 address = self.api.GetAddresses([address_id])[0]
487 for field in address_fields:
488 assert address[field] == address_fields[field]
491 print "Added address", address_id, "to site", site_id
493 def UpdateAddresses(self):
495 Make random changes to any addresses we may have added.
498 for address_id in self.address_ids:
500 address_fields = random_address()
501 self.api.UpdateAddress(address_id, address_fields)
505 address = self.api.GetAddresses([address_id])[0]
506 for field in address_fields:
507 assert address[field] == address_fields[field]
510 print "Updated address", address_id
512 def DeleteAddresses(self):
514 Delete any random addresses we may have added.
517 for address_id in self.address_ids:
518 # Remove address types
519 address = self.api.GetAddresses([address_id])[0]
520 for address_type_id in address['address_type_ids']:
521 self.api.DeleteAddressTypeFromAddress(address_type_id, address_id)
524 address = self.api.GetAddresses([address_id])[0]
525 assert not address['address_type_ids']
527 self.api.DeleteAddress(address_id)
530 assert not self.api.GetAddresses([address_id])
533 print "Deleted address", address_id
536 assert not self.api.GetAddresses(self.address_ids)
538 self.address_ids = []
540 def AddPersons(self, per_site = 10):
542 Add a number of random users to each site.
545 for site_id in self.site_ids:
546 for i in range(per_site):
548 person_fields = random_person()
549 person_id = self.api.AddPerson(person_fields)
551 # Should return a unique person_id
552 assert person_id not in self.person_ids
553 self.person_ids.append(person_id)
557 person = self.api.GetPersons([person_id])[0]
558 for field in person_fields:
559 if field != 'password':
560 assert person[field] == person_fields[field]
562 auth = {'AuthMethod': "password",
563 'Username': person_fields['email'],
564 'AuthString': person_fields['password']}
567 # Check that user is disabled
569 assert not self.api.AuthCheck(auth)
573 # Add random set of roles
574 role_ids = random.sample([20, 30, 40], randint(1, 3))
575 for role_id in role_ids:
576 self.api.AddRoleToPerson(role_id, person_id)
579 person = self.api.GetPersons([person_id])[0]
580 assert set(role_ids) == set(person['role_ids'])
583 self.api.UpdatePerson(person_id, {'enabled': True})
586 # Check that user is enabled
587 assert self.api.AuthCheck(auth)
589 # Associate user with site
590 self.api.AddPersonToSite(person_id, site_id)
591 self.api.SetPersonPrimarySite(person_id, site_id)
594 person = self.api.GetPersons([person_id])[0]
595 assert person['site_ids'][0] == site_id
598 print "Added user", person_id, "to site", site_id
600 def UpdatePersons(self):
602 Make random changes to any users we may have added.
605 for person_id in self.person_ids:
607 person_fields = random_person()
609 person_fields['enabled'] = True
610 self.api.UpdatePerson(person_id, person_fields)
614 person = self.api.GetPersons([person_id])[0]
615 for field in person_fields:
616 if field != 'password':
617 assert person[field] == person_fields[field]
620 print "Updated person", person_id
622 person = self.api.GetPersons([person_id])[0]
624 # Associate user with a random set of sites
625 site_ids = random.sample(self.site_ids, randint(0, len(self.site_ids)))
626 for site_id in (set(site_ids) - set(person['site_ids'])):
627 self.api.AddPersonToSite(person_id, site_id)
628 for site_id in (set(person['site_ids']) - set(site_ids)):
629 self.api.DeletePersonFromSite(person_id, site_id)
632 self.api.SetPersonPrimarySite(person_id, site_ids[0])
635 person = self.api.GetPersons([person_id])[0]
636 assert set(site_ids) == set(person['site_ids'])
639 print "Updated person", person_id, "to sites", site_ids
641 def DeletePersons(self):
643 Delete any random users we may have added.
646 for person_id in self.person_ids:
648 person = self.api.GetPersons([person_id])[0]
649 for site_id in person['site_ids']:
650 self.api.DeletePersonFromSite(person_id, site_id)
653 person = self.api.GetPersons([person_id])[0]
654 assert not person['site_ids']
657 for role_id in person['role_ids']:
658 self.api.DeleteRoleFromPerson(role_id, person_id)
661 person = self.api.GetPersons([person_id])[0]
662 assert not person['role_ids']
665 self.api.UpdatePerson(person_id, {'enabled': False})
668 person = self.api.GetPersons([person_id])[0]
669 assert not person['enabled']
672 self.api.DeletePerson(person_id)
675 assert not self.api.GetPersons([person_id])
678 print "Deleted user", person_id
681 assert not self.api.GetPersons(self.person_ids)
685 def AddKeys(self, per_person = 2):
687 Add a number of random keys to each user.
690 key_types = self.api.GetKeyTypes()
692 raise Exception, "No key types"
694 for person_id in self.person_ids:
695 for i in range(per_person):
697 key_fields = random_key(key_types)
698 key_id = self.api.AddPersonKey(person_id, key_fields)
700 # Should return a unique key_id
701 assert key_id not in self.key_ids
702 self.key_ids.append(key_id)
706 key = self.api.GetKeys([key_id])[0]
707 for field in key_fields:
708 assert key[field] == key_fields[field]
710 # Add and immediately blacklist a key
711 key_fields = random_key(key_types)
712 key_id = self.api.AddPersonKey(person_id, key_fields)
714 self.api.BlacklistKey(key_id)
716 # Is effectively deleted
717 assert not self.api.GetKeys([key_id])
719 # Cannot be added again
721 key_id = self.api.AddPersonKey(person_id, key_fields)
727 print "Added key", key_id, "to user", person_id
729 def UpdateKeys(self):
731 Make random changes to any keys we may have added.
734 key_types = self.api.GetKeyTypes()
736 raise Exception, "No key types"
738 for key_id in self.key_ids:
740 key_fields = random_key(key_types)
741 self.api.UpdateKey(key_id, key_fields)
745 key = self.api.GetKeys([key_id])[0]
746 for field in key_fields:
747 assert key[field] == key_fields[field]
750 print "Updated key", key_id
752 def DeleteKeys(self):
754 Delete any random keys we may have added.
757 for key_id in self.key_ids:
758 self.api.DeleteKey(key_id)
761 assert not self.api.GetKeys([key_id])
764 print "Deleted key", key_id
767 assert not self.api.GetKeys(self.key_ids)
771 def AddNodeGroups(self, n = 10):
773 Add a number of random node groups.
778 nodegroup_fields = random_nodegroup()
779 nodegroup_id = self.api.AddNodeGroup(nodegroup_fields)
781 # Should return a unique nodegroup_id
782 assert nodegroup_id not in self.nodegroup_ids
783 self.nodegroup_ids.append(nodegroup_id)
787 nodegroup = self.api.GetNodeGroups([nodegroup_id])[0]
788 for field in nodegroup_fields:
789 assert nodegroup[field] == nodegroup_fields[field]
792 print "Added node group", nodegroup_id
794 def UpdateNodeGroups(self):
796 Make random changes to any node groups we may have added.
799 for nodegroup_id in self.nodegroup_ids:
801 nodegroup_fields = random_nodegroup()
802 self.api.UpdateNodeGroup(nodegroup_id, nodegroup_fields)
806 nodegroup = self.api.GetNodeGroups([nodegroup_id])[0]
807 for field in nodegroup_fields:
808 assert nodegroup[field] == nodegroup_fields[field]
811 print "Updated node group", nodegroup_id
813 def DeleteNodeGroups(self):
815 Delete any random node groups we may have added.
818 for nodegroup_id in self.nodegroup_ids:
819 self.api.DeleteNodeGroup(nodegroup_id)
822 assert not self.api.GetNodeGroups([nodegroup_id])
825 print "Deleted node group", nodegroup_id
828 assert not self.api.GetNodeGroups(self.nodegroup_ids)
830 self.nodegroup_ids = []
832 def AddNodes(self, per_site = 2):
834 Add a number of random nodes to each site. Each node will also
835 be added to a random node group if AddNodeGroups() was
839 boot_states = self.api.GetBootStates()
841 raise Exception, "No boot states"
843 for site_id in self.site_ids:
844 for i in range(per_site):
846 node_fields = random_node(boot_states)
847 node_id = self.api.AddNode(site_id, node_fields)
849 # Should return a unique node_id
850 assert node_id not in self.node_ids
851 self.node_ids.append(node_id)
853 # Add to a random set of node groups
854 nodegroup_ids = random.sample(self.nodegroup_ids, randint(0, len(self.nodegroup_ids)))
855 for nodegroup_id in nodegroup_ids:
856 self.api.AddNodeToNodeGroup(node_id, nodegroup_id)
860 node = self.api.GetNodes([node_id])[0]
861 for field in node_fields:
862 assert node[field] == node_fields[field]
865 print "Added node", node_id
867 def UpdateNodes(self):
869 Make random changes to any nodes we may have added.
872 boot_states = self.api.GetBootStates()
874 raise Exception, "No boot states"
876 for node_id in self.node_ids:
878 node_fields = random_node(boot_states)
879 self.api.UpdateNode(node_id, node_fields)
881 node = self.api.GetNodes([node_id])[0]
883 # Add to a random set of node groups
884 nodegroup_ids = random.sample(self.nodegroup_ids, randint(0, len(self.nodegroup_ids)))
885 for nodegroup_id in (set(nodegroup_ids) - set(node['nodegroup_ids'])):
886 self.api.AddNodeToNodeGroup(node_id, nodegroup_id)
887 for nodegroup_id in (set(node['nodegroup_ids']) - set(nodegroup_ids)):
888 self.api.DeleteNodeFromNodeGroup(node_id, nodegroup_id)
892 node = self.api.GetNodes([node_id])[0]
893 for field in node_fields:
894 assert node[field] == node_fields[field]
895 assert set(nodegroup_ids) == set(node['nodegroup_ids'])
898 print "Updated node", node_id
899 print "Added node", node_id, "to node groups", nodegroup_ids
901 def DeleteNodes(self):
903 Delete any random nodes we may have added.
906 for node_id in self.node_ids:
907 # Remove from node groups
908 node = self.api.GetNodes([node_id])[0]
909 for nodegroup_id in node['nodegroup_ids']:
910 self.api.DeleteNodeFromNodeGroup(node_id, nodegroup_id)
913 node = self.api.GetNodes([node_id])[0]
914 assert not node['nodegroup_ids']
916 self.api.DeleteNode(node_id)
919 assert not self.api.GetNodes([node_id])
922 print "Deleted node", node_id
925 assert not self.api.GetNodes(self.node_ids)
929 def AddNodeNetworks(self, per_node = 1):
931 Add a number of random network interfaces to each node.
934 network_methods = self.api.GetNetworkMethods()
935 if not network_methods:
936 raise Exception, "No network methods"
938 network_types = self.api.GetNetworkTypes()
939 if not network_types:
940 raise Exception, "No network types"
942 for node_id in self.node_ids:
943 for i in range(per_node):
944 method = random.sample(network_methods, 1)[0]
945 type = random.sample(network_types, 1)[0]
948 nodenetwork_fields = random_nodenetwork(method, type)
949 nodenetwork_id = self.api.AddNodeNetwork(node_id, nodenetwork_fields)
951 # Should return a unique nodenetwork_id
952 assert nodenetwork_id not in self.nodenetwork_ids
953 self.nodenetwork_ids.append(nodenetwork_id)
957 nodenetwork = self.api.GetNodeNetworks([nodenetwork_id])[0]
958 for field in nodenetwork_fields:
959 assert nodenetwork[field] == nodenetwork_fields[field]
962 print "Added node network", nodenetwork_id, "to node", node_id
964 def UpdateNodeNetworks(self):
966 Make random changes to any network interfaces we may have added.
969 network_methods = self.api.GetNetworkMethods()
970 if not network_methods:
971 raise Exception, "No network methods"
973 network_types = self.api.GetNetworkTypes()
974 if not network_types:
975 raise Exception, "No network types"
977 for nodenetwork_id in self.nodenetwork_ids:
978 method = random.sample(network_methods, 1)[0]
979 type = random.sample(network_types, 1)[0]
982 nodenetwork_fields = random_nodenetwork(method, type)
983 self.api.UpdateNodeNetwork(nodenetwork_id, nodenetwork_fields)
987 nodenetwork = self.api.GetNodeNetworks([nodenetwork_id])[0]
988 for field in nodenetwork_fields:
989 assert nodenetwork[field] == nodenetwork_fields[field]
992 print "Updated node network", nodenetwork_id
994 def DeleteNodeNetworks(self):
996 Delete any random network interfaces we may have added.
999 for nodenetwork_id in self.nodenetwork_ids:
1000 self.api.DeleteNodeNetwork(nodenetwork_id)
1003 assert not self.api.GetNodeNetworks([nodenetwork_id])
1006 print "Deleted node network", nodenetwork_id
1009 assert not self.api.GetNodeNetworks(self.nodenetwork_ids)
1011 self.nodenetwork_ids = []
1013 def AddPCUs(self, per_site = 1):
1015 Add a number of random PCUs to each site. Each node at the
1016 site will be added to a port on the PCU if AddNodes() was
1020 for site_id in self.site_ids:
1021 for i in range(per_site):
1023 pcu_fields = random_pcu()
1024 pcu_id = self.api.AddPCU(site_id, pcu_fields)
1026 # Should return a unique pcu_id
1027 assert pcu_id not in self.pcu_ids
1028 self.pcu_ids.append(pcu_id)
1030 # Add each node at this site to a different port on this PCU
1031 site = self.api.GetSites([site_id])[0]
1032 port = randint(1, 10)
1033 for node_id in site['node_ids']:
1034 self.api.AddNodeToPCU(node_id, pcu_id, port)
1039 pcu = self.api.GetPCUs([pcu_id])[0]
1040 for field in pcu_fields:
1041 assert pcu[field] == pcu_fields[field]
1044 print "Added PCU", pcu_id, "to site", site_id
1046 def UpdatePCUs(self):
1048 Make random changes to any PCUs we may have added.
1051 for pcu_id in self.pcu_ids:
1053 pcu_fields = random_pcu()
1054 self.api.UpdatePCU(pcu_id, pcu_fields)
1058 pcu = self.api.GetPCUs([pcu_id])[0]
1059 for field in pcu_fields:
1060 assert pcu[field] == pcu_fields[field]
1063 print "Updated PCU", pcu_id
1065 def DeletePCUs(self):
1067 Delete any random nodes we may have added.
1070 for pcu_id in self.pcu_ids:
1071 # Remove nodes from PCU
1072 pcu = self.api.GetPCUs([pcu_id])[0]
1073 for node_id in pcu['node_ids']:
1074 self.api.DeleteNodeFromPCU(node_id, pcu_id)
1077 pcu = self.api.GetPCUs([pcu_id])[0]
1078 assert not pcu['node_ids']
1080 self.api.DeletePCU(pcu_id)
1083 assert not self.api.GetPCUs([pcu_id])
1086 print "Deleted PCU", pcu_id
1089 assert not self.api.GetPCUs(self.pcu_ids)
1093 def AddConfFiles(self, n = 10):
1095 Add a number of random global configuration files.
1101 # Add a random configuration file
1102 conf_files.append(random_conf_file())
1105 # Add a nodegroup override file
1106 nodegroup_conf_file = conf_files[0].copy()
1107 nodegroup_conf_file['source'] = randpath(255)
1108 conf_files.append(nodegroup_conf_file)
1110 # Add a node override file
1111 node_conf_file = conf_files[0].copy()
1112 node_conf_file['source'] = randpath(255)
1113 conf_files.append(node_conf_file)
1115 for conf_file_fields in conf_files:
1116 conf_file_id = self.api.AddConfFile(conf_file_fields)
1118 # Should return a unique conf_file_id
1119 assert conf_file_id not in self.conf_file_ids
1120 self.conf_file_ids.append(conf_file_id)
1123 if conf_file_fields == nodegroup_conf_file and self.nodegroup_ids:
1124 nodegroup_id = random.sample(self.nodegroup_ids, 1)[0]
1125 self.api.AddConfFileToNodeGroup(conf_file_id, nodegroup_id)
1130 if conf_file_fields == node_conf_file and self.node_ids:
1131 node_id = random.sample(self.node_ids, 1)[0]
1132 self.api.AddConfFileToNode(conf_file_id, node_id)
1137 # Check configuration file
1138 conf_file = self.api.GetConfFiles([conf_file_id])[0]
1139 for field in conf_file_fields:
1140 assert conf_file[field] == conf_file_fields[field]
1143 print "Added configuration file", conf_file_id,
1144 if nodegroup_id is not None:
1145 print "to node group", nodegroup_id,
1146 elif node_id is not None:
1147 print "to node", node_id,
1150 def UpdateConfFiles(self):
1152 Make random changes to any configuration files we may have added.
1155 for conf_file_id in self.conf_file_ids:
1156 # Update configuration file
1157 conf_file_fields = random_conf_file()
1158 # Do not update dest so that it remains an override if set
1159 del conf_file_fields['dest']
1160 self.api.UpdateConfFile(conf_file_id, conf_file_fields)
1163 # Check configuration file
1164 conf_file = self.api.GetConfFiles([conf_file_id])[0]
1165 for field in conf_file_fields:
1166 assert conf_file[field] == conf_file_fields[field]
1169 print "Updated configuration file", conf_file_id
1171 def DeleteConfFiles(self):
1173 Delete any random configuration files we may have added.
1176 for conf_file_id in self.conf_file_ids:
1177 self.api.DeleteConfFile(conf_file_id)
1180 assert not self.api.GetConfFiles([conf_file_id])
1183 print "Deleted configuration file", conf_file_id
1186 assert not self.api.GetConfFiles(self.conf_file_ids)
1188 self.conf_file_ids = []
1190 def AddSliceAttributeTypes(self, n = 10):
1192 Add a number of random slice attribute types.
1195 roles = self.api.GetRoles()
1197 raise Exception, "No roles"
1198 role_ids = [role['role_id'] for role in roles]
1201 attribute_type_fields = random_attribute_type(role_ids)
1202 attribute_type_id = self.api.AddSliceAttributeType(attribute_type_fields)
1204 # Should return a unique attribute_type_id
1205 assert attribute_type_id not in self.attribute_type_ids
1206 self.attribute_type_ids.append(attribute_type_id)
1209 # Check slice attribute type
1210 attribute_type = self.api.GetSliceAttributeTypes([attribute_type_id])[0]
1211 for field in attribute_type_fields:
1212 assert attribute_type[field] == attribute_type_fields[field]
1215 print "Added slice attribute type", attribute_type_id
1217 def UpdateSliceAttributeTypes(self):
1219 Make random changes to any slice attribute types we may have added.
1222 roles = self.api.GetRoles()
1224 raise Exception, "No roles"
1225 role_ids = [role['role_id'] for role in roles]
1227 for attribute_type_id in self.attribute_type_ids:
1228 # Update slice attribute type
1229 attribute_type_fields = random_attribute_type(role_ids)
1230 self.api.UpdateSliceAttributeType(attribute_type_id, attribute_type_fields)
1233 # Check slice attribute type
1234 attribute_type = self.api.GetSliceAttributeTypes([attribute_type_id])[0]
1235 for field in attribute_type_fields:
1236 assert attribute_type[field] == attribute_type_fields[field]
1239 print "Updated slice attribute type", attribute_type_id
1241 def DeleteSliceAttributeTypes(self):
1243 Delete any random slice attribute types we may have added.
1246 for attribute_type_id in self.attribute_type_ids:
1247 self.api.DeleteSliceAttributeType(attribute_type_id)
1250 assert not self.api.GetSliceAttributeTypes([attribute_type_id])
1253 print "Deleted slice attribute type", attribute_type_id
1256 assert not self.api.GetSliceAttributeTypes(self.attribute_type_ids)
1258 self.attribute_type_ids = []
1260 def AddSlices(self, per_site = 10):
1262 Add a number of random slices per site.
1265 for site in self.api.GetSites(self.site_ids):
1266 for i in range(min(per_site, site['max_slices'])):
1268 slice_fields = random_slice(site['login_base'])
1269 slice_id = self.api.AddSlice(slice_fields)
1271 # Should return a unique slice_id
1272 assert slice_id not in self.slice_ids
1273 self.slice_ids.append(slice_id)
1275 # Add slice to a random set of nodes
1276 node_ids = random.sample(self.node_ids, randint(0, len(self.node_ids)))
1278 self.api.AddSliceToNodes(slice_id, node_ids)
1280 # Add random set of site users to slice
1281 person_ids = random.sample(site['person_ids'], randint(0, len(site['person_ids'])))
1282 for person_id in person_ids:
1283 self.api.AddPersonToSlice(person_id, slice_id)
1287 slice = self.api.GetSlices([slice_id])[0]
1288 for field in slice_fields:
1289 assert slice[field] == slice_fields[field]
1291 assert set(node_ids) == set(slice['node_ids'])
1292 assert set(person_ids) == set(slice['person_ids'])
1295 print "Added slice", slice_id, "to site", site['site_id'],
1297 print "and nodes", node_ids,
1300 print "Added users", site['person_ids'], "to slice", slice_id
1302 def UpdateSlices(self):
1304 Make random changes to any slices we may have added.
1307 for slice_id in self.slice_ids:
1309 slice_fields = random_slice("unused")
1310 # Cannot change slice name
1311 del slice_fields['name']
1312 self.api.UpdateSlice(slice_id, slice_fields)
1314 slice = self.api.GetSlices([slice_id])[0]
1316 # Add slice to a random set of nodes
1317 node_ids = random.sample(self.node_ids, randint(0, len(self.node_ids)))
1318 self.api.AddSliceToNodes(slice_id, list(set(node_ids) - set(slice['node_ids'])))
1319 self.api.DeleteSliceFromNodes(slice_id, list(set(slice['node_ids']) - set(node_ids)))
1321 # Add random set of users to slice
1322 person_ids = random.sample(self.person_ids, randint(0, len(self.person_ids)))
1323 for person_id in (set(person_ids) - set(slice['person_ids'])):
1324 self.api.AddPersonToSlice(person_id, slice_id)
1325 for person_id in (set(slice['person_ids']) - set(person_ids)):
1326 self.api.DeletePersonFromSlice(person_id, slice_id)
1329 slice = self.api.GetSlices([slice_id])[0]
1330 for field in slice_fields:
1331 assert slice[field] == slice_fields[field]
1332 assert set(node_ids) == set(slice['node_ids'])
1333 assert set(person_ids) == set(slice['person_ids'])
1336 print "Updated slice", slice_id
1337 print "Added nodes", node_ids, "to slice", slice_id
1338 print "Added persons", person_ids, "to slice", slice_id
1340 def DeleteSlices(self):
1342 Delete any random slices we may have added.
1345 for slice_id in self.slice_ids:
1346 self.api.DeleteSlice(slice_id)
1349 assert not self.api.GetSlices([slice_id])
1352 print "Deleted slice", slice_id
1355 assert not self.api.GetSlices(self.slice_ids)
1359 def AddSliceAttributes(self, per_slice = 2):
1361 Add a number of random slices per site.
1364 if not self.attribute_type_ids:
1367 for slice_id in self.slice_ids:
1368 slice = self.api.GetSlices([slice_id])[0]
1370 for i in range(per_slice):
1371 # Set a random slice/sliver attribute
1372 for attribute_type_id in random.sample(self.attribute_type_ids, 1):
1373 value = randstr(16, letters + '_' + digits)
1374 # Make it a sliver attribute with 50% probability
1375 if slice['node_ids']:
1376 node_id = random.sample(slice['node_ids'] + [None] * len(slice['node_ids']), 1)[0]
1380 # Add slice attribute
1382 slice_attribute_id = self.api.AddSliceAttribute(slice_id, attribute_type_id, value)
1384 slice_attribute_id = self.api.AddSliceAttribute(slice_id, attribute_type_id, value, node_id)
1386 # Should return a unique slice_attribute_id
1387 assert slice_attribute_id not in self.slice_attribute_ids
1388 self.slice_attribute_ids.append(slice_attribute_id)
1391 # Check slice attribute
1392 slice_attribute = self.api.GetSliceAttributes([slice_attribute_id])[0]
1393 for field in 'attribute_type_id', 'slice_id', 'node_id', 'slice_attribute_id', 'value':
1394 assert slice_attribute[field] == locals()[field]
1397 print "Added slice attribute", slice_attribute_id, "of type", attribute_type_id,
1398 if node_id is not None:
1399 print "to node", node_id,
1402 def UpdateSliceAttributes(self):
1404 Make random changes to any slice attributes we may have added.
1407 for slice_attribute_id in self.slice_attribute_ids:
1408 # Update slice attribute
1409 value = randstr(16, letters + '_' + digits)
1410 self.api.UpdateSliceAttribute(slice_attribute_id, value)
1412 # Check slice attribute again
1413 slice_attribute = self.api.GetSliceAttributes([slice_attribute_id])[0]
1414 assert slice_attribute['value'] == value
1417 print "Updated slice attribute", slice_attribute_id
1419 def DeleteSliceAttributes(self):
1421 Delete any random slice attributes we may have added.
1424 for slice_attribute_id in self.slice_attribute_ids:
1425 self.api.DeleteSliceAttribute(slice_attribute_id)
1428 assert not self.api.GetSliceAttributes([slice_attribute_id])
1431 print "Deleted slice attribute", slice_attribute_id
1434 assert not self.api.GetSliceAttributes(self.slice_attribute_ids)
1436 self.slice_attribute_ids = []
1439 parser = OptionParser()
1440 parser.add_option("-c", "--check", action = "store_true", default = False, help = "Check most actions (default: %default)")
1441 parser.add_option("-q", "--quiet", action = "store_true", default = False, help = "Be quiet (default: %default)")
1442 parser.add_option("-t", "--tiny", action = "store_true", default = False, help = "Run a tiny test (default: %default)")
1443 (options, args) = parser.parse_args()
1445 test = Test(api = Shell(),
1446 check = options.check,
1447 verbose = not options.quiet)
1452 params = Test.default
1456 if __name__ == "__main__":