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