1 # Thierry Parmentelat <thierry.parmentelat@inria.fr>
2 # Copyright (C) 2010 INRIA
7 from datetime import datetime, timedelta
12 from TestNode import TestNode
13 from TestUser import TestUser
14 from TestBoxQemu import TestBoxQemu
16 from Completer import Completer, CompleterTask
17 from TestSlice import CompleterTaskSliceSsh
21 def __init__ (self, test_auth_sfa, slice_spec):
22 self.test_auth_sfa=test_auth_sfa
23 self.slice_spec=slice_spec
25 self.test_plc=self.test_auth_sfa.test_plc
28 return self.test_auth_sfa.obj_hrn(self.slice_spec['name'])
30 return self.test_auth_sfa.sfi_path()
32 # send back up to the TestAuthSfa
33 def sfi_path (self): return self.test_auth_sfa.sfi_path()
34 def rspec_style (self): return self.test_auth_sfa.rspec_style()
35 def sfi_pi(self,*args,**kwds): return self.test_auth_sfa.sfi_pi(*args, **kwds)
36 def sfi_user(self,*args,**kwds): return self.test_auth_sfa.sfi_user(*args, **kwds)
38 def discover_option(self):
39 if self.rspec_style()=='pg': return "-r GENI"
42 # those are step names exposed as methods of TestPlc, hence the _sfa
44 # needs to be run as pi
45 def sfa_register_slice(self,options):
46 "run sfi register (on Registry)"
47 sfi_command="register"
48 sfi_command += " --type slice"
49 sfi_command += " --xrn %s"%self.hrn()
50 for opt in self.slice_spec['register_options']:
51 sfi_command += " %s"%(opt)
52 return self.test_plc.run_in_guest(self.sfi_pi(sfi_command))==0
54 def sfa_renew_slice(self, options):
55 "run sfi renew (on Aggregates)"
56 # too_late = (datetime.now() + timedelta(weeks=52)).strftime("%Y-%m-%d")
57 one_month = (datetime.now() + timedelta(weeks=4)).strftime("%Y-%m-%d")
60 # we expect this to fail on too long term attemps, but to succeed otherwise
62 for ( renew_until, expected) in [ (too_late, False), (one_month, True) ] :
64 sfi_command += " %s"%self.hrn()
65 sfi_command += " %s"%renew_until
66 succeeded = self.test_plc.run_in_guest(self.sfi_user(sfi_command))==0
67 if succeeded!=expected:
68 utils.header ("Expecting success=%s, got %s"%(expected,succeeded))
69 # however it turns out sfi renew always returns fine....
71 # so for helping manual checks:
72 # xxx this should use sfa_get_expires below and actually check the expected result
73 sfi_command="show -k hrn -k expires %s"%self.hrn()
74 self.test_plc.run_in_guest(self.sfi_user(sfi_command))
77 def sfa_get_expires (self, options):
78 filename="%s.json"%self.hrn()
80 inplc_filename=os.path.join(self.sfi_path(),filename)
81 # /vservers/<>/root/sfi/... - cannot use os.path
82 inbox_filename="%s%s"%(self.test_plc.vm_root_in_host(),inplc_filename)
84 sfi_command += "-R %s --rawformat json"%inplc_filename
85 sfi_command += " status"
86 sfi_command += " %s"%self.hrn()
87 # cannot find it if sfi status returns an error
88 if self.test_plc.run_in_guest (self.sfi_user(sfi_command)) !=0: return
89 if self.test_plc.test_ssh.fetch(inbox_filename,filename)!=0: return
91 with file(filename) as f: status = json.loads(f.read())
93 sliver=value['geni_slivers'][0]
94 expires=sliver['geni_expires']
95 print " * expiration for %s (first sliver) -> %s"%(self.hrn(),expires)
100 # helper - filename to store a given result
101 def _resname (self,name,ext): return "%s.%s"%(name,ext)
102 def adfile (self): return self._resname("ad","rspec")
103 def reqfile (self): return self._resname("req","rspec")
104 def empty_reqfile (self): return "empty-rspec.xml"
105 def nodefile (self): return self._resname("nodes","txt")
108 def sfa_discover(self,options):
109 "discover resources into resouces_in.rspec"
110 return self.test_plc.run_in_guest(self.sfi_user(\
111 "resources %s -o %s/%s"% (self.discover_option(),self.sfi_path(),self.adfile())))==0
113 def sfa_rspec(self,options):
114 "invoke sfiListNodes and sfiAddSlivers to prepare a rspec"
116 "sfiListNodes.py -i %s/%s -o %s/%s"%(self.sfi_path(),self.adfile(),self.sfi_path(),self.nodefile()),
117 "sfiAddSliver.py -i %s/%s -n %s/%s -o %s/%s"%\
118 (self.sfi_path(),self.adfile(),self.sfi_path(),self.nodefile(),self.sfi_path(),self.reqfile()),
120 for command in commands:
121 if self.test_plc.run_in_guest(command)!=0: return False
124 def _sfa_allocate(self,file,options):
125 command=self.sfi_user("allocate %s %s"%(self.hrn(),file))
126 return self.test_plc.run_in_guest(command)==0
128 def sfa_allocate(self,options):
129 "invoke run sfi allocate (on SM)"
130 return self._sfa_allocate(self.reqfile(),options)
131 def sfa_allocate_empty(self,options):
132 "invoke run sfi allocate (on SM) with an empty rspec"
133 return self._sfa_allocate(self.empty_reqfile(),options)
135 def sfa_provision(self,options):
136 "invoke run sfi provision (on SM)"
137 command=self.sfi_user("provision %s"%(self.hrn()))
138 return self.test_plc.run_in_guest(command)==0
140 sfa_provision_empty = sfa_provision
143 return "%s_%s"%(self.test_auth_sfa.login_base,self.slice_spec['name'])
145 # all local nodes in slice ?
146 def sfa_check_slice_plc (self,options):
147 "check the slice has been created at the plc - all local nodes should be in slice"
148 slice=self.test_plc.apiserver.GetSlices(self.test_plc.auth_root(), self.plc_name())[0]
149 nodes=self.test_plc.apiserver.GetNodes(self.test_plc.auth_root(), {'peer_id':None})
152 if node['node_id'] in slice['node_ids']:
153 utils.header("local node %s found in slice %s"%(node['hostname'],slice['name']))
155 utils.header("ERROR - local node %s NOT FOUND in slice %s"%(node['hostname'],slice['name']))
159 # no node left in slice ?
160 def sfa_check_slice_plc_empty (self,options):
161 "check the slice have been emptied at the plcs - no node should be in slice"
162 slices=self.test_plc.apiserver.GetSlices(self.test_plc.auth_root(),
165 return not slices[0]['node_ids']
167 # xxx historically this used to do the same as sfa-create-slice
168 # which was later on split into 3 distinct steps,
169 # and we can ignore the first that is about setting up the rspec
170 def sfa_update_slice(self,options):
171 "re-run sfi allocate and provision (on SM) on existing object"
172 return self.sfa_allocate(options) and self.sfa_provision(options)
175 def sfa_delete_slice(self,options):
177 self.test_plc.run_in_guest(self.sfi_pi("delete %s"%(self.hrn(),)))
178 return self.test_plc.run_in_guest(self.sfi_pi("remove -t slice %s"%(self.hrn(),)))==0
180 def locate_private_key(self):
181 return self.test_plc.locate_private_key_from_key_names ( [ self.slice_spec['key_name'] ] )
183 # check the resulting sliver
184 def ssh_slice_sfa(self,options,timeout_minutes=40,silent_minutes=0,period_seconds=15):
185 "tries to ssh-enter the SFA slice"
186 timeout = timedelta(minutes=timeout_minutes)
187 graceout = timedelta(minutes=silent_minutes)
188 period = timedelta(seconds=period_seconds)
190 private_key=self.locate_private_key()
192 utils.header("WARNING: Cannot find a valid key for slice %s"%self.name())
194 command="echo hostname ; hostname; echo id; id; echo uname -a ; uname -a"
197 slicename=self.plc_name()
198 dry_run = getattr(options,'dry_run',False)
199 for nodename in self.slice_spec['nodenames']:
200 (site_spec,node_spec) = self.test_plc.locate_node(nodename)
201 tasks.append( CompleterTaskSliceSsh(self.test_plc,node_spec['node_fields']['hostname'],
202 slicename,private_key,command,expected=True,dry_run=dry_run))
203 return Completer (tasks, message='ssh_slice_sfa').run (timeout, graceout, period)