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