Example #1
0
 def _parse_and_validate_user_input_config_file(self, args):
     ip_type = EdgeConfigInputSources.FILE
     parser = EdgeConfigParserFactory.create_parser(ip_type, args)
     self.edge_config = parser.parse()
     EdgeHostPlatform.install_edge_by_config_file(self.edge_config,
                                                  args.config_file)
     return True
Example #2
0
    def _mount_certificates_into_agent_container(self):
        mnt_path = self._obtain_mount_path()
        if mnt_path is None:
            return
        container_name = self._edge_runtime_container_name

        # setup module volume with CA cert
        ca_cert_file = EdgeHostPlatform.get_root_ca_cert_file()
        module_vol_path = '{0}/{1}'.format(mnt_path,
                                           self._EDGE_MODULE_VOL_NAME)
        self._client.copy_file_to_volume(container_name,
                                         ca_cert_file['file_name'],
                                         module_vol_path,
                                         ca_cert_file['file_path'])

        # setup hub volume CA chain and Edge server certs
        ca_chain_cert_file = EdgeHostPlatform.get_ca_chain_cert_file()
        hub_cert_dict = EdgeHostPlatform.get_hub_cert_pfx_file()
        hub_vol_path = '{0}/{1}'.format(mnt_path, self._EDGE_HUB_VOL_NAME)
        self._client.copy_file_to_volume(container_name,
                                         ca_chain_cert_file['file_name'],
                                         hub_vol_path,
                                         ca_chain_cert_file['file_path'])
        self._client.copy_file_to_volume(container_name,
                                         hub_cert_dict['file_name'],
                                         hub_vol_path,
                                         hub_cert_dict['file_path'])
Example #3
0
    def execute_user_command(self):
        """This is the main function that implements the CLI.

        Overall flow:
        1. Read, validate and process the input arguments.
        2. Update configuration files on the host based on user input.
        3. Construct the deployment specific command object to execute the
           the user input command.
        4. Log any status, progress and errors along the way to stdout
        5. Return to caller with an error code.
            0 -- Success
            Non Zero -- Error
        """
        error_code = 1
        host = platform.system()
        if EdgeDefault.is_host_supported(host) is False:
            log.error('Unsupported host platform: %s.', host)
        elif EdgeHostPlatform.is_deployment_supported(EC.DEPLOYMENT_DOCKER) is False:
            log.error('Docker is not installed or is unavailable. Please ensure docker is installed and is up and running.')
        else:
            try:
                if self._process_cli_args():
                    self._execute_command()
                    error_code = 0
            except edgectl.errors.EdgeError:
                log.debug('Errors observed running %s command.', self._prog())

        if error_code != 0:
            log.error('Exiting with errors. Return code: %s', str(error_code))
        return error_code
Example #4
0
 def _parse_update_options(self, args):
     is_valid = self._parse_command_options_common(args)
     if is_valid:
         if args.image is not None:
             prior_image = self.edge_config.deployment_config.edge_image
             if prior_image != args.image:
                 try:
                     self.edge_config.deployment_config.edge_image = args.image
                 except ValueError as ex:
                     msg = 'Error setting --image data: {0}. {1}'.format(args.image, ex)
                     log.error(msg)
                     raise edgectl.errors.EdgeError(msg, ex)
                 EdgeHostPlatform.install_edge_by_json_data(self.edge_config, False)
                 config_file = EdgeHostPlatform.get_host_config_file_path()
                 log.info('The runtime configuration file %s was updated with' \
                          ' the new image: %s', config_file, args.image)
     return is_valid
Example #5
0
    def _parse_login_options(self, args):
        is_valid = self._parse_command_options_common(args)
        if is_valid:
            try:
                self.edge_config.deployment_config.add_registry(
                    args.address, args.username, args.password)
            except ValueError as ex:
                log.error('%s', str(ex))
                msg = EdgeUtils.sanitize_registry_data(args.address,
                                                       args.username,
                                                       args.password)
                log.error('Error setting login data: [%s].', msg)
                raise edgectl.errors.EdgeError('Error setting login data', ex)

            EdgeHostPlatform.install_edge_by_json_data(self.edge_config, False)
            config_file = EdgeHostPlatform.get_host_config_file_path()
            log.info('The runtime configuration file %s was updated with' \
                     ' the credentials for registry: %s', config_file, args.address)
        return is_valid
Example #6
0
 def _parse_installed_config_file_options(self, args):
     result = False
     ins_cfg_file_path = EdgeHostPlatform.get_host_config_file_path()
     if ins_cfg_file_path is None:
         log.error('Runtime has not been configured on this device.\nPlease run \'%s setup\' first.', EdgeCLI._prog())
     else:
         log.debug('Found config File: %s', ins_cfg_file_path)
         ip_type = EdgeConfigInputSources.FILE
         parser = EdgeConfigParserFactory.create_parser(ip_type, args)
         self.edge_config = parser.parse(ins_cfg_file_path)
         result = True
     return result
Example #7
0
    def _setup_certificates(self, env_dict, volume_dict):
        mnt_path = self._obtain_mount_path()
        if mnt_path is None:
            return

        # create volumes for mounting certs into hub and all other edge modules
        self._client.create_volume(self._EDGE_HUB_VOL_NAME)
        self._client.create_volume(self._EDGE_MODULE_VOL_NAME)

        # add volume mounts into edge agent
        hub_vol_path = '{0}/{1}'.format(mnt_path, self._EDGE_HUB_VOL_NAME)
        volume_dict[self._EDGE_HUB_VOL_NAME] = {
            'bind': hub_vol_path,
            'mode': 'rw'
        }
        module_vol_path = \
            '{0}/{1}'.format(mnt_path, self._EDGE_MODULE_VOL_NAME)
        volume_dict[self._EDGE_MODULE_VOL_NAME] = {
            'bind': module_vol_path,
            'mode': 'rw'
        }

        # setup env vars describing volume names and paths
        env_dict['EdgeHubVolumeName'] = self._EDGE_HUB_VOL_NAME
        env_dict['EdgeHubVolumePath'] = hub_vol_path
        env_dict['EdgeModuleVolumeName'] = self._EDGE_MODULE_VOL_NAME
        env_dict['EdgeModuleVolumePath'] = module_vol_path

        # setup env vars describing CA cert location for all edge modules
        ca_cert_file = EdgeHostPlatform.get_root_ca_cert_file()
        env_dict['EdgeModuleCACertificateFile'] = \
            '{0}/{1}'.format(module_vol_path, ca_cert_file['file_name'])

        # setup env vars describing CA cert location for all edge hub
        ca_chain_cert_file = EdgeHostPlatform.get_ca_chain_cert_file()
        env_dict['EdgeModuleHubServerCAChainCertificateFile'] = \
            '{0}/{1}'.format(hub_vol_path, ca_chain_cert_file['file_name'])
        hub_cert_dict = EdgeHostPlatform.get_hub_cert_pfx_file()
        env_dict['EdgeModuleHubServerCertificateFile'] = \
            '{0}/{1}'.format(hub_vol_path, hub_cert_dict['file_name'])
Example #8
0
    def _parse_setup_options(self, args):
        cmd = args.subparser_name
        log.debug('Command: ' + cmd)
        is_valid = False

        if args.config_file is not None:
            # we are using options specified in the config file
            try:
                is_valid = self._parse_and_validate_user_input_config_file(
                    args)
            except edgectl.errors.EdgeValueError as ex_value:
                log.error('Please check the configuration values in the config file' \
                          ' and re-run \'%s setup\'', EdgeCLI._prog())
                raise edgectl.errors.EdgeError(
                    'Error when parsing configuration data', ex_value)
            except edgectl.errors.EdgeFileParseError as ex_parse:
                log.error('Please check the configuration in config file: %s' \
                          ' and re-run \'%s setup\'', ex_parse.file_name, EdgeCLI._prog())
                raise edgectl.errors.EdgeError(
                    'Error when parsing configuration data', ex_parse)
        else:
            # we are using cli options, validate all the supplied args
            try:
                is_valid = self._parse_and_validate_user_input(args)
            except edgectl.errors.EdgeValueError as ex_value:
                log.error(
                    'Please fix any input values and re-run \'%s setup\'',
                    EdgeCLI._prog())
                raise edgectl.errors.EdgeError('Incorrect input options',
                                               ex_value)
            except edgectl.errors.EdgeFileParseError as ex_parse:
                log.critical(
                    'Please restore the config file or reinstall the %s utility.',
                    EdgeCLI._prog())
                raise edgectl.errors.EdgeError(
                    'Error when parsing configuration data', ex_parse)
            except edgectl.errors.EdgeFileAccessError as ex_access:
                if ex_access.file_name == EdgeDefault.get_default_settings_file_path(
                ):
                    log.critical(
                        'Please restore the config file or reinstall the %s utility.',
                        EdgeCLI._prog())
                raise edgectl.errors.EdgeError('Filesystem access errors',
                                               ex_access)
        if is_valid:
            config_file = EdgeHostPlatform.get_host_config_file_path()
            log.info('The runtime configuration file %s was updated with' \
                     ' the ''setup'' options.', config_file)
        return is_valid
Example #9
0
 def _check_prerequisites(self):
     is_error = True
     msg = ''
     if self._client.check_availability() is False:
         msg = 'Docker is unavailable'
     else:
         engine_os = self._client.get_os_type()
         engines = EdgeHostPlatform.get_supported_docker_engines()
         if engine_os.lower() not in engines:
             msg = 'Unsupported docker OS type: {0}'.format(engine_os)
         else:
             is_error = False
     if is_error is True:
         log.error(msg)
         raise EdgeDeploymentError(msg)
Example #10
0
    def create_command(command, edge_config):
        """ API to create an Edge command
        Args:
            command (str): Edge command name
            edge_config (obj): A valid instance of the edgectl.config.EdgeHostConfig

        Returns:
            Instance of edgectl.deployment.EdgeCommand

        Raises:
            edgectl.errors.EdgeValueError if the command or deployment type is unsupported
        """
        result = None
        if command is None:
            msg = 'Command cannot be None'
            log.error(msg)
            raise edgectl.errors.EdgeValueError(msg)

        if edge_config is None or isinstance(
                edge_config, edgectl.config.EdgeHostConfig) is False:
            msg = 'Invalid Edge config object'
            log.error(msg)
            raise edgectl.errors.EdgeValueError(msg)

        deployment = edge_config.deployment_type
        if command not in list(EdgeCommandFactory._supported_commands.keys()):
            msg = 'Unsupported command: ' + command
            log.error(msg)
            raise edgectl.errors.EdgeValueError(msg)
        else:
            if EdgeHostPlatform.is_deployment_supported(deployment):
                if deployment == EC.DEPLOYMENT_DOCKER:
                    deployment_cmd_obj = EdgeDeploymentCommandDocker(
                        edge_config)
                    result = EdgeCommandFactory._supported_commands[command](
                        deployment_cmd_obj)
            else:
                msg = 'IoT Edge deployment not supported: {0}'.format(
                    deployment)
                log.critical(msg)
                raise edgectl.errors.EdgeValueError(msg)

        return result
Example #11
0
    def _parse_data(self, data, config_file):
        try:
            config = EdgeHostConfig()
            config.schema_version = data[EC.SCHEMA_KEY]
            config.connection_string = data[EC.DEVICE_CONNECTION_STRING_KEY]

            edge_config_dir = None
            cfg_src = EdgeConfigDirInputSource.NONE
            if EC.CONFIG_DIR_KEY in list(data.keys()):
                edge_config_dir = data[EC.CONFIG_DIR_KEY]
                cfg_src = EdgeConfigDirInputSource.USER_PROVIDED

            cfg_dir_opt = EdgeHostPlatform.choose_platform_config_dir(edge_config_dir, cfg_src)
            config.config_dir = cfg_dir_opt[0]
            config.config_dir_source = cfg_dir_opt[1]

            config.home_dir = data[EC.HOMEDIR_KEY]
            config.hostname = data[EC.HOSTNAME_KEY]
            config.log_level = data[EC.EDGE_RUNTIME_LOG_LEVEL_KEY]

            if EC.UPSTREAM_PROTOCOL in list(data.keys()):
                config.upstream_protocol = data[EC.UPSTREAM_PROTOCOL]
            else:
                config.upstream_protocol = EdgeUpstreamProtocol.NONE

            # parse certificate settings
            certs_cfg_data = data[EC.SECURITY_KEY][EC.CERTS_KEY]
            security_option = certs_cfg_data[EC.CERTS_OPTION_KEY]
            subject_dict = {}
            if EC.CERTS_SUBJECT_KEY in list(certs_cfg_data.keys()):
                subject_dict = certs_cfg_data[EC.CERTS_SUBJECT_KEY]
            cert_config = EdgeCertConfig()
            if security_option == EC.SELFSIGNED_KEY:
                ss_cert_data = certs_cfg_data[EC.SELFSIGNED_KEY]
                dev_pass_file = None
                agt_pass_file = None
                if EC.DEVICE_CA_PASSPHRASE_FILE_KEY in list(ss_cert_data.keys()):
                    dev_pass_file = ss_cert_data[EC.DEVICE_CA_PASSPHRASE_FILE_KEY]
                if EC.AGENT_CA_PASSPHRASE_FILE_KEY in list(ss_cert_data.keys()):
                    agt_pass_file = ss_cert_data[EC.AGENT_CA_PASSPHRASE_FILE_KEY]
                cert_config.set_options(ss_cert_data[EC.FORCENOPASSWD_KEY],
                                        subject_dict,
                                        device_ca_passphrase_file=dev_pass_file,
                                        agent_ca_passphrase_file=agt_pass_file)
            else:
                pre_install = certs_cfg_data[EC.PREINSTALL_KEY]
                dev_pass_file = pre_install[EC.DEVICE_CA_PASSPHRASE_FILE_KEY]
                agt_pass_file = pre_install[EC.AGENT_CA_PASSPHRASE_FILE_KEY]
                owner_ca_cert_file = pre_install[EC.PREINSTALL_OWNER_CA_CERT_KEY]
                dev_ca_cert_file = pre_install[EC.PREINSTALL_DEVICE_CERT_KEY]
                dev_ca_chain_cert_file = pre_install[EC.PREINSTALL_DEVICE_CHAINCERT_KEY]
                dev_ca_pk_file = pre_install[EC.PREINSTALL_DEVICE_PRIVKEY_KEY]
                cert_config.set_options(pre_install[EC.FORCENOPASSWD_KEY],
                                        subject_dict,
                                        device_ca_passphrase_file=dev_pass_file,
                                        agent_ca_passphrase_file=agt_pass_file,
                                        owner_ca_cert_file=owner_ca_cert_file,
                                        device_ca_cert_file=dev_ca_cert_file,
                                        device_ca_chain_cert_file=dev_ca_chain_cert_file,
                                        device_ca_private_key_file=dev_ca_pk_file)


            config.certificate_config = cert_config
            docker_cfg = None
            deployment_type = data[EC.DEPLOYMENT_KEY][EC.DEPLOYMENT_TYPE_KEY]
            if deployment_type == EC.DEPLOYMENT_DOCKER_KEY:
                docker_cfg = data[EC.DEPLOYMENT_KEY][EC.DEPLOYMENT_DOCKER_KEY]
                deploy_cfg = EdgeDeploymentConfigDocker()
                deploy_cfg.uri = docker_cfg[EC.DOCKER_URI_KEY]
                deploy_cfg.edge_image = docker_cfg[EC.EDGE_RUNTIME_IMAGE_KEY]
                for reg in docker_cfg[EC.REGISTRIES_KEY]:
                    deploy_cfg.add_registry(reg[EC.REGISTRY_ADDRESS_KEY],
                                            reg[EC.REGISTRY_USERNAME_KEY],
                                            reg[EC.REGISTRY_PASSWORD_KEY])
                docker_log_cfg = docker_cfg[EC.DOCKER_LOGGING_OPTS_KEY]
                deploy_cfg.logging_driver = \
                    docker_log_cfg[EC.DOCKER_LOGGING_DRIVER_KEY]
                log_opts = docker_log_cfg[EC.DOCKER_LOGGING_DRIVER_OPTS_KEY]
                for opt_key, opt_val in list(log_opts.items()):
                    deploy_cfg.add_logging_option(opt_key, opt_val)

            if docker_cfg is None:
                raise ValueError('Unsupported deployment type: %s' % (deployment_type))
            config.deployment_config = deploy_cfg
            self._deployment_type = deployment_type
            result = config
        except ValueError as ex_value:
            log.error('Error when parsing config data from file: %s. %s.',
                      config_file, str(ex_value))
            raise edgectl.errors.EdgeValueError('Error when parsing config file: %s', config_file)

        return result
Example #12
0
    def parse(self, ignored=None):
        args = self._input_args
        try:
            defaults_json = EdgeDefault.get_default_settings_json()
            cs = args.connection_string
            if cs is None or len(cs) == 0:
                raise ValueError('Please specify the device connection string' \
                                 ' using the --connection-string option')

            config = EdgeHostConfig()
            config.schema_version = defaults_json[EC.SCHEMA_KEY]
            config.connection_string = cs

            cfg_src = EdgeConfigDirInputSource.USER_PROVIDED
            cfg_dir_opt = EdgeHostPlatform.choose_platform_config_dir(args.edge_config_dir, cfg_src)

            config.config_dir = cfg_dir_opt[0]
            config.config_dir_source = cfg_dir_opt[1]

            home_dir = args.edge_home_dir
            if home_dir is None:
                home_dir = EdgeHostPlatform.get_home_dir()
            config.home_dir = home_dir

            hostname = args.edge_hostname
            if hostname is None:
                hostname = EdgeUtils.get_hostname()
            config.hostname = hostname

            log_level = args.runtime_log_level
            if log_level is None:
                log_level = EdgeDefault.get_default_runtime_log_level()
            config.log_level = log_level

            upstream_protocol = args.upstream_protocol
            if upstream_protocol is None:
                config.upstream_protocol = EdgeUpstreamProtocol.NONE
            else:
                config.upstream_protocol = upstream_protocol

            deploy_cfg = None
            if self._deployment_type == EC.DEPLOYMENT_DOCKER:
                deploy_cfg = EdgeDeploymentConfigDocker()
                docker_deploy_data = \
                    defaults_json[EC.DEPLOYMENT_KEY][EC.DEPLOYMENT_DOCKER_KEY]
                registries = args.docker_registries
                if registries is None:
                    registries = docker_deploy_data[EC.REGISTRIES_KEY]
                    for registry in registries:
                        deploy_cfg.add_registry(registry[EC.REGISTRY_ADDRESS_KEY],
                                                registry[EC.REGISTRY_USERNAME_KEY],
                                                registry[EC.REGISTRY_PASSWORD_KEY])
                else:
                    idx = 0
                    address = ''
                    username = ''
                    password = ''
                    for item in registries:
                        if idx == 0:
                            address = item
                        elif idx == 1:
                            username = item
                        else:
                            password = item
                            deploy_cfg.add_registry(address, username, password)
                        idx = (idx + 1) % 3

                image = args.image
                if image is None:
                    image = docker_deploy_data[EC.EDGE_RUNTIME_IMAGE_KEY]
                deploy_cfg.edge_image = image

                uri = args.docker_uri
                if uri is None:
                    uri = EdgeHostPlatform.get_docker_uri()
                deploy_cfg.uri = uri

                docker_log_cfg = docker_deploy_data[EC.DOCKER_LOGGING_OPTS_KEY]
                deploy_cfg.logging_driver = \
                    docker_log_cfg[EC.DOCKER_LOGGING_DRIVER_KEY]
                driver_log_opts = \
                    docker_log_cfg[EC.DOCKER_LOGGING_DRIVER_OPTS_KEY]
                for opt_key, opt_val in list(driver_log_opts.items()):
                    deploy_cfg.add_logging_option(opt_key, opt_val)

            if deploy_cfg is None:
                raise ValueError('Unsupported deployment type: %s', self._deployment_type)

            config.deployment_config = deploy_cfg

            subj_dict = {}
            if args.country:
                subj_dict[EC.SUBJECT_COUNTRY_KEY] = args.country
            if args.state:
                subj_dict[EC.SUBJECT_STATE_KEY] = args.state
            if args.locality:
                subj_dict[EC.SUBJECT_LOCALITY_KEY] = args.locality
            if args.organization:
                subj_dict[EC.SUBJECT_ORGANIZATION_KEY] = args.organization
            if args.organization_unit:
                subj_dict[EC.SUBJECT_ORGANIZATION_UNIT_KEY] = args.organization_unit
            if args.common_name:
                subj_dict[EC.SUBJECT_COMMON_NAME_KEY] = args.common_name

            cert_config = EdgeCertConfig()
            cert_config.set_options(args.auto_cert_gen_force_no_passwords,
                                    subj_dict,
                                    owner_ca_cert_file=args.owner_ca_cert_file,
                                    device_ca_cert_file=args.device_ca_cert_file,
                                    device_ca_chain_cert_file=args.device_ca_chain_cert_file,
                                    device_ca_private_key_file=args.device_ca_private_key_file,
                                    device_ca_passphrase=args.device_ca_passphrase,
                                    device_ca_passphrase_file=args.device_ca_passphrase_file,
                                    agent_ca_passphrase=args.agent_ca_passphrase,
                                    agent_ca_passphrase_file=args.agent_ca_passphrase_file)
            config.certificate_config = cert_config
            return config
        except ValueError as ex_value:
            log.error('Error parsing user input data: %s.', str(ex_value))
            raise edgectl.errors.EdgeValueError('Error parsing user input data')
Example #13
0
 def _parse_and_validate_user_input(self, args):
     ip_type = EdgeConfigInputSources.CLI
     parser = EdgeConfigParserFactory.create_parser(ip_type, args)
     self.edge_config = parser.parse()
     EdgeHostPlatform.install_edge_by_json_data(self.edge_config, True)
     return True
Example #14
0
 def _parse_uninstall_options(self, args):
     is_valid = self._parse_command_options_common(args)
     if is_valid:
         EdgeHostPlatform.uninstall_edge(self.edge_config.home_dir)
     return is_valid