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(node_types,boot_states):
150 'hostname': randhostname(),
151 'node_type': random.sample(node_types,1)[0],
152 'boot_state': random.sample(boot_states, 1)[0],
153 'model': randstr(255),
154 'version': randstr(64),
155 # for testing node tags
159 def random_interface(method, type):
163 'bwlimit': randint(500000, 10000000),
167 ip = randint(0, 0xffffffff)
168 netmask = (0xffffffff << randint(2, 31)) & 0xffffffff
169 network = ip & netmask
170 broadcast = ((ip & netmask) | ~netmask) & 0xffffffff
171 gateway = randint(network + 1, broadcast - 1)
172 dns1 = randint(0, 0xffffffff)
174 for field in 'ip', 'netmask', 'network', 'broadcast', 'gateway', 'dns1':
175 interface_fields[field] = socket.inet_ntoa(struct.pack('>L', locals()[field]))
177 return interface_fields
184 'hostname': randhostname(),
185 'ip': socket.inet_ntoa(struct.pack('>L', randint(0, 0xffffffff))),
186 'protocol': randstr(16),
187 'username': randstr(254),
188 'password': randstr(254),
189 'notes': randstr(254),
190 'model': randstr(32),
193 def random_conf_file():
195 'enabled': bool(randint()),
196 'source': randpath(255),
197 'dest': randpath(255),
198 'file_permissions': "%#o" % randint(0, 512),
199 'file_owner': randstr(32, letters + '_' + digits),
200 'file_group': randstr(32, letters + '_' + digits),
201 'preinstall_cmd': randpath(100),
202 'postinstall_cmd': randpath(100),
203 'error_cmd': randpath(100),
204 'ignore_cmd_errors': bool(randint()),
205 'always_update': bool(randint()),
208 def random_slice(login_base):
210 'name': login_base + "_" + randstr(11, letters).lower(),
211 'url': "http://" + randhostname() + "/",
212 'description': randstr(2048),
219 'addresses_per_site': 1,
220 'persons_per_site': 1,
221 'keys_per_person': 1,
225 'interfaces_per_node': 1,
229 'slices_per_site': 1,
230 'attributes_per_slice': 1,
236 'addresses_per_site': 2,
237 'persons_per_site': 4,
238 'keys_per_person': 2,
242 'interfaces_per_node': 1,
246 'slices_per_site': 4,
247 'attributes_per_slice': 2,
250 def __init__(self, api, check = True, verbose = True, preserve = False):
253 self.verbose = verbose
254 self.preserve = preserve
257 self.address_type_ids = []
258 self.address_ids = []
261 self.slice_type_ids = []
262 self.nodegroup_type_ids = []
263 self.ilink_type_ids = []
264 self.nodegroup_ids = []
266 self.interface_ids = []
269 self.conf_file_ids = []
271 self.slice_tag_ids = []
273 def Cardinals (self):
274 return [len(x) for x in (
275 self.api.GetNodes({},['node_id']),
276 self.api.GetSites({},['site_id']),
277 self.api.GetPersons({},['person_id']),
278 self.api.GetSlices({},['slice_id']),
281 def Run(self, **kwds):
283 Run a complete database and API consistency test. Populates
284 the database with a set of random entities, updates them, then
285 deletes them. Examples:
287 test.Run() # Defaults
288 test.Run(**Test.default) # Defaults
289 test.Run(**Test.tiny) # Tiny set
290 test.Run(sites = 123, slices_per_site = 4) # Defaults with overrides
293 cardinals_before=self.Cardinals()
294 print 'Cardinals before test (n,s,p,sl)',cardinals_before
299 print 'Preserving - delete skipped'
303 cardinals_after=self.Cardinals()
304 print 'Cardinals after test (n,s,p,sl)',cardinals_after
306 if cardinals_before != cardinals_after:
307 raise Exception, 'cardinals before and after differ - check deletion mechanisms'
309 def Add(self, **kwds):
311 Populate the database with a set of random entities. Examples:
313 test.populate() # Defaults
314 test.populate(Test.tiny) # Tiny set
315 test.populate(sites = 123, slices_per_site = 4) # Defaults with overrides
318 params = self.default.copy()
321 self.AddSites(params['sites'])
322 self.AddAddressTypes(params['address_types'])
323 self.AddAddresses(params['addresses_per_site'])
324 self.AddPersons(params['persons_per_site'])
325 self.AddKeys(params['keys_per_person'])
326 self.AddTagTypes(params['slice_tags'],params['nodegroups'],params['ilinks'])
327 self.AddNodeGroups(params['nodegroups'])
328 self.AddNodes(params['nodes_per_site'])
329 self.AddInterfaces(params['interfaces_per_node'])
330 self.AddIlinks (params['ilinks'])
331 self.AddPCUs(params['pcus_per_site'])
332 self.AddConfFiles(params['conf_files'])
333 self.AddSlices(params['slices_per_site'])
334 self.AddSliceTags(params['attributes_per_slice'])
338 self.UpdateAddressTypes()
339 self.UpdateAddresses()
342 self.UpdateTagTypes()
343 self.UpdateNodeGroups()
345 self.UpdateInterfaces()
348 self.UpdateConfFiles()
350 self.UpdateSliceTags()
353 self.DeleteSliceTags()
356 self.DeleteConfFiles()
359 self.DeleteInterfaces()
362 self.DeleteNodeGroups()
363 self.DeleteTagTypes()
364 self.DeleteAddresses()
365 self.DeleteAddressTypes()
368 def AddSites(self, n = 10):
370 Add a number of random sites.
375 site_fields = random_site()
376 site_id = self.api.AddSite(site_fields)
378 # Should return a unique site_id
379 assert site_id not in self.site_ids
380 self.site_ids.append(site_id)
382 # Enable slice creation
383 site_fields['max_slices'] = randint(1, 10)
384 self.api.UpdateSite(site_id, site_fields)
388 site = self.api.GetSites([site_id])[0]
389 for field in site_fields:
390 assert site[field] == site_fields[field]
393 print "Added site", site_id
395 def UpdateSites(self):
397 Make random changes to any sites we may have added.
400 for site_id in self.site_ids:
402 site_fields = random_site()
403 # Do not change login_base
404 if 'login_base' in site_fields:
405 del site_fields['login_base']
406 self.api.UpdateSite(site_id, site_fields)
410 site = self.api.GetSites([site_id])[0]
411 for field in site_fields:
412 assert site[field] == site_fields[field]
415 print "Updated site", site_id
417 def DeleteSites(self):
419 Delete any random sites we may have added.
422 for site_id in self.site_ids:
423 self.api.DeleteSite(site_id)
426 assert not self.api.GetSites([site_id])
429 print "Deleted site", site_id
432 assert not self.api.GetSites(self.site_ids)
436 def AddAddressTypes(self, n = 2):
438 Add a number of random address types.
442 address_type_fields = random_address_type()
443 address_type_id = self.api.AddAddressType(address_type_fields)
445 # Should return a unique address_type_id
446 assert address_type_id not in self.address_type_ids
447 self.address_type_ids.append(address_type_id)
451 address_type = self.api.GetAddressTypes([address_type_id])[0]
452 for field in address_type_fields:
453 assert address_type[field] == address_type_fields[field]
456 print "Added address type", address_type_id
458 def UpdateAddressTypes(self):
460 Make random changes to any address types we may have added.
463 for address_type_id in self.address_type_ids:
464 # Update address_type
465 address_type_fields = random_address_type()
466 self.api.UpdateAddressType(address_type_id, address_type_fields)
470 address_type = self.api.GetAddressTypes([address_type_id])[0]
471 for field in address_type_fields:
472 assert address_type[field] == address_type_fields[field]
475 print "Updated address_type", address_type_id
477 def DeleteAddressTypes(self):
479 Delete any random address types we may have added.
482 for address_type_id in self.address_type_ids:
483 self.api.DeleteAddressType(address_type_id)
486 assert not self.api.GetAddressTypes([address_type_id])
489 print "Deleted address type", address_type_id
492 assert not self.api.GetAddressTypes(self.address_type_ids)
494 self.address_type_ids = []
496 def AddAddresses(self, per_site = 2):
498 Add a number of random addresses to each site.
501 for site_id in self.site_ids:
502 for i in range(per_site):
503 address_fields = random_address()
504 address_id = self.api.AddSiteAddress(site_id, address_fields)
506 # Should return a unique address_id
507 assert address_id not in self.address_ids
508 self.address_ids.append(address_id)
510 # Add random address type
511 if self.address_type_ids:
512 for address_type_id in random.sample(self.address_type_ids, 1):
513 self.api.AddAddressTypeToAddress(address_type_id, address_id)
517 address = self.api.GetAddresses([address_id])[0]
518 for field in address_fields:
519 assert address[field] == address_fields[field]
522 print "Added address", address_id, "to site", site_id
524 def UpdateAddresses(self):
526 Make random changes to any addresses we may have added.
529 for address_id in self.address_ids:
531 address_fields = random_address()
532 self.api.UpdateAddress(address_id, address_fields)
536 address = self.api.GetAddresses([address_id])[0]
537 for field in address_fields:
538 assert address[field] == address_fields[field]
541 print "Updated address", address_id
543 def DeleteAddresses(self):
545 Delete any random addresses we may have added.
548 for address_id in self.address_ids:
549 # Remove address types
550 address = self.api.GetAddresses([address_id])[0]
551 for address_type_id in address['address_type_ids']:
552 self.api.DeleteAddressTypeFromAddress(address_type_id, address_id)
555 address = self.api.GetAddresses([address_id])[0]
556 assert not address['address_type_ids']
558 self.api.DeleteAddress(address_id)
561 assert not self.api.GetAddresses([address_id])
564 print "Deleted address", address_id
567 assert not self.api.GetAddresses(self.address_ids)
569 self.address_ids = []
571 def AddPersons(self, per_site = 10):
573 Add a number of random users to each site.
576 for site_id in self.site_ids:
577 for i in range(per_site):
579 person_fields = random_person()
580 person_id = self.api.AddPerson(person_fields)
582 # Should return a unique person_id
583 assert person_id not in self.person_ids
584 self.person_ids.append(person_id)
588 person = self.api.GetPersons([person_id])[0]
589 for field in person_fields:
590 if field != 'password':
591 assert person[field] == person_fields[field]
593 auth = {'AuthMethod': "password",
594 'Username': person_fields['email'],
595 'AuthString': person_fields['password']}
598 # Check that user is disabled
600 assert not self.api.AuthCheck(auth)
604 # Add random set of roles
605 role_ids = random.sample([20, 30, 40], randint(1, 3))
606 for role_id in role_ids:
607 self.api.AddRoleToPerson(role_id, person_id)
610 person = self.api.GetPersons([person_id])[0]
611 assert set(role_ids) == set(person['role_ids'])
614 self.api.UpdatePerson(person_id, {'enabled': True})
617 # Check that user is enabled
618 assert self.api.AuthCheck(auth)
620 # Associate user with site
621 self.api.AddPersonToSite(person_id, site_id)
622 self.api.SetPersonPrimarySite(person_id, site_id)
625 person = self.api.GetPersons([person_id])[0]
626 assert person['site_ids'][0] == site_id
629 print "Added user", person_id, "to site", site_id
631 def UpdatePersons(self):
633 Make random changes to any users we may have added.
636 for person_id in self.person_ids:
638 person_fields = random_person()
640 person_fields['enabled'] = True
641 self.api.UpdatePerson(person_id, person_fields)
645 person = self.api.GetPersons([person_id])[0]
646 for field in person_fields:
647 if field != 'password':
648 assert person[field] == person_fields[field]
651 print "Updated person", person_id
653 person = self.api.GetPersons([person_id])[0]
655 # Associate user with a random set of sites
656 site_ids = random.sample(self.site_ids, randint(0, len(self.site_ids)))
657 for site_id in (set(site_ids) - set(person['site_ids'])):
658 self.api.AddPersonToSite(person_id, site_id)
659 for site_id in (set(person['site_ids']) - set(site_ids)):
660 self.api.DeletePersonFromSite(person_id, site_id)
663 self.api.SetPersonPrimarySite(person_id, site_ids[0])
666 person = self.api.GetPersons([person_id])[0]
667 assert set(site_ids) == set(person['site_ids'])
670 print "Updated person", person_id, "to sites", site_ids
672 def DeletePersons(self):
674 Delete any random users we may have added.
677 for person_id in self.person_ids:
679 person = self.api.GetPersons([person_id])[0]
680 for site_id in person['site_ids']:
681 self.api.DeletePersonFromSite(person_id, site_id)
684 person = self.api.GetPersons([person_id])[0]
685 assert not person['site_ids']
688 for role_id in person['role_ids']:
689 self.api.DeleteRoleFromPerson(role_id, person_id)
692 person = self.api.GetPersons([person_id])[0]
693 assert not person['role_ids']
696 self.api.UpdatePerson(person_id, {'enabled': False})
699 person = self.api.GetPersons([person_id])[0]
700 assert not person['enabled']
703 self.api.DeletePerson(person_id)
706 assert not self.api.GetPersons([person_id])
709 print "Deleted user", person_id
712 assert not self.api.GetPersons(self.person_ids)
716 def AddKeys(self, per_person = 2):
718 Add a number of random keys to each user.
721 key_types = self.api.GetKeyTypes()
723 raise Exception, "No key types"
725 for person_id in self.person_ids:
726 for i in range(per_person):
728 key_fields = random_key(key_types)
729 key_id = self.api.AddPersonKey(person_id, key_fields)
731 # Should return a unique key_id
732 assert key_id not in self.key_ids
733 self.key_ids.append(key_id)
737 key = self.api.GetKeys([key_id])[0]
738 for field in key_fields:
739 assert key[field] == key_fields[field]
741 # Add and immediately blacklist a key
742 key_fields = random_key(key_types)
743 key_id = self.api.AddPersonKey(person_id, key_fields)
745 self.api.BlacklistKey(key_id)
747 # Is effectively deleted
748 assert not self.api.GetKeys([key_id])
750 # Cannot be added again
752 key_id = self.api.AddPersonKey(person_id, key_fields)
758 print "Added key", key_id, "to user", person_id
760 def UpdateKeys(self):
762 Make random changes to any keys we may have added.
765 key_types = self.api.GetKeyTypes()
767 raise Exception, "No key types"
769 for key_id in self.key_ids:
771 key_fields = random_key(key_types)
772 self.api.UpdateKey(key_id, key_fields)
776 key = self.api.GetKeys([key_id])[0]
777 for field in key_fields:
778 assert key[field] == key_fields[field]
781 print "Updated key", key_id
783 def DeleteKeys(self):
785 Delete any random keys we may have added.
788 for key_id in self.key_ids:
789 self.api.DeleteKey(key_id)
792 assert not self.api.GetKeys([key_id])
795 print "Deleted key", key_id
798 assert not self.api.GetKeys(self.key_ids)
802 def AddNodeGroups(self, n = 10):
804 Add a number of random node groups.
809 tag_type_id = self.nodegroup_type_ids[i]
810 tagname=self.api.GetTagTypes([tag_type_id])[0]['tagname']
813 groupname = random_nodegroup() ['groupname']
815 nodegroup_id = self.api.AddNodeGroup(groupname, tagname, tagvalue)
817 # Should return a unique nodegroup_id
818 assert nodegroup_id not in self.nodegroup_ids
819 self.nodegroup_ids.append(nodegroup_id)
823 nodegroup = self.api.GetNodeGroups([nodegroup_id])[0]
824 assert nodegroup['groupname'] == groupname
825 assert nodegroup['tagname'] == tagname
826 assert nodegroup['tagvalue'] == tagvalue
829 print "Added node group", nodegroup_id
831 def UpdateNodeGroups(self):
833 Make random changes to any node groups we may have added.
836 for nodegroup_id in self.nodegroup_ids:
838 groupname = random_nodegroup()['groupname']
839 # cannot change tagname
840 nodegroup_fields = { 'groupname':groupname }
841 self.api.UpdateNodeGroup(nodegroup_id, nodegroup_fields)
845 nodegroup = self.api.GetNodeGroups([nodegroup_id])[0]
846 for field in nodegroup_fields:
847 assert nodegroup[field] == nodegroup_fields[field]
850 print "Updated node group", nodegroup_id
852 def DeleteNodeGroups(self):
854 Delete any random node groups we may have added.
857 for nodegroup_id in self.nodegroup_ids:
858 self.api.DeleteNodeGroup(nodegroup_id)
861 assert not self.api.GetNodeGroups([nodegroup_id])
864 print "Deleted node group", nodegroup_id
867 assert not self.api.GetNodeGroups(self.nodegroup_ids)
869 self.nodegroup_ids = []
871 def AddNodes(self, per_site = 2):
873 Add a number of random nodes to each site. Each node will also
874 be added to a random node group if AddNodeGroups() was
878 node_types = self.api.GetNodeTypes()
880 raise Exception, "No node types"
881 boot_states = self.api.GetBootStates()
883 raise Exception, "No boot states"
885 for site_id in self.site_ids:
886 for i in range(per_site):
888 node_fields = random_node(node_types,boot_states)
889 node_id = self.api.AddNode(site_id, node_fields)
891 # Should return a unique node_id
892 assert node_id not in self.node_ids
893 self.node_ids.append(node_id)
895 # Add to a random set of node groups
896 nodegroup_ids = random.sample(self.nodegroup_ids, randint(0, len(self.nodegroup_ids)))
897 for nodegroup_id in nodegroup_ids:
898 tagname = self.api.GetNodeGroups([nodegroup_id])[0]['tagname']
899 self.api.AddNodeTag( node_id, tagname, 'yes' )
903 node = self.api.GetNodes([node_id])[0]
904 for field in node_fields:
905 assert node[field] == node_fields[field]
908 print "Added node", node_id
910 def UpdateNodes(self):
912 Make random changes to any nodes we may have added.
915 node_types = self.api.GetNodeTypes()
917 raise Exception, "No node types"
918 boot_states = self.api.GetBootStates()
920 raise Exception, "No boot states"
922 for node_id in self.node_ids:
924 node_fields = random_node(node_types,boot_states)
925 self.api.UpdateNode(node_id, node_fields)
927 # for testing node arch
928 check=node_fields.copy()
929 arch=check.pop('arch')
930 node = self.api.GetNodes(node_id)[0]
932 raise Exception,'Unexpected result in GetNodes()'
934 # again when fetching 'arch' explicitly
935 node = self.api.GetNodes(node_id,Node.fields.keys()+'arch')[0]
936 if node != node_fields:
937 raise Exception,"Unexpected result in GetNodes(['__all__','arch'])"
940 # Add to a random set of node groups
941 nodegroup_ids = random.sample(self.nodegroup_ids, randint(0, len(self.nodegroup_ids)))
942 for nodegroup_id in (set(nodegroup_ids) - set(node['nodegroup_ids'])):
943 nodegroup = self.api.GetNodeGroups([nodegroup_id])[0]
944 tagname = nodegroup['tagname']
945 node_tags = self.api.GetNodeTags({'node_id':node_id,'tagname':tagname})
947 self.api.AddNodeTag(node_id,tagname,'yes')
949 node_tag=node_tags[0]
950 self.api.UpdateNodeTag(node_tag['node_tag_id'],'yes')
951 for nodegroup_id in (set(node['nodegroup_ids']) - set(nodegroup_ids)):
952 nodegroup = self.api.GetNodeGroups([nodegroup_id])[0]
953 tagname = nodegroup['tagname']
954 node_tags = self.api.GetNodeTags({'node_id':node_id,'tagname':tagname})
956 self.api.AddNodeTag(node_id,tagname,'no')
958 node_tag=node_tags[0]
959 self.api.UpdateNodeTag(node_tag['node_tag_id'],'no')
963 node = self.api.GetNodes([node_id])[0]
964 for field in node_fields:
965 assert node[field] == node_fields[field]
966 assert set(nodegroup_ids) == set(node['nodegroup_ids'])
969 print "Updated node", node_id
971 def DeleteNodes(self):
973 Delete any random nodes we may have added.
976 for node_id in self.node_ids:
977 # Remove from node groups
978 node = self.api.GetNodes([node_id])[0]
979 for node_tag in GetNodeTags ( {'node_id': node_id} ):
980 self.api.UpdateNodeTag(node_tag['node_tag_id'],'')
983 node = self.api.GetNodes([node_id])[0]
984 assert not node['nodegroup_ids']
986 self.api.DeleteNode(node_id)
989 assert not self.api.GetNodes([node_id])
992 print "Deleted node", node_id
995 assert not self.api.GetNodes(self.node_ids)
999 def AddInterfaces(self, per_node = 1):
1001 Add a number of random network interfaces to each node.
1004 network_methods = self.api.GetNetworkMethods()
1005 if not network_methods:
1006 raise Exception, "No network methods"
1008 network_types = self.api.GetNetworkTypes()
1009 if not network_types:
1010 raise Exception, "No network types"
1012 for node_id in self.node_ids:
1013 for i in range(per_node):
1014 method = random.sample(network_methods, 1)[0]
1015 type = random.sample(network_types, 1)[0]
1018 interface_fields = random_interface(method, type)
1019 interface_id = self.api.AddInterface(node_id, interface_fields)
1021 # Should return a unique interface_id
1022 assert interface_id not in self.interface_ids
1023 self.interface_ids.append(interface_id)
1027 interface = self.api.GetInterfaces([interface_id])[0]
1028 for field in interface_fields:
1029 assert interface[field] == interface_fields[field]
1032 print "Added interface", interface_id, "to node", node_id
1034 def UpdateInterfaces(self):
1036 Make random changes to any network interfaces we may have added.
1039 network_methods = self.api.GetNetworkMethods()
1040 if not network_methods:
1041 raise Exception, "No network methods"
1043 network_types = self.api.GetNetworkTypes()
1044 if not network_types:
1045 raise Exception, "No network types"
1047 for interface_id in self.interface_ids:
1048 method = random.sample(network_methods, 1)[0]
1049 type = random.sample(network_types, 1)[0]
1052 interface_fields = random_interface(method, type)
1053 self.api.UpdateInterface(interface_id, interface_fields)
1057 interface = self.api.GetInterfaces([interface_id])[0]
1058 for field in interface_fields:
1059 assert interface[field] == interface_fields[field]
1062 print "Updated interface", interface_id
1064 def DeleteInterfaces(self):
1066 Delete any random network interfaces we may have added.
1069 for interface_id in self.interface_ids:
1070 self.api.DeleteInterface(interface_id)
1073 assert not self.api.GetInterfaces([interface_id])
1076 print "Deleted interface", interface_id
1079 assert not self.api.GetInterfaces(self.interface_ids)
1081 self.interface_ids = []
1083 def AddIlinks (self, n):
1085 Add random links between interfaces.
1089 src = random.sample(self.interface_ids,1)[0]
1090 dst = random.sample(self.interface_ids,1)[0]
1091 ilink_id = self.api.AddIlink (src,dst,
1092 self.ilink_type_ids[i],
1095 assert ilink_id not in self.ilink_ids
1096 self.ilink_ids.append(ilink_id)
1099 print 'Added Ilink',ilink_id,' - attached interface',src,'to',dst
1102 retrieve=GetIlinks({'src_interface_id':src,'dst_interface_id':dst,
1103 'tag_type_id':self.ilink_type_ids[i]})
1104 assert ilink_id==retrieve[0]['ilink_id']
1107 def UpdateIlinks (self):
1109 for ilink_id in self.ilink_ids:
1110 new_value=random_ilink()
1111 self.api.UpdateIlink(ilink_id,new_value)
1114 ilink=self.api.GetIlinks([ilink_id])[0]
1115 assert ilink['value'] == new_value
1118 print 'Updated Ilink',ilink_id
1120 def DeleteIlinks (self):
1121 for ilink_id in self.ilink_ids:
1122 self.api.DeleteIlink(ilink_id)
1125 assert not self.api.GetIlinks({'ilink_id':ilink_id})
1128 print 'Deleted Ilink',ilink_id
1131 assert not self.api.GetIlinks(self.ilink_ids)
1136 def AddPCUs(self, per_site = 1):
1138 Add a number of random PCUs to each site. Each node at the
1139 site will be added to a port on the PCU if AddNodes() was
1143 for site_id in self.site_ids:
1144 for i in range(per_site):
1146 pcu_fields = random_pcu()
1147 pcu_id = self.api.AddPCU(site_id, pcu_fields)
1149 # Should return a unique pcu_id
1150 assert pcu_id not in self.pcu_ids
1151 self.pcu_ids.append(pcu_id)
1153 # Add each node at this site to a different port on this PCU
1154 site = self.api.GetSites([site_id])[0]
1155 port = randint(1, 10)
1156 for node_id in site['node_ids']:
1157 self.api.AddNodeToPCU(node_id, pcu_id, port)
1162 pcu = self.api.GetPCUs([pcu_id])[0]
1163 for field in pcu_fields:
1164 assert pcu[field] == pcu_fields[field]
1167 print "Added PCU", pcu_id, "to site", site_id
1169 def UpdatePCUs(self):
1171 Make random changes to any PCUs we may have added.
1174 for pcu_id in self.pcu_ids:
1176 pcu_fields = random_pcu()
1177 self.api.UpdatePCU(pcu_id, pcu_fields)
1181 pcu = self.api.GetPCUs([pcu_id])[0]
1182 for field in pcu_fields:
1183 assert pcu[field] == pcu_fields[field]
1186 print "Updated PCU", pcu_id
1188 def DeletePCUs(self):
1190 Delete any random nodes we may have added.
1193 for pcu_id in self.pcu_ids:
1194 # Remove nodes from PCU
1195 pcu = self.api.GetPCUs([pcu_id])[0]
1196 for node_id in pcu['node_ids']:
1197 self.api.DeleteNodeFromPCU(node_id, pcu_id)
1200 pcu = self.api.GetPCUs([pcu_id])[0]
1201 assert not pcu['node_ids']
1203 self.api.DeletePCU(pcu_id)
1206 assert not self.api.GetPCUs([pcu_id])
1209 print "Deleted PCU", pcu_id
1212 assert not self.api.GetPCUs(self.pcu_ids)
1216 def AddConfFiles(self, n = 10):
1218 Add a number of random global configuration files.
1224 # Add a random configuration file
1225 conf_files.append(random_conf_file())
1228 # Add a nodegroup override file
1229 nodegroup_conf_file = conf_files[0].copy()
1230 nodegroup_conf_file['source'] = randpath(255)
1231 conf_files.append(nodegroup_conf_file)
1233 # Add a node override file
1234 node_conf_file = conf_files[0].copy()
1235 node_conf_file['source'] = randpath(255)
1236 conf_files.append(node_conf_file)
1238 for conf_file_fields in conf_files:
1239 conf_file_id = self.api.AddConfFile(conf_file_fields)
1241 # Should return a unique conf_file_id
1242 assert conf_file_id not in self.conf_file_ids
1243 self.conf_file_ids.append(conf_file_id)
1246 if conf_file_fields == nodegroup_conf_file and self.nodegroup_ids:
1247 nodegroup_id = random.sample(self.nodegroup_ids, 1)[0]
1248 self.api.AddConfFileToNodeGroup(conf_file_id, nodegroup_id)
1253 if conf_file_fields == node_conf_file and self.node_ids:
1254 node_id = random.sample(self.node_ids, 1)[0]
1255 self.api.AddConfFileToNode(conf_file_id, node_id)
1260 # Check configuration file
1261 conf_file = self.api.GetConfFiles([conf_file_id])[0]
1262 for field in conf_file_fields:
1263 assert conf_file[field] == conf_file_fields[field]
1266 print "Added configuration file", conf_file_id,
1267 if nodegroup_id is not None:
1268 print "to node group", nodegroup_id,
1269 elif node_id is not None:
1270 print "to node", node_id,
1273 def UpdateConfFiles(self):
1275 Make random changes to any configuration files we may have added.
1278 for conf_file_id in self.conf_file_ids:
1279 # Update configuration file
1280 conf_file_fields = random_conf_file()
1281 # Do not update dest so that it remains an override if set
1282 if 'dest' in conf_file_fields:
1283 del conf_file_fields['dest']
1284 self.api.UpdateConfFile(conf_file_id, conf_file_fields)
1287 # Check configuration file
1288 conf_file = self.api.GetConfFiles([conf_file_id])[0]
1289 for field in conf_file_fields:
1290 assert conf_file[field] == conf_file_fields[field]
1293 print "Updated configuration file", conf_file_id
1295 def DeleteConfFiles(self):
1297 Delete any random configuration files we may have added.
1300 for conf_file_id in self.conf_file_ids:
1301 self.api.DeleteConfFile(conf_file_id)
1304 assert not self.api.GetConfFiles([conf_file_id])
1307 print "Deleted configuration file", conf_file_id
1310 assert not self.api.GetConfFiles(self.conf_file_ids)
1312 self.conf_file_ids = []
1314 def AddTagTypes(self,n_sa,n_ng,n_il):
1316 Add as many tag types as there are nodegroups,
1317 will use tagvalue=yes for each nodegroup
1320 roles = self.api.GetRoles()
1322 raise Exception, "No roles"
1323 role_ids = [role['role_id'] for role in roles]
1325 for i in range (n_sa + n_ng + n_il):
1326 tag_type_fields = random_tag_type (role_ids)
1327 tag_type_id = self.api.AddTagType (tag_type_fields)
1329 assert tag_type_id not in \
1330 self.slice_type_ids + \
1331 self.nodegroup_type_ids + \
1335 self.slice_type_ids.append(tag_type_id)
1336 elif i < n_sa+n_ng :
1337 self.nodegroup_type_ids.append(tag_type_id)
1339 self.ilink_type_ids.append(tag_type_id)
1342 tag_type = self.api.GetTagTypes([tag_type_id])[0]
1343 for field in tag_type_fields:
1344 assert tag_type[field] == tag_type_fields[field]
1346 print "Updated slice attribute type", tag_type_id
1348 def UpdateTagTypes(self):
1350 Make random changes to any slice attribute types we may have added.
1353 roles = self.api.GetRoles()
1355 raise Exception, "No roles"
1356 role_ids = [role['role_id'] for role in roles]
1358 for tag_type_id in self.slice_type_ids + self.nodegroup_type_ids + self.ilink_type_ids:
1359 # Update slice attribute type
1360 tag_type_fields = random_tag_type(role_ids)
1361 self.api.UpdateTagType(tag_type_id, tag_type_fields)
1364 # Check slice attribute type
1365 tag_type = self.api.GetTagTypes([tag_type_id])[0]
1366 for field in tag_type_fields:
1367 assert tag_type[field] == tag_type_fields[field]
1369 print "Updated slice attribute type", tag_type_id
1371 def DeleteTagTypes(self):
1373 Delete any random slice attribute types we may have added.
1376 for tag_type_id in self.slice_type_ids + self.nodegroup_type_ids + self.ilink_type_ids:
1377 self.api.DeleteTagType(tag_type_id)
1380 assert not self.api.GetTagTypes([tag_type_id])
1383 print "Deleted slice attribute type", tag_type_id
1386 assert not self.api.GetTagTypes(self.slice_type_ids+self.nodegroup_type_ids+self.ilink_type_ids)
1388 self.slice_type_ids = []
1389 self.nodegroup_type_ids = []
1391 def AddSlices(self, per_site = 10):
1393 Add a number of random slices per site.
1396 for site in self.api.GetSites(self.site_ids):
1397 for i in range(min(per_site, site['max_slices'])):
1399 slice_fields = random_slice(site['login_base'])
1400 slice_id = self.api.AddSlice(slice_fields)
1402 # Should return a unique slice_id
1403 assert slice_id not in self.slice_ids
1404 self.slice_ids.append(slice_id)
1406 # Add slice to a random set of nodes
1407 node_ids = random.sample(self.node_ids, randint(0, len(self.node_ids)))
1409 self.api.AddSliceToNodes(slice_id, node_ids)
1411 # Add random set of site users to slice
1412 person_ids = random.sample(site['person_ids'], randint(0, len(site['person_ids'])))
1413 for person_id in person_ids:
1414 self.api.AddPersonToSlice(person_id, slice_id)
1418 slice = self.api.GetSlices([slice_id])[0]
1419 for field in slice_fields:
1420 assert slice[field] == slice_fields[field]
1422 assert set(node_ids) == set(slice['node_ids'])
1423 assert set(person_ids) == set(slice['person_ids'])
1426 print "Added slice", slice_id, "to site", site['site_id'],
1428 print "and nodes", node_ids,
1431 print "Added users", site['person_ids'], "to slice", slice_id
1433 def UpdateSlices(self):
1435 Make random changes to any slices we may have added.
1438 for slice_id in self.slice_ids:
1440 slice_fields = random_slice("unused")
1441 # Cannot change slice name
1442 if 'name' in slice_fields:
1443 del slice_fields['name']
1444 self.api.UpdateSlice(slice_id, slice_fields)
1446 slice = self.api.GetSlices([slice_id])[0]
1448 # Add slice to a random set of nodes
1449 node_ids = random.sample(self.node_ids, randint(0, len(self.node_ids)))
1450 self.api.AddSliceToNodes(slice_id, list(set(node_ids) - set(slice['node_ids'])))
1451 self.api.DeleteSliceFromNodes(slice_id, list(set(slice['node_ids']) - set(node_ids)))
1453 # Add random set of users to slice
1454 person_ids = random.sample(self.person_ids, randint(0, len(self.person_ids)))
1455 for person_id in (set(person_ids) - set(slice['person_ids'])):
1456 self.api.AddPersonToSlice(person_id, slice_id)
1457 for person_id in (set(slice['person_ids']) - set(person_ids)):
1458 self.api.DeletePersonFromSlice(person_id, slice_id)
1461 slice = self.api.GetSlices([slice_id])[0]
1462 for field in slice_fields:
1463 assert slice[field] == slice_fields[field]
1464 assert set(node_ids) == set(slice['node_ids'])
1465 assert set(person_ids) == set(slice['person_ids'])
1468 print "Updated slice", slice_id
1469 print "Added nodes", node_ids, "to slice", slice_id
1470 print "Added persons", person_ids, "to slice", slice_id
1472 def DeleteSlices(self):
1474 Delete any random slices we may have added.
1477 for slice_id in self.slice_ids:
1478 self.api.DeleteSlice(slice_id)
1481 assert not self.api.GetSlices([slice_id])
1484 print "Deleted slice", slice_id
1487 assert not self.api.GetSlices(self.slice_ids)
1491 def AddSliceTags(self, per_slice = 2):
1493 Add a number of random slices per site.
1496 if not self.slice_type_ids:
1499 for slice_id in self.slice_ids:
1500 slice = self.api.GetSlices([slice_id])[0]
1502 for i in range(per_slice):
1503 # Set a random slice/sliver attribute
1504 for tag_type_id in random.sample(self.slice_type_ids, 1):
1505 value = randstr(16, letters + '_' + digits)
1506 # Make it a sliver attribute with 50% probability
1507 if slice['node_ids']:
1508 node_id = random.sample(slice['node_ids'] + [None] * len(slice['node_ids']), 1)[0]
1512 # Add slice attribute
1514 slice_tag_id = self.api.AddSliceTag(slice_id, tag_type_id, value)
1516 slice_tag_id = self.api.AddSliceTag(slice_id, tag_type_id, value, node_id)
1518 # Should return a unique slice_tag_id
1519 assert slice_tag_id not in self.slice_tag_ids
1520 self.slice_tag_ids.append(slice_tag_id)
1523 # Check slice attribute
1524 slice_tag = self.api.GetSliceTags([slice_tag_id])[0]
1525 for field in 'tag_type_id', 'slice_id', 'node_id', 'slice_tag_id', 'value':
1526 assert slice_tag[field] == locals()[field]
1529 print "Added slice attribute", slice_tag_id, "of type", tag_type_id,
1530 if node_id is not None:
1531 print "to node", node_id,
1534 def UpdateSliceTags(self):
1536 Make random changes to any slice attributes we may have added.
1539 for slice_tag_id in self.slice_tag_ids:
1540 # Update slice attribute
1541 value = randstr(16, letters + '_' + digits)
1542 self.api.UpdateSliceTag(slice_tag_id, value)
1544 # Check slice attribute again
1545 slice_tag = self.api.GetSliceTags([slice_tag_id])[0]
1546 assert slice_tag['value'] == value
1549 print "Updated slice attribute", slice_tag_id
1551 def DeleteSliceTags(self):
1553 Delete any random slice attributes we may have added.
1556 for slice_tag_id in self.slice_tag_ids:
1557 self.api.DeleteSliceTag(slice_tag_id)
1560 assert not self.api.GetSliceTags([slice_tag_id])
1563 print "Deleted slice attribute", slice_tag_id
1566 assert not self.api.GetSliceTags(self.slice_tag_ids)
1568 self.slice_tag_ids = []
1571 parser = OptionParser()
1572 parser.add_option("-c", "--check", action = "store_true", default = False,
1573 help = "Check most actions (default: %default)")
1574 parser.add_option("-q", "--quiet", action = "store_true", default = False,
1575 help = "Be quiet (default: %default)")
1576 parser.add_option("-p","--preserve", action="store_true", default =False,
1577 help = "Do not delete created objects")
1578 parser.add_option("-t", "--tiny", action = "store_true", default = False,
1579 help = "Run a tiny test (default: %default)")
1580 (options, args) = parser.parse_args()
1582 test = Test(api = Shell(),
1583 check = options.check,
1584 verbose = not options.quiet,
1585 preserve = options.preserve)
1590 params = Test.default
1594 if __name__ == "__main__":