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)
930 # for testing node arch
931 check=node_fields.copy()
932 columns=node_fields.keys()
933 for tagname in tag_fields:
935 columns.remove(tagname)
937 node = self.api.GetNodes([node_id],columns)[0]
938 if dict(node) != check:
939 raise Exception,'Unexpected result in GetNodes() %r vs %r'%(node,check)
941 print 'WARNING: skipping updatenode with tags as this is not implemented yet'
942 # # again when fetching 'arch' explicitly
943 # node = self.api.GetNodes([node_id],columns+tag_fields)[0]
944 # if dict(node) != node_fields:
945 # raise Exception,"Unexpected result in GetNodes() with tags %r vs %r"%(node,node_fields)
947 # Add to a random set of node groups
948 nodegroup_ids = random.sample(self.nodegroup_ids, randint(0, len(self.nodegroup_ids)))
949 for nodegroup_id in (set(nodegroup_ids) - set(node['nodegroup_ids'])):
950 nodegroup = self.api.GetNodeGroups([nodegroup_id])[0]
951 tagname = nodegroup['tagname']
952 node_tags = self.api.GetNodeTags({'node_id':node_id,'tagname':tagname})
954 self.api.AddNodeTag(node_id,tagname,'yes')
956 node_tag=node_tags[0]
957 self.api.UpdateNodeTag(node_tag['node_tag_id'],'yes')
958 for nodegroup_id in (set(node['nodegroup_ids']) - set(nodegroup_ids)):
959 nodegroup = self.api.GetNodeGroups([nodegroup_id])[0]
960 tagname = nodegroup['tagname']
961 node_tags = self.api.GetNodeTags({'node_id':node_id,'tagname':tagname})
963 self.api.AddNodeTag(node_id,tagname,'no')
965 node_tag=node_tags[0]
966 self.api.UpdateNodeTag(node_tag['node_tag_id'],'no')
970 node = self.api.GetNodes([node_id])[0]
971 for field in node_fields:
972 assert node[field] == node_fields[field]
973 assert set(nodegroup_ids) == set(node['nodegroup_ids'])
976 print "Updated node", node_id
978 def DeleteNodes(self):
980 Delete any random nodes we may have added.
983 for node_id in self.node_ids:
984 # Remove from node groups
985 node = self.api.GetNodes([node_id])[0]
986 for node_tag in GetNodeTags ( {'node_id': node_id} ):
987 self.api.UpdateNodeTag(node_tag['node_tag_id'],'')
990 node = self.api.GetNodes([node_id])[0]
991 assert not node['nodegroup_ids']
993 self.api.DeleteNode(node_id)
996 assert not self.api.GetNodes([node_id])
999 print "Deleted node", node_id
1002 assert not self.api.GetNodes(self.node_ids)
1006 def AddInterfaces(self, per_node = 1):
1008 Add a number of random network interfaces to each node.
1011 network_methods = self.api.GetNetworkMethods()
1012 if not network_methods:
1013 raise Exception, "No network methods"
1015 network_types = self.api.GetNetworkTypes()
1016 if not network_types:
1017 raise Exception, "No network types"
1019 for node_id in self.node_ids:
1020 for i in range(per_node):
1021 method = random.sample(network_methods, 1)[0]
1022 type = random.sample(network_types, 1)[0]
1025 interface_fields = random_interface(method, type)
1026 interface_id = self.api.AddInterface(node_id, interface_fields)
1028 # Should return a unique interface_id
1029 assert interface_id not in self.interface_ids
1030 self.interface_ids.append(interface_id)
1034 interface = self.api.GetInterfaces([interface_id])[0]
1035 for field in interface_fields:
1036 assert interface[field] == interface_fields[field]
1039 print "Added interface", interface_id, "to node", node_id
1041 def UpdateInterfaces(self):
1043 Make random changes to any network interfaces we may have added.
1046 network_methods = self.api.GetNetworkMethods()
1047 if not network_methods:
1048 raise Exception, "No network methods"
1050 network_types = self.api.GetNetworkTypes()
1051 if not network_types:
1052 raise Exception, "No network types"
1054 for interface_id in self.interface_ids:
1055 method = random.sample(network_methods, 1)[0]
1056 type = random.sample(network_types, 1)[0]
1059 interface_fields = random_interface(method, type)
1060 self.api.UpdateInterface(interface_id, interface_fields)
1064 interface = self.api.GetInterfaces([interface_id])[0]
1065 for field in interface_fields:
1066 assert interface[field] == interface_fields[field]
1069 print "Updated interface", interface_id
1071 def DeleteInterfaces(self):
1073 Delete any random network interfaces we may have added.
1076 for interface_id in self.interface_ids:
1077 self.api.DeleteInterface(interface_id)
1080 assert not self.api.GetInterfaces([interface_id])
1083 print "Deleted interface", interface_id
1086 assert not self.api.GetInterfaces(self.interface_ids)
1088 self.interface_ids = []
1090 def AddIlinks (self, n):
1092 Add random links between interfaces.
1096 src = random.sample(self.interface_ids,1)[0]
1097 dst = random.sample(self.interface_ids,1)[0]
1098 ilink_id = self.api.AddIlink (src,dst,
1099 self.ilink_type_ids[i],
1102 assert ilink_id not in self.ilink_ids
1103 self.ilink_ids.append(ilink_id)
1106 print 'Added Ilink',ilink_id,' - attached interface',src,'to',dst
1109 retrieve=GetIlinks({'src_interface_id':src,'dst_interface_id':dst,
1110 'tag_type_id':self.ilink_type_ids[i]})
1111 assert ilink_id==retrieve[0]['ilink_id']
1114 def UpdateIlinks (self):
1116 for ilink_id in self.ilink_ids:
1117 new_value=random_ilink()
1118 self.api.UpdateIlink(ilink_id,new_value)
1121 ilink=self.api.GetIlinks([ilink_id])[0]
1122 assert ilink['value'] == new_value
1125 print 'Updated Ilink',ilink_id
1127 def DeleteIlinks (self):
1128 for ilink_id in self.ilink_ids:
1129 self.api.DeleteIlink(ilink_id)
1132 assert not self.api.GetIlinks({'ilink_id':ilink_id})
1135 print 'Deleted Ilink',ilink_id
1138 assert not self.api.GetIlinks(self.ilink_ids)
1143 def AddPCUs(self, per_site = 1):
1145 Add a number of random PCUs to each site. Each node at the
1146 site will be added to a port on the PCU if AddNodes() was
1150 for site_id in self.site_ids:
1151 for i in range(per_site):
1153 pcu_fields = random_pcu()
1154 pcu_id = self.api.AddPCU(site_id, pcu_fields)
1156 # Should return a unique pcu_id
1157 assert pcu_id not in self.pcu_ids
1158 self.pcu_ids.append(pcu_id)
1160 # Add each node at this site to a different port on this PCU
1161 site = self.api.GetSites([site_id])[0]
1162 port = randint(1, 10)
1163 for node_id in site['node_ids']:
1164 self.api.AddNodeToPCU(node_id, pcu_id, port)
1169 pcu = self.api.GetPCUs([pcu_id])[0]
1170 for field in pcu_fields:
1171 assert pcu[field] == pcu_fields[field]
1174 print "Added PCU", pcu_id, "to site", site_id
1176 def UpdatePCUs(self):
1178 Make random changes to any PCUs we may have added.
1181 for pcu_id in self.pcu_ids:
1183 pcu_fields = random_pcu()
1184 self.api.UpdatePCU(pcu_id, pcu_fields)
1188 pcu = self.api.GetPCUs([pcu_id])[0]
1189 for field in pcu_fields:
1190 assert pcu[field] == pcu_fields[field]
1193 print "Updated PCU", pcu_id
1195 def DeletePCUs(self):
1197 Delete any random nodes we may have added.
1200 for pcu_id in self.pcu_ids:
1201 # Remove nodes from PCU
1202 pcu = self.api.GetPCUs([pcu_id])[0]
1203 for node_id in pcu['node_ids']:
1204 self.api.DeleteNodeFromPCU(node_id, pcu_id)
1207 pcu = self.api.GetPCUs([pcu_id])[0]
1208 assert not pcu['node_ids']
1210 self.api.DeletePCU(pcu_id)
1213 assert not self.api.GetPCUs([pcu_id])
1216 print "Deleted PCU", pcu_id
1219 assert not self.api.GetPCUs(self.pcu_ids)
1223 def AddConfFiles(self, n = 10):
1225 Add a number of random global configuration files.
1231 # Add a random configuration file
1232 conf_files.append(random_conf_file())
1235 # Add a nodegroup override file
1236 nodegroup_conf_file = conf_files[0].copy()
1237 nodegroup_conf_file['source'] = randpath(255)
1238 conf_files.append(nodegroup_conf_file)
1240 # Add a node override file
1241 node_conf_file = conf_files[0].copy()
1242 node_conf_file['source'] = randpath(255)
1243 conf_files.append(node_conf_file)
1245 for conf_file_fields in conf_files:
1246 conf_file_id = self.api.AddConfFile(conf_file_fields)
1248 # Should return a unique conf_file_id
1249 assert conf_file_id not in self.conf_file_ids
1250 self.conf_file_ids.append(conf_file_id)
1253 if conf_file_fields == nodegroup_conf_file and self.nodegroup_ids:
1254 nodegroup_id = random.sample(self.nodegroup_ids, 1)[0]
1255 self.api.AddConfFileToNodeGroup(conf_file_id, nodegroup_id)
1260 if conf_file_fields == node_conf_file and self.node_ids:
1261 node_id = random.sample(self.node_ids, 1)[0]
1262 self.api.AddConfFileToNode(conf_file_id, node_id)
1267 # Check configuration file
1268 conf_file = self.api.GetConfFiles([conf_file_id])[0]
1269 for field in conf_file_fields:
1270 assert conf_file[field] == conf_file_fields[field]
1273 print "Added configuration file", conf_file_id,
1274 if nodegroup_id is not None:
1275 print "to node group", nodegroup_id,
1276 elif node_id is not None:
1277 print "to node", node_id,
1280 def UpdateConfFiles(self):
1282 Make random changes to any configuration files we may have added.
1285 for conf_file_id in self.conf_file_ids:
1286 # Update configuration file
1287 conf_file_fields = random_conf_file()
1288 # Do not update dest so that it remains an override if set
1289 if 'dest' in conf_file_fields:
1290 del conf_file_fields['dest']
1291 self.api.UpdateConfFile(conf_file_id, conf_file_fields)
1294 # Check configuration file
1295 conf_file = self.api.GetConfFiles([conf_file_id])[0]
1296 for field in conf_file_fields:
1297 assert conf_file[field] == conf_file_fields[field]
1300 print "Updated configuration file", conf_file_id
1302 def DeleteConfFiles(self):
1304 Delete any random configuration files we may have added.
1307 for conf_file_id in self.conf_file_ids:
1308 self.api.DeleteConfFile(conf_file_id)
1311 assert not self.api.GetConfFiles([conf_file_id])
1314 print "Deleted configuration file", conf_file_id
1317 assert not self.api.GetConfFiles(self.conf_file_ids)
1319 self.conf_file_ids = []
1321 def AddTagTypes(self,n_sa,n_ng,n_il):
1323 Add as many tag types as there are nodegroups,
1324 will use tagvalue=yes for each nodegroup
1327 roles = self.api.GetRoles()
1329 raise Exception, "No roles"
1330 role_ids = [role['role_id'] for role in roles]
1332 for i in range (n_sa + n_ng + n_il):
1333 tag_type_fields = random_tag_type (role_ids)
1334 tag_type_id = self.api.AddTagType (tag_type_fields)
1336 assert tag_type_id not in \
1337 self.slice_type_ids + \
1338 self.nodegroup_type_ids + \
1342 self.slice_type_ids.append(tag_type_id)
1343 elif i < n_sa+n_ng :
1344 self.nodegroup_type_ids.append(tag_type_id)
1346 self.ilink_type_ids.append(tag_type_id)
1349 tag_type = self.api.GetTagTypes([tag_type_id])[0]
1350 for field in tag_type_fields:
1351 assert tag_type[field] == tag_type_fields[field]
1353 print "Updated slice attribute type", tag_type_id
1355 def UpdateTagTypes(self):
1357 Make random changes to any slice attribute types we may have added.
1360 roles = self.api.GetRoles()
1362 raise Exception, "No roles"
1363 role_ids = [role['role_id'] for role in roles]
1365 for tag_type_id in self.slice_type_ids + self.nodegroup_type_ids + self.ilink_type_ids:
1366 # Update slice attribute type
1367 tag_type_fields = random_tag_type(role_ids)
1368 self.api.UpdateTagType(tag_type_id, tag_type_fields)
1371 # Check slice attribute type
1372 tag_type = self.api.GetTagTypes([tag_type_id])[0]
1373 for field in tag_type_fields:
1374 assert tag_type[field] == tag_type_fields[field]
1376 print "Updated slice attribute type", tag_type_id
1378 def DeleteTagTypes(self):
1380 Delete any random slice attribute types we may have added.
1383 for tag_type_id in self.slice_type_ids + self.nodegroup_type_ids + self.ilink_type_ids:
1384 self.api.DeleteTagType(tag_type_id)
1387 assert not self.api.GetTagTypes([tag_type_id])
1390 print "Deleted slice attribute type", tag_type_id
1393 assert not self.api.GetTagTypes(self.slice_type_ids+self.nodegroup_type_ids+self.ilink_type_ids)
1395 self.slice_type_ids = []
1396 self.nodegroup_type_ids = []
1398 def AddSlices(self, per_site = 10):
1400 Add a number of random slices per site.
1403 for site in self.api.GetSites(self.site_ids):
1404 for i in range(min(per_site, site['max_slices'])):
1406 slice_fields = random_slice(site['login_base'])
1407 slice_id = self.api.AddSlice(slice_fields)
1409 # Should return a unique slice_id
1410 assert slice_id not in self.slice_ids
1411 self.slice_ids.append(slice_id)
1413 # Add slice to a random set of nodes
1414 node_ids = random.sample(self.node_ids, randint(0, len(self.node_ids)))
1416 self.api.AddSliceToNodes(slice_id, node_ids)
1418 # Add random set of site users to slice
1419 person_ids = random.sample(site['person_ids'], randint(0, len(site['person_ids'])))
1420 for person_id in person_ids:
1421 self.api.AddPersonToSlice(person_id, slice_id)
1425 slice = self.api.GetSlices([slice_id])[0]
1426 for field in slice_fields:
1427 assert slice[field] == slice_fields[field]
1429 assert set(node_ids) == set(slice['node_ids'])
1430 assert set(person_ids) == set(slice['person_ids'])
1433 print "Added slice", slice_id, "to site", site['site_id'],
1435 print "and nodes", node_ids,
1438 print "Added users", site['person_ids'], "to slice", slice_id
1440 def UpdateSlices(self):
1442 Make random changes to any slices we may have added.
1445 for slice_id in self.slice_ids:
1447 slice_fields = random_slice("unused")
1448 # Cannot change slice name
1449 if 'name' in slice_fields:
1450 del slice_fields['name']
1451 self.api.UpdateSlice(slice_id, slice_fields)
1453 slice = self.api.GetSlices([slice_id])[0]
1455 # Add slice to a random set of nodes
1456 node_ids = random.sample(self.node_ids, randint(0, len(self.node_ids)))
1457 self.api.AddSliceToNodes(slice_id, list(set(node_ids) - set(slice['node_ids'])))
1458 self.api.DeleteSliceFromNodes(slice_id, list(set(slice['node_ids']) - set(node_ids)))
1460 # Add random set of users to slice
1461 person_ids = random.sample(self.person_ids, randint(0, len(self.person_ids)))
1462 for person_id in (set(person_ids) - set(slice['person_ids'])):
1463 self.api.AddPersonToSlice(person_id, slice_id)
1464 for person_id in (set(slice['person_ids']) - set(person_ids)):
1465 self.api.DeletePersonFromSlice(person_id, slice_id)
1468 slice = self.api.GetSlices([slice_id])[0]
1469 for field in slice_fields:
1470 assert slice[field] == slice_fields[field]
1471 assert set(node_ids) == set(slice['node_ids'])
1472 assert set(person_ids) == set(slice['person_ids'])
1475 print "Updated slice", slice_id
1476 print "Added nodes", node_ids, "to slice", slice_id
1477 print "Added persons", person_ids, "to slice", slice_id
1479 def DeleteSlices(self):
1481 Delete any random slices we may have added.
1484 for slice_id in self.slice_ids:
1485 self.api.DeleteSlice(slice_id)
1488 assert not self.api.GetSlices([slice_id])
1491 print "Deleted slice", slice_id
1494 assert not self.api.GetSlices(self.slice_ids)
1498 def AddSliceTags(self, per_slice = 2):
1500 Add a number of random slices per site.
1503 if not self.slice_type_ids:
1506 for slice_id in self.slice_ids:
1507 slice = self.api.GetSlices([slice_id])[0]
1509 for i in range(per_slice):
1510 # Set a random slice/sliver attribute
1511 for tag_type_id in random.sample(self.slice_type_ids, 1):
1512 value = randstr(16, letters + '_' + digits)
1513 # Make it a sliver attribute with 50% probability
1514 if slice['node_ids']:
1515 node_id = random.sample(slice['node_ids'] + [None] * len(slice['node_ids']), 1)[0]
1519 # Add slice attribute
1521 slice_tag_id = self.api.AddSliceTag(slice_id, tag_type_id, value)
1523 slice_tag_id = self.api.AddSliceTag(slice_id, tag_type_id, value, node_id)
1525 # Should return a unique slice_tag_id
1526 assert slice_tag_id not in self.slice_tag_ids
1527 self.slice_tag_ids.append(slice_tag_id)
1530 # Check slice attribute
1531 slice_tag = self.api.GetSliceTags([slice_tag_id])[0]
1532 for field in 'tag_type_id', 'slice_id', 'node_id', 'slice_tag_id', 'value':
1533 assert slice_tag[field] == locals()[field]
1536 print "Added slice attribute", slice_tag_id, "of type", tag_type_id,
1537 if node_id is not None:
1538 print "to node", node_id,
1541 def UpdateSliceTags(self):
1543 Make random changes to any slice attributes we may have added.
1546 for slice_tag_id in self.slice_tag_ids:
1547 # Update slice attribute
1548 value = randstr(16, letters + '_' + digits)
1549 self.api.UpdateSliceTag(slice_tag_id, value)
1551 # Check slice attribute again
1552 slice_tag = self.api.GetSliceTags([slice_tag_id])[0]
1553 assert slice_tag['value'] == value
1556 print "Updated slice attribute", slice_tag_id
1558 def DeleteSliceTags(self):
1560 Delete any random slice attributes we may have added.
1563 for slice_tag_id in self.slice_tag_ids:
1564 self.api.DeleteSliceTag(slice_tag_id)
1567 assert not self.api.GetSliceTags([slice_tag_id])
1570 print "Deleted slice attribute", slice_tag_id
1573 assert not self.api.GetSliceTags(self.slice_tag_ids)
1575 self.slice_tag_ids = []
1578 parser = OptionParser()
1579 parser.add_option("-c", "--check", action = "store_true", default = False,
1580 help = "Check most actions (default: %default)")
1581 parser.add_option("-q", "--quiet", action = "store_true", default = False,
1582 help = "Be quiet (default: %default)")
1583 parser.add_option("-p","--preserve", action="store_true", default =False,
1584 help = "Do not delete created objects")
1585 parser.add_option("-t", "--tiny", action = "store_true", default = False,
1586 help = "Run a tiny test (default: %default)")
1587 (options, args) = parser.parse_args()
1589 test = Test(api = Shell(),
1590 check = options.check,
1591 verbose = not options.quiet,
1592 preserve = options.preserve)
1597 params = Test.default
1601 if __name__ == "__main__":