def check(ctx, config, check_install, template): """Validate CSE configuration.""" try: config_dict = get_validated_config(config) except (KeyError, ValueError, Exception): # TODO() replace Exception with specific (see validate_amqp_config) click.secho(f"Config file '{config}' is invalid", fg='red') return if check_install: try: check_cse_installation(config_dict, check_template=template) except EntityNotFoundException: click.secho("CSE installation is invalid", fg='red')
def test_0100_cse_check_invalid_installation(config): """Tests that `cse check` fails for an invalid installation. command: cse check -c cse_test_config.yaml -i expected: check fails """ for i, template_dict in enumerate(config['broker']['templates']): config['broker']['templates'][i]['catalog_item'] = f"_bad{i}" try: check_cse_installation(config) assert False, "cse check passed when it should have failed." except EntityNotFoundException: pass
def check(ctx, config, pks_config, skip_config_decryption, check_install): """Validate CSE config file.""" if skip_config_decryption: password = None else: password = os.getenv('CSE_CONFIG_PASSWORD') or prompt_text( PASSWORD_FOR_CONFIG_DECRYPTION_MSG, color='green', hide_input=True) try: check_python_version(ConsoleMessagePrinter()) except Exception as err: click.secho(str(err), fg='red') sys.exit(1) config_dict = None try: config_dict = get_validated_config( config, pks_config_file_name=pks_config, skip_config_decryption=skip_config_decryption, decryption_password=password, msg_update_callback=ConsoleMessagePrinter()) except (NotAcceptableException, VcdException, ValueError, KeyError, TypeError) as err: click.secho(str(err), fg='red') except AmqpConnectionError as err: click.secho(str(err), fg='red') click.secho("check config file amqp section.", fg='red') except requests.exceptions.ConnectionError as err: click.secho(f"Cannot connect to {err.request.url}.", fg='red') except cryptography.fernet.InvalidToken: click.secho(CONFIG_DECRYPTION_ERROR_MSG, fg='red') except vim.fault.InvalidLogin: click.secho( "vCenter login failed (check config file vCenter " "username/password).", fg='red') if check_install and config_dict: try: check_cse_installation(config_dict, msg_update_callback=ConsoleMessagePrinter()) except Exception as err: click.secho(f"Error : {err}") click.secho("CSE installation is invalid", fg='red')
def run(self, msg_update_callback=utils.NullPrinter()): self.config = get_validated_config( self.config_file, pks_config_file_name=self.pks_config_file, skip_config_decryption=self.skip_config_decryption, decryption_password=self.decryption_password, log_wire_file=logger.SERVER_DEBUG_WIRELOG_FILEPATH, logger_debug=logger.SERVER_LOGGER, msg_update_callback=msg_update_callback) populate_vsphere_list(self.config['vcs']) # Load def entity-type and interface self._load_def_schema(msg_update_callback=msg_update_callback) # Read k8s catalog definition from catalog item metadata and append # the same to to server run-time config self._load_template_definition_from_catalog( msg_update_callback=msg_update_callback) if float(self.config['vcd']['api_version']) < float( vCDApiVersion.VERSION_35.value): # noqa: E501 # Read templates rules from config and update template deinfition # in server run-time config self._process_template_rules( msg_update_callback=msg_update_callback) # Make sure that all vms in templates are compliant with the # compute policy specified in template definition (can be affected # by rules). self._process_template_compute_policy_compliance( msg_update_callback=msg_update_callback) else: msg = "Template rules are not supported by CSE for vCD api " \ "version 35.0 or above. Skipping template rule processing." msg_update_callback.info(msg) logger.SERVER_LOGGER.debug(msg) if self.should_check_config: check_cse_installation(self.config, msg_update_callback=msg_update_callback) if self.config.get('pks_config'): pks_config = self.config.get('pks_config') self.pks_cache = PksCache( pks_servers=pks_config.get('pks_api_servers', []), pks_accounts=pks_config.get('pks_accounts', []), pvdcs=pks_config.get('pvdcs', []), orgs=pks_config.get('orgs', []), nsxt_servers=pks_config.get('nsxt_servers', [])) amqp = self.config['amqp'] num_consumers = self.config['service']['listeners'] for n in range(num_consumers): try: c = MessageConsumer(amqp['host'], amqp['port'], amqp['ssl'], amqp['vhost'], amqp['username'], amqp['password'], amqp['exchange'], amqp['routing_key']) name = 'MessageConsumer-%s' % n t = Thread(name=name, target=consumer_thread, args=(c, )) t.daemon = True t.start() msg = f"Started thread '{name} ({t.ident})'" msg_update_callback.general(msg) logger.SERVER_LOGGER.info(msg) self.threads.append(t) self.consumers.append(c) time.sleep(0.25) except KeyboardInterrupt: break except Exception: logger.SERVER_LOGGER.error(traceback.format_exc()) logger.SERVER_LOGGER.info( f"Number of threads started: {len(self.threads)}") # noqa: E501 self._state = ServerState.RUNNING message = f"Container Service Extension for vCloud Director" \ f"\nServer running using config file: {self.config_file}" \ f"\nLog files: {logger.SERVER_INFO_LOG_FILEPATH}, " \ f"{logger.SERVER_DEBUG_LOG_FILEPATH}" \ f"\nwaiting for requests (ctrl+c to close)" signal.signal(signal.SIGINT, signal_handler) msg_update_callback.general_no_color(message) logger.SERVER_LOGGER.info(message) # Record telemetry on user action and details of operation. cse_params = { PayloadKey.WAS_DECRYPTION_SKIPPED: bool(self.skip_config_decryption), # noqa: E501 PayloadKey.WAS_PKS_CONFIG_FILE_PROVIDED: bool(self.pks_config_file), # noqa: E501 PayloadKey.WAS_INSTALLATION_CHECK_SKIPPED: bool(self.should_check_config) # noqa: E501 } record_user_action_details(cse_operation=CseOperation.SERVICE_RUN, cse_params=cse_params) record_user_action(cse_operation=CseOperation.SERVICE_RUN) while True: try: time.sleep(1) if self._state == ServerState.STOPPING and \ self.active_requests_count() == 0: break except KeyboardInterrupt: break except Exception: msg_update_callback.general_no_color(traceback.format_exc()) logger.SERVER_LOGGER.error(traceback.format_exc()) sys.exit(1) logger.SERVER_LOGGER.info("Stop detected") logger.SERVER_LOGGER.info("Closing connections...") for c in self.consumers: try: c.stop() except Exception: logger.SERVER_LOGGER.error(traceback.format_exc()) self._state = ServerState.STOPPED logger.SERVER_LOGGER.info("Done")
def run(self, msg_update_callback=None): configure_server_logger() self.config = get_validated_config( self.config_file, msg_update_callback=msg_update_callback) populate_vsphere_list(self.config['vcs']) # Read k8s catalog definition from catalog item metadata and append # the same to to server run-time config self._load_template_definition_from_catalog( msg_update_callback=msg_update_callback) # Read templates rules from config and update template deinfition in # server run-time config self._process_template_rules(msg_update_callback=msg_update_callback) # Make sure that all vms in templates are compliant with the compute # policy specified in template definition (can be affected by rules). self._process_template_compute_policy_compliance( msg_update_callback=msg_update_callback) if self.should_check_config: check_cse_installation(self.config, msg_update_callback=msg_update_callback) if self.config.get('pks_config'): pks_config = self.config.get('pks_config') self.pks_cache = PksCache( pks_servers=pks_config.get('pks_api_servers', []), pks_accounts=pks_config.get('pks_accounts', []), pvdcs=pks_config.get('pvdcs', []), orgs=pks_config.get('orgs', []), nsxt_servers=pks_config.get('nsxt_servers', [])) amqp = self.config['amqp'] num_consumers = self.config['service']['listeners'] for n in range(num_consumers): try: c = MessageConsumer(amqp['host'], amqp['port'], amqp['ssl'], amqp['vhost'], amqp['username'], amqp['password'], amqp['exchange'], amqp['routing_key']) name = 'MessageConsumer-%s' % n t = Thread(name=name, target=consumer_thread, args=(c, )) t.daemon = True t.start() msg = f"Started thread '{name} ({t.ident})'" if msg_update_callback: msg_update_callback.general(msg) LOGGER.info(msg) self.threads.append(t) self.consumers.append(c) time.sleep(0.25) except KeyboardInterrupt: break except Exception: LOGGER.error(traceback.format_exc()) LOGGER.info(f"Number of threads started: {len(self.threads)}") self._state = ServerState.RUNNING message = f"Container Service Extension for vCloud Director" \ f"\nServer running using config file: {self.config_file}" \ f"\nLog files: {SERVER_INFO_LOG_FILEPATH}, " \ f"{SERVER_DEBUG_LOG_FILEPATH}" \ f"\nwaiting for requests (ctrl+c to close)" signal.signal(signal.SIGINT, signal_handler) if msg_update_callback: msg_update_callback.general_no_color(message) LOGGER.info(message) while True: try: time.sleep(1) if self._state == ServerState.STOPPING and \ self.active_requests_count() == 0: break except KeyboardInterrupt: break except Exception: if msg_update_callback: msg_update_callback.general_no_color( traceback.format_exc()) LOGGER.error(traceback.format_exc()) sys.exit(1) LOGGER.info("Stop detected") LOGGER.info("Closing connections...") for c in self.consumers: try: c.stop() except Exception: LOGGER.error(traceback.format_exc()) self._state = ServerState.STOPPED LOGGER.info("Done")
def run(self): self.config = get_validated_config(self.config_file) if self.should_check_config: check_cse_installation(self.config) configure_server_logger() message = f"Container Service Extension for vCloudDirector" \ f"\nServer running using config file: {self.config_file}" \ f"\nLog files: {SERVER_INFO_LOG_FILEPATH}, " \ f"{SERVER_DEBUG_LOG_FILEPATH}" \ f"\nwaiting for requests (ctrl+c to close)" signal.signal(signal.SIGINT, signal_handler) click.secho(message) LOGGER.info(message) amqp = self.config['amqp'] num_consumers = self.config['service']['listeners'] for n in range(num_consumers): try: c = MessageConsumer(amqp['host'], amqp['port'], amqp['ssl'], amqp['vhost'], amqp['username'], amqp['password'], amqp['exchange'], amqp['routing_key']) name = 'MessageConsumer-%s' % n t = Thread(name=name, target=consumer_thread, args=(c, )) t.daemon = True t.start() LOGGER.info('started thread %s', t.ident) self.threads.append(t) self.consumers.append(c) time.sleep(0.25) except KeyboardInterrupt: break except Exception: print(traceback.format_exc()) LOGGER.info('num of threads started: %s', len(self.threads)) self.is_enabled = True while True: try: time.sleep(1) if self.should_stop and self.active_requests_count() == 0: break except KeyboardInterrupt: break except Exception: click.secho(traceback.format_exc()) sys.exit(1) LOGGER.info('stop detected') LOGGER.info('closing connections...') for c in self.consumers: try: c.stop() except Exception: pass LOGGER.info('done')
def run(self, msg_update_callback=None): self.config = get_validated_config( self.config_file, msg_update_callback=msg_update_callback) if self.should_check_config: check_cse_installation(self.config, msg_update_callback=msg_update_callback) configure_server_logger() message = f"Container Service Extension for vCloudDirector" \ f"\nServer running using config file: {self.config_file}" \ f"\nLog files: {SERVER_INFO_LOG_FILEPATH}, " \ f"{SERVER_DEBUG_LOG_FILEPATH}" \ f"\nwaiting for requests (ctrl+c to close)" signal.signal(signal.SIGINT, signal_handler) if msg_update_callback: msg_update_callback.general_no_color(message) LOGGER.info(message) if self.config.get('pks_config'): pks_config = self.config.get('pks_config') self.pks_cache = PksCache( pks_servers=pks_config.get('pks_api_servers', []), pks_accounts=pks_config.get('pks_accounts', []), pvdcs=pks_config.get('pvdcs', []), orgs=pks_config.get('orgs', []), nsxt_servers=pks_config.get('nsxt_servers', [])) amqp = self.config['amqp'] num_consumers = self.config['service']['listeners'] for n in range(num_consumers): try: c = MessageConsumer(amqp['host'], amqp['port'], amqp['ssl'], amqp['vhost'], amqp['username'], amqp['password'], amqp['exchange'], amqp['routing_key']) name = 'MessageConsumer-%s' % n t = Thread(name=name, target=consumer_thread, args=(c, )) t.daemon = True t.start() LOGGER.info("Started thread {t.ident}") self.threads.append(t) self.consumers.append(c) time.sleep(0.25) except KeyboardInterrupt: break except Exception: print(traceback.format_exc()) LOGGER.info(f"Number of threads started: {len(self.threads)}") self._state = ServerState.RUNNING while True: try: time.sleep(1) if self._state == ServerState.STOPPING and \ self.active_requests_count() == 0: break except KeyboardInterrupt: break except Exception: if msg_update_callback: msg_update_callback.general_no_color( traceback.format_exc()) sys.exit(1) LOGGER.info("Stop detected") LOGGER.info("Closing connections...") for c in self.consumers: try: c.stop() except Exception: pass self._state = ServerState.STOPPED LOGGER.info("Done")
def run(self, msg_update_callback=None): configure_server_logger() self.config = get_validated_config( self.config_file, msg_update_callback=msg_update_callback) populate_vsphere_list(self.config['vcs']) # Read K8 catalog definition from catalog item metadata and append # to server config client = None try: client = Client(self.config['vcd']['host'], api_version=self.config['vcd']['api_version'], verify_ssl_certs=self.config['vcd']['verify'], log_file=SERVER_DEBUG_WIRELOG_FILEPATH, log_requests=True, log_headers=True, log_bodies=True) credentials = BasicLoginCredentials(self.config['vcd']['username'], SYSTEM_ORG_NAME, self.config['vcd']['password']) client.set_credentials(credentials) org_name = self.config['broker']['org'] catalog_name = self.config['broker']['catalog'] k8_templates = get_all_k8s_local_template_definition( client=client, catalog_name=catalog_name, org_name=org_name) if not k8_templates: msg = "No valid K8 templates were found in catalog " \ f"'{catalog_name}'. Unable to start CSE server." if msg_update_callback: msg_update_callback.error(msg) LOGGER.error(msg) sys.exit(1) # Check that deafult K8 template exists in vCD at the correct # revision default_template_name = \ self.config['broker']['default_template_name'] default_template_revision = \ str(self.config['broker']['default_template_revision']) found_default_template = False for template in k8_templates: if str(template['revision']) == default_template_revision \ and template['name'] == default_template_name: found_default_template = True msg = f"Found K8 template '{template['name']}' at revision " \ f"{template['revision']} in catalog '{catalog_name}'" if msg_update_callback: msg_update_callback.general(msg) LOGGER.info(msg) if not found_default_template: msg = f"Default template {default_template_name} with " \ f"revision {default_template_revision} not found." \ " Unable to start CSE server." if msg_update_callback: msg_update_callback.error(msg) LOGGER.error(msg) sys.exit(1) self.config['broker']['templates'] = k8_templates finally: if client: client.logout() # TODO Rule framework, update config with rules if self.should_check_config: check_cse_installation(self.config, msg_update_callback=msg_update_callback) if self.config.get('pks_config'): pks_config = self.config.get('pks_config') self.pks_cache = PksCache( pks_servers=pks_config.get('pks_api_servers', []), pks_accounts=pks_config.get('pks_accounts', []), pvdcs=pks_config.get('pvdcs', []), orgs=pks_config.get('orgs', []), nsxt_servers=pks_config.get('nsxt_servers', [])) amqp = self.config['amqp'] num_consumers = self.config['service']['listeners'] for n in range(num_consumers): try: c = MessageConsumer(amqp['host'], amqp['port'], amqp['ssl'], amqp['vhost'], amqp['username'], amqp['password'], amqp['exchange'], amqp['routing_key']) name = 'MessageConsumer-%s' % n t = Thread(name=name, target=consumer_thread, args=(c, )) t.daemon = True t.start() msg = f"Started thread '{name} ({t.ident})'" if msg_update_callback: msg_update_callback.general(msg) LOGGER.info(msg) self.threads.append(t) self.consumers.append(c) time.sleep(0.25) except KeyboardInterrupt: break except Exception: LOGGER.error(traceback.format_exc()) LOGGER.info(f"Number of threads started: {len(self.threads)}") self._state = ServerState.RUNNING message = f"Container Service Extension for vCloud Director" \ f"\nServer running using config file: {self.config_file}" \ f"\nLog files: {SERVER_INFO_LOG_FILEPATH}, " \ f"{SERVER_DEBUG_LOG_FILEPATH}" \ f"\nwaiting for requests (ctrl+c to close)" signal.signal(signal.SIGINT, signal_handler) if msg_update_callback: msg_update_callback.general_no_color(message) LOGGER.info(message) while True: try: time.sleep(1) if self._state == ServerState.STOPPING and \ self.active_requests_count() == 0: break except KeyboardInterrupt: break except Exception: if msg_update_callback: msg_update_callback.general_no_color( traceback.format_exc()) LOGGER.error(traceback.format_exc()) sys.exit(1) LOGGER.info("Stop detected") LOGGER.info("Closing connections...") for c in self.consumers: try: c.stop() except Exception: pass self._state = ServerState.STOPPED LOGGER.info("Done")
def run(self, msg_update_callback=utils.NullPrinter()): sysadmin_client = None try: sysadmin_client = vcd_utils.get_sys_admin_client() verify_version_compatibility(sysadmin_client, self.config['vcd']['api_version'], utils.should_use_mqtt_protocol(self.config)) # noqa: E501 except Exception as err: logger.SERVER_LOGGER.info(err) raise finally: if sysadmin_client: sysadmin_client.logout() if utils.should_use_mqtt_protocol(self.config): # Store/setup MQTT extension, api filter, and token info try: sysadmin_client = vcd_utils.get_sys_admin_client() mqtt_ext_manager = MQTTExtensionManager(sysadmin_client) ext_info = mqtt_ext_manager.get_extension_info( ext_name=server_constants.CSE_SERVICE_NAME, ext_version=server_constants.MQTT_EXTENSION_VERSION, ext_vendor=server_constants.MQTT_EXTENSION_VENDOR) ext_urn_id = ext_info[MQTTExtKey.EXT_URN_ID] ext_uuid = mqtt_ext_manager.get_extension_uuid(ext_urn_id) api_filters_status = mqtt_ext_manager.check_api_filters_setup( ext_uuid, configure_cse.API_FILTER_PATTERNS) if not api_filters_status: msg = 'MQTT Api filter is not set up' logger.SERVER_LOGGER.error(msg) raise cse_exception.MQTTExtensionError(msg) token_info = mqtt_ext_manager.create_extension_token( token_name=server_constants.MQTT_TOKEN_NAME, ext_urn_id=ext_urn_id) self.config['mqtt'].update(ext_info) self.config['mqtt'].update(token_info) self.config['mqtt'][MQTTExtKey.EXT_UUID] = ext_uuid except Exception as err: msg = f'MQTT extension setup error: {err}' logger.SERVER_LOGGER.error(msg) raise err finally: if sysadmin_client: sysadmin_client.logout() populate_vsphere_list(self.config['vcs']) # Load def entity-type and interface self._load_def_schema(msg_update_callback=msg_update_callback) # Read k8s catalog definition from catalog item metadata and append # the same to to server run-time config self._load_template_definition_from_catalog( msg_update_callback=msg_update_callback) self._load_placement_policy_details( msg_update_callback=msg_update_callback) if float(self.config['vcd']['api_version']) < float(vCDApiVersion.VERSION_35.value): # noqa: E501 # Read templates rules from config and update template deinfition # in server run-time config self._process_template_rules( msg_update_callback=msg_update_callback) # Make sure that all vms in templates are compliant with the # compute policy specified in template definition (can be affected # by rules). self._process_template_compute_policy_compliance( msg_update_callback=msg_update_callback) else: msg = "Template rules are not supported by CSE for vCD api " \ "version 35.0 or above. Skipping template rule processing." msg_update_callback.info(msg) logger.SERVER_LOGGER.debug(msg) if self.should_check_config: configure_cse.check_cse_installation( self.config, msg_update_callback=msg_update_callback) if self.config.get('pks_config'): pks_config = self.config.get('pks_config') self.pks_cache = PksCache( pks_servers=pks_config.get('pks_api_servers', []), pks_accounts=pks_config.get('pks_accounts', []), pvdcs=pks_config.get('pvdcs', []), orgs=pks_config.get('orgs', []), nsxt_servers=pks_config.get('nsxt_servers', [])) num_processors = self.config['service']['processors'] try: self.consumer = MessageConsumer(self.config, num_processors) name = server_constants.MESSAGE_CONSUMER_THREAD consumer_thread = Thread(name=name, target=consumer_thread_run, args=(self.consumer, )) consumer_thread.daemon = True consumer_thread.start() self.consumer_thread = consumer_thread msg = f"Started thread '{name}' ({consumer_thread.ident})" msg_update_callback.general(msg) logger.SERVER_LOGGER.info(msg) except KeyboardInterrupt: if self.consumer: self.consumer.stop() interrupt_msg = f"\nKeyboard interrupt when starting thread " \ f"'{name}'" logger.SERVER_LOGGER.debug(interrupt_msg) raise Exception(interrupt_msg) except Exception: if self.consumer: self.consumer.stop() logger.SERVER_LOGGER.error(traceback.format_exc()) # Updating state to Running before starting watchdog because watchdog # exits when server is not Running self._state = ServerState.RUNNING # Start consumer watchdog name = server_constants.WATCHDOG_THREAD consumer_watchdog = Thread(name=name, target=watchdog_thread_run, args=(self, num_processors)) consumer_watchdog.daemon = True consumer_watchdog.start() self._consumer_watchdog = consumer_watchdog msg = f"Started thread '{name}' ({consumer_watchdog.ident})" msg_update_callback.general(msg) logger.SERVER_LOGGER.info(msg) message = f"Container Service Extension for vCloud Director" \ f"\nServer running using config file: {self.config_file}" \ f"\nLog files: {logger.SERVER_INFO_LOG_FILEPATH}, " \ f"{logger.SERVER_DEBUG_LOG_FILEPATH}" \ f"\nwaiting for requests (ctrl+c to close)" signal.signal(signal.SIGINT, signal_handler) msg_update_callback.general_no_color(message) logger.SERVER_LOGGER.info(message) # Record telemetry on user action and details of operation. cse_params = { PayloadKey.WAS_DECRYPTION_SKIPPED: bool(self.skip_config_decryption), # noqa: E501 PayloadKey.WAS_PKS_CONFIG_FILE_PROVIDED: bool(self.pks_config_file), # noqa: E501 PayloadKey.WAS_INSTALLATION_CHECK_SKIPPED: bool(self.should_check_config) # noqa: E501 } record_user_action_details(cse_operation=CseOperation.SERVICE_RUN, cse_params=cse_params) record_user_action(cse_operation=CseOperation.SERVICE_RUN) while True: try: time.sleep(1) if self._state == ServerState.STOPPING and \ self.active_requests_count() == 0: break except KeyboardInterrupt: break except Exception: msg_update_callback.general_no_color( traceback.format_exc()) logger.SERVER_LOGGER.error(traceback.format_exc()) sys.exit(1) logger.SERVER_LOGGER.info("Stop detected") logger.SERVER_LOGGER.info("Closing connections...") self._state = ServerState.STOPPING try: self.consumer.stop() except Exception: logger.SERVER_LOGGER.error(traceback.format_exc()) self._state = ServerState.STOPPED logger.SERVER_LOGGER.info("Done")