diff --git a/cloud-image/create_image.py b/cloud-image/create_image.py index d980a2ba..b7b1fec1 100644 --- a/cloud-image/create_image.py +++ b/cloud-image/create_image.py @@ -101,8 +101,9 @@ def main(): startup_script) passwd = uuid.uuid4().hex instance.change_password(passwd) - # wait for the password change to be processed - sleep(POLL_SEC) + # wait for the password change to be processed. Continuing while + # a password change is processing will cause image creation to fail. + sleep(POLL_SEC*6) env.host_string = str(instance.accessIPv4) env.user = "root" diff --git a/cloud-image/script_template b/cloud-image/script_template index e7c5ad56..c59fbbe6 100644 --- a/cloud-image/script_template +++ b/cloud-image/script_template @@ -11,9 +11,7 @@ mkdir -p /opt/gns3 pushd /opt/gns3 git clone --branch ${git_branch} ${git_url} cd gns3-server -pip3 install tornado -pip3 install pyzmq -pip3 install jsonschema +pip3 install -r dev-requirements.txt python3 ./setup.py install ${rc_local} diff --git a/gns3dms/main.py b/gns3dms/main.py index bad64a44..1e86cbac 100644 --- a/gns3dms/main.py +++ b/gns3dms/main.py @@ -24,7 +24,7 @@ # number has been incremented) """ -Monitors communication with the GNS3 client via tmp file. Will terminate the instance if +Monitors communication with the GNS3 client via tmp file. Will terminate the instance if communication is lost. """ @@ -62,7 +62,7 @@ sys.path.append(EXTRA_LIB) import daemon -my_daemon = None +my_daemon = None usage = """ USAGE: %s @@ -73,14 +73,15 @@ Options: -v, --verbose Enable verbose logging -h, --help Display this menu :) - --cloud_api_key Rackspace API key + --cloud_api_key Rackspace API key --cloud_user_name --instance_id ID of the Rackspace instance to terminate - - --deadtime How long in seconds can the communication lose exist before we - shutdown this instance. - Default: + --region Region of instance + + --deadtime How long in seconds can the communication lose exist before we + shutdown this instance. + Default: Example --deadtime=3600 (60 minutes) --check-interval Defaults to --deadtime, used for debugging @@ -111,6 +112,7 @@ def parse_cmd_line(argv): "cloud_user_name=", "cloud_api_key=", "instance_id=", + "region=", "deadtime=", "init-wait=", "check-interval=", @@ -130,6 +132,7 @@ def parse_cmd_line(argv): cmd_line_option_list["cloud_user_name"] = None cmd_line_option_list["cloud_api_key"] = None cmd_line_option_list["instance_id"] = None + cmd_line_option_list["region"] = None cmd_line_option_list["deadtime"] = 60 * 60 #minutes cmd_line_option_list["check-interval"] = None cmd_line_option_list["init-wait"] = 5 * 60 @@ -162,6 +165,8 @@ def parse_cmd_line(argv): cmd_line_option_list["cloud_api_key"] = val elif (opt in ("--instance_id")): cmd_line_option_list["instance_id"] = val + elif (opt in ("--region")): + cmd_line_option_list["region"] = val elif (opt in ("--deadtime")): cmd_line_option_list["deadtime"] = int(val) elif (opt in ("--check-interval")): @@ -200,6 +205,12 @@ def parse_cmd_line(argv): print(usage) sys.exit(2) + if cmd_line_option_list["region"] is None: + print("You need to specify a region") + print(usage) + sys.exit(2) + + return cmd_line_option_list def get_gns3secrets(cmd_line_option_list): @@ -208,19 +219,19 @@ def get_gns3secrets(cmd_line_option_list): """ gns3secret_paths = [ - os.path.expanduser("~/"), + os.path.join(os.path.expanduser("~"), '.config', 'GNS3'), SCRIPT_PATH, ] config = configparser.ConfigParser() for gns3secret_path in gns3secret_paths: - gns3secret_file = "%s/.gns3secrets.conf" % (gns3secret_path) + gns3secret_file = "%s/cloud.conf" % (gns3secret_path) if os.path.isfile(gns3secret_file): config.read(gns3secret_file) try: - for key, value in config.items("Cloud"): + for key, value in config.items("CLOUD_SERVER"): cmd_line_option_list[key] = value.strip() except configparser.NoSectionError: pass @@ -256,7 +267,7 @@ def set_logging(cmd_options): ) syslog_hndlr.setFormatter(sys_formatter) - + log.setLevel(log_level) log.addHandler(console_log) log.addHandler(syslog_hndlr) @@ -308,7 +319,7 @@ def monitor_loop(options): if delta.seconds > options["deadtime"]: log.warning("Deadtime exceeded, terminating instance ...") - #Terminate involes many layers of HTTP / API calls, lots of + #Terminate involes many layers of HTTP / API calls, lots of #different errors types could occur here. try: rksp = Rackspace(options) @@ -341,8 +352,8 @@ def main(): log.info("Received shutdown signal") options["shutdown"] = True - - pid_file = "%s/.gns3ias.pid" % (expanduser("~")) + + pid_file = "%s/.gns3dms.pid" % (expanduser("~")) if options["shutdown"]: send_shutdown(pid_file) diff --git a/gns3dms/modules/daemon.py b/gns3dms/modules/daemon.py index d10d8d2e..c7245335 100644 --- a/gns3dms/modules/daemon.py +++ b/gns3dms/modules/daemon.py @@ -7,38 +7,38 @@ class daemon: Usage: subclass the daemon class and override the run() method.""" - def __init__(self, pidfile, options): + def __init__(self, pidfile, options): self.pidfile = pidfile self.options = options - + def daemonize(self): """Deamonize class. UNIX double fork mechanism.""" - try: - pid = os.fork() + try: + pid = os.fork() if pid > 0: # exit first parent - sys.exit(0) - except OSError as err: + sys.exit(0) + except OSError as err: sys.stderr.write('fork #1 failed: {0}\n'.format(err)) sys.exit(1) - + # decouple from parent environment - os.chdir('/') - os.setsid() - os.umask(0) - + os.chdir('/') + os.setsid() + os.umask(0) + # do second fork - try: - pid = os.fork() + try: + pid = os.fork() if pid > 0: # exit from second parent - sys.exit(0) - except OSError as err: + sys.exit(0) + except OSError as err: sys.stderr.write('fork #2 failed: {0}\n'.format(err)) - sys.exit(1) - + sys.exit(1) + # redirect standard file descriptors sys.stdout.flush() sys.stderr.flush() @@ -49,17 +49,26 @@ class daemon: os.dup2(si.fileno(), sys.stdin.fileno()) os.dup2(so.fileno(), sys.stdout.fileno()) os.dup2(se.fileno(), sys.stderr.fileno()) - + # write pidfile atexit.register(self.delpid) pid = str(os.getpid()) with open(self.pidfile,'w+') as f: f.write(pid + '\n') - + def delpid(self): os.remove(self.pidfile) + def check_pid(self, pid): + """ Check For the existence of a unix pid. """ + try: + os.kill(pid, 0) + except OSError: + return False + else: + return True + def start(self): """Start the daemon.""" @@ -70,13 +79,19 @@ class daemon: pid = int(pf.read().strip()) except IOError: pid = None - + if pid: - message = "pidfile {0} already exist. " + \ - "Daemon already running?\n" + pid_exist = self.check_pid(pid) + + if pid_exist: + message = "Already running: %s\n" % (pid) + sys.stderr.write(message) + sys.exit(1) + else: + message = "pidfile {0} already exist. " + \ + "but process is dead\n" sys.stderr.write(message.format(self.pidfile)) - sys.exit(1) - + # Start the daemon self.daemonize() self.run() @@ -90,14 +105,14 @@ class daemon: pid = int(pf.read().strip()) except IOError: pid = None - + if not pid: message = "pidfile {0} does not exist. " + \ "Daemon not running?\n" sys.stderr.write(message.format(self.pidfile)) return # not an error in a restart - # Try killing the daemon process + # Try killing the daemon process try: while 1: os.kill(pid, signal.SIGTERM) @@ -118,6 +133,6 @@ class daemon: def run(self): """You should override this method when you subclass Daemon. - - It will be called after the process has been daemonized by + + It will be called after the process has been daemonized by start() or restart().""" diff --git a/gns3dms/modules/rackspace_cloud.py b/gns3dms/modules/rackspace_cloud.py index 4b1d6c0f..00059047 100644 --- a/gns3dms/modules/rackspace_cloud.py +++ b/gns3dms/modules/rackspace_cloud.py @@ -41,6 +41,7 @@ class Rackspace(object): self.authenticated = False self.hostname = socket.gethostname() self.instance_id = options["instance_id"] + self.region = options["region"] log.debug("Authenticating with Rackspace") log.debug("My hostname: %s" % (self.hostname)) @@ -51,16 +52,17 @@ class Rackspace(object): if self.authenticated == False: log.critical("Not authenticated against rackspace!!!!") - for region_dict in self.rksp.list_regions(): - region_k, region_v = region_dict.popitem() - log.debug("Checking region: %s" % (region_k)) - self.rksp.set_region(region_v) - for server in self.rksp.list_instances(): - log.debug("Checking server: %s" % (server.name)) - if server.name.lower() == self.hostname.lower() and server.id == self.instance_id: - log.info("Found matching instance: %s" % (server.id)) - log.info("Startup id: %s" % (self.instance_id)) - return server + for region in self.rksp.list_regions(): + log.debug("Rackspace regions: %s" % (region)) + + log.debug("Checking region: %s" % (self.region)) + self.rksp.set_region(self.region) + for server in self.rksp.list_instances(): + log.debug("Checking server: %s" % (server.name)) + if server.name.lower() == self.hostname.lower() and server.id == self.instance_id: + log.info("Found matching instance: %s" % (server.id)) + log.info("Startup id: %s" % (self.instance_id)) + return server def terminate(self): server = self._find_my_instance() diff --git a/gns3server/cert_utils/create_cert.sh b/gns3server/cert_utils/create_cert.sh index 57427088..92f6edfb 100755 --- a/gns3server/cert_utils/create_cert.sh +++ b/gns3server/cert_utils/create_cert.sh @@ -62,13 +62,13 @@ C=CA ST=Alberta O=GNS3 localityName=Calgary -commonName=gns3server.localdomain.com +commonName=$DOMAIN organizationalUnitName=GNS3Server emailAddress=gns3cert@gns3.com " # Generate the server private key -openssl genrsa -aes256 -out $DST_DIR/$DOMAIN.key -passout env:PASSPHRASE 2048 +openssl genrsa -aes256 -out $DOMAIN.key -passout env:PASSPHRASE 2048 fail_if_error $? #openssl rsa -outform der -in $DOMAIN.pem -out $DOMAIN.key -passin env:PASSPHRASE @@ -93,4 +93,7 @@ fail_if_error $? openssl x509 -req -days 3650 -in $DOMAIN.csr -signkey $DOMAIN.key -out $DOMAIN.crt fail_if_error $? +echo "${DST_DIR}${DOMAIN}.key" +echo "${DST_DIR}${DOMAIN}.crt" + cd $OLD_DIR \ No newline at end of file diff --git a/gns3server/config.py b/gns3server/config.py index cd2d07a1..caa9c0d4 100644 --- a/gns3server/config.py +++ b/gns3server/config.py @@ -62,16 +62,21 @@ class Config(object): # 5: server.conf in the current working directory home = os.path.expanduser("~") + self._cloud_config = os.path.join(home, ".config", appname, "cloud.conf") filename = "server.conf" self._files = [os.path.join(home, ".config", appname, filename), os.path.join(home, ".config", appname + ".conf"), os.path.join("/etc/xdg", appname, filename), os.path.join("/etc/xdg", appname + ".conf"), - filename] + filename, + self._cloud_config] self._config = configparser.ConfigParser() self.read_config() + def list_cloud_config_file(self): + return self._cloud_config + def read_config(self): """ Read the configuration files. diff --git a/gns3server/handlers/auth_handler.py b/gns3server/handlers/auth_handler.py index f136ab02..3d8cf331 100644 --- a/gns3server/handlers/auth_handler.py +++ b/gns3server/handlers/auth_handler.py @@ -29,6 +29,9 @@ log = logging.getLogger(__name__) class GNS3BaseHandler(tornado.web.RequestHandler): def get_current_user(self): + if 'required_user' not in self.settings: + return "FakeUser" + user = self.get_secure_cookie("user") if not user: return None @@ -38,6 +41,9 @@ class GNS3BaseHandler(tornado.web.RequestHandler): class GNS3WebSocketBaseHandler(tornado.websocket.WebSocketHandler): def get_current_user(self): + if 'required_user' not in self.settings: + return "FakeUser" + user = self.get_secure_cookie("user") if not user: return None diff --git a/gns3server/handlers/version_handler.py b/gns3server/handlers/version_handler.py index 3b338bd2..ec83d4ce 100644 --- a/gns3server/handlers/version_handler.py +++ b/gns3server/handlers/version_handler.py @@ -22,7 +22,6 @@ from ..version import __version__ class VersionHandler(GNS3BaseHandler): - @tornado.web.authenticated def get(self): response = {'version': __version__} self.write(response) diff --git a/gns3server/modules/__init__.py b/gns3server/modules/__init__.py index dd628589..b451a69b 100644 --- a/gns3server/modules/__init__.py +++ b/gns3server/modules/__init__.py @@ -17,12 +17,13 @@ import sys from .base import IModule +from .deadman import DeadMan from .dynamips import Dynamips +from .qemu import Qemu from .vpcs import VPCS from .virtualbox import VirtualBox -from .qemu import Qemu -MODULES = [Dynamips, VPCS, VirtualBox, Qemu] +MODULES = [DeadMan, Dynamips, VPCS, VirtualBox, Qemu] if sys.platform.startswith("linux"): # IOU runs only on Linux diff --git a/gns3server/modules/deadman/__init__.py b/gns3server/modules/deadman/__init__.py index ab81e971..c5619c96 100644 --- a/gns3server/modules/deadman/__init__.py +++ b/gns3server/modules/deadman/__init__.py @@ -30,7 +30,7 @@ from gns3server.config import Config import logging log = logging.getLogger(__name__) -class DeadMan(): +class DeadMan(IModule): """ DeadMan module. @@ -54,8 +54,18 @@ class DeadMan(): if 'heartbeat_file' in kwargs: self._heartbeat_file = kwargs['heartbeat_file'] + self._is_enabled = False + try: + cloud_config = Config.instance().get_section_config("CLOUD_SERVER") + instance_id = cloud_config["instance_id"] + cloud_user_name = cloud_config["cloud_user_name"] + cloud_api_key = cloud_config["cloud_api_key"] + self._is_enabled = True + except KeyError: + log.critical("Missing cloud.conf - disabling Deadman Switch") self._deadman_process = None + self.heartbeat() self.start() def _start_deadman_process(self): @@ -63,14 +73,19 @@ class DeadMan(): Start a subprocess and return the object """ + #gnsserver gets configuration options from cloud.conf. This is where + #the client adds specific cloud information. + #gns3dms also reads in cloud.conf. That is why we don't need to specific + #all the command line arguments here. + cmd = [] - cmd.append("gns3dms") - cmd.append("--file %s" % (self._heartbeat_file)) + cmd.append("--file") + cmd.append("%s" % (self._heartbeat_file)) cmd.append("--background") - log.debug("Deadman: Running %s"%(cmd)) + log.info("Deadman: Running command: %s"%(cmd)) - process = subprocess.Popen(cmd, shell=False) + process = subprocess.Popen(cmd, stderr=subprocess.STDOUT, shell=False) return process def _stop_deadman_process(self): @@ -82,7 +97,7 @@ class DeadMan(): cmd.append("gns3dms") cmd.append("-k") - log.debug("Deadman: Running %s"%(cmd)) + log.info("Deadman: Running command: %s"%(cmd)) process = subprocess.Popen(cmd, shell=False) return process @@ -111,8 +126,9 @@ class DeadMan(): Start the deadman process on the server """ - self._deadman_process = self._start_deadman_process() - log.debug("Deadman: Process is starting") + if self._is_enabled: + self._deadman_process = self._start_deadman_process() + log.debug("Deadman: Process is starting") @IModule.route("deadman.reset") def reset(self, request=None): @@ -137,7 +153,7 @@ class DeadMan(): now = time.time() with open(self._heartbeat_file, 'w') as heartbeat_file: - heartbeat_file.write(now) + heartbeat_file.write(str(now)) heartbeat_file.close() log.debug("Deadman: heartbeat_file updated: %s %s" % ( @@ -145,5 +161,4 @@ class DeadMan(): now, )) - self.start() \ No newline at end of file diff --git a/gns3server/server.py b/gns3server/server.py index 275123ad..42f8ec88 100644 --- a/gns3server/server.py +++ b/gns3server/server.py @@ -141,37 +141,41 @@ class Server(object): instance.start() # starts the new process - def _get_cert_info(self): - """ - Finds the cert and key file needed for SSL - """ - - home = expanduser("~") - ssl_dir = "%s/.conf/GNS3Certs/" % (home) - log.debug("Looking for SSL certs in: %s" % (ssl_dir)) - - keyfile = "%s/gns3server.localdomain.com.key" % (ssl_dir) - certfile = "%s/gns3server.localdomain.com.crt" % (ssl_dir) - - if os.path.isfile(keyfile) and os.path.isfile(certfile): - return { "certfile" : certfile, - "keyfile" : keyfile, - } - def run(self): """ Starts the Tornado web server and ZeroMQ server. """ - # FIXME: debug mode! settings = { "debug":True, "cookie_secret": base64.b64encode(uuid.uuid4().bytes + uuid.uuid4().bytes), "login_url": "/login", - "required_user" : "test123", - "required_pass" : "test456", } + ssl_options = {} + + try: + cloud_config = Config.instance().get_section_config("CLOUD_SERVER") + + cloud_settings = { + + "required_user" : cloud_config['WEB_USERNAME'], + "required_pass" : cloud_config['WEB_PASSWORD'], + } + + settings.update(cloud_settings) + + if cloud_config["SSL_ENABLED"] == "yes": + ssl_options = { + "certfile" : cloud_config["SSL_CRT"], + "keyfile" : cloud_config["SSL_KEY"], + } + + log.info("Certs found - starting in SSL mode") + except KeyError: + log.info("Missing cloud.conf - disabling HTTP auth and SSL") + + router = self._create_zmq_router() # Add our JSON-RPC Websocket handler to Tornado self.handlers.extend([(r"/", JSONRPCWebSocket, dict(zmq_router=router))]) @@ -191,11 +195,8 @@ class Server(object): zmq.zmq_version())) kwargs = {"address": self._host} - ssl_options = self._get_cert_info() - if ssl_options: - log.info("Certs found - starting in SSL mode") - kwargs['ssl_options'] = ssl_options + kwargs["ssl_options"] = ssl_options if parse_version(tornado.version) >= parse_version("3.1"): kwargs["max_buffer_size"] = 524288000 # 500 MB file upload limit diff --git a/gns3server/start_server.py b/gns3server/start_server.py new file mode 100644 index 00000000..279ccbc3 --- /dev/null +++ b/gns3server/start_server.py @@ -0,0 +1,242 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2013 GNS3 Technologies Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# __version__ is a human-readable version number. + +# __version_info__ is a four-tuple for programmatic comparison. The first +# three numbers are the components of the version number. The fourth +# is zero for an official release, positive for a development branch, +# or negative for a release candidate or beta (after the base version +# number has been incremented) + +""" +Startup script for GNS3 Server Cloud Instance +""" + +import os +import sys +import configparser +import getopt +import datetime +import signal +from logging.handlers import * +from os.path import expanduser +from gns3server.config import Config +import ast +import subprocess +import uuid + +SCRIPT_NAME = os.path.basename(__file__) + +#Is the full path when used as an import +SCRIPT_PATH = os.path.dirname(__file__) + +if not SCRIPT_PATH: + SCRIPT_PATH = os.path.join(os.path.dirname(os.path.abspath( + sys.argv[0]))) + + +LOG_NAME = "gns3-startup" +log = None + +usage = """ +USAGE: %s + +Options: + + -d, --debug Enable debugging + -v, --verbose Enable verbose logging + -h, --help Display this menu :) + + --data Python dict of data to be written to the config file: + " { 'gns3' : 'Is AWESOME' } " + +""" % (SCRIPT_NAME) + +# Parse cmd line options +def parse_cmd_line(argv): + """ + Parse command line arguments + + argv: Pass in cmd line arguments + """ + + short_args = "dvh" + long_args = ("debug", + "verbose", + "help", + "data=", + ) + try: + opts, extra_opts = getopt.getopt(argv[1:], short_args, long_args) + except getopt.GetoptError as e: + print("Unrecognized command line option or missing required argument: %s" %(e)) + print(usage) + sys.exit(2) + + cmd_line_option_list = {} + cmd_line_option_list["debug"] = False + cmd_line_option_list["verbose"] = True + cmd_line_option_list["data"] = None + + if sys.platform == "linux": + cmd_line_option_list['syslog'] = "/dev/log" + elif sys.platform == "osx": + cmd_line_option_list['syslog'] = "/var/run/syslog" + else: + cmd_line_option_list['syslog'] = ('localhost',514) + + for opt, val in opts: + if (opt in ("-h", "--help")): + print(usage) + sys.exit(0) + elif (opt in ("-d", "--debug")): + cmd_line_option_list["debug"] = True + elif (opt in ("-v", "--verbose")): + cmd_line_option_list["verbose"] = True + elif (opt in ("--data")): + cmd_line_option_list["data"] = ast.literal_eval(val) + + return cmd_line_option_list + + +def set_logging(cmd_options): + """ + Setup logging and format output for console and syslog + + Syslog is using the KERN facility + """ + log = logging.getLogger("%s" % (LOG_NAME)) + log_level = logging.INFO + log_level_console = logging.WARNING + + if cmd_options['verbose'] == True: + log_level_console = logging.INFO + + if cmd_options['debug'] == True: + log_level_console = logging.DEBUG + log_level = logging.DEBUG + + formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') + sys_formatter = logging.Formatter('%(name)s - %(levelname)s - %(message)s') + + console_log = logging.StreamHandler() + console_log.setLevel(log_level_console) + console_log.setFormatter(formatter) + + syslog_hndlr = SysLogHandler( + address=cmd_options['syslog'], + facility=SysLogHandler.LOG_KERN + ) + + syslog_hndlr.setFormatter(sys_formatter) + + log.setLevel(log_level) + log.addHandler(console_log) + log.addHandler(syslog_hndlr) + + return log + +def _generate_certs(): + cmd = [] + cmd.append("%s/cert_utils/create_cert.sh" % (SCRIPT_PATH)) + + log.debug("Generating certs ...") + output_raw = subprocess.check_output(cmd, shell=False, + stderr=subprocess.STDOUT) + + output_str = output_raw.decode("utf-8") + output = output_str.strip().split("\n") + log.debug(output) + return (output[-2], output[-1]) + +def _start_gns3server(): + cmd = [] + cmd.append("gns3server") + + log.info("Starting gns3server ...") + subprocess.Popen(cmd, shell=False) + + +def main(): + + global log + options = parse_cmd_line(sys.argv) + log = set_logging(options) + + def _shutdown(signalnum=None, frame=None): + """ + Handles the SIGINT and SIGTERM event, inside of main so it has access to + the log vars. + """ + + log.info("Received shutdown signal") + sys.exit(0) + + + # Setup signal to catch Control-C / SIGINT and SIGTERM + signal.signal(signal.SIGINT, _shutdown) + signal.signal(signal.SIGTERM, _shutdown) + + client_data = {} + + config = Config.instance() + cfg = config.list_cloud_config_file() + cfg_path = os.path.dirname(cfg) + + try: + os.makedirs(cfg_path) + except FileExistsError: + pass + + (server_key, server_crt) = _generate_certs() + + cloud_config = configparser.ConfigParser() + cloud_config['CLOUD_SERVER'] = {} + + if options['data']: + cloud_config['CLOUD_SERVER'] = options['data'] + + cloud_config['CLOUD_SERVER']['SSL_KEY'] = server_key + cloud_config['CLOUD_SERVER']['SSL_CRT'] = server_crt + cloud_config['CLOUD_SERVER']['SSL_ENABLED'] = 'yes' + cloud_config['CLOUD_SERVER']['WEB_USERNAME'] = str(uuid.uuid4()).upper()[0:8] + cloud_config['CLOUD_SERVER']['WEB_PASSWORD'] = str(uuid.uuid4()).upper()[0:8] + + with open(cfg, 'w') as cloud_config_file: + cloud_config.write(cloud_config_file) + + cloud_config_file.close() + + _start_gns3server() + + with open(server_crt, 'r') as cert_file: + cert_data = cert_file.readlines() + + cert_file.close() + + client_data['SSL_CRT_FILE'] = server_crt + client_data['SSL_CRT'] = cert_data + client_data['WEB_USERNAME'] = cloud_config['CLOUD_SERVER']['WEB_USERNAME'] + client_data['WEB_PASSWORD'] = cloud_config['CLOUD_SERVER']['WEB_PASSWORD'] + + print(client_data) + + +if __name__ == "__main__": + result = main() + sys.exit(result) diff --git a/requirements.txt b/requirements.txt index 2cf31cd5..3e267f9a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -5,4 +5,5 @@ jsonschema pycurl python-dateutil apache-libcloud +requests