split sfa-create-slice into sfa-rspec\ 1 sfa-allocate and sfa-provision
[tests.git] / system / TestSliceSfa.py
1 # Thierry Parmentelat <thierry.parmentelat@inria.fr>
2 # Copyright (C) 2010 INRIA 
3 #
4
5 import os.path
6 import time
7 from datetime import datetime, timedelta
8 import json
9 import traceback
10
11 import utils
12 from TestNode import TestNode
13 from TestUser import TestUser
14 from TestBoxQemu import TestBoxQemu
15 from TestSsh import TestSsh
16
17 from Completer import Completer, CompleterTask
18 from TestSlice import CompleterTaskSliceSsh
19
20 class TestSliceSfa:
21
22     def __init__ (self, test_auth_sfa, slice_spec):
23         self.test_auth_sfa=test_auth_sfa
24         self.slice_spec=slice_spec
25         # shortcuts
26         self.test_plc=self.test_auth_sfa.test_plc
27
28     def hrn (self): 
29         return self.test_auth_sfa.obj_hrn(self.slice_spec['name'])
30     def sfi_path (self):
31         return self.test_auth_sfa.sfi_path()
32
33     # send back up to the TestAuthSfa
34     def sfi_path (self): return self.test_auth_sfa.sfi_path()
35     def rspec_style (self): return self.test_auth_sfa.rspec_style()
36     def sfi_pi(self,*args,**kwds): return self.test_auth_sfa.sfi_pi(*args, **kwds)
37     def sfi_user(self,*args,**kwds): return self.test_auth_sfa.sfi_user(*args, **kwds)
38
39     def discover_option(self):
40         if self.rspec_style()=='pg': return "-r GENI"
41         else:                        return "-r sfa"
42
43     # those are step names exposed as methods of TestPlc, hence the _sfa
44
45     # needs to be run as pi
46     def sfa_register_slice(self,options):
47         "run sfi register (on Registry)"
48         sfi_command="register"
49         sfi_command += " --type slice"
50         sfi_command += " --xrn %s"%self.hrn()
51         for opt in self.slice_spec['register_options']:
52             sfi_command += " %s"%(opt)
53         return self.test_plc.run_in_guest(self.sfi_pi(sfi_command))==0
54
55     def sfa_renew_slice(self, options):
56         "run sfi renew (on Aggregates)"
57 #        too_late =  (datetime.now() + timedelta(weeks=52)).strftime("%Y-%m-%d")
58         one_month = (datetime.now() + timedelta(weeks=4)).strftime("%Y-%m-%d")
59         too_late =  "+12m"
60 #        one_month = "+4w"
61         # we expect this to fail on too long term attemps, but to succeed otherwise
62         overall=True
63         for ( renew_until, expected) in [ (too_late, False), (one_month, True) ] :
64             sfi_command="renew"
65             sfi_command += " %s"%self.hrn()
66             sfi_command += " %s"%renew_until
67             succeeded = self.test_plc.run_in_guest(self.sfi_user(sfi_command))==0
68             if succeeded!=expected:
69                 utils.header ("Expecting success=%s, got %s"%(expected,succeeded))
70                 # however it turns out sfi renew always returns fine....
71                 #overall=False
72             # so for helping manual checks:
73             # xxx this should use sfa_get_expires below and actually check the expected result
74             sfi_command="show -k hrn -k expires %s"%self.hrn()
75             self.test_plc.run_in_guest(self.sfi_user(sfi_command))
76         return overall
77
78     def sfa_get_expires (self, options):
79         filename="%s.json"%self.hrn()
80         # /root/sfi/pg/<>
81         inplc_filename=os.path.join(self.sfi_path(),filename)
82         # /vservers/<>/root/sfi/... - cannot use os.path 
83         inbox_filename="%s%s"%(self.test_plc.vm_root_in_host(),inplc_filename)
84         sfi_command  =""
85         sfi_command += "-R %s --rawformat json"%inplc_filename
86         sfi_command += " status"
87         sfi_command += " %s"%self.hrn()
88         # cannot find it if sfi status returns an error
89         if self.test_plc.run_in_guest (self.sfi_user(sfi_command)) !=0: return
90         if self.test_plc.test_ssh.fetch(inbox_filename,filename)!=0: return 
91         try:
92             with file(filename) as f: status = json.loads(f.read())
93             value=status['value']
94             sliver=value['geni_slivers'][0]
95             expires=sliver['geni_expires']
96             print " * expiration for %s (first sliver) -> %s"%(self.hrn(),expires)
97             return expires
98         except:
99             traceback.print_exc()
100
101     # helper - filename to store a given result
102     def _resname (self,name,ext): return "%s.%s"%(name,ext)
103     def adfile (self): return self._resname("ad","rspec")
104     def reqfile (self): return self._resname("req","rspec")
105     def nodefile (self): return self._resname("nodes","txt")
106     
107     # run as user
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
112
113     def sfa_rspec(self,options):
114         "invoke sfiListNodes and sfiAddSlivers to prepare a rspec"
115         commands=[
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()),
119             ]
120         for command in commands:
121             if self.test_plc.run_in_guest(command)!=0: return False
122         return True
123
124     def sfa_allocate(self,options):
125         "invoke run sfi allocate (on SM)"
126         command=self.sfi_user("allocate %s %s"%(self.hrn(),self.reqfile()))
127         return self.test_plc.run_in_guest(command)==0
128
129     def sfa_provision(self,options):
130         "invoke run sfi provision (on SM)"
131         command=self.sfi_user("provision %s"%(self.hrn()))
132         return self.test_plc.run_in_guest(command)==0
133
134     def plc_name (self):
135         return "%s_%s"%(self.test_auth_sfa.login_base,self.slice_spec['name'])
136
137     # all local nodes in slice ?
138     def sfa_check_slice_plc (self,options):
139         "check the slices have been created at the plcs - all local nodes should be in slice"
140         slice=self.test_plc.apiserver.GetSlices(self.test_plc.auth_root(), self.plc_name())[0]
141         nodes=self.test_plc.apiserver.GetNodes(self.test_plc.auth_root(), {'peer_id':None})
142         result=True
143         for node in nodes: 
144             if node['node_id'] in slice['node_ids']:
145                 utils.header("local node %s found in slice %s"%(node['hostname'],slice['name']))
146             else:
147                 utils.header("ERROR - local node %s NOT FOUND in slice %s"%(node['hostname'],slice['name']))
148                 result=False
149         return result
150
151     # xxx historically this used to do the same as sfa-create-slice
152     # which was later on split into 3 distinct steps, 
153     # and we can ignore the first that is about setting up the rspec
154     def sfa_update_slice(self,options):
155         "re-run sfi allocate and provision (on SM) on existing object"
156         return self.sfa_allocate(options) and self.sfa_provision(options)
157
158     # run as pi
159     def sfa_delete_slice(self,options):
160         "run sfi delete"
161         self.test_plc.run_in_guest(self.sfi_pi("delete %s"%(self.hrn(),)))
162         return self.test_plc.run_in_guest(self.sfi_pi("remove -t slice %s"%(self.hrn(),)))==0
163
164     def locate_private_key(self):
165         return self.test_plc.locate_private_key_from_key_names ( [ self.slice_spec['key_name'] ] )
166
167     # check the resulting sliver
168     def ssh_slice_sfa(self,options,timeout_minutes=40,silent_minutes=0,period_seconds=15):
169         "tries to ssh-enter the SFA slice"
170         timeout  = timedelta(minutes=timeout_minutes)
171         graceout = timedelta(minutes=silent_minutes)
172         period   = timedelta(seconds=period_seconds)
173         # locate a key
174         private_key=self.locate_private_key()
175         if not private_key :
176             utils.header("WARNING: Cannot find a valid key for slice %s"%self.name())
177             return False
178         command="echo hostname ; hostname; echo id; id; echo uname -a ; uname -a"
179         
180         tasks=[]
181         slicename=self.plc_name()
182         dry_run = getattr(options,'dry_run',False)
183         for nodename in self.slice_spec['nodenames']:
184             (site_spec,node_spec) = self.test_plc.locate_node(nodename)
185             tasks.append( CompleterTaskSliceSsh(self.test_plc,node_spec['node_fields']['hostname'],
186                                                 slicename,private_key,command,expected=True,dry_run=dry_run))
187         return Completer (tasks).run (timeout, graceout, period)