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
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'])
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
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
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
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
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'])
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
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)
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
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
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')
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
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