Bug 372 - Cloud init files do not get applied on Openstack/AWS datacenters
[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.RestconfTasklet(),
270 rift.vcs.RiftCli(),
271 rift.vcs.uAgentTasklet(),
272 rift.vcs.Launchpad(),
273 ]
274
275 standby_procs = [
276 RedisServer(),
277 rift.vcs.uAgentTasklet()
278 ]
279
280 restart_procs = [
281 VnfmTasklet(recovery_action=core.RecoveryType.RESTART.value, data_storetype=core.DataStore.REDIS.value),
282 VnsTasklet(recovery_action=core.RecoveryType.RESTART.value, data_storetype=core.DataStore.REDIS.value),
283 MonitorTasklet(recovery_action=core.RecoveryType.RESTART.value, data_storetype=core.DataStore.REDIS.value),
284 NsmTasklet(recovery_action=core.RecoveryType.RESTART.value, data_storetype=core.DataStore.REDIS.value),
285 ResMgrTasklet(recovery_action=core.RecoveryType.RESTART.value, data_storetype=core.DataStore.REDIS.value),
286 ]
287 super(Demo, self).__init__(
288 # Construct the system. This system consists of 1 cluster in 1
289 # colony. The master cluster houses CLI and management VMs
290 sysinfo = rift.vcs.SystemInfo(
291 zookeeper=rift.vcs.manifest.RaZookeeper(zake=False, master_ip=mgmt_ip_list[0]),
292 colonies=[
293 rift.vcs.Colony(
294 name='master',
295 uid=1,
296 clusters=[
297 rift.vcs.VirtualMachine(
298 name='vm-templ-1',
299 ip=mgmt_ip_list[0],
300 procs=procs,
301 restart_procs=restart_procs,
302 ),
303 rift.vcs.VirtualMachine(
304 name='vm-templ-2',
305 ip=mgmt_ip_list[1],
306 standby_procs=standby_procs,
307 start=False,
308 ),
309 ] if len(mgmt_ip_list) == 2 else [
310 rift.vcs.VirtualMachine(
311 name='vm-templ-1',
312 ip=mgmt_ip_list[0],
313 procs=procs,
314 restart_procs=restart_procs,
315 ),
316 ]
317 )
318 ],
319 ),
320
321 # Define the generic portmap.
322 port_map = {},
323
324 # Define a mapping from the placeholder logical names to the real
325 # port names for each of the different modes supported by this demo.
326 port_names = {
327 'ethsim': {
328 },
329 'pci': {
330 }
331 },
332
333 # Define the connectivity between logical port names.
334 port_groups = {},
335 )
336
337
338 def main(argv=sys.argv[1:]):
339 logging.basicConfig(format='%(asctime)-15s %(levelname)s %(message)s')
340
341 # Create a parser which includes all generic demo arguments
342 parser = rift.vcs.demo.DemoArgParser()
343
344 args = parser.parse_args(argv)
345
346 # Disable loading any kernel modules for the launchpad VM
347 # since it doesn't need it and it will fail within containers
348 os.environ["NO_KERNEL_MODS"] = "1"
349
350 # Remove the persistant DTS recovery files
351 for f in os.listdir(os.environ["INSTALLDIR"]):
352 if f.endswith(".db"):
353 os.remove(os.path.join(os.environ["INSTALLDIR"], f))
354
355 #load demo info and create Demo object
356 demo = Demo(args.mgmt_ip_list)
357
358 # Create the prepared system from the demo
359 system = rift.vcs.demo.prepared_system_from_demo_and_args(demo, args,
360 northbound_listing=["platform_schema_listing.txt", "platform_mgmt_schema_listing.txt", "cli_launchpad_schema_listing.txt"],
361 netconf_trace_override=True)
362
363 confd_ip = socket.gethostbyname(socket.gethostname())
364 intf = netifaces.ifaddresses('eth0')
365 if intf and netifaces.AF_INET in intf and len(intf[netifaces.AF_INET]):
366 confd_ip = intf[netifaces.AF_INET][0]['addr']
367 rift.vcs.logger.configure_sink(config_file=None, confd_ip=confd_ip)
368
369 # Start the prepared system
370 system.start()
371
372
373 if __name__ == "__main__":
374 resource.setrlimit(resource.RLIMIT_CORE, (resource.RLIM_INFINITY, resource.RLIM_INFINITY) )
375 try:
376 main()
377 except rift.vcs.demo.ReservationError:
378 print("ERROR: unable to retrieve a list of IP addresses from the reservation system")
379 sys.exit(1)
380 except rift.vcs.demo.MissingModeError:
381 print("ERROR: you need to provide a mode to run the script")
382 sys.exit(1)
383 finally:
384 os.system("stty sane")