def get_cert(self, project_id, cert_ref, resource_ref, **kwargs): """Retrieves the specified cert. :param project_id: Project ID for the owner of the certificate :param cert_ref: the UUID of the cert to retrieve :param resource_ref: Full HATEOAS reference to the consuming resource :returns: neutron_lbaas.common.cert_manager.cert_manager.Cert representation of the certificate data :raises CertificateStorageException: if certificate retrieval fails """ LOG.info(_LI( "Loading certificate {0} from the local filesystem." ).format(cert_ref)) filename_base = os.path.join(CONF.certificates.storage_path, cert_ref) filename_certificate = "{0}.crt".format(filename_base) filename_private_key = "{0}.key".format(filename_base) filename_intermediates = "{0}.int".format(filename_base) filename_pkp = "{0}.pass".format(filename_base) cert_data = dict() try: with open(filename_certificate, 'r') as cert_file: cert_data['certificate'] = cert_file.read() except IOError: LOG.error(_LE( "Failed to read certificate for {0}." ).format(cert_ref)) raise exceptions.CertificateStorageException( msg="Certificate could not be read." ) try: with open(filename_private_key, 'r') as key_file: cert_data['private_key'] = key_file.read() except IOError: LOG.error(_LE( "Failed to read private key for {0}." ).format(cert_ref)) raise exceptions.CertificateStorageException( msg="Private Key could not be read." ) try: with open(filename_intermediates, 'r') as int_file: cert_data['intermediates'] = int_file.read() except IOError: pass try: with open(filename_pkp, 'r') as pass_file: cert_data['private_key_passphrase'] = pass_file.read() except IOError: pass return Cert(**cert_data)
def _check_and_update_entity_status_in_db(self, track_loadbalancer, db_entity, entity_status, entity_manager): if not db_entity.provisioning_status.startswith("PENDING_"): # no operation is attempted on this entity return if entity_status: if entity_status[PROV].startswith("PENDING_"): # an entity is not finished provisioning. Continue to track track_loadbalancer['track'] = True return if entity_status[PROV] == constants.ERROR: # Marked for failed completion try: entity_manager.failed_completion( self.admin_ctx, db_entity) except Exception: LOG.error(_LE("error with failed completion")) return if db_entity.provisioning_status == constants.PENDING_DELETE: # entity is under deletion # if entity is missing in lb status tree it should to be # deleted if entity_status: msg = ('Invalid status set for delete of %s in statuses', db_entity.id) LOG.error(msg) return try: entity_manager.successful_completion( self.admin_ctx, db_entity, delete=True) except Exception: LOG.error(_LE("error with successful completion")) return if entity_status[PROV] != constants.ACTIVE: msg = ('Invalid prov status for %s, should be ACTIVE ' "for CREATE and UPDATE", db_entity.id) LOG.error(msg) return try: entity_manager.successful_completion( self.admin_ctx, db_entity) except Exception: LOG.error(_LE("error with successful completion")) return
def _call(self, action, resource, data, headers, binary=False): if resource.startswith('http'): uri = resource else: uri = self.base_uri + resource if binary: body = data else: body = jsonutils.dumps(data) debug_data = 'binary' if binary else body debug_data = debug_data if debug_data else 'EMPTY' if not headers: headers = {'Authorization': 'Basic %s' % self.auth} else: headers['Authorization'] = 'Basic %s' % self.auth conn = None if self.ssl: conn = http_client.HTTPSConnection( self.server, self.port, timeout=self.timeout) if conn is None: LOG.error(_LE('vdirectRESTClient: Could not establish HTTPS ' 'connection')) return 0, None, None, None else: conn = http_client.HTTPConnection( self.server, self.port, timeout=self.timeout) if conn is None: LOG.error(_LE('vdirectRESTClient: Could not establish HTTP ' 'connection')) return 0, None, None, None try: conn.request(action, uri, body, headers) response = conn.getresponse() respstr = response.read() respdata = respstr try: respdata = jsonutils.loads(respstr) except ValueError: # response was not JSON, ignore the exception pass ret = (response.status, response.reason, respstr, respdata) except Exception as e: log_dict = {'action': action, 'e': e} LOG.error(_LE('vdirectRESTClient: %(action)s failure, %(e)r'), log_dict) ret = -1, None, None, None conn.close() return ret
def get_cert(cert_ref, service_name='lbaas', lb_id=None, check_only=False, **kwargs): """Retrieves the specified cert and registers as a consumer. :param cert_ref: the UUID of the cert to retrieve :param service_name: Friendly name for the consuming service :param lb_id: Loadbalancer id for building resource consumer URL :param check_only: Read Certificate data without registering :returns: octavia.certificates.common.Cert representation of the certificate data :raises Exception: if certificate retrieval fails """ connection = BarbicanKeystoneAuth.get_barbican_client() LOG.info(_LI( "Loading certificate container {0} from Barbican." ).format(cert_ref)) try: if check_only: cert_container = connection.containers.get( container_ref=cert_ref ) else: cert_container = connection.containers.register_consumer( container_ref=cert_ref, name=service_name, url=CertManager._get_service_url(lb_id) ) return Cert(cert_container) except Exception: with excutils.save_and_reraise_exception(): LOG.exception(_LE("Error getting {0}").format(cert_ref))
def delete_cert(self, project_id, cert_ref, resource_ref, **kwargs): """Deletes the specified cert. :param project_id: Project ID for the owner of the certificate :param cert_ref: the UUID of the cert to delete :param resource_ref: Full HATEOAS reference to the consuming resource :raises CertificateStorageException: if certificate deletion fails """ LOG.info(_LI( "Deleting certificate {0} from the local filesystem." ).format(cert_ref)) filename_base = os.path.join(CONF.certificates.storage_path, cert_ref) filename_certificate = "{0}.crt".format(filename_base) filename_private_key = "{0}.key".format(filename_base) filename_intermediates = "{0}.int".format(filename_base) filename_pkp = "{0}.pass".format(filename_base) try: os.remove(filename_certificate) os.remove(filename_private_key) os.remove(filename_intermediates) os.remove(filename_pkp) except IOError as ioe: LOG.error(_LE( "Failed to delete certificate {0}." ).format(cert_ref)) raise exceptions.CertificateStorageException(message=ioe.message)
def _remove_workflow(self, ids, context, post_remove_function): wf_name = ids['pool'] LOG.debug('Remove the workflow %s' % wf_name) resource = '/api/workflow/%s' % (wf_name) rest_return = self.rest_client.call('DELETE', resource, None, None) response = _rest_wrapper(rest_return, [204, 202, 404]) if rest_return[RESP_STATUS] == 404: if post_remove_function: try: post_remove_function(True) LOG.debug('Post-remove workflow function %r completed', post_remove_function) except Exception: with excutils.save_and_reraise_exception(): LOG.exception(_LE('Post-remove workflow function ' '%r failed'), post_remove_function) self.plugin._delete_db_vip(context, ids['vip']) else: oper = OperationAttributes( response['uri'], ids, lb_db.Vip, ids['vip'], delete=True, post_op_function=post_remove_function) LOG.debug('Pushing operation %s to the queue', oper) self._start_completion_handling_thread() self.queue.put_nowait(oper)
def get_session(): """Initializes a Keystone session. :returns: a Keystone Session object :raises Exception: if the session cannot be established """ global _SESSION if not _SESSION: auth_url = cfg.CONF.service_auth.auth_url kwargs = {'auth_url': auth_url, 'username': cfg.CONF.service_auth.admin_user, 'password': cfg.CONF.service_auth.admin_password} if cfg.CONF.service_auth.auth_version == '2': client = v2_client kwargs['tenant_name'] = cfg.CONF.service_auth.admin_tenant_name elif cfg.CONF.service_auth.auth_version == '3': client = v3_client kwargs['project_name'] = cfg.CONF.service_auth.admin_tenant_name kwargs['user_domain_name'] = (cfg.CONF.service_auth. admin_user_domain) kwargs['project_domain_name'] = (cfg.CONF.service_auth. admin_project_domain) else: raise Exception('Unknown keystone version!') try: kc = client.Password(**kwargs) _SESSION = session.Session(auth=kc) except Exception: with excutils.save_and_reraise_exception(): LOG.exception(_LE("Error creating Keystone session.")) return _SESSION
def _actually_delete_cert(cert_ref): """Deletes the specified cert. Very dangerous. Do not recommend. :param cert_ref: the UUID of the cert to delete :raises Exception: if certificate deletion fails """ connection = BarbicanKeystoneAuth.get_barbican_client() LOG.info(_LI( "Recursively deleting certificate container {0} from Barbican." ).format(cert_ref)) try: certificate_container = connection.containers.get(cert_ref) certificate_container.certificate.delete() if certificate_container.intermediates: certificate_container.intermediates.delete() if certificate_container.private_key_passphrase: certificate_container.private_key_passphrase.delete() certificate_container.private_key.delete() certificate_container.delete() except Exception: with excutils.save_and_reraise_exception(): LOG.exception(_LE( "Error recursively deleting certificate container {0}" ).format(cert_ref))
def _handle_failed_driver_call(self, operation, obj, driver): obj_type = obj.__class__.__name__.lower() LOG.exception( _LE("%(operation)s %(obj)s %(id)s failed on device " "driver %(driver)s"), {"operation": operation.capitalize(), "obj": obj_type, "id": obj.id, "driver": driver}, ) self._update_statuses(obj, error=True)
def _reload_loadbalancer(self, loadbalancer_id): try: loadbalancer_dict = self.plugin_rpc.get_loadbalancer(loadbalancer_id) loadbalancer = data_models.LoadBalancer.from_dict(loadbalancer_dict) driver_name = loadbalancer.provider.device_driver if driver_name not in self.device_drivers: LOG.error(_LE("No device driver on agent: %s."), driver_name) self.plugin_rpc.update_status("loadbalancer", loadbalancer_id, constants.ERROR) return self.device_drivers[driver_name].deploy_instance(loadbalancer) self.instance_mapping[loadbalancer_id] = driver_name self.plugin_rpc.loadbalancer_deployed(loadbalancer_id) except Exception: LOG.exception(_LE("Unable to deploy instance for " "loadbalancer: %s"), loadbalancer_id) self.needs_resync = True
def _handle_failed_driver_call(self, operation, obj, driver): obj_type = obj.__class__.__name__.lower() LOG.exception(_LE('%(operation)s %(obj)s %(id)s failed on device ' 'driver %(driver)s'), {'operation': operation.capitalize(), 'obj': obj_type, 'id': obj.id, 'driver': driver}) self._update_statuses(obj, error=True)
def get_cert(self, project_id, cert_ref, resource_ref, check_only=False, service_name='lbaas'): """Retrieves the specified cert and registers as a consumer. :param cert_ref: the UUID of the cert to retrieve :param resource_ref: Full HATEOAS reference to the consuming resource :param check_only: Read Certificate data without registering :param service_name: Friendly name for the consuming service :returns: octavia.certificates.common.Cert representation of the certificate data :raises Exception: if certificate retrieval fails """ connection = self.auth.get_barbican_client(project_id) LOG.info(_LI( "Loading certificate container {0} from Barbican." ).format(cert_ref)) try: if check_only: cert_container = connection.containers.get( container_ref=cert_ref ) else: cert_container = connection.containers.register_consumer( container_ref=cert_ref, name=service_name, url=resource_ref ) return Cert(cert_container) except Exception: with excutils.save_and_reraise_exception(): LOG.exception(_LE("Error getting {0}").format(cert_ref))
def get_host_names(certificate): """Extract the host names from the Pem encoded X509 certificate :param certificate: A PEM encoded certificate :returns: A dictionary containing the following keys: ['cn', 'dns_names'] where 'cn' is the CN from the SubjectName of the certificate, and 'dns_names' is a list of dNSNames (possibly empty) from the SubjectAltNames of the certificate. """ try: certificate = certificate.encode('ascii') cert = _get_x509_from_pem_bytes(certificate) cn = cert.subject.get_attributes_for_oid(x509.OID_COMMON_NAME)[0] host_names = { 'cn': cn.value.lower(), 'dns_names': [] } try: ext = cert.extensions.get_extension_for_oid( x509.OID_SUBJECT_ALTERNATIVE_NAME ) host_names['dns_names'] = ext.value.get_values_for_type( x509.DNSName) except x509.ExtensionNotFound: LOG.debug("%s extension not found", x509.OID_SUBJECT_ALTERNATIVE_NAME) return host_names except Exception: LOG.exception(_LE("Unreadable certificate.")) raise exceptions.UnreadableCert
def run(self): while not self.stoprequest.isSet(): try: oper = self.queue.get(timeout=1) # Get the current queue size (N) and set the counter with it. # Handle N operations with no intermission. # Once N operations handles, get the size again and repeat. if self.opers_to_handle_before_rest <= 0: self.opers_to_handle_before_rest = self.queue.qsize() + 1 LOG.debug('Operation consumed from the queue: ' + str(oper)) # check the status - if oper is done: update the db , # else push the oper again to the queue if not self.handle_operation_completion(oper): LOG.debug('Operation %s is not completed yet..' % oper) # Not completed - push to the queue again self.queue.put_nowait(oper) self.queue.task_done() self.opers_to_handle_before_rest -= 1 # Take one second rest before start handling # new operations or operations handled before if self.opers_to_handle_before_rest <= 0: time.sleep(1) except Queue.Empty: continue except Exception: LOG.error(_LE( "Exception was thrown inside OperationCompletionHandler"))
def delete_cert(cert_ref, lb_id, service_name='lbaas', **kwargs): """Deregister as a consumer for the specified cert. :param cert_ref: the UUID of the cert to retrieve :param service_name: Friendly name for the consuming service :param lb_id: Loadbalancer id for building resource consumer URL :raises Exception: if deregistration fails """ connection = BarbicanKeystoneAuth.get_barbican_client() LOG.info(_LI( "Deregistering as a consumer of {0} in Barbican." ).format(cert_ref)) try: connection.containers.remove_consumer( container_ref=cert_ref, name=service_name, url=CertManager._get_service_url(lb_id) ) except Exception: with excutils.save_and_reraise_exception(): LOG.exception(_LE( "Error deregistering as a consumer of {0}" ).format(cert_ref))
def __init__(self, plugin): super(HaproxyNSDriver, self).__init__(plugin) self.conf = cfg.CONF self.state_path = os.path.join( self.conf.haproxy.loadbalancer_state_path, STATE_PATH_V2_APPEND) if not self.conf.haproxy.interface_driver: self.conf.haproxy.interface_driver = DEFAULT_INTERFACE_DRIVER try: vif_driver_class = n_utils.load_class_by_alias_or_classname( 'neutron.interface_drivers', self.conf.haproxy.interface_driver) except ImportError: with excutils.save_and_reraise_exception(): msg = (_LE('Error importing interface driver: %s') % self.conf.haproxy.interface_driver) LOG.exception(msg) self.vif_driver = vif_driver_class(self.conf) # instantiate managers here self.load_balancer = LoadBalancerManager(self) self.listener = ListenerManager(self) self.pool = PoolManager(self) self.member = MemberManager(self) self.health_monitor = HealthMonitorManager(self) self.admin_ctx = ncontext.get_admin_context() self.deployed_loadbalancer_ids = set() self._deploy_existing_instances() SimpleHaproxyStatsService(self).start()
def __init__(self, cert_container): if not isinstance(cert_container, barbican_client.containers.CertificateContainer): raise TypeError(_LE( "Retrieved Barbican Container is not of the correct type " "(certificate).")) self._cert_container = cert_container
def _get_driver_for_pool(self, context, pool_id): pool = self.get_pool(context, pool_id) try: return self.drivers[pool['provider']] except KeyError: raise n_exc.Invalid(_LE("Error retrieving provider for pool %s") % pool_id)
def _get_driver_for_provider(self, provider): try: return self.drivers[provider] except KeyError: # raise if not associated (should never be reached) raise n_exc.Invalid(_LE("Error retrieving driver for provider " "%s") % provider)
def _report_state(self): try: instance_count = len(self.instance_mapping) self.agent_state["configurations"]["instances"] = instance_count self.state_rpc.report_state(self.context, self.agent_state) self.agent_state.pop("start_flag", None) except Exception: LOG.exception(_LE("Failed reporting state!"))
def _reload_pool(self, pool_id): try: logical_config = self.plugin_rpc.get_logical_device(pool_id) driver_name = logical_config['driver'] if driver_name not in self.device_drivers: LOG.error(_LE('No device driver on agent: %s.'), driver_name) self.plugin_rpc.update_status( 'pool', pool_id, np_const.ERROR) return self.device_drivers[driver_name].deploy_instance(logical_config) self.instance_mapping[pool_id] = driver_name self.plugin_rpc.pool_deployed(pool_id) except Exception: LOG.exception(_LE('Unable to deploy instance for pool: %s'), pool_id) self.needs_resync = True
def kill_pids_in_file(pid_path): if os.path.exists(pid_path): with open(pid_path, "r") as pids: for pid in pids: pid = pid.strip() try: linux_utils.execute(["kill", "-9", pid], run_as_root=True) except RuntimeError: LOG.exception(_LE("Unable to kill haproxy process: %s"), pid)
def _get_driver_for_loadbalancer(self, context, loadbalancer_id): lb = self.db.get_loadbalancer(context, loadbalancer_id) try: return self.drivers[lb.provider.provider_name] except KeyError: raise n_exc.Invalid( _LE("Error retrieving provider for load balancer. Possible " "providers are %s.") % self.drivers.keys() )
def _destroy_loadbalancer(self, lb_id): driver = self._get_driver(lb_id) try: driver.undeploy_instance(lb_id, delete_namespace=True) del self.instance_mapping[lb_id] self.plugin_rpc.loadbalancer_destroyed(lb_id) except Exception: LOG.exception(_LE("Unable to destroy device for loadbalancer: %s"), lb_id) self.needs_resync = True
def _destroy_pool(self, pool_id): driver = self._get_driver(pool_id) try: driver.undeploy_instance(pool_id, delete_namespace=True) del self.instance_mapping[pool_id] self.plugin_rpc.pool_destroyed(pool_id) except Exception: LOG.exception(_LE('Unable to destroy device for pool: %s'), pool_id) self.needs_resync = True
def get_barbican_client(cls, project_id=None): if not cls._barbican_client: try: cls._barbican_client = barbican_client.Client( session=keystone.get_session() ) except Exception: with excutils.save_and_reraise_exception(): LOG.exception(_LE("Error creating Barbican client")) return cls._barbican_client
def collect_stats(self, context): for loadbalancer_id, driver_name in self.instance_mapping.items(): driver = self.device_drivers[driver_name] try: stats = driver.loadbalancer.get_stats(loadbalancer_id) if stats: self.plugin_rpc.update_loadbalancer_stats(loadbalancer_id, stats) except Exception: LOG.exception(_LE("Error updating statistics on loadbalancer" " %s"), loadbalancer_id) self.needs_resync = True
def verify_lbaas_mutual_exclusion(): """Verifies lbaas v1 and lbaas v2 cannot be active concurrently.""" plugins = set([LoadBalancerPlugin.__name__, LoadBalancerPluginv2.__name__]) cfg_sps = set([sp.split('.')[-1] for sp in cfg.CONF.service_plugins]) if len(plugins.intersection(cfg_sps)) >= 2: msg = _LE("Cannot have service plugins %(v1)s and %(v2)s active at " "the same time!") % {'v1': LoadBalancerPlugin.__name__, 'v2': LoadBalancerPluginv2.__name__} LOG.error(msg) raise SystemExit(1)
def collect_stats(self, context): for pool_id, driver_name in self.instance_mapping.items(): driver = self.device_drivers[driver_name] try: stats = driver.get_stats(pool_id) if stats: self.plugin_rpc.update_pool_stats(pool_id, stats) except Exception: LOG.exception(_LE('Error updating statistics on pool %s'), pool_id) self.needs_resync = True
def _recover(self, action, resource, data, headers, binary=False): if self.server and self.secondary_server: self._flip_servers() resp = self._call(action, resource, data, headers, binary) return resp else: LOG.error(_LE('REST client is not able to recover ' 'since only one vDirect server is ' 'configured.')) return -1, None, None, None
def delete_vip(self, context, vip): """Delete a Vip First delete it from the device. If deletion ended OK - remove data from DB as well. If the deletion failed - mark vip with error status in DB """ ext_vip = self._populate_vip_graph(context, vip) params = _translate_vip_object_graph(ext_vip, self.plugin, context) ids = params.pop('__ids__') try: # get neutron port id associated with the vip (present if vip and # pip are different) and release it after workflow removed port_filter = { 'name': [_make_pip_name_from_vip(vip)], } ports = self.plugin._core_plugin.get_ports(context, filters=port_filter) if ports: LOG.debug('Retrieved pip nport: %(port)r for vip: %(vip)s', { 'port': ports[0], 'vip': vip['id'] }) delete_pip_nport_function = self._get_delete_pip_nports( context, ports) else: delete_pip_nport_function = None LOG.debug('Found no pip nports associated with vip: %s', vip['id']) # removing the WF will cause deletion of the configuration from the # device self._remove_workflow(ids, context, delete_pip_nport_function) except r_exc.RESTRequestFailure: pool_id = ext_vip['pool_id'] LOG.exception( _LE('Failed to remove workflow %s. ' 'Going to set vip to ERROR status'), pool_id) self.plugin.update_status(context, lb_db.Vip, ids['vip'], constants.ERROR)
def create_loadbalancer(self, context, loadbalancer, driver_name): loadbalancer = data_models.LoadBalancer.from_dict(loadbalancer) if driver_name not in self.device_drivers: LOG.error(_LE('No device driver on agent: %s.'), driver_name) self.plugin_rpc.update_status('loadbalancer', loadbalancer.id, provisioning_status=constants.ERROR) return driver = self.device_drivers[driver_name] try: driver.loadbalancer.create(loadbalancer) except Exception: self._handle_failed_driver_call('create', loadbalancer, driver.get_name()) else: self.instance_mapping[loadbalancer.id] = driver_name self._update_statuses(loadbalancer)
def _check_orphan_loadbalancer_associations(self, context, provider_names): """Checks remaining associations between loadbalancers and providers. If admin has not undeployed resources with provider that was deleted from configuration, neutron service is stopped. Admin must delete resources prior to removing providers from configuration. """ loadbalancers = self.db.get_loadbalancers(context) lost_providers = set( [lb.provider.provider_name for lb in loadbalancers if lb.provider.provider_name not in provider_names]) # resources are left without provider - stop the service if lost_providers: msg = _LE("Delete associated load balancers before " "removing providers %s") % list(lost_providers) LOG.error(msg) raise SystemExit(1)
def __init__(self, service_uri, username, password, ncc_cleanup_mode="False"): if not service_uri: LOG.exception( _LE("No NetScaler Control Center URI specified. " "Cannot connect.")) raise NCCException(NCCException.CONNECTION_ERROR) self.service_uri = service_uri.strip('/') self.auth = None self.cleanup_mode = False if username and password: self.username = username self.password = password if ncc_cleanup_mode.lower() == "true": self.cleanup_mode = True
def _call_driver_operation(self, context, driver_method, db_entity, old_db_entity=None): manager_method = "%s.%s" % (driver_method.__self__.__class__.__name__, driver_method.__name__) LOG.info(_LI("Calling driver operation %s") % manager_method) try: if old_db_entity: driver_method(context, old_db_entity, db_entity) else: driver_method(context, db_entity) # catching and reraising agent issues except (lbaas_agentschedulerv2.NoEligibleLbaasAgent, lbaas_agentschedulerv2.NoActiveLbaasAgent) as no_agent: raise no_agent except Exception: LOG.exception(_LE("There was an error in the driver")) self._handle_driver_error(context, db_entity) raise loadbalancerv2.DriverError()
def _delete_db_pool(self, context, id): # proxy the call until plugin inherits from DBPlugin # rely on uuid uniqueness: try: with context.session.begin(subtransactions=True): self.service_type_manager.del_resource_associations( context, [id]) super(LoadBalancerPlugin, self).delete_pool(context, id) except Exception: # that should not happen # if it's still a case - something goes wrong # log the error and mark the pool as ERROR LOG.error(_LE('Failed to delete pool %s, putting it in ERROR ' 'state'), id) with excutils.save_and_reraise_exception(): self.update_status(context, ldb.Pool, id, constants.ERROR)
def handle_operation_completion(self, oper): result = self.rest_client.call('GET', oper.operation_url, None, None) completed = result[RESP_DATA]['complete'] reason = result[RESP_REASON], description = result[RESP_STR] if completed: # operation is done - update the DB with the status # or delete the entire graph from DB success = result[RESP_DATA]['success'] sec_to_completion = time.time() - oper.creation_time debug_data = { 'oper': oper, 'sec_to_completion': sec_to_completion, 'success': success } LOG.debug( 'Operation %(oper)s is completed after ' '%(sec_to_completion)d sec ' 'with success status: %(success)s :', debug_data) db_status = None if not success: # failure - log it and set the return ERROR as DB state if reason or description: msg = 'Reason:%s. Description:%s' % (reason, description) else: msg = "unknown" error_params = {"operation": oper, "msg": msg} LOG.error( _LE('Operation %(operation)s failed. Reason: ' '%(msg)s'), error_params) db_status = constants.ERROR else: if oper.delete: _remove_object_from_db(self.plugin, oper) else: db_status = constants.ACTIVE if db_status: _update_vip_graph_status(self.plugin, oper, db_status) OperationCompletionHandler._run_post_op_function(success, oper) return completed
def handle_operation_completion(self, oper): result = self.rest_client.call('GET', oper.operation_url, None, None) LOG.debug('Operation completion requested %(uri)s and got: %(result)s', { 'uri': oper.operation_url, 'result': result }) completed = result[rest.RESP_DATA]['complete'] reason = result[rest.RESP_REASON], description = result[rest.RESP_STR] if completed: # operation is done - update the DB with the status # or delete the entire graph from DB success = result[rest.RESP_DATA]['success'] sec_to_completion = time.time() - oper.creation_time debug_data = { 'oper': oper, 'sec_to_completion': sec_to_completion, 'success': success } LOG.debug( 'Operation %(oper)s is completed after ' '%(sec_to_completion)d sec ' 'with success status: %(success)s :', debug_data) if not success: # failure - log it and set the return ERROR as DB state if reason or description: msg = 'Reason:%s. Description:%s' % (reason, description) else: msg = "unknown" error_params = {"operation": oper, "msg": msg} LOG.error( _LE('Operation %(operation)s failed. Reason: %(msg)s'), error_params) oper.status = constants.ERROR OperationCompletionHandler._run_post_failure_function(oper) else: oper.status = constants.ACTIVE OperationCompletionHandler._run_post_success_function(oper) return completed
def get_session(): """Initializes a Keystone session. :returns: a Keystone Session object :raises Exception: if the session cannot be established """ global _SESSION if not _SESSION: auth_url = cfg.CONF.service_auth.auth_url insecure = cfg.CONF.service_auth.insecure kwargs = { 'auth_url': auth_url, 'username': cfg.CONF.service_auth.admin_user, 'password': cfg.CONF.service_auth.admin_password } if cfg.CONF.service_auth.auth_version == '2': client = v2_client kwargs['tenant_name'] = cfg.CONF.service_auth.admin_tenant_name elif cfg.CONF.service_auth.auth_version == '3': client = v3_client kwargs['project_name'] = cfg.CONF.service_auth.admin_tenant_name kwargs['user_domain_name'] = ( cfg.CONF.service_auth.admin_user_domain) kwargs['project_domain_name'] = ( cfg.CONF.service_auth.admin_project_domain) else: raise Exception(_('Unknown keystone version!')) try: kc = client.Password(**kwargs) _SESSION = session.Session(auth=kc, verify=not insecure) except Exception: with excutils.save_and_reraise_exception(): LOG.exception(_LE("Error creating Keystone session.")) return _SESSION
def remove_workflow(self, ctx, manager, lb): wf_name = self._get_wf_name(lb) LOG.debug('Remove the workflow %s' % wf_name) resource = '/api/workflow/%s' % (wf_name) rest_return = self.rest_client.call('DELETE', resource, None, None) response = _rest_wrapper(rest_return, [204, 202, 404]) if rest_return[rest.RESP_STATUS] in [404]: try: self._delete_proxy_port(ctx, lb) LOG.debug('Proxy port for LB %s was deleted', lb.id) except Exception: with excutils.save_and_reraise_exception(): LOG.error(_LE('Proxy port deletion for LB %s ' 'failed'), lb.id) manager.successful_completion(ctx, lb, delete=True) else: oper = OperationAttributes( manager, response['uri'], lb, lb, old_data_model=None, delete=True, post_operation_function=self._delete_proxy_port) self._start_completion_handling_thread() self.queue.put_nowait(oper)
class UnsupportedEntityOperation(RadwareLBaasV2Exception): message = _LE('%(operation)s operation is not supported for %(entity)s.')
def _update_status_tree_in_db(self, lb_id, loadbalancer_statuses): track_loadbalancer = {"track": False} db_lb = self.plugin.db.get_loadbalancer(self.admin_ctx, lb_id) if (not loadbalancer_statuses and db_lb.provisioning_status == constants.PENDING_DELETE): try: self.load_balancer.successful_completion( self.admin_ctx, db_lb, delete=True) except Exception: LOG.error(_LE("error with successful completion")) PROVISIONING_STATUS_TRACKER.remove(lb_id) return else: status_lb = loadbalancer_statuses["loadbalancer"] status_listeners = status_lb["listeners"] for db_listener in db_lb.listeners: db_listener.loadbalancer = db_lb status_listener = (self. _update_entity_status_in_db(track_loadbalancer, db_listener, status_listeners, self.listener)) if not status_listener: continue db_pool = db_listener.default_pool if not db_pool: continue db_pool.listener = db_listener status_pools = status_listener['pools'] status_pool = self._update_entity_status_in_db(track_loadbalancer, db_pool, status_pools, self.pool) db_members = db_pool.members if not status_pool: continue status_members = status_pool['members'] for db_member in db_members: db_member.pool = db_pool self._update_entity_status_in_db(track_loadbalancer, db_member, status_members, self.member) db_hm = db_pool.healthmonitor if db_hm: db_hm.pool = db_pool status_hm = status_pool['healthmonitor'] self._update_entity_status_in_db(track_loadbalancer, db_hm, [status_hm], self.health_monitor) if not track_loadbalancer['track']: self._update_entity_status_in_db( track_loadbalancer, db_lb, status_lb, self.load_balancer) if not track_loadbalancer['track']: PROVISIONING_STATUS_TRACKER.remove(lb_id)
def _handle_failed_driver_call(self, operation, obj_type, obj_id, driver): LOG.exception(_LE('%(operation)s %(obj)s %(id)s failed on device ' 'driver %(driver)s'), {'operation': operation.capitalize(), 'obj': obj_type, 'id': obj_id, 'driver': driver}) self.plugin_rpc.update_status(obj_type, obj_id, np_const.ERROR)
class UnreadableCert(TLSException): message = _LE("Could not read X509 from PEM")
class RESTRequestFailure(RadwareLBaasV2Exception): message = _LE('REST request failed with status %(status)s. ' 'Reason: %(reason)s, Description: %(description)s. ' 'Success status codes are %(success_codes)s')
def check_subnet_in_use(self, context, subnet_id): query = context.session.query(Pool).filter_by(subnet_id=subnet_id) if query.count(): pool_id = query.one().id raise n_exc.SubnetInUse( reason=_LE("Subnet is used by loadbalancer pool %s") % pool_id)
def _get_driver_for_provider(self, provider): if provider in self.drivers: return self.drivers[provider] # raise if not associated (should never be reached) raise n_exc.Invalid(_LE("Error retrieving driver for provider %s") % provider)
class LoadbalancerReschedulingFailed(exceptions.Conflict): message = _LE("Failed rescheduling loadbalancer %(loadbalancer_id)s: " "no eligible lbaas agent found.")
class CertificateStorageException(TLSException): message = _LE('Could not store certificate: %(msg)s')
class MisMatchedKey(TLSException): message = _LE("Key and x509 certificate do not match")
class RadwareLBaasV2Exception(exceptions.LbaasException): message = _LE('An unknown exception occurred in ' 'Radware LBaaS v2 provider.')
class ModelMapException(exceptions.NeutronException): message = _LE("Unable to map model class %(target_name)s")
def store_cert(self, project_id, certificate, private_key, intermediates=None, private_key_passphrase=None, expiration=None, name='LBaaS TLS Cert'): """Stores a certificate in the certificate manager. :param certificate: PEM encoded TLS certificate :param private_key: private key for the supplied certificate :param intermediates: ordered and concatenated intermediate certs :param private_key_passphrase: optional passphrase for the supplied key :param expiration: the expiration time of the cert in ISO 8601 format :param name: a friendly name for the cert :returns: the container_ref of the stored cert :raises Exception: if certificate storage fails """ connection = self.auth.get_barbican_client(project_id) LOG.info( _LI("Storing certificate container '{0}' in Barbican.").format( name)) certificate_secret = None private_key_secret = None intermediates_secret = None pkp_secret = None try: certificate_secret = connection.secrets.create( payload=certificate, expiration=expiration, name="Certificate") private_key_secret = connection.secrets.create( payload=private_key, expiration=expiration, name="Private Key") certificate_container = connection.containers.create_certificate( name=name, certificate=certificate_secret, private_key=private_key_secret) if intermediates: intermediates_secret = connection.secrets.create( payload=intermediates, expiration=expiration, name="Intermediates") certificate_container.intermediates = intermediates_secret if private_key_passphrase: pkp_secret = connection.secrets.create( payload=private_key_passphrase, expiration=expiration, name="Private Key Passphrase") certificate_container.private_key_passphrase = pkp_secret certificate_container.store() return certificate_container.container_ref # Barbican (because of Keystone-middleware) sometimes masks # exceptions strangely -- this will catch anything that it raises and # reraise the original exception, while also providing useful # feedback in the logs for debugging except Exception: for secret in [ certificate_secret, private_key_secret, intermediates_secret, pkp_secret ]: if secret and secret.secret_ref: old_ref = secret.secret_ref try: secret.delete() LOG.info( _LI("Deleted secret {0} ({1}) during rollback."). format(secret.name, old_ref)) except Exception: LOG.warning( _LW("Failed to delete {0} ({1}) during rollback. This " "is probably not a problem.").format( secret.name, old_ref)) with excutils.save_and_reraise_exception(): LOG.exception(_LE("Error storing certificate data"))
class NeedsPassphrase(TLSException): message = _LE("Passphrase needed to decrypt key but client " "did not provide one.")
def _execute_request(self, method, resource_uri, headers, body=None): service_uri_dict = {"service_uri": self.service_uri} try: response = requests.request(method, url=resource_uri, headers=headers, data=body) except requests.exceptions.SSLError: LOG.exception(_LE("SSL error occurred while connecting " "to %(service_uri)s"), service_uri_dict) raise NCCException(NCCException.CONNECTION_ERROR) except requests.exceptions.ConnectionError: LOG.exception(_LE("Connection error occurred while connecting" "to %(service_uri)s"), service_uri_dict) raise NCCException(NCCException.CONNECTION_ERROR) except requests.exceptions.Timeout: LOG.exception( _LE("Request to %(service_uri)s timed out"), service_uri_dict) raise NCCException(NCCException.CONNECTION_ERROR) except (requests.exceptions.URLRequired, requests.exceptions.InvalidURL, requests.exceptions.MissingSchema, requests.exceptions.InvalidSchema): LOG.exception(_LE("Request did not specify a valid URL")) raise NCCException(NCCException.REQUEST_ERROR) except requests.exceptions.TooManyRedirects: LOG.exception(_LE("Too many redirects occurred for request ")) raise NCCException(NCCException.REQUEST_ERROR) except requests.exceptions.RequestException: LOG.exception( _LE("A request error while connecting to %(service_uri)s"), service_uri_dict) raise NCCException(NCCException.REQUEST_ERROR) except Exception: LOG.exception( _LE("A unknown error occurred during request to" " %(service_uri)s"), service_uri_dict) raise NCCException(NCCException.UNKNOWN_ERROR) resp_dict = self._get_response_dict(response) resp_body = resp_dict['body'] LOG.info(_LI("Response: %(resp_body)s"), {"resp_body": resp_body}) response_status = resp_dict['status'] if response_status == requests.codes.unauthorized: LOG.exception(_LE("Unable to login. Invalid credentials passed." "for: %s"), self.service_uri) if not self.is_login(resource_uri): # Session expired, relogin and retry.... self.login() # Retry the operation headers.update({AUTH_HEADER: self.auth}) self._execute_request(method, resource_uri, headers, body) else: raise NCCException(NCCException.RESPONSE_ERROR) if not self._is_valid_response(response_status): response_msg = resp_body response_dict = {"method": method, "url": resource_uri, "response_status": response_status, "response_msg": response_msg} LOG.exception(_LE("Failed %(method)s operation on %(url)s " "status code: %(response_status)s " "message: %(response_msg)s"), response_dict) raise NCCException(NCCException.RESPONSE_ERROR, response_status) return response_status, resp_dict
def periodic_tasks(self, *args): try: self._collect_and_store_stats() except Exception: LOG.exception(_LE("Periodic task failed."))
class AuthenticationMissing(RadwareLBaasV2Exception): message = _LE('vDirect user/password missing. ' 'Specify in configuration file, under [radwarev2] section')
class WorkflowTemplateMissing(RadwareLBaasV2Exception): message = _LE('Workflow template %(workflow_template)s is missing ' 'on vDirect server. Upload missing workflow')