various changes in the test suite
[plcapi.git] / TestPeers.py
1 #!/usr/bin/env python
2 ###
3 ##############################
4 ###
5 ### preparation / requirements
6 ###
7 ### two separate instances of myplc
8 ### for now they are located on the same box on lurch
9 ###
10 ### expectations :
11 ### your myplcs should more or less come out of the box, 
12 ### I prefer not to alter the default PLC_ROOT_USER value,
13 ### instead we create a PI account on the site_id=1
14 ###
15 ##############################
16
17 ### xxx todo
18 # check sites
19 # check persons
20
21 # support reloading without wiping everything off
22 # dunno how to do (defvar plc)
23
24 import getopt
25 import sys
26 import time
27
28 import Shell
29 import PLC.Methods
30
31 # when running locally, we might wish to run only our local stuff
32 dummy_print_methods = [ 'RefreshPeer' ]
33 class DummyShell:
34     class Callable:
35         def __init__(self,method,index):
36             self.method=method
37             self.index=index
38             self.printed=False
39         def __call__ (self, *args, **kwds):
40             if not self.printed or self.method in dummy_print_methods:
41                 print "Dummy method %s on remote peer %d skipped"%(self.method,self.index)
42                 self.printed=True
43             return 0
44     def __init__(self,index):
45         self.index=index
46     def init(self):
47         for method in PLC.Methods.methods:
48             # ignore path-defined methods for now
49             if "." not in method:
50                 setattr(self,method,DummyShell.Callable(method,self.index))
51     def show_config(self,*args):
52         print 'DummyShell'
53         
54 ####################
55 import xmlrpclib
56 import os
57
58 ## try to support reload
59 try:
60     globals()['plc']
61 except:
62     plc=[None,None,None]
63 try:
64     globals()['s']
65 except:
66     s=[None,None,None]
67     
68 ####################
69 # predefined stuff
70 # number of 'system' persons
71 # builtin maint, local root, 2 persons for the peering
72 system_persons = 4
73 # among that, 1 gets refreshed - other ones have conflicting names
74 system_persons_cross = 1
75
76 system_slices_ids = (1,2)
77 def system_slices ():
78     return len(system_slices_ids)
79 def total_slices ():
80     return number_slices+system_slices()
81
82 # temporary - the myplc I use doesnt know about 'system' yet
83 def system_slivers ():
84 #    return len(system_slices_ids)
85     return 0
86 # too tedious to do the maths : how many slices attached to node 1
87 expected_slivers=None
88 def total_slivers ():
89     global expected_slivers
90     if expected_slivers is None:
91         expected_slivers=0
92         actual_nodes_per_slice = min (number_nodes,number_nodes_per_slice)
93         for ns in myrange(number_slices):
94             slice_range = [ map_on_node (n+ns) for n in range(actual_nodes_per_slice)]
95             if 1 in slice_range:
96                 expected_slivers += 1
97     return expected_slivers+system_slivers()
98
99 ####################
100 # set initial conditions
101 # actual persons_per_slice is min(number_persons,number_persons_per_slice)
102 # actual nodes_per_slice is min(number_nodes,number_nodes_per_slice)
103 # this is to prevent quadractic test times on big tests
104 def define_test (sites,persons,nodes,slices,
105                  keys_per_person,nodes_per_slice,persons_per_slice,fast_mode=None):
106     global number_sites, number_persons, number_nodes, number_slices
107     global number_keys_per_person, number_nodes_per_slice, number_persons_per_slice, fast_flag
108     number_sites = sites
109     number_persons=persons
110     number_nodes=nodes
111     number_slices=slices
112     number_keys_per_person=keys_per_person
113     number_nodes_per_slice=nodes_per_slice
114     number_persons_per_slice=persons_per_slice
115     if fast_mode is not None:
116         fast_flag=fast_mode
117
118 # when we run locally on a given peer
119 local_peer=None
120
121 def show_test():
122     print '%d sites, %d persons, %d nodes & %d slices'%(
123         number_sites,number_persons,number_nodes,number_slices)
124     print '%d keys/person, %d nodes/slice & %d persons/slice'%(
125         number_keys_per_person,number_nodes_per_slice,number_persons_per_slice)
126     print 'fast_flag',fast_flag
127     if local_peer is not None:
128         print 'Running locally on index %d'%local_peer
129
130 def mini():
131     define_test(1,1,1,1,1,1,1,True)
132     
133 def normal():
134     define_test (sites=4,persons=4,nodes=5,slices=4,
135                  keys_per_person=2,nodes_per_slice=3,persons_per_slice=6,fast_mode=False)
136
137 def apply_factor (factor):
138     global number_sites, number_persons, number_nodes, number_slices
139     [number_sites, number_persons, number_nodes, number_slices] = \
140                    [factor*x for x in     [number_sites, number_persons, number_nodes, number_slices]]
141                                                                    
142
143 # use only 1 key in this case
144 big_factor=4
145 def big():
146     global number_sites, number_persons, number_nodes, number_slices
147     number_sites=200
148     number_persons=500
149     number_nodes=350
150     number_slices=500
151     global nodes_per_slice
152     nodes_per_slice=3
153     global number_keys_per_person
154     number_keys_per_person=1
155     global number_persons_per_slice
156     number_persons_per_slice=3
157
158 #huge_factor=1000
159 def huge():
160     global number_sites, number_persons, number_nodes, number_slices
161     number_sites=1000
162     number_persons=2000
163     number_nodes=3000
164     number_slices=2000
165     global nodes_per_slice
166     nodes_per_slice=3
167     global number_keys_per_person
168     number_keys_per_person=1
169     global number_persons_per_slice
170     number_persons_per_slice=3
171
172 # use mini test by default in interactive mode
173 mini()
174 #normal()
175
176 ####################
177 # argh, for login_name that doesn't accept digits
178 plain_numbers=['zero','one','two','three','four','five','six','seven','eight','nine','ten',
179                'eleven','twelve','thirteen','fourteen','fifteen','sixteen','seventeen','eighteen','nineteen','twenty']
180 plain_digits=['a','b','c','d','e','f','g','h','i','j']
181 ####################
182 plc[1]={ 'plcname':'plc1 in federation',
183          'hostname':'lurch.cs.princeton.edu',
184          'url-format':'https://%s:443/PLCAPI/',
185          'builtin-admin-id':'root@plc1.org',
186          'builtin-admin-password':'root',
187          'peer-admin-name':'peer1@planet-lab.org',
188          'peer-admin-password':'peer',
189          'node-format':'n1-%03d.plc1.org',
190          'plainname' : 'one',
191          'site-format':'one%s',
192          'person-format' : 'user1-%d@plc1.org',
193          'key-format':'ssh-rsa 11key4plc11 user%d-key%d',
194          'person-password' : 'password1',
195        }
196 plc[2]={ 'plcname':'plc2 in federation',
197          'hostname':'planetlab-devbox.inria.fr',
198          'url-format':'https://%s:443/PLCAPI/',
199          'builtin-admin-id':'root@plc2.org',
200          'builtin-admin-password':'root',
201          'peer-admin-name':'peer2@planet-lab.org',
202          'peer-admin-password':'peer',
203          'node-format':'n2-%03d.plc2.org',
204          'plainname' : 'two',
205          'site-format':'two%s',
206          'person-format' : 'user2-%d@plc2.org',
207          'key-format':'ssh-rsa 22key4plc22 user%d-key%d',
208          'person-password' : 'password2',
209        }
210
211 ####################
212 def peer_index(i):
213     return 3-i
214
215 def plc_name (i):
216     return plc[i]['plcname']
217
218 def site_name (i,n):
219     x=site_login_base(i,n)
220     return 'Site fullname '+x
221
222 def site_login_base (i,n):
223     # for huge
224     if number_sites<len(plain_numbers):
225         return plc[i]['site-format']%plain_numbers[n]
226     else:
227         string=''
228         while True:
229             quo=n/10
230             rem=n%10
231             string=plain_digits[rem]+string
232             if quo == 0:
233                 break
234             else:
235                 n=quo
236         return plc[i]['site-format']%string
237
238 def person_name (i,n):
239     return plc[i]['person-format']%n
240
241 def key_name (i,n,k):
242     return plc[i]['key-format']%(n,k)
243
244 def node_name (i,n):
245     return plc[i]['node-format']%n
246
247 def slice_name (i,n):
248     site_index=map_on_site(n)
249     return "%s_slice%d"%(site_login_base(i,site_index),n)
250
251 def sat_name (i):
252     return 'sat_%d'%i
253
254 # to have indexes start at 1
255 def map_on (n,max):
256     result=(n%max)
257     if result==0:
258         result=max
259     return result
260
261 def myrange (n):
262     return range (1,n+1,1)
263
264 def map_on_site (n):
265     return map_on (n,number_sites)
266
267 def map_on_person (n):
268     return map_on (n,number_persons)
269
270 def map_on_node (n):
271     return map_on (n,number_nodes)
272
273 def message (*args):
274     print "====================",
275     print args
276     
277 ##########
278 def timer_start ():
279     global epoch,last_time
280     epoch = time.time()
281     last_time=epoch
282     print '+++ timer start'
283
284 def timer_show ():
285     global last_time
286     now=time.time()
287     print '+++ %.02f seconds ellapsed (%.02f)'%(now-epoch,now-last_time)
288     last_time=now
289
290 ####################
291 def test00_init (args=[1,2]):
292     timer_start()
293     ## have you loaded this file already (support for reload)
294     for i in args:
295         url=plc[i]['url-format']%plc[i]['hostname']
296         plc[i]['url']=url
297         if local_peer is None:
298             # the regular remote mode
299             argv=[sys.argv[0],
300                   # xxx todo - Shell.py still needs a non-empty config even if we define everything
301                   '--config','dummy-config',
302                   '--url',url,
303                   '--user',plc[i]['builtin-admin-id'],
304                   '--password',plc[i]['builtin-admin-password']]
305             print 'initializing s[%d]=>%s'%(i,url)
306             s[i]=Shell.Shell(argv)
307             s[i].init()
308         elif local_peer == i:
309             # local mode - use Shell's Direct mode - use /etc/planetlab/plc_config
310             s[i]=Shell.Shell([sys.argv[0]])
311             s[i].init()
312         else:
313             # remote peer in local mode : use dummy shell instead
314             s[i]=DummyShell(i)
315             s[i].init()
316
317 def test00_print (args=[1,2]):
318     for i in args:
319         print '==================== s[%d]'%i
320         s[i].show_config()
321     print '===================='
322
323 def check_nodes (el,ef,args=[1,2]):
324     for i in args:
325         # use a single request and sort afterwards for efficiency
326         # could have used GetNodes's scope as well
327         all_nodes = s[i].GetNodes()
328         n = len ([ x for x in all_nodes if x['peer_id'] is None])
329         f = len ([ x for x in all_nodes if x['peer_id'] is not None])
330         print '%02d: Checking nodes: got %d local (e=%d) & %d foreign (e=%d)'%(i,n,el,f,ef)
331         assert n==el
332         assert f==ef
333
334 def check_keys (el,ef,args=[1,2]):
335     for i in args:
336         # use a single request and sort afterwards for efficiency
337         # could have used GetKeys's scope as well
338         all_keys = s[i].GetKeys()
339         n = len ([ x for x in all_keys if x['peer_id'] is None])
340         f = len ([ x for x in all_keys if x['peer_id'] is not None])
341         print '%02d: Checking keys: got %d local (e=%d) & %d foreign (e=%d)'%(i,n,el,f,ef)
342         assert n==el
343         assert f==ef
344
345 def check_persons (el,ef,args=[1,2]):
346     for i in args:
347         # use a single request and sort afterwards for efficiency
348         # could have used GetPersons's scope as well
349         all_persons = s[i].GetPersons()
350         n = len ([ x for x in all_persons if x['peer_id'] is None])
351         f = len ([ x for x in all_persons if x['peer_id'] is not None])
352         print '%02d: Checking persons: got %d local (e=%d) & %d foreign (e=%d)'%(i,n,el,f,ef)
353         assert n==el
354         assert f==ef
355
356 # expected : local slices, foreign slices
357 def check_slices (els,efs,args=[1,2]):
358     for i in args:
359         ls=len(s[i].GetSlices({'peer_id':None}))
360         fs=len(s[i].GetSlices({'~peer_id':None}))
361         print '%02d: Checking slices: got %d local (e=%d) & %d foreign (e=%d)'%(i,ls,els,fs,efs)
362         assert els==ls
363         assert efs==fs
364
365 def show_nodes (i,node_ids):
366     # same as above
367     all_nodes = s[i].GetNodes(node_ids)
368     loc_nodes = filter (lambda n: n['peer_id'] is None, all_nodes)
369     for_nodes = filter (lambda n: n['peer_id'] is not None, all_nodes)
370
371     for message,nodes in [ ['LOC',loc_nodes], ['FOR',for_nodes] ] :
372         if nodes:
373             print '[%s:%d] : '%(message,len(nodes)),
374             for node in nodes:
375                 print node['hostname']+' ',
376             print ''
377
378 def check_slice_nodes (expected_nodes, is_local_slice, args=[1,2]):
379     for ns in myrange(number_slices):
380         check_slice_nodes_n (ns,expected_nodes, is_local_slice, args)
381
382 def check_slice_nodes_n (ns,expected_nodes, is_local_slice, args=[1,2]):
383     for i in args:
384         peer=peer_index(i)
385         if is_local_slice:
386             sname=slice_name(i,ns)
387             slice=s[i].GetSlices({'name':[sname],'peer_id':None})[0]
388             message='local'
389         else:
390             sname=slice_name(peer,ns)
391             slice=s[i].GetSlices({'name':[sname],'~peer_id':None})[0]
392             message='foreign'
393         print '%02d: %s slice %s (e=%d) '%(i,message,sname,expected_nodes),
394         slice_node_ids=slice['node_ids']
395         print 'on nodes ',slice_node_ids
396         show_nodes (i,slice_node_ids)
397         assert len(slice_node_ids)>=expected_nodes
398         if len(slice_node_ids) != expected_nodes:
399             print 'TEMPORARY'
400
401 # expected : nodes on local slice
402 def check_local_slice_nodes (expected, args=[1,2]):
403     check_slice_nodes(expected,True,args)
404
405 # expected : nodes on foreign slice
406 def check_foreign_slice_nodes (expected, args=[1,2]):
407     check_slice_nodes(expected,False,args)
408
409 def check_conf_files (args=[1,2]):
410     for nn in myrange(number_nodes):
411         check_conf_files_n (nn,args)
412
413 def check_conf_files_n (nn,args=[1,2]):
414     for i in args:
415         nodename=node_name(i,nn)
416         ndict= s[i].GetSlivers([nodename])[0]
417         assert ndict['hostname'] == nodename
418         conf_files = ndict['conf_files']
419         print '%02d: %d conf_files in GetSlivers for node %s'%(i,len(conf_files),nodename)
420         for conf_file in conf_files:
421             print 'source=',conf_file['source'],'|',
422             print 'dest=',conf_file['dest'],'|',
423             print 'enabled=',conf_file['enabled'],'|',
424             print ''
425
426 import pprint
427 pp = pprint.PrettyPrinter(indent=3)
428
429 def check_slivers (esn,args=[1,2]):
430     for nn in myrange(number_nodes):
431         check_slivers_n (nn,esn,args)
432
433 # too verbose to check all nodes, let's check only the first one
434 def check_slivers_1 (esn,args=[1,2]):
435     check_slivers_n (1,esn,args)
436
437 def check_slivers_n (nn,esn,args=[1,2]):
438     for i in args:
439         nodename=node_name(i,nn)
440         ndict= s[i].GetSlivers([nodename])[0]
441         assert ndict['hostname'] == nodename
442         slivers = ndict['slivers']
443         print '%02d: %d slivers (exp. %d) in GetSlivers for node %s'\
444               %(i,len(slivers),esn,nodename)
445         for sliver in slivers:
446             print '>>slivername = ',sliver['name']
447             pretty_printer.pprint(sliver)
448         assert len(slivers) == esn
449                 
450
451 ####################
452 def test00_admin_person (args=[1,2]):
453     global plc
454     for i in args:
455         email = plc[i]['peer-admin-name']
456         try:
457             p=s[i].GetPersons([email])[0]
458             plc[i]['peer-admin-id']=p['person_id']
459         except:
460             person_id=s[i].AddPerson({'first_name':'Local', 
461                                       'last_name':'PeerPoint', 
462                                       'role_ids':[10],
463                                       'email':email,
464                                       'password':plc[i]['peer-admin-password']})
465             if person_id:
466                 print '%02d:== created peer admin account %d, %s - %s'%(
467                     i, person_id,plc[i]['peer-admin-name'],plc[i]['peer-admin-password'])
468             plc[i]['peer-admin-id']=person_id
469
470 def test00_admin_enable (args=[1,2]):
471     for i in args:
472         if s[i].AdmSetPersonEnabled(plc[i]['peer-admin-id'],True):
473             s[i].AddRoleToPerson('admin',plc[i]['peer-admin-id'])
474             print '%02d:== enabled+admin on account %d:%s'%(i,plc[i]['peer-admin-id'],plc[i]['peer-admin-name'])
475
476 def test00_peer_person (args=[1,2]):
477     global plc
478     for i in args:
479         peer=peer_index(i)
480         email=plc[peer]['peer-admin-name']
481         try:
482             p=s[i].GetPersons([email])[0]
483             plc[i]['peer_person_id']=p['person_id']
484         except:
485             person_id = s[i].AddPerson ( {'first_name':'Peering(plain passwd)', 'last_name':plc_name(peer), 'role_ids':[3000],
486                                                'email':email,'password':plc[peer]['peer-admin-password']})
487             if person_id:
488                 print '%02d:== Created person %d as the peer person'%(i,person_id)
489             plc[i]['peer_person_id']=person_id
490
491 ####################
492 def test00_peer (args=[1,2]):
493     global plc
494     for i in args:
495         peer=peer_index(i)
496         peername = plc_name(peer)
497         try:
498             p=s[i].GetPeers ( [peername])[0]
499             plc[i]['peer_id']=p['peer_id']
500         except:
501             peer_id=s[i].AddPeer ( {'peername':peername,'peer_url':plc[peer]['url'],'person_id':plc[i]['peer_person_id']})
502             # NOTE : need to manually reset the encrypted password through SQL at this point
503             if peer_id:
504                 print '%02d:Created peer %d'%(i,peer_id)
505                 print "PLEASE manually set password for person_id=%d in DB%d"%(plc[i]['peer_person_id'],i)
506             plc[i]['peer_id']=peer_id
507
508 def test00_peer_passwd (args=[1,2]):
509     if local_peer is None:
510         for i in args:
511             # using an ad-hoc local command for now - never could get quotes to reach sql....
512             print "Attempting to remotely set passwd for person_id=%d in DB%d"%(plc[i]['peer_person_id'],i),
513             retcod=os.system("ssh root@%s new_plc_api/person-password.sh %d"%(plc[i]['hostname'],plc[i]['peer_person_id']))
514             print '-> system returns',retcod
515     else:
516         i=local_peer
517         print "Locally setting passwd for person_id=%d in DB%d"%(plc[i]['peer_person_id'],i),
518         retcod=os.system("./person-password.sh -l %d"%(plc[i]['peer_person_id']))
519         print '-> system returns',retcod
520     
521 # this one gets cached 
522 def get_peer_id (i):
523     try:
524         return plc[i]['peer_id']
525     except:
526         peername = plc_name (peer_index(i))
527         peer_id = s[i].GetPeers([peername])[0]['peer_id']
528         plc[i]['peer_id'] = peer_id
529         return peer_id
530
531 ##############################
532 def test00_refresh (message,args=[1,2]):
533     print '=== refresh',message
534     timer_show()
535     for i in args:
536         print '%02d:== Refreshing peer'%(i),
537         retcod=s[i].RefreshPeer(get_peer_id(i))
538         keys=retcod.keys()
539         keys.sort()
540         print "Result: {",
541         for key in keys:
542             if "time" not in key:
543                 print key,retcod[key],
544         print "}"
545         print "+++ ellapsed: {",
546         timers=retcod['timers']
547         keys=timers.keys()
548         keys.sort()
549         for key in keys:
550             print key,timers[key],
551         print "}"
552         timer_show()
553
554 ####################
555 def test01_site (args=[1,2]):
556     for ns in myrange(number_sites):
557         test01_site_n (ns,True,args)
558
559 def test01_del_site (args=[1,2]):
560     for ns in myrange(number_sites):
561         test01_site_n (ns,False,args)
562
563 def test01_site_n (ns,add_if_true,args=[1,2]):
564     for i in args:
565         login_base = site_login_base (i,ns)
566         try:
567             site_id = s[i].GetSites([login_base])[0]['site_id']
568             if not add_if_true:
569                 if s[i].DeleteSite(site_id):
570                     print "%02d:== deleted site_id %d"%(i,site_id)
571         except:
572             if add_if_true:
573                 sitename=site_name(i,ns)
574                 abbrev_name="abbr"+str(i)
575                 max_slices = number_slices
576                 site_id=s[i].AddSite ( {'name':plc_name(i),
577                                         'abbreviated_name': abbrev_name,
578                                         'login_base': login_base,
579                                         'is_public': True,
580                                         'url': 'http://%s.com/'%abbrev_name,
581                                         'max_slices':max_slices})
582                 ### max_slices does not seem taken into account at that stage
583                 if site_id:
584                     s[i].UpdateSite(site_id,{'max_slices':max_slices})
585                     print '%02d:== Created site %d with max_slices=%d'%(i,site_id,max_slices)
586
587 ####################
588 def test02_person (args=[1,2]):
589     for np in myrange(number_persons):
590         test02_person_n (np,True,args)
591
592 def test02_del_person (args=[1,2]):
593     for np in myrange(number_persons):
594         test02_person_n (np,False,args)
595
596 def test02_person_n (np,add_if_true,args=[1,2]):
597     test02_person_n_ks (np, myrange(number_keys_per_person),add_if_true,args)
598
599 def test02_person_n_ks (np,nks,add_if_true,args=[1,2]):
600     for i in args:
601         email = person_name(i,np)
602         try:
603             person_id=s[i].GetPersons([email])[0]['person_id']
604             if not add_if_true:
605                 if s[i].DeletePerson(person_id):
606                     print "%02d:== deleted person_id %d"%(i,person_id)
607         except:
608             if add_if_true:
609                 password = plc[i]['person-password']
610                 person_id=s[i].AddPerson({'first_name':'Your average', 
611                                                'last_name':'User%d'%np, 
612                                                'role_ids':[30],
613                                                'email':email,
614                                                'password': password })
615                 if person_id:
616                     print '%02d:== created user account %d, %s - %s'%(i, person_id,email,password)
617                     for nk in nks:
618                         key=key_name(i,np,nk)
619                         s[i].AddPersonKey(email,{'key_type':'ssh', 'key':key})
620                         print '%02d:== added key %s to person %s'%(i,key,email)
621
622 ####################
623 # retrieves node_id from hostname - checks for local nodes only
624 def get_local_node_id(i,nodename):
625     return s[i].GetNodes({'hostname':nodename,'peer_id':None})[0]['node_id']
626
627 # clean all local nodes - foreign nodes are not supposed to be cleaned up manually
628 def clean_all_nodes (args=[1,2]):
629     for i in args:
630         print '%02d:== Cleaning all nodes'%i
631         local_nodes = s[i].GetNodes({'peer_id':None})
632         if local_nodes:
633             for node in local_nodes:
634                 print '%02d:==== Cleaning node %d'%(i,node['node_id'])
635                 s[i].DeleteNode(node['node_id'])
636
637 def test03_node (args=[1,2]):
638     for nn in myrange(number_nodes):
639         test03_node_n (nn,args)
640
641 def test03_node_n (nn,args=[1,2]):
642     for i in args:
643         nodename = node_name(i,nn)
644         try:
645             get_local_node_id(i,nodename)
646         except:
647             login_base=site_login_base(i,map_on_site(nn))
648             n=s[i].AddNode(login_base,{'hostname': nodename})
649             if n:
650                 print '%02d:== Added node %d %s'%(i,n,node_name(i,nn))
651
652 def test02_delnode (args=[1,2]):
653     for nn in myrange(number_nodes):
654         test02_delnode_n (nn,args)
655
656 def test02_delnode_n (nn,args=[1,2]):
657     for i in args:
658         nodename = node_name(i,nn)
659         node_id = get_local_node_id (i,nodename)
660         retcod=s[i].DeleteNode(nodename)
661         if retcod:
662             print '%02d:== Deleted node %d, returns %s'%(i,node_id,retcod)
663
664 ####################
665 def clean_all_slices (args=[1,2]):
666     for i in args:
667         print '%02d:== Cleaning all slices'%i
668         for slice in s[i].GetSlices({'peer_id':None}):
669             slice_id = slice['slice_id']
670             if slice_id not in system_slices_ids:
671                 if s[i].DeleteSlice(slice_id):
672                     print '%02d:==== Cleaned slice %d'%(i,slice_id)
673
674 def test04_slice (args=[1,2]):
675     for n in myrange(number_slices):
676         test04_slice_n (n,args)
677
678 def test04_slice_n (ns,args=[1,2]):
679     for i in args:
680         peer=peer_index(i)
681         plcname=plc_name(i)
682         slicename=slice_name(i,ns)
683         max_nodes=number_nodes
684         try:
685             s[i].GetSlices([slicename])[0]
686         except:
687             slice_id=s[i].AddSlice ({'name':slicename,
688                                      'description':'slice %s on %s'%(slicename,plcname),
689                                      'url':'http://planet-lab.org/%s'%slicename,
690                                      'max_nodes':max_nodes,
691                                      'instanciation':'plc-instantiated',
692                                      })
693             if slice_id:
694                 print '%02d:== created slice %d - max nodes=%d'%(i,slice_id,max_nodes)
695                 actual_persons_per_slice = min (number_persons,number_persons_per_slice)
696                 person_indexes=[map_on_person (p+ns) for p in range(actual_persons_per_slice)]
697                 for np in person_indexes:
698                     email = person_name (i,np)
699                     retcod = s[i].AddPersonToSlice (email, slicename)
700                     print '%02d:== Attached person %s to slice %s'%(i,email,slicename)
701         
702
703 def test04_node_slice (is_local, add_if_true, args=[1,2]):
704     for ns in myrange(number_slices):
705         test04_node_slice_ns (ns,is_local, add_if_true, args)
706
707 def test04_node_slice_ns (ns,is_local, add_if_true, args=[1,2]):
708     actual_nodes_per_slice = min (number_nodes,number_nodes_per_slice)
709     node_indexes = [ map_on_node (n+ns) for n in range(actual_nodes_per_slice)]
710     test04_node_slice_nl_n (node_indexes,ns,is_local, add_if_true, args)
711
712 def test04_node_slice_nl_n (nnl,ns,is_local, add_if_true, args=[1,2]):
713     for i in args:
714         peer=peer_index(i)
715         sname = slice_name (i,ns)
716         
717         if is_local:
718             hostnames=[node_name(i,nn) for nn in nnl]
719             nodetype='local'
720         else:
721             hostnames=[node_name(peer,nn) for nn in nnl]
722             nodetype='foreign'
723         if add_if_true:
724             res=s[i].AddSliceToNodes (sname,hostnames)
725             message="added"
726         else:
727             res=s[i].DeleteSliceFromNodes (sname,hostnames)
728             message="deleted"
729         if res:
730             print '%02d:== %s in slice %s %s '%(i,message,sname,nodetype),
731             print hostnames
732
733 def test04_slice_add_lnode (args=[1,2]):
734     test04_node_slice (True,True,args)
735
736 def test04_slice_add_fnode (args=[1,2]):
737     test04_node_slice (False,True,args)
738
739 def test04_slice_del_lnode (args=[1,2]):
740     test04_node_slice (True,False,args)
741
742 def test04_slice_del_fnode (args=[1,2]):
743     test04_node_slice (False,False,args)
744
745 ####################
746 def test05_sat (args=[1,2]):
747     for i in args:
748         name = sat_name(i)
749         try:
750             sat_id=s[i].GetSliceAttributeTypes ([name])[0]
751         except:
752             description="custom sat on plc%d"%i
753             min_role_id=10
754             sat_id=s[i].AddSliceAttributeType ({ 'name':name,
755                                                  'description': description,
756                                                  'min_role_id' : min_role_id})
757             if sat_id:
758                 print '%02d:== created SliceAttributeType = %d'%(i,sat_id)
759
760 # for test, we create 4 slice_attributes
761 # on slice1 - sat=custom_made (see above) - all nodes
762 # on slice1 - sat=custom_made (see above) - node=n1
763 # on slice1 - sat='net_max' - all nodes
764 # on slice1 - sat='net_max' - node=n1
765
766 def test05_sa_atom (slice_name,sat_name,value,node,i):
767     sa_id=s[i].GetSliceAttributes({'name':sat_name,
768                                    'value':value})
769     if not sa_id:
770         if node:
771             sa_id=s[i].AddSliceAttribute(slice_name,
772                                          sat_name,
773                                          value,
774                                          node)
775         else:
776             print 'slice_name',slice_name,'sat_name',sat_name
777             sa_id=s[i].AddSliceAttribute(slice_name,
778                                          sat_name,
779                                          value)
780         if sa_id:
781             print '%02d:== created SliceAttribute = %d'%(i,sa_id),
782             print 'On slice',slice_name,'and node',node
783         
784 def test05_sa (args=[1,2]):
785     for i in args:
786         test05_sa_atom (slice_name(i,1),sat_name(i),'custom sat/all nodes',None,i)
787         test05_sa_atom (slice_name(i,1),sat_name(i),'custom sat/node1',node_name(i,1),i)
788         test05_sa_atom (slice_name(i,1),'net_max','predefined sat/all nodes',None,i)
789         test05_sa_atom (slice_name(i,1),'net_max','predefined sat/node1',node_name(i,1),i)
790         
791 ##############################
792 # readable dumps
793 ##############################
794 def p_site (s):
795     print s['site_id'],s['peer_id'],s['login_base'],s['name'],s['node_ids']
796
797 def p_key (k):
798     print  k['key_id'],k['peer_id'],k['key']
799     
800 def p_person (p):
801     print  p['person_id'],p['peer_id'],p['email'],'keys:',p['key_ids'],'sites:',p['site_ids']
802
803 def p_node(n):
804     print n['node_id'],n['peer_id'],n['hostname'],'sls=',n['slice_ids'],'site=',n['site_id']
805
806 def p_slice(s):
807     print s['slice_id'],s['peer_id'],s['name'],'nodes=',s['node_ids'],'persons=',s['person_ids']
808     print '---','sas=',s['slice_attribute_ids'],s['name'],'crp=',s['creator_person_id']
809     print "--- 'expires':",s['expires']
810
811 def p_sat(sat):
812     print sat['attribute_type_id'],sat['peer_id'], sat['name'], sat['min_role_id'], sat['description']
813
814 def p_sa (sa):
815         print sa['slice_attribute_id'],sa['peer_id'],sa['name'],'AT_id:',sa['attribute_type_id']
816         print '---','v=',sa['value'],'sl=',sa['slice_id'],'n=',sa['node_id']
817
818 import pprint
819 pretty_printer=pprint.PrettyPrinter(5)
820
821 def p_sliver (margin,x):
822     print margin,'SLIVERS for : hostname',x['hostname']
823     print margin,'%d config files'%len(x['conf_files'])
824     for sv in x['slivers']:
825         p_sliver_slice(margin,sv,x['hostname'])
826
827 def p_sliver_slice(margin,sliver,hostname):
828     print margin,'SLIVER on hostname %s, s='%hostname,sliver['name']
829     print margin,'KEYS',
830     pretty_printer.pprint(sliver['keys'])
831     print margin,'ATTRIBUTES',
832     pretty_printer.pprint(sliver['attributes'])
833
834 def dump (args=[1,2]):
835     for i in args:
836         print '%02d:============================== DUMPING'%i
837         print '%02d: SITES'%i
838         [p_site(x) for x in s[i].GetSites()]
839         print '%02d: KEYS'%i
840         [p_key(x) for x in s[i].GetKeys()]
841         print '%02d: PERSONS'%i
842         [p_person(x) for x in s[i].GetPersons()]
843         print '%02d: NODES'%i
844         [p_node(x) for x in s[i].GetNodes()]
845         print '%02d: SLICES'%i
846         [p_slice(x) for x in s[i].GetSlices()]
847         print '%02d: Slice Attribute Types'%i
848         [p_sat(x) for x in s[i].GetSliceAttributeTypes()]
849         print '%02d: Slice Attributes'%i
850         [p_sa(x) for x in s[i].GetSliceAttributes()]
851         print '%02d: SLIVERS'%i
852         [p_sliver('%02d:'%i,x) for x in s[i].GetSlivers()]
853         print '%02d:============================== END DUMP'%i
854     
855
856 ## for usage under the api
857 def pt ():
858     for x in GetSites():
859         p_site(x)
860         
861 def pk ():
862     for x in GetKeys():
863         print  (x['key_id'],x['peer_id'],x['key']) 
864
865 def pp ():
866     for x in GetPersons():
867         p_person(x)
868
869 def pn ():
870     for x in GetNodes():
871         p_node(x)
872
873 def ps ():
874     for x in GetSlices():
875         p_slice(x)
876
877 def psat():
878     for x in GetSliceAttributeTypes():
879         p_sat(x)
880         
881 def psa():
882     for x in GetSliceAttributes():
883         p_sa(x)
884         
885 def pv ():
886     for s in GetSlivers():
887         p_sliver('',s)
888
889 def all():
890     print 'SITES'
891     pt()
892     print 'KEYS'
893     pk()
894     print 'PERSONS'
895     pp()
896     print 'NODES'
897     pn()
898     print 'SLICES'
899     ps()
900     print 'SLICE ATTR TYPES'
901     psat()
902     print 'SLICE ATTRS'
903     psa()
904     print 'SLIVERS'
905     pv()
906
907
908 ####################
909 def test_all_init ():
910     message ("INIT")
911     test00_init ()
912     test00_print ()
913     test00_admin_person ()
914     test00_admin_enable ()
915     test00_peer_person ()
916     test00_peer ()
917     test00_peer_passwd ()
918
919 def test_all_sites ():
920     test01_site ()
921     test00_refresh ('after site creation')
922
923 def test_all_persons ():
924     test02_del_person()
925     test00_refresh ('before persons&keys creation')
926     check_keys(0,0)
927     check_persons(system_persons,system_persons_cross)
928     message ("Creating persons&keys")
929     test02_person ()
930     if not fast_flag:
931         message ("1 extra del/add cycle for unique indexes")
932         test02_del_person([2])
933         test02_person([2])
934     check_keys(number_persons*number_keys_per_person,0)
935     check_persons(system_persons+number_persons,system_persons_cross)
936     test00_refresh ('after persons&keys creation')
937     check_keys(number_persons*number_keys_per_person,number_persons*number_keys_per_person)
938     check_persons(system_persons+number_persons,system_persons_cross+number_persons)
939
940 def test_all_nodes ():
941
942     message ("RESETTING NODES")
943     clean_all_nodes ()
944     test00_refresh ('cleaned nodes')
945     check_nodes(0,0)
946
947     # create one node on each site
948     message ("CREATING NODES")
949     test03_node ()
950     check_nodes(number_nodes,0)
951     test00_refresh ('after node creation')
952     check_nodes(number_nodes,number_nodes)
953     test02_delnode([2])
954     if not fast_flag:
955         message ("2 extra del/add cycles on plc2 for different indexes")
956         test03_node ([2])
957         test02_delnode([2])
958         test03_node ([2])
959         test02_delnode([2])
960     check_nodes(0,number_nodes,[2])
961     test00_refresh('after deletion on plc2')
962     check_nodes(number_nodes,0,[1])
963     check_nodes(0,number_nodes,[2])
964     message ("ADD on plc2 for different indexes")
965     test03_node ([2])
966     check_nodes (number_nodes,0,[1])
967     check_nodes (number_nodes,number_nodes,[2])
968     test00_refresh('after re-creation on plc2')
969     check_nodes (number_nodes,number_nodes,)
970
971 def test_all_addslices ():
972
973     # reset
974     message ("RESETTING SLICES TEST")
975     clean_all_nodes ()
976     test03_node ()
977     clean_all_slices ()
978     test00_refresh ("After slices init")
979
980     # create slices on plc1
981     message ("CREATING SLICES on plc1")
982     test04_slice ([1])
983     # each site has 3 local slices and 0 foreign slice
984     check_slices (total_slices(),0,[1])
985     check_slices (system_slices(),0,[2])
986     test00_refresh ("after slice created on plc1")
987     check_slices (total_slices(),0,[1])
988     check_slices (system_slices(),number_slices,[2])
989     # no slice has any node yet
990     check_local_slice_nodes(0,[1])
991     check_foreign_slice_nodes(0,[2])
992
993     # insert local nodes in local slice on plc1
994     message ("ADDING LOCAL NODES IN SLICES")
995     test04_slice_add_lnode ([1])
996     # of course the change is only local
997     check_local_slice_nodes (number_nodes_per_slice,[1])
998     check_foreign_slice_nodes(0,[2])
999
1000     # refreshing
1001     test00_refresh ("After local nodes were added on plc1")
1002     check_local_slice_nodes (number_nodes_per_slice,[1])
1003     check_foreign_slice_nodes (number_nodes_per_slice,[2])
1004
1005     # now we add foreign nodes into local slice
1006     message ("ADDING FOREIGN NODES IN SLICES")
1007     test04_slice_add_fnode ([1])
1008     check_local_slice_nodes (2*number_nodes_per_slice,[1])
1009     check_foreign_slice_nodes (number_nodes_per_slice,[2])
1010
1011     # refreshing
1012     test00_refresh ("After foreign nodes were added in plc1")
1013     # remember that foreign slices only know about LOCAL nodes
1014     # so this does not do anything
1015     check_local_slice_nodes (2*number_nodes_per_slice,[1])
1016     check_foreign_slice_nodes (2*number_nodes_per_slice,[2])
1017
1018     check_slivers_1(total_slivers())
1019
1020 def test_all_delslices ():
1021
1022     message ("DELETING FOREIGN NODES FROM SLICES")
1023     test04_slice_del_fnode([1])
1024     check_local_slice_nodes (number_nodes_per_slice,[1])
1025     check_foreign_slice_nodes (2*number_nodes_per_slice,[2])
1026     # mmh?
1027     check_slivers_1(total_slivers(),[1])
1028
1029     test00_refresh ("After foreign nodes were removed on plc1")
1030     check_local_slice_nodes (number_nodes_per_slice,[1])
1031     check_foreign_slice_nodes (number_nodes_per_slice,[2])
1032     
1033     message ("DELETING LOCAL NODES FROM SLICES")
1034     test04_slice_del_lnode([1])
1035     check_local_slice_nodes (0,[1])
1036     check_foreign_slice_nodes (number_nodes_per_slice,[2])
1037
1038     test00_refresh ("After local nodes were removed on plc1")
1039     check_local_slice_nodes (0,[1])
1040     check_foreign_slice_nodes (0,[2])
1041
1042     message ("CHECKING SLICES CLEAN UP")
1043     clean_all_slices([1])
1044     check_slices (system_slices(),0,[1])
1045     check_slices (system_slices(),number_slices,[2])
1046     test00_refresh ("After slices clenaup")
1047     check_slices(system_slices(),0)
1048
1049 def test_all_slices ():
1050     test_all_addslices ()
1051     test_all_delslices ()
1052     
1053 def test_all_sats ():
1054     test05_sat ()
1055     test00_refresh("after SliceAttributeType creation")                   
1056
1057 def test_all ():
1058     test_all_init ()
1059     timer_show()
1060     test_all_sites ()
1061     timer_show()
1062     test_all_persons ()
1063     timer_show()
1064     test_all_nodes ()
1065     timer_show()
1066     test_all_slices ()
1067     timer_show()
1068     test_all_sats ()
1069     timer_show()
1070     dump()
1071     timer_show()
1072     message("END")
1073
1074 ### ad hoc test sequences
1075 # we just create objects here so we can dump the DB
1076 def populate ():
1077     timer_start()
1078     test_all_init()
1079     timer_show()
1080     test01_site()
1081     timer_show()
1082     test02_person()
1083     timer_show()
1084     test03_node()
1085     timer_show()
1086     test04_slice([1])
1087     timer_show()
1088     test04_slice_add_lnode([1])
1089     timer_show()
1090     test05_sat()
1091     timer_show()
1092     test05_sa([1])
1093     timer_show()
1094     message("END")
1095
1096 def populate_end():
1097     test00_init()
1098     test00_refresh ("populate: refreshing peer 1",[1])
1099     timer_show()
1100     test04_slice_add_fnode([1])
1101     timer_show()
1102     test00_refresh("populate: refresh all")
1103     timer_show()
1104     test00_refresh("empty refresh")
1105     dump()
1106     timer_show()
1107     message("END")
1108
1109 # temporary - scratch as needed
1110 def test_now ():
1111     test_all_init()
1112     test_all_sites ()
1113 #    clean_all_nodes()
1114 #    clean_all_slices()
1115 #    populate()
1116
1117 #####
1118 def usage ():
1119     print "Usage: %s [-n] [-f]"%sys.argv[0]
1120     print " -n runs test_now instead of test_all"
1121     print " -p runs populate instead of test_all"
1122     print " -e runs populate_end of test_all"
1123     print " -m run in mini mode (1 instance of each class)"
1124     print " -b performs big run"
1125     print " -H performs huge run"
1126     print " -f n : increases normal sizes by <n>"
1127     print " -l n : tester runs locally for peer <n>, rather than through xmlrpc"
1128     
1129     sys.exit(1)
1130
1131 def main ():
1132     try:
1133         (o,a) = getopt.getopt(sys.argv[1:], "emnpbHf:l:")
1134     except:
1135         usage()
1136     func = test_all
1137     for (opt,val) in o:
1138         if opt=='-n':
1139             print 'Running test_now'
1140             func = test_now
1141         elif opt=='-p':
1142             print 'Running populate'
1143             func = populate
1144         elif opt=='-e':
1145             print 'Running populate_end'
1146             func = populate_end
1147         elif opt=='-m':
1148             mini()
1149         elif opt=='-b':
1150             big()
1151         elif opt=='-H':
1152             huge()
1153         elif opt=='-f':
1154             factor=int(val)
1155             apply_factor(factor)
1156         elif opt=='-l':
1157             global local_peer
1158             local_peer=int(val)
1159             if local_peer not in (1,2):
1160                 usage()
1161         else:
1162             usage()
1163     if a:
1164         usage()
1165     show_test()
1166     func()   
1167     timer_show()
1168
1169 if __name__ == '__main__':
1170     normal()
1171     main()
1172