Merge "[RIFT 16413, 16414] Unittest failures fixed for utest_package, utest_publisher...
[osm/SO.git] / rwlaunchpad / test / mgmt_recovery.py
1 #!/usr/bin/env python3
2
3 #
4 # Copyright 2016 RIFT.IO Inc
5 #
6 # Licensed under the Apache License, Version 2.0 (the "License");
7 # you may not use this file except in compliance with the License.
8 # You may obtain a copy of the License at
9 #
10 # http://www.apache.org/licenses/LICENSE-2.0
11 #
12 # Unless required by applicable law or agreed to in writing, software
13 # distributed under the License is distributed on an "AS IS" BASIS,
14 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 # See the License for the specific language governing permissions and
16 # limitations under the License.
17 #
18
19
20 import logging
21 import os
22 import resource
23 import socket
24 import sys
25 import subprocess
26 import shlex
27 import shutil
28 import netifaces
29
30 from rift.rwlib.util import certs
31 import rift.rwcal.cloudsim
32 import rift.rwcal.cloudsim.net
33 import rift.vcs
34 import rift.vcs.core as core
35 import rift.vcs.demo
36 import rift.vcs.vms
37
38 import rift.rwcal.cloudsim
39 import rift.rwcal.cloudsim.net
40
41 from rift.vcs.ext import ClassProperty
42
43 logger = logging.getLogger(__name__)
44
45
46 class NsmTasklet(rift.vcs.core.Tasklet):
47 """
48 This class represents a network services manager tasklet.
49 """
50
51 def __init__(self, name='network-services-manager', uid=None,
52 config_ready=True,
53 recovery_action=core.RecoveryType.FAILCRITICAL.value,
54 data_storetype=core.DataStore.NOSTORE.value,
55 ):
56 """
57 Creates a NsmTasklet object.
58
59 Arguments:
60 name - the name of the tasklet
61 uid - a unique identifier
62 """
63 super(NsmTasklet, self).__init__(name=name, uid=uid,
64 config_ready=config_ready,
65 recovery_action=recovery_action,
66 data_storetype=data_storetype,
67 )
68
69 plugin_directory = ClassProperty('./usr/lib/rift/plugins/rwnsmtasklet')
70 plugin_name = ClassProperty('rwnsmtasklet')
71
72
73 class VnsTasklet(rift.vcs.core.Tasklet):
74 """
75 This class represents a network services manager tasklet.
76 """
77
78 def __init__(self, name='virtual-network-service', uid=None,
79 config_ready=True,
80 recovery_action=core.RecoveryType.FAILCRITICAL.value,
81 data_storetype=core.DataStore.NOSTORE.value,
82 ):
83 """
84 Creates a VnsTasklet object.
85
86 Arguments:
87 name - the name of the tasklet
88 uid - a unique identifier
89 """
90 super(VnsTasklet, self).__init__(name=name, uid=uid,
91 config_ready=config_ready,
92 recovery_action=recovery_action,
93 data_storetype=data_storetype,
94 )
95
96 plugin_directory = ClassProperty('./usr/lib/rift/plugins/rwvnstasklet')
97 plugin_name = ClassProperty('rwvnstasklet')
98
99
100 class VnfmTasklet(rift.vcs.core.Tasklet):
101 """
102 This class represents a virtual network function manager tasklet.
103 """
104
105 def __init__(self, name='virtual-network-function-manager', uid=None,
106 config_ready=True,
107 recovery_action=core.RecoveryType.FAILCRITICAL.value,
108 data_storetype=core.DataStore.NOSTORE.value,
109 ):
110 """
111 Creates a VnfmTasklet object.
112
113 Arguments:
114 name - the name of the tasklet
115 uid - a unique identifier
116 """
117 super(VnfmTasklet, self).__init__(name=name, uid=uid,
118 config_ready=config_ready,
119 recovery_action=recovery_action,
120 data_storetype=data_storetype,
121 )
122
123 plugin_directory = ClassProperty('./usr/lib/rift/plugins/rwvnfmtasklet')
124 plugin_name = ClassProperty('rwvnfmtasklet')
125
126
127 class ResMgrTasklet(rift.vcs.core.Tasklet):
128 """
129 This class represents a Resource Manager tasklet.
130 """
131
132 def __init__(self, name='Resource-Manager', uid=None,
133 config_ready=True,
134 recovery_action=core.RecoveryType.FAILCRITICAL.value,
135 data_storetype=core.DataStore.NOSTORE.value,
136 ):
137 """
138 Creates a ResMgrTasklet object.
139
140 Arguments:
141 name - the name of the tasklet
142 uid - a unique identifier
143 """
144 super(ResMgrTasklet, self).__init__(name=name, uid=uid,
145 config_ready=config_ready,
146 recovery_action=recovery_action,
147 data_storetype=data_storetype,
148 )
149
150 plugin_directory = ClassProperty('./usr/lib/rift/plugins/rwresmgrtasklet')
151 plugin_name = ClassProperty('rwresmgrtasklet')
152
153
154 class MonitorTasklet(rift.vcs.core.Tasklet):
155 """
156 This class represents a tasklet that is used to monitor NFVI metrics.
157 """
158
159 def __init__(self, name='nfvi-metrics-monitor', uid=None,
160 config_ready=True,
161 recovery_action=core.RecoveryType.FAILCRITICAL.value,
162 data_storetype=core.DataStore.NOSTORE.value,
163 ):
164 """
165 Creates a MonitorTasklet object.
166
167 Arguments:
168 name - the name of the tasklet
169 uid - a unique identifier
170
171 """
172 super(MonitorTasklet, self).__init__(name=name, uid=uid,
173 config_ready=config_ready,
174 recovery_action=recovery_action,
175 data_storetype=data_storetype,
176 )
177
178 plugin_directory = ClassProperty('./usr/lib/rift/plugins/rwmonitor')
179 plugin_name = ClassProperty('rwmonitor')
180
181
182 def get_ui_ssl_args():
183 """Returns the SSL parameter string for launchpad UI processes"""
184
185 try:
186 use_ssl, certfile_path, keyfile_path = certs.get_bootstrap_cert_and_key()
187 except certs.BootstrapSslMissingException:
188 logger.error('No bootstrap certificates found. Disabling UI SSL')
189 use_ssl = False
190
191 # If we're not using SSL, no SSL arguments are necessary
192 if not use_ssl:
193 return ""
194
195 return "--enable-https --keyfile-path=%s --certfile-path=%s" % (keyfile_path, certfile_path)
196
197
198 class UIServer(rift.vcs.NativeProcess):
199 def __init__(self, name="RW.MC.UI",
200 config_ready=True,
201 recovery_action=core.RecoveryType.FAILCRITICAL.value,
202 data_storetype=core.DataStore.NOSTORE.value,
203 ):
204 super(UIServer, self).__init__(
205 name=name,
206 exe="./usr/share/rw.ui/skyquake/scripts/launch_ui.sh",
207 config_ready=config_ready,
208 recovery_action=recovery_action,
209 data_storetype=data_storetype,
210 )
211
212 @property
213 def args(self):
214 return get_ui_ssl_args()
215
216
217 class RedisServer(rift.vcs.NativeProcess):
218 def __init__(self, name="RW.Redis.Server",
219 config_ready=True,
220 recovery_action=core.RecoveryType.FAILCRITICAL.value,
221 data_storetype=core.DataStore.NOSTORE.value,
222 ):
223 super(RedisServer, self).__init__(
224 name=name,
225 exe="/usr/bin/redis-server",
226 config_ready=config_ready,
227 recovery_action=recovery_action,
228 data_storetype=data_storetype,
229 )
230
231 @property
232 def args(self):
233 return "./usr/bin/active_redis.conf --port 9999"
234
235 class ConfigManagerTasklet(rift.vcs.core.Tasklet):
236 """
237 This class represents a Resource Manager tasklet.
238 """
239
240 def __init__(self, name='Configuration-Manager', uid=None,
241 config_ready=True,
242 recovery_action=core.RecoveryType.FAILCRITICAL.value,
243 data_storetype=core.DataStore.NOSTORE.value,
244 ):
245 """
246 Creates a ConfigManagerTasklet object.
247
248 Arguments:
249 name - the name of the tasklet
250 uid - a unique identifier
251 """
252 super(ConfigManagerTasklet, self).__init__(name=name, uid=uid,
253 config_ready=config_ready,
254 recovery_action=recovery_action,
255 data_storetype=data_storetype,
256 )
257
258 plugin_directory = ClassProperty('./usr/lib/rift/plugins/rwconmantasklet')
259 plugin_name = ClassProperty('rwconmantasklet')
260
261
262 class Demo(rift.vcs.demo.Demo):
263 def __init__(self,mgmt_ip_list):
264
265 procs = [
266 ConfigManagerTasklet(),
267 UIServer(),
268 RedisServer(),
269 rift.vcs.RestPortForwardTasklet(),
270 rift.vcs.RestconfTasklet(),
271 rift.vcs.RiftCli(),
272 rift.vcs.uAgentTasklet(),
273 rift.vcs.Launchpad(),
274 ]
275
276 standby_procs = [
277 RedisServer(),
278 rift.vcs.uAgentTasklet(mode_active=False),
279 ]
280
281 restart_procs = [
282 VnfmTasklet(recovery_action=core.RecoveryType.RESTART.value, data_storetype=core.DataStore.REDIS.value),
283 VnsTasklet(recovery_action=core.RecoveryType.RESTART.value, data_storetype=core.DataStore.REDIS.value),
284 MonitorTasklet(recovery_action=core.RecoveryType.RESTART.value, data_storetype=core.DataStore.REDIS.value),
285 NsmTasklet(recovery_action=core.RecoveryType.RESTART.value, data_storetype=core.DataStore.REDIS.value),
286 ResMgrTasklet(recovery_action=core.RecoveryType.RESTART.value, data_storetype=core.DataStore.REDIS.value),
287 ]
288 super(Demo, self).__init__(
289 # Construct the system. This system consists of 1 cluster in 1
290 # colony. The master cluster houses CLI and management VMs
291 sysinfo = rift.vcs.SystemInfo(
292 zookeeper=rift.vcs.manifest.RaZookeeper(zake=False, master_ip=mgmt_ip_list[0]),
293 colonies=[
294 rift.vcs.Colony(
295 name='master',
296 uid=1,
297 clusters=[
298 rift.vcs.VirtualMachine(
299 name='vm-templ-1',
300 ip=mgmt_ip_list[0],
301 procs=procs,
302 restart_procs=restart_procs,
303 ),
304 rift.vcs.VirtualMachine(
305 name='vm-templ-2',
306 ip=mgmt_ip_list[1],
307 standby_procs=standby_procs,
308 start=False,
309 ),
310 ] if len(mgmt_ip_list) == 2 else [
311 rift.vcs.VirtualMachine(
312 name='vm-templ-1',
313 ip=mgmt_ip_list[0],
314 procs=procs,
315 restart_procs=restart_procs,
316 ),
317 ]
318 )
319 ],
320 ),
321
322 # Define the generic portmap.
323 port_map = {},
324
325 # Define a mapping from the placeholder logical names to the real
326 # port names for each of the different modes supported by this demo.
327 port_names = {
328 'ethsim': {
329 },
330 'pci': {
331 }
332 },
333
334 # Define the connectivity between logical port names.
335 port_groups = {},
336 )
337
338
339 def main(argv=sys.argv[1:]):
340 logging.basicConfig(format='%(asctime)-15s %(levelname)s %(message)s')
341
342 # Create a parser which includes all generic demo arguments
343 parser = rift.vcs.demo.DemoArgParser()
344
345 args = parser.parse_args(argv)
346
347 # Disable loading any kernel modules for the launchpad VM
348 # since it doesn't need it and it will fail within containers
349 os.environ["NO_KERNEL_MODS"] = "1"
350
351 # Remove the persistant DTS recovery files
352 for f in os.listdir(os.environ["INSTALLDIR"]):
353 if f.endswith(".db"):
354 os.remove(os.path.join(os.environ["INSTALLDIR"], f))
355
356 #load demo info and create Demo object
357 demo = Demo(args.mgmt_ip_list)
358
359 # Create the prepared system from the demo
360 system = rift.vcs.demo.prepared_system_from_demo_and_args(demo, args,
361 northbound_listing="cli_launchpad_schema_listing.txt",
362 netconf_trace_override=True)
363
364 confd_ip = socket.gethostbyname(socket.gethostname())
365 intf = netifaces.ifaddresses('eth0')
366 if intf and netifaces.AF_INET in intf and len(intf[netifaces.AF_INET]):
367 confd_ip = intf[netifaces.AF_INET][0]['addr']
368 rift.vcs.logger.configure_sink(config_file=None, confd_ip=confd_ip)
369
370 # Start the prepared system
371 system.start()
372
373
374 if __name__ == "__main__":
375 resource.setrlimit(resource.RLIMIT_CORE, (resource.RLIM_INFINITY, resource.RLIM_INFINITY) )
376 try:
377 main()
378 except rift.vcs.demo.ReservationError:
379 print("ERROR: unable to retrieve a list of IP addresses from the reservation system")
380 sys.exit(1)
381 except rift.vcs.demo.MissingModeError:
382 print("ERROR: you need to provide a mode to run the script")
383 sys.exit(1)
384 finally:
385 os.system("stty sane")