blob: c9e471e84ec7609b7ffe4c23c69f5713e2f05850 [file] [log] [blame]
#!/usr/bin/env python3
#
# Copyright 2016 RIFT.IO Inc
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import logging
import os
import resource
import socket
import sys
import subprocess
import shlex
import shutil
import netifaces
from rift.rwlib.util import certs
import rift.rwcal.cloudsim
import rift.rwcal.cloudsim.net
import rift.vcs
import rift.vcs.core as core
import rift.vcs.demo
import rift.vcs.vms
import rift.rwcal.cloudsim
import rift.rwcal.cloudsim.net
from rift.vcs.ext import ClassProperty
logger = logging.getLogger(__name__)
class NsmTasklet(rift.vcs.core.Tasklet):
"""
This class represents a network services manager tasklet.
"""
def __init__(self, name='network-services-manager', uid=None,
config_ready=True,
recovery_action=core.RecoveryType.FAILCRITICAL.value,
data_storetype=core.DataStore.NOSTORE.value,
):
"""
Creates a NsmTasklet object.
Arguments:
name - the name of the tasklet
uid - a unique identifier
"""
super(NsmTasklet, self).__init__(name=name, uid=uid,
config_ready=config_ready,
recovery_action=recovery_action,
data_storetype=data_storetype,
)
plugin_directory = ClassProperty('./usr/lib/rift/plugins/rwnsmtasklet')
plugin_name = ClassProperty('rwnsmtasklet')
class VnsTasklet(rift.vcs.core.Tasklet):
"""
This class represents a network services manager tasklet.
"""
def __init__(self, name='virtual-network-service', uid=None,
config_ready=True,
recovery_action=core.RecoveryType.FAILCRITICAL.value,
data_storetype=core.DataStore.NOSTORE.value,
):
"""
Creates a VnsTasklet object.
Arguments:
name - the name of the tasklet
uid - a unique identifier
"""
super(VnsTasklet, self).__init__(name=name, uid=uid,
config_ready=config_ready,
recovery_action=recovery_action,
data_storetype=data_storetype,
)
plugin_directory = ClassProperty('./usr/lib/rift/plugins/rwvnstasklet')
plugin_name = ClassProperty('rwvnstasklet')
class VnfmTasklet(rift.vcs.core.Tasklet):
"""
This class represents a virtual network function manager tasklet.
"""
def __init__(self, name='virtual-network-function-manager', uid=None,
config_ready=True,
recovery_action=core.RecoveryType.FAILCRITICAL.value,
data_storetype=core.DataStore.NOSTORE.value,
):
"""
Creates a VnfmTasklet object.
Arguments:
name - the name of the tasklet
uid - a unique identifier
"""
super(VnfmTasklet, self).__init__(name=name, uid=uid,
config_ready=config_ready,
recovery_action=recovery_action,
data_storetype=data_storetype,
)
plugin_directory = ClassProperty('./usr/lib/rift/plugins/rwvnfmtasklet')
plugin_name = ClassProperty('rwvnfmtasklet')
class ResMgrTasklet(rift.vcs.core.Tasklet):
"""
This class represents a Resource Manager tasklet.
"""
def __init__(self, name='Resource-Manager', uid=None,
config_ready=True,
recovery_action=core.RecoveryType.FAILCRITICAL.value,
data_storetype=core.DataStore.NOSTORE.value,
):
"""
Creates a ResMgrTasklet object.
Arguments:
name - the name of the tasklet
uid - a unique identifier
"""
super(ResMgrTasklet, self).__init__(name=name, uid=uid,
config_ready=config_ready,
recovery_action=recovery_action,
data_storetype=data_storetype,
)
plugin_directory = ClassProperty('./usr/lib/rift/plugins/rwresmgrtasklet')
plugin_name = ClassProperty('rwresmgrtasklet')
class ImageMgrTasklet(rift.vcs.core.Tasklet):
"""
This class represents a Image Manager tasklet.
"""
def __init__(self, name='Image-Manager', uid=None,
config_ready=True,
recovery_action=core.RecoveryType.FAILCRITICAL.value,
data_storetype=core.DataStore.NOSTORE.value,
):
"""
Creates a Image Manager Tasklet object.
Arguments:
name - the name of the tasklet
uid - a unique identifier
"""
super(ImageMgrTasklet, self).__init__(
name=name, uid=uid,
config_ready=config_ready,
recovery_action=recovery_action,
data_storetype=data_storetype,
)
plugin_directory = ClassProperty('./usr/lib/rift/plugins/rwimagemgrtasklet')
plugin_name = ClassProperty('rwimagemgrtasklet')
class MonitorTasklet(rift.vcs.core.Tasklet):
"""
This class represents a tasklet that is used to monitor NFVI metrics.
"""
def __init__(self, name='nfvi-metrics-monitor', uid=None,
config_ready=True,
recovery_action=core.RecoveryType.FAILCRITICAL.value,
data_storetype=core.DataStore.NOSTORE.value,
):
"""
Creates a MonitorTasklet object.
Arguments:
name - the name of the tasklet
uid - a unique identifier
"""
super(MonitorTasklet, self).__init__(name=name, uid=uid,
config_ready=config_ready,
recovery_action=recovery_action,
data_storetype=data_storetype,
)
plugin_directory = ClassProperty('./usr/lib/rift/plugins/rwmonitor')
plugin_name = ClassProperty('rwmonitor')
class RedisServer(rift.vcs.NativeProcess):
def __init__(self, name="RW.Redis.Server",
config_ready=True,
recovery_action=core.RecoveryType.FAILCRITICAL.value,
data_storetype=core.DataStore.NOSTORE.value,
):
super(RedisServer, self).__init__(
name=name,
exe="/usr/bin/redis-server",
config_ready=config_ready,
recovery_action=recovery_action,
data_storetype=data_storetype,
)
@property
def args(self):
return "./usr/bin/active_redis.conf --port 9999"
class MonitoringParameterTasklet(rift.vcs.core.Tasklet):
"""
This class represents a tasklet that is used to generate monitoring
parameters.
"""
def __init__(self, name='Monitoring-Parameter', uid=None,
config_ready=True,
recovery_action=core.RecoveryType.FAILCRITICAL.value,
data_storetype=core.DataStore.NOSTORE.value,
):
"""
Creates a MonitoringParameterTasklet object.
Arguments:
name - the name of the tasklet
uid - a unique identifier
"""
super(MonitoringParameterTasklet, self).__init__(name=name, uid=uid,
config_ready=config_ready,
recovery_action=recovery_action,
data_storetype=data_storetype,
)
plugin_directory = ClassProperty('./usr/lib/rift/plugins/rwmonparam')
plugin_name = ClassProperty('rwmonparam')
class AutoscalerTasklet(rift.vcs.core.Tasklet):
"""
This class represents a tasklet that is used to generate monitoring
parameters.
"""
def __init__(self, name='Autoscaler', uid=None,
config_ready=True,
recovery_action=core.RecoveryType.FAILCRITICAL.value,
data_storetype=core.DataStore.NOSTORE.value,
):
"""
Creates a MonitoringParameterTasklet object.
Arguments:
name - the name of the tasklet
uid - a unique identifier
"""
super(AutoscalerTasklet, self).__init__(name=name, uid=uid,
config_ready=config_ready,
recovery_action=recovery_action,
data_storetype=data_storetype,
)
plugin_directory = ClassProperty('./usr/lib/rift/plugins/rwautoscaler')
plugin_name = ClassProperty('rwautoscaler')
class StagingManagerTasklet(rift.vcs.core.Tasklet):
"""
A class that provide a simple staging area for all tasklets
"""
def __init__(self, name='StagingManager', uid=None,
config_ready=True,
recovery_action=core.RecoveryType.FAILCRITICAL.value,
data_storetype=core.DataStore.NOSTORE.value,
):
"""
Creates a StagingMangerTasklet object.
Arguments:
name - the name of the tasklet
uid - a unique identifier
"""
super(StagingManagerTasklet, self).__init__(name=name, uid=uid,
config_ready=config_ready,
recovery_action=recovery_action,
data_storetype=data_storetype,
)
plugin_directory = ClassProperty('./usr/lib/rift/plugins/rwstagingmgr')
plugin_name = ClassProperty('rwstagingmgr')
def get_ui_ssl_args():
"""Returns the SSL parameter string for launchpad UI processes"""
try:
use_ssl, certfile_path, keyfile_path = certs.get_bootstrap_cert_and_key()
except certs.BootstrapSslMissingException:
logger.error('No bootstrap certificates found. Disabling UI SSL')
use_ssl = False
# If we're not using SSL, no SSL arguments are necessary
if not use_ssl:
return ""
return "--enable-https --keyfile-path=%s --certfile-path=%s" % (keyfile_path, certfile_path)
class UIServer(rift.vcs.NativeProcess):
def __init__(self, name="RW.MC.UI",
config_ready=True,
recovery_action=core.RecoveryType.FAILCRITICAL.value,
data_storetype=core.DataStore.NOSTORE.value,
):
super(UIServer, self).__init__(
name=name,
exe="./usr/share/rw.ui/skyquake/scripts/launch_ui.sh",
config_ready=config_ready,
recovery_action=recovery_action,
data_storetype=data_storetype,
)
@property
def args(self):
return get_ui_ssl_args()
class ConfigManagerTasklet(rift.vcs.core.Tasklet):
"""
This class represents a Resource Manager tasklet.
"""
def __init__(self, name='Configuration-Manager', uid=None,
config_ready=True,
recovery_action=core.RecoveryType.FAILCRITICAL.value,
data_storetype=core.DataStore.NOSTORE.value,
):
"""
Creates a ConfigManagerTasklet object.
Arguments:
name - the name of the tasklet
uid - a unique identifier
"""
super(ConfigManagerTasklet, self).__init__(name=name, uid=uid,
config_ready=config_ready,
recovery_action=recovery_action,
data_storetype=data_storetype,
)
plugin_directory = ClassProperty('./usr/lib/rift/plugins/rwconmantasklet')
plugin_name = ClassProperty('rwconmantasklet')
class PackageManagerTasklet(rift.vcs.core.Tasklet):
"""
This class represents a Resource Manager tasklet.
"""
def __init__(self, name='Package-Manager', uid=None,
config_ready=True,
recovery_action=core.RecoveryType.FAILCRITICAL.value,
data_storetype=core.DataStore.NOSTORE.value,
):
"""
Creates a PackageManager object.
Arguments:
name - the name of the tasklet
uid - a unique identifier
"""
super(PackageManagerTasklet, self).__init__(name=name, uid=uid,
config_ready=config_ready,
recovery_action=recovery_action,
data_storetype=data_storetype,
)
plugin_directory = ClassProperty('./usr/lib/rift/plugins/rwpkgmgr')
plugin_name = ClassProperty('rwpkgmgr')
class GlanceServer(rift.vcs.NativeProcess):
def __init__(self, name="glance-image-catalog",
config_ready=True,
recovery_action=core.RecoveryType.FAILCRITICAL.value,
data_storetype=core.DataStore.NOSTORE.value,
):
super(GlanceServer, self).__init__(
name=name,
exe="./usr/bin/glance_start_wrapper",
config_ready=config_ready,
recovery_action=recovery_action,
data_storetype=data_storetype,
)
@property
def args(self):
return "./etc/glance"
class Demo(rift.vcs.demo.Demo):
def __init__(self, no_ui=False, ha_mode=None, mgmt_ip_list=[], test_name=None):
procs = [
ConfigManagerTasklet(),
GlanceServer(),
rift.vcs.DtsRouterTasklet(),
rift.vcs.MsgBrokerTasklet(),
rift.vcs.RestPortForwardTasklet(),
rift.vcs.RestconfTasklet(),
rift.vcs.RiftCli(),
rift.vcs.uAgentTasklet(),
rift.vcs.Launchpad(),
]
standby_procs = [
RedisServer(),
rift.vcs.DtsRouterTasklet(),
rift.vcs.MsgBrokerTasklet(),
]
datastore = core.DataStore.BDB.value
if ha_mode:
procs.append(RedisServer())
datastore = core.DataStore.REDIS.value
if not no_ui:
procs.append(UIServer())
restart_procs = [
VnfmTasklet(recovery_action=core.RecoveryType.RESTART.value, data_storetype=datastore),
VnsTasklet(recovery_action=core.RecoveryType.RESTART.value, data_storetype=datastore),
MonitorTasklet(recovery_action=core.RecoveryType.RESTART.value, data_storetype=datastore),
MonitoringParameterTasklet(recovery_action=core.RecoveryType.RESTART.value, data_storetype=datastore),
NsmTasklet(recovery_action=core.RecoveryType.RESTART.value, data_storetype=datastore),
ResMgrTasklet(recovery_action=core.RecoveryType.RESTART.value, data_storetype=datastore),
ImageMgrTasklet(recovery_action=core.RecoveryType.RESTART.value, data_storetype=datastore),
AutoscalerTasklet(recovery_action=core.RecoveryType.RESTART.value, data_storetype=datastore),
PackageManagerTasklet(recovery_action=core.RecoveryType.RESTART.value, data_storetype=datastore),
StagingManagerTasklet(recovery_action=core.RecoveryType.RESTART.value, data_storetype=datastore),
]
if not mgmt_ip_list or len(mgmt_ip_list) == 0:
mgmt_ip_list.append("127.0.0.1")
colony = rift.vcs.core.Colony(name='top', uid=1)
lead_lp_vm = rift.vcs.VirtualMachine(
name='vm-launchpad-1',
ip=mgmt_ip_list[0],
procs=procs,
restart_procs=restart_procs,
)
lead_lp_vm.leader = True
colony.append(lead_lp_vm)
if ha_mode:
stby_lp_vm = rift.vcs.VirtualMachine(
name='launchpad-vm-2',
ip=mgmt_ip_list[1],
procs=standby_procs,
start=False,
)
# WA to Agent mode_active flag reset
stby_lp_vm.add_tasklet(rift.vcs.uAgentTasklet(), mode_active=False)
colony.append(stby_lp_vm)
sysinfo = rift.vcs.SystemInfo(
mode='ethsim',
zookeeper=rift.vcs.manifest.RaZookeeper(master_ip=mgmt_ip_list[0]),
colonies=[colony],
multi_broker=True,
multi_dtsrouter=True,
mgmt_ip_list=mgmt_ip_list,
test_name=test_name,
)
super(Demo, self).__init__(
# Construct the system. This system consists of 1 cluster in 1
# colony. The master cluster houses CLI and management VMs
sysinfo = sysinfo,
# Define the generic portmap.
port_map = {},
# Define a mapping from the placeholder logical names to the real
# port names for each of the different modes supported by this demo.
port_names = {
'ethsim': {
},
'pci': {
}
},
# Define the connectivity between logical port names.
port_groups = {},
)
def main(argv=sys.argv[1:]):
logging.basicConfig(format='%(asctime)-15s %(levelname)s %(message)s')
# Create a parser which includes all generic demo arguments
parser = rift.vcs.demo.DemoArgParser()
parser.add_argument("--no-ui", action='store_true')
args = parser.parse_args(argv)
# Disable loading any kernel modules for the launchpad VM
# since it doesn't need it and it will fail within containers
os.environ["NO_KERNEL_MODS"] = "1"
cleanup_dir_name = None
if os.environ["INSTALLDIR"] in ["/", "/home/rift", "/home/rift/.install",
"/usr/rift/build/fc20_debug/install/usr/rift", "/usr/rift"]:
cleanup_dir_name = os.environ["INSTALLDIR"] + "/var/rift/"
if args.test_name and not cleanup_dir_name:
cleanup_dir_name = "find {rift_install}/var/rift -name '*{pattern}*' -type d".format( \
rift_install=os.environ['RIFT_INSTALL'],
pattern = args.test_name)
try:
cleanup_dir_name = subprocess.check_output(cleanup_dir_name, shell=True)
cleanup_dir_name = cleanup_dir_name[:-1].decode("utf-8") + "/"
except Exception as e:
print ("Directory not found exception occurred. Probably running for first time")
print ("Zookeper cleanup cmd = {}".format(cleanup_dir_name))
else:
if not cleanup_dir_name:
cleanup_dir_name = os.environ["INSTALLDIR"] + "/"
# Remove the persistent Redis data
try:
for f in os.listdir(cleanup_dir_name):
if f.endswith(".aof") or f.endswith(".rdb"):
os.remove(os.path.join(cleanup_dir_name, f))
# Remove the persistant DTS recovery files
for f in os.listdir(cleanup_dir_name):
if f.endswith(".db"):
os.remove(os.path.join(cleanup_dir_name, f))
shutil.rmtree(os.path.join(cleanup_dir_name, "zk/server-1"))
shutil.rmtree(os.path.join(os.environ["INSTALLDIR"], "var/rift/tmp*"))
except FileNotFoundError as e:
pass
except Exception as e:
print ("Error while cleanup: {}".format(str(e)))
ha_mode = args.ha_mode
mgmt_ip_list = [] if not args.mgmt_ip_list else args.mgmt_ip_list
#load demo info and create Demo object
demo = Demo(args.no_ui, ha_mode, mgmt_ip_list, args.test_name)
# Create the prepared system from the demo
system = rift.vcs.demo.prepared_system_from_demo_and_args(demo, args,
northbound_listing="cli_launchpad_schema_listing.txt",
netconf_trace_override=True)
confd_ip = socket.gethostbyname(socket.gethostname())
# TODO: This need to be changed when launchpad starts running on multiple VMs
rift.vcs.logger.configure_sink(config_file=None, confd_ip="127.0.0.1")
# Start the prepared system
system.start()
if __name__ == "__main__":
resource.setrlimit(resource.RLIMIT_CORE, (resource.RLIM_INFINITY, resource.RLIM_INFINITY) )
try:
main()
except rift.vcs.demo.ReservationError:
print("ERROR: unable to retrieve a list of IP addresses from the reservation system")
sys.exit(1)
except rift.vcs.demo.MissingModeError:
print("ERROR: you need to provide a mode to run the script")
sys.exit(1)
finally:
os.system("stty sane")