fix calling convention
[plcapi.git] / Test.py
1 #!/usr/bin/env ./Shell.py
2 #
3 # Test script example
4 #
5 # Mark Huang <mlhuang@cs.princeton.edu>
6 # Copyright (C) 2006 The Trustees of Princeton University
7 #
8 # $Id$
9 #
10
11 from pprint import pprint
12 from string import letters, digits, punctuation
13 import re
14 import socket
15 import struct
16 import base64
17 import os
18
19 from random import Random
20 random = Random()
21
22 def randfloat(min = 0.0, max = 1.0):
23     return float(min) + (random.random() * (float(max) - float(min)))
24
25 def randint(min = 0, max = 1):
26     return int(randfloat(min, max + 1))
27
28 # See "2.2 Characters" in the XML specification:
29 #
30 # #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD]
31 # avoiding
32 # [#x7F-#x84], [#x86-#x9F], [#xFDD0-#xFDDF]
33
34 ascii_xml_chars = map(unichr, [0x9, 0xA, 0xD])
35 ascii_xml_chars += map(unichr, xrange(0x20, 0x7F - 1))
36 low_xml_chars = list(ascii_xml_chars)
37 low_xml_chars += map(unichr, xrange(0x84 + 1, 0x86 - 1))
38 low_xml_chars += map(unichr, xrange(0x9F + 1, 0xFF))
39 valid_xml_chars = list(low_xml_chars)
40 valid_xml_chars += map(unichr, xrange(0xFF + 1, 0xD7FF))
41 valid_xml_chars += map(unichr, xrange(0xE000, 0xFDD0 - 1))
42 valid_xml_chars += map(unichr, xrange(0xFDDF + 1, 0xFFFD))
43
44 def randstr(length, pool = valid_xml_chars, encoding = "utf-8"):
45     sample = random.sample(pool, min(length, len(pool)))
46     while True:
47         s = u''.join(sample)
48         bytes = len(s.encode(encoding))
49         if bytes > length:
50             sample.pop()
51         elif bytes < length:
52             sample += random.sample(pool, min(length - bytes, len(pool)))
53             random.shuffle(sample)
54         else:
55             break
56     return s
57
58 def randhostname():
59     # 1. Each part begins and ends with a letter or number.
60     # 2. Each part except the last can contain letters, numbers, or hyphens.
61     # 3. Each part is between 1 and 64 characters, including the trailing dot.
62     # 4. At least two parts.
63     # 5. Last part can only contain between 2 and 6 letters.
64     hostname = 'a' + randstr(61, letters + digits + '-') + '1.' + \
65                'b' + randstr(61, letters + digits + '-') + '2.' + \
66                'c' + randstr(5, letters)
67     return hostname
68
69 def randpath(length):
70     parts = []
71     for i in range(randint(1, 10)):
72         parts.append(randstr(randint(1, 30), ascii_xml_chars))
73     return os.sep.join(parts)[0:length]
74
75 def randemail():
76     return (randstr(100, letters + digits) + "@" + randhostname()).lower()
77
78 def randkey(bits = 2048):
79     key_types = ["ssh-dss", "ssh-rsa"]
80     key_type = random.sample(key_types, 1)[0]
81     return ' '.join([key_type,
82                      base64.b64encode(''.join(randstr(bits / 8).encode("utf-8"))),
83                      randemail()])
84
85 def unicmp(a, b, encoding = "utf-8"):
86     """
87     When connected directly to the DB, values are returned as raw
88     8-bit strings that may need to be decoded (as UTF-8 by default) in
89     order to compare them against expected Python Unicode strings.
90     """
91     
92     is8bit = re.compile("[\x80-\xff]").search
93     if isinstance(a, str) and is8bit(a):
94         a = unicode(a, encoding)
95     if isinstance(b, str) and is8bit(b):
96         b = unicode(b, encoding)
97     return a == b
98
99 admin = {'AuthMethod': "capability",
100          'Username': config.PLC_API_MAINTENANCE_USER,
101          'AuthString': config.PLC_API_MAINTENANCE_PASSWORD,
102          'Role': "admin"}
103
104 user = {'AuthMethod': "password",
105         'Role': "user"}
106
107 pi = {'AuthMethod': "password",
108       'Role': "pi"}
109
110 tech = {'AuthMethod': "password",
111         'Role': "tech"}
112
113 # Add sites
114 site_ids = []
115 for i in range(3):
116     def random_site():
117         return {
118             'name': randstr(254),
119             'abbreviated_name': randstr(50),
120             'login_base': randstr(20, letters).lower(),
121             'latitude': int(randfloat(-90.0, 90.0) * 1000) / 1000.0,
122             'longitude': int(randfloat(-180.0, 180.0) * 1000) / 1000.0,
123             }
124             
125     # Add site
126     site_fields = random_site()
127     print "AddSite",
128     site_id = AddSite(admin, site_fields)
129
130     # Should return a unique site_id
131     assert site_id not in site_ids
132     site_ids.append(site_id)
133     print "=>", site_id
134
135     # Check site
136     print "GetSites(%d)" % site_id,
137     site = GetSites(admin, [site_id])[0]
138     for field in site_fields:
139         assert unicmp(site[field], site_fields[field])
140     print "=> OK"
141
142     # Update site
143     site_fields = random_site()
144     # Currently cannot change login_base
145     del site_fields['login_base']
146     site_fields['max_slices'] = randint(1, 10)
147     print "UpdateSite(%d)" % site_id,
148     UpdateSite(admin, site_id, site_fields)
149     print "=> OK"
150
151     # Check site again
152     site = GetSites(admin, [site_id])[0]
153     for field in site_fields:
154         if field != 'login_base':
155             assert unicmp(site[field], site_fields[field])
156
157 print "GetSites",
158 sites = GetSites(admin, site_ids)
159 assert set(site_ids) == set([site['site_id'] for site in sites])
160 print "=>", site_ids
161
162 # Add address types
163 address_type_ids = []
164 for i in range(3):
165     def random_address_type():
166         return {
167             'name': randstr(20),
168             'description': randstr(254),
169             }
170
171     print "AddAddressType",
172     address_type_fields = random_address_type()
173     address_type_id = AddAddressType(admin, address_type_fields)
174
175     # Should return a unique address_type_id
176     assert address_type_id not in address_type_ids
177     address_type_ids.append(address_type_id)
178     print "=>", address_type_id
179
180     # Check address type
181     print "GetAddressTypes(%d)" % address_type_id,
182     address_type = GetAddressTypes(admin, [address_type_id])[0]
183     for field in 'name', 'description':
184         assert unicmp(address_type[field], address_type_fields[field])
185     print "=> OK"
186
187     # Update address type
188     address_type_fields = random_address_type()
189     print "UpdateAddressType(%d)" % address_type_id,
190     UpdateAddressType(admin, address_type_id, address_type_fields)
191     print "=> OK"
192
193     # Check address type again
194     address_type = GetAddressTypes(admin, [address_type_id])[0]
195     for field in 'name', 'description':
196         assert unicmp(address_type[field], address_type_fields[field])
197
198 print "GetAddressTypes",
199 address_types = GetAddressTypes(admin, address_type_ids)
200 assert set(address_type_ids) == set([address_type['address_type_id'] for address_type in address_types])
201 print "=>", address_type_ids
202
203 # Add site addresses
204 address_ids = []
205 for site_id in site_ids:
206     for i in range(3):
207         def random_address():
208             return {
209                 'line1': randstr(254),
210                 'line2': randstr(254),
211                 'line3': randstr(254),
212                 'city': randstr(254),
213                 'state': randstr(254),
214                 'postalcode': randstr(64),
215                 'country': randstr(128),
216                 }
217
218         print "AddSiteAddress",
219         address_fields = random_address()
220         address_id = AddSiteAddress(admin, site_id, address_fields)
221
222         # Should return a unique address_id
223         assert address_id not in address_ids
224         address_ids.append(address_id)
225         print "=>", address_id
226
227         # Check address
228         print "GetAddresses(%d)" % address_id,
229         address = GetAddresses(admin, [address_id])[0]
230         for field in address_fields:
231             assert unicmp(address[field], address_fields[field])
232         print "=> OK"
233
234         # Update address
235         address_fields = random_address()
236         print "UpdateAddress(%d)" % address_id,
237         UpdateAddress(admin, address_id, address_fields)
238         print "=> OK"
239
240         # Check address again
241         address = GetAddresses(admin, [address_id])[0]
242         for field in address_fields:
243             assert unicmp(address[field], address_fields[field])
244
245         # Add address types
246         for address_type_id in address_type_ids:
247             print "AddAddressTypeToAddress(%d, %d)" % (address_type_id, address_id),
248             AddAddressTypeToAddress(admin, address_type_id, address_id)
249             print "=> OK"
250         
251 print "GetAddresses",
252 addresses = GetAddresses(admin, address_ids)
253 assert set(address_ids) == set([address['address_id'] for address in addresses])
254 for address in addresses:
255     assert set(address_type_ids) == set(address['address_type_ids'])
256 print "=>", address_ids
257
258 print "GetRoles",
259 roles = GetRoles(admin)
260 role_ids = [role['role_id'] for role in roles]
261 roles = [role['name'] for role in roles]
262 roles = dict(zip(roles, role_ids))
263 print "=>", role_ids
264
265 print "GetKeyTypes",
266 key_types = GetKeyTypes(admin)
267 print "=>", key_types
268
269 # Add users
270 person_ids = []
271 key_ids = []
272 for auth in user, pi, tech:
273     def random_person():
274         global auth
275
276         person_fields = {
277             'first_name': randstr(128),
278             'last_name': randstr(128),
279             'email': randemail(),
280             'bio': randstr(254),
281             # Accounts are disabled by default
282             'enabled': False,
283             'password': randstr(254),
284             }
285
286         auth['Username'] = person_fields['email']
287         auth['AuthString'] = person_fields['password']
288
289         return person_fields
290
291     # Add account
292     person_fields = random_person()
293     print "AddPerson",
294     person_id = AddPerson(admin, person_fields)
295
296     # Should return a unique person_id
297     assert person_id not in person_ids
298     person_ids.append(person_id)
299     print "=>", person_id
300
301     # Check account
302     print "GetPersons(%d)" % person_id,
303     person = GetPersons(admin, [person_id])[0]
304     for field in person_fields:
305         if field != 'password':
306             assert unicmp(person[field], person_fields[field])
307     print "=> OK"
308
309     # Update account
310     person_fields = random_person()
311     print "UpdatePerson(%d)" % person_id,
312     UpdatePerson(admin, person_id, person_fields)
313     print "=> OK"
314
315     # Check account again
316     person = GetPersons(admin, [person_id])[0]
317     for field in person_fields:
318         if field != 'password':
319             assert unicmp(person[field], person_fields[field])
320
321     # Check that account is really disabled
322     try:
323         assert not AuthCheck(auth)
324     except:
325         pass
326
327     # Add role
328     role_id = roles[auth['Role']]
329     print "AddRoleToPerson(%d, %d)" % (role_id, person_id),
330     AddRoleToPerson(admin, role_id, person_id)
331     person = GetPersons(admin, [person_id])[0]
332     assert [role_id] == person['role_ids']
333     print "=> OK"
334
335     # Enable account
336     UpdatePerson(admin, person_id, {'enabled': True})
337
338     # Check authentication
339     print "AuthCheck(%s)" % auth['Username'],
340     assert AuthCheck(auth)
341     print "=> OK"
342
343     # Associate account with each site
344     for site_id in site_ids:
345         print "AddPersonToSite(%d, %d)" % (person_id, site_id),
346         AddPersonToSite(admin, person_id, site_id)
347         print "=> OK"
348
349     # Make sure it really did it
350     person = GetPersons(admin, [person_id])[0]
351     person_site_ids = person['site_ids']
352     assert set(site_ids) == set(person['site_ids'])
353
354     # First site should be the primary site
355     print "SetPersonPrimarySite(%d, %d)" % (person_id, person_site_ids[1]),
356     SetPersonPrimarySite(auth, person_id, person_site_ids[1])
357     person = GetPersons(admin, [person_id])[0]
358     assert person['site_ids'][0] == person_site_ids[1]
359     print "=> OK"
360
361     def random_key():
362         return {
363             'key_type': random.sample(key_types, 1)[0],
364             'key': randkey()
365             }
366
367     # Add keys
368     for i in range(3):
369         # Add slice attribute
370         key_fields = random_key()
371         print "AddPersonKey",
372         key_id = AddPersonKey(admin, person_id, key_fields)
373
374         # Should return a unique key_id
375         assert key_id not in key_ids
376         key_ids.append(key_id)
377         print "=>", key_id
378
379         # Check key
380         print "GetKeys(%d)" % key_id,
381         key = GetKeys(admin, [key_id])[0]
382         for field in key_fields:
383             assert unicmp(key[field], key_fields[field])
384         print "=> OK"
385
386         # Update key
387         key_fields = random_key()
388         print "UpdateKey(%d)" % key_id,
389         UpdateKey(admin, key_id, key_fields)
390         key = GetKeys(admin, [key_id])[0]
391         for field in key_fields:
392             assert unicmp(key[field], key_fields[field])
393         print "=> OK"
394
395     # Add and immediately blacklist a key
396     key_fields = random_key()
397     print "AddPersonKey",
398     key_id = AddPersonKey(admin, person_id, key_fields)
399     print "=>", key_id
400
401     print "BlacklistKey(%d)" % key_id,
402     BlacklistKey(admin, key_id)
403
404     # Is effectively deleted
405     assert not GetKeys(admin, [key_id])
406     person = GetPersons(admin, [person_id])[0]
407     assert key_id not in person['key_ids']
408
409     # Cannot be added again
410     try:
411         key_id = AddPersonKey(admin, person_id, key_fields)
412         assert False
413     except Exception, e:
414         pass
415
416     print "=> OK"
417
418 print "GetPersons",
419 persons = GetPersons(admin, person_ids)
420 assert set(person_ids) == set([person['person_id'] for person in persons])
421 print "=>", person_ids
422
423 # Add node groups
424 nodegroup_ids = []
425 for i in range(3):
426     def random_nodegroup():
427         return {
428             'name': randstr(50),
429             'description': randstr(200),
430             }
431
432     # Add node group
433     print "AddNodeGroup",
434     nodegroup_fields = random_nodegroup()
435     nodegroup_id = AddNodeGroup(admin, nodegroup_fields)
436
437     # Should return a unique nodegroup_id
438     assert nodegroup_id not in nodegroup_ids
439     nodegroup_ids.append(nodegroup_id)
440     print "=>", nodegroup_id
441
442     # Check node group
443     print "GetNodeGroups(%d)" % nodegroup_id,
444     nodegroup = GetNodeGroups(admin, [nodegroup_id])[0]
445     for field in nodegroup_fields:
446         assert unicmp(nodegroup[field], nodegroup_fields[field])
447     print "=> OK"
448
449     # Update node group, with a readable name
450     nodegroup_fields = random_nodegroup()
451     nodegroup_fields['name'] = randstr(16, letters + ' ' + digits)
452     print "UpdateNodeGroup",
453     UpdateNodeGroup(admin, nodegroup_id, nodegroup_fields)
454     print "=> OK"
455
456     # Check node group again
457     nodegroup = GetNodeGroups(admin, [nodegroup_id])[0]
458     for field in nodegroup_fields:
459         assert unicmp(nodegroup[field], nodegroup_fields[field])
460
461 print "GetNodeGroups",
462 nodegroups = GetNodeGroups(admin, nodegroup_ids)
463 assert set(nodegroup_ids) == set([nodegroup['nodegroup_id'] for nodegroup in nodegroups])
464 print "=>", nodegroup_ids
465
466 print "GetBootStates",
467 boot_states = GetBootStates(admin)
468 print "=>", boot_states
469
470 # Add nodes
471 node_ids = []
472 for site_id in site_ids:
473     for i in range(3):
474         def random_node():
475             return {
476                 'hostname': randhostname(),
477                 'boot_state': random.sample(boot_states, 1)[0],
478                 'model': randstr(255),
479                 'version': randstr(64),
480                 }
481
482         # Add node
483         node_fields = random_node()
484         print "AddNode",
485         node_id = AddNode(admin, site_id, node_fields)
486
487         # Should return a unique node_id
488         assert node_id not in node_ids
489         node_ids.append(node_id)
490         print "=>", node_id
491
492         # Check node
493         print "GetNodes(%d)" % node_id,
494         node = GetNodes(admin, [node_id])[0]
495         for field in node_fields:
496             assert unicmp(node[field], node_fields[field])
497         print "=> OK"
498
499         # Update node
500         node_fields = random_node()
501         print "UpdateNode(%d)" % node_id,
502         UpdateNode(admin, node_id, node_fields)
503         print "=> OK"
504
505         # Check node again
506         node = GetNodes(admin, [node_id])[0]
507         for field in node_fields:
508             assert unicmp(node[field], node_fields[field])
509
510         # Add to node groups
511         for nodegroup_id in nodegroup_ids:
512             print "AddNodeToNodeGroup(%d, %d)" % (node_id, nodegroup_id),
513             AddNodeToNodeGroup(admin, node_id, nodegroup_id)
514             print "=> OK"
515         
516 print "GetNodes",
517 nodes = GetNodes(admin, node_ids)
518 assert set(node_ids) == set([node['node_id'] for node in nodes])
519 print "=>", node_ids
520
521 print "GetNodeGroups",
522 nodegroups = GetNodeGroups(admin, nodegroup_ids)
523 for nodegroup in nodegroups:
524     assert set(nodegroup['node_ids']) == set(node_ids)
525 print "=> OK"
526
527 print "GetNetworkMethods",
528 network_methods = GetNetworkMethods(admin)
529 print "=>", network_methods
530
531 print "GetNetworkTypes",
532 network_types = GetNetworkTypes(admin)
533 print "=>", network_types
534
535 # Add node networks
536 nodenetwork_ids = []
537 for node_id in node_ids:
538     def random_nodenetwork(method, type):
539         nodenetwork_fields = {
540             'method': method,
541             'type': type,
542             'bwlimit': randint(500000, 10000000),
543             }
544
545         if method != 'dhcp':
546             ip = randint(0, 0xffffffff)
547             netmask = (0xffffffff << randint(2, 31)) & 0xffffffff
548             network = ip & netmask
549             broadcast = ((ip & netmask) | ~netmask) & 0xffffffff
550             gateway = randint(network + 1, broadcast - 1)
551             dns1 = randint(0, 0xffffffff)
552
553             for field in 'ip', 'netmask', 'network', 'broadcast', 'gateway', 'dns1':
554                 nodenetwork_fields[field] = socket.inet_ntoa(struct.pack('>L', locals()[field]))
555
556         return nodenetwork_fields
557
558     for method in network_methods:
559         for type in network_types:
560             # Add node network
561             print "AddNodeNetwork",
562             nodenetwork_fields = random_nodenetwork(method, type)
563             nodenetwork_id = AddNodeNetwork(admin, node_id, nodenetwork_fields)
564
565             # Should return a unique nodenetwork_id
566             assert nodenetwork_id not in nodenetwork_ids
567             nodenetwork_ids.append(nodenetwork_id)
568             print "=>", nodenetwork_id
569
570             # Check node network
571             print "GetNodeNetworks(%d)" % nodenetwork_id,
572             nodenetwork = GetNodeNetworks(admin, [nodenetwork_id])[0]
573             for field in nodenetwork_fields:
574                 assert unicmp(nodenetwork[field], nodenetwork_fields[field])
575             print "=> OK"
576
577             # Update node network
578             nodenetwork_fields = random_nodenetwork(method, type)
579             print "UpdateNodeNetwork(%d)" % nodenetwork_id,
580             UpdateNodeNetwork(admin, nodenetwork_id, nodenetwork_fields)
581             print "=> OK"
582
583             # Check node network again
584             nodenetwork = GetNodeNetworks(admin, [nodenetwork_id])[0]
585             for field in nodenetwork_fields:
586                 assert unicmp(nodenetwork[field], nodenetwork_fields[field])
587
588 print "GetNodeNetworks",
589 nodenetworks = GetNodeNetworks(admin, nodenetwork_ids)
590 assert set(nodenetwork_ids) == set([nodenetwork['nodenetwork_id'] for nodenetwork in nodenetworks])
591 print "=>", nodenetwork_ids
592
593 # Add PCUs
594 pcu_ids = []
595 for site_id in site_ids:
596     def random_pcu():
597         return {
598             'hostname': randhostname(),
599             'ip': socket.inet_ntoa(struct.pack('>L', randint(0, 0xffffffff))),
600             'protocol': randstr(16),
601             'username': randstr(254),
602             'password': randstr(254),
603             'notes': randstr(254),
604             'model': randstr(32),
605             }
606
607     # Add PCU
608     pcu_fields = random_pcu()
609     print "AddPCU",
610     pcu_id = AddPCU(admin, site_id, pcu_fields)
611
612     # Should return a unique pcu_id
613     assert pcu_id not in pcu_ids
614     pcu_ids.append(pcu_id)
615     print "=>", pcu_id
616
617     # Check PCU
618     print "GetPCUs(%d)" % pcu_id,
619     pcu = GetPCUs(admin, [pcu_id])[0]
620     for field in pcu_fields:
621         assert unicmp(pcu[field], pcu_fields[field])
622     print "=> OK"
623
624     # Update PCU
625     pcu_fields = random_pcu()
626     print "UpdatePCU(%d)" % pcu_id,
627     UpdatePCU(admin, pcu_id, pcu_fields)
628     print "=> OK"
629
630     # Check PCU again
631     pcu = GetPCUs(admin, [pcu_id])[0]
632     for field in pcu_fields:
633         assert unicmp(pcu[field], pcu_fields[field])
634
635     # Add each node at this site to a different port on this PCU
636     site = GetSites(admin, [site_id])[0]
637     port = randint(1, 10)
638     for node_id in site['node_ids']:
639         print "AddNodeToPCU(%d, %d, %d)" % (node_id, pcu_id, port),
640         AddNodeToPCU(admin, node_id, pcu_id, port)
641         print "=> OK"
642         port += 1
643
644 print "GetPCUs",
645 pcus = GetPCUs(admin, pcu_ids)
646 assert set(pcu_ids) == set([pcu['pcu_id'] for pcu in pcus])
647 print "=>", pcu_ids
648
649 # Add configuration files
650 conf_file_ids = []
651 for nodegroup_id in nodegroup_ids:
652     def random_conf_file():
653         return {
654             'enabled': bool(randint()),
655             'source': randpath(255),
656             'dest': randpath(255),
657             'file_permissions': "%#o" % randint(0, 512),
658             'file_owner': randstr(32, letters + '_' + digits),
659             'file_group': randstr(32, letters + '_' + digits),
660             'preinstall_cmd': randpath(100),
661             'postinstall_cmd': randpath(100),
662             'error_cmd': randpath(100),
663             'ignore_cmd_errors': bool(randint()),
664             'always_update': bool(randint()),
665             }
666
667     # Add configuration file
668     conf_file_fields = random_conf_file()
669     print "AddConfFile",
670     conf_file_id = AddConfFile(admin, conf_file_fields)
671
672     # Should return a unique conf_file_id
673     assert conf_file_id not in conf_file_ids
674     conf_file_ids.append(conf_file_id)
675     print "=>", conf_file_id
676
677     # Check configuration file
678     print "GetConfFiles(%d)" % conf_file_id,
679     conf_file = GetConfFiles(admin, [conf_file_id])[0]
680     for field in conf_file_fields:
681         assert unicmp(conf_file[field], conf_file_fields[field])
682     print "=> OK"
683
684     # Update configuration file
685     conf_file_fields = random_conf_file()
686     print "UpdateConfFile(%d)" % conf_file_id,
687     UpdateConfFile(admin, conf_file_id, conf_file_fields)
688     print "=> OK"
689
690     # Check configuration file
691     conf_file = GetConfFiles(admin, [conf_file_id])[0]
692     for field in conf_file_fields:
693         assert unicmp(conf_file[field], conf_file_fields[field])
694
695     # Add to all node groups
696     for nodegroup_id in nodegroup_ids:
697         print "AddConfFileToNodeGroup(%d, %d)" % (conf_file_id, nodegroup_id),
698         AddConfFileToNodeGroup(admin, conf_file_id, nodegroup_id)
699         print "=> OK"
700
701     # Add to all nodes
702     for node_id in node_ids:
703         print "AddConfFileToNode(%d, %d)" % (conf_file_id, node_id),
704         AddConfFileToNode(admin, conf_file_id, node_id)
705         print "=> OK"
706
707 print "GetConfFiles",
708 conf_files = GetConfFiles(admin, conf_file_ids)
709 assert set(conf_file_ids) == set([conf_file['conf_file_id'] for conf_file in conf_files])
710 for conf_file in conf_files:
711     assert set(nodegroup_ids) == set(conf_file['nodegroup_ids'])
712     assert set(node_ids) == set(conf_file['node_ids'])
713 print "=>", conf_file_ids
714
715 # Add slice attribute types
716 attribute_type_ids = []
717 for i in range(3):
718     def random_attribute_type():
719         return {
720             'name': randstr(100),
721             'description': randstr(254),
722             'min_role_id': random.sample(roles.values(), 1)[0],
723             }
724
725     # Add slice attribute type
726     attribute_type_fields = random_attribute_type()
727     print "AddSliceAttributeType",
728     attribute_type_id = AddSliceAttributeType(admin, attribute_type_fields)
729
730     # Should return a unique attribute_type_id
731     assert attribute_type_id not in attribute_type_ids
732     attribute_type_ids.append(attribute_type_id)
733     print "=>", attribute_type_id
734
735     # Check slice attribute type
736     print "GetSliceAttributeTypes(%d)" % attribute_type_id,
737     attribute_type = GetSliceAttributeTypes(admin, [attribute_type_id])[0]
738     for field in attribute_type_fields:
739         assert unicmp(attribute_type[field], attribute_type_fields[field])
740     print "=> OK"
741
742     # Update slice attribute type
743     attribute_type_fields = random_attribute_type()
744     print "UpdateSliceAttributeType(%d)" % attribute_type_id,
745     UpdateSliceAttributeType(admin, attribute_type_id, attribute_type_fields)
746     print "=> OK"
747
748     # Check slice attribute type again
749     attribute_type = GetSliceAttributeTypes(admin, [attribute_type_id])[0]
750     for field in attribute_type_fields:
751         assert unicmp(attribute_type[field], attribute_type_fields[field])
752
753 # Add slices and slice attributes
754 slice_ids = []
755 slice_attribute_ids = []
756 for site in sites:
757     for i in range(site['max_slices']):
758         def random_slice():
759             return {
760                 'name': site['login_base'] + "_" + randstr(11, letters).lower(),
761                 'url': "http://" + randhostname() + "/",
762                 'description': randstr(2048),
763                 }
764
765         # Add slice
766         slice_fields = random_slice()
767         print "AddSlice",
768         slice_id = AddSlice(admin, slice_fields)
769
770         # Should return a unique slice_id
771         assert slice_id not in slice_ids
772         slice_ids.append(slice_id)
773         print "=>", slice_id
774
775         # Check slice
776         print "GetSlices(%d)" % slice_id,
777         slice = GetSlices(admin, [slice_id])[0]
778         for field in slice_fields:
779             assert unicmp(slice[field], slice_fields[field])
780         print "=> OK"
781
782         # Update slice
783         slice_fields = random_slice()
784         # Cannot change slice name
785         del slice_fields['name']
786         print "UpdateSlice(%d)" % slice_id,
787         UpdateSlice(admin, slice_id, slice_fields)
788         slice = GetSlices(admin, [slice_id])[0]
789         for field in slice_fields:
790             assert unicmp(slice[field], slice_fields[field])
791         print "=> OK"
792
793         # Add slice to all nodes
794         print "AddSliceToNodes(%d, %s)" % (slice_id, str(node_ids)),
795         AddSliceToNodes(admin, slice_id, node_ids)
796         slice = GetSlices(admin, [slice_id])[0]
797         assert set(node_ids) == set(slice['node_ids'])
798         print "=> OK"
799
800         # Add users to slice
801         for person_id in person_ids:
802             print "AddPersonToSlice(%d, %d)" % (person_id, slice_id),
803             AddPersonToSlice(admin, person_id, slice_id)
804             print "=> OK" 
805         slice = GetSlices(admin, [slice_id])[0]
806         assert set(person_ids) == set(slice['person_ids'])
807
808         # Set slice/sliver attributes
809         for attribute_type_id in attribute_type_ids:
810             value = randstr(16, letters + '_' + digits)
811             # Make it a sliver attribute with 50% probability
812             node_id = random.sample(node_ids + [None] * len(node_ids), 1)[0]
813
814             # Add slice attribute
815             print "AddSliceAttribute(%d, %d)" % (slice_id, attribute_type_id),
816             if node_id is None:
817                 slice_attribute_id = AddSliceAttribute(admin, slice_id, attribute_type_id, value)
818             else:
819                 slice_attribute_id = AddSliceAttribute(admin, slice_id, attribute_type_id, value, node_id)
820
821             # Should return a unique slice_attribute_id
822             assert slice_attribute_id not in slice_attribute_ids
823             slice_attribute_ids.append(slice_attribute_id)
824             print "=>", slice_attribute_id
825
826             # Check slice attribute
827             print "GetSliceAttributes(%d)" % slice_attribute_id,
828             slice_attribute = GetSliceAttributes(admin, [slice_attribute_id])[0]
829             for field in 'attribute_type_id', 'slice_id', 'node_id', 'slice_attribute_id', 'value':
830                 assert unicmp(slice_attribute[field], locals()[field])
831             print "=> OK"
832
833             # Update slice attribute
834             value = randstr(16, letters + '_' + digits)
835             print "UpdateSliceAttribute(%d)" % slice_attribute_id,
836             UpdateSliceAttribute(admin, slice_attribute_id, value)
837             slice_attribute = GetSliceAttributes(admin, [slice_attribute_id])[0]
838             for field in 'attribute_type_id', 'slice_id', 'node_id', 'slice_attribute_id', 'value':
839                 assert unicmp(slice_attribute[field], locals()[field])
840             print "=> OK"
841
842 # Delete slices
843 for slice_id in slice_ids:
844     # Delete slice attributes
845     slice = GetSlices(admin, [slice_id])[0]
846     for slice_attribute_id in slice['slice_attribute_ids']:
847         print "DeleteSliceAttribute(%d, %d)" % (slice_id, slice_attribute_id),
848         DeleteSliceAttribute(admin, slice_attribute_id)
849         print "=> OK"
850     slice = GetSlices(admin, [slice_id])[0]
851     assert not slice['slice_attribute_ids']
852
853     # Delete users from slice
854     for person_id in person_ids:
855         print "DeletePersonFromSlice(%d, %d)" % (person_id, slice_id),
856         DeletePersonFromSlice(admin, person_id, slice_id)
857         print "=> OK"
858     slice = GetSlices(admin, [slice_id])[0]
859     assert not slice['person_ids']
860
861     # Delete nodes from slice
862     print "DeleteSliceFromNodes(%d, %s)" % (slice_id, node_ids),
863     DeleteSliceFromNodes(admin, slice_id, node_ids)
864     print "=> OK"
865     slice = GetSlices(admin, [slice_id])[0]
866     assert not slice['node_ids']
867
868     # Delete slice
869     print "DeleteSlice(%d)" % slice_id,
870     DeleteSlice(admin, slice_id)
871     assert not GetSlices(admin, [slice_id])
872
873     # Make sure it really deleted it
874     slices = GetSlices(admin, slice_ids)
875     assert slice_id not in [slice['slice_id'] for slice in slices]
876     print "=> OK"
877
878 print "GetSlices",
879 assert not GetSlices(admin, slice_ids)
880 print "=> []"
881
882 # Delete slice attribute types
883 for attribute_type_id in attribute_type_ids:
884     # Delete slice attribute type
885     print "DeleteSliceAttributeType(%d)" % attribute_type_id,
886     DeleteSliceAttributeType(admin, attribute_type_id)
887     assert not GetSliceAttributeTypes(admin, [attribute_type_id])
888
889     # Make sure it really deleted it
890     attribute_types = GetSliceAttributeTypes(admin, attribute_type_ids)
891     assert attribute_type_id not in [attribute_type['attribute_type_id'] for attribute_type in attribute_types]
892     print "=> OK"
893
894 print "GetSliceAttributeTypes",
895 assert not GetSliceAttributeTypes(admin, attribute_type_ids)
896 print "=> []"
897
898 # Delete configuration files
899 for conf_file in conf_files:
900     conf_file_id = conf_file['conf_file_id']
901
902     for node_id in conf_file['node_ids']:
903         print "DeleteConfFileFromNode(%d, %d)" % (conf_file_id, node_id),
904         DeleteConfFileFromNode(admin, conf_file_id, node_id)
905         print "=> OK"
906
907     for nodegroup_id in conf_file['nodegroup_ids']:
908         print "DeleteConfFileFromNodeGroup(%d, %d)" % (conf_file_id, nodegroup_id),
909         DeleteConfFileFromNodeGroup(admin, conf_file_id, nodegroup_id)
910         print "=> OK"
911
912     print "DeleteConfFile(%d)" % conf_file_id,
913     DeleteConfFile(admin, conf_file_id)
914     print "=> OK"
915
916 print "GetConfFiles",
917 assert not GetConfFiles(admin, conf_file_ids)
918 print "=> []"
919
920 # Delete PCUs
921 for pcu in pcus:
922     pcu_id = pcu['pcu_id']
923
924     for node_id in pcu['node_ids']:
925         print "DeleteNodeFromPCU(%d, %d)" % (node_id, pcu_id),
926         DeleteNodeFromPCU(admin, node_id, pcu_id)
927         print "=> OK"
928
929     print "DeletePCU(%d)" % pcu_id,
930     DeletePCU(admin, pcu_id)
931     print "=> OK"
932
933 print "GetPCUs",
934 assert not GetPCUs(admin, pcu_ids)
935 print "=> []"
936     
937 # Delete node networks
938 for nodenetwork_id in nodenetwork_ids:
939     print "DeleteNodeNetwork(%d)" % nodenetwork_id,
940     DeleteNodeNetwork(admin, nodenetwork_id)
941     print "=>", "OK"
942
943 print "GetNodeNetworks",
944 assert not GetNodeNetworks(admin, nodenetwork_ids)
945 print "=> []"
946
947 # Delete nodes
948 for node_id in node_ids:
949     # Remove from node groups
950     for nodegroup_id in nodegroup_ids:
951         print "DeleteNodeFromNodeGroup(%d, %d)" % (node_id, nodegroup_id),
952         DeleteNodeFromNodeGroup(admin, node_id, nodegroup_id)
953         print "=> OK"
954     node = GetNodes(admin, [node_id])[0]
955     assert not node['nodegroup_ids']
956
957     # Delete node
958     print "DeleteNode(%d)" % node_id,
959     DeleteNode(admin, node_id)
960     assert not GetNodes(admin, [node_id])
961
962     # Make sure it really deleted it
963     nodes = GetNodes(admin, node_ids)
964     assert node_id not in [node['node_id'] for node in nodes]
965     print "=> OK"
966
967 print "GetNodes",
968 assert not GetNodes(admin, node_ids)
969 print "=> []"
970
971 nodegroups = GetNodeGroups(admin, nodegroup_ids)
972 for nodegroup in nodegroups:
973     assert not set(node_ids).intersection(nodegroup['node_ids'])
974
975 # Delete users
976 for person_id in person_ids:
977     # Delete keys
978     person = GetPersons(admin, [person_id])[0]
979     for key_id in person['key_ids']:
980         print "DeleteKey(%d)" % key_id,
981         DeleteKey(admin, key_id)
982         print "=> OK"
983     person = GetPersons(admin, [person_id])[0]
984     assert not person['key_ids']
985
986     # Remove from each site
987     for site_id in site_ids:
988         print "DeletePersonFromSite(%d, %d)" % (person_id, site_id),
989         DeletePersonFromSite(admin, person_id, site_id)
990         print "=> OK"
991     person = GetPersons(admin, [person_id])[0]
992     assert not person['site_ids']
993
994     # Revoke role
995     person = GetPersons(admin, [person_id])[0]
996     for role_id in person['role_ids']:
997         print "DeleteRoleFromPerson(%d, %d)" % (role_id, person_id),
998         DeleteRoleFromPerson(admin, role_id, person_id)
999         print "=> OK"
1000     person = GetPersons(admin, [person_id])[0]
1001     assert not person['role_ids']
1002
1003     # Disable account
1004     UpdatePerson(admin, person_id, {'enabled': False})
1005     person = GetPersons(admin, [person_id])[0]
1006     assert not person['enabled']
1007
1008     # Delete account
1009     print "DeletePerson(%d)" % person_id,
1010     DeletePerson(admin, person_id)
1011     assert not GetPersons(admin, [person_id])                         
1012     print "=> OK"
1013
1014 print "GetPersons",
1015 assert not GetPersons(admin, person_ids)
1016 print "=> []"
1017
1018 # Delete node groups
1019 for nodegroup_id in nodegroup_ids:
1020     print "DeleteNodeGroup(%d)" % nodegroup_id,
1021     DeleteNodeGroup(admin, nodegroup_id)
1022     assert not GetNodeGroups(admin, [nodegroup_id])
1023     print "=> OK"
1024
1025 print "GetNodeGroups",
1026 assert not GetNodeGroups(admin, nodegroup_ids)
1027 print "=> []"
1028
1029 # Delete site addresses
1030 for address_id in address_ids:
1031     # Remove address types
1032     for address_type_id in address_type_ids:
1033         print "DeleteAddressTypeFromAddress(%d, %d)" % (address_type_id, address_id),
1034         DeleteAddressTypeFromAddress(admin, address_type_id, address_id)
1035         print "=> OK"
1036     address = GetAddresses(admin, [address_id])[0]
1037     assert not address['address_type_ids']
1038
1039     print "DeleteAddress(%d)" % address_id,
1040     DeleteAddress(admin, address_id)
1041     assert not GetAddresses(admin, [address_id])
1042     print "=> OK"
1043
1044 print "GetAddresss",
1045 assert not GetAddresses(admin, address_ids)
1046 print "=> []"
1047
1048 # Delete address types
1049 for address_type_id in address_type_ids:
1050     print "DeleteAddressType(%d)" % address_type_id,
1051     DeleteAddressType(admin, address_type_id)
1052     assert not GetAddressTypes(admin, [address_type_id])
1053     print "=> OK"
1054     
1055 print "GetAddressTypes",
1056 assert not GetAddressTypes(admin, address_type_ids)
1057 print "=> []"
1058
1059 # Delete sites
1060 for site_id in site_ids:
1061     print "DeleteSite(%d)" % site_id,
1062     DeleteSite(admin, site_id)
1063     assert not GetSites(admin, [site_id])
1064     print "=> OK"
1065
1066 print "GetSites",
1067 assert not GetSites(admin, site_ids)
1068 print "=> []"