4 # Copyright 2016 RIFT.IO Inc
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
10 # http://www.apache.org/licenses/LICENSE-2.0
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.
30 from rift
.rwlib
.util
import certs
31 import rift
.rwcal
.cloudsim
32 import rift
.rwcal
.cloudsim
.net
34 import rift
.vcs
.core
as core
38 import rift
.rwcal
.cloudsim
39 import rift
.rwcal
.cloudsim
.net
41 from rift
.vcs
.ext
import ClassProperty
43 logger
= logging
.getLogger(__name__
)
46 class NsmTasklet(rift
.vcs
.core
.Tasklet
):
48 This class represents a network services manager tasklet.
51 def __init__(self
, name
='network-services-manager', uid
=None,
53 recovery_action
=core
.RecoveryType
.FAILCRITICAL
.value
,
54 data_storetype
=core
.DataStore
.NOSTORE
.value
,
57 Creates a NsmTasklet object.
60 name - the name of the tasklet
61 uid - a unique identifier
63 super(NsmTasklet
, self
).__init
__(name
=name
, uid
=uid
,
64 config_ready
=config_ready
,
65 recovery_action
=recovery_action
,
66 data_storetype
=data_storetype
,
69 plugin_directory
= ClassProperty('./usr/lib/rift/plugins/rwnsmtasklet')
70 plugin_name
= ClassProperty('rwnsmtasklet')
73 class VnsTasklet(rift
.vcs
.core
.Tasklet
):
75 This class represents a network services manager tasklet.
78 def __init__(self
, name
='virtual-network-service', uid
=None,
80 recovery_action
=core
.RecoveryType
.FAILCRITICAL
.value
,
81 data_storetype
=core
.DataStore
.NOSTORE
.value
,
84 Creates a VnsTasklet object.
87 name - the name of the tasklet
88 uid - a unique identifier
90 super(VnsTasklet
, self
).__init
__(name
=name
, uid
=uid
,
91 config_ready
=config_ready
,
92 recovery_action
=recovery_action
,
93 data_storetype
=data_storetype
,
96 plugin_directory
= ClassProperty('./usr/lib/rift/plugins/rwvnstasklet')
97 plugin_name
= ClassProperty('rwvnstasklet')
100 class VnfmTasklet(rift
.vcs
.core
.Tasklet
):
102 This class represents a virtual network function manager tasklet.
105 def __init__(self
, name
='virtual-network-function-manager', uid
=None,
107 recovery_action
=core
.RecoveryType
.FAILCRITICAL
.value
,
108 data_storetype
=core
.DataStore
.NOSTORE
.value
,
111 Creates a VnfmTasklet object.
114 name - the name of the tasklet
115 uid - a unique identifier
117 super(VnfmTasklet
, self
).__init
__(name
=name
, uid
=uid
,
118 config_ready
=config_ready
,
119 recovery_action
=recovery_action
,
120 data_storetype
=data_storetype
,
123 plugin_directory
= ClassProperty('./usr/lib/rift/plugins/rwvnfmtasklet')
124 plugin_name
= ClassProperty('rwvnfmtasklet')
127 class ResMgrTasklet(rift
.vcs
.core
.Tasklet
):
129 This class represents a Resource Manager tasklet.
132 def __init__(self
, name
='Resource-Manager', uid
=None,
134 recovery_action
=core
.RecoveryType
.FAILCRITICAL
.value
,
135 data_storetype
=core
.DataStore
.NOSTORE
.value
,
138 Creates a ResMgrTasklet object.
141 name - the name of the tasklet
142 uid - a unique identifier
144 super(ResMgrTasklet
, self
).__init
__(name
=name
, uid
=uid
,
145 config_ready
=config_ready
,
146 recovery_action
=recovery_action
,
147 data_storetype
=data_storetype
,
150 plugin_directory
= ClassProperty('./usr/lib/rift/plugins/rwresmgrtasklet')
151 plugin_name
= ClassProperty('rwresmgrtasklet')
154 class ImageMgrTasklet(rift
.vcs
.core
.Tasklet
):
156 This class represents a Image Manager tasklet.
159 def __init__(self
, name
='Image-Manager', uid
=None,
161 recovery_action
=core
.RecoveryType
.FAILCRITICAL
.value
,
162 data_storetype
=core
.DataStore
.NOSTORE
.value
,
165 Creates a Image Manager Tasklet object.
168 name - the name of the tasklet
169 uid - a unique identifier
171 super(ImageMgrTasklet
, self
).__init
__(
173 config_ready
=config_ready
,
174 recovery_action
=recovery_action
,
175 data_storetype
=data_storetype
,
178 plugin_directory
= ClassProperty('./usr/lib/rift/plugins/rwimagemgrtasklet')
179 plugin_name
= ClassProperty('rwimagemgrtasklet')
182 class MonitorTasklet(rift
.vcs
.core
.Tasklet
):
184 This class represents a tasklet that is used to monitor NFVI metrics.
187 def __init__(self
, name
='nfvi-metrics-monitor', uid
=None,
189 recovery_action
=core
.RecoveryType
.FAILCRITICAL
.value
,
190 data_storetype
=core
.DataStore
.NOSTORE
.value
,
193 Creates a MonitorTasklet object.
196 name - the name of the tasklet
197 uid - a unique identifier
200 super(MonitorTasklet
, self
).__init
__(name
=name
, uid
=uid
,
201 config_ready
=config_ready
,
202 recovery_action
=recovery_action
,
203 data_storetype
=data_storetype
,
206 plugin_directory
= ClassProperty('./usr/lib/rift/plugins/rwmonitor')
207 plugin_name
= ClassProperty('rwmonitor')
209 class RedisServer(rift
.vcs
.NativeProcess
):
210 def __init__(self
, name
="RW.Redis.Server",
212 recovery_action
=core
.RecoveryType
.FAILCRITICAL
.value
,
213 data_storetype
=core
.DataStore
.NOSTORE
.value
,
215 super(RedisServer
, self
).__init
__(
217 exe
="/usr/bin/redis-server",
218 config_ready
=config_ready
,
219 recovery_action
=recovery_action
,
220 data_storetype
=data_storetype
,
225 return "./usr/bin/active_redis.conf --port 9999"
228 class MonitoringParameterTasklet(rift
.vcs
.core
.Tasklet
):
230 This class represents a tasklet that is used to generate monitoring
234 def __init__(self
, name
='Monitoring-Parameter', uid
=None,
236 recovery_action
=core
.RecoveryType
.FAILCRITICAL
.value
,
237 data_storetype
=core
.DataStore
.NOSTORE
.value
,
240 Creates a MonitoringParameterTasklet object.
243 name - the name of the tasklet
244 uid - a unique identifier
247 super(MonitoringParameterTasklet
, self
).__init
__(name
=name
, uid
=uid
,
248 config_ready
=config_ready
,
249 recovery_action
=recovery_action
,
250 data_storetype
=data_storetype
,
253 plugin_directory
= ClassProperty('./usr/lib/rift/plugins/rwmonparam')
254 plugin_name
= ClassProperty('rwmonparam')
257 class AutoscalerTasklet(rift
.vcs
.core
.Tasklet
):
259 This class represents a tasklet that is used to generate monitoring
263 def __init__(self
, name
='Autoscaler', uid
=None,
265 recovery_action
=core
.RecoveryType
.FAILCRITICAL
.value
,
266 data_storetype
=core
.DataStore
.NOSTORE
.value
,
269 Creates a MonitoringParameterTasklet object.
272 name - the name of the tasklet
273 uid - a unique identifier
276 super(AutoscalerTasklet
, self
).__init
__(name
=name
, uid
=uid
,
277 config_ready
=config_ready
,
278 recovery_action
=recovery_action
,
279 data_storetype
=data_storetype
,
282 plugin_directory
= ClassProperty('./usr/lib/rift/plugins/rwautoscaler')
283 plugin_name
= ClassProperty('rwautoscaler')
286 def get_ui_ssl_args():
287 """Returns the SSL parameter string for launchpad UI processes"""
290 use_ssl
, certfile_path
, keyfile_path
= certs
.get_bootstrap_cert_and_key()
291 except certs
.BootstrapSslMissingException
:
292 logger
.error('No bootstrap certificates found. Disabling UI SSL')
295 # If we're not using SSL, no SSL arguments are necessary
299 return "--enable-https --keyfile-path=%s --certfile-path=%s" % (keyfile_path
, certfile_path
)
302 class UIServer(rift
.vcs
.NativeProcess
):
303 def __init__(self
, name
="RW.MC.UI",
305 recovery_action
=core
.RecoveryType
.FAILCRITICAL
.value
,
306 data_storetype
=core
.DataStore
.NOSTORE
.value
,
308 super(UIServer
, self
).__init
__(
310 exe
="./usr/share/rw.ui/skyquake/scripts/launch_ui.sh",
311 config_ready
=config_ready
,
312 recovery_action
=recovery_action
,
313 data_storetype
=data_storetype
,
318 return get_ui_ssl_args()
320 class ConfigManagerTasklet(rift
.vcs
.core
.Tasklet
):
322 This class represents a Resource Manager tasklet.
325 def __init__(self
, name
='Configuration-Manager', uid
=None,
327 recovery_action
=core
.RecoveryType
.FAILCRITICAL
.value
,
328 data_storetype
=core
.DataStore
.NOSTORE
.value
,
331 Creates a ConfigManagerTasklet object.
334 name - the name of the tasklet
335 uid - a unique identifier
337 super(ConfigManagerTasklet
, self
).__init
__(name
=name
, uid
=uid
,
338 config_ready
=config_ready
,
339 recovery_action
=recovery_action
,
340 data_storetype
=data_storetype
,
343 plugin_directory
= ClassProperty('./usr/lib/rift/plugins/rwconmantasklet')
344 plugin_name
= ClassProperty('rwconmantasklet')
346 class GlanceServer(rift
.vcs
.NativeProcess
):
347 def __init__(self
, name
="glance-image-catalog",
349 recovery_action
=core
.RecoveryType
.FAILCRITICAL
.value
,
350 data_storetype
=core
.DataStore
.NOSTORE
.value
,
352 super(GlanceServer
, self
).__init
__(
354 exe
="./usr/bin/glance_start_wrapper",
355 config_ready
=config_ready
,
356 recovery_action
=recovery_action
,
357 data_storetype
=data_storetype
,
362 return "./etc/glance"
365 class Demo(rift
.vcs
.demo
.Demo
):
366 def __init__(self
, no_ui
=False, ha_mode
=None, mgmt_ip_list
=[], test_name
=None):
368 ConfigManagerTasklet(),
370 rift
.vcs
.DtsRouterTasklet(),
371 rift
.vcs
.MsgBrokerTasklet(),
372 rift
.vcs
.RestPortForwardTasklet(),
373 rift
.vcs
.RestconfTasklet(),
375 rift
.vcs
.uAgentTasklet(),
376 rift
.vcs
.Launchpad(),
381 rift
.vcs
.DtsRouterTasklet(),
382 rift
.vcs
.MsgBrokerTasklet(),
385 datastore
= core
.DataStore
.BDB
.value
387 procs
.append(RedisServer())
388 datastore
= core
.DataStore
.REDIS
.value
391 procs
.append(UIServer())
394 VnfmTasklet(recovery_action
=core
.RecoveryType
.RESTART
.value
, data_storetype
=datastore
),
395 VnsTasklet(recovery_action
=core
.RecoveryType
.RESTART
.value
, data_storetype
=datastore
),
396 MonitorTasklet(recovery_action
=core
.RecoveryType
.RESTART
.value
, data_storetype
=datastore
),
397 MonitoringParameterTasklet(recovery_action
=core
.RecoveryType
.RESTART
.value
, data_storetype
=datastore
),
398 NsmTasklet(recovery_action
=core
.RecoveryType
.RESTART
.value
, data_storetype
=datastore
),
399 ResMgrTasklet(recovery_action
=core
.RecoveryType
.RESTART
.value
, data_storetype
=datastore
),
400 ImageMgrTasklet(recovery_action
=core
.RecoveryType
.RESTART
.value
, data_storetype
=datastore
),
401 AutoscalerTasklet(recovery_action
=core
.RecoveryType
.RESTART
.value
, data_storetype
=datastore
),
404 if not mgmt_ip_list
or len(mgmt_ip_list
) == 0:
405 mgmt_ip_list
.append("127.0.0.1")
407 colony
= rift
.vcs
.core
.Colony(name
='top', uid
=1)
409 lead_lp_vm
= rift
.vcs
.VirtualMachine(
410 name
='vm-launchpad-1',
413 restart_procs
=restart_procs
,
415 lead_lp_vm
.leader
= True
416 colony
.append(lead_lp_vm
)
419 stby_lp_vm
= rift
.vcs
.VirtualMachine(
420 name
='launchpad-vm-2',
425 # WA to Agent mode_active flag reset
426 stby_lp_vm
.add_tasklet(rift
.vcs
.uAgentTasklet(), mode_active
=False)
427 colony
.append(stby_lp_vm
)
429 sysinfo
= rift
.vcs
.SystemInfo(
431 zookeeper
=rift
.vcs
.manifest
.RaZookeeper(master_ip
=mgmt_ip_list
[0]),
434 multi_dtsrouter
=True,
435 mgmt_ip_list
=mgmt_ip_list
,
439 super(Demo
, self
).__init
__(
440 # Construct the system. This system consists of 1 cluster in 1
441 # colony. The master cluster houses CLI and management VMs
444 # Define the generic portmap.
447 # Define a mapping from the placeholder logical names to the real
448 # port names for each of the different modes supported by this demo.
456 # Define the connectivity between logical port names.
461 def main(argv
=sys
.argv
[1:]):
462 logging
.basicConfig(format
='%(asctime)-15s %(levelname)s %(message)s')
464 # Create a parser which includes all generic demo arguments
465 parser
= rift
.vcs
.demo
.DemoArgParser()
466 parser
.add_argument("--no-ui", action
='store_true')
467 args
= parser
.parse_args(argv
)
469 # Disable loading any kernel modules for the launchpad VM
470 # since it doesn't need it and it will fail within containers
471 os
.environ
["NO_KERNEL_MODS"] = "1"
474 cleanup_dir_name
= None
475 if os
.environ
["INSTALLDIR"] in ["/", "/home/rift", "/home/rift/.install",
476 "/usr/rift/build/fc20_debug/install/usr/rift", "/usr/rift"]:
477 cleanup_dir_name
= os
.environ
["INSTALLDIR"] + "/var/rift/"
479 if args
.test_name
and not cleanup_dir_name
:
480 cleanup_dir_name
= "find {rift_install}/var/rift -name '*{pattern}*' -type d".format( \
481 rift_install
=os
.environ
['RIFT_INSTALL'],
482 pattern
= args
.test_name
)
484 cleanup_dir_name
= subprocess
.check_output(cleanup_dir_name
, shell
=True)
485 cleanup_dir_name
= cleanup_dir_name
[:-1].decode("utf-8") + "/"
486 except Exception as e
:
487 print ("Directory not found exception occurred. Probably running for first time")
488 print ("Zookeper cleanup cmd = {}".format(cleanup_dir_name
))
490 if not cleanup_dir_name
:
491 cleanup_dir_name
= os
.environ
["INSTALLDIR"] + "/"
493 # Remove the persistent Redis data
495 for f
in os
.listdir(cleanup_dir_name
):
496 if f
.endswith(".aof") or f
.endswith(".rdb"):
497 os
.remove(os
.path
.join(cleanup_dir_name
, f
))
499 # Remove the persistant DTS recovery files
500 for f
in os
.listdir(cleanup_dir_name
):
501 if f
.endswith(".db"):
502 os
.remove(os
.path
.join(cleanup_dir_name
, f
))
504 shutil
.rmtree(os
.path
.join(cleanup_dir_name
, "zk/server-1"))
505 shutil
.rmtree(os
.path
.join(os
.environ
["INSTALLDIR"], "var/rift/tmp*"))
506 except FileNotFoundError
as e
:
508 except Exception as e
:
509 print ("Error while cleanup: {}".format(str(e
)))
511 ha_mode
= args
.ha_mode
512 mgmt_ip_list
= [] if not args
.mgmt_ip_list
else args
.mgmt_ip_list
514 #load demo info and create Demo object
515 demo
= Demo(args
.no_ui
, ha_mode
, mgmt_ip_list
, args
.test_name
)
517 # Create the prepared system from the demo
518 system
= rift
.vcs
.demo
.prepared_system_from_demo_and_args(demo
, args
,
519 northbound_listing
="cli_launchpad_schema_listing.txt",
520 netconf_trace_override
=True)
522 confd_ip
= socket
.gethostbyname(socket
.gethostname())
523 # TODO: This need to be changed when launchpad starts running on multiple VMs
524 rift
.vcs
.logger
.configure_sink(config_file
=None, confd_ip
="127.0.0.1")
526 # Start the prepared system
530 if __name__
== "__main__":
531 resource
.setrlimit(resource
.RLIMIT_CORE
, (resource
.RLIM_INFINITY
, resource
.RLIM_INFINITY
) )
534 except rift
.vcs
.demo
.ReservationError
:
535 print("ERROR: unable to retrieve a list of IP addresses from the reservation system")
537 except rift
.vcs
.demo
.MissingModeError
:
538 print("ERROR: you need to provide a mode to run the script")
541 os
.system("stty sane")