#!/usr/bin/env python3 import argparse import logging import os import sys import gi gi.require_version('RwcalYang', '1.0') gi.require_version('RwCal', '1.0') gi.require_version('RwLog', '1.0') import rift.cal.server as cal_server import rift.cal.client as cal_client import rift.cal.utils as cal_utils import rift.rwcal.cloudsim.lxc as lxc import rift.rwcal.cloudsim.lvm as lvm import rift.rwcal.cloudsim.shell as shell from prettytable import PrettyTable START_PARSER = "start" STOP_PARSER = "stop" CLEAN_PARSER = "clean" FCLEAN_PARSER = "force-clean" IMAGE_PARSER = "image-create" STATUS_PARSER = "status" class CloudsimOperations(cal_utils.CloudSimCalMixin): def __init__(self, args): super().__init__() self.log = cal_utils.Logger( daemon_mode=False, log_name="Parser", log_level=logging.getLevelName(args.log_level)).logger self.args = args self.operations = cal_server.CloudsimServerOperations(self.log) self.client = cal_client.CloudsimClient(self.log) self._cal, self._account = None, None @property def log_file(self): return cal_utils.Logger.LOG_FILE @cal_utils.check_and_create_bridge def start_server(self): self.operations.start_server(foreground=self.args.foreground) @cal_utils.check_and_create_bridge def stop_server(self): self.operations.stop_server() @cal_utils.check_and_create_bridge def clean_resources(self): """Clean all resource using rest APIs. """ self.operations.clean_server(images=self.args.all) @cal_utils.check_and_create_bridge def upload_image(self): """Onboard image to cloudsim server.""" self.client.upload_image(self.args.location, name=self.args.name) def force_clean_resources(self): """Force clean up all resource. """ self.log.info("Cleaning up logs") shell.command("rm -f {}".format(self.log_file)) self.log.info("Cleaning up PID file") shell.command("rm -f {}".format(self.operations.PID_FILE)) try: self.log.info("Purging LXC resources") for container in lxc.containers(): lxc.stop(container) for container in lxc.containers(): lxc.destroy(container) lvm.destroy('rift') except shell.ProcessError: self.log.exception("Unable to purge resources. Trying a force clean now.") lxc.force_clean() @cal_utils.check_and_create_bridge def show_status(self): cld_tbl = PrettyTable(['PID', 'Status', 'Log file']) pid = self.operations.pid if pid: cld_tbl.add_row([pid, "RUNNING", self.log_file]) else: cld_tbl.add_row(["-", "STOPPED", self.log_file]) print ("Cloudsim server:") print (cld_tbl) if not pid: return # Images img_tbl = PrettyTable(['ID', 'Name', 'Format']) vlink_tbl = PrettyTable([ 'ID', 'Name', 'Bridge Name', 'State', 'Subnet', 'Ports', "IPs"]) vdu_tbl = PrettyTable([ 'ID', 'Name', 'LXC Name', 'IP', 'State', 'Ports', "VLink ID"]) images = self.client.images if images: for image in images: img_tbl.add_row([image.id, image.name, image.disk_format]) print ("Images:") print (img_tbl) vlinks = self.client.vlinks if vlinks: for vlink in vlinks: ports, ips = [], [] for cp in vlink.connection_points: ports.append("{} ({})".format(cp.name, cp.connection_point_id)) ips.append(cp.ip_address) vlink_tbl.add_row([ vlink.virtual_link_id, vlink.name, vlink.name[:15], vlink.state, vlink.subnet, "\n".join(ports), "\n".join(ips)]) print ("Vlink:") print (vlink_tbl) lxc_to_ip = lxc.ls_info() def get_lxc_name(ip): for lxc_name, ips in lxc_to_ip.items(): if str(ip) in ips: return lxc_name return "" vdus = self.client.vdus if vdus: for vdu in vdus: ports, links = [], [] for cp in vdu.connection_points: ports.append("{} ({})".format(cp.name, cp.ip_address)) links.append(cp.virtual_link_id) vdu_tbl.add_row([ vdu.vdu_id, vdu.name, get_lxc_name(vdu.public_ip), vdu.public_ip, vdu.state, "\n".join(ports), "\n".join(links)]) print ("VDU:") print (vdu_tbl) def parse(arguments): parser = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter) parser.add_argument( '--log-level', '-l', default="WARNING", type=str, choices=["INFO", "DEBUG", "WARNING", "ERROR"], help="Set log level, defaults to warning and above.") subparsers = parser.add_subparsers() start_parser = subparsers.add_parser(START_PARSER, help="Start the server") start_parser.add_argument( '--foreground', "-f", help="Run the server in the foreground. The logs are sent to console.", default=False, action="store_true") start_parser.set_defaults(which=START_PARSER) stop_parser = subparsers.add_parser(STOP_PARSER, help="Stop the server") stop_parser.set_defaults(which=STOP_PARSER) clean_parser = subparsers.add_parser( CLEAN_PARSER, help="Clean LXC resources. By default all resources except " + \ "images are cleared.") clean_parser.add_argument( '--all', '-a', help="Cleans up all resources including images", default=False, action="store_true") clean_parser.set_defaults(which=CLEAN_PARSER) fclean_parser = subparsers.add_parser( FCLEAN_PARSER, help="Force clean all lxc resources") fclean_parser.set_defaults(which=FCLEAN_PARSER) image_parser = subparsers.add_parser(IMAGE_PARSER, help="Upload images") image_parser.add_argument( '--name', '-n', help="(Optional) Name of the image") image_parser.add_argument( '--location', '-l', help="Image location. If name is not specified the basename of " + \ "the image path is used.", required=True) image_parser.set_defaults(which=IMAGE_PARSER) show_parser = subparsers.add_parser( STATUS_PARSER, help="Shows the current status of LXC") show_parser.set_defaults(which=STATUS_PARSER) args = parser.parse_args(arguments) return args def main(args): args = parse(args) operations = CloudsimOperations(args) if args.which == START_PARSER: operations.start_server() elif args.which == STOP_PARSER: operations.stop_server() elif args.which == FCLEAN_PARSER: operations.force_clean_resources() elif args.which == CLEAN_PARSER: operations.clean_resources() elif args.which == IMAGE_PARSER: operations.upload_image() elif args.which == STATUS_PARSER: operations.show_status() if __name__ == "__main__": main(sys.argv[1:])