blob: c2392c23b3a0a736cea2aef40e4c7d12c84a87e6 [file] [log] [blame]
Jeremy Mordkoff6f07e6f2016-09-07 18:56:51 -04001#!/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
20import logging
21import os
22import resource
23import socket
24import sys
25import subprocess
26import shlex
27import shutil
28import netifaces
29
30from rift.rwlib.util import certs
31import rift.rwcal.cloudsim
32import rift.rwcal.cloudsim.net
33import rift.vcs
34import rift.vcs.core as core
35import rift.vcs.demo
36import rift.vcs.vms
37
38import rift.rwcal.cloudsim
39import rift.rwcal.cloudsim.net
40
41from rift.vcs.ext import ClassProperty
42
43logger = logging.getLogger(__name__)
44
45
46class 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
73class 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
100class 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
127class 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
154class 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
182def 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
198class 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
217class 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
235class 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
262class Demo(rift.vcs.demo.Demo):
263 def __init__(self,mgmt_ip_list):
264
265 procs = [
266 ConfigManagerTasklet(),
267 UIServer(),
268 RedisServer(),
Jeremy Mordkoff6f07e6f2016-09-07 18:56:51 -0400269 rift.vcs.RestconfTasklet(),
270 rift.vcs.RiftCli(),
271 rift.vcs.uAgentTasklet(),
272 rift.vcs.Launchpad(),
273 ]
274
275 standby_procs = [
276 RedisServer(),
Jeremy Mordkoff4870d0e2017-09-30 20:28:33 -0400277 rift.vcs.uAgentTasklet()
Jeremy Mordkoff6f07e6f2016-09-07 18:56:51 -0400278 ]
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
338def 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,
Jeremy Mordkoff4870d0e2017-09-30 20:28:33 -0400360 northbound_listing=["platform_schema_listing.txt", "platform_mgmt_schema_listing.txt", "cli_launchpad_schema_listing.txt"],
Jeremy Mordkoff6f07e6f2016-09-07 18:56:51 -0400361 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
373if __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")