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 node = self.api.GetNodes([node_id])[0]
931 # Add to a random set of node groups
932 nodegroup_ids = random.sample(self.nodegroup_ids, randint(0, len(self.nodegroup_ids)))
933 for nodegroup_id in (set(nodegroup_ids) - set(node['nodegroup_ids'])):
934 nodegroup = self.api.GetNodeGroups([nodegroup_id])[0]
935 tagname = nodegroup['tagname']
936 node_tags = self.api.GetNodeTags({'node_id':node_id,'tagname':tagname})
938 self.api.AddNodeTag(node_id,tagname,'yes')
940 node_tag=node_tags[0]
941 self.api.UpdateNodeTag(node_tag['node_tag_id'],'yes')
942 for nodegroup_id in (set(node['nodegroup_ids']) - set(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,'no')
949 node_tag=node_tags[0]
950 self.api.UpdateNodeTag(node_tag['node_tag_id'],'no')
954 node = self.api.GetNodes([node_id])[0]
955 for field in node_fields:
956 if field not in tag_fields:
957 if node[field] != node_fields[field]:
958 raise Exception, "Unexpected field %s in node after GetNodes()"%field
959 assert set(nodegroup_ids) == set(node['nodegroup_ids'])
961 print 'WARNING: skipping updatenode with tags as this is not implemented yet'
962 # again when fetching 'arch' explicitly
963 node2 = self.api.GetNodes([node_id],node_fields.keys())[0]
964 for field in node_fields:
965 if node2[field] != node_fields[field]:
966 raise Exception, "Unexpected field %s in node after GetNodes(tags)"%field
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__":