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) }
149 def random_node(node_types,boot_states):
151 'hostname': randhostname(),
152 'node_type': random.sample(node_types,1)[0],
153 'boot_state': random.sample(boot_states, 1)[0],
154 'model': randstr(255),
155 'version': randstr(64),
156 # for testing node tags
160 def random_interface(method, type):
164 'bwlimit': randint(500000, 10000000),
168 ip = randint(0, 0xffffffff)
169 netmask = (0xffffffff << randint(2, 31)) & 0xffffffff
170 network = ip & netmask
171 broadcast = ((ip & netmask) | ~netmask) & 0xffffffff
172 gateway = randint(network + 1, broadcast - 1)
173 dns1 = randint(0, 0xffffffff)
175 for field in 'ip', 'netmask', 'network', 'broadcast', 'gateway', 'dns1':
176 interface_fields[field] = socket.inet_ntoa(struct.pack('>L', locals()[field]))
178 return interface_fields
185 'hostname': randhostname(),
186 'ip': socket.inet_ntoa(struct.pack('>L', randint(0, 0xffffffff))),
187 'protocol': randstr(16),
188 'username': randstr(254),
189 'password': randstr(254),
190 'notes': randstr(254),
191 'model': randstr(32),
194 def random_conf_file():
196 'enabled': bool(randint()),
197 'source': randpath(255),
198 'dest': randpath(255),
199 'file_permissions': "%#o" % randint(0, 512),
200 'file_owner': randstr(32, letters + '_' + digits),
201 'file_group': randstr(32, letters + '_' + digits),
202 'preinstall_cmd': randpath(100),
203 'postinstall_cmd': randpath(100),
204 'error_cmd': randpath(100),
205 'ignore_cmd_errors': bool(randint()),
206 'always_update': bool(randint()),
209 def random_slice(login_base):
211 'name': login_base + "_" + randstr(11, letters).lower(),
212 'url': "http://" + randhostname() + "/",
213 'description': randstr(2048),
220 'addresses_per_site': 1,
221 'persons_per_site': 1,
222 'keys_per_person': 1,
226 'interfaces_per_node': 1,
230 'slices_per_site': 1,
231 'attributes_per_slice': 1,
237 'addresses_per_site': 2,
238 'persons_per_site': 4,
239 'keys_per_person': 2,
243 'interfaces_per_node': 1,
247 'slices_per_site': 4,
248 'attributes_per_slice': 2,
251 def __init__(self, api, check = True, verbose = True, preserve = False):
254 self.verbose = verbose
255 self.preserve = preserve
258 self.address_type_ids = []
259 self.address_ids = []
262 self.slice_type_ids = []
263 self.nodegroup_type_ids = []
264 self.ilink_type_ids = []
265 self.nodegroup_ids = []
267 self.interface_ids = []
270 self.conf_file_ids = []
272 self.slice_tag_ids = []
274 def Cardinals (self):
275 return [len(x) for x in (
276 self.api.GetNodes({},['node_id']),
277 self.api.GetSites({},['site_id']),
278 self.api.GetPersons({},['person_id']),
279 self.api.GetSlices({},['slice_id']),
282 def Run(self, **kwds):
284 Run a complete database and API consistency test. Populates
285 the database with a set of random entities, updates them, then
286 deletes them. Examples:
288 test.Run() # Defaults
289 test.Run(**Test.default) # Defaults
290 test.Run(**Test.tiny) # Tiny set
291 test.Run(sites = 123, slices_per_site = 4) # Defaults with overrides
294 cardinals_before=self.Cardinals()
295 print 'Cardinals before test (n,s,p,sl)',cardinals_before
300 print 'Preserving - delete skipped'
304 cardinals_after=self.Cardinals()
305 print 'Cardinals after test (n,s,p,sl)',cardinals_after
307 if cardinals_before != cardinals_after:
308 raise Exception, 'cardinals before and after differ - check deletion mechanisms'
310 def Add(self, **kwds):
312 Populate the database with a set of random entities. Examples:
314 test.populate() # Defaults
315 test.populate(Test.tiny) # Tiny set
316 test.populate(sites = 123, slices_per_site = 4) # Defaults with overrides
319 params = self.default.copy()
322 self.AddSites(params['sites'])
323 self.AddAddressTypes(params['address_types'])
324 self.AddAddresses(params['addresses_per_site'])
325 self.AddPersons(params['persons_per_site'])
326 self.AddKeys(params['keys_per_person'])
327 self.AddTagTypes(params['slice_tags'],params['nodegroups'],params['ilinks'])
328 self.AddNodeGroups(params['nodegroups'])
329 self.AddNodes(params['nodes_per_site'])
330 self.AddInterfaces(params['interfaces_per_node'])
331 self.AddIlinks (params['ilinks'])
332 self.AddPCUs(params['pcus_per_site'])
333 self.AddConfFiles(params['conf_files'])
334 self.AddSlices(params['slices_per_site'])
335 self.AddSliceTags(params['attributes_per_slice'])
339 self.UpdateAddressTypes()
340 self.UpdateAddresses()
343 self.UpdateTagTypes()
344 self.UpdateNodeGroups()
346 self.UpdateInterfaces()
349 self.UpdateConfFiles()
351 self.UpdateSliceTags()
354 self.DeleteSliceTags()
357 self.DeleteConfFiles()
360 self.DeleteInterfaces()
363 self.DeleteNodeGroups()
364 self.DeleteTagTypes()
365 self.DeleteAddresses()
366 self.DeleteAddressTypes()
369 def AddSites(self, n = 10):
371 Add a number of random sites.
376 site_fields = random_site()
377 site_id = self.api.AddSite(site_fields)
379 # Should return a unique site_id
380 assert site_id not in self.site_ids
381 self.site_ids.append(site_id)
383 # Enable slice creation
384 site_fields['max_slices'] = randint(1, 10)
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 "Added site", site_id
396 def UpdateSites(self):
398 Make random changes to any sites we may have added.
401 for site_id in self.site_ids:
403 site_fields = random_site()
404 # Do not change login_base
405 if 'login_base' in site_fields:
406 del site_fields['login_base']
407 self.api.UpdateSite(site_id, site_fields)
411 site = self.api.GetSites([site_id])[0]
412 for field in site_fields:
413 assert site[field] == site_fields[field]
416 print "Updated site", site_id
418 def DeleteSites(self):
420 Delete any random sites we may have added.
423 for site_id in self.site_ids:
424 self.api.DeleteSite(site_id)
427 assert not self.api.GetSites([site_id])
430 print "Deleted site", site_id
433 assert not self.api.GetSites(self.site_ids)
437 def AddAddressTypes(self, n = 2):
439 Add a number of random address types.
443 address_type_fields = random_address_type()
444 address_type_id = self.api.AddAddressType(address_type_fields)
446 # Should return a unique address_type_id
447 assert address_type_id not in self.address_type_ids
448 self.address_type_ids.append(address_type_id)
452 address_type = self.api.GetAddressTypes([address_type_id])[0]
453 for field in address_type_fields:
454 assert address_type[field] == address_type_fields[field]
457 print "Added address type", address_type_id
459 def UpdateAddressTypes(self):
461 Make random changes to any address types we may have added.
464 for address_type_id in self.address_type_ids:
465 # Update address_type
466 address_type_fields = random_address_type()
467 self.api.UpdateAddressType(address_type_id, address_type_fields)
471 address_type = self.api.GetAddressTypes([address_type_id])[0]
472 for field in address_type_fields:
473 assert address_type[field] == address_type_fields[field]
476 print "Updated address_type", address_type_id
478 def DeleteAddressTypes(self):
480 Delete any random address types we may have added.
483 for address_type_id in self.address_type_ids:
484 self.api.DeleteAddressType(address_type_id)
487 assert not self.api.GetAddressTypes([address_type_id])
490 print "Deleted address type", address_type_id
493 assert not self.api.GetAddressTypes(self.address_type_ids)
495 self.address_type_ids = []
497 def AddAddresses(self, per_site = 2):
499 Add a number of random addresses to each site.
502 for site_id in self.site_ids:
503 for i in range(per_site):
504 address_fields = random_address()
505 address_id = self.api.AddSiteAddress(site_id, address_fields)
507 # Should return a unique address_id
508 assert address_id not in self.address_ids
509 self.address_ids.append(address_id)
511 # Add random address type
512 if self.address_type_ids:
513 for address_type_id in random.sample(self.address_type_ids, 1):
514 self.api.AddAddressTypeToAddress(address_type_id, address_id)
518 address = self.api.GetAddresses([address_id])[0]
519 for field in address_fields:
520 assert address[field] == address_fields[field]
523 print "Added address", address_id, "to site", site_id
525 def UpdateAddresses(self):
527 Make random changes to any addresses we may have added.
530 for address_id in self.address_ids:
532 address_fields = random_address()
533 self.api.UpdateAddress(address_id, address_fields)
537 address = self.api.GetAddresses([address_id])[0]
538 for field in address_fields:
539 assert address[field] == address_fields[field]
542 print "Updated address", address_id
544 def DeleteAddresses(self):
546 Delete any random addresses we may have added.
549 for address_id in self.address_ids:
550 # Remove address types
551 address = self.api.GetAddresses([address_id])[0]
552 for address_type_id in address['address_type_ids']:
553 self.api.DeleteAddressTypeFromAddress(address_type_id, address_id)
556 address = self.api.GetAddresses([address_id])[0]
557 assert not address['address_type_ids']
559 self.api.DeleteAddress(address_id)
562 assert not self.api.GetAddresses([address_id])
565 print "Deleted address", address_id
568 assert not self.api.GetAddresses(self.address_ids)
570 self.address_ids = []
572 def AddPersons(self, per_site = 10):
574 Add a number of random users to each site.
577 for site_id in self.site_ids:
578 for i in range(per_site):
580 person_fields = random_person()
581 person_id = self.api.AddPerson(person_fields)
583 # Should return a unique person_id
584 assert person_id not in self.person_ids
585 self.person_ids.append(person_id)
589 person = self.api.GetPersons([person_id])[0]
590 for field in person_fields:
591 if field != 'password':
592 assert person[field] == person_fields[field]
594 auth = {'AuthMethod': "password",
595 'Username': person_fields['email'],
596 'AuthString': person_fields['password']}
599 # Check that user is disabled
601 assert not self.api.AuthCheck(auth)
605 # Add random set of roles
606 role_ids = random.sample([20, 30, 40], randint(1, 3))
607 for role_id in role_ids:
608 self.api.AddRoleToPerson(role_id, person_id)
611 person = self.api.GetPersons([person_id])[0]
612 assert set(role_ids) == set(person['role_ids'])
615 self.api.UpdatePerson(person_id, {'enabled': True})
618 # Check that user is enabled
619 assert self.api.AuthCheck(auth)
621 # Associate user with site
622 self.api.AddPersonToSite(person_id, site_id)
623 self.api.SetPersonPrimarySite(person_id, site_id)
626 person = self.api.GetPersons([person_id])[0]
627 assert person['site_ids'][0] == site_id
630 print "Added user", person_id, "to site", site_id
632 def UpdatePersons(self):
634 Make random changes to any users we may have added.
637 for person_id in self.person_ids:
639 person_fields = random_person()
641 person_fields['enabled'] = True
642 self.api.UpdatePerson(person_id, person_fields)
646 person = self.api.GetPersons([person_id])[0]
647 for field in person_fields:
648 if field != 'password':
649 assert person[field] == person_fields[field]
652 print "Updated person", person_id
654 person = self.api.GetPersons([person_id])[0]
656 # Associate user with a random set of sites
657 site_ids = random.sample(self.site_ids, randint(0, len(self.site_ids)))
658 for site_id in (set(site_ids) - set(person['site_ids'])):
659 self.api.AddPersonToSite(person_id, site_id)
660 for site_id in (set(person['site_ids']) - set(site_ids)):
661 self.api.DeletePersonFromSite(person_id, site_id)
664 self.api.SetPersonPrimarySite(person_id, site_ids[0])
667 person = self.api.GetPersons([person_id])[0]
668 assert set(site_ids) == set(person['site_ids'])
671 print "Updated person", person_id, "to sites", site_ids
673 def DeletePersons(self):
675 Delete any random users we may have added.
678 for person_id in self.person_ids:
680 person = self.api.GetPersons([person_id])[0]
681 for site_id in person['site_ids']:
682 self.api.DeletePersonFromSite(person_id, site_id)
685 person = self.api.GetPersons([person_id])[0]
686 assert not person['site_ids']
689 for role_id in person['role_ids']:
690 self.api.DeleteRoleFromPerson(role_id, person_id)
693 person = self.api.GetPersons([person_id])[0]
694 assert not person['role_ids']
697 self.api.UpdatePerson(person_id, {'enabled': False})
700 person = self.api.GetPersons([person_id])[0]
701 assert not person['enabled']
704 self.api.DeletePerson(person_id)
707 assert not self.api.GetPersons([person_id])
710 print "Deleted user", person_id
713 assert not self.api.GetPersons(self.person_ids)
717 def AddKeys(self, per_person = 2):
719 Add a number of random keys to each user.
722 key_types = self.api.GetKeyTypes()
724 raise Exception, "No key types"
726 for person_id in self.person_ids:
727 for i in range(per_person):
729 key_fields = random_key(key_types)
730 key_id = self.api.AddPersonKey(person_id, key_fields)
732 # Should return a unique key_id
733 assert key_id not in self.key_ids
734 self.key_ids.append(key_id)
738 key = self.api.GetKeys([key_id])[0]
739 for field in key_fields:
740 assert key[field] == key_fields[field]
742 # Add and immediately blacklist a key
743 key_fields = random_key(key_types)
744 key_id = self.api.AddPersonKey(person_id, key_fields)
746 self.api.BlacklistKey(key_id)
748 # Is effectively deleted
749 assert not self.api.GetKeys([key_id])
751 # Cannot be added again
753 key_id = self.api.AddPersonKey(person_id, key_fields)
759 print "Added key", key_id, "to user", person_id
761 def UpdateKeys(self):
763 Make random changes to any keys we may have added.
766 key_types = self.api.GetKeyTypes()
768 raise Exception, "No key types"
770 for key_id in self.key_ids:
772 key_fields = random_key(key_types)
773 self.api.UpdateKey(key_id, key_fields)
777 key = self.api.GetKeys([key_id])[0]
778 for field in key_fields:
779 assert key[field] == key_fields[field]
782 print "Updated key", key_id
784 def DeleteKeys(self):
786 Delete any random keys we may have added.
789 for key_id in self.key_ids:
790 self.api.DeleteKey(key_id)
793 assert not self.api.GetKeys([key_id])
796 print "Deleted key", key_id
799 assert not self.api.GetKeys(self.key_ids)
803 def AddNodeGroups(self, n = 10):
805 Add a number of random node groups.
810 tag_type_id = self.nodegroup_type_ids[i]
811 tagname=self.api.GetTagTypes([tag_type_id])[0]['tagname']
814 groupname = random_nodegroup() ['groupname']
816 nodegroup_id = self.api.AddNodeGroup(groupname, tagname, tagvalue)
818 # Should return a unique nodegroup_id
819 assert nodegroup_id not in self.nodegroup_ids
820 self.nodegroup_ids.append(nodegroup_id)
824 nodegroup = self.api.GetNodeGroups([nodegroup_id])[0]
825 assert nodegroup['groupname'] == groupname
826 assert nodegroup['tagname'] == tagname
827 assert nodegroup['tagvalue'] == tagvalue
830 print "Added node group", nodegroup_id
832 def UpdateNodeGroups(self):
834 Make random changes to any node groups we may have added.
837 for nodegroup_id in self.nodegroup_ids:
839 groupname = random_nodegroup()['groupname']
840 # cannot change tagname
841 nodegroup_fields = { 'groupname':groupname }
842 self.api.UpdateNodeGroup(nodegroup_id, nodegroup_fields)
846 nodegroup = self.api.GetNodeGroups([nodegroup_id])[0]
847 for field in nodegroup_fields:
848 assert nodegroup[field] == nodegroup_fields[field]
851 print "Updated node group", nodegroup_id
853 def DeleteNodeGroups(self):
855 Delete any random node groups we may have added.
858 for nodegroup_id in self.nodegroup_ids:
859 self.api.DeleteNodeGroup(nodegroup_id)
862 assert not self.api.GetNodeGroups([nodegroup_id])
865 print "Deleted node group", nodegroup_id
868 assert not self.api.GetNodeGroups(self.nodegroup_ids)
870 self.nodegroup_ids = []
872 def AddNodes(self, per_site = 2):
874 Add a number of random nodes to each site. Each node will also
875 be added to a random node group if AddNodeGroups() was
879 node_types = self.api.GetNodeTypes()
881 raise Exception, "No node types"
882 boot_states = self.api.GetBootStates()
884 raise Exception, "No boot states"
886 for site_id in self.site_ids:
887 for i in range(per_site):
889 node_fields = random_node(node_types,boot_states)
890 node_id = self.api.AddNode(site_id, node_fields)
892 # Should return a unique node_id
893 assert node_id not in self.node_ids
894 self.node_ids.append(node_id)
896 # Add to a random set of node groups
897 nodegroup_ids = random.sample(self.nodegroup_ids, randint(0, len(self.nodegroup_ids)))
898 for nodegroup_id in nodegroup_ids:
899 tagname = self.api.GetNodeGroups([nodegroup_id])[0]['tagname']
900 self.api.AddNodeTag( node_id, tagname, 'yes' )
904 node = self.api.GetNodes([node_id])[0]
905 for field in node_fields:
906 if field not in tag_fields:
907 assert node[field] == node_fields[field]
910 print "Added node", node_id
912 def UpdateNodes(self):
914 Make random changes to any nodes we may have added.
917 node_types = self.api.GetNodeTypes()
919 raise Exception, "No node types"
920 boot_states = self.api.GetBootStates()
922 raise Exception, "No boot states"
924 for node_id in self.node_ids:
926 node_fields = random_node(node_types,boot_states)
927 self.api.UpdateNode(node_id, node_fields)
929 # for testing node arch
930 check=node_fields.copy()
931 for tagname in tag_fields:
933 node = self.api.GetNodes(node_id)[0]
935 raise Exception,'Unexpected result in GetNodes()'
937 # again when fetching 'arch' explicitly
938 node = self.api.GetNodes(node_id,Node.fields.keys()+tag_fields)[0]
939 if node != node_fields:
940 raise Exception,"Unexpected result in GetNodes() with tags"
943 # Add to a random set of node groups
944 nodegroup_ids = random.sample(self.nodegroup_ids, randint(0, len(self.nodegroup_ids)))
945 for nodegroup_id in (set(nodegroup_ids) - set(node['nodegroup_ids'])):
946 nodegroup = self.api.GetNodeGroups([nodegroup_id])[0]
947 tagname = nodegroup['tagname']
948 node_tags = self.api.GetNodeTags({'node_id':node_id,'tagname':tagname})
950 self.api.AddNodeTag(node_id,tagname,'yes')
952 node_tag=node_tags[0]
953 self.api.UpdateNodeTag(node_tag['node_tag_id'],'yes')
954 for nodegroup_id in (set(node['nodegroup_ids']) - set(nodegroup_ids)):
955 nodegroup = self.api.GetNodeGroups([nodegroup_id])[0]
956 tagname = nodegroup['tagname']
957 node_tags = self.api.GetNodeTags({'node_id':node_id,'tagname':tagname})
959 self.api.AddNodeTag(node_id,tagname,'no')
961 node_tag=node_tags[0]
962 self.api.UpdateNodeTag(node_tag['node_tag_id'],'no')
966 node = self.api.GetNodes([node_id])[0]
967 for field in node_fields:
968 assert node[field] == node_fields[field]
969 assert set(nodegroup_ids) == set(node['nodegroup_ids'])
972 print "Updated node", node_id
974 def DeleteNodes(self):
976 Delete any random nodes we may have added.
979 for node_id in self.node_ids:
980 # Remove from node groups
981 node = self.api.GetNodes([node_id])[0]
982 for node_tag in GetNodeTags ( {'node_id': node_id} ):
983 self.api.UpdateNodeTag(node_tag['node_tag_id'],'')
986 node = self.api.GetNodes([node_id])[0]
987 assert not node['nodegroup_ids']
989 self.api.DeleteNode(node_id)
992 assert not self.api.GetNodes([node_id])
995 print "Deleted node", node_id
998 assert not self.api.GetNodes(self.node_ids)
1002 def AddInterfaces(self, per_node = 1):
1004 Add a number of random network interfaces to each node.
1007 network_methods = self.api.GetNetworkMethods()
1008 if not network_methods:
1009 raise Exception, "No network methods"
1011 network_types = self.api.GetNetworkTypes()
1012 if not network_types:
1013 raise Exception, "No network types"
1015 for node_id in self.node_ids:
1016 for i in range(per_node):
1017 method = random.sample(network_methods, 1)[0]
1018 type = random.sample(network_types, 1)[0]
1021 interface_fields = random_interface(method, type)
1022 interface_id = self.api.AddInterface(node_id, interface_fields)
1024 # Should return a unique interface_id
1025 assert interface_id not in self.interface_ids
1026 self.interface_ids.append(interface_id)
1030 interface = self.api.GetInterfaces([interface_id])[0]
1031 for field in interface_fields:
1032 assert interface[field] == interface_fields[field]
1035 print "Added interface", interface_id, "to node", node_id
1037 def UpdateInterfaces(self):
1039 Make random changes to any network interfaces we may have added.
1042 network_methods = self.api.GetNetworkMethods()
1043 if not network_methods:
1044 raise Exception, "No network methods"
1046 network_types = self.api.GetNetworkTypes()
1047 if not network_types:
1048 raise Exception, "No network types"
1050 for interface_id in self.interface_ids:
1051 method = random.sample(network_methods, 1)[0]
1052 type = random.sample(network_types, 1)[0]
1055 interface_fields = random_interface(method, type)
1056 self.api.UpdateInterface(interface_id, interface_fields)
1060 interface = self.api.GetInterfaces([interface_id])[0]
1061 for field in interface_fields:
1062 assert interface[field] == interface_fields[field]
1065 print "Updated interface", interface_id
1067 def DeleteInterfaces(self):
1069 Delete any random network interfaces we may have added.
1072 for interface_id in self.interface_ids:
1073 self.api.DeleteInterface(interface_id)
1076 assert not self.api.GetInterfaces([interface_id])
1079 print "Deleted interface", interface_id
1082 assert not self.api.GetInterfaces(self.interface_ids)
1084 self.interface_ids = []
1086 def AddIlinks (self, n):
1088 Add random links between interfaces.
1092 src = random.sample(self.interface_ids,1)[0]
1093 dst = random.sample(self.interface_ids,1)[0]
1094 ilink_id = self.api.AddIlink (src,dst,
1095 self.ilink_type_ids[i],
1098 assert ilink_id not in self.ilink_ids
1099 self.ilink_ids.append(ilink_id)
1102 print 'Added Ilink',ilink_id,' - attached interface',src,'to',dst
1105 retrieve=GetIlinks({'src_interface_id':src,'dst_interface_id':dst,
1106 'tag_type_id':self.ilink_type_ids[i]})
1107 assert ilink_id==retrieve[0]['ilink_id']
1110 def UpdateIlinks (self):
1112 for ilink_id in self.ilink_ids:
1113 new_value=random_ilink()
1114 self.api.UpdateIlink(ilink_id,new_value)
1117 ilink=self.api.GetIlinks([ilink_id])[0]
1118 assert ilink['value'] == new_value
1121 print 'Updated Ilink',ilink_id
1123 def DeleteIlinks (self):
1124 for ilink_id in self.ilink_ids:
1125 self.api.DeleteIlink(ilink_id)
1128 assert not self.api.GetIlinks({'ilink_id':ilink_id})
1131 print 'Deleted Ilink',ilink_id
1134 assert not self.api.GetIlinks(self.ilink_ids)
1139 def AddPCUs(self, per_site = 1):
1141 Add a number of random PCUs to each site. Each node at the
1142 site will be added to a port on the PCU if AddNodes() was
1146 for site_id in self.site_ids:
1147 for i in range(per_site):
1149 pcu_fields = random_pcu()
1150 pcu_id = self.api.AddPCU(site_id, pcu_fields)
1152 # Should return a unique pcu_id
1153 assert pcu_id not in self.pcu_ids
1154 self.pcu_ids.append(pcu_id)
1156 # Add each node at this site to a different port on this PCU
1157 site = self.api.GetSites([site_id])[0]
1158 port = randint(1, 10)
1159 for node_id in site['node_ids']:
1160 self.api.AddNodeToPCU(node_id, pcu_id, port)
1165 pcu = self.api.GetPCUs([pcu_id])[0]
1166 for field in pcu_fields:
1167 assert pcu[field] == pcu_fields[field]
1170 print "Added PCU", pcu_id, "to site", site_id
1172 def UpdatePCUs(self):
1174 Make random changes to any PCUs we may have added.
1177 for pcu_id in self.pcu_ids:
1179 pcu_fields = random_pcu()
1180 self.api.UpdatePCU(pcu_id, pcu_fields)
1184 pcu = self.api.GetPCUs([pcu_id])[0]
1185 for field in pcu_fields:
1186 assert pcu[field] == pcu_fields[field]
1189 print "Updated PCU", pcu_id
1191 def DeletePCUs(self):
1193 Delete any random nodes we may have added.
1196 for pcu_id in self.pcu_ids:
1197 # Remove nodes from PCU
1198 pcu = self.api.GetPCUs([pcu_id])[0]
1199 for node_id in pcu['node_ids']:
1200 self.api.DeleteNodeFromPCU(node_id, pcu_id)
1203 pcu = self.api.GetPCUs([pcu_id])[0]
1204 assert not pcu['node_ids']
1206 self.api.DeletePCU(pcu_id)
1209 assert not self.api.GetPCUs([pcu_id])
1212 print "Deleted PCU", pcu_id
1215 assert not self.api.GetPCUs(self.pcu_ids)
1219 def AddConfFiles(self, n = 10):
1221 Add a number of random global configuration files.
1227 # Add a random configuration file
1228 conf_files.append(random_conf_file())
1231 # Add a nodegroup override file
1232 nodegroup_conf_file = conf_files[0].copy()
1233 nodegroup_conf_file['source'] = randpath(255)
1234 conf_files.append(nodegroup_conf_file)
1236 # Add a node override file
1237 node_conf_file = conf_files[0].copy()
1238 node_conf_file['source'] = randpath(255)
1239 conf_files.append(node_conf_file)
1241 for conf_file_fields in conf_files:
1242 conf_file_id = self.api.AddConfFile(conf_file_fields)
1244 # Should return a unique conf_file_id
1245 assert conf_file_id not in self.conf_file_ids
1246 self.conf_file_ids.append(conf_file_id)
1249 if conf_file_fields == nodegroup_conf_file and self.nodegroup_ids:
1250 nodegroup_id = random.sample(self.nodegroup_ids, 1)[0]
1251 self.api.AddConfFileToNodeGroup(conf_file_id, nodegroup_id)
1256 if conf_file_fields == node_conf_file and self.node_ids:
1257 node_id = random.sample(self.node_ids, 1)[0]
1258 self.api.AddConfFileToNode(conf_file_id, node_id)
1263 # Check configuration file
1264 conf_file = self.api.GetConfFiles([conf_file_id])[0]
1265 for field in conf_file_fields:
1266 assert conf_file[field] == conf_file_fields[field]
1269 print "Added configuration file", conf_file_id,
1270 if nodegroup_id is not None:
1271 print "to node group", nodegroup_id,
1272 elif node_id is not None:
1273 print "to node", node_id,
1276 def UpdateConfFiles(self):
1278 Make random changes to any configuration files we may have added.
1281 for conf_file_id in self.conf_file_ids:
1282 # Update configuration file
1283 conf_file_fields = random_conf_file()
1284 # Do not update dest so that it remains an override if set
1285 if 'dest' in conf_file_fields:
1286 del conf_file_fields['dest']
1287 self.api.UpdateConfFile(conf_file_id, conf_file_fields)
1290 # Check configuration file
1291 conf_file = self.api.GetConfFiles([conf_file_id])[0]
1292 for field in conf_file_fields:
1293 assert conf_file[field] == conf_file_fields[field]
1296 print "Updated configuration file", conf_file_id
1298 def DeleteConfFiles(self):
1300 Delete any random configuration files we may have added.
1303 for conf_file_id in self.conf_file_ids:
1304 self.api.DeleteConfFile(conf_file_id)
1307 assert not self.api.GetConfFiles([conf_file_id])
1310 print "Deleted configuration file", conf_file_id
1313 assert not self.api.GetConfFiles(self.conf_file_ids)
1315 self.conf_file_ids = []
1317 def AddTagTypes(self,n_sa,n_ng,n_il):
1319 Add as many tag types as there are nodegroups,
1320 will use tagvalue=yes for each nodegroup
1323 roles = self.api.GetRoles()
1325 raise Exception, "No roles"
1326 role_ids = [role['role_id'] for role in roles]
1328 for i in range (n_sa + n_ng + n_il):
1329 tag_type_fields = random_tag_type (role_ids)
1330 tag_type_id = self.api.AddTagType (tag_type_fields)
1332 assert tag_type_id not in \
1333 self.slice_type_ids + \
1334 self.nodegroup_type_ids + \
1338 self.slice_type_ids.append(tag_type_id)
1339 elif i < n_sa+n_ng :
1340 self.nodegroup_type_ids.append(tag_type_id)
1342 self.ilink_type_ids.append(tag_type_id)
1345 tag_type = self.api.GetTagTypes([tag_type_id])[0]
1346 for field in tag_type_fields:
1347 assert tag_type[field] == tag_type_fields[field]
1349 print "Updated slice attribute type", tag_type_id
1351 def UpdateTagTypes(self):
1353 Make random changes to any slice attribute types we may have added.
1356 roles = self.api.GetRoles()
1358 raise Exception, "No roles"
1359 role_ids = [role['role_id'] for role in roles]
1361 for tag_type_id in self.slice_type_ids + self.nodegroup_type_ids + self.ilink_type_ids:
1362 # Update slice attribute type
1363 tag_type_fields = random_tag_type(role_ids)
1364 self.api.UpdateTagType(tag_type_id, tag_type_fields)
1367 # Check slice attribute type
1368 tag_type = self.api.GetTagTypes([tag_type_id])[0]
1369 for field in tag_type_fields:
1370 assert tag_type[field] == tag_type_fields[field]
1372 print "Updated slice attribute type", tag_type_id
1374 def DeleteTagTypes(self):
1376 Delete any random slice attribute types we may have added.
1379 for tag_type_id in self.slice_type_ids + self.nodegroup_type_ids + self.ilink_type_ids:
1380 self.api.DeleteTagType(tag_type_id)
1383 assert not self.api.GetTagTypes([tag_type_id])
1386 print "Deleted slice attribute type", tag_type_id
1389 assert not self.api.GetTagTypes(self.slice_type_ids+self.nodegroup_type_ids+self.ilink_type_ids)
1391 self.slice_type_ids = []
1392 self.nodegroup_type_ids = []
1394 def AddSlices(self, per_site = 10):
1396 Add a number of random slices per site.
1399 for site in self.api.GetSites(self.site_ids):
1400 for i in range(min(per_site, site['max_slices'])):
1402 slice_fields = random_slice(site['login_base'])
1403 slice_id = self.api.AddSlice(slice_fields)
1405 # Should return a unique slice_id
1406 assert slice_id not in self.slice_ids
1407 self.slice_ids.append(slice_id)
1409 # Add slice to a random set of nodes
1410 node_ids = random.sample(self.node_ids, randint(0, len(self.node_ids)))
1412 self.api.AddSliceToNodes(slice_id, node_ids)
1414 # Add random set of site users to slice
1415 person_ids = random.sample(site['person_ids'], randint(0, len(site['person_ids'])))
1416 for person_id in person_ids:
1417 self.api.AddPersonToSlice(person_id, slice_id)
1421 slice = self.api.GetSlices([slice_id])[0]
1422 for field in slice_fields:
1423 assert slice[field] == slice_fields[field]
1425 assert set(node_ids) == set(slice['node_ids'])
1426 assert set(person_ids) == set(slice['person_ids'])
1429 print "Added slice", slice_id, "to site", site['site_id'],
1431 print "and nodes", node_ids,
1434 print "Added users", site['person_ids'], "to slice", slice_id
1436 def UpdateSlices(self):
1438 Make random changes to any slices we may have added.
1441 for slice_id in self.slice_ids:
1443 slice_fields = random_slice("unused")
1444 # Cannot change slice name
1445 if 'name' in slice_fields:
1446 del slice_fields['name']
1447 self.api.UpdateSlice(slice_id, slice_fields)
1449 slice = self.api.GetSlices([slice_id])[0]
1451 # Add slice to a random set of nodes
1452 node_ids = random.sample(self.node_ids, randint(0, len(self.node_ids)))
1453 self.api.AddSliceToNodes(slice_id, list(set(node_ids) - set(slice['node_ids'])))
1454 self.api.DeleteSliceFromNodes(slice_id, list(set(slice['node_ids']) - set(node_ids)))
1456 # Add random set of users to slice
1457 person_ids = random.sample(self.person_ids, randint(0, len(self.person_ids)))
1458 for person_id in (set(person_ids) - set(slice['person_ids'])):
1459 self.api.AddPersonToSlice(person_id, slice_id)
1460 for person_id in (set(slice['person_ids']) - set(person_ids)):
1461 self.api.DeletePersonFromSlice(person_id, slice_id)
1464 slice = self.api.GetSlices([slice_id])[0]
1465 for field in slice_fields:
1466 assert slice[field] == slice_fields[field]
1467 assert set(node_ids) == set(slice['node_ids'])
1468 assert set(person_ids) == set(slice['person_ids'])
1471 print "Updated slice", slice_id
1472 print "Added nodes", node_ids, "to slice", slice_id
1473 print "Added persons", person_ids, "to slice", slice_id
1475 def DeleteSlices(self):
1477 Delete any random slices we may have added.
1480 for slice_id in self.slice_ids:
1481 self.api.DeleteSlice(slice_id)
1484 assert not self.api.GetSlices([slice_id])
1487 print "Deleted slice", slice_id
1490 assert not self.api.GetSlices(self.slice_ids)
1494 def AddSliceTags(self, per_slice = 2):
1496 Add a number of random slices per site.
1499 if not self.slice_type_ids:
1502 for slice_id in self.slice_ids:
1503 slice = self.api.GetSlices([slice_id])[0]
1505 for i in range(per_slice):
1506 # Set a random slice/sliver attribute
1507 for tag_type_id in random.sample(self.slice_type_ids, 1):
1508 value = randstr(16, letters + '_' + digits)
1509 # Make it a sliver attribute with 50% probability
1510 if slice['node_ids']:
1511 node_id = random.sample(slice['node_ids'] + [None] * len(slice['node_ids']), 1)[0]
1515 # Add slice attribute
1517 slice_tag_id = self.api.AddSliceTag(slice_id, tag_type_id, value)
1519 slice_tag_id = self.api.AddSliceTag(slice_id, tag_type_id, value, node_id)
1521 # Should return a unique slice_tag_id
1522 assert slice_tag_id not in self.slice_tag_ids
1523 self.slice_tag_ids.append(slice_tag_id)
1526 # Check slice attribute
1527 slice_tag = self.api.GetSliceTags([slice_tag_id])[0]
1528 for field in 'tag_type_id', 'slice_id', 'node_id', 'slice_tag_id', 'value':
1529 assert slice_tag[field] == locals()[field]
1532 print "Added slice attribute", slice_tag_id, "of type", tag_type_id,
1533 if node_id is not None:
1534 print "to node", node_id,
1537 def UpdateSliceTags(self):
1539 Make random changes to any slice attributes we may have added.
1542 for slice_tag_id in self.slice_tag_ids:
1543 # Update slice attribute
1544 value = randstr(16, letters + '_' + digits)
1545 self.api.UpdateSliceTag(slice_tag_id, value)
1547 # Check slice attribute again
1548 slice_tag = self.api.GetSliceTags([slice_tag_id])[0]
1549 assert slice_tag['value'] == value
1552 print "Updated slice attribute", slice_tag_id
1554 def DeleteSliceTags(self):
1556 Delete any random slice attributes we may have added.
1559 for slice_tag_id in self.slice_tag_ids:
1560 self.api.DeleteSliceTag(slice_tag_id)
1563 assert not self.api.GetSliceTags([slice_tag_id])
1566 print "Deleted slice attribute", slice_tag_id
1569 assert not self.api.GetSliceTags(self.slice_tag_ids)
1571 self.slice_tag_ids = []
1574 parser = OptionParser()
1575 parser.add_option("-c", "--check", action = "store_true", default = False,
1576 help = "Check most actions (default: %default)")
1577 parser.add_option("-q", "--quiet", action = "store_true", default = False,
1578 help = "Be quiet (default: %default)")
1579 parser.add_option("-p","--preserve", action="store_true", default =False,
1580 help = "Do not delete created objects")
1581 parser.add_option("-t", "--tiny", action = "store_true", default = False,
1582 help = "Run a tiny test (default: %default)")
1583 (options, args) = parser.parse_args()
1585 test = Test(api = Shell(),
1586 check = options.check,
1587 verbose = not options.quiet,
1588 preserve = options.preserve)
1593 params = Test.default
1597 if __name__ == "__main__":