diff --git a/devstack/plugin.sh b/devstack/plugin.sh index 6c95c2e08a..d6b0048291 100644 --- a/devstack/plugin.sh +++ b/devstack/plugin.sh @@ -321,6 +321,16 @@ function octavia_configure { iniset $OCTAVIA_CONF service_auth cafile $SSL_BUNDLE_FILE iniset $OCTAVIA_CONF service_auth memcached_servers $SERVICE_HOST:11211 + # neutron + iniset $OCTAVIA_CONF neutron auth_url $KEYSTONE_SERVICE_URI + iniset $OCTAVIA_CONF neutron auth_type password + iniset $OCTAVIA_CONF neutron username $OCTAVIA_USERNAME + iniset $OCTAVIA_CONF neutron password $OCTAVIA_PASSWORD + iniset $OCTAVIA_CONF neutron user_domain_name $OCTAVIA_USER_DOMAIN_NAME + iniset $OCTAVIA_CONF neutron project_name $OCTAVIA_PROJECT_NAME + iniset $OCTAVIA_CONF neutron project_domain_name $OCTAVIA_PROJECT_DOMAIN_NAME + iniset $OCTAVIA_CONF neutron cafile $SSL_BUNDLE_FILE + # Setting other required default options iniset $OCTAVIA_CONF controller_worker amphora_driver ${OCTAVIA_AMPHORA_DRIVER} iniset $OCTAVIA_CONF controller_worker compute_driver ${OCTAVIA_COMPUTE_DRIVER} diff --git a/octavia/common/clients.py b/octavia/common/clients.py index 771944db03..fa6ee54f83 100644 --- a/octavia/common/clients.py +++ b/octavia/common/clients.py @@ -12,9 +12,11 @@ from cinderclient import client as cinder_client from glanceclient import client as glance_client -from neutronclient.neutron import client as neutron_client +from keystoneauth1 import session +from keystoneauth1 import token_endpoint from novaclient import api_versions from novaclient import client as nova_client +import openstack from oslo_config import cfg from oslo_log import log as logging from oslo_utils import excutils @@ -25,7 +27,6 @@ LOG = logging.getLogger(__name__) CONF = cfg.CONF GLANCE_VERSION = '2' -NEUTRON_VERSION = '2.0' NOVA_VERSION = '2.15' CINDER_VERSION = '3' @@ -73,38 +74,20 @@ class NeutronAuth(object): neutron_client = None @classmethod - def get_neutron_client(cls, region, service_name=None, endpoint=None, - endpoint_type='publicURL', insecure=False, - ca_cert=None): - """Create neutron client object. - - :param region: The region of the service - :param service_name: The name of the neutron service in the catalog - :param endpoint: The endpoint of the service - :param endpoint_type: The endpoint_type of the service - :param insecure: Turn off certificate validation - :param ca_cert: CA Cert file path - :return: a Neutron Client object. - :raises Exception: if the client cannot be created - """ - ksession = keystone.KeystoneSession() + def get_neutron_client(cls): + """Create neutron client object.""" + ksession = keystone.KeystoneSession('neutron') if not cls.neutron_client: - kwargs = {'region_name': region, - 'session': ksession.get_session(), - 'endpoint_type': endpoint_type, - 'insecure': insecure} - if service_name: - kwargs['service_name'] = service_name - if endpoint: - kwargs['endpoint_override'] = endpoint - if ca_cert: - kwargs['ca_cert'] = ca_cert - try: - cls.neutron_client = neutron_client.Client( - NEUTRON_VERSION, **kwargs) - except Exception: - with excutils.save_and_reraise_exception(): - LOG.exception("Error creating Neutron client.") + sess = ksession.get_session() + + kwargs = {} + if CONF.neutron.endpoint_override: + kwargs['network_endpoint_override'] = ( + CONF.neutron.endpoint_override) + + conn = openstack.connection.Connection( + session=sess, **kwargs) + cls.neutron_client = conn return cls.neutron_client @classmethod @@ -113,26 +96,23 @@ class NeutronAuth(object): It's possible that the token in the context is a trust scoped which can't be used to initialize a keystone session. - We directly use the token and endpoint_url to initialize neutron client. """ - neutron_endpoint = CONF.neutron.endpoint - if not neutron_endpoint: - session = keystone.KeystoneSession().get_session() - endpoint_data = session.get_endpoint_data( + sess = keystone.KeystoneSession('neutron').get_session() + neutron_endpoint = CONF.neutron.endpoint_override + if neutron_endpoint is None: + endpoint_data = sess.get_endpoint_data( service_type='network', interface=CONF.neutron.endpoint_type, region_name=CONF.neutron.region_name) neutron_endpoint = endpoint_data.catalog_url - kwargs = { - 'token': context.auth_token, - 'endpoint_url': neutron_endpoint, - 'insecure': CONF.neutron.insecure, - 'ca_cert': CONF.neutron.ca_certificates_file - } + user_auth = token_endpoint.Token(neutron_endpoint, context.auth_token) + user_sess = session.Session(auth=user_auth) - return neutron_client.Client(NEUTRON_VERSION, **kwargs) + conn = openstack.connection.Connection( + session=user_sess, oslo_conf=CONF) + return conn.network class GlanceAuth(object): diff --git a/octavia/common/config.py b/octavia/common/config.py index 345da4cca4..a285e6a3b9 100644 --- a/octavia/common/config.py +++ b/octavia/common/config.py @@ -37,10 +37,6 @@ from octavia import version LOG = logging.getLogger(__name__) -EXTRA_LOG_LEVEL_DEFAULTS = [ - 'neutronclient.v2_0.client=INFO', -] - core_opts = [ cfg.HostnameOpt('host', default=utils.get_hostname(), sample_default='', @@ -89,7 +85,7 @@ api_opts = [ 'octavia.api.drivers entrypoint.'), default={'amphora': 'The Octavia Amphora driver.', 'octavia': 'Deprecated alias of the Octavia Amphora ' - 'driver.', + 'driver.', }), cfg.StrOpt('default_provider_driver', default='amphora', help=_('Default provider driver.')), @@ -747,21 +743,27 @@ cinder_opts = [ ] neutron_opts = [ - cfg.StrOpt('service_name', - help=_('The name of the neutron service in the ' - 'keystone catalog')), cfg.StrOpt('endpoint', help=_('A new endpoint to override the endpoint ' - 'in the keystone catalog.')), - cfg.StrOpt('region_name', - help=_('Region in Identity service catalog to use for ' - 'communication with the OpenStack services.')), - cfg.StrOpt('endpoint_type', default='publicURL', - help=_('Endpoint interface in identity service to use')), + 'in the keystone catalog.'), + deprecated_for_removal=True, + deprecated_reason=_('The endpoint_override option defined by ' + 'keystoneauth1 is the new name for this ' + 'option.'), + deprecated_since='2023.2/Bobcat'), + cfg.StrOpt('endpoint_type', help=_('Endpoint interface in identity ' + 'service to use'), + deprecated_for_removal=True, + deprecated_reason=_('This option was replaced by the ' + 'valid_interfaces option defined by ' + 'keystoneauth.'), + deprecated_since='2023.2/Bobcat'), cfg.StrOpt('ca_certificates_file', - help=_('CA certificates file path')), - cfg.BoolOpt('insecure', - default=False, - help=_('Disable certificate validation on SSL connections ')), + help=_('CA certificates file path'), + deprecated_for_removal=True, + deprecated_reason=_('The cafile option defined by ' + 'keystoneauth1 is the new name for this ' + 'option.'), + deprecated_since='2023.2/Bobcat'), ] glance_opts = [ @@ -902,8 +904,16 @@ _SQL_CONNECTION_DEFAULT = 'sqlite://' db_options.set_defaults(cfg.CONF, connection=_SQL_CONNECTION_DEFAULT, max_pool_size=10, max_overflow=20, pool_timeout=10) -ks_loading.register_auth_conf_options(cfg.CONF, constants.SERVICE_AUTH) -ks_loading.register_session_conf_options(cfg.CONF, constants.SERVICE_AUTH) + +def register_ks_options(group): + ks_loading.register_auth_conf_options(cfg.CONF, group) + ks_loading.register_session_conf_options(cfg.CONF, group) + ks_loading.register_adapter_conf_options(cfg.CONF, group, + include_deprecated=False) + + +register_ks_options(constants.SERVICE_AUTH) +register_ks_options('neutron') def register_cli_opts(): @@ -911,6 +921,31 @@ def register_cli_opts(): logging.register_options(cfg.CONF) +def handle_neutron_deprecations(): + # Apply neutron deprecated options to their new setting if needed + + # Basicaly: if the value of the deprecated option is not the default: + # * convert it to a valid "new" value if needed + # * set it as the default for the new option + # Thus [neutron]. has an higher precedence than + # [neutron]. + loc = cfg.CONF.get_location('endpoint', 'neutron') + if loc and loc.location != cfg.Locations.opt_default: + cfg.CONF.set_default('endpoint_override', cfg.CONF.neutron.endpoint, + 'neutron') + + loc = cfg.CONF.get_location('endpoint_type', 'neutron') + if loc and loc.location != cfg.Locations.opt_default: + endpoint_type = cfg.CONF.neutron.endpoint_type.replace('URL', '') + cfg.CONF.set_default('valid_interfaces', [endpoint_type], + 'neutron') + + loc = cfg.CONF.get_location('ca_certificates_file', 'neutron') + if loc and loc.location != cfg.Locations.opt_default: + cfg.CONF.set_default('cafile', cfg.CONF.neutron.ca_certificates_file, + 'neutron') + + def init(args, **kwargs): register_cli_opts() cfg.CONF(args=args, project='octavia', @@ -920,14 +955,20 @@ def init(args, **kwargs): setup_remote_debugger() validate.check_default_ciphers_prohibit_list_conflict() + # Override default auth_type for plugins with the default from service_auth + auth_type = cfg.CONF.service_auth.auth_type + cfg.CONF.set_default('auth_type', auth_type, 'neutron') + + handle_neutron_deprecations() + def setup_logging(conf): """Sets up the logging options for a log with supplied name. :param conf: a cfg.ConfOpts object """ - logging.set_defaults(default_log_levels=logging.get_default_log_levels() + - EXTRA_LOG_LEVEL_DEFAULTS) + ll = logging.get_default_log_levels() + logging.set_defaults(default_log_levels=ll) product_name = "octavia" logging.setup(conf, product_name) LOG.info("Logging enabled!") diff --git a/octavia/common/keystone.py b/octavia/common/keystone.py index 8c5214d390..507f33facf 100644 --- a/octavia/common/keystone.py +++ b/octavia/common/keystone.py @@ -12,6 +12,7 @@ # License for the specific language governing permissions and limitations # under the License. +from keystoneauth1 import exceptions as ks_exceptions from keystoneauth1 import loading as ks_loading from keystonemiddleware import auth_token from oslo_config import cfg @@ -32,14 +33,17 @@ class KeystoneSession(object): self._auth = None self.section = section - ks_loading.register_auth_conf_options(cfg.CONF, self.section) - ks_loading.register_session_conf_options(cfg.CONF, self.section) - def get_session(self): + def get_session(self, auth=None): """Initializes a Keystone session. :return: a Keystone Session object """ + if auth: + # Do not use the singleton with custom auth params + return ks_loading.load_session_from_conf_options( + cfg.CONF, self.section, auth=auth) + if not self._session: self._session = ks_loading.load_session_from_conf_options( cfg.CONF, self.section, auth=self.get_auth()) @@ -48,8 +52,57 @@ class KeystoneSession(object): def get_auth(self): if not self._auth: - self._auth = ks_loading.load_auth_from_conf_options( - cfg.CONF, self.section) + try: + self._auth = ks_loading.load_auth_from_conf_options( + cfg.CONF, self.section) + except ks_exceptions.auth_plugins.MissingRequiredOptions as e: + if self.section == constants.SERVICE_AUTH: + raise e + # NOTE(gthiemonge): MissingRequiredOptions is raised: there is + # one or more missing auth options in the config file. It may + # be due to the migration from python-neutronclient to + # openstacksdk. + # With neutronclient, most of the auth settings were in + # [service_auth] with a few overrides in [neutron], + # but with openstacksdk, we have all the auth settings in the + # [neutron] section. In order to support smooth upgrades, in + # case those options are missing, we override the undefined + # options with the existing settings from [service_auth]. + + # This code should be removed when all the deployment tools set + # the correct options in [neutron] + + # The config options are lazily registered/loaded by keystone, + # it means that we cannot get/set them before invoking + # 'load_auth_from_conf_options' on 'service_auth'. + ks_loading.load_auth_from_conf_options( + cfg.CONF, constants.SERVICE_AUTH) + + config = getattr(cfg.CONF, self.section) + for opt in config: + # For each option in the [neutron] section, get its setting + # location, if the location is 'opt_default' or + # 'set_default', it means that the option is not configured + # in the config file, it should be replaced with the one + # from [service_auth] + loc = cfg.CONF.get_location(opt, self.section) + if not loc or loc.location in (cfg.Locations.opt_default, + cfg.Locations.set_default): + if hasattr(cfg.CONF.service_auth, opt): + cur_value = getattr(config, opt) + value = getattr(cfg.CONF.service_auth, opt) + if value != cur_value: + log_value = (value if opt != "password" + else "") + LOG.debug("Overriding [%s].%s with '%s'", + self.section, opt, log_value) + cfg.CONF.set_override(opt, value, self.section) + + # Now we can call load_auth_from_conf_options for this specific + # service with the newly defined options. + self._auth = ks_loading.load_auth_from_conf_options( + cfg.CONF, self.section) + return self._auth def get_service_user_id(self): diff --git a/octavia/network/drivers/neutron/allowed_address_pairs.py b/octavia/network/drivers/neutron/allowed_address_pairs.py index fbaacd3c55..bb0d8a5345 100644 --- a/octavia/network/drivers/neutron/allowed_address_pairs.py +++ b/octavia/network/drivers/neutron/allowed_address_pairs.py @@ -14,9 +14,9 @@ import ipaddress import time -from neutronclient.common import exceptions as neutron_client_exceptions from novaclient import exceptions as nova_client_exceptions from octavia_lib.common import constants as lib_consts +import openstack.exceptions as os_exceptions from oslo_config import cfg from oslo_log import log as logging from stevedore import driver as stevedore_driver @@ -84,14 +84,15 @@ class AllowedAddressPairsDriver(neutron_base.BaseNeutronDriver): def _plug_amphora_vip(self, amphora, subnet): # We need a vip port owned by Octavia for Act/Stby and failover try: - port = {constants.PORT: { + port = { constants.NAME: 'octavia-lb-vrrp-' + amphora.id, constants.NETWORK_ID: subnet.network_id, constants.FIXED_IPS: [{'subnet_id': subnet.id}], constants.ADMIN_STATE_UP: True, - constants.DEVICE_OWNER: OCTAVIA_OWNER}} - new_port = self.neutron_client.create_port(port) - new_port = utils.convert_port_dict_to_model(new_port) + constants.DEVICE_OWNER: OCTAVIA_OWNER, + } + new_port = self.network_proxy.create_port(**port) + new_port = utils.convert_port_to_model(new_port) LOG.debug('Created vip port: %(port_id)s for amphora: %(amp)s', {'port_id': new_port.id, 'amp': amphora.id}) @@ -112,7 +113,7 @@ class AllowedAddressPairsDriver(neutron_base.BaseNeutronDriver): LOG.exception(message) try: if new_port: - self.neutron_client.delete_port(new_port.id) + self.network_proxy.delete_port(new_port.id) LOG.debug('Deleted base (VRRP) port %s due to plug_port ' 'failure.', new_port.id) except Exception: @@ -126,7 +127,7 @@ class AllowedAddressPairsDriver(neutron_base.BaseNeutronDriver): def _add_vip_address_pairs(self, port_id, vip_address_list): try: self._add_allowed_address_pairs_to_port(port_id, vip_address_list) - except neutron_client_exceptions.PortNotFoundClient as e: + except os_exceptions.ResourceNotFound as e: raise base.PortNotFound(str(e)) except Exception as e: message = _('Error adding allowed address pair(s) {ips} ' @@ -138,10 +139,8 @@ class AllowedAddressPairsDriver(neutron_base.BaseNeutronDriver): def _get_lb_security_group(self, load_balancer_id): sec_grp_name = common_utils.get_vip_security_group_name( load_balancer_id) - sec_grps = self.neutron_client.list_security_groups(name=sec_grp_name) - if sec_grps and sec_grps.get(constants.SECURITY_GROUPS): - return sec_grps.get(constants.SECURITY_GROUPS)[0] - return None + sec_grp = self.network_proxy.find_security_group(sec_grp_name) + return sec_grp def _get_ethertype_for_ip(self, ip): address = ipaddress.ip_address(ip) @@ -152,8 +151,8 @@ class AllowedAddressPairsDriver(neutron_base.BaseNeutronDriver): return 'IPv6' if net.version == 6 else 'IPv4' def _update_security_group_rules(self, load_balancer, sec_grp_id): - rules = self.neutron_client.list_security_group_rules( - security_group_id=sec_grp_id) + rules = tuple(self.network_proxy.security_group_rules( + security_group_id=sec_grp_id)) updated_ports = [] listener_peer_ports = [] @@ -192,11 +191,11 @@ class AllowedAddressPairsDriver(neutron_base.BaseNeutronDriver): # port_range_max and min will be the same since this driver is # responsible for creating these rules old_ports = [] - for rule in rules.get('security_group_rules', []): + for rule in rules: # Don't remove egress rules and don't confuse other protocols with # None ports with the egress rules. VRRP uses protocol 51 and 112 if (rule.get('direction') == 'egress' or - rule.get('protocol').upper() not in + rule.get('protocol').upper() not in [constants.PROTOCOL_TCP, constants.PROTOCOL_UDP, lib_consts.PROTOCOL_SCTP]): continue @@ -206,7 +205,7 @@ class AllowedAddressPairsDriver(neutron_base.BaseNeutronDriver): add_ports = set(updated_ports) - set(old_ports) del_ports = set(old_ports) - set(updated_ports) - for rule in rules.get('security_group_rules', []): + for rule in rules: if (rule.get('protocol', '') and rule.get('protocol', '').upper() in [constants.PROTOCOL_TCP, constants.PROTOCOL_UDP, @@ -215,8 +214,8 @@ class AllowedAddressPairsDriver(neutron_base.BaseNeutronDriver): rule.get('remote_ip_prefix')) in del_ports): rule_id = rule.get(constants.ID) try: - self.neutron_client.delete_security_group_rule(rule_id) - except neutron_client_exceptions.NotFound: + self.network_proxy.delete_security_group_rule(rule_id) + except os_exceptions.ResourceNotFound: LOG.info("Security group rule %s not found, will assume " "it is already deleted.", rule_id) @@ -247,7 +246,7 @@ class AllowedAddressPairsDriver(neutron_base.BaseNeutronDriver): constants.VRRP_PROTOCOL_NUM, direction='ingress', ethertype=primary_ethertype) - except neutron_client_exceptions.Conflict: + except os_exceptions.ConflictException: # It's ok if this rule already exists pass except Exception as e: @@ -257,7 +256,7 @@ class AllowedAddressPairsDriver(neutron_base.BaseNeutronDriver): self._create_security_group_rule( sec_grp_id, constants.AUTH_HEADER_PROTOCOL_NUMBER, direction='ingress', ethertype=primary_ethertype) - except neutron_client_exceptions.Conflict: + except os_exceptions.ConflictException: # It's ok if this rule already exists pass except Exception as e: @@ -284,10 +283,10 @@ class AllowedAddressPairsDriver(neutron_base.BaseNeutronDriver): attempts = 0 while attempts <= CONF.networking.max_retries: try: - self.neutron_client.delete_security_group(sec_grp) + self.network_proxy.delete_security_group(sec_grp) LOG.info("Deleted security group %s", sec_grp) return - except neutron_client_exceptions.NotFound: + except os_exceptions.ResourceNotFound: LOG.info("Security group %s not found, will assume it is " "already deleted", sec_grp) return @@ -304,31 +303,33 @@ class AllowedAddressPairsDriver(neutron_base.BaseNeutronDriver): def _delete_security_group(self, vip, port): if self.sec_grp_enabled: - sec_grp = self._get_lb_security_group(vip.load_balancer.id) + try: + lb_id = vip.load_balancer.id + except AttributeError: + sec_grp = None + else: + sec_grp = self._get_lb_security_group(lb_id) if sec_grp: - sec_grp_id = sec_grp.get(constants.ID) + sec_grp_id = sec_grp.id LOG.info( "Removing security group %(sg)s from port %(port)s", {'sg': sec_grp_id, constants.PORT: vip.port_id}) raw_port = None try: if port: - raw_port = self.neutron_client.show_port(port.id) + raw_port = self.network_proxy.get_port(port.id) except Exception: LOG.warning('Unable to get port information for port ' '%s. Continuing to delete the security ' 'group.', port.id) if raw_port: - sec_grps = raw_port.get( - constants.PORT, {}).get(constants.SECURITY_GROUPS, []) - if sec_grp_id in sec_grps: + sec_grps = raw_port.security_group_ids + if sec_grps and sec_grp_id in sec_grps: sec_grps.remove(sec_grp_id) - port_update = {constants.PORT: { - constants.SECURITY_GROUPS: sec_grps}} try: - self.neutron_client.update_port(port.id, - port_update) - except neutron_client_exceptions.PortNotFoundClient: + self.network_proxy.update_port( + port.id, security_group_ids=sec_grps) + except os_exceptions.ResourceNotFound: LOG.warning('Unable to update port information ' 'for port %s. Continuing to delete ' 'the security group since port not ' @@ -348,7 +349,7 @@ class AllowedAddressPairsDriver(neutron_base.BaseNeutronDriver): try: LOG.warning('Deleting extra port %s on security ' 'group %s...', port_id, sec_grp_id) - self.neutron_client.delete_port(port_id) + self.network_proxy.delete_port(port_id) except Exception: LOG.warning('Failed to delete extra port %s on ' 'security group %s.', @@ -361,13 +362,17 @@ class AllowedAddressPairsDriver(neutron_base.BaseNeutronDriver): This can happen if a failover has occurred. """ - for amphora in vip.load_balancer.amphorae: - try: - self.neutron_client.delete_port(amphora.vrrp_port_id) - except (neutron_client_exceptions.NotFound, - neutron_client_exceptions.PortNotFoundClient): - LOG.debug('VIP instance port %s already deleted. Skipping.', - amphora.vrrp_port_id) + try: + for amphora in vip.load_balancer.amphorae: + try: + self.network_proxy.delete_port(amphora.vrrp_port_id) + except os_exceptions.ResourceNotFound: + LOG.debug( + 'VIP instance port %s already deleted. Skipping.', + amphora.vrrp_port_id) + except AttributeError as ex: + LOG.warning(f"Cannot delete port from amphorae. Object does not " + f"exist ({ex!r})") try: port = self.get_port(vip.port_id) @@ -381,9 +386,8 @@ class AllowedAddressPairsDriver(neutron_base.BaseNeutronDriver): if port and port.device_owner == OCTAVIA_OWNER: try: - self.neutron_client.delete_port(vip.port_id) - except (neutron_client_exceptions.NotFound, - neutron_client_exceptions.PortNotFoundClient): + self.network_proxy.delete_port(vip.port_id) + except os_exceptions.ResourceNotFound: LOG.debug('VIP port %s already deleted. Skipping.', vip.port_id) except Exception as e: @@ -546,29 +550,29 @@ class AllowedAddressPairsDriver(neutron_base.BaseNeutronDriver): project_id_key = 'tenant_id' # It can be assumed that network_id exists - port = {constants.PORT: { + port = { constants.NAME: 'octavia-lb-' + load_balancer.id, constants.NETWORK_ID: load_balancer.vip.network_id, constants.ADMIN_STATE_UP: False, 'device_id': 'lb-{0}'.format(load_balancer.id), constants.DEVICE_OWNER: OCTAVIA_OWNER, - project_id_key: load_balancer.project_id}} + project_id_key: load_balancer.project_id} if fixed_ips: - port[constants.PORT][constants.FIXED_IPS] = fixed_ips + port[constants.FIXED_IPS] = fixed_ips try: - new_port = self.neutron_client.create_port(port) + new_port = self.network_proxy.create_port(**port) except Exception as e: message = _('Error creating neutron port on network ' '{network_id} due to {e}.').format( - network_id=load_balancer.vip.network_id, e=str(e)) + network_id=load_balancer.vip.network_id, e=repr(e)) LOG.exception(message) raise base.AllocateVIPException( message, orig_msg=getattr(e, constants.MESSAGE, None), orig_code=getattr(e, constants.STATUS_CODE, None), ) - new_port = utils.convert_port_dict_to_model(new_port) + new_port = utils.convert_port_to_model(new_port) return self._port_to_vip(new_port, load_balancer, octavia_owned=True) def unplug_aap_port(self, vip, amphora, subnet): @@ -585,11 +589,11 @@ class AllowedAddressPairsDriver(neutron_base.BaseNeutronDriver): except Exception: pass try: - aap_update = {constants.PORT: { + aap_update = { constants.ALLOWED_ADDRESS_PAIRS: [] - }} - self.neutron_client.update_port(interface.port_id, - aap_update) + } + self.network_proxy.update_port(interface.port_id, + **aap_update) except Exception as e: message = _('Error unplugging VIP. Could not clear ' 'allowed address pairs from port ' @@ -601,9 +605,8 @@ class AllowedAddressPairsDriver(neutron_base.BaseNeutronDriver): try: port = self.get_port(amphora.vrrp_port_id) if port.name.startswith('octavia-lb-vrrp-'): - self.neutron_client.delete_port(amphora.vrrp_port_id) - except (neutron_client_exceptions.NotFound, - neutron_client_exceptions.PortNotFoundClient): + self.network_proxy.delete_port(amphora.vrrp_port_id) + except base.PortNotFound: pass except Exception as e: LOG.error('Failed to delete port. Resources may still be in ' @@ -704,11 +707,10 @@ class AllowedAddressPairsDriver(neutron_base.BaseNeutronDriver): for port in ports: try: - self.neutron_client.update_port( - port.id, {constants.PORT: {'dns_name': ''}}) + self.network_proxy.update_port( + port.id, dns_name='') - except (neutron_client_exceptions.NotFound, - neutron_client_exceptions.PortNotFoundClient) as e: + except os_exceptions.ResourceNotFound as e: raise base.PortNotFound() from e def plug_port(self, amphora, port): @@ -824,15 +826,15 @@ class AllowedAddressPairsDriver(neutron_base.BaseNeutronDriver): for port in ports: try: - neutron_port = self.neutron_client.show_port( - port.id).get(constants.PORT) + neutron_port = self.network_proxy.get_port( + port.id) device_id = neutron_port['device_id'] start = int(time.time()) while device_id: time.sleep(CONF.networking.retry_interval) - neutron_port = self.neutron_client.show_port( - port.id).get(constants.PORT) + neutron_port = self.network_proxy.get_port( + port.id) device_id = neutron_port['device_id'] timed_out = int(time.time()) - start >= port_detach_timeout @@ -843,8 +845,7 @@ class AllowedAddressPairsDriver(neutron_base.BaseNeutronDriver): (port.id, device_id, port_detach_timeout)) raise base.TimeoutException(message) - except (neutron_client_exceptions.NotFound, - neutron_client_exceptions.PortNotFoundClient): + except os_exceptions.ResourceNotFound: pass def delete_port(self, port_id): @@ -854,9 +855,8 @@ class AllowedAddressPairsDriver(neutron_base.BaseNeutronDriver): :returns: None """ try: - self.neutron_client.delete_port(port_id) - except (neutron_client_exceptions.NotFound, - neutron_client_exceptions.PortNotFoundClient): + self.network_proxy.delete_port(port_id) + except os_exceptions.ResourceNotFound: LOG.debug('VIP instance port %s already deleted. Skipping.', port_id) except Exception as e: @@ -870,10 +870,9 @@ class AllowedAddressPairsDriver(neutron_base.BaseNeutronDriver): :returns: None """ try: - self.neutron_client.update_port( - port_id, {constants.PORT: {constants.ADMIN_STATE_UP: state}}) - except (neutron_client_exceptions.NotFound, - neutron_client_exceptions.PortNotFoundClient) as e: + self.network_proxy.update_port( + port_id, admin_state_up=state) + except os_exceptions.ResourceNotFound as e: raise base.PortNotFound(str(e)) except Exception as e: raise exceptions.NetworkServiceError(net_error=str(e)) @@ -912,11 +911,11 @@ class AllowedAddressPairsDriver(neutron_base.BaseNeutronDriver): if security_group_ids: port[constants.SECURITY_GROUPS] = security_group_ids - new_port = self.neutron_client.create_port({constants.PORT: port}) + new_port = self.network_proxy.create_port(**port) LOG.debug('Created port: %(port)s', {constants.PORT: new_port}) - return utils.convert_port_dict_to_model(new_port) + return utils.convert_port_to_model(new_port) except Exception as e: message = _('Error creating a port on network ' '{network_id} due to {error}.').format( @@ -933,14 +932,15 @@ class AllowedAddressPairsDriver(neutron_base.BaseNeutronDriver): """ try: if self.sec_grp_enabled and sg_name: - sec_grps = self.neutron_client.list_security_groups( - name=sg_name) - if sec_grps and sec_grps.get(constants.SECURITY_GROUPS): - sg_dict = sec_grps.get(constants.SECURITY_GROUPS)[0] - return utils.convert_security_group_dict_to_model(sg_dict) - message = _('Security group {name} not found.').format( - name=sg_name) - raise base.SecurityGroupNotFound(message) + sec_grps = self.network_proxy.security_groups(name=sg_name) + try: + sg = next(sec_grps) + return utils.convert_security_group_to_model(sg) + except StopIteration: + # pylint: disable=raise-missing-from + message = _('Security group {name} not found.').format( + name=sg_name) + raise base.SecurityGroupNotFound(message) return None except base.SecurityGroupNotFound: raise diff --git a/octavia/network/drivers/neutron/base.py b/octavia/network/drivers/neutron/base.py index 667562342d..3e2d54575d 100644 --- a/octavia/network/drivers/neutron/base.py +++ b/octavia/network/drivers/neutron/base.py @@ -12,7 +12,9 @@ # License for the specific language governing permissions and limitations # under the License. -from neutronclient.common import exceptions as neutron_client_exceptions +from openstack.connection import Connection +import openstack.exceptions as os_exceptions +from openstack.network.v2._proxy import Proxy from oslo_config import cfg from oslo_log import log as logging @@ -23,33 +25,28 @@ from octavia.network import base from octavia.network import data_models as network_models from octavia.network.drivers.neutron import utils - LOG = logging.getLogger(__name__) DNS_INT_EXT_ALIAS = 'dns-integration' SEC_GRP_EXT_ALIAS = 'security-group' QOS_EXT_ALIAS = 'qos' +CONF_GROUP = 'neutron' CONF = cfg.CONF class BaseNeutronDriver(base.AbstractNetworkDriver): - def __init__(self): - self.neutron_client = clients.NeutronAuth.get_neutron_client( - endpoint=CONF.neutron.endpoint, - region=CONF.neutron.region_name, - endpoint_type=CONF.neutron.endpoint_type, - service_name=CONF.neutron.service_name, - insecure=CONF.neutron.insecure, - ca_cert=CONF.neutron.ca_certificates_file - ) + self.network_proxy: Proxy = self.os_connection.network self._check_extension_cache = {} self.sec_grp_enabled = self._check_extension_enabled(SEC_GRP_EXT_ALIAS) self.dns_integration_enabled = self._check_extension_enabled( DNS_INT_EXT_ALIAS) self._qos_enabled = self._check_extension_enabled(QOS_EXT_ALIAS) - self.project_id = self.neutron_client.get_auth_info().get( - 'auth_tenant_id') + self.project_id = self.os_connection.current_project_id + + @property + def os_connection(self) -> Connection: + return clients.NeutronAuth.get_neutron_client() def _check_extension_enabled(self, extension_alias): if extension_alias in self._check_extension_cache: @@ -60,12 +57,11 @@ class BaseNeutronDriver(base.AbstractNetworkDriver): 'status': 'enabled' if status else 'disabled' }) else: - try: - self.neutron_client.show_extension(extension_alias) + if self.network_proxy.find_extension(extension_alias): LOG.debug('Neutron extension %(ext)s found enabled', {'ext': extension_alias}) self._check_extension_cache[extension_alias] = True - except neutron_client_exceptions.NotFound: + else: LOG.debug('Neutron extension %(ext)s is not enabled', {'ext': extension_alias}) self._check_extension_cache[extension_alias] = False @@ -123,64 +119,51 @@ class BaseNeutronDriver(base.AbstractNetworkDriver): fixed_ips=fixed_ips) def _add_allowed_address_pairs_to_port(self, port_id, ip_address_list): - aap = { - 'port': { - 'allowed_address_pairs': [ - {'ip_address': ip} for ip in ip_address_list - ] - } - } - self.neutron_client.update_port(port_id, aap) + aap = [{'ip_address': ip} for ip in ip_address_list] + self.network_proxy.update_port(port_id, + allowed_address_pairs=aap) def _add_security_group_to_port(self, sec_grp_id, port_id): - port_update = {'port': {'security_groups': [sec_grp_id]}} # Note: Neutron accepts the SG even if it already exists try: - self.neutron_client.update_port(port_id, port_update) - except neutron_client_exceptions.PortNotFoundClient as e: + self.network_proxy.update_port( + port_id, security_groups=[sec_grp_id]) + except os_exceptions.NotFoundException as e: raise base.PortNotFound(str(e)) except Exception as e: raise base.NetworkException(str(e)) def _get_ports_by_security_group(self, sec_grp_id): - all_ports = self.neutron_client.list_ports(project_id=self.project_id) - filtered_ports = [] - for port in all_ports.get('ports', []): - if sec_grp_id in port.get('security_groups', []): - filtered_ports.append(port) + all_ports = self.network_proxy.ports(project_id=self.project_id) + filtered_ports = [ + p for p in all_ports if (p.security_group_ids and + sec_grp_id in p.security_group_ids)] return filtered_ports def _create_security_group(self, name): - new_sec_grp = {'security_group': {'name': name}} - sec_grp = self.neutron_client.create_security_group(new_sec_grp) - return sec_grp['security_group'] + sec_grp = self.network_proxy.create_security_group(name=name) + return sec_grp def _create_security_group_rule(self, sec_grp_id, protocol, direction='ingress', port_min=None, port_max=None, ethertype='IPv6', cidr=None): rule = { - 'security_group_rule': { - 'security_group_id': sec_grp_id, - 'direction': direction, - 'protocol': protocol, - 'port_range_min': port_min, - 'port_range_max': port_max, - 'ethertype': ethertype, - 'remote_ip_prefix': cidr, - } + 'security_group_id': sec_grp_id, + 'direction': direction, + 'protocol': protocol, + 'port_range_min': port_min, + 'port_range_max': port_max, + 'ethertype': ethertype, + 'remote_ip_prefix': cidr, } - self.neutron_client.create_security_group_rule(rule) + self.network_proxy.create_security_group_rule(**rule) def apply_qos_on_port(self, qos_id, port_id): - body = { - 'port': - {'qos_policy_id': qos_id} - } try: - self.neutron_client.update_port(port_id, body) - except neutron_client_exceptions.PortNotFoundClient as e: + self.network_proxy.update_port(port_id, qos_policy_id=qos_id) + except os_exceptions.ResourceNotFound as e: raise base.PortNotFound(str(e)) except Exception as e: raise base.NetworkException(str(e)) @@ -188,26 +171,26 @@ class BaseNeutronDriver(base.AbstractNetworkDriver): def get_plugged_networks(self, compute_id): # List neutron ports associated with the Amphora try: - ports = self.neutron_client.list_ports(device_id=compute_id) + ports = self.network_proxy.ports(device_id=compute_id) except Exception: LOG.debug('Error retrieving plugged networks for compute ' 'device %s.', compute_id) - ports = {'ports': []} - return [self._port_to_octavia_interface( - compute_id, port) for port in ports['ports']] + ports = tuple() + return [self._port_to_octavia_interface(compute_id, port) for port in + ports] def _get_resource(self, resource_type, resource_id, context=None): - neutron_client = self.neutron_client + network = self.network_proxy if context and not CONF.networking.allow_invisible_resource_usage: - neutron_client = clients.NeutronAuth.get_user_neutron_client( + network = clients.NeutronAuth.get_user_neutron_client( context) try: - resource = getattr(neutron_client, 'show_%s' % - resource_type)(resource_id) - return getattr(utils, 'convert_%s_dict_to_model' % + resource = getattr( + network, f"get_{resource_type}")(resource_id) + return getattr(utils, 'convert_%s_to_model' % resource_type)(resource) - except neutron_client_exceptions.NotFound as e: + except os_exceptions.ResourceNotFound as e: message = _('{resource_type} not found ' '({resource_type} id: {resource_id}).').format( resource_type=resource_type, resource_id=resource_id) @@ -228,20 +211,25 @@ class BaseNeutronDriver(base.AbstractNetworkDriver): If unique_item set to True, only the first resource is returned. """ try: - resource = getattr(self.neutron_client, 'list_%ss' % - resource_type)(**filters) + resources = getattr( + self.network_proxy, f"{resource_type}s")(**filters) conversion_function = getattr( utils, - 'convert_%s_dict_to_model' % resource_type) - if not resource['%ss' % resource_type]: - # no items found - raise neutron_client_exceptions.NotFound() - if unique_item: - return conversion_function(resource['%ss' % resource_type][0]) + 'convert_%s_to_model' % resource_type) + try: + # get first item to see if there is at least one resource + res_list = [conversion_function(next(resources))] + except StopIteration: + # pylint: disable=raise-missing-from + raise os_exceptions.NotFoundException( + f'No resource of type {resource_type} found that matches ' + f'given filter criteria: {filters}.') - return list(map(conversion_function, - resource['%ss' % resource_type])) - except neutron_client_exceptions.NotFound as e: + if unique_item: + return res_list[0] + return res_list + [conversion_function(r) for r in resources] + + except os_exceptions.NotFoundException as e: message = _('{resource_type} not found ' '({resource_type} Filters: {filters}.').format( resource_type=resource_type, filters=filters) @@ -300,10 +288,10 @@ class BaseNeutronDriver(base.AbstractNetworkDriver): fixed_ips.append(new_fixed_ip_dict) - body = {'port': {'fixed_ips': fixed_ips}} try: - updated_port = self.neutron_client.update_port(port_id, body) - return utils.convert_port_dict_to_model(updated_port) + updated_port = self.network_proxy.update_port( + port_id, fixed_ips=fixed_ips) + return utils.convert_port_to_model(updated_port) except Exception as e: raise base.NetworkException(str(e)) @@ -315,9 +303,9 @@ class BaseNeutronDriver(base.AbstractNetworkDriver): if fixed_ip.subnet_id != subnet_id ] - body = {'port': {'fixed_ips': fixed_ips}} try: - updated_port = self.neutron_client.update_port(port_id, body) - return utils.convert_port_dict_to_model(updated_port) + updated_port = self.network_proxy.update_port( + port_id, fixed_ips=fixed_ips) + return utils.convert_port_to_model(updated_port) except Exception as e: raise base.NetworkException(str(e)) diff --git a/octavia/network/drivers/neutron/utils.py b/octavia/network/drivers/neutron/utils.py index f41d066a5a..cd1028a532 100644 --- a/octavia/network/drivers/neutron/utils.py +++ b/octavia/network/drivers/neutron/utils.py @@ -13,113 +13,97 @@ # under the License. -from octavia.common import constants +from openstack.network.v2.network_ip_availability import NetworkIPAvailability + from octavia.network import data_models as network_models -def convert_subnet_dict_to_model(subnet_dict): - subnet = subnet_dict.get('subnet', subnet_dict) - subnet_hrs = subnet.get('host_routes', []) +def convert_subnet_to_model(subnet): host_routes = [network_models.HostRoute(nexthop=hr.get('nexthop'), destination=hr.get('destination')) - for hr in subnet_hrs] - return network_models.Subnet(id=subnet.get(constants.ID), - name=subnet.get(constants.NAME), - network_id=subnet.get('network_id'), - project_id=subnet.get(constants.TENANT_ID), - gateway_ip=subnet.get('gateway_ip'), - cidr=subnet.get('cidr'), - ip_version=subnet.get('ip_version'), - host_routes=host_routes - ) + for hr in subnet.host_routes] if subnet.host_routes else [] + return network_models.Subnet( + id=subnet.id, + name=subnet.name, + network_id=subnet.network_id, + project_id=subnet.project_id, + gateway_ip=subnet.gateway_ip, + cidr=subnet.cidr, + ip_version=subnet.ip_version, + host_routes=host_routes, + ) -def convert_port_dict_to_model(port_dict): - port = port_dict.get('port', port_dict) - fixed_ips = [network_models.FixedIP(subnet_id=fixed_ip.get('subnet_id'), - ip_address=fixed_ip.get('ip_address')) - for fixed_ip in port.get('fixed_ips', [])] +def convert_port_to_model(port): + if port.get('fixed_ips'): + fixed_ips = [convert_fixed_ip_dict_to_model(fixed_ip) + for fixed_ip in port.fixed_ips] + else: + fixed_ips = [] return network_models.Port( - id=port.get(constants.ID), - name=port.get(constants.NAME), - device_id=port.get('device_id'), - device_owner=port.get('device_owner'), - mac_address=port.get('mac_address'), - network_id=port.get('network_id'), - status=port.get('status'), - project_id=port.get(constants.TENANT_ID), - admin_state_up=port.get('admin_state_up'), + id=port.id, + name=port.name, + device_id=port.device_id, + device_owner=port.device_owner, + mac_address=port.mac_address, + network_id=port.network_id, + status=port.status, + project_id=port.project_id, + admin_state_up=port.is_admin_state_up, fixed_ips=fixed_ips, - qos_policy_id=port.get('qos_policy_id'), - security_group_ids=port.get(constants.SECURITY_GROUPS, []) + qos_policy_id=port.qos_policy_id, + security_group_ids=port.security_group_ids ) -def convert_network_dict_to_model(network_dict): - nw = network_dict.get('network', network_dict) +def convert_network_to_model(nw): return network_models.Network( - id=nw.get(constants.ID), - name=nw.get(constants.NAME), - subnets=nw.get('subnets'), - project_id=nw.get(constants.TENANT_ID), - admin_state_up=nw.get('admin_state_up'), - mtu=nw.get('mtu'), - provider_network_type=nw.get('provider:network_type'), - provider_physical_network=nw.get('provider:physical_network'), - provider_segmentation_id=nw.get('provider:segmentation_id'), - router_external=nw.get('router:external'), - port_security_enabled=nw.get('port_security_enabled') + id=nw.id, + name=nw.name, + subnets=nw.subnet_ids, + project_id=nw.project_id, + admin_state_up=nw.is_admin_state_up, + mtu=nw.mtu, + provider_network_type=nw.provider_network_type, + provider_physical_network=nw.provider_physical_network, + provider_segmentation_id=nw.provider_segmentation_id, + router_external=nw.is_router_external, + port_security_enabled=nw.is_port_security_enabled, ) -def convert_fixed_ip_dict_to_model(fixed_ip_dict): - fixed_ip = fixed_ip_dict.get('fixed_ip', fixed_ip_dict) +def convert_fixed_ip_dict_to_model(fixed_ip: dict): return network_models.FixedIP(subnet_id=fixed_ip.get('subnet_id'), ip_address=fixed_ip.get('ip_address')) -def convert_qos_policy_dict_to_model(qos_policy_dict): - qos_policy = qos_policy_dict.get('policy', qos_policy_dict) - return network_models.QosPolicy(id=qos_policy.get(constants.ID)) +def convert_qos_policy_to_model(qos_policy): + return network_models.QosPolicy(id=qos_policy.id) -# We can't use "floating_ip" because we need to match the neutron client method -def convert_floatingip_dict_to_model(floating_ip_dict): - floating_ip = floating_ip_dict.get('floatingip', floating_ip_dict) - return network_models.FloatingIP( - id=floating_ip.get(constants.ID), - description=floating_ip.get(constants.DESCRIPTION), - project_id=floating_ip.get(constants.PROJECT_ID, - floating_ip.get(constants.TENANT_ID)), - status=floating_ip.get('status'), - router_id=floating_ip.get('router_id'), - port_id=floating_ip.get('port_id'), - floating_network_id=floating_ip.get('floating_network_id'), - floating_ip_address=floating_ip.get('floating_ip_address'), - fixed_ip_address=floating_ip.get('fixed_ip_address'), - fixed_port_id=floating_ip.get('fixed_port_id') - ) - - -def convert_network_ip_availability_dict_to_model( - network_ip_availability_dict): - nw_ip_avail = network_ip_availability_dict.get( - 'network_ip_availability', network_ip_availability_dict) - ip_avail = network_models.Network_IP_Availability.from_dict(nw_ip_avail) - ip_avail.subnet_ip_availability = nw_ip_avail.get('subnet_ip_availability') +def convert_network_ip_availability_to_model( + nw_ip_avail: NetworkIPAvailability): + ip_avail = network_models.Network_IP_Availability( + network_id=nw_ip_avail.network_id, + tenant_id=nw_ip_avail.tenant_id, + project_id=nw_ip_avail.project_id, + network_name=nw_ip_avail.network_name, total_ips=nw_ip_avail.total_ips, + used_ips=nw_ip_avail.used_ips, + subnet_ip_availability=nw_ip_avail.subnet_ip_availability) return ip_avail -def convert_security_group_dict_to_model(security_group_dict): - sg_rule_ids = [rule.get(constants.ID) for rule in - security_group_dict.get(constants.SECURITY_GROUP_RULES, [])] +def convert_security_group_to_model(security_group): + if security_group.security_group_rules: + sg_rule_ids = [rule['id'] for rule in + security_group.security_group_rules] + else: + sg_rule_ids = [] return network_models.SecurityGroup( - id=security_group_dict.get(constants.ID), - project_id=security_group_dict.get( - constants.PROJECT_ID, - security_group_dict.get(constants.TENANT_ID)), - name=security_group_dict.get(constants.NAME), - description=security_group_dict.get(constants.DESCRIPTION), + id=security_group.id, + project_id=security_group.project_id, + name=security_group.name, + description=security_group.description, security_group_rule_ids=sg_rule_ids, - tags=security_group_dict.get(constants.TAGS, []), - stateful=security_group_dict.get('stateful')) + tags=security_group.tags, + stateful=security_group.stateful) diff --git a/octavia/tests/common/constants.py b/octavia/tests/common/constants.py index 387859bbf3..94a598dd66 100644 --- a/octavia/tests/common/constants.py +++ b/octavia/tests/common/constants.py @@ -12,6 +12,12 @@ # License for the specific language governing permissions and limitations # under the License. from octavia_lib.common import constants as lib_constants +from openstack.network.v2.floating_ip import FloatingIP +from openstack.network.v2.network import Network +from openstack.network.v2.network_ip_availability import NetworkIPAvailability +from openstack.network.v2.port import Port +from openstack.network.v2.security_group import SecurityGroup +from openstack.network.v2.subnet import Subnet from octavia.common import constants @@ -43,16 +49,16 @@ MOCK_MAC_ADDR = 'fe:16:3e:00:95:5c' MOCK_MAC_ADDR2 = 'fe:16:3e:00:95:5d' MOCK_PROJECT_ID = 'mock-project-1' MOCK_HOST_ROUTES = [] -MOCK_SUBNET = {'subnet': {'id': MOCK_SUBNET_ID, - 'network_id': MOCK_NETWORK_ID, - 'name': MOCK_SUBNET_NAME, - 'tenant_id': MOCK_PROJECT_ID, - 'gateway_ip': MOCK_GATEWAY_IP, - 'cidr': MOCK_CIDR, - 'ip_version': MOCK_IP_VERSION, - 'host_routes': MOCK_HOST_ROUTES}} -MOCK_SUBNET2 = {'subnet': {'id': MOCK_SUBNET_ID2, - 'network_id': MOCK_NETWORK_ID2}} +MOCK_SUBNET = Subnet(**{'id': MOCK_SUBNET_ID, + 'network_id': MOCK_NETWORK_ID, + 'name': MOCK_SUBNET_NAME, + 'tenant_id': MOCK_PROJECT_ID, + 'gateway_ip': MOCK_GATEWAY_IP, + 'cidr': MOCK_CIDR, + 'ip_version': MOCK_IP_VERSION, + 'host_routes': MOCK_HOST_ROUTES}) +MOCK_SUBNET2 = Subnet(**{'id': MOCK_SUBNET_ID2, + 'network_id': MOCK_NETWORK_ID2}) MOCK_HOST_ROUTES = [] MOCK_NOVA_INTERFACE = MockNovaInterface() @@ -69,7 +75,7 @@ MOCK_DEVICE_ID2 = 'Moctavia124' MOCK_SECURITY_GROUP_ID = 'security-group-1' MOCK_SECURITY_GROUP_NAME = 'SecurityGroup1' -MOCK_SECURITY_GROUP = { +MOCK_SECURITY_GROUP = SecurityGroup(**{ "id": MOCK_SECURITY_GROUP_ID, "name": MOCK_SECURITY_GROUP_NAME, "tenant_id": MOCK_PROJECT_ID, @@ -113,7 +119,7 @@ MOCK_SECURITY_GROUP = { "created_at": "2020-03-12T20:43:31Z", "updated_at": "2020-03-12T20:44:48Z", "revision_number": 3, - "project_id": MOCK_PROJECT_ID} + "project_id": MOCK_PROJECT_ID}) MOCK_ADMIN_STATE_UP = True MOCK_STATUS = 'ACTIVE' @@ -122,59 +128,60 @@ MOCK_NETWORK_TYPE = 'flat' MOCK_SEGMENTATION_ID = 1 MOCK_ROUTER_EXTERNAL = False -MOCK_NEUTRON_PORT = {'port': {'network_id': MOCK_NETWORK_ID, - 'device_id': MOCK_DEVICE_ID, - 'device_owner': MOCK_DEVICE_OWNER, - 'id': MOCK_PORT_ID, - 'name': MOCK_PORT_NAME, - 'tenant_id': MOCK_PROJECT_ID, - 'admin_state_up': MOCK_ADMIN_STATE_UP, - 'status': MOCK_STATUS, - 'mac_address': MOCK_MAC_ADDR, - 'fixed_ips': [{'ip_address': MOCK_IP_ADDRESS, - 'subnet_id': MOCK_SUBNET_ID}], - 'security_groups': [MOCK_SECURITY_GROUP_ID]}} +MOCK_NEUTRON_PORT = Port(**{'network_id': MOCK_NETWORK_ID, + 'device_id': MOCK_DEVICE_ID, + 'device_owner': MOCK_DEVICE_OWNER, + 'id': MOCK_PORT_ID, + 'name': MOCK_PORT_NAME, + 'tenant_id': MOCK_PROJECT_ID, + 'admin_state_up': MOCK_ADMIN_STATE_UP, + 'status': MOCK_STATUS, + 'mac_address': MOCK_MAC_ADDR, + 'fixed_ips': [{'ip_address': MOCK_IP_ADDRESS, + 'subnet_id': MOCK_SUBNET_ID}], + 'security_groups': [MOCK_SECURITY_GROUP_ID]}) MOCK_NEUTRON_QOS_POLICY_ID = 'mock-qos-id' MOCK_QOS_POLICY_ID1 = 'qos1-id' MOCK_QOS_POLICY_ID2 = 'qos2-id' -MOCK_NEUTRON_PORT2 = {'port': {'network_id': MOCK_NETWORK_ID2, - 'device_id': MOCK_DEVICE_ID2, - 'device_owner': MOCK_DEVICE_OWNER, - 'id': MOCK_PORT_ID2, - 'name': MOCK_PORT_NAME2, - 'tenant_id': MOCK_PROJECT_ID, - 'admin_state_up': MOCK_ADMIN_STATE_UP, - 'status': MOCK_STATUS, - 'mac_address': MOCK_MAC_ADDR2, - 'fixed_ips': [{'ip_address': MOCK_IP_ADDRESS2, - 'subnet_id': MOCK_SUBNET_ID2}]}} +MOCK_NEUTRON_PORT2 = Port(**{'network_id': MOCK_NETWORK_ID2, + 'device_id': MOCK_DEVICE_ID2, + 'device_owner': MOCK_DEVICE_OWNER, + 'id': MOCK_PORT_ID2, + 'name': MOCK_PORT_NAME2, + 'tenant_id': MOCK_PROJECT_ID, + 'admin_state_up': MOCK_ADMIN_STATE_UP, + 'status': MOCK_STATUS, + 'mac_address': MOCK_MAC_ADDR2, + 'fixed_ips': [{'ip_address': MOCK_IP_ADDRESS2, + 'subnet_id': MOCK_SUBNET_ID2}]}) -MOCK_NETWORK = {'network': {'id': MOCK_NETWORK_ID, - 'name': MOCK_NETWORK_NAME, - 'tenant_id': MOCK_PROJECT_ID, - 'admin_state_up': MOCK_ADMIN_STATE_UP, - 'subnets': [MOCK_SUBNET_ID], - 'mtu': MOCK_MTU, - 'provider:network_type': 'flat', - 'provider:physical_network': MOCK_NETWORK_NAME, - 'provider:segmentation_id': MOCK_SEGMENTATION_ID, - 'router:external': MOCK_ROUTER_EXTERNAL}} -MOCK_FIXED_IP = {'fixed_ip': {'subnet_id': MOCK_SUBNET_ID, - 'ip_address': MOCK_IP_ADDRESS}} +MOCK_NETWORK = Network(**{'id': MOCK_NETWORK_ID, + 'name': MOCK_NETWORK_NAME, + 'project_id': MOCK_PROJECT_ID, + 'admin_state_up': MOCK_ADMIN_STATE_UP, + 'subnet_ids': [MOCK_SUBNET_ID], + 'mtu': MOCK_MTU, + 'provider_network_type': 'flat', + 'provider_physical_network': MOCK_NETWORK_NAME, + 'provider_segmentation_id': MOCK_SEGMENTATION_ID, + 'router_external': MOCK_ROUTER_EXTERNAL, + 'port_security_enabled': False}) +MOCK_FIXED_IP = {'subnet_id': MOCK_SUBNET_ID, + 'ip_address': MOCK_IP_ADDRESS} MOCK_FLOATING_IP_ID = 'floating-ip-1' MOCK_FLOATING_IP_DESC = 'TestFloatingIP1' MOCK_ROUTER_ID = 'mock-router-1' -MOCK_FLOATING_IP = {'floatingip': {'id': MOCK_FLOATING_IP_ID, - 'description': MOCK_FLOATING_IP_DESC, - 'tenant_id': MOCK_PROJECT_ID, - 'status': MOCK_STATUS, - 'port_id': MOCK_PORT_ID, - 'router_id': MOCK_ROUTER_ID, - 'floating_network_id': MOCK_NETWORK_ID, - 'floating_ip_address': MOCK_IP_ADDRESS, - 'fixed_ip_address': MOCK_IP_ADDRESS2, - 'fixed_port_id': MOCK_PORT_ID2}} +MOCK_FLOATING_IP = FloatingIP(**{'id': MOCK_FLOATING_IP_ID, + 'description': MOCK_FLOATING_IP_DESC, + 'tenant_id': MOCK_PROJECT_ID, + 'status': MOCK_STATUS, + 'port_id': MOCK_PORT_ID, + 'router_id': MOCK_ROUTER_ID, + 'floating_network_id': MOCK_NETWORK_ID, + 'floating_ip_address': MOCK_IP_ADDRESS, + 'fixed_ip_address': MOCK_IP_ADDRESS2, + 'fixed_port_id': MOCK_PORT_ID2}) MOCK_AMP_ID1 = 'amp1-id' MOCK_AMP_ID2 = 'amp2-id' @@ -205,17 +212,17 @@ MOCK_MANAGEMENT_INTERFACE2.net_id = MOCK_MANAGEMENT_NET_ID MOCK_MANAGEMENT_INTERFACE2.port_id = MOCK_MANAGEMENT_PORT_ID2 MOCK_MANAGEMENT_INTERFACE2.fixed_ips = MOCK_MANAGEMENT_FIXED_IPS2 -MOCK_MANAGEMENT_PORT1 = {'port': {'network_id': MOCK_MANAGEMENT_NET_ID, - 'device_id': MOCK_AMP_COMPUTE_ID1, - 'device_owner': MOCK_DEVICE_OWNER, - 'id': MOCK_MANAGEMENT_PORT_ID1, - 'fixed_ips': MOCK_MANAGEMENT_FIXED_IPS1}} +MOCK_MANAGEMENT_PORT1 = Port(**{'network_id': MOCK_MANAGEMENT_NET_ID, + 'device_id': MOCK_AMP_COMPUTE_ID1, + 'device_owner': MOCK_DEVICE_OWNER, + 'id': MOCK_MANAGEMENT_PORT_ID1, + 'fixed_ips': MOCK_MANAGEMENT_FIXED_IPS1}) -MOCK_MANAGEMENT_PORT2 = {'port': {'network_id': MOCK_MANAGEMENT_NET_ID, - 'device_id': MOCK_AMP_COMPUTE_ID2, - 'device_owner': MOCK_DEVICE_OWNER, - 'id': MOCK_MANAGEMENT_PORT_ID2, - 'fixed_ips': MOCK_MANAGEMENT_FIXED_IPS2}} +MOCK_MANAGEMENT_PORT2 = Port(**{'network_id': MOCK_MANAGEMENT_NET_ID, + 'device_id': MOCK_AMP_COMPUTE_ID2, + 'device_owner': MOCK_DEVICE_OWNER, + 'id': MOCK_MANAGEMENT_PORT_ID2, + 'fixed_ips': MOCK_MANAGEMENT_FIXED_IPS2}) MOCK_VIP_SUBNET_ID = 'vip-subnet-1' MOCK_VIP_SUBNET_ID2 = 'vip-subnet-2' @@ -242,17 +249,17 @@ MOCK_VRRP_INTERFACE2.net_id = MOCK_VIP_NET_ID MOCK_VRRP_INTERFACE2.port_id = MOCK_VRRP_PORT_ID2 MOCK_VRRP_INTERFACE2.fixed_ips = MOCK_VRRP_FIXED_IPS2 -MOCK_VRRP_PORT1 = {'port': {'network_id': MOCK_VIP_NET_ID, - 'device_id': MOCK_AMP_COMPUTE_ID1, - 'device_owner': MOCK_DEVICE_OWNER, - 'id': MOCK_VRRP_PORT_ID1, - 'fixed_ips': MOCK_VRRP_FIXED_IPS1}} +MOCK_VRRP_PORT1 = Port(**{'network_id': MOCK_VIP_NET_ID, + 'device_id': MOCK_AMP_COMPUTE_ID1, + 'device_owner': MOCK_DEVICE_OWNER, + 'id': MOCK_VRRP_PORT_ID1, + 'fixed_ips': MOCK_VRRP_FIXED_IPS1}) -MOCK_VRRP_PORT2 = {'port': {'network_id': MOCK_VIP_NET_ID, - 'device_id': MOCK_AMP_COMPUTE_ID2, - 'device_owner': MOCK_DEVICE_OWNER, - 'id': MOCK_VRRP_PORT_ID2, - 'fixed_ips': MOCK_VRRP_FIXED_IPS2}} +MOCK_VRRP_PORT2 = Port(**{'network_id': MOCK_VIP_NET_ID, + 'device_id': MOCK_AMP_COMPUTE_ID2, + 'device_owner': MOCK_DEVICE_OWNER, + 'id': MOCK_VRRP_PORT_ID2, + 'fixed_ips': MOCK_VRRP_FIXED_IPS2}) MOCK_NETWORK_TOTAL_IPS = 254 MOCK_NETWORK_USED_IPS = 0 @@ -262,13 +269,13 @@ MOCK_SUBNET_IP_AVAILABILITY = [{'used_ips': MOCK_SUBNET_USED_IPS, 'subnet_id': MOCK_SUBNET_ID, 'total_ips': MOCK_SUBNET_TOTAL_IPS}] -MOCK_NETWORK_IP_AVAILABILITY = {'network_ip_availability': ( - {'network_id': MOCK_NETWORK_ID, - 'tenant_id': MOCK_PROJECT_ID, - 'network_name': MOCK_NETWORK_NAME, - 'total_ips': MOCK_NETWORK_TOTAL_IPS, - 'used_ips': MOCK_NETWORK_USED_IPS, - 'subnet_ip_availability': MOCK_SUBNET_IP_AVAILABILITY})} +MOCK_NETWORK_IP_AVAILABILITY = NetworkIPAvailability( + **{'network_id': MOCK_NETWORK_ID, + 'tenant_id': MOCK_PROJECT_ID, + 'network_name': MOCK_NETWORK_NAME, + 'total_ips': MOCK_NETWORK_TOTAL_IPS, + 'used_ips': MOCK_NETWORK_USED_IPS, + 'subnet_ip_availability': MOCK_SUBNET_IP_AVAILABILITY}) INVALID_LISTENER_POOL_PROTOCOL_MAP = { constants.PROTOCOL_HTTP: [constants.PROTOCOL_HTTPS, diff --git a/octavia/tests/unit/common/test_clients.py b/octavia/tests/unit/common/test_clients.py index 5b8e144bad..fc72c8989c 100644 --- a/octavia/tests/unit/common/test_clients.py +++ b/octavia/tests/unit/common/test_clients.py @@ -13,7 +13,6 @@ from unittest import mock import cinderclient.v3 import glanceclient.v2 -import neutronclient.v2_0 import novaclient.v2 from oslo_config import cfg @@ -62,44 +61,6 @@ class TestNovaAuth(base.TestCase): self.assertIs(bc1, bc2) -class TestNeutronAuth(base.TestCase): - - def setUp(self): - # Reset the session and client - clients.NeutronAuth.neutron_client = None - keystone._SESSION = None - - super().setUp() - - @mock.patch('keystoneauth1.session.Session', mock.Mock()) - def test_get_neutron_client(self): - # There should be no existing client - self.assertIsNone( - clients.NeutronAuth.neutron_client - ) - - # Mock out the keystone session and get the client - keystone._SESSION = mock.MagicMock() - bc1 = clients.NeutronAuth.get_neutron_client( - region=None, endpoint_type='publicURL') - - # Our returned client should also be the saved client - self.assertIsInstance( - clients.NeutronAuth.neutron_client, - neutronclient.v2_0.client.Client - ) - self.assertIs( - clients.NeutronAuth.neutron_client, - bc1 - ) - - # Getting the session again should return the same object - bc2 = clients.NeutronAuth.get_neutron_client( - region="test-region", service_name="neutronEndpoint1", - endpoint="test-endpoint", endpoint_type='publicURL', insecure=True) - self.assertIs(bc1, bc2) - - class TestGlanceAuth(base.TestCase): def setUp(self): diff --git a/octavia/tests/unit/common/test_keystone.py b/octavia/tests/unit/common/test_keystone.py new file mode 100644 index 0000000000..e207522850 --- /dev/null +++ b/octavia/tests/unit/common/test_keystone.py @@ -0,0 +1,54 @@ +# Copyright Red Hat +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +from unittest import mock +from unittest.mock import call + +from keystoneauth1 import exceptions as ks_exceptions +from oslo_config import cfg +from oslo_config import fixture as oslo_fixture + +import octavia.common.keystone as ks +import octavia.tests.unit.base as base + + +class TestKeystoneSession(base.TestCase): + + @mock.patch("oslo_config.cfg.ConfigOpts.get_location", return_value=None) + @mock.patch("octavia.common.keystone.ks_loading" + ".load_auth_from_conf_options") + @mock.patch("octavia.common.keystone.LOG") + def test_get_auth_neutron_override(self, mock_log, mock_load_auth, + mock_get_location): + opt_mock = mock.MagicMock() + opt_mock.dest = "foo" + conf = oslo_fixture.Config(cfg.CONF) + conf.conf.service_auth.cafile = "bar" + + mock_load_auth.side_effect = [ + ks_exceptions.auth_plugins.MissingRequiredOptions( + [opt_mock]), + None, + None + ] + + sess = ks.KeystoneSession("neutron") + sess.get_auth() + + mock_load_auth.assert_has_calls([call(cfg.CONF, 'neutron'), + call(cfg.CONF, 'service_auth'), + call(cfg.CONF, 'neutron')]) + mock_log.debug.assert_has_calls( + [call("Overriding [%s].%s with '%s'", 'neutron', 'cafile', + 'bar')] + ) diff --git a/octavia/tests/unit/network/drivers/neutron/test_allowed_address_pairs.py b/octavia/tests/unit/network/drivers/neutron/test_allowed_address_pairs.py index 26f94b16ee..20fa865485 100644 --- a/octavia/tests/unit/network/drivers/neutron/test_allowed_address_pairs.py +++ b/octavia/tests/unit/network/drivers/neutron/test_allowed_address_pairs.py @@ -11,16 +11,17 @@ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. -import copy from unittest import mock -from neutronclient.common import exceptions as neutron_exceptions from novaclient.client import exceptions as nova_exceptions +import openstack.exceptions as os_exceptions +from openstack.network.v2.port import Port +from openstack.network.v2.security_group import SecurityGroup +from openstack.network.v2.subnet import Subnet from oslo_config import cfg from oslo_config import fixture as oslo_fixture from oslo_utils import uuidutils -from octavia.common import clients from octavia.common import constants from octavia.common import data_models from octavia.common import exceptions @@ -59,17 +60,16 @@ class TestAllowedAddressPairsDriver(base.TestCase): def setUp(self): super().setUp() - with mock.patch('octavia.common.clients.neutron_client.Client', - autospec=True) as neutron_client: + with mock.patch('octavia.common.clients.openstack.connection' + '.Connection', autospec=True) as os_connection: with mock.patch('stevedore.driver.DriverManager.driver', autospec=True): - client = neutron_client(clients.NEUTRON_VERSION) - client.list_extensions.return_value = { - 'extensions': [ - {'alias': allowed_address_pairs.AAP_EXT_ALIAS}, - {'alias': neutron_base.SEC_GRP_EXT_ALIAS} - ] - } + network_proxy = os_connection().network + network_proxy.find_extension = ( + lambda x: 'alias' if x in ( + allowed_address_pairs.AAP_EXT_ALIAS, + neutron_base.SEC_GRP_EXT_ALIAS) + else None) self.k_session = mock.patch( 'keystoneauth1.session.Session').start() self.driver = allowed_address_pairs.AllowedAddressPairsDriver() @@ -108,18 +108,13 @@ class TestAllowedAddressPairsDriver(base.TestCase): lb.vip.load_balancer = lb vip = lb.vip sec_grp_id = 'lb-sec-grp1' - show_port = self.driver.neutron_client.show_port - show_port.return_value = {'port': { - 'device_owner': allowed_address_pairs.OCTAVIA_OWNER}} - delete_port = self.driver.neutron_client.delete_port - delete_sec_grp = self.driver.neutron_client.delete_security_group - list_security_groups = self.driver.neutron_client.list_security_groups - security_groups = { - 'security_groups': [ - {'id': sec_grp_id} - ] - } - list_security_groups.return_value = security_groups + show_port = self.driver.network_proxy.get_port + show_port.return_value = Port( + device_owner=allowed_address_pairs.OCTAVIA_OWNER) + delete_port = self.driver.network_proxy.delete_port + delete_sec_grp = self.driver.network_proxy.delete_security_group + list_security_groups = self.driver.network_proxy.find_security_group + list_security_groups.return_value = SecurityGroup(id=sec_grp_id) self.driver.deallocate_vip(vip) calls = [mock.call(vip.port_id)] for amp in lb.amphorae: @@ -132,38 +127,27 @@ class TestAllowedAddressPairsDriver(base.TestCase): lb.vip.load_balancer = lb vip = lb.vip sec_grp_id = 'lb-sec-grp1' - show_port = self.driver.neutron_client.show_port - port = {'port': { - 'device_owner': allowed_address_pairs.OCTAVIA_OWNER}} + show_port = self.driver.network_proxy.get_port + port = Port(device_owner=allowed_address_pairs.OCTAVIA_OWNER) show_port.side_effect = [port, Exception] - list_security_groups = self.driver.neutron_client.list_security_groups - security_groups = { - 'security_groups': [ - {'id': sec_grp_id} - ] - } - list_security_groups.return_value = security_groups + list_security_groups = self.driver.network_proxy.find_security_group + list_security_groups.return_value = SecurityGroup(id=sec_grp_id) self.driver.deallocate_vip(vip) - self.driver.neutron_client.update_port.assert_not_called() + self.driver.network_proxy.update_port.assert_not_called() def test_deallocate_vip_port_deleted(self): lb = dmh.generate_load_balancer_tree() lb.vip.load_balancer = lb vip = lb.vip sec_grp_id = 'lb-sec-grp1' - show_port = self.driver.neutron_client.show_port - show_port.return_value = {'port': { - 'device_owner': allowed_address_pairs.OCTAVIA_OWNER}} - delete_port = self.driver.neutron_client.delete_port - delete_port.side_effect = neutron_exceptions.NotFound - delete_sec_grp = self.driver.neutron_client.delete_security_group - list_security_groups = self.driver.neutron_client.list_security_groups - security_groups = { - 'security_groups': [ - {'id': sec_grp_id} - ] - } - list_security_groups.return_value = security_groups + show_port = self.driver.network_proxy.get_port + show_port.return_value = Port( + device_owner=allowed_address_pairs.OCTAVIA_OWNER) + delete_port = self.driver.network_proxy.delete_port + delete_port.side_effect = os_exceptions.ResourceNotFound + delete_sec_grp = self.driver.network_proxy.delete_security_group + find_security_group = self.driver.network_proxy.find_security_group + find_security_group.return_value = SecurityGroup(id=sec_grp_id) self.driver.deallocate_vip(vip) calls = [mock.call(vip.port_id)] for amp in lb.amphorae: @@ -175,16 +159,13 @@ class TestAllowedAddressPairsDriver(base.TestCase): lb = dmh.generate_load_balancer_tree() lb.vip.load_balancer = lb vip = lb.vip - show_port = self.driver.neutron_client.show_port - show_port.return_value = {'port': { - 'device_owner': allowed_address_pairs.OCTAVIA_OWNER}} - delete_port = self.driver.neutron_client.delete_port - delete_sec_grp = self.driver.neutron_client.delete_security_group - list_security_groups = self.driver.neutron_client.list_security_groups - security_groups = { - 'security_groups': [] - } - list_security_groups.return_value = security_groups + show_port = self.driver.network_proxy.get_port + show_port.return_value = Port( + device_owner=allowed_address_pairs.OCTAVIA_OWNER) + delete_port = self.driver.network_proxy.delete_port + delete_sec_grp = self.driver.network_proxy.delete_security_group + list_security_groups = self.driver.network_proxy.find_security_group + list_security_groups.return_value = None self.driver.deallocate_vip(vip) delete_port.assert_called_with(vip.port_id) delete_sec_grp.assert_not_called() @@ -193,10 +174,10 @@ class TestAllowedAddressPairsDriver(base.TestCase): lb = dmh.generate_load_balancer_tree() vip = data_models.Vip(port_id='1') vip.load_balancer = lb - show_port = self.driver.neutron_client.show_port - show_port.return_value = {'port': { - 'device_owner': allowed_address_pairs.OCTAVIA_OWNER}} - delete_port = self.driver.neutron_client.delete_port + show_port = self.driver.network_proxy.get_port + show_port.return_value = Port( + device_owner=allowed_address_pairs.OCTAVIA_OWNER) + delete_port = self.driver.network_proxy.delete_port delete_port.side_effect = [None, None, TypeError] self.assertRaises(network_base.DeallocateVIPException, self.driver.deallocate_vip, vip) @@ -209,27 +190,22 @@ class TestAllowedAddressPairsDriver(base.TestCase): lb = dmh.generate_load_balancer_tree() lb.vip.load_balancer = lb vip = lb.vip - show_port = self.driver.neutron_client.show_port - show_port.return_value = {'port': { - 'device_owner': allowed_address_pairs.OCTAVIA_OWNER}} - delete_port = self.driver.neutron_client.delete_port - list_ports = self.driver.neutron_client.list_ports - list_security_groups = self.driver.neutron_client.list_security_groups - delete_sec_grp = self.driver.neutron_client.delete_security_group - security_groups = { - 'security_groups': [ - {'id': t_constants.MOCK_SECURITY_GROUP_ID} - ] - } - list_security_groups.return_value = security_groups + show_port = self.driver.network_proxy.get_port + show_port.return_value = Port( + device_owner=allowed_address_pairs.OCTAVIA_OWNER) + delete_port = self.driver.network_proxy.delete_port + list_ports = self.driver.network_proxy.ports + find_security_group = self.driver.network_proxy.find_security_group + delete_sec_grp = self.driver.network_proxy.delete_security_group + security_group = SecurityGroup(id=t_constants.MOCK_SECURITY_GROUP_ID) + find_security_group.return_value = security_group delete_grp_results = [ network_base.DeallocateVIPException for _ in range(max_retries + 1)] # Total tries = max_retries + 1 delete_grp_results.append(None) delete_sec_grp.side_effect = delete_grp_results - list_ports.side_effect = [{ - "ports": [t_constants.MOCK_NEUTRON_PORT['port'], - t_constants.MOCK_NEUTRON_PORT2['port']]}] + list_ports.return_value = iter([t_constants.MOCK_NEUTRON_PORT, + t_constants.MOCK_NEUTRON_PORT2]) self.driver.deallocate_vip(vip) # First we expect the amp's ports to be deleted dp_calls = [mock.call(amp.vrrp_port_id) for amp in lb.amphorae] @@ -248,19 +224,19 @@ class TestAllowedAddressPairsDriver(base.TestCase): lb = dmh.generate_load_balancer_tree() vip = data_models.Vip(port_id='1') vip.load_balancer = lb - show_port = self.driver.neutron_client.show_port - show_port.side_effect = neutron_exceptions.PortNotFoundClient + show_port = self.driver.network_proxy.get_port + show_port.side_effect = os_exceptions.ResourceNotFound self.driver.deallocate_vip(vip) def test_deallocate_vip_when_port_not_found_for_update(self): lb = dmh.generate_load_balancer_tree() vip = data_models.Vip(port_id='1') vip.load_balancer = lb - show_port = self.driver.neutron_client.show_port - show_port.return_value = {'port': { - 'device_owner': allowed_address_pairs.OCTAVIA_OWNER}} - update_port = self.driver.neutron_client.update_port - update_port.side_effect = neutron_exceptions.PortNotFoundClient + show_port = self.driver.network_proxy.get_port + show_port.return_value = Port( + device_owner=allowed_address_pairs.OCTAVIA_OWNER) + update_port = self.driver.network_proxy.update_port + update_port.side_effect = os_exceptions.ResourceNotFound self.driver.deallocate_vip(vip) def test_deallocate_vip_when_port_not_owned_by_octavia(self): @@ -268,23 +244,19 @@ class TestAllowedAddressPairsDriver(base.TestCase): lb.vip.load_balancer = lb vip = lb.vip sec_grp_id = 'lb-sec-grp1' - show_port = self.driver.neutron_client.show_port - show_port.return_value = {'port': { + show_port = self.driver.network_proxy.get_port + show_port.return_value = Port(**{ 'id': vip.port_id, 'device_owner': 'neutron:LOADBALANCERV2', - 'security_groups': [sec_grp_id]}} - update_port = self.driver.neutron_client.update_port - delete_sec_grp = self.driver.neutron_client.delete_security_group - list_security_groups = self.driver.neutron_client.list_security_groups - security_groups = { - 'security_groups': [ - {'id': sec_grp_id} - ] - } - list_security_groups.return_value = security_groups + 'security_groups': [sec_grp_id]}) + update_port = self.driver.network_proxy.update_port + delete_sec_grp = self.driver.network_proxy.delete_security_group + list_security_groups = self.driver.network_proxy.find_security_group + list_security_groups.return_value = SecurityGroup(id=sec_grp_id) self.driver.deallocate_vip(vip) - expected_port_update = {'port': {'security_groups': []}} - update_port.assert_called_once_with(vip.port_id, expected_port_update) + expected_port_update = {'security_group_ids': []} + update_port.assert_called_once_with(vip.port_id, + **expected_port_update) delete_sec_grp.assert_called_once_with(sec_grp_id) def test_deallocate_vip_when_vip_port_not_found(self): @@ -295,8 +267,8 @@ class TestAllowedAddressPairsDriver(base.TestCase): session_mock = mock.MagicMock() session_mock.get_project_id.return_value = admin_project_id self.k_session.return_value = session_mock - show_port = self.driver.neutron_client.show_port - show_port.side_effect = neutron_exceptions.PortNotFoundClient + show_port = self.driver.network_proxy.get_port + show_port.side_effect = os_exceptions.ResourceNotFound self.driver.deallocate_vip(vip) def test_plug_aap_errors_when_nova_cant_find_network_to_attach(self): @@ -317,8 +289,8 @@ class TestAllowedAddressPairsDriver(base.TestCase): network_attach = self.driver.compute.attach_network_or_port network_attach.return_value = t_constants.MOCK_NOVA_INTERFACE - update_port = self.driver.neutron_client.update_port - update_port.side_effect = neutron_exceptions.PortNotFoundClient + update_port = self.driver.network_proxy.update_port + update_port.side_effect = os_exceptions.ResourceNotFound self.assertRaises(network_base.PortNotFound, self.driver.plug_aap_port, lb, lb.vip, lb.amphorae[0], subnet) @@ -408,40 +380,40 @@ class TestAllowedAddressPairsDriver(base.TestCase): subnet = network_models.Subnet(id=t_constants.MOCK_VIP_SUBNET_ID, network_id=t_constants.MOCK_VIP_NET_ID) - list_ports = self.driver.neutron_client.list_ports - port1 = t_constants.MOCK_MANAGEMENT_PORT1['port'] - port2 = t_constants.MOCK_MANAGEMENT_PORT2['port'] - list_ports.side_effect = [{'ports': [port1]}, {'ports': [port2]}] + list_ports = self.driver.network_proxy.ports + port1 = t_constants.MOCK_MANAGEMENT_PORT1 + port2 = t_constants.MOCK_MANAGEMENT_PORT2 + list_ports.return_value = iter([port1, port2]) network_attach = self.driver.compute.attach_network_or_port network_attach.side_effect = [t_constants.MOCK_VRRP_INTERFACE1] - update_port = self.driver.neutron_client.update_port - expected_aap = {'port': {'allowed_address_pairs': - [{'ip_address': lb.vip.ip_address}]}} + update_port = self.driver.network_proxy.update_port + expected_aap = { + 'allowed_address_pairs': [{'ip_address': lb.vip.ip_address}]} amp = self.driver.plug_aap_port(lb, lb.vip, lb.amphorae[0], subnet) - update_port.assert_any_call(amp.vrrp_port_id, expected_aap) + update_port.assert_any_call(amp.vrrp_port_id, **expected_aap) self.assertIn(amp.vrrp_ip, [t_constants.MOCK_VRRP_IP1, t_constants.MOCK_VRRP_IP2]) self.assertEqual(lb.vip.ip_address, amp.ha_ip) @mock.patch('octavia.network.drivers.neutron.utils.' - 'convert_port_dict_to_model') + 'convert_port_to_model') def test_plug_aap_port_create_fails(self, mock_convert): lb = dmh.generate_load_balancer_tree() subnet = network_models.Subnet(id=t_constants.MOCK_VIP_SUBNET_ID, network_id=t_constants.MOCK_VIP_NET_ID) - list_ports = self.driver.neutron_client.list_ports - port1 = t_constants.MOCK_MANAGEMENT_PORT1['port'] - port2 = t_constants.MOCK_MANAGEMENT_PORT2['port'] - list_ports.side_effect = [{'ports': [port1]}, {'ports': [port2]}] - port_create = self.driver.neutron_client.create_port + list_ports = self.driver.network_proxy.ports + port1 = t_constants.MOCK_MANAGEMENT_PORT1 + port2 = t_constants.MOCK_MANAGEMENT_PORT2 + list_ports.return_value = iter([port1, port2]) + port_create = self.driver.network_proxy.create_port port_create.side_effect = [Exception('Create failure')] self.assertRaises(network_base.PlugVIPException, self.driver.plug_aap_port, lb, lb.vip, lb.amphorae[0], subnet) mock_convert.assert_not_called() - self.driver.neutron_client.delete_port.assert_not_called() + self.driver.network_proxy.delete_port.assert_not_called() def test_plug_aap_port_attach_fails(self): lb = dmh.generate_load_balancer_tree() @@ -449,16 +421,16 @@ class TestAllowedAddressPairsDriver(base.TestCase): subnet = network_models.Subnet(id=t_constants.MOCK_VIP_SUBNET_ID, network_id=t_constants.MOCK_VIP_NET_ID) - list_ports = self.driver.neutron_client.list_ports - port1 = t_constants.MOCK_MANAGEMENT_PORT1['port'] - port2 = t_constants.MOCK_MANAGEMENT_PORT2['port'] - list_ports.side_effect = [{'ports': [port1]}, {'ports': [port2]}] + list_ports = self.driver.network_proxy.ports + port1 = t_constants.MOCK_MANAGEMENT_PORT1 + port2 = t_constants.MOCK_MANAGEMENT_PORT2 + list_ports.return_value = iter([port1, port2]) network_attach = self.driver.compute.attach_network_or_port network_attach.side_effect = [Exception('Attach failure')] self.assertRaises(network_base.PlugVIPException, self.driver.plug_aap_port, lb, lb.vip, lb.amphorae[0], subnet) - self.driver.neutron_client.delete_port.assert_called_once() + self.driver.network_proxy.delete_port.assert_called_once() def test_plug_aap_port_with_add_vips(self): additional_vips = [ @@ -470,21 +442,20 @@ class TestAllowedAddressPairsDriver(base.TestCase): subnet = network_models.Subnet(id=t_constants.MOCK_VIP_SUBNET_ID, network_id=t_constants.MOCK_VIP_NET_ID) - list_ports = self.driver.neutron_client.list_ports - port1 = t_constants.MOCK_MANAGEMENT_PORT1['port'] - port2 = t_constants.MOCK_MANAGEMENT_PORT2['port'] - list_ports.side_effect = [{'ports': [port1]}, {'ports': [port2]}] + list_ports = self.driver.network_proxy.ports + port1 = t_constants.MOCK_MANAGEMENT_PORT1 + port2 = t_constants.MOCK_MANAGEMENT_PORT2 + list_ports.return_value = iter([port1, port2]) network_attach = self.driver.compute.attach_network_or_port network_attach.side_effect = [t_constants.MOCK_VRRP_INTERFACE1] - update_port = self.driver.neutron_client.update_port + update_port = self.driver.network_proxy.update_port amp = self.driver.plug_aap_port(lb, lb.vip, lb.amphorae[0], subnet) expected_aap = { - 'port': { - 'allowed_address_pairs': - [{'ip_address': lb.vip.ip_address}, - {'ip_address': lb.additional_vips[0].ip_address}]}} + 'allowed_address_pairs': + [{'ip_address': lb.vip.ip_address}, + {'ip_address': lb.additional_vips[0].ip_address}]} - update_port.assert_any_call(amp.vrrp_port_id, expected_aap) + update_port.assert_any_call(amp.vrrp_port_id, **expected_aap) self.assertIn(amp.vrrp_ip, [t_constants.MOCK_VRRP_IP1, t_constants.MOCK_VRRP_IP2]) self.assertEqual(lb.vip.ip_address, amp.ha_ip) @@ -505,14 +476,14 @@ class TestAllowedAddressPairsDriver(base.TestCase): subnet = network_models.Subnet( id=t_constants.MOCK_MANAGEMENT_SUBNET_ID, network_id=t_constants.MOCK_MANAGEMENT_NET_ID) - list_ports = self.driver.neutron_client.list_ports - port1 = t_constants.MOCK_MANAGEMENT_PORT1['port'] - port2 = t_constants.MOCK_MANAGEMENT_PORT2['port'] + list_ports = self.driver.network_proxy.ports + port1 = t_constants.MOCK_MANAGEMENT_PORT1 + port2 = t_constants.MOCK_MANAGEMENT_PORT2 self._set_safely(t_constants.MOCK_MANAGEMENT_FIXED_IPS1[0], 'ip_address', lb.amphorae[0].lb_network_ip) self._set_safely(t_constants.MOCK_MANAGEMENT_FIXED_IPS2[0], 'ip_address', lb.amphorae[1].lb_network_ip) - list_ports.side_effect = [{'ports': [port1]}, {'ports': [port2]}] + list_ports.side_effect = [iter([port1]), iter([port2])] network_attach = self.driver.compute.attach_network_or_port self._set_safely(t_constants.MOCK_VRRP_INTERFACE1, 'net_id', t_constants.MOCK_MANAGEMENT_NET_ID) @@ -523,11 +494,11 @@ class TestAllowedAddressPairsDriver(base.TestCase): self._set_safely(t_constants.MOCK_VRRP_FIXED_IPS2[0], 'subnet_id', t_constants.MOCK_MANAGEMENT_SUBNET_ID) network_attach.side_effect = [t_constants.MOCK_VRRP_INTERFACE1] - update_port = self.driver.neutron_client.update_port - expected_aap = {'port': {'allowed_address_pairs': - [{'ip_address': lb.vip.ip_address}]}} + update_port = self.driver.network_proxy.update_port + expected_aap = { + 'allowed_address_pairs': [{'ip_address': lb.vip.ip_address}]} amp = self.driver.plug_aap_port(lb, lb.vip, lb.amphorae[0], subnet) - update_port.assert_any_call(amp.vrrp_port_id, expected_aap) + update_port.assert_any_call(amp.vrrp_port_id, **expected_aap) self.assertIn(amp.vrrp_ip, [t_constants.MOCK_VRRP_IP1, t_constants.MOCK_VRRP_IP2]) self.assertEqual(lb.vip.ip_address, amp.ha_ip) @@ -557,7 +528,7 @@ class TestAllowedAddressPairsDriver(base.TestCase): self.assertFalse(result) def test_allocate_vip_when_port_already_provided(self): - show_port = self.driver.neutron_client.show_port + show_port = self.driver.network_proxy.get_port show_port.return_value = t_constants.MOCK_NEUTRON_PORT fake_lb_vip = data_models.Vip( port_id=t_constants.MOCK_PORT_ID, @@ -580,15 +551,15 @@ class TestAllowedAddressPairsDriver(base.TestCase): bad_existing_port.port_id = uuidutils.generate_uuid() bad_existing_port.network_id = uuidutils.generate_uuid() bad_existing_port.subnet_id = uuidutils.generate_uuid() - show_port = self.driver.neutron_client.show_port + show_port = self.driver.network_proxy.get_port show_port.return_value = bad_existing_port - port_create_dict = copy.deepcopy(t_constants.MOCK_NEUTRON_PORT) - port_create_dict['port']['device_owner'] = ( + port_create_dict = Port(**t_constants.MOCK_NEUTRON_PORT.to_dict()) + port_create_dict['device_owner'] = ( allowed_address_pairs.OCTAVIA_OWNER) - port_create_dict['port']['device_id'] = 'lb-1' - create_port = self.driver.neutron_client.create_port + port_create_dict['device_id'] = 'lb-1' + create_port = self.driver.network_proxy.create_port create_port.return_value = port_create_dict - show_subnet = self.driver.neutron_client.show_subnet + show_subnet = self.driver.network_proxy.get_subnet show_subnet.return_value = {'subnet': { 'id': t_constants.MOCK_SUBNET_ID, 'network_id': t_constants.MOCK_NETWORK_ID @@ -601,19 +572,17 @@ class TestAllowedAddressPairsDriver(base.TestCase): project_id='test-project') vip, additional_vips = self.driver.allocate_vip(fake_lb) exp_create_port_call = { - 'port': { - 'name': 'octavia-lb-1', - 'network_id': t_constants.MOCK_NETWORK_ID, - 'device_id': 'lb-1', - 'device_owner': allowed_address_pairs.OCTAVIA_OWNER, - 'admin_state_up': False, - 'project_id': 'test-project', - 'fixed_ips': [{'subnet_id': t_constants.MOCK_SUBNET_ID}] - } + 'name': 'octavia-lb-1', + 'network_id': t_constants.MOCK_NETWORK_ID, + 'device_id': 'lb-1', + 'device_owner': allowed_address_pairs.OCTAVIA_OWNER, + 'admin_state_up': False, + 'project_id': 'test-project', + 'fixed_ips': [{'subnet_id': t_constants.MOCK_SUBNET_ID}] } - self.driver.neutron_client.delete_port.assert_called_once_with( + self.driver.network_proxy.delete_port.assert_called_once_with( t_constants.MOCK_PORT_ID) - create_port.assert_called_once_with(exp_create_port_call) + create_port.assert_called_once_with(**exp_create_port_call) self.assertIsInstance(vip, data_models.Vip) self.assertEqual(t_constants.MOCK_IP_ADDRESS, vip.ip_address) self.assertEqual(t_constants.MOCK_SUBNET_ID, vip.subnet_id) @@ -627,13 +596,13 @@ class TestAllowedAddressPairsDriver(base.TestCase): '_check_extension_enabled', return_value=True) def test_allocate_vip_when_port_not_found(self, mock_check_ext, mock_get_port): - port_create_dict = copy.deepcopy(t_constants.MOCK_NEUTRON_PORT) - port_create_dict['port']['device_owner'] = ( + port_create_dict = Port(**t_constants.MOCK_NEUTRON_PORT.to_dict()) + port_create_dict['device_owner'] = ( allowed_address_pairs.OCTAVIA_OWNER) - port_create_dict['port']['device_id'] = 'lb-1' - create_port = self.driver.neutron_client.create_port + port_create_dict['device_id'] = 'lb-1' + create_port = self.driver.network_proxy.create_port create_port.return_value = port_create_dict - show_subnet = self.driver.neutron_client.show_subnet + show_subnet = self.driver.network_proxy.get_subnet show_subnet.return_value = {'subnet': { 'id': t_constants.MOCK_SUBNET_ID, 'network_id': t_constants.MOCK_NETWORK_ID @@ -645,17 +614,15 @@ class TestAllowedAddressPairsDriver(base.TestCase): project_id='test-project') vip, additional_vips = self.driver.allocate_vip(fake_lb) exp_create_port_call = { - 'port': { - 'name': 'octavia-lb-1', - 'network_id': t_constants.MOCK_NETWORK_ID, - 'device_id': 'lb-1', - 'device_owner': allowed_address_pairs.OCTAVIA_OWNER, - 'admin_state_up': False, - 'project_id': 'test-project', - 'fixed_ips': [{'subnet_id': t_constants.MOCK_SUBNET_ID}] - } + 'name': 'octavia-lb-1', + 'network_id': t_constants.MOCK_NETWORK_ID, + 'device_id': 'lb-1', + 'device_owner': allowed_address_pairs.OCTAVIA_OWNER, + 'admin_state_up': False, + 'project_id': 'test-project', + 'fixed_ips': [{'subnet_id': t_constants.MOCK_SUBNET_ID}] } - create_port.assert_called_once_with(exp_create_port_call) + create_port.assert_called_once_with(**exp_create_port_call) self.assertIsInstance(vip, data_models.Vip) self.assertEqual(t_constants.MOCK_IP_ADDRESS, vip.ip_address) self.assertEqual(t_constants.MOCK_SUBNET_ID, vip.subnet_id) @@ -681,7 +648,7 @@ class TestAllowedAddressPairsDriver(base.TestCase): fake_lb_vip = data_models.Vip( subnet_id=t_constants.MOCK_SUBNET_ID) fake_lb = data_models.LoadBalancer(id='1', vip=fake_lb_vip) - create_port = self.driver.neutron_client.create_port + create_port = self.driver.network_proxy.create_port create_port.side_effect = Exception self.assertRaises(network_base.AllocateVIPException, self.driver.allocate_vip, fake_lb) @@ -689,17 +656,17 @@ class TestAllowedAddressPairsDriver(base.TestCase): @mock.patch('octavia.network.drivers.neutron.base.BaseNeutronDriver.' '_check_extension_enabled', return_value=True) def test_allocate_vip_when_no_port_provided(self, mock_check_ext): - port_create_dict = copy.deepcopy(t_constants.MOCK_NEUTRON_PORT) - port_create_dict['port']['device_owner'] = ( + port_create_dict = Port(**t_constants.MOCK_NEUTRON_PORT.to_dict()) + port_create_dict['device_owner'] = ( allowed_address_pairs.OCTAVIA_OWNER) - port_create_dict['port']['device_id'] = 'lb-1' - create_port = self.driver.neutron_client.create_port + port_create_dict['device_id'] = 'lb-1' + create_port = self.driver.network_proxy.create_port create_port.return_value = port_create_dict - show_subnet = self.driver.neutron_client.show_subnet - show_subnet.return_value = {'subnet': { + show_subnet = self.driver.network_proxy.get_subnet + show_subnet.return_value = { 'id': t_constants.MOCK_SUBNET_ID, 'network_id': t_constants.MOCK_NETWORK_ID - }} + } fake_lb_vip = data_models.Vip(subnet_id=t_constants.MOCK_SUBNET_ID, network_id=t_constants.MOCK_NETWORK_ID, ip_address=t_constants.MOCK_IP_ADDRESS) @@ -707,18 +674,16 @@ class TestAllowedAddressPairsDriver(base.TestCase): project_id='test-project') vip, additional_vips = self.driver.allocate_vip(fake_lb) exp_create_port_call = { - 'port': { - 'name': 'octavia-lb-1', - 'network_id': t_constants.MOCK_NETWORK_ID, - 'device_id': 'lb-1', - 'device_owner': allowed_address_pairs.OCTAVIA_OWNER, - 'admin_state_up': False, - 'project_id': 'test-project', - 'fixed_ips': [{'ip_address': t_constants.MOCK_IP_ADDRESS, - 'subnet_id': t_constants.MOCK_SUBNET_ID}] - } + 'name': 'octavia-lb-1', + 'network_id': t_constants.MOCK_NETWORK_ID, + 'device_id': 'lb-1', + 'device_owner': allowed_address_pairs.OCTAVIA_OWNER, + 'admin_state_up': False, + 'project_id': 'test-project', + 'fixed_ips': [{'ip_address': t_constants.MOCK_IP_ADDRESS, + 'subnet_id': t_constants.MOCK_SUBNET_ID}] } - create_port.assert_called_once_with(exp_create_port_call) + create_port.assert_called_once_with(**exp_create_port_call) self.assertIsInstance(vip, data_models.Vip) self.assertEqual(t_constants.MOCK_IP_ADDRESS, vip.ip_address) self.assertEqual(t_constants.MOCK_SUBNET_ID, vip.subnet_id) @@ -729,17 +694,17 @@ class TestAllowedAddressPairsDriver(base.TestCase): @mock.patch('octavia.network.drivers.neutron.base.BaseNeutronDriver.' '_check_extension_enabled', return_value=True) def test_allocate_vip_when_no_port_fixed_ip(self, mock_check_ext): - port_create_dict = copy.deepcopy(t_constants.MOCK_NEUTRON_PORT) - port_create_dict['port']['device_owner'] = ( + port_create_dict = Port(**t_constants.MOCK_NEUTRON_PORT.to_dict()) + port_create_dict['device_owner'] = ( allowed_address_pairs.OCTAVIA_OWNER) - port_create_dict['port']['device_id'] = 'lb-1' - create_port = self.driver.neutron_client.create_port + port_create_dict['device_id'] = 'lb-1' + create_port = self.driver.network_proxy.create_port create_port.return_value = port_create_dict - show_subnet = self.driver.neutron_client.show_subnet - show_subnet.return_value = {'subnet': { + show_subnet = self.driver.network_proxy.get_subnet + show_subnet.return_value = Subnet(**{ 'id': t_constants.MOCK_SUBNET_ID, 'network_id': t_constants.MOCK_NETWORK_ID - }} + }) fake_lb_vip = data_models.Vip(subnet_id=t_constants.MOCK_SUBNET_ID, network_id=t_constants.MOCK_NETWORK_ID, ip_address=t_constants.MOCK_IP_ADDRESS) @@ -747,18 +712,16 @@ class TestAllowedAddressPairsDriver(base.TestCase): project_id='test-project') vip, additional_vips = self.driver.allocate_vip(fake_lb) exp_create_port_call = { - 'port': { - 'name': 'octavia-lb-1', - 'network_id': t_constants.MOCK_NETWORK_ID, - 'device_id': 'lb-1', - 'device_owner': allowed_address_pairs.OCTAVIA_OWNER, - 'admin_state_up': False, - 'project_id': 'test-project', - 'fixed_ips': [{'subnet_id': t_constants.MOCK_SUBNET_ID, - 'ip_address': t_constants.MOCK_IP_ADDRESS}] - } + 'name': 'octavia-lb-1', + 'network_id': t_constants.MOCK_NETWORK_ID, + 'device_id': 'lb-1', + 'device_owner': allowed_address_pairs.OCTAVIA_OWNER, + 'admin_state_up': False, + 'project_id': 'test-project', + 'fixed_ips': [{'subnet_id': t_constants.MOCK_SUBNET_ID, + 'ip_address': t_constants.MOCK_IP_ADDRESS}] } - create_port.assert_called_once_with(exp_create_port_call) + create_port.assert_called_once_with(**exp_create_port_call) self.assertIsInstance(vip, data_models.Vip) self.assertEqual(t_constants.MOCK_IP_ADDRESS, vip.ip_address) self.assertEqual(t_constants.MOCK_SUBNET_ID, vip.subnet_id) @@ -769,31 +732,29 @@ class TestAllowedAddressPairsDriver(base.TestCase): @mock.patch('octavia.network.drivers.neutron.base.BaseNeutronDriver.' '_check_extension_enabled', return_value=True) def test_allocate_vip_when_no_port_no_fixed_ip(self, mock_check_ext): - port_create_dict = copy.deepcopy(t_constants.MOCK_NEUTRON_PORT) - port_create_dict['port']['device_owner'] = ( + port_create_dict = Port(**t_constants.MOCK_NEUTRON_PORT.to_dict()) + port_create_dict['device_owner'] = ( allowed_address_pairs.OCTAVIA_OWNER) - port_create_dict['port']['device_id'] = 'lb-1' - create_port = self.driver.neutron_client.create_port + port_create_dict['device_id'] = 'lb-1' + create_port = self.driver.network_proxy.create_port create_port.return_value = port_create_dict - show_subnet = self.driver.neutron_client.show_subnet - show_subnet.return_value = {'subnet': { + show_subnet = self.driver.network_proxy.get_subnet + show_subnet.return_value = { 'id': t_constants.MOCK_SUBNET_ID, 'network_id': t_constants.MOCK_NETWORK_ID - }} + } fake_lb_vip = data_models.Vip(network_id=t_constants.MOCK_NETWORK_ID) fake_lb = data_models.LoadBalancer(id='1', vip=fake_lb_vip, project_id='test-project') vip, additional_vips = self.driver.allocate_vip(fake_lb) exp_create_port_call = { - 'port': { - 'name': 'octavia-lb-1', - 'network_id': t_constants.MOCK_NETWORK_ID, - 'device_id': 'lb-1', - 'device_owner': allowed_address_pairs.OCTAVIA_OWNER, - 'admin_state_up': False, - 'project_id': 'test-project'} - } - create_port.assert_called_once_with(exp_create_port_call) + 'name': 'octavia-lb-1', + 'network_id': t_constants.MOCK_NETWORK_ID, + 'device_id': 'lb-1', + 'device_owner': allowed_address_pairs.OCTAVIA_OWNER, + 'admin_state_up': False, + 'project_id': 'test-project'} + create_port.assert_called_once_with(**exp_create_port_call) self.assertIsInstance(vip, data_models.Vip) self.assertEqual(t_constants.MOCK_PORT_ID, vip.port_id) self.assertEqual(fake_lb.id, vip.load_balancer_id) @@ -802,17 +763,17 @@ class TestAllowedAddressPairsDriver(base.TestCase): @mock.patch('octavia.network.drivers.neutron.base.BaseNeutronDriver.' '_check_extension_enabled', return_value=False) def test_allocate_vip_when_no_port_provided_tenant(self, mock_check_ext): - port_create_dict = copy.deepcopy(t_constants.MOCK_NEUTRON_PORT) - port_create_dict['port']['device_owner'] = ( + port_create_dict = Port(**t_constants.MOCK_NEUTRON_PORT.to_dict()) + port_create_dict['device_owner'] = ( allowed_address_pairs.OCTAVIA_OWNER) - port_create_dict['port']['device_id'] = 'lb-1' - create_port = self.driver.neutron_client.create_port + port_create_dict['device_id'] = 'lb-1' + create_port = self.driver.network_proxy.create_port create_port.return_value = port_create_dict - show_subnet = self.driver.neutron_client.show_subnet - show_subnet.return_value = {'subnet': { + show_subnet = self.driver.network_proxy.get_subnet + show_subnet.return_value = { 'id': t_constants.MOCK_SUBNET_ID, 'network_id': t_constants.MOCK_NETWORK_ID - }} + } fake_lb_vip = data_models.Vip(subnet_id=t_constants.MOCK_SUBNET_ID, network_id=t_constants.MOCK_NETWORK_ID, ip_address=t_constants.MOCK_IP_ADDRESS) @@ -820,18 +781,16 @@ class TestAllowedAddressPairsDriver(base.TestCase): project_id='test-project') vip, additional_vips = self.driver.allocate_vip(fake_lb) exp_create_port_call = { - 'port': { - 'name': 'octavia-lb-1', - 'network_id': t_constants.MOCK_NETWORK_ID, - 'device_id': 'lb-1', - 'device_owner': allowed_address_pairs.OCTAVIA_OWNER, - 'admin_state_up': False, - 'tenant_id': 'test-project', - 'fixed_ips': [{'ip_address': t_constants.MOCK_IP_ADDRESS, - 'subnet_id': t_constants.MOCK_SUBNET_ID}] - } + 'name': 'octavia-lb-1', + 'network_id': t_constants.MOCK_NETWORK_ID, + 'device_id': 'lb-1', + 'device_owner': allowed_address_pairs.OCTAVIA_OWNER, + 'admin_state_up': False, + 'tenant_id': 'test-project', + 'fixed_ips': [{'ip_address': t_constants.MOCK_IP_ADDRESS, + 'subnet_id': t_constants.MOCK_SUBNET_ID}] } - create_port.assert_called_once_with(exp_create_port_call) + create_port.assert_called_once_with(**exp_create_port_call) self.assertIsInstance(vip, data_models.Vip) self.assertEqual(t_constants.MOCK_IP_ADDRESS, vip.ip_address) self.assertEqual(t_constants.MOCK_SUBNET_ID, vip.subnet_id) @@ -842,17 +801,17 @@ class TestAllowedAddressPairsDriver(base.TestCase): @mock.patch('octavia.network.drivers.neutron.base.BaseNeutronDriver.' '_check_extension_enabled', return_value=False) def test_allocate_vip_with_additional_vips(self, mock_check_ext): - port_create_dict = copy.deepcopy(t_constants.MOCK_NEUTRON_PORT) - port_create_dict['port']['device_owner'] = ( + port_create_dict = Port(**t_constants.MOCK_NEUTRON_PORT.to_dict()) + port_create_dict['device_owner'] = ( allowed_address_pairs.OCTAVIA_OWNER) - port_create_dict['port']['device_id'] = 'lb-1' - create_port = self.driver.neutron_client.create_port + port_create_dict['device_id'] = 'lb-1' + create_port = self.driver.network_proxy.create_port create_port.return_value = port_create_dict - show_subnet = self.driver.neutron_client.show_subnet - show_subnet.return_value = {'subnet': { + show_subnet = self.driver.network_proxy.get_subnet + show_subnet.return_value = { 'id': t_constants.MOCK_SUBNET_ID, 'network_id': t_constants.MOCK_NETWORK_ID - }} + } fake_lb_vip = data_models.Vip(subnet_id=t_constants.MOCK_SUBNET_ID, network_id=t_constants.MOCK_NETWORK_ID, ip_address=t_constants.MOCK_IP_ADDRESS) @@ -865,21 +824,19 @@ class TestAllowedAddressPairsDriver(base.TestCase): project_id='test-project') vip, additional_vips = self.driver.allocate_vip(fake_lb) exp_create_port_call = { - 'port': { - 'name': 'octavia-lb-1', - 'network_id': t_constants.MOCK_NETWORK_ID, - 'device_id': 'lb-1', - 'device_owner': allowed_address_pairs.OCTAVIA_OWNER, - 'admin_state_up': False, - 'tenant_id': 'test-project', - 'fixed_ips': [ - {'ip_address': t_constants.MOCK_IP_ADDRESS, - 'subnet_id': t_constants.MOCK_SUBNET_ID}, - {'ip_address': t_constants.MOCK_IP_ADDRESS2}, - {'subnet_id': t_constants.MOCK_SUBNET_ID3}] - } + 'name': 'octavia-lb-1', + 'network_id': t_constants.MOCK_NETWORK_ID, + 'device_id': 'lb-1', + 'device_owner': allowed_address_pairs.OCTAVIA_OWNER, + 'admin_state_up': False, + 'tenant_id': 'test-project', + 'fixed_ips': [ + {'ip_address': t_constants.MOCK_IP_ADDRESS, + 'subnet_id': t_constants.MOCK_SUBNET_ID}, + {'ip_address': t_constants.MOCK_IP_ADDRESS2}, + {'subnet_id': t_constants.MOCK_SUBNET_ID3}] } - create_port.assert_called_once_with(exp_create_port_call) + create_port.assert_called_once_with(**exp_create_port_call) self.assertIsInstance(vip, data_models.Vip) self.assertEqual(t_constants.MOCK_IP_ADDRESS, vip.ip_address) self.assertEqual(t_constants.MOCK_SUBNET_ID, vip.subnet_id) @@ -892,23 +849,22 @@ class TestAllowedAddressPairsDriver(base.TestCase): def test_unplug_aap_port_errors_when_update_port_cant_find_port( self, mock_time_sleep, mock_time_time): lb = dmh.generate_load_balancer_tree() - list_ports = self.driver.neutron_client.list_ports - port1 = t_constants.MOCK_NEUTRON_PORT['port'] + list_ports = self.driver.network_proxy.ports + port1 = t_constants.MOCK_NEUTRON_PORT port2 = { 'id': '4', 'network_id': '3', 'fixed_ips': - [{'ip_address': '10.0.0.2'}] + [{'ip_address': '10.0.0.2'}] } subnet = network_models.Subnet( id=t_constants.MOCK_MANAGEMENT_SUBNET_ID, network_id='3') list_ports.side_effect = [ - {'ports': [port1, port2]}, - {'ports': [port1, port2]}, - {'ports': [port1]} + iter([port1, port2]), + iter([port1, port2]), + iter([port1]), ] - mock_time_time.side_effect = [1, 1, 2] - update_port = self.driver.neutron_client.update_port - update_port.side_effect = neutron_exceptions.PortNotFoundClient + update_port = self.driver.network_proxy.update_port + update_port.side_effect = os_exceptions.ResourceNotFound self.assertRaises(network_base.UnplugVIPException, self.driver.unplug_aap_port, lb.vip, lb.amphorae[0], subnet) @@ -918,25 +874,25 @@ class TestAllowedAddressPairsDriver(base.TestCase): def test_unplug_aap_errors_when_update_port_fails( self, mock_time_sleep, mock_time_time): lb = dmh.generate_load_balancer_tree() - port1 = t_constants.MOCK_NEUTRON_PORT['port'] + port1 = t_constants.MOCK_NEUTRON_PORT port2 = { 'id': '4', 'network_id': '3', 'fixed_ips': - [{'ip_address': '10.0.0.2'}] + [{'ip_address': '10.0.0.2'}] } subnet = network_models.Subnet( id=t_constants.MOCK_MANAGEMENT_SUBNET_ID, network_id='3') - list_ports = self.driver.neutron_client.list_ports + list_ports = self.driver.network_proxy.ports list_ports.side_effect = [ - {'ports': [port1, port2]}, - {'ports': [port1, port2]}, - {'ports': [port1]} + iter([port1, port2]), + iter([port1, port2]), + iter([port1]), ] mock_time_time.side_effect = [1, 1, 2] - update_port = self.driver.neutron_client.update_port + update_port = self.driver.network_proxy.update_port update_port.side_effect = TypeError self.assertRaises(network_base.UnplugVIPException, self.driver.unplug_aap_port, lb.vip, @@ -944,8 +900,8 @@ class TestAllowedAddressPairsDriver(base.TestCase): def test_unplug_vip_errors_when_vip_subnet_not_found(self): lb = dmh.generate_load_balancer_tree() - show_subnet = self.driver.neutron_client.show_subnet - show_subnet.side_effect = neutron_exceptions.NotFound + show_subnet = self.driver.network_proxy.get_subnet + show_subnet.side_effect = os_exceptions.ResourceNotFound self.assertRaises(network_base.PluggedVIPNotFound, self.driver.unplug_vip, lb, lb.vip) @@ -953,7 +909,7 @@ class TestAllowedAddressPairsDriver(base.TestCase): 'AllowedAddressPairsDriver.unplug_aap_port') def test_unplug_vip(self, mock): lb = dmh.generate_load_balancer_tree() - show_subnet = self.driver.neutron_client.show_subnet + show_subnet = self.driver.network_proxy.get_subnet show_subnet.return_value = t_constants.MOCK_SUBNET self.driver.unplug_vip(lb, lb.vip) self.assertEqual(len(lb.amphorae), mock.call_count) @@ -965,27 +921,27 @@ class TestAllowedAddressPairsDriver(base.TestCase): def test_unplug_aap_port(self, mock_unplug_network, mock_time_sleep, mock_time_time): lb = dmh.generate_load_balancer_tree() - update_port = self.driver.neutron_client.update_port - port1 = t_constants.MOCK_NEUTRON_PORT['port'] + update_port = self.driver.network_proxy.update_port + port1 = t_constants.MOCK_NEUTRON_PORT port2 = { 'id': '4', 'network_id': '3', 'fixed_ips': - [{'ip_address': '10.0.0.2'}] + [{'ip_address': '10.0.0.2'}] } subnet = network_models.Subnet( id=t_constants.MOCK_MANAGEMENT_SUBNET_ID, network_id='3') - list_ports = self.driver.neutron_client.list_ports + list_ports = self.driver.network_proxy.ports list_ports.side_effect = [ - {'ports': [port1, port2]}, - {'ports': [port1, port2]}, - {'ports': [port1]} + iter([port1, port2]), + iter([port1, port2]), + iter([port1]), ] mock_time_time.side_effect = [1, 1, 2] - get_port = self.driver.neutron_client.get_port - get_port.side_effect = neutron_exceptions.NotFound + get_port = self.driver.network_proxy.get_port + get_port.side_effect = os_exceptions.ResourceNotFound self.driver.unplug_aap_port(lb.vip, lb.amphorae[0], subnet) - clear_aap = {'port': {'allowed_address_pairs': []}} - update_port.assert_called_once_with(port2.get('id'), clear_aap) + clear_aap = {'allowed_address_pairs': []} + update_port.assert_called_once_with(port2.get('id'), **clear_aap) mock_unplug_network.assert_called_once_with( lb.amphorae[0].compute_id, subnet.network_id) @@ -1032,15 +988,15 @@ class TestAllowedAddressPairsDriver(base.TestCase): def test_unplug_network_when_compute_port_cant_be_found(self): net_id = t_constants.MOCK_NOVA_INTERFACE.net_id - list_ports = self.driver.neutron_client.list_ports - list_ports.return_value = {'ports': []} + list_ports = self.driver.network_proxy.ports + list_ports.return_value = iter([]) self.assertRaises(network_base.NetworkNotFound, self.driver.unplug_network, t_constants.MOCK_COMPUTE_ID, net_id) def test_unplug_network_when_list_ports_fails(self): net_id = t_constants.MOCK_NOVA_INTERFACE.net_id - list_ports = self.driver.neutron_client.list_ports + list_ports = self.driver.network_proxy.ports list_ports.side_effect = Exception self.assertRaises(network_base.NetworkException, self.driver.unplug_network, @@ -1049,16 +1005,16 @@ class TestAllowedAddressPairsDriver(base.TestCase): @mock.patch("time.time") @mock.patch("time.sleep") def test_unplug_network(self, mock_time_sleep, mock_time_time): - list_ports = self.driver.neutron_client.list_ports - port1 = t_constants.MOCK_NEUTRON_PORT['port'] + list_ports = self.driver.network_proxy.ports + port1 = t_constants.MOCK_NEUTRON_PORT port2 = { 'id': '4', 'network_id': '3', 'fixed_ips': - [{'ip_address': '10.0.0.2'}] + [{'ip_address': '10.0.0.2'}] } list_ports.side_effect = [ - {'ports': [port1, port2]}, - {'ports': [port1, port2]}, - {'ports': [port1]} + iter([port1, port2]), + iter([port1, port2]), + iter([port1]), ] port_detach = self.driver.compute.detach_port @@ -1076,13 +1032,14 @@ class TestAllowedAddressPairsDriver(base.TestCase): @mock.patch("octavia.network.drivers.neutron.allowed_address_pairs.LOG") def test_unplug_network_timeout(self, mock_log, mock_time_sleep, mock_time_time): - list_ports = self.driver.neutron_client.list_ports - port1 = t_constants.MOCK_NEUTRON_PORT['port'] - port2 = { + list_ports = self.driver.network_proxy.ports + port1 = t_constants.MOCK_NEUTRON_PORT + port2 = Port(**{ 'id': '4', 'network_id': '3', 'fixed_ips': - [{'ip_address': '10.0.0.2'}] - } - list_ports.return_value = {'ports': [port1, port2]} + [{'ip_address': '10.0.0.2'}] + }) + + list_ports.side_effect = [iter([port1, port2]) for _ in range(7)] port_detach = self.driver.compute.detach_port mock_time_time.side_effect = [0, 0, 1, 2, 10, 20, 100, 300] @@ -1114,118 +1071,101 @@ class TestAllowedAddressPairsDriver(base.TestCase): ip_address=self.IPV6_ADDRESS_1) lb = data_models.LoadBalancer(id='1', listeners=listeners, vip=vip, additional_vips=[additional_vip]) - list_sec_grps = self.driver.neutron_client.list_security_groups - list_sec_grps.return_value = {'security_groups': [{'id': 'secgrp-1'}]} - fake_rules = { - 'security_group_rules': [ - {'id': 'rule-80', 'port_range_max': 80, 'protocol': 'tcp', - 'remote_ip_prefix': '10.0.101.0/24'}, - {'id': 'rule-22', 'port_range_max': 22, 'protocol': 'tcp'} - ] - } - list_rules = self.driver.neutron_client.list_security_group_rules + list_sec_grps = self.driver.network_proxy.find_security_group + list_sec_grps.return_value = {'id': 'secgrp-1'} + fake_rules = [ + {'id': 'rule-80', 'port_range_max': 80, 'protocol': 'tcp', + 'remote_ip_prefix': '10.0.101.0/24'}, + {'id': 'rule-22', 'port_range_max': 22, 'protocol': 'tcp'} + ] + list_rules = self.driver.network_proxy.security_group_rules list_rules.return_value = fake_rules - delete_rule = self.driver.neutron_client.delete_security_group_rule - create_rule = self.driver.neutron_client.create_security_group_rule + delete_rule = self.driver.network_proxy.delete_security_group_rule + create_rule = self.driver.network_proxy.create_security_group_rule self.driver.update_vip(lb) delete_rule.assert_called_once_with('rule-22') expected_create_rule_1 = { - 'security_group_rule': { - 'security_group_id': 'secgrp-1', - 'direction': 'ingress', - 'protocol': 'tcp', - 'port_range_min': 1024, - 'port_range_max': 1024, - 'ethertype': 'IPv4', - 'remote_ip_prefix': None - } + 'security_group_id': 'secgrp-1', + 'direction': 'ingress', + 'protocol': 'tcp', + 'port_range_min': 1024, + 'port_range_max': 1024, + 'ethertype': 'IPv4', + 'remote_ip_prefix': None } expected_create_rule_udp_peer = { - 'security_group_rule': { - 'security_group_id': 'secgrp-1', - 'direction': 'ingress', - 'protocol': 'tcp', - 'port_range_min': 1026, - 'port_range_max': 1026, - 'ethertype': 'IPv4', - 'remote_ip_prefix': None - } + 'security_group_id': 'secgrp-1', + 'direction': 'ingress', + 'protocol': 'tcp', + 'port_range_min': 1026, + 'port_range_max': 1026, + 'ethertype': 'IPv4', + 'remote_ip_prefix': None } expected_create_rule_2 = { - 'security_group_rule': { - 'security_group_id': 'secgrp-1', - 'direction': 'ingress', - 'protocol': 'tcp', - 'port_range_min': 1025, - 'port_range_max': 1025, - 'ethertype': 'IPv4', - 'remote_ip_prefix': None - } + 'security_group_id': 'secgrp-1', + 'direction': 'ingress', + 'protocol': 'tcp', + 'port_range_min': 1025, + 'port_range_max': 1025, + 'ethertype': 'IPv4', + 'remote_ip_prefix': None } expected_create_rule_3 = { - 'security_group_rule': { - 'security_group_id': 'secgrp-1', - 'direction': 'ingress', - 'protocol': 'tcp', - 'port_range_min': 443, - 'port_range_max': 443, - 'ethertype': 'IPv4', - 'remote_ip_prefix': '10.0.102.0/24' - } + 'security_group_id': 'secgrp-1', + 'direction': 'ingress', + 'protocol': 'tcp', + 'port_range_min': 443, + 'port_range_max': 443, + 'ethertype': 'IPv4', + 'remote_ip_prefix': '10.0.102.0/24' } expected_create_rule_4 = { - 'security_group_rule': { - 'security_group_id': 'secgrp-1', - 'direction': 'ingress', - 'protocol': 'tcp', - 'port_range_min': 443, - 'port_range_max': 443, - 'ethertype': 'IPv4', - 'remote_ip_prefix': '10.0.103.0/24' - } + 'security_group_id': 'secgrp-1', + 'direction': 'ingress', + 'protocol': 'tcp', + 'port_range_min': 443, + 'port_range_max': 443, + 'ethertype': 'IPv4', + 'remote_ip_prefix': '10.0.103.0/24' } expected_create_rule_5 = { - 'security_group_rule': { - 'security_group_id': 'secgrp-1', - 'direction': 'ingress', - 'protocol': 'tcp', - 'port_range_min': 443, - 'port_range_max': 443, - 'ethertype': 'IPv6', - 'remote_ip_prefix': '2001:0DB8::/32' - } + 'security_group_id': 'secgrp-1', + 'direction': 'ingress', + 'protocol': 'tcp', + 'port_range_min': 443, + 'port_range_max': 443, + 'ethertype': 'IPv6', + 'remote_ip_prefix': '2001:0DB8::/32' } expected_create_rule_udp_1 = { - 'security_group_rule': { - 'security_group_id': 'secgrp-1', - 'direction': 'ingress', - 'protocol': 'udp', - 'port_range_min': 50, - 'port_range_max': 50, - 'ethertype': 'IPv4', - 'remote_ip_prefix': None - } + 'security_group_id': 'secgrp-1', + 'direction': 'ingress', + 'protocol': 'udp', + 'port_range_min': 50, + 'port_range_max': 50, + 'ethertype': 'IPv4', + 'remote_ip_prefix': None } expected_create_rule_udp_2 = { - 'security_group_rule': { - 'security_group_id': 'secgrp-1', - 'direction': 'ingress', - 'protocol': 'udp', - 'port_range_min': 50, - 'port_range_max': 50, - 'ethertype': 'IPv6', - 'remote_ip_prefix': None - } + 'security_group_id': 'secgrp-1', + 'direction': 'ingress', + 'protocol': 'udp', + 'port_range_min': 50, + 'port_range_max': 50, + 'ethertype': 'IPv6', + 'remote_ip_prefix': None } - create_rule.assert_has_calls([mock.call(expected_create_rule_1), - mock.call(expected_create_rule_udp_peer), - mock.call(expected_create_rule_2), - mock.call(expected_create_rule_3), - mock.call(expected_create_rule_4), - mock.call(expected_create_rule_5), - mock.call(expected_create_rule_udp_1), - mock.call(expected_create_rule_udp_2)], + create_rule.assert_has_calls([mock.call(**expected_create_rule_1), + mock.call( + **expected_create_rule_udp_peer), + mock.call(**expected_create_rule_2), + mock.call(**expected_create_rule_3), + mock.call(**expected_create_rule_4), + mock.call(**expected_create_rule_5), + mock.call(**expected_create_rule_udp_1), + mock.call(**expected_create_rule_udp_2)], any_order=True) def test_update_vip_when_protocol_and_peer_ports_overlap(self): @@ -1239,18 +1179,16 @@ class TestAllowedAddressPairsDriver(base.TestCase): allowed_cidrs=[lc_1])] vip = data_models.Vip(ip_address='10.0.0.2') lb = data_models.LoadBalancer(id='1', listeners=listeners, vip=vip) - list_sec_grps = self.driver.neutron_client.list_security_groups - list_sec_grps.return_value = {'security_groups': [{'id': 'secgrp-1'}]} - fake_rules = { - 'security_group_rules': [ - {'id': 'rule-80', 'port_range_max': 80, 'protocol': 'tcp'}, - {'id': 'rule-22', 'port_range_max': 22, 'protocol': 'tcp'} - ] - } - list_rules = self.driver.neutron_client.list_security_group_rules + list_sec_grps = self.driver.network_proxy.find_security_group + list_sec_grps.return_value = {'id': 'secgrp-1'} + fake_rules = [ + {'id': 'rule-80', 'port_range_max': 80, 'protocol': 'tcp'}, + {'id': 'rule-22', 'port_range_max': 22, 'protocol': 'tcp'} + ] + list_rules = self.driver.network_proxy.security_group_rules list_rules.return_value = fake_rules - delete_rule = self.driver.neutron_client.delete_security_group_rule - create_rule = self.driver.neutron_client.create_security_group_rule + delete_rule = self.driver.network_proxy.delete_security_group_rule + create_rule = self.driver.network_proxy.create_security_group_rule self.driver.update_vip(lb) delete_rule.assert_called_once_with('rule-22') @@ -1270,19 +1208,17 @@ class TestAllowedAddressPairsDriver(base.TestCase): provisioning_status=constants.PENDING_DELETE)] vip = data_models.Vip(ip_address='10.0.0.2') lb = data_models.LoadBalancer(id='1', listeners=listeners, vip=vip) - list_sec_grps = self.driver.neutron_client.list_security_groups - list_sec_grps.return_value = {'security_groups': [{'id': 'secgrp-1'}]} - fake_rules = { - 'security_group_rules': [ - {'id': 'rule-80', 'port_range_max': 80, 'protocol': 'tcp'}, - {'id': 'rule-22', 'port_range_max': 443, 'protocol': 'tcp'}, - {'id': 'rule-udp-50', 'port_range_max': 50, 'protocol': 'tcp'} - ] - } - list_rules = self.driver.neutron_client.list_security_group_rules + list_sec_grps = self.driver.network_proxy.find_security_group + list_sec_grps.return_value = {'id': 'secgrp-1'} + fake_rules = [ + {'id': 'rule-80', 'port_range_max': 80, 'protocol': 'tcp'}, + {'id': 'rule-22', 'port_range_max': 443, 'protocol': 'tcp'}, + {'id': 'rule-udp-50', 'port_range_max': 50, 'protocol': 'tcp'} + ] + list_rules = self.driver.network_proxy.security_group_rules list_rules.return_value = fake_rules - delete_rule = self.driver.neutron_client.delete_security_group_rule - create_rule = self.driver.neutron_client.create_security_group_rule + delete_rule = self.driver.network_proxy.delete_security_group_rule + create_rule = self.driver.network_proxy.create_security_group_rule self.driver.update_vip(lb) delete_rule.assert_has_calls( [mock.call('rule-22'), mock.call('rule-udp-50')]) @@ -1292,17 +1228,15 @@ class TestAllowedAddressPairsDriver(base.TestCase): listeners = [] vip = data_models.Vip(ip_address='10.0.0.2') lb = data_models.LoadBalancer(id='1', listeners=listeners, vip=vip) - list_sec_grps = self.driver.neutron_client.list_security_groups - list_sec_grps.return_value = {'security_groups': [{'id': 'secgrp-1'}]} - fake_rules = { - 'security_group_rules': [ - {'id': 'all-egress', 'protocol': None, 'direction': 'egress'}, - {'id': 'ssh-rule', 'protocol': 'tcp', 'port_range_max': 22} - ] - } - list_rules = self.driver.neutron_client.list_security_group_rules + list_sec_grps = self.driver.network_proxy.find_security_group + list_sec_grps.return_value = {'id': 'secgrp-1'} + fake_rules = [ + {'id': 'all-egress', 'protocol': None, 'direction': 'egress'}, + {'id': 'ssh-rule', 'protocol': 'tcp', 'port_range_max': 22} + ] + list_rules = self.driver.network_proxy.security_group_rules list_rules.return_value = fake_rules - delete_rule = self.driver.neutron_client.delete_security_group_rule + delete_rule = self.driver.network_proxy.delete_security_group_rule self.driver.update_vip(lb) delete_rule.assert_called_once_with('ssh-rule') @@ -1310,18 +1244,16 @@ class TestAllowedAddressPairsDriver(base.TestCase): listeners = [] vip = data_models.Vip(ip_address='10.0.0.2') lb = data_models.LoadBalancer(id='1', listeners=listeners, vip=vip) - list_sec_grps = self.driver.neutron_client.list_security_groups - list_sec_grps.return_value = {'security_groups': [{'id': 'secgrp-1'}]} - fake_rules = { - 'security_group_rules': [ - {'id': 'all-egress', 'protocol': None, 'direction': 'egress'}, - {'id': 'ssh-rule', 'protocol': 'tcp', 'port_range_max': 22} - ] - } - list_rules = self.driver.neutron_client.list_security_group_rules + list_sec_grps = self.driver.network_proxy.find_security_group + list_sec_grps.return_value = {'id': 'secgrp-1'} + fake_rules = [ + {'id': 'all-egress', 'protocol': None, 'direction': 'egress'}, + {'id': 'ssh-rule', 'protocol': 'tcp', 'port_range_max': 22} + ] + list_rules = self.driver.network_proxy.security_group_rules list_rules.return_value = fake_rules - delete_rule = self.driver.neutron_client.delete_security_group_rule - delete_rule.side_effect = neutron_exceptions.NotFound + delete_rule = self.driver.network_proxy.delete_security_group_rule + delete_rule.side_effect = os_exceptions.ResourceNotFound self.driver.update_vip(lb) delete_rule.assert_called_once_with('ssh-rule') @@ -1329,8 +1261,8 @@ class TestAllowedAddressPairsDriver(base.TestCase): listeners = [] vip = data_models.Vip(ip_address='10.0.0.2') lb = data_models.LoadBalancer(id='1', listeners=listeners, vip=vip) - list_sec_grps = self.driver.neutron_client.list_security_groups - list_sec_grps.return_value = {'security_groups': []} + list_sec_grps = self.driver.network_proxy.find_security_group + list_sec_grps.return_value = None self.assertRaises(exceptions.MissingVIPSecurityGroup, self.driver.update_vip, lb) @@ -1342,25 +1274,27 @@ class TestAllowedAddressPairsDriver(base.TestCase): listeners = [] vip = data_models.Vip(ip_address='10.0.0.2') lb = data_models.LoadBalancer(id='1', listeners=listeners, vip=vip) - list_sec_grps = self.driver.neutron_client.list_security_groups - list_sec_grps.return_value = {'security_groups': []} + list_sec_grps = self.driver.network_proxy.find_security_group + list_sec_grps.return_value = None self.driver.update_vip(lb, for_delete=True) update_rules.assert_not_called() def test_failover_preparation(self): original_dns_integration_state = self.driver.dns_integration_enabled self.driver.dns_integration_enabled = False - ports = {"ports": [ - {"fixed_ips": [{"subnet_id": self.SUBNET_ID_1, - "ip_address": self.IP_ADDRESS_1}], - "id": self.FIXED_IP_ID_1, "network_id": self.NETWORK_ID_1}, - {"fixed_ips": [{"subnet_id": self.SUBNET_ID_2, - "ip_address": self.IP_ADDRESS_2}], - "id": self.FIXED_IP_ID_2, "network_id": self.NETWORK_ID_2}]} - self.driver.neutron_client.list_ports.return_value = ports - self.driver.neutron_client.show_port = mock.Mock( + ports = [ + Port(**{"fixed_ips": [{"subnet_id": self.SUBNET_ID_1, + "ip_address": self.IP_ADDRESS_1}], + "id": self.FIXED_IP_ID_1, + "network_id": self.NETWORK_ID_1}), + Port(**{"fixed_ips": [{"subnet_id": self.SUBNET_ID_2, + "ip_address": self.IP_ADDRESS_2}], + "id": self.FIXED_IP_ID_2, + "network_id": self.NETWORK_ID_2})] + self.driver.network_proxy.ports.return_value = ports + self.driver.network_proxy.get_port = mock.Mock( side_effect=self._failover_show_port_side_effect) - port_update = self.driver.neutron_client.update_port + port_update = self.driver.network_proxy.update_port amphora = data_models.Amphora( id=self.AMPHORA_ID, load_balancer_id=self.LB_ID, compute_id=self.COMPUTE_ID, status=self.ACTIVE, @@ -1371,38 +1305,42 @@ class TestAllowedAddressPairsDriver(base.TestCase): self.driver.dns_integration_enabled = original_dns_integration_state def test_failover_preparation_dns_integration(self): - ports = {"ports": [ - {"fixed_ips": [{"subnet_id": self.SUBNET_ID_1, - "ip_address": self.IP_ADDRESS_1}], - "id": self.FIXED_IP_ID_1, "network_id": self.NETWORK_ID_1}, - {"fixed_ips": [{"subnet_id": self.SUBNET_ID_2, - "ip_address": self.IP_ADDRESS_2}], - "id": self.FIXED_IP_ID_2, "network_id": self.NETWORK_ID_2}]} + ports = [ + Port(**{"fixed_ips": [{"subnet_id": self.SUBNET_ID_1, + "ip_address": self.IP_ADDRESS_1}], + "id": self.FIXED_IP_ID_1, + "network_id": self.NETWORK_ID_1}), + Port(**{"fixed_ips": [{"subnet_id": self.SUBNET_ID_2, + "ip_address": self.IP_ADDRESS_2}], + "id": self.FIXED_IP_ID_2, + "network_id": self.NETWORK_ID_2})] original_dns_integration_state = self.driver.dns_integration_enabled self.driver.dns_integration_enabled = True - self.driver.neutron_client.list_ports.return_value = ports - self.driver.neutron_client.show_port = mock.Mock( + self.driver.network_proxy.ports.return_value = ports + self.driver.network_proxy.get_port = mock.Mock( side_effect=self._failover_show_port_side_effect) - port_update = self.driver.neutron_client.update_port + port_update = self.driver.network_proxy.update_port amphora = data_models.Amphora( id=self.AMPHORA_ID, load_balancer_id=self.LB_ID, compute_id=self.COMPUTE_ID, status=self.ACTIVE, lb_network_ip=self.LB_NET_IP, ha_port_id=self.HA_PORT_ID, ha_ip=self.HA_IP) self.driver.failover_preparation(amphora) - port_update.assert_called_once_with(ports['ports'][1].get('id'), - {'port': {'dns_name': ''}}) + port_update.assert_called_once_with(ports[1].get('id'), + dns_name='') self.driver.dns_integration_enabled = original_dns_integration_state def _failover_show_port_side_effect(self, port_id): if port_id == self.LB_NET_PORT_ID: - return {"fixed_ips": [{"subnet_id": self.SUBNET_ID_1, - "ip_address": self.IP_ADDRESS_1}], - "id": self.FIXED_IP_ID_1, "network_id": self.NETWORK_ID_1} + return Port(**{"fixed_ips": [{"subnet_id": self.SUBNET_ID_1, + "ip_address": self.IP_ADDRESS_1}], + "id": self.FIXED_IP_ID_1, + "network_id": self.NETWORK_ID_1}) if port_id == self.HA_PORT_ID: - return {"fixed_ips": [{"subnet_id": self.SUBNET_ID_2, - "ip_address": self.IP_ADDRESS_2}], - "id": self.FIXED_IP_ID_2, "network_id": self.NETWORK_ID_2} + return Port(**{"fixed_ips": [{"subnet_id": self.SUBNET_ID_2, + "ip_address": self.IP_ADDRESS_2}], + "id": self.FIXED_IP_ID_2, + "network_id": self.NETWORK_ID_2}) def test_plug_port(self): port = mock.MagicMock() @@ -1459,7 +1397,7 @@ class TestAllowedAddressPairsDriver(base.TestCase): vip_mock = mock.MagicMock() amphora_mock.status = constants.DELETED load_balancer_mock.amphorae = [amphora_mock] - show_port = self.driver.neutron_client.show_port + show_port = self.driver.network_proxy.get_port show_port.side_effect = [ t_constants.MOCK_NEUTRON_PORT, t_constants.MOCK_NEUTRON_PORT, t_constants.MOCK_NEUTRON_PORT, t_constants.MOCK_NEUTRON_PORT, @@ -1469,15 +1407,15 @@ class TestAllowedAddressPairsDriver(base.TestCase): t_constants.MOCK_NEUTRON_PORT, t_constants.MOCK_NEUTRON_PORT, t_constants.MOCK_NEUTRON_PORT, t_constants.MOCK_NEUTRON_PORT, Exception('boom')] - fake_subnet = {'subnet': { + fake_subnet = Subnet(**{ 'id': t_constants.MOCK_SUBNET_ID, 'gateway_ip': t_constants.MOCK_IP_ADDRESS, - 'cidr': t_constants.MOCK_CIDR}} - fake_subnet2 = {'subnet': { + 'cidr': t_constants.MOCK_CIDR}) + fake_subnet2 = Subnet(**{ 'id': t_constants.MOCK_SUBNET_ID2, 'gateway_ip': t_constants.MOCK_IP_ADDRESS2, - 'cidr': t_constants.MOCK_CIDR}} - show_subnet = self.driver.neutron_client.show_subnet + 'cidr': t_constants.MOCK_CIDR}) + show_subnet = self.driver.network_proxy.get_subnet show_subnet.return_value = fake_subnet configs = self.driver.get_network_configs(load_balancer_mock) self.assertEqual({}, configs) @@ -1504,10 +1442,10 @@ class TestAllowedAddressPairsDriver(base.TestCase): # will return the same values if a method happens to call it # multiple times for different subnets. We should be able to verify # different requests get different expected data. - expected_port_id = t_constants.MOCK_NEUTRON_PORT['port']['id'] + expected_port_id = t_constants.MOCK_NEUTRON_PORT['id'] self.assertEqual(expected_port_id, config.ha_port.id) self.assertEqual(expected_port_id, config.vrrp_port.id) - expected_subnet_id = fake_subnet['subnet']['id'] + expected_subnet_id = fake_subnet['id'] self.assertEqual(expected_subnet_id, config.ha_subnet.id) self.assertEqual(expected_subnet_id, config.vrrp_subnet.id) @@ -1545,10 +1483,10 @@ class TestAllowedAddressPairsDriver(base.TestCase): # will return the same values if a method happens to call it # multiple times for different subnets. We should be able to verify # different requests get different expected data. - expected_port_id = t_constants.MOCK_NEUTRON_PORT['port']['id'] + expected_port_id = t_constants.MOCK_NEUTRON_PORT['id'] self.assertEqual(expected_port_id, config.ha_port.id) self.assertEqual(expected_port_id, config.vrrp_port.id) - expected_subnet_id = fake_subnet['subnet']['id'] + expected_subnet_id = fake_subnet['id'] self.assertEqual(expected_subnet_id, config.ha_subnet.id) self.assertEqual(expected_subnet_id, config.vrrp_subnet.id) @@ -1565,33 +1503,33 @@ class TestAllowedAddressPairsDriver(base.TestCase): compute_id=self.COMPUTE_ID, status=self.ACTIVE, lb_network_ip=self.LB_NET_IP, ha_port_id=self.HA_PORT_ID, ha_ip=self.HA_IP) - ports = {"ports": [ - {"fixed_ips": [{"subnet_id": self.SUBNET_ID_1, - "ip_address": self.IP_ADDRESS_1}], - "id": self.FIXED_IP_ID_1, "network_id": self.NETWORK_ID_1}, - {"fixed_ips": [{"subnet_id": self.SUBNET_ID_2, - "ip_address": self.IP_ADDRESS_2}], - "id": self.FIXED_IP_ID_2, "network_id": self.NETWORK_ID_2}]} - show_port_1_without_device_id = {"fixed_ips": [ + ports = (p for p in [ + Port(**{"fixed_ips": [{"subnet_id": self.SUBNET_ID_1, + "ip_address": self.IP_ADDRESS_1}], + "id": self.FIXED_IP_ID_1, + "network_id": self.NETWORK_ID_1}), + Port(**{"fixed_ips": [{"subnet_id": self.SUBNET_ID_2, + "ip_address": self.IP_ADDRESS_2}], + "id": self.FIXED_IP_ID_2, + "network_id": self.NETWORK_ID_2})]) + show_port_1_without_device_id = Port(**{"fixed_ips": [ {"subnet_id": self.SUBNET_ID_1, "ip_address": self.IP_ADDRESS_1}], "id": self.FIXED_IP_ID_1, "network_id": self.NETWORK_ID_1, - "device_id": ''} - show_port_2_with_device_id = {"fixed_ips": [ + "device_id": ''}) + show_port_2_with_device_id = Port(**{"fixed_ips": [ {"subnet_id": self.SUBNET_ID_2, "ip_address": self.IP_ADDRESS_2}], "id": self.FIXED_IP_ID_2, "network_id": self.NETWORK_ID_2, - "device_id": self.DEVICE_ID} - show_port_2_without_device_id = {"fixed_ips": [ + "device_id": self.DEVICE_ID}) + show_port_2_without_device_id = Port(**{"fixed_ips": [ {"subnet_id": self.SUBNET_ID_2, "ip_address": self.IP_ADDRESS_2}], "id": self.FIXED_IP_ID_2, "network_id": self.NETWORK_ID_2, - "device_id": None} - self.driver.neutron_client.list_ports.return_value = ports - port_mock = mock.MagicMock() - port_mock.get = mock.Mock( + "device_id": None}) + self.driver.network_proxy.ports.return_value = ports + self.driver.network_proxy.get_port = mock.MagicMock( side_effect=[show_port_1_without_device_id, show_port_2_with_device_id, show_port_2_with_device_id, show_port_2_without_device_id]) - self.driver.neutron_client.show_port.return_value = port_mock self.driver.wait_for_port_detach(amphora) self.assertEqual(1, mock_sleep.call_count) @@ -1606,22 +1544,22 @@ class TestAllowedAddressPairsDriver(base.TestCase): compute_id=self.COMPUTE_ID, status=self.ACTIVE, lb_network_ip=self.LB_NET_IP, ha_port_id=self.HA_PORT_ID, ha_ip=self.HA_IP) - ports = {"ports": [ - {"fixed_ips": [{"subnet_id": self.SUBNET_ID_1, - "ip_address": self.IP_ADDRESS_1}], - "id": self.FIXED_IP_ID_1, "network_id": self.NETWORK_ID_1}, - {"fixed_ips": [{"subnet_id": self.SUBNET_ID_2, - "ip_address": self.IP_ADDRESS_2}], - "id": self.FIXED_IP_ID_2, "network_id": self.NETWORK_ID_2}]} - show_port_1_with_device_id = {"fixed_ips": [ + ports = (p for p in [ + Port(**{"fixed_ips": [{"subnet_id": self.SUBNET_ID_1, + "ip_address": self.IP_ADDRESS_1}], + "id": self.FIXED_IP_ID_1, + "network_id": self.NETWORK_ID_1}), + Port(**{"fixed_ips": [{"subnet_id": self.SUBNET_ID_2, + "ip_address": self.IP_ADDRESS_2}], + "id": self.FIXED_IP_ID_2, + "network_id": self.NETWORK_ID_2})]) + show_port_1_with_device_id = Port(**{"fixed_ips": [ {"subnet_id": self.SUBNET_ID_2, "ip_address": self.IP_ADDRESS_2}], "id": self.FIXED_IP_ID_2, "network_id": self.NETWORK_ID_2, - "device_id": self.DEVICE_ID} - self.driver.neutron_client.list_ports.return_value = ports - port_mock = mock.MagicMock() - port_mock.get = mock.Mock( + "device_id": self.DEVICE_ID}) + self.driver.network_proxy.ports.return_value = ports + self.driver.network_proxy.get_port = mock.MagicMock( return_value=show_port_1_with_device_id) - self.driver.neutron_client.show_port.return_value = port_mock self.assertRaises(network_base.TimeoutException, self.driver.wait_for_port_detach, amphora) @@ -1629,13 +1567,14 @@ class TestAllowedAddressPairsDriver(base.TestCase): def test_delete_port(self): PORT_ID = uuidutils.generate_uuid() - self.driver.neutron_client.delete_port.side_effect = [ - mock.DEFAULT, neutron_exceptions.NotFound, Exception('boom')] + self.driver.network_proxy.delete_port.side_effect = [ + mock.DEFAULT, os_exceptions.ResourceNotFound, + Exception('boom')] # Test successful delete self.driver.delete_port(PORT_ID) - self.driver.neutron_client.delete_port.assert_called_once_with(PORT_ID) + self.driver.network_proxy.delete_port.assert_called_once_with(PORT_ID) # Test port NotFound (does not raise) self.driver.delete_port(PORT_ID) @@ -1648,24 +1587,24 @@ class TestAllowedAddressPairsDriver(base.TestCase): PORT_ID = uuidutils.generate_uuid() TEST_STATE = 'test state' - self.driver.neutron_client.update_port.side_effect = [ - mock.DEFAULT, neutron_exceptions.NotFound, Exception('boom')] + self.driver.network_proxy.update_port.side_effect = [ + mock.DEFAULT, os_exceptions.ResourceNotFound, Exception('boom')] # Test successful state set self.driver.set_port_admin_state_up(PORT_ID, TEST_STATE) - self.driver.neutron_client.update_port.assert_called_once_with( - PORT_ID, {'port': {'admin_state_up': TEST_STATE}}) + self.driver.network_proxy.update_port.assert_called_once_with( + PORT_ID, admin_state_up=TEST_STATE) # Test port NotFound self.assertRaises(network_base.PortNotFound, self.driver.set_port_admin_state_up, - PORT_ID, {'port': {'admin_state_up': TEST_STATE}}) + PORT_ID, TEST_STATE) # Test unknown exception self.assertRaises(exceptions.NetworkServiceError, self.driver.set_port_admin_state_up, PORT_ID, - {'port': {'admin_state_up': TEST_STATE}}) + TEST_STATE) def test_create_port(self): ADMIN_STATE_UP = False @@ -1680,7 +1619,7 @@ class TestAllowedAddressPairsDriver(base.TestCase): SUBNET1_ID = uuidutils.generate_uuid() FIXED_IPS = [{'subnet_id': SUBNET1_ID, 'ip_address': IP_ADDRESS1}] - MOCK_NEUTRON_PORT = {'port': { + MOCK_NEUTRON_PORT = Port(**{ 'network_id': NETWORK_ID, 'device_id': t_constants.MOCK_DEVICE_ID, 'device_owner': t_constants.MOCK_DEVICE_OWNER, 'id': t_constants.MOCK_PORT_ID, 'name': FAKE_NAME, @@ -1691,7 +1630,7 @@ class TestAllowedAddressPairsDriver(base.TestCase): 'fixed_ips': [{'ip_address': IP_ADDRESS1, 'subnet_id': SUBNET1_ID}], 'security_groups': [], - 'qos_policy_id': QOS_POLICY_ID}} + 'qos_policy_id': QOS_POLICY_ID}) reference_port_dict = {'admin_state_up': ADMIN_STATE_UP, 'device_id': t_constants.MOCK_DEVICE_ID, @@ -1707,7 +1646,7 @@ class TestAllowedAddressPairsDriver(base.TestCase): 'security_group_ids': [], 'status': t_constants.MOCK_STATUS} - self.driver.neutron_client.create_port.side_effect = [ + self.driver.network_proxy.create_port.side_effect = [ MOCK_NEUTRON_PORT, MOCK_NEUTRON_PORT, Exception('boom')] # Test successful path @@ -1718,8 +1657,8 @@ class TestAllowedAddressPairsDriver(base.TestCase): qos_policy_id=QOS_POLICY_ID) self.assertEqual(reference_port_dict, result.to_dict()) - self.driver.neutron_client.create_port.assert_called_once_with( - {'port': { + self.driver.network_proxy.create_port.assert_called_once_with( + **{ 'network_id': NETWORK_ID, 'admin_state_up': ADMIN_STATE_UP, 'device_owner': allowed_address_pairs.OCTAVIA_OWNER, 'allowed_address_pairs': [ @@ -1727,7 +1666,7 @@ class TestAllowedAddressPairsDriver(base.TestCase): 'fixed_ips': [{ 'subnet_id': SUBNET1_ID, 'ip_address': IP_ADDRESS1}], 'name': FAKE_NAME, 'qos_policy_id': QOS_POLICY_ID, - 'security_groups': [SECURITY_GROUP_ID]}}) + 'security_groups': [SECURITY_GROUP_ID]}) # Test minimal successful path result = self.driver.create_port(NETWORK_ID) @@ -1745,8 +1684,7 @@ class TestAllowedAddressPairsDriver(base.TestCase): # Test the case of security groups disabled in neutron FAKE_SG_NAME = 'Fake_SG_name' - FAKE_NEUTRON_SECURITY_GROUPS = {'security_groups': [ - t_constants.MOCK_SECURITY_GROUP]} + FAKE_NEUTRON_SECURITY_GROUPS = iter([t_constants.MOCK_SECURITY_GROUP]) reference_sg_dict = {'id': t_constants.MOCK_SECURITY_GROUP_ID, 'name': t_constants.MOCK_SECURITY_GROUP_NAME, 'description': '', 'tags': [], @@ -1754,15 +1692,15 @@ class TestAllowedAddressPairsDriver(base.TestCase): 'stateful': None, 'project_id': t_constants.MOCK_PROJECT_ID} - neutron_client = self.driver.neutron_client - neutron_client.list_security_groups.side_effect = [ - FAKE_NEUTRON_SECURITY_GROUPS, None, Exception('boom')] + network_proxy = self.driver.network_proxy + network_proxy.security_groups.side_effect = [ + FAKE_NEUTRON_SECURITY_GROUPS, iter([]), Exception('boom')] self.driver.sec_grp_enabled = False result = self.driver.get_security_group(FAKE_SG_NAME) self.assertIsNone(result) - neutron_client.list_security_groups.assert_not_called() + network_proxy.security_groups.assert_not_called() # Test successful get of the security group self.driver.sec_grp_enabled = True @@ -1770,7 +1708,7 @@ class TestAllowedAddressPairsDriver(base.TestCase): result = self.driver.get_security_group(FAKE_SG_NAME) self.assertEqual(reference_sg_dict, result.to_dict()) - neutron_client.list_security_groups.assert_called_once_with( + network_proxy.security_groups.assert_called_once_with( name=FAKE_SG_NAME) # Test no security groups returned diff --git a/octavia/tests/unit/network/drivers/neutron/test_base.py b/octavia/tests/unit/network/drivers/neutron/test_base.py index 2ea5a070bb..975a0f9149 100644 --- a/octavia/tests/unit/network/drivers/neutron/test_base.py +++ b/octavia/tests/unit/network/drivers/neutron/test_base.py @@ -13,11 +13,9 @@ # under the License. from unittest import mock -from neutronclient.common import exceptions as neutron_client_exceptions from oslo_config import cfg from oslo_config import fixture as oslo_fixture -from octavia.common import clients from octavia.common import data_models from octavia.network import base as network_base from octavia.network import data_models as network_models @@ -26,6 +24,12 @@ from octavia.network.drivers.neutron import utils from octavia.tests.common import constants as t_constants from octavia.tests.common import data_model_helpers as dmh from octavia.tests.unit import base +import openstack.exceptions as os_exceptions +from openstack.network.v2.network import Network +from openstack.network.v2.network_ip_availability import NetworkIPAvailability +from openstack.network.v2.port import Port +from openstack.network.v2.qos_policy import QoSPolicy +from openstack.network.v2.subnet import Subnet class TestBaseNeutronNetworkDriver(base.TestCase): @@ -42,95 +46,88 @@ class TestBaseNeutronNetworkDriver(base.TestCase): def setUp(self): super().setUp() - with mock.patch('octavia.common.clients.neutron_client.Client', - autospec=True) as neutron_client: - client = neutron_client(clients.NEUTRON_VERSION) - client.list_extensions.return_value = { - 'extensions': [ - {'alias': neutron_base.SEC_GRP_EXT_ALIAS} - ] - } + with mock.patch('octavia.common.clients.openstack.connection.' + 'Connection', autospec=True) as os_connection: + self._original_find_extension = ( + os_connection.return_value.network.find_extension) + os_connection.return_value.network.find_extension = ( + lambda x: 'alias' if x == neutron_base.SEC_GRP_EXT_ALIAS else + None) self.k_session = mock.patch( 'keystoneauth1.session.Session').start() self.driver = self._instantiate_partial_abc( neutron_base.BaseNeutronDriver) def test__check_extension_enabled(self): - show_extension = self.driver.neutron_client.show_extension - show_extension.side_effect = [None, neutron_client_exceptions.NotFound] - - self.assertTrue(self.driver._check_extension_enabled('TEST1')) - self.assertFalse(self.driver._check_extension_enabled('TEST2')) - show_extension.assert_has_calls( - [mock.call('TEST1'), mock.call('TEST2')]) + with mock.patch.object(self.driver.network_proxy, "find_extension", + side_effect=[True, False]) as show_extension: + self.assertTrue(self.driver._check_extension_enabled('TEST1')) + self.assertFalse(self.driver._check_extension_enabled('TEST2')) + show_extension.assert_has_calls( + [mock.call('TEST1'), mock.call('TEST2')]) def test__check_extension_enabled_cached(self): - show_extension = self.driver.neutron_client.show_extension - - self.driver._check_extension_cache = {'TEST1': True, 'TEST2': False} - self.assertTrue(self.driver._check_extension_enabled('TEST1')) - self.assertFalse(self.driver._check_extension_enabled('TEST2')) - self.assertNotIn(mock.call('TEST1'), show_extension.mock_calls) - self.assertNotIn(mock.call('TEST2'), show_extension.mock_calls) + with mock.patch.object(self.driver.network_proxy, "find_extension", + ) as show_extension: + self.driver._check_extension_cache = {'TEST1': True, + 'TEST2': False} + self.assertTrue(self.driver._check_extension_enabled('TEST1')) + self.assertFalse(self.driver._check_extension_enabled('TEST2')) + self.assertNotIn(mock.call('TEST1'), show_extension.mock_calls) + self.assertNotIn(mock.call('TEST2'), show_extension.mock_calls) def test__add_allowed_address_pair_to_port(self): self.driver._add_allowed_address_pairs_to_port( t_constants.MOCK_PORT_ID, [t_constants.MOCK_IP_ADDRESS]) expected_aap_dict = { - 'port': { - 'allowed_address_pairs': [ - {'ip_address': t_constants.MOCK_IP_ADDRESS}]}} - self.driver.neutron_client.update_port.assert_has_calls([ - mock.call(t_constants.MOCK_PORT_ID, expected_aap_dict)]) + 'allowed_address_pairs': [ + {'ip_address': t_constants.MOCK_IP_ADDRESS}]} + self.driver.network_proxy.update_port.assert_has_calls([ + mock.call(t_constants.MOCK_PORT_ID, **expected_aap_dict)]) def test__add_security_group_to_port(self): self.driver._add_security_group_to_port( t_constants.MOCK_SECURITY_GROUP_ID, t_constants.MOCK_PORT_ID) expected_sg_dict = { - 'port': { - 'security_groups': [ - t_constants.MOCK_SECURITY_GROUP_ID]}} - self.driver.neutron_client.update_port.assert_has_calls([ - mock.call(t_constants.MOCK_PORT_ID, expected_sg_dict)]) + 'security_groups': [ + t_constants.MOCK_SECURITY_GROUP_ID]} + self.driver.network_proxy.update_port.assert_has_calls([ + mock.call(t_constants.MOCK_PORT_ID, **expected_sg_dict)]) def test__add_security_group_to_port_with_port_not_found(self): - self.driver.neutron_client.update_port.side_effect = ( - neutron_client_exceptions.PortNotFoundClient) + self.driver.network_proxy.update_port.side_effect = ( + os_exceptions.ResourceNotFound) self.assertRaises( network_base.PortNotFound, self.driver._add_security_group_to_port, t_constants.MOCK_SECURITY_GROUP_ID, t_constants.MOCK_PORT_ID) def test__add_security_group_to_port_with_other_exception(self): - self.driver.neutron_client.update_port.side_effect = IOError + self.driver.network_proxy.update_port.side_effect = IOError self.assertRaises( network_base.NetworkException, self.driver._add_security_group_to_port, t_constants.MOCK_SECURITY_GROUP_ID, t_constants.MOCK_PORT_ID) def test__get_ports_by_security_group(self): - self.driver.neutron_client.list_ports.return_value = { - "ports": [ - t_constants.MOCK_NEUTRON_PORT['port'], - t_constants.MOCK_NEUTRON_PORT2['port']] - } + self.driver.network_proxy.ports.return_value = [ + t_constants.MOCK_NEUTRON_PORT, + t_constants.MOCK_NEUTRON_PORT2] ports = self.driver._get_ports_by_security_group( t_constants.MOCK_SECURITY_GROUP_ID) self.assertEqual(1, len(ports)) - self.assertIn(t_constants.MOCK_NEUTRON_PORT['port'], ports) + self.assertIn(t_constants.MOCK_NEUTRON_PORT, ports) def test__create_security_group(self): sg_return = self.driver._create_security_group( t_constants.MOCK_SECURITY_GROUP_NAME) expected_sec_grp_dict = { - 'security_group': { - 'name': t_constants.MOCK_SECURITY_GROUP_NAME}} - self.driver.neutron_client.create_security_group.assert_has_calls([ - mock.call(expected_sec_grp_dict)]) + 'name': t_constants.MOCK_SECURITY_GROUP_NAME} + self.driver.network_proxy.create_security_group.assert_has_calls([ + mock.call(**expected_sec_grp_dict)]) self.assertEqual( sg_return, - self.driver.neutron_client.create_security_group()[ - 'security_group']) + self.driver.network_proxy.create_security_group()) def test__create_security_group_rule(self): self.driver._create_security_group_rule( @@ -142,22 +139,21 @@ class TestBaseNeutronNetworkDriver(base.TestCase): ethertype=5, cidr="10.0.0.0/24") expected_sec_grp_rule_dict = { - 'security_group_rule': { - 'security_group_id': t_constants.MOCK_SECURITY_GROUP_ID, - 'direction': 1, - 'protocol': 2, - 'port_range_min': 3, - 'port_range_max': 4, - 'ethertype': 5, - 'remote_ip_prefix': '10.0.0.0/24'}} - self.driver.neutron_client.create_security_group_rule.assert_has_calls( - [mock.call(expected_sec_grp_rule_dict)]) + 'security_group_id': t_constants.MOCK_SECURITY_GROUP_ID, + 'direction': 1, + 'protocol': 2, + 'port_range_min': 3, + 'port_range_max': 4, + 'ethertype': 5, + 'remote_ip_prefix': '10.0.0.0/24'} + self.driver.network_proxy.create_security_group_rule.assert_has_calls( + [mock.call(**expected_sec_grp_rule_dict)]) def test__port_to_vip(self): lb = dmh.generate_load_balancer_tree() lb.vip.subnet_id = t_constants.MOCK_SUBNET_ID lb.vip.ip_address = t_constants.MOCK_IP_ADDRESS - port = utils.convert_port_dict_to_model(t_constants.MOCK_NEUTRON_PORT) + port = utils.convert_port_to_model(t_constants.MOCK_NEUTRON_PORT) vip, additional_vips = self.driver._port_to_vip(port, lb) self.assertIsInstance(vip, data_models.Vip) self.assertIsInstance(additional_vips, list) @@ -179,19 +175,19 @@ class TestBaseNeutronNetworkDriver(base.TestCase): self.assertIn('10.0.0.1', ips) def test_get_plugged_networks(self): - list_ports = self.driver.neutron_client.list_ports + list_ports = self.driver.network_proxy.ports list_ports.side_effect = TypeError o_ifaces = self.driver.get_plugged_networks( t_constants.MOCK_DEVICE_ID) self.assertEqual(0, len(o_ifaces)) list_ports.side_effect = None list_ports.reset_mock() - port1 = t_constants.MOCK_NEUTRON_PORT['port'] + port1 = t_constants.MOCK_NEUTRON_PORT port2 = { 'id': '4', 'network_id': '3', 'fixed_ips': - [{'ip_address': '10.0.0.2'}] + [{'ip_address': '10.0.0.2'}] } - list_ports.return_value = {'ports': [port1, port2]} + list_ports.return_value = [port1, port2] plugged_networks = self.driver.get_plugged_networks( t_constants.MOCK_DEVICE_ID) for pn in plugged_networks: @@ -207,10 +203,10 @@ class TestBaseNeutronNetworkDriver(base.TestCase): config = self.useFixture(oslo_fixture.Config(cfg.CONF)) config.config(group="networking", allow_invisible_resource_usage=True) - show_network = self.driver.neutron_client.show_network - show_network.return_value = {'network': { + show_network = self.driver.network_proxy.get_network + show_network.return_value = Network(**{ 'id': t_constants.MOCK_NETWORK_ID, - 'subnets': [t_constants.MOCK_SUBNET_ID]}} + 'subnets': [t_constants.MOCK_SUBNET_ID]}) network = self.driver.get_network(t_constants.MOCK_NETWORK_ID) self.assertIsInstance(network, network_models.Network) self.assertEqual(t_constants.MOCK_NETWORK_ID, network.id) @@ -219,10 +215,10 @@ class TestBaseNeutronNetworkDriver(base.TestCase): @mock.patch("octavia.common.clients.NeutronAuth.get_user_neutron_client") def test_get_user_network(self, neutron_client_mock): - show_network = neutron_client_mock.return_value.show_network - show_network.return_value = {'network': { + show_network = neutron_client_mock.return_value.get_network + show_network.return_value = Network(**{ 'id': t_constants.MOCK_NETWORK_ID, - 'subnets': [t_constants.MOCK_SUBNET_ID]}} + 'subnets': [t_constants.MOCK_SUBNET_ID]}) network = self.driver.get_network(t_constants.MOCK_NETWORK_ID, context=mock.ANY) @@ -236,11 +232,11 @@ class TestBaseNeutronNetworkDriver(base.TestCase): config = self.useFixture(oslo_fixture.Config(cfg.CONF)) config.config(group="networking", allow_invisible_resource_usage=True) - show_subnet = self.driver.neutron_client.show_subnet - show_subnet.return_value = {'subnet': { + show_subnet = self.driver.network_proxy.get_subnet + show_subnet.return_value = Subnet(**{ 'id': t_constants.MOCK_SUBNET_ID, 'gateway_ip': t_constants.MOCK_IP_ADDRESS, - 'cidr': t_constants.MOCK_CIDR}} + 'cidr': t_constants.MOCK_CIDR}) subnet = self.driver.get_subnet(t_constants.MOCK_SUBNET_ID) self.assertIsInstance(subnet, network_models.Subnet) self.assertEqual(t_constants.MOCK_SUBNET_ID, subnet.id) @@ -249,11 +245,11 @@ class TestBaseNeutronNetworkDriver(base.TestCase): @mock.patch("octavia.common.clients.NeutronAuth.get_user_neutron_client") def test_get_user_subnet(self, neutron_client_mock): - show_subnet = neutron_client_mock.return_value.show_subnet - show_subnet.return_value = {'subnet': { + show_subnet = neutron_client_mock.return_value.get_subnet + show_subnet.return_value = Subnet(**{ 'id': t_constants.MOCK_SUBNET_ID, 'gateway_ip': t_constants.MOCK_IP_ADDRESS, - 'cidr': t_constants.MOCK_CIDR}} + 'cidr': t_constants.MOCK_CIDR}) subnet = self.driver.get_subnet(t_constants.MOCK_SUBNET_ID, context=mock.ANY) @@ -267,15 +263,15 @@ class TestBaseNeutronNetworkDriver(base.TestCase): config = self.useFixture(oslo_fixture.Config(cfg.CONF)) config.config(group="networking", allow_invisible_resource_usage=True) - show_port = self.driver.neutron_client.show_port - show_port.return_value = {'port': { + show_port = self.driver.network_proxy.get_port + show_port.return_value = Port(**{ 'id': t_constants.MOCK_PORT_ID, 'mac_address': t_constants.MOCK_MAC_ADDR, 'network_id': t_constants.MOCK_NETWORK_ID, 'fixed_ips': [{ 'subnet_id': t_constants.MOCK_SUBNET_ID, 'ip_address': t_constants.MOCK_IP_ADDRESS - }]}} + }]}) port = self.driver.get_port(t_constants.MOCK_PORT_ID) self.assertIsInstance(port, network_models.Port) self.assertEqual(t_constants.MOCK_PORT_ID, port.id) @@ -290,15 +286,15 @@ class TestBaseNeutronNetworkDriver(base.TestCase): @mock.patch("octavia.common.clients.NeutronAuth.get_user_neutron_client") def test_get_user_port(self, neutron_client_mock): - show_port = neutron_client_mock.return_value.show_port - show_port.return_value = {'port': { + show_port = neutron_client_mock.return_value.get_port + show_port.return_value = Port(**{ 'id': t_constants.MOCK_PORT_ID, 'mac_address': t_constants.MOCK_MAC_ADDR, 'network_id': t_constants.MOCK_NETWORK_ID, 'fixed_ips': [{ 'subnet_id': t_constants.MOCK_SUBNET_ID, 'ip_address': t_constants.MOCK_IP_ADDRESS - }]}} + }]}) port = self.driver.get_port(t_constants.MOCK_PORT_ID, context=mock.ANY) @@ -314,11 +310,11 @@ class TestBaseNeutronNetworkDriver(base.TestCase): port.fixed_ips[0].ip_address) def test_get_network_by_name(self): - list_network = self.driver.neutron_client.list_networks - list_network.return_value = {'networks': [{'network': { + list_network = self.driver.network_proxy.networks + list_network.return_value = iter([Network(**{ 'id': t_constants.MOCK_NETWORK_ID, 'name': t_constants.MOCK_NETWORK_NAME, - 'subnets': [t_constants.MOCK_SUBNET_ID]}}]} + 'subnets': [t_constants.MOCK_SUBNET_ID]})]) network = self.driver.get_network_by_name( t_constants.MOCK_NETWORK_NAME) self.assertIsInstance(network, network_models.Network) @@ -327,7 +323,7 @@ class TestBaseNeutronNetworkDriver(base.TestCase): self.assertEqual(1, len(network.subnets)) self.assertEqual(t_constants.MOCK_SUBNET_ID, network.subnets[0]) # Negative - list_network.side_effect = neutron_client_exceptions.NotFound + list_network.side_effect = os_exceptions.ResourceNotFound self.assertRaises(network_base.NetworkNotFound, self.driver.get_network_by_name, t_constants.MOCK_NETWORK_NAME) @@ -337,12 +333,12 @@ class TestBaseNeutronNetworkDriver(base.TestCase): t_constants.MOCK_NETWORK_NAME) def test_get_subnet_by_name(self): - list_subnet = self.driver.neutron_client.list_subnets - list_subnet.return_value = {'subnets': [{'subnet': { + list_subnet = self.driver.network_proxy.subnets + list_subnet.return_value = iter([Subnet(**{ 'id': t_constants.MOCK_SUBNET_ID, 'name': t_constants.MOCK_SUBNET_NAME, 'gateway_ip': t_constants.MOCK_IP_ADDRESS, - 'cidr': t_constants.MOCK_CIDR}}]} + 'cidr': t_constants.MOCK_CIDR})]) subnet = self.driver.get_subnet_by_name(t_constants.MOCK_SUBNET_NAME) self.assertIsInstance(subnet, network_models.Subnet) self.assertEqual(t_constants.MOCK_SUBNET_ID, subnet.id) @@ -350,7 +346,7 @@ class TestBaseNeutronNetworkDriver(base.TestCase): self.assertEqual(t_constants.MOCK_IP_ADDRESS, subnet.gateway_ip) self.assertEqual(t_constants.MOCK_CIDR, subnet.cidr) # Negative - list_subnet.side_effect = neutron_client_exceptions.NotFound + list_subnet.side_effect = os_exceptions.ResourceNotFound self.assertRaises(network_base.SubnetNotFound, self.driver.get_subnet_by_name, t_constants.MOCK_SUBNET_NAME) @@ -360,8 +356,8 @@ class TestBaseNeutronNetworkDriver(base.TestCase): t_constants.MOCK_SUBNET_NAME) def test_get_port_by_name(self): - list_port = self.driver.neutron_client.list_ports - list_port.return_value = {'ports': [{'port': { + list_port = self.driver.network_proxy.ports + list_port.return_value = iter([Port(**{ 'id': t_constants.MOCK_PORT_ID, 'name': t_constants.MOCK_PORT_NAME, 'mac_address': t_constants.MOCK_MAC_ADDR, @@ -369,7 +365,7 @@ class TestBaseNeutronNetworkDriver(base.TestCase): 'fixed_ips': [{ 'subnet_id': t_constants.MOCK_SUBNET_ID, 'ip_address': t_constants.MOCK_IP_ADDRESS - }]}}]} + }]})]) port = self.driver.get_port_by_name(t_constants.MOCK_PORT_NAME) self.assertIsInstance(port, network_models.Port) self.assertEqual(t_constants.MOCK_PORT_ID, port.id) @@ -383,7 +379,7 @@ class TestBaseNeutronNetworkDriver(base.TestCase): self.assertEqual(t_constants.MOCK_IP_ADDRESS, port.fixed_ips[0].ip_address) # Negative - list_port.side_effect = neutron_client_exceptions.NotFound + list_port.side_effect = os_exceptions.ResourceNotFound self.assertRaises(network_base.PortNotFound, self.driver.get_port_by_name, t_constants.MOCK_PORT_NAME) @@ -393,8 +389,8 @@ class TestBaseNeutronNetworkDriver(base.TestCase): t_constants.MOCK_PORT_NAME) def test_get_port_by_net_id_device_id(self): - list_port = self.driver.neutron_client.list_ports - list_port.return_value = {'ports': [{'port': { + list_port = self.driver.network_proxy.ports + list_port.return_value = iter([Port(**{ 'id': t_constants.MOCK_PORT_ID, 'name': t_constants.MOCK_PORT_NAME, 'mac_address': t_constants.MOCK_MAC_ADDR, @@ -403,7 +399,7 @@ class TestBaseNeutronNetworkDriver(base.TestCase): 'fixed_ips': [{ 'subnet_id': t_constants.MOCK_SUBNET_ID, 'ip_address': t_constants.MOCK_IP_ADDRESS - }]}}]} + }]})]) port = self.driver.get_port_by_net_id_device_id( t_constants.MOCK_NETWORK_ID, t_constants.MOCK_DEVICE_ID) self.assertIsInstance(port, network_models.Port) @@ -419,7 +415,7 @@ class TestBaseNeutronNetworkDriver(base.TestCase): self.assertEqual(t_constants.MOCK_IP_ADDRESS, port.fixed_ips[0].ip_address) # Negative - list_port.side_effect = neutron_client_exceptions.NotFound + list_port.side_effect = os_exceptions.ResourceNotFound self.assertRaises(network_base.PortNotFound, self.driver.get_port_by_net_id_device_id, t_constants.MOCK_PORT_NAME, @@ -436,12 +432,10 @@ class TestBaseNeutronNetworkDriver(base.TestCase): The expected result is: only the first port is returned. """ - list_port = self.driver.neutron_client.list_ports - list_port.return_value = { - 'ports': [t_constants.MOCK_NEUTRON_PORT, - t_constants.MOCK_NEUTRON_PORT2, - ], - } + list_port = self.driver.network_proxy.ports + list_port.return_value = iter([t_constants.MOCK_NEUTRON_PORT, + t_constants.MOCK_NEUTRON_PORT2, + ]) port = self.driver.get_port_by_net_id_device_id( t_constants.MOCK_NETWORK_ID, t_constants.MOCK_DEVICE_ID) @@ -458,7 +452,7 @@ class TestBaseNeutronNetworkDriver(base.TestCase): self.assertEqual(t_constants.MOCK_IP_ADDRESS, port.fixed_ips[0].ip_address) # Negative - list_port.side_effect = neutron_client_exceptions.NotFound + list_port.side_effect = os_exceptions.ResourceNotFound self.assertRaises(network_base.PortNotFound, self.driver.get_port_by_net_id_device_id, t_constants.MOCK_PORT_NAME, @@ -471,12 +465,10 @@ class TestBaseNeutronNetworkDriver(base.TestCase): def test_get_multiple_ports_by_net_id_device_id(self): """Test _get_resources_by_filters, when result is not unique""" - list_port = self.driver.neutron_client.list_ports - list_port.return_value = { - 'ports': [t_constants.MOCK_NEUTRON_PORT, - t_constants.MOCK_NEUTRON_PORT2, - ], - } + list_port = self.driver.network_proxy.ports + list_port.return_value = iter([t_constants.MOCK_NEUTRON_PORT, + t_constants.MOCK_NEUTRON_PORT2, + ]) ports = self.driver._get_resources_by_filters( 'port', @@ -495,10 +487,8 @@ class TestBaseNeutronNetworkDriver(base.TestCase): def test_get_unique_port_by_name(self): """Test _get_resources_by_filters, when result is unique""" - list_port = self.driver.neutron_client.list_ports - list_port.return_value = { - 'ports': [t_constants.MOCK_NEUTRON_PORT] - } + list_port = self.driver.network_proxy.ports + list_port.return_value = iter([t_constants.MOCK_NEUTRON_PORT]) port = self.driver._get_resources_by_filters( 'port', unique_item=True, name=t_constants.MOCK_PORT_NAME) @@ -508,44 +498,54 @@ class TestBaseNeutronNetworkDriver(base.TestCase): def test_get_non_existing_port_by_name(self): """Test _get_resources_by_filters, when result is empty""" - list_port = self.driver.neutron_client.list_ports - list_port.return_value = {'ports': []} + list_port = self.driver.network_proxy.ports + list_port.return_value = iter([]) self.assertRaises(network_base.PortNotFound, self.driver._get_resources_by_filters, 'port', unique_item=True, name='port1') def test_get_qos_policy(self): - get_qos = self.driver.neutron_client.show_qos_policy - get_qos.return_value = {'policy': { - 'id': t_constants.MOCK_NEUTRON_QOS_POLICY_ID}} + get_qos = self.driver.network_proxy.get_qos_policy + get_qos.return_value = QoSPolicy(**{ + 'id': t_constants.MOCK_NEUTRON_QOS_POLICY_ID}) qos = self.driver.get_qos_policy( t_constants.MOCK_NEUTRON_QOS_POLICY_ID) self.assertIsInstance(qos, network_models.QosPolicy) self.assertEqual(t_constants.MOCK_NEUTRON_QOS_POLICY_ID, qos.id) - get_qos.side_effect = neutron_client_exceptions.NotFound + get_qos.side_effect = os_exceptions.ResourceNotFound self.assertRaises(network_base.QosPolicyNotFound, self.driver.get_qos_policy, t_constants.MOCK_NEUTRON_QOS_POLICY_ID) - get_qos.side_effect = neutron_client_exceptions.ServiceUnavailable + get_qos.side_effect = os_exceptions.SDKException self.assertRaises(network_base.NetworkException, self.driver.get_qos_policy, t_constants.MOCK_NEUTRON_QOS_POLICY_ID) + def test_apply_qos_on_port(self): + update_port = self.driver.network_proxy.update_port + self.driver.apply_qos_on_port( + t_constants.MOCK_NEUTRON_QOS_POLICY_ID, + t_constants.MOCK_PORT_ID + ) + update_port.assert_called_once_with( + t_constants.MOCK_PORT_ID, + qos_policy_id=t_constants.MOCK_NEUTRON_QOS_POLICY_ID) + def test_apply_or_undo_qos_on_port(self): # The apply and undo qos function use the same "update_port" with # neutron client. So testing them in one Uts. - update_port = self.driver.neutron_client.update_port - update_port.side_effect = neutron_client_exceptions.PortNotFoundClient + update_port = self.driver.network_proxy.update_port + update_port.side_effect = os_exceptions.ResourceNotFound self.assertRaises(network_base.PortNotFound, self.driver.apply_qos_on_port, t_constants.MOCK_PORT_ID, t_constants.MOCK_NEUTRON_QOS_POLICY_ID) - update_port.side_effect = neutron_client_exceptions.ServiceUnavailable + update_port.side_effect = os_exceptions.SDKException self.assertRaises(network_base.NetworkException, self.driver.apply_qos_on_port, t_constants.MOCK_PORT_ID, @@ -553,12 +553,13 @@ class TestBaseNeutronNetworkDriver(base.TestCase): def test_get_network_ip_availability(self): show_network_ip_availability = ( - self.driver.neutron_client.show_network_ip_availability) + self.driver.network_proxy.get_network_ip_availability) show_network_ip_availability.return_value = ( - {'network_ip_availability': { - 'network_id': t_constants.MOCK_NETWORK_ID, - 'subnet_ip_availability': t_constants.MOCK_SUBNET_IP_AVAILABILITY - }}) + NetworkIPAvailability(**{ + 'network_id': t_constants.MOCK_NETWORK_ID, + 'subnet_ip_availability': + t_constants.MOCK_SUBNET_IP_AVAILABILITY + })) ip_avail = self.driver.get_network_ip_availability( network_models.Network(t_constants.MOCK_NETWORK_ID)) self.assertIsInstance(ip_avail, network_models.Network_IP_Availability) @@ -567,8 +568,8 @@ class TestBaseNeutronNetworkDriver(base.TestCase): ip_avail.subnet_ip_availability) def test_plug_fixed_ip(self): - show_port = self.driver.neutron_client.show_port - show_port.return_value = { + show_port = self.driver.network_proxy.get_port + show_port.return_value = Port(**{ 'id': t_constants.MOCK_PORT_ID, 'fixed_ips': [ { @@ -576,34 +577,31 @@ class TestBaseNeutronNetworkDriver(base.TestCase): 'ip_address': t_constants.MOCK_IP_ADDRESS, 'subnet': None }] - } + }) self.driver.plug_fixed_ip(t_constants.MOCK_PORT_ID, t_constants.MOCK_SUBNET_ID2, t_constants.MOCK_IP_ADDRESS2) expected_body = { - 'port': { - 'fixed_ips': [ - { - 'subnet_id': t_constants.MOCK_SUBNET_ID, - 'ip_address': t_constants.MOCK_IP_ADDRESS, - 'subnet': None - }, { - 'subnet_id': t_constants.MOCK_SUBNET_ID2, - 'ip_address': t_constants.MOCK_IP_ADDRESS2 - } - ] - } - + 'fixed_ips': [ + { + 'subnet_id': t_constants.MOCK_SUBNET_ID, + 'ip_address': t_constants.MOCK_IP_ADDRESS, + 'subnet': None + }, { + 'subnet_id': t_constants.MOCK_SUBNET_ID2, + 'ip_address': t_constants.MOCK_IP_ADDRESS2 + } + ] } - self.driver.neutron_client.update_port.assert_called_once_with( + self.driver.network_proxy.update_port.assert_called_once_with( t_constants.MOCK_PORT_ID, - expected_body) + **expected_body) def test_plug_fixed_ip_no_ip_address(self): - show_port = self.driver.neutron_client.show_port - show_port.return_value = { + show_port = self.driver.network_proxy.get_port + show_port.return_value = Port(**{ 'id': t_constants.MOCK_PORT_ID, 'fixed_ips': [ { @@ -611,31 +609,27 @@ class TestBaseNeutronNetworkDriver(base.TestCase): 'ip_address': t_constants.MOCK_IP_ADDRESS, 'subnet': None }] - } + }) self.driver.plug_fixed_ip(t_constants.MOCK_PORT_ID, t_constants.MOCK_SUBNET_ID2) expected_body = { - 'port': { - 'fixed_ips': [ - { - 'subnet_id': t_constants.MOCK_SUBNET_ID, - 'ip_address': t_constants.MOCK_IP_ADDRESS, - 'subnet': None - }, { - 'subnet_id': t_constants.MOCK_SUBNET_ID2, - } - ] - } - + 'fixed_ips': [ + { + 'subnet_id': t_constants.MOCK_SUBNET_ID, + 'ip_address': t_constants.MOCK_IP_ADDRESS, + 'subnet': None + }, { + 'subnet_id': t_constants.MOCK_SUBNET_ID2, + } + ] } - self.driver.neutron_client.update_port.assert_called_once_with( - t_constants.MOCK_PORT_ID, - expected_body) + self.driver.network_proxy.update_port.assert_called_once_with( + t_constants.MOCK_PORT_ID, **expected_body) def test_plug_fixed_ip_exception(self): - show_port = self.driver.neutron_client.show_port + show_port = self.driver.network_proxy.get_port show_port.return_value = { 'id': t_constants.MOCK_PORT_ID, 'fixed_ips': [ @@ -646,7 +640,7 @@ class TestBaseNeutronNetworkDriver(base.TestCase): }] } - self.driver.neutron_client.update_port.side_effect = Exception + self.driver.network_proxy.update_port.side_effect = Exception self.assertRaises(network_base.NetworkException, self.driver.plug_fixed_ip, @@ -654,8 +648,8 @@ class TestBaseNeutronNetworkDriver(base.TestCase): t_constants.MOCK_SUBNET_ID2) def test_unplug_fixed_ip(self): - show_port = self.driver.neutron_client.show_port - show_port.return_value = { + show_port = self.driver.network_proxy.get_port + show_port.return_value = Port(**{ 'id': t_constants.MOCK_PORT_ID, 'fixed_ips': [ { @@ -667,40 +661,33 @@ class TestBaseNeutronNetworkDriver(base.TestCase): 'ip_address': t_constants.MOCK_IP_ADDRESS2, 'subnet': None }] - } + }) self.driver.unplug_fixed_ip(t_constants.MOCK_PORT_ID, t_constants.MOCK_SUBNET_ID) expected_body = { - 'port': { - 'fixed_ips': [ - { - 'subnet_id': t_constants.MOCK_SUBNET_ID2, - 'ip_address': t_constants.MOCK_IP_ADDRESS2, - 'subnet': None - } - ] - } - - } - self.driver.neutron_client.update_port.assert_called_once_with( - t_constants.MOCK_PORT_ID, - expected_body) - - def test_unplug_fixed_ip_exception(self): - show_port = self.driver.neutron_client.show_port - show_port.return_value = { - 'id': t_constants.MOCK_PORT_ID, 'fixed_ips': [ { - 'subnet_id': t_constants.MOCK_SUBNET_ID, - 'ip_address': t_constants.MOCK_IP_ADDRESS, + 'subnet_id': t_constants.MOCK_SUBNET_ID2, + 'ip_address': t_constants.MOCK_IP_ADDRESS2, 'subnet': None - }] + } + ] } + self.driver.network_proxy.update_port.assert_called_once_with( + t_constants.MOCK_PORT_ID, + **expected_body) - self.driver.neutron_client.update_port.side_effect = Exception + def test_unplug_fixed_ip_exception(self): + show_port = self.driver.network_proxy.get_port + show_port.return_value = Port( + device_id=t_constants.MOCK_PORT_ID, + fixed_ips=[(t_constants.MOCK_IP_ADDRESS, + t_constants.MOCK_SUBNET_ID)], + ) + + self.driver.network_proxy.update_port.side_effect = Exception self.assertRaises(network_base.NetworkException, self.driver.unplug_fixed_ip, diff --git a/octavia/tests/unit/network/drivers/neutron/test_utils.py b/octavia/tests/unit/network/drivers/neutron/test_utils.py index dad6d21953..4a80ce1a0c 100644 --- a/octavia/tests/unit/network/drivers/neutron/test_utils.py +++ b/octavia/tests/unit/network/drivers/neutron/test_utils.py @@ -37,8 +37,8 @@ class TestNeutronUtils(base.TestCase): if hay[key] is not None}) self.assertIn(newneedle, newhaystack) - def test_convert_subnet_dict_to_model(self): - model_obj = utils.convert_subnet_dict_to_model( + def test_convert_subnet_to_model(self): + model_obj = utils.convert_subnet_to_model( t_constants.MOCK_SUBNET) assert_dict = dict( id=t_constants.MOCK_SUBNET_ID, @@ -52,8 +52,8 @@ class TestNeutronUtils(base.TestCase): ) self._compare_ignore_value_none(model_obj.to_dict(), assert_dict) - def test_convert_port_dict_to_model(self): - model_obj = utils.convert_port_dict_to_model( + def test_convert_port_to_model(self): + model_obj = utils.convert_port_to_model( t_constants.MOCK_NEUTRON_PORT) assert_dict = dict( id=t_constants.MOCK_PORT_ID, @@ -69,12 +69,12 @@ class TestNeutronUtils(base.TestCase): security_group_ids=[], ) self._compare_ignore_value_none(model_obj.to_dict(), assert_dict) - fixed_ips = t_constants.MOCK_NEUTRON_PORT['port']['fixed_ips'] + fixed_ips = t_constants.MOCK_NEUTRON_PORT['fixed_ips'] for ip in model_obj.fixed_ips: self._in_ignore_value_none(ip.to_dict(), fixed_ips) - def test_convert_network_dict_to_model(self): - model_obj = utils.convert_network_dict_to_model( + def test_convert_network_to_model(self): + model_obj = utils.convert_network_to_model( t_constants.MOCK_NETWORK) assert_dict = dict( id=t_constants.MOCK_NETWORK_ID, @@ -86,11 +86,12 @@ class TestNeutronUtils(base.TestCase): provider_network_type=t_constants.MOCK_NETWORK_TYPE, provider_physical_network=t_constants.MOCK_NETWORK_NAME, provider_segmentation_id=t_constants.MOCK_SEGMENTATION_ID, - router_external=t_constants.MOCK_ROUTER_EXTERNAL + router_external=t_constants.MOCK_ROUTER_EXTERNAL, + port_security_enabled=False, ) model_dict = model_obj.to_dict() model_dict['subnets'] = model_obj.subnets - self._compare_ignore_value_none(model_dict, assert_dict) + self._compare_ignore_value_none(assert_dict, model_dict) def test_convert_fixed_ip_dict_to_model(self): model_obj = utils.convert_fixed_ip_dict_to_model( @@ -99,31 +100,14 @@ class TestNeutronUtils(base.TestCase): subnet_id=t_constants.MOCK_SUBNET_ID, ip_address=t_constants.MOCK_IP_ADDRESS ) - self._compare_ignore_value_none(model_obj.to_dict(), assert_dict) + self._compare_ignore_value_none(assert_dict, model_obj.to_dict()) - def test_convert_floatingip_dict_to_model(self): - model_obj = utils.convert_floatingip_dict_to_model( - t_constants.MOCK_FLOATING_IP) - assert_dict = dict( - id=t_constants.MOCK_FLOATING_IP_ID, - description=t_constants.MOCK_FLOATING_IP_DESC, - project_id=t_constants.MOCK_PROJECT_ID, - status=t_constants.MOCK_STATUS, - router_id=t_constants.MOCK_ROUTER_ID, - port_id=t_constants.MOCK_PORT_ID, - floating_network_id=t_constants.MOCK_NETWORK_ID, - network_id=t_constants.MOCK_NETWORK_ID, - floating_ip_address=t_constants.MOCK_IP_ADDRESS, - fixed_ip_address=t_constants.MOCK_IP_ADDRESS2, - fixed_port_id=t_constants.MOCK_PORT_ID2 - ) - self._compare_ignore_value_none(model_obj.to_dict(), assert_dict) - - def test_convert_network_ip_availability_dict_to_model(self): - model_obj = utils.convert_network_ip_availability_dict_to_model( + def test_convert_network_ip_availability_to_model(self): + model_obj = utils.convert_network_ip_availability_to_model( t_constants.MOCK_NETWORK_IP_AVAILABILITY) assert_dict = dict( network_id=t_constants.MOCK_NETWORK_ID, + project_id=t_constants.MOCK_PROJECT_ID, tenant_id=t_constants.MOCK_PROJECT_ID, network_name=t_constants.MOCK_NETWORK_NAME, total_ips=t_constants.MOCK_NETWORK_TOTAL_IPS, diff --git a/releasenotes/notes/removed-neutronclient-43f62f25210c3392.yaml b/releasenotes/notes/removed-neutronclient-43f62f25210c3392.yaml new file mode 100644 index 0000000000..ea3096390c --- /dev/null +++ b/releasenotes/notes/removed-neutronclient-43f62f25210c3392.yaml @@ -0,0 +1,23 @@ +--- +upgrade: + - | + Authentication settings for Neutron should be added + directly to the [neutron] section of the configuration now. The exact + settings depend on the `auth_type` used. Refer to + https://docs.openstack.org/keystoneauth/latest/plugin-options.html + for a list of possible options. +deprecations: + - | + In a future release Octavia will no longer take the authentication + settings for Neutron from the [service_auth] as a fallback. It will + require them to be in the [neutron] section. The *endpoint* option is now + deprecated and replaced by *endpoint_override*. Similarly, the + new name of the *endpoint_type* option is now *valid_interfaces* and + the new name of the *ca_certificates_file* option is now *cafile*. + Note that [service_auth] + settings will still be used for other services like Nova and Glance. +other: + - | + Replaced code that uses the deprecated python-neutronclient library with + code that uses openstacksdk and removed python-neutronclient as a + dependency. diff --git a/requirements.txt b/requirements.txt index 872c355b6f..a89ef4ccf0 100644 --- a/requirements.txt +++ b/requirements.txt @@ -16,9 +16,9 @@ requests>=2.23.0 # Apache-2.0 rfc3986>=1.2.0 # Apache-2.0 keystoneauth1>=3.4.0 # Apache-2.0 keystonemiddleware>=9.5.0 # Apache-2.0 -python-neutronclient>=6.7.0 # Apache-2.0 WebOb>=1.8.2 # MIT stevedore>=1.20.0 # Apache-2.0 +openstacksdk>=0.103.0 # Apache-2.0 oslo.config>=6.8.0 # Apache-2.0 oslo.context>=2.22.0 # Apache-2.0 oslo.db[mysql]>=8.4.0 # Apache-2.0 diff --git a/specs/template.rst b/specs/template.rst index bb27668c13..64a26211c3 100644 --- a/specs/template.rst +++ b/specs/template.rst @@ -330,7 +330,7 @@ Aside from the API, are there other ways a user will interact with this feature? Keep in mind that 'user' in this context could mean either tenant or operator. -* Does this change have an impact on python-neutronclient? What does the user +* Does this change have an impact on openstacksdk? What does the user interface there look like? Performance Impact