def should_register_cse(client, ext_install): """Decides if CSE installation should register CSE to vCD. Returns False if CSE is already registered, or if the user declines registration. :param pyvcloud.vcd.client.Client client: :param str ext_install: 'skip' skips registration, 'config' allows registration without prompting user, 'prompt' asks user before registration. :return: boolean that signals whether we should register CSE to vCD. :rtype: bool """ if ext_install == 'skip': return False ext = APIExtension(client) try: cse_info = ext.get_extension_info(CSE_NAME, namespace=CSE_NAMESPACE) msg = f"Found 'cse' extension on vCD, enabled={cse_info['enabled']}" click.secho(msg, fg='green') LOGGER.info(msg) return False except MissingRecordException: prompt_msg = "Register 'cse' as an API extension in vCD?" if ext_install == 'prompt' and not click.confirm(prompt_msg): msg = f"Skipping CSE registration." click.secho(msg, fg='yellow') LOGGER.warning(msg) return False return True
def test_0080_update_service(self): """Test the method APIExtension.update_extension(). This test passes if the routing key and exchange after execution of the method matches the respective test strings. """ logger = Environment.get_default_logger() api_extension = APIExtension(TestApiExtension._client) ext_name = TestApiExtension._service_name ext_namespace = TestApiExtension._service1_namespace logger.debug('Updating service (name:' + ext_name + ', namespace:' + ext_namespace + ').') test_routing_key = 'testroutingkey' test_exchange = 'testexchange' href = api_extension.update_extension(name=ext_name, namespace=ext_namespace, routing_key=test_routing_key, exchange=test_exchange) self.assertEqual(href, TestApiExtension._service1_href) ext_info = api_extension.get_extension_info(ext_name, namespace=ext_namespace) self.assertEqual(ext_info['routingKey'], test_routing_key) self.assertEqual(ext_info['exchange'], test_exchange)
def info(ctx, name, namespace): try: restore_session(ctx) ext = APIExtension(ctx.obj['client']) stdout(ext.get_extension_info(name, namespace), ctx) except Exception as e: stderr(e, ctx)
def test_0030_get_service_info_with_invalid_name(self): """Test the method APIExtension.get_extension_info(). Invoke the method with an invalid service name. This test passes if the an MissingRecordException is raised by the method. """ api_extension = APIExtension(TestApiExtension._client) try: api_extension.get_extension_info( name=TestApiExtension._non_existent_service_name) self.fail('Should not be able to fetch service ' + TestApiExtension._non_existent_service_name) except MissingRecordException as e: pass
def test_0030_get_service_info_with_invalid_name(self): """Test the method APIExtension.get_extension_info(). Invoke the method with an invalid service name. This test passes if the an MissingRecordException is raised by the method. """ api_extension = APIExtension(TestApiExtension._client) try: api_extension.get_extension_info( name=TestApiExtension._non_existent_service_name) self.fail('Should not be able to fetch service ' + TestApiExtension._non_existent_service_name) except MissingRecordException: pass
def test_0080_update_service(self): """Test the method APIExtension.update_extension(). This test passes if the routing key and exchange after execution of the method matches the respective test strings. """ logger = Environment.get_default_logger() api_extension = APIExtension(TestApiExtension._client) ext_name = TestApiExtension._service_name ext_namespace = TestApiExtension._service1_namespace logger.debug('Updating service (name:' + ext_name + ', namespace:' + ext_namespace + ').') test_routing_key = 'testroutingkey' test_exchange = 'testexchange' href = api_extension.update_extension( name=ext_name, namespace=ext_namespace, routing_key=test_routing_key, exchange=test_exchange) self.assertEqual(href, TestApiExtension._service1_href) ext_info = api_extension.get_extension_info(ext_name, namespace=ext_namespace) self.assertEqual(ext_info['routingKey'], test_routing_key) self.assertEqual(ext_info['exchange'], test_exchange)
def test_0050_get_service_info_with_invalid_namespace(self): """Test the method APIExtension.get_extension_info(). Invoke the method with the name of the service created in setup, but an invalid namespace. This test passes if the an empty dictionary is returned by the method. """ api_extension = APIExtension(TestApiExtension._client) try: api_extension.get_extension_info( name=TestApiExtension._service_name, namespace=TestApiExtension._non_existent_service_namespace) self.fail('Should not be able to fetch service ' + TestApiExtension._non_existent_service_name) except MissingRecordException: pass
def test_0050_get_service_info_with_invalid_namespace(self): """Test the method APIExtension.get_extension_info(). Invoke the method with the name of the service created in setup, but an invalid namespace. This test passes if the an empty dictionary is returned by the method. """ api_extension = APIExtension(TestApiExtension._client) try: api_extension.get_extension_info( name=TestApiExtension._service_name, namespace=TestApiExtension._non_existent_service_namespace) self.fail('Should not be able to fetch service ' + TestApiExtension._non_existent_service_name) except MissingRecordException as e: pass
def test_0040_get_service_info_with_no_namespace(self): """Test the method APIExtension.get_extension_info(). Invoke the method with the name of the first service created in setup, but don't send the namespace. This test passes if the an MultipleRecordsException is raised by the method. """ api_extension = APIExtension(TestApiExtension._client) try: api_extension.get_extension_info( name=TestApiExtension._service_name) self.fail('Should not be able to fetch service ' + TestApiExtension._service_name + ' with an empty namespace.') except MultipleRecordsException: pass
def get_telemetry_instance_id(vcd_host: str, vcd_username: str, vcd_password: str, verify_ssl: bool, is_mqtt_exchange: bool, logger_debug=NULL_LOGGER, msg_update_callback=NullPrinter()): """Get CSE AMQP or MQTT extension id which is used as instance id. Any exception is logged as error. No exception is leaked out of this method and does not affect the server startup. :param str vcd_host: :param str vcd_username: :param str vcd_password: :param bool verify_ssl: :param bool is_mqtt_exchange: :param logging.logger logger_debug: logger instance to log any error in retrieving CSE extension id. :param utils.ConsoleMessagePrinter msg_update_callback: Callback object. :return instance id to use for sending data to Vmware telemetry server :rtype str (unless no instance id found) """ client = None try: client = Client(vcd_host, verify_ssl_certs=verify_ssl) client.set_credentials( BasicLoginCredentials(vcd_username, SYSTEM_ORG_NAME, vcd_password)) if is_mqtt_exchange: # Get MQTT extension uuid mqtt_ext_manager = MQTTExtensionManager(client) ext_info = mqtt_ext_manager.get_extension_info( ext_name=CSE_SERVICE_NAME, ext_version=MQTT_EXTENSION_VERSION, ext_vendor=MQTT_EXTENSION_VENDOR) if not ext_info: logger_debug.debug("Failed to retrieve telemetry instance id") return None logger_debug.debug("Retrieved telemetry instance id") return mqtt_ext_manager.get_extension_uuid( ext_info[MQTTExtKey.EXT_URN_ID]) else: # Get AMQP extension id ext = APIExtension(client) cse_info = ext.get_extension_info(CSE_SERVICE_NAME, namespace=CSE_SERVICE_NAMESPACE) logger_debug.debug("Retrieved telemetry instance id") return cse_info.get('id') except Exception as err: msg = f"Cannot retrieve telemetry instance id:{err}" msg_update_callback.general(msg) logger_debug.error(msg, exc_info=True) finally: if client is not None: client.logout()
def test_0040_get_service_info_with_no_namespace(self): """Test the method APIExtension.get_extension_info(). Invoke the method with the name of the first service created in setup, but don't send the namespace. This test passes if the an MultipleRecordsException is raised by the method. """ api_extension = APIExtension(TestApiExtension._client) try: api_extension.get_extension_info( name=TestApiExtension._service_name) self.fail('Should not be able to fetch service ' + TestApiExtension._service_name + ' with an empty namespace.') except MultipleRecordsException as e: pass
def test_0002_get_extension(self): extension = APIExtension(self.client) ext_info = extension.get_extension_info( self.config['vcd']['extension_name'], self.config['vcd']['extension_namespace']) assert ext_info assert ext_info['name'] == self.config['vcd']['extension_name'] assert ext_info['namespace'] == \ self.config['vcd']['extension_namespace'] assert ext_info['filter_1'].startswith('/api/')
def test_0002_get_extension(self): extension = APIExtension(self.client) ext_info = extension.get_extension_info( self.config['vcd']['extension_name'], self.config['vcd']['extension_namespace']) assert ext_info assert ext_info['name'] == self.config['vcd']['extension_name'] assert ext_info['namespace'] == \ self.config['vcd']['extension_namespace'] assert ext_info['filter_1'].startswith('/api/')
def initialize_on_vcloud(self): """Check and/register the extension on vCloud. """ self.log('info', 'Checking the initialization status of extension in vCloud.') if not ( self.conf('vcloud.api_extension.namespace') and self.conf('vcloud.api_extension.exchange') and self.conf('vcloud.api_extension.routing_key') ): self.log('warning', 'Missing items in configuration to make the initialization check-up. Ignoring.') return client = login_as_system_admin() ext_manager = APIExtension(client) try: current_ext_on_vcd = ext_manager.get_extension_info( self.name, namespace=self.conf('vcloud.api_extension.namespace')) self.log('info', 'Extension is already registered on vCloud') except MissingRecordException: self.log('warning', "This extension is not (yet) declared on vCloud.") current_ext_on_vcd = None except MultipleRecordsException: self.log('error', "Multiple extensions found with same name and namespace") sys.exit(-1) # Force a fresh redeploy of the full extension (Warning: be carrefull, ID will change !) if current_ext_on_vcd and self.conf('vcloud.api_extension.force_redeploy', False): ext_manager.delete_extension( self.name, namespace=self.conf('vcloud.api_extension.namespace')) self.log('info', 'Extension is unregistered on vCloud') current_ext_on_vcd = None # Only update an existing extension (Warning: does not update the API filters/patterns!) if current_ext_on_vcd and self.conf('vcloud.api_extension.auto_update', False): current_ext_on_vcd = ext_manager.update_extension( self.name, namespace=self.conf('vcloud.api_extension.namespace'), routing_key=self.conf('vcloud.api_extension.routing_key'), exchange=self.conf('vcloud.api_extension.exchange')) self.log('info', 'Extension is updated on vCloud') # Register a new extension if not current_ext_on_vcd: ext_manager.add_extension( self.name, namespace=self.conf('vcloud.api_extension.namespace'), routing_key=self.conf('vcloud.api_extension.routing_key'), exchange=self.conf('vcloud.api_extension.exchange'), patterns=self.conf('vcloud.api_extension.api_filters')) self.log('info', 'Extension is registered on vCloud') # Ensure to enable it ext_manager.enable_extension(self.name, namespace=self.conf('vcloud.api_extension.namespace'), enabled=True) self.log('info', 'Extension is enabled on vCloud')
def _register_cse(client, routing_key, exchange, msg_update_callback=utils.NullPrinter()): """Register or update CSE on vCD. :param pyvcloud.vcd.client.Client client: :param pyvcloud.vcd.client.Client client: :param str routing_key: :param str exchange: :param utils.ConsoleMessagePrinter msg_update_callback: Callback object. """ ext = APIExtension(client) patterns = [ f'/api/{server_constants.CSE_SERVICE_NAME}', f'/api/{server_constants.CSE_SERVICE_NAME}/.*', f'/api/{server_constants.CSE_SERVICE_NAME}/.*/.*', f'/api/{server_constants.PKS_SERVICE_NAME}', f'/api/{server_constants.PKS_SERVICE_NAME}/.*', f'/api/{server_constants.PKS_SERVICE_NAME}/.*/.*' ] cse_info = None try: cse_info = ext.get_extension_info( server_constants.CSE_SERVICE_NAME, namespace=server_constants.CSE_SERVICE_NAMESPACE) # noqa: E501 except MissingRecordException: pass if cse_info is None: ext.add_extension( server_constants.CSE_SERVICE_NAME, server_constants.CSE_SERVICE_NAMESPACE, routing_key, # noqa: E501 exchange, patterns) msg = f"Registered {server_constants.CSE_SERVICE_NAME} as an API extension in vCD" # noqa: E501 else: ext.update_extension( server_constants.CSE_SERVICE_NAME, namespace=server_constants.CSE_SERVICE_NAMESPACE, # noqa: E501 routing_key=routing_key, exchange=exchange) msg = f"Updated {server_constants.CSE_SERVICE_NAME} API Extension in vCD" # noqa: E501 msg_update_callback.general(msg) INSTALL_LOGGER.info(msg)
def get_telemetry_instance_id(config_dict, logger_debug=NULL_LOGGER, msg_update_callback=NullPrinter()): """Get CSE AMQP or MQTT extension id which is used as instance id. Any exception is logged as error. No exception is leaked out of this method and does not affect the server startup. :param dict config_dict: CSE configuration :param logging.logger logger_debug: logger instance to log any error in retrieving CSE extension id. :param utils.ConsoleMessagePrinter msg_update_callback: Callback object. :return instance id to use for sending data to Vmware telemetry server :rtype str (unless no instance id found) """ vcd = config_dict['vcd'] try: client = Client(vcd['host'], api_version=vcd['api_version'], verify_ssl_certs=vcd['verify']) client.set_credentials(BasicLoginCredentials( vcd['username'], SYSTEM_ORG_NAME, vcd['password'])) if should_use_mqtt_protocol(config_dict): # Get MQTT extension uuid mqtt_ext_manager = MQTTExtensionManager(client) ext_info = mqtt_ext_manager.get_extension_info( ext_name=CSE_SERVICE_NAME, ext_version=MQTT_EXTENSION_VERSION, ext_vendor=MQTT_EXTENSION_VENDOR) if not ext_info: return None return mqtt_ext_manager.get_extension_uuid( ext_info[MQTTExtKey.EXT_URN_ID]) else: # Get AMQP extension id ext = APIExtension(client) cse_info = ext.get_extension_info(CSE_SERVICE_NAME, namespace=CSE_SERVICE_NAMESPACE) logger_debug.info("Retrieved telemetry instance id") return cse_info.get('id') except Exception as err: msg = f"Cannot retrieve telemetry instance id:{err}" msg_update_callback.general(msg) logger_debug.error(msg) finally: if client is not None: client.logout()
def test_0020_get_service_info(self): """Test the method APIExtension.get_extension_info(). Invoke the method with the name and namespace of the first service created in setup. A call to APIExtension.get_extension_info() also tests APIExtension.get_extension() and APIExtension.get_api_filters(). This test passes if the service detail retrieved by the method is not None, and the details are correct. """ api_extension = APIExtension(TestApiExtension._client) service = api_extension.get_extension_info( name=TestApiExtension._service_name, namespace=TestApiExtension._service1_namespace) self._check_service_details(service, TestApiExtension._service1_namespace) self._check_filter_details(service)
def test_0020_get_service_info(self): """Test the method APIExtension.get_extension_info(). Invoke the method with the name and namespace of the first service created in setup. A call to APIExtension.get_extension_info() also tests APIExtension.get_extension() and APIExtension.get_api_filters(). This test passes if the service detail retrieved by the method is not None, and the details are correct. """ api_extension = APIExtension(TestApiExtension._client) service = api_extension.get_extension_info( name=TestApiExtension._service_name, namespace=TestApiExtension._service1_namespace) self._check_service_details(service, TestApiExtension._service1_namespace) self._check_filter_details(service)
def get_telemetry_instance_id(vcd, logger_instance=None, msg_update_callback=None): """Get CSE extension id which is used as instance id. Any exception is logged as error. No exception is leaked out of this method and does not affect the server startup. :param dict vcd: 'vcd' section of config file as a dict. :param logging.logger logger_instance: logger instance to log any error in retrieving CSE extension id. :param utils.ConsoleMessagePrinter msg_update_callback: Callback object that writes messages onto console. :return instance id to use for sending data to Vmware telemetry server :rtype str :raises Exception: if any exception happens while retrieving CSE extension id """ try: client = Client(vcd['host'], api_version=vcd['api_version'], verify_ssl_certs=vcd['verify']) client.set_credentials( BasicLoginCredentials(vcd['username'], SYSTEM_ORG_NAME, vcd['password'])) ext = APIExtension(client) cse_info = ext.get_extension_info(CSE_SERVICE_NAME, namespace=CSE_SERVICE_NAMESPACE) if logger_instance: logger_instance.info("Retrieved telemetry instance id") return cse_info.get('id') except Exception as err: msg = f"Cannot retrieve telemetry instance id:{err}" if msg_update_callback: msg_update_callback.general(msg) if logger_instance: logger_instance.error(msg) finally: if client is not None: client.logout()
def register_extension(ctx, client, config, ext_install): if ext_install == 'skip': click.secho('Extension configuration: skipped') return ext = APIExtension(client) try: name = 'cse' cse_ext = ext.get_extension_info(name) click.secho('Find extension \'%s\', enabled=%s: %s' % (name, cse_ext['enabled'], bool_to_msg(True))) except Exception: if ext_install == 'prompt': if not click.confirm('Do you want to register CSE as an API ' 'extension in vCD?'): click.secho('CSE not registered') return exchange = 'vcdext' patterns = '/api/cse,/api/cse/.*,/api/cse/.*/.*' ext.add_extension(name, name, name, exchange, patterns.split(',')) click.secho('Registered extension \'%s\': %s' % (name, bool_to_msg(True)))
def _register_cse(client, routing_key, exchange, msg_update_callback=None): """Register or update CSE on vCD. :param pyvcloud.vcd.client.Client client: :param pyvcloud.vcd.client.Client client: :param str routing_key: :param str exchange: :param utils.ConsoleMessagePrinter msg_update_callback: Callback object that writes messages onto console. """ ext = APIExtension(client) patterns = [ f'/api/{CSE_SERVICE_NAME}', f'/api/{CSE_SERVICE_NAME}/.*', f'/api/{CSE_SERVICE_NAME}/.*/.*' ] cse_info = None try: cse_info = ext.get_extension_info(CSE_SERVICE_NAME, namespace=CSE_SERVICE_NAMESPACE) except MissingRecordException: pass if cse_info is None: ext.add_extension(CSE_SERVICE_NAME, CSE_SERVICE_NAMESPACE, routing_key, exchange, patterns) msg = f"Registered {CSE_SERVICE_NAME} as an API extension in vCD" else: ext.update_extension(CSE_SERVICE_NAME, namespace=CSE_SERVICE_NAMESPACE, routing_key=routing_key, exchange=exchange) msg = f"Updated {CSE_SERVICE_NAME} API Extension in vCD" if msg_update_callback: msg_update_callback.general(msg) LOGGER.info(msg)