- convert to use new API calls only
[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: Test.py,v 1.10 2006/10/16 21:57:28 mlhuang Exp $
9 #
10
11 from pprint import pprint
12 from string import letters, digits, punctuation
13 import re
14 import socket
15 import struct
16
17 from random import Random
18 random = Random()
19
20 def randfloat(min = 0.0, max = 1.0):
21     return float(min) + (random.random() * (float(max) - float(min)))
22
23 def randint(min = 0, max = 1):
24     return int(randfloat(min, max + 1))
25
26 # See "2.2 Characters" in the XML specification:
27 #
28 # #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD]
29 # avoiding
30 # [#x7F-#x84], [#x86-#x9F], [#xFDD0-#xFDDF]
31
32 low_xml_chars  = map(unichr, [0x9, 0xA, 0xD])
33 low_xml_chars += map(unichr, xrange(0x20, 0x7F - 1))
34 low_xml_chars += map(unichr, xrange(0x84 + 1, 0x86 - 1))
35 low_xml_chars += map(unichr, xrange(0x9F + 1, 0xFF))
36 valid_xml_chars  = list(low_xml_chars)
37 valid_xml_chars += map(unichr, xrange(0xFF + 1, 0xD7FF))
38 valid_xml_chars += map(unichr, xrange(0xE000, 0xFDD0 - 1))
39 valid_xml_chars += map(unichr, xrange(0xFDDF + 1, 0xFFFD))
40
41 def randstr(length, pool = valid_xml_chars, encoding = "utf-8"):
42     sample = random.sample(pool, min(length, len(pool)))
43     while True:
44         s = u''.join(sample)
45         bytes = len(s.encode(encoding))
46         if bytes > length:
47             sample.pop()
48         elif bytes < length:
49             sample += random.sample(pool, min(length - bytes, len(pool)))
50             random.shuffle(sample)
51         else:
52             break
53     return s
54
55 def randhostname():
56     # 1. Each part begins and ends with a letter or number.
57     # 2. Each part except the last can contain letters, numbers, or hyphens.
58     # 3. Each part is between 1 and 64 characters, including the trailing dot.
59     # 4. At least two parts.
60     # 5. Last part can only contain between 2 and 6 letters.
61     hostname = 'a' + randstr(61, letters + digits + '-') + '1.' + \
62                'b' + randstr(61, letters + digits + '-') + '2.' + \
63                'c' + randstr(5, letters)
64     return hostname
65
66 def unicmp(a, b, encoding = "utf-8"):
67     """
68     When connected directly to the DB, values are returned as raw
69     8-bit strings that may need to be decoded (as UTF-8 by default) in
70     order to compare them against expected Python Unicode strings.
71     """
72     
73     is8bit = re.compile("[\x80-\xff]").search
74     if isinstance(a, str) and is8bit(a):
75         a = unicode(a, encoding)
76     if isinstance(b, str) and is8bit(b):
77         b = unicode(b, encoding)
78     return a == b
79
80 admin = {'AuthMethod': "capability",
81          'Username': config.PLC_API_MAINTENANCE_USER,
82          'AuthString': config.PLC_API_MAINTENANCE_PASSWORD,
83          'Role': "admin"}
84
85 user = {'AuthMethod': "password",
86         'Role': "user"}
87
88 pi = {'AuthMethod': "password",
89       'Role': "pi"}
90
91 tech = {'AuthMethod': "password",
92         'Role': "tech"}
93
94 # Add sites
95 site_ids = []
96 for i in range(3):
97     name = randstr(254)
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
102
103     # Add site
104     print "AddSite(%s)" % login_base,
105     site_id = AddSite(admin, name, abbreviated_name, login_base,
106                       {'latitude': latitude, 'longitude': longitude})
107
108     # Should return a unique site_id
109     assert site_id not in site_ids
110     site_ids.append(site_id)
111     print "=>", site_id
112
113     # Check site
114     print "GetSites(%d)" % site_id,
115     site = GetSites(admin, [site_id])[0]
116     for key in 'name', 'abbreviated_name', 'login_base', 'latitude', 'longitude', 'site_id':
117         assert unicmp(site[key], locals()[key])
118     print "=> OK"
119
120     # Update site
121     name = randstr(254)
122     abbreviated_name = randstr(50)
123     latitude = int(randfloat(-90.0, 90.0) * 1000) / 1000.0
124     longitude = int(randfloat(-180.0, 180.0) * 1000) / 1000.0
125     max_slices = 10
126     print "UpdateSite(%s)" % login_base,
127     UpdateSite(admin, site_id, {'name': name, 'abbreviated_name': abbreviated_name,
128                                 'latitude': latitude, 'longitude': longitude,
129                                 'max_slices': max_slices})
130     site = GetSites(admin, [site_id])[0]
131     for key in 'name', 'abbreviated_name', 'latitude', 'longitude', 'max_slices':
132         assert unicmp(site[key], locals()[key])
133     print "=> OK"
134
135 print "GetSites",
136 sites = GetSites(admin, site_ids)
137 assert set(site_ids) == set([site['site_id'] for site in sites])
138 print "=>", site_ids
139
140 print "GetRoles",
141 roles = GetRoles(admin)
142 role_ids = [role['role_id'] for role in roles]
143 roles = [role['name'] for role in roles]
144 roles = dict(zip(roles, role_ids))
145 print "=>", role_ids
146
147 # Add users
148 person_ids = []
149 for auth in user, pi, tech:
150     first_name = randstr(128)
151     last_name = randstr(128)
152     # 119 + 1 + 64 + 64 + 6 = 254
153     email = (randstr(119, letters + digits) + "@" + randhostname()).lower()
154     bio = randstr(254)
155     # Accounts are disabled by default
156     enabled = False
157
158     auth['Username'] = email
159     auth['AuthString'] = randstr(254)
160
161     # Add account
162     print "AddPerson(%s)" % email,
163     person_id = AddPerson(admin, first_name, last_name,
164                           {'email': email, 'bio': bio,
165                            'password': auth['AuthString']})
166
167     # Should return a unique person_id
168     assert person_id not in person_ids
169     person_ids.append(person_id)
170     print "=>", person_id
171
172     # Check account
173     print "GetPersons(%d)" % person_id,
174     person = GetPersons(admin, [person_id])[0]
175     for key in 'first_name', 'last_name', 'email', 'bio', 'person_id', 'enabled':
176         assert unicmp(person[key], locals()[key])
177     print "=> OK"
178
179     # Update account
180     first_name = randstr(128)
181     last_name = randstr(128)
182     bio = randstr(254)
183     print "UpdatePerson(%d)" % person_id,
184     UpdatePerson(admin, person_id, {'first_name': first_name,
185                                     'last_name': last_name,
186                                     'bio': bio})
187     print "=> OK"
188
189     # Check account again
190     person = GetPersons(admin, [person_id])[0]
191     for key in 'first_name', 'last_name', 'email', 'bio':
192         assert unicmp(person[key], locals()[key])
193
194     # Check that account is really disabled
195     try:
196         assert not AuthCheck(auth)
197     except:
198         pass
199
200     # Add role
201     role_id = roles[auth['Role']]
202     print "AddRoleToPerson(%d, %d)" % (role_id, person_id),
203     AddRoleToPerson(admin, role_id, person_id)
204     person = GetPersons(admin, [person_id])[0]
205     assert [role_id] == person['role_ids']
206     print "=> OK"
207
208     # Enable account
209     UpdatePerson(admin, person_id, {'enabled': True})
210
211     # Check authentication
212     print "AuthCheck(%s)" % auth['Username'],
213     assert AuthCheck(auth)
214     print "=> OK"
215
216     # Associate account with each site
217     for site_id in site_ids:
218         print "AddPersonToSite(%d, %d)" % (person_id, site_id),
219         AddPersonToSite(admin, person_id, site_id)
220         print "=> OK"
221
222     # Make sure it really did it
223     person = GetPersons(admin, [person_id])[0]
224     person_site_ids = person['site_ids']
225     assert set(site_ids) == set(person['site_ids'])
226
227     # First site should be the primary site
228     print "SetPersonPrimarySite(%d, %d)" % (person_id, person_site_ids[1]),
229     SetPersonPrimarySite(auth, person_id, person_site_ids[1])
230     person = GetPersons(admin, [person_id])[0]
231     assert person['site_ids'][0] == person_site_ids[1]
232     print "=> OK"
233
234 print "GetPersons",
235 persons = GetPersons(admin, person_ids)
236 assert set(person_ids) == set([person['person_id'] for person in persons])
237 print "=>", person_ids
238
239 # Add node groups
240 nodegroup_ids = []
241 for i in range(3):
242     name = randstr(50)
243     description = randstr(200)
244
245     # Add node group
246     print "AddNodeGroup",
247     nodegroup_id = AddNodeGroup(admin, name, {'description': description})
248
249     # Should return a unique nodegroup_id
250     assert nodegroup_id not in nodegroup_ids
251     nodegroup_ids.append(nodegroup_id)
252     print "=>", nodegroup_id
253
254     # Check node group
255     print "GetNodeGroups(%d)" % nodegroup_id,
256     nodegroup = GetNodeGroups(admin, [nodegroup_id])[0]
257     for key in 'name', 'description', 'nodegroup_id':
258         assert unicmp(nodegroup[key], locals()[key])
259     print "=> OK"
260
261     # Update node group
262     name = randstr(16, letters + ' ' + digits)
263     description = randstr(200)
264     print "UpdateNodeGroup",
265     UpdateNodeGroup(admin, nodegroup_id, {'name': name, 'description': description})
266     print "=> OK"
267
268     # Check node group again
269     nodegroup = GetNodeGroups(admin, [nodegroup_id])[0]
270     for key in 'name', 'description', 'nodegroup_id':
271         assert unicmp(nodegroup[key], locals()[key])
272
273 print "GetNodeGroups",
274 nodegroups = GetNodeGroups(admin, nodegroup_ids)
275 assert set(nodegroup_ids) == set([nodegroup['nodegroup_id'] for nodegroup in nodegroups])
276 print "=>", nodegroup_ids
277
278 # Add nodes
279 node_ids = []
280 for site_id in site_ids:
281     for i in range(3):
282         hostname = randhostname()
283         boot_state = 'inst'
284         model = randstr(255)
285
286         # Add node
287         print "AddNode(%s)" % hostname,
288         node_id = AddNode(admin, site_id, hostname,
289                           {'boot_state': boot_state, 'model': model})
290
291         # Should return a unique node_id
292         assert node_id not in node_ids
293         node_ids.append(node_id)
294         print "=>", node_id
295
296         # Check node
297         print "GetNodes(%d)" % node_id,
298         node = GetNodes(admin, [node_id])[0]
299         for key in 'hostname', 'boot_state', 'model', 'node_id':
300             assert unicmp(node[key], locals()[key])
301         print "=> OK"
302
303         # Update node
304         hostname = randhostname()
305         model = randstr(255)
306         print "UpdateNode(%d)" % node_id,
307         UpdateNode(admin, node_id, {'hostname': hostname, 'model': model})
308         print "=> OK"
309
310         # Check node again
311         node = GetNodes(admin, [node_id])[0]
312         for key in 'hostname', 'boot_state', 'model', 'node_id':
313             assert unicmp(node[key], locals()[key])
314
315         # Add to node groups
316         for nodegroup_id in nodegroup_ids:
317             print "AddNodeToNodeGroup(%d, %d)" % (nodegroup_id, node_id),
318             AddNodeToNodeGroup(admin, nodegroup_id, node_id)
319             print "=> OK"
320         
321 print "GetNodes",
322 nodes = GetNodes(admin, node_ids)
323 assert set(node_ids) == set([node['node_id'] for node in nodes])
324 print "=>", node_ids
325
326 print "GetNodeGroups",
327 nodegroups = GetNodeGroups(admin, nodegroup_ids)
328 for nodegroup in nodegroups:
329     assert set(nodegroup['node_ids']) == set(node_ids)
330 print "=> OK"
331
332 # Add node networks
333 nodenetwork_ids = []
334 for node_id in node_ids:
335     ip = randint(0, 0xffffffff)
336     netmask = (0xffffffff << randint(2, 31)) & 0xffffffff
337     network = ip & netmask
338     broadcast = ((ip & netmask) | ~netmask) & 0xffffffff
339     gateway = randint(network + 1, broadcast - 1)
340     dns1 = randint(0, 0xffffffff)
341     bwlimit = randint(500000, 10000000)
342
343     for method in 'static', 'dhcp':
344         optional = {'bwlimit': bwlimit}
345         if method == 'static':
346             for key in 'ip', 'netmask', 'network', 'broadcast', 'gateway', 'dns1':
347                 optional[key] = socket.inet_ntoa(struct.pack('>L', locals()[key]))
348
349         # Add node network
350         print "AddNodeNetwork(%s)" % method,
351         nodenetwork_id = AddNodeNetwork(admin, node_id, method, 'ipv4', optional)
352
353         # Should return a unique nodenetwork_id
354         assert nodenetwork_id not in nodenetwork_ids
355         nodenetwork_ids.append(nodenetwork_id)
356         print "=>", nodenetwork_id
357
358         # Check node network
359         print "GetNodeNetworks(%d)" % nodenetwork_id,
360         nodenetwork = GetNodeNetworks(admin, [nodenetwork_id])[0]
361         if method == 'static':
362             for key in 'ip', 'netmask', 'network', 'broadcast', 'gateway', 'dns1':
363                 address = struct.unpack('>L', socket.inet_aton(nodenetwork[key]))[0]
364                 assert address == locals()[key]
365         print "=> OK"
366
367         # Update node network
368         optional = {'bwlimit': bwlimit}
369         if nodenetwork['method'] == 'static':
370             for key in 'ip', 'netmask', 'network', 'broadcast', 'gateway', 'dns1':
371                 optional[key] = socket.inet_ntoa(struct.pack('>L', locals()[key]))
372
373         print "UpdateNodeNetwork(%d)" % nodenetwork_id,
374         UpdateNodeNetwork(admin, nodenetwork['nodenetwork_id'], optional)
375         print "=> OK"
376
377         # Check node network again
378         nodenetwork = GetNodeNetworks(admin, [nodenetwork_id])[0]
379         if nodenetwork['method'] == 'static':
380             for key in 'ip', 'netmask', 'network', 'broadcast', 'gateway', 'dns1':
381                 address = struct.unpack('>L', socket.inet_aton(nodenetwork[key]))[0]
382                 assert address == locals()[key]
383
384 print "GetNodeNetworks",
385 nodenetworks = GetNodeNetworks(admin, nodenetwork_ids)
386 assert set(nodenetwork_ids) == set([nodenetwork['nodenetwork_id'] for nodenetwork in nodenetworks])
387 print "=>", nodenetwork_ids
388
389 # Add slice attribute types
390 attribute_type_ids = []
391 for i in range(3):
392     name = randstr(100)
393     description = randstr(254)
394     min_role_id = random.sample(roles.values(), 1)[0]
395
396     # Add slice attribute type
397     print "AddSliceAttributeType",
398     attribute_type_id = AddSliceAttributeType(admin, name,
399                                          {'description': description,
400                                           'min_role_id': min_role_id})
401
402     # Should return a unique attribute_type_id
403     assert attribute_type_id not in attribute_type_ids
404     attribute_type_ids.append(attribute_type_id)
405     print "=>", attribute_type_id
406
407     # Check slice attribute type
408     print "GetSliceAttributeTypes(%d)" % attribute_type_id,
409     attribute_type = GetSliceAttributeTypes(admin, [attribute_type_id])[0]
410     for key in 'name', 'min_role_id', 'description':
411         assert unicmp(attribute_type[key], locals()[key])
412     print "=> OK"
413
414     # Update slice attribute type
415     name = "attribute_" + randstr(10, letters + '_')
416     description = randstr(254)
417     min_role_id = random.sample(roles.values(), 1)[0]
418     print "UpdateSliceAttributeType(%d)" % attribute_type_id,
419     UpdateSliceAttributeType(admin, attribute_type_id,
420                              {'name': name,
421                               'description': description,
422                               'min_role_id': min_role_id})
423     attribute_type = GetSliceAttributeTypes(admin, [attribute_type_id])[0]
424     for key in 'name', 'min_role_id', 'description':
425         assert unicmp(attribute_type[key], locals()[key])
426     print "=> OK"
427
428 # Add slices and slice attributes
429 slice_ids = []
430 slice_attribute_ids = []
431 for site in sites:
432     for i in range(10):
433         name = site['login_base'] + "_" + randstr(11, letters).lower()
434         url = "http://" + randhostname() + "/"
435         description = randstr(2048)
436
437         # Add slice
438         print "AddSlice(%s)" % name,
439         slice_id = AddSlice(admin, name, {'url': url, 'description': description})
440
441         # Should return a unique slice_id
442         assert slice_id not in slice_ids
443         slice_ids.append(slice_id)
444         print "=>", slice_id
445
446         # Check slice
447         print "GetSlices(%d)" % slice_id,
448         slice = GetSlices(admin, [slice_id])[0]
449         for key in 'name', 'url', 'description', 'slice_id':
450             assert unicmp(slice[key], locals()[key])
451         print "=> OK"
452
453         # Update slice
454         url = "http://" + randhostname() + "/"
455         description = randstr(2048)
456         print "UpdateSlice(%d)" % slice_id,
457         UpdateSlice(admin, slice_id, {'url': url, 'description': description})
458         slice = GetSlices(admin, [slice_id])[0]
459         for key in 'name', 'url', 'description', 'slice_id':
460             assert unicmp(slice[key], locals()[key])
461         print "=> OK"
462
463         # Add slice to all nodes
464         print "AddSliceToNodes(%d, %s)" % (slice_id, str(node_ids)),
465         AddSliceToNodes(admin, name, node_ids)
466         slice = GetSlices(admin, [slice_id])[0]
467         assert set(node_ids) == set(slice['node_ids'])
468         print "=> OK"
469
470         # Add users to slice
471         for person_id in person_ids:
472             print "AddPersonToSlice(%d, %d)" % (person_id, slice_id),
473             AddPersonToSlice(admin, person_id, slice_id)
474             print "=> OK" 
475         slice = GetSlices(admin, [slice_id])[0]
476         assert set(person_ids) == set(slice['person_ids'])
477
478         # Set slice/sliver attributes
479         for attribute_type_id in attribute_type_ids:
480             value = randstr(16, letters + '_' + digits)
481             # Make it a sliver attribute with 50% probability
482             node_id = random.sample(node_ids + [None] * len(node_ids), 1)[0]
483
484             # Add slice attribute
485             print "AddSliceAttribute(%d, %d)" % (slice_id, attribute_type_id),
486             if node_id is None:
487                 slice_attribute_id = AddSliceAttribute(admin, slice_id, attribute_type_id, value)
488             else:
489                 slice_attribute_id = AddSliceAttribute(admin, slice_id, attribute_type_id, value, node_id)
490
491             # Should return a unique slice_attribute_id
492             assert slice_attribute_id not in slice_attribute_ids
493             slice_attribute_ids.append(slice_attribute_id)
494             print "=>", slice_attribute_id
495
496             # Check slice attribute
497             print "GetSliceAttributes(%d)" % slice_attribute_id,
498             slice_attribute = GetSliceAttributes(admin, [slice_attribute_id])[0]
499             for key in 'attribute_type_id', 'slice_id', 'node_id', 'slice_attribute_id', 'value':
500                 assert unicmp(slice_attribute[key], locals()[key])
501             print "=> OK"
502
503             # Update slice attribute
504             url = "http://" + randhostname() + "/"
505             description = randstr(2048)
506             print "UpdateSliceAttribute(%d)" % slice_attribute_id,
507             UpdateSliceAttribute(admin, slice_attribute_id, value)
508             slice_attribute = GetSliceAttributes(admin, [slice_attribute_id])[0]
509             for key in 'attribute_type_id', 'slice_id', 'node_id', 'slice_attribute_id', 'value':
510                 assert unicmp(slice_attribute[key], locals()[key])
511             print "=> OK"
512
513 # Delete slices
514 for slice_id in slice_ids:
515     # Delete slice attributes
516     slice = GetSlices(admin, [slice_id])[0]
517     for slice_attribute_id in slice['slice_attribute_ids']:
518         print "DeleteSliceAttribute(%d, %d)" % (slice_id, slice_attribute_id),
519         DeleteSliceAttribute(admin, slice_attribute_id)
520         print "=> OK"
521     slice = GetSlices(admin, [slice_id])[0]
522     assert not slice['slice_attribute_ids']
523
524     # Delete users from slice
525     for person_id in person_ids:
526         print "DeletePersonFromSlice(%d, %d)" % (person_id, slice_id),
527         DeletePersonFromSlice(admin, person_id, slice_id)
528         print "=> OK"
529     slice = GetSlices(admin, [slice_id])[0]
530     assert not slice['person_ids']
531
532     # Delete nodes from slice
533     print "DeleteSliceFromNodes(%d, %s)" % (slice_id, node_ids),
534     DeleteSliceFromNodes(admin, slice_id, node_ids)
535     print "=> OK"
536     slice = GetSlices(admin, [slice_id])[0]
537     assert not slice['node_ids']
538
539     # Delete slice
540     print "DeleteSlice(%d)" % slice_id,
541     DeleteSlice(admin, slice_id)
542     assert not GetSlices(admin, [slice_id])
543
544     # Make sure it really deleted it
545     slices = GetSlices(admin, slice_ids)
546     assert slice_id not in [slice['slice_id'] for slice in slices]
547     print "=> OK"
548
549 print "GetSlices",
550 assert not GetSlices(admin, slice_ids)
551 print "=> []"
552
553 # Delete slice attribute types
554 for attribute_type_id in attribute_type_ids:
555     # Delete slice attribute type
556     print "DeleteSliceAttributeType(%d)" % attribute_type_id,
557     DeleteSliceAttributeType(admin, attribute_type_id)
558     assert not GetSliceAttributeTypes(admin, [attribute_type_id])
559
560     # Make sure it really deleted it
561     attribute_types = GetSliceAttributeTypes(admin, attribute_type_ids)
562     assert attribute_type_id not in [attribute_type['attribute_type_id'] for attribute_type in attribute_types]
563     print "=> OK"
564
565 print "GetSliceAttributeTypes",
566 assert not GetSliceAttributeTypes(admin, attribute_type_ids)
567 print "=> []"
568
569 # Delete node networks
570 for nodenetwork_id in nodenetwork_ids:
571     print "DeleteNodeNetwork(%d)" % nodenetwork_id,
572     DeleteNodeNetwork(admin, nodenetwork_id)
573     print "=>", "OK"
574
575 print "GetNodeNetworks",
576 assert not GetNodeNetworks(admin, nodenetwork_ids)
577 print "=> []"
578
579 # Delete nodes
580 for node_id in node_ids:
581     # Remove from node groups
582     for nodegroup_id in nodegroup_ids:
583         print "DeleteNodeFromNodeGroup(%d, %d)" % (nodegroup_id, node_id),
584         DeleteNodeFromNodeGroup(admin, nodegroup_id, node_id)
585         print "=> OK"
586     node = GetNodes(admin, [node_id])[0]
587     assert not node['nodegroup_ids']
588
589     # Delete node
590     print "DeleteNode(%d)" % node_id,
591     DeleteNode(admin, node_id)
592     assert not GetNodes(admin, [node_id])
593
594     # Make sure it really deleted it
595     nodes = GetNodes(admin, node_ids)
596     assert node_id not in [node['node_id'] for node in nodes]
597     print "=> OK"
598
599 print "GetNodes",
600 assert not GetNodes(admin, node_ids)
601 print "=> []"
602
603 nodegroups = GetNodeGroups(admin, nodegroup_ids)
604 for nodegroup in nodegroups:
605     assert not set(node_ids).intersection(nodegroup['node_ids'])
606
607 # Delete users
608 for person_id in person_ids:
609     # Remove from each site
610     for site_id in site_ids:
611         print "DeletePersonFromSite(%d, %d)" % (person_id, site_id),
612         DeletePersonFromSite(admin, person_id, site_id)
613         print "=> OK"
614     person = GetPersons(admin, [person_id])[0]
615     assert not person['site_ids']
616
617     # Revoke role
618     person = GetPersons(admin, [person_id])[0]
619     for role_id in person['role_ids']:
620         print "DeleteRoleFromPerson(%d, %d)" % (role_id, person_id),
621         DeleteRoleFromPerson(admin, role_id, person_id)
622         print "=> OK"
623     person = GetPersons(admin, [person_id])[0]
624     assert not person['role_ids']
625
626     # Disable account
627     UpdatePerson(admin, person_id, {'enabled': False})
628     person = GetPersons(admin, [person_id])[0]
629     assert not person['enabled']
630
631     # Delete account
632     print "DeletePerson(%d)" % person_id,
633     DeletePerson(admin, person_id)
634     assert not GetPersons(admin, [person_id])                         
635     print "=> OK"
636
637 print "GetPersons",
638 assert not GetPersons(admin, person_ids)
639 print "=> []"
640
641 # Delete node groups
642 for nodegroup_id in nodegroup_ids:
643     print "DeleteNodeGroup(%d)" % nodegroup_id,
644     DeleteNodeGroup(admin, nodegroup_id)
645     assert not GetNodeGroups(admin, [nodegroup_id])
646     print "=> OK"
647
648 print "GetNodeGroups",
649 assert not GetNodeGroups(admin, nodegroup_ids)
650 print "=> []"
651
652 # Delete sites
653 for site_id in site_ids:
654     print "DeleteSite(%d)" % site_id,
655     DeleteSite(admin, site_id)
656     assert not GetSites(admin, [site_id])
657     print "=> OK"
658
659 print "GetSites",
660 assert not GetSites(admin, site_ids)
661 print "=> []"