def setup_cloud_environment(self): execute_command(command=self.__create_cloud_command(), working_directory=os.curdir, environment_variables=None, executor=None, logger=self._logger, livestream=True)
def __wait_for_service(self, service_name): # Waits until the given service has at least one instance which is running and ready. logging.info("Waiting for {name_} service.".format(name_=service_name)) script_path = os.path.join( os.getcwd(), "utilities/docker_service_wait_until_running.sh") script_args = "--service {service_} --host {host_}" utils.execute_command( command=script_path + " " + script_args.format( service_=service_name, host_=self.host, ), working_directory=os.curdir, environment_variables=None, executor="StackDeploy", )
def call_operator(individual): # Write individual to file in input_path. # https://docs.python-guide.org/scenarios/serialization/#json-file-nested-data input_path = utils.get_custom_setting("input_path") with open(input_path, "x") as f: json.dump(individual, f, sort_keys=True, cls=IndividualEncoder) # Call operator with provided command. command_str = utils.get_custom_setting("command") logging.info( "Retrieved command string: {cmdstr_}".format(cmdstr_=command_str)) fixed_command = "" marker_open = 0 marker_close = -1 idx = 0 for char in command_str: if char == "{": marker_open = idx elif char == "}": prev_marker = marker_close + 1 # initially 0 fixed_command += command_str[prev_marker:marker_open] marker_close = idx key = command_str[marker_open + 1:marker_close] value = utils.get_property(key) if type(value) is list: param_string = ",".join(value) else: param_string = str(value) fixed_command += param_string idx += 1 logging.info("Calling operator with: {cmd_}".format(cmd_=fixed_command)) logs, error = utils.execute_command( command=fixed_command, working_directory=None, environment_variables=None, executor="AGENT", livestream=True, ) logging.info(logs) # Retrieve individual from file in output_path. # https://docs.python-guide.org/scenarios/serialization/#json-file-nested-data output_path = utils.get_custom_setting("output_path") with open(output_path, "r") as f: ind_dict = json.load(f) resulting_individual = Individual(ind_dict["solution"], ind_dict["fitness"]) logging.info("Reading from output file: {}".format(resulting_individual)) # Delete the files that were created to ensure fresh start. os.remove(input_path) os.remove(output_path) return resulting_individual
def __update_service_with_configs(self, configs, service_name, container_config=None): # Updates the given service with the new configs. logging.info( "Updating {name_} with docker configs.".format(name_=service_name)) config_param = self.__prepare_array_as_script_param( configs, container_config) script_path = os.path.join( os.getcwd(), "utilities/docker_service_update_configs.sh") script_args = "--service {service_} --host {host_} --configs {confs_}" utils.execute_command( command=script_path + " " + script_args.format( service_=service_name, host_=self.host, confs_=config_param, ), working_directory=os.curdir, environment_variables=None, executor="StackDeploy", )
def create(ctx, provider_name, configuration_file_path): """ Create and setup the cloud environment. :param provider_name: the cloud provider name. :type provider_name: str :param configuration_file_path: the path to the cloud configuration file. :type configuration_file_path: str :param ctx: the click cli context, automatically passed by cli. """ # Retrieves the configuration. configuration = get_configuration(configuration_file_path) # Recognizes the correct driver. driver = get_driver(provider_name, ctx.meta["orchestrator"], configuration, logger) click.echo(driver.name) # Creates the cloud environment. driver.setup_cloud_environment() # Saves the manager's IP address. manager_host, error = utils.execute_command( command="docker-machine ip dockermaster", working_directory=os.curdir, environment_variables=None, executor=None, logger=logger, ) if error: logger.error(error) click.echo(error) else: if not ctx.meta["master_host"]: click.echo( "Setting master host {host_}".format(host_=manager_host)) else: click.echo("Updating config for master host to {host_}".format( host_=manager_host)) ctx.meta["master_host"] = manager_host # Updates the meta context storage file. utils.store_context(ctx.meta, CLIENT_CLI_CONTEXT_FILE)
def init(ctx, port, cert_path): """ Initialize the PGA Manager. :param port: the external port on the host to map to the container. Defaults to the current meta config. See :func:`config` for reference. :type port: int :param cert_path: the path to a folder containing your SSL certificates. Can also be set in the context, see 'config certificates'. :type cert_path: str :param ctx: the click cli context, automatically passed by cli. """ # Retrieves the certificates path. if not cert_path: if not ctx.meta["cert_path"]: raise Exception( "No certificates path defined! You can define it by providing it as an argument " "or by explicitly setting it with command 'client config cert-path'. " "Type 'client config cert-path --help' for more details.") cert_path = ctx.meta["cert_path"] else: ctx.meta["cert_path"] = cert_path click.echo("Updating config for certificates path to {path_}".format( path_=ctx.meta["cert_path"])) # Sets the port if not provided. if not port: port = ctx.meta["master_port"] # Ensures there is a known host to connect to. if not ctx.meta["master_host"]: raise Exception( "No master host defined! You can define it by creating the cloud environment " "or by explicitly setting it with command 'client config master-host'. " "Type 'client config master-host --help' for more details.") # Initializes the PGA manager via the selected orchestrator. if ctx.meta["orchestrator"] == "docker": # Creates a docker client to issue docker commands via SSL connection. docker_client = docker_utils.get_docker_client( cert_path=cert_path, host_addr=ctx.meta["master_host"], host_port=2376 # default docker port; Note above https://docs.docker.com/engine/security/https/#secure-by-default ) # Creates docker secrets for sharing the SSL certificates. ssl_ca_path = os.path.join(cert_path, "ca.pem") ssl_cert_path = os.path.join(cert_path, "cert.pem") ssl_key_path = os.path.join(cert_path, "key.pem") try: ssl_ca_file = open(ssl_ca_path, mode="rb") ssl_ca_content = ssl_ca_file.read() ssl_ca_file.close() ssl_cert_file = open(ssl_cert_path, mode="rb") ssl_cert_content = ssl_cert_file.read() ssl_cert_file.close() ssl_key_file = open(ssl_key_path, mode="rb") ssl_key_content = ssl_key_file.read() ssl_key_file.close() docker_client.secrets.create( name="SSL_CA_PEM", data=ssl_ca_content, labels={"PGAcloud": "PGA-Management"}, ) docker_client.secrets.create( name="SSL_CERT_PEM", data=ssl_cert_content, labels={"PGAcloud": "PGA-Management"}, ) docker_client.secrets.create( name="SSL_KEY_PEM", data=ssl_key_content, labels={"PGAcloud": "PGA-Management"}, ) except Exception as e: traceback.print_exc() logger.error(traceback.format_exc()) # Creates the manager service on the host. management_network = docker_utils.get_management_network() click.echo("--- Creating manager service.") docker_client.services.create( image="jluech/pga-cloud-manager", name="manager", hostname="manager", networks=[management_network.name], endpoint_spec={ "Ports": [ { "Protocol": "tcp", "PublishedPort": port, "TargetPort": 5000 }, ], }, mounts=["/var/run/docker.sock:/var/run/docker.sock:rw" ], # enable docker commands inside manager container ) # Updates the service with the new secrets. click.echo("--- Updating with SSL secrets.") script_path = os.path.join( os.getcwd(), "utilities/docker_service_update_secrets.sh") script_args = "--certs {certs_} --host {host_}" utils.execute_command(command=script_path + " " + script_args.format( certs_=cert_path, host_=ctx.meta["master_host"]), working_directory=os.curdir, environment_variables=None, executor=None, logger=logger, livestream=True) # Waits for WAIT_FOR_CONFIRMATION_DURATION seconds or until manager service is running. service_running = False service_status = "NOK" exceeding = False troubled = False duration = 0.0 start = time.perf_counter() while not service_running and duration < WAIT_FOR_CONFIRMATION_DURATION: try: response = http.get(url="http://{addr_}:{port_}/status".format( addr_=ctx.meta["master_host"], port_=ctx.meta["master_port"]), verify=False) service_status = response.content.decode("utf-8") except: pass finally: service_running = service_status == "OK" if duration >= WAIT_FOR_CONFIRMATION_EXCEEDING and not exceeding: click.echo("This is taking longer than usual...") exceeding = True # only print this once if duration >= WAIT_FOR_CONFIRMATION_TROUBLED and not troubled: click.echo("Oh come on! You can do it...") troubled = True # only print this once time.sleep(WAIT_FOR_CONFIRMATION_SLEEP) # avoid network overhead duration = time.perf_counter() - start if duration >= WAIT_FOR_CONFIRMATION_DURATION: click.echo( "Exceeded waiting time of {time_} seconds. It may have encountered an error. " "Please verify or try again shortly.".format( time_=WAIT_FOR_CONFIRMATION_DURATION)) else: click.echo("Successfully created manager service.") else: click.echo("kubernetes orchestrator not implemented yet." ) # TODO 202: implement kubernetes orchestrator # Updates the meta context storage file. utils.store_context(ctx.meta, CLIENT_CLI_CONTEXT_FILE)