Example #1
0
 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)
Example #2
0
 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",
     )
Example #3
0
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
Example #4
0
 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",
     )
Example #5
0
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)
Example #6
0
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)