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