Merge pull request #284 from Cerberus98/rm10638

Adds connection switching to the Nvp driver
This commit is contained in:
Meow Purrpurr 2014-11-21 11:00:10 -06:00
commit 32790d450c
4 changed files with 307 additions and 245 deletions

View File

@ -17,6 +17,8 @@
NVP client driver for Quark NVP client driver for Quark
""" """
import contextlib
import aiclib import aiclib
from neutron.extensions import securitygroup as sg_ext from neutron.extensions import securitygroup as sg_ext
from neutron.openstack.common import log as logging from neutron.openstack.common import log as logging
@ -89,6 +91,7 @@ class NVPDriver(base.BaseDriver):
# NOTE(mdietz): What does default_tz actually mean? # NOTE(mdietz): What does default_tz actually mean?
# We don't have one default. # We don't have one default.
# NOTE(jkoelker): Transport Zone # NOTE(jkoelker): Transport Zone
# NOTE(mdietz): :-/ tz isn't the issue. default is
default_tz = CONF.NVP.default_tz default_tz = CONF.NVP.default_tz
LOG.info("Loading NVP settings " + str(default_tz)) LOG.info("Loading NVP settings " + str(default_tz))
connections = CONF.NVP.controller_connection connections = CONF.NVP.controller_connection
@ -99,6 +102,7 @@ class NVPDriver(base.BaseDriver):
'max_rules_per_group': CONF.NVP.max_rules_per_group, 'max_rules_per_group': CONF.NVP.max_rules_per_group,
'max_rules_per_port': CONF.NVP.max_rules_per_port}) 'max_rules_per_port': CONF.NVP.max_rules_per_port})
LOG.info("Loading NVP settings " + str(connections)) LOG.info("Loading NVP settings " + str(connections))
for conn in connections: for conn in connections:
(ip, port, user, pw, req_timeout, (ip, port, user, pw, req_timeout,
http_timeout, retries, redirects) = conn.split(":") http_timeout, retries, redirects) = conn.split(":")
@ -114,7 +118,11 @@ class NVPDriver(base.BaseDriver):
default_tz=default_tz, default_tz=default_tz,
backoff=backoff)) backoff=backoff))
def get_connection(self): def _connection(self):
if len(self.nvp_connections) == 0:
raise exceptions.NoBackendConnectionsDefined(
msg="No NVP connections defined cannot continue")
conn = self.nvp_connections[self.conn_index] conn = self.nvp_connections[self.conn_index]
if "connection" not in conn: if "connection" not in conn:
scheme = conn["port"] == "443" and "https" or "http" scheme = conn["port"] == "443" and "https" or "http"
@ -132,6 +140,22 @@ class NVPDriver(base.BaseDriver):
backoff=backoff) backoff=backoff)
return conn["connection"] return conn["connection"]
def _next_connection(self):
# TODO(anyone): Do we want to drop and create new connections at some
# point? What about recycling them after a certain
# number of usages or time, proactively?
conn_len = len(self.nvp_connections)
if conn_len:
self.conn_index = (self.conn_index + 1) % conn_len
@contextlib.contextmanager
def get_connection(self):
try:
yield self._connection()
except Exception:
self._next_connection()
raise
def create_network(self, context, network_name, tags=None, def create_network(self, context, network_name, tags=None,
network_id=None, **kwargs): network_id=None, **kwargs):
return self._lswitch_create(context, network_name, tags, return self._lswitch_create(context, network_name, tags,
@ -187,67 +211,67 @@ class NVPDriver(base.BaseDriver):
security_groups = security_groups or [] security_groups = security_groups or []
tenant_id = context.tenant_id tenant_id = context.tenant_id
lswitch = self._create_or_choose_lswitch(context, network_id) lswitch = self._create_or_choose_lswitch(context, network_id)
connection = self.get_connection() with self.get_connection() as connection:
port = connection.lswitch_port(lswitch) port = connection.lswitch_port(lswitch)
port.admin_status_enabled(status) port.admin_status_enabled(status)
nvp_group_ids = self._get_security_groups_for_port(context, nvp_group_ids = self._get_security_groups_for_port(context,
security_groups) security_groups)
port.security_profiles(nvp_group_ids) port.security_profiles(nvp_group_ids)
tags = [dict(tag=network_id, scope="neutron_net_id"), tags = [dict(tag=network_id, scope="neutron_net_id"),
dict(tag=port_id, scope="neutron_port_id"), dict(tag=port_id, scope="neutron_port_id"),
dict(tag=tenant_id, scope="os_tid"), dict(tag=tenant_id, scope="os_tid"),
dict(tag=device_id, scope="vm_id")] dict(tag=device_id, scope="vm_id")]
LOG.debug("Creating port on switch %s" % lswitch) LOG.debug("Creating port on switch %s" % lswitch)
port.tags(tags) port.tags(tags)
res = port.create() res = port.create()
try: try:
"""Catching odd NVP returns here will make it safe to assume that """Catching odd NVP returns here will make it safe to assume that
NVP returned something correct.""" NVP returned something correct."""
res["lswitch"] = lswitch res["lswitch"] = lswitch
except TypeError: except TypeError:
LOG.exception("Unexpected return from NVP: %s" % res) LOG.exception("Unexpected return from NVP: %s" % res)
raise raise
port = connection.lswitch_port(lswitch) port = connection.lswitch_port(lswitch)
port.uuid = res["uuid"] port.uuid = res["uuid"]
port.attachment_vif(port_id) port.attachment_vif(port_id)
return res return res
def update_port(self, context, port_id, status=True, def update_port(self, context, port_id, status=True,
security_groups=None, **kwargs): security_groups=None, **kwargs):
security_groups = security_groups or [] security_groups = security_groups or []
connection = self.get_connection() with self.get_connection() as connection:
lswitch_id = self._lswitch_from_port(context, port_id) lswitch_id = self._lswitch_from_port(context, port_id)
port = connection.lswitch_port(lswitch_id, port_id) port = connection.lswitch_port(lswitch_id, port_id)
nvp_group_ids = self._get_security_groups_for_port(context, nvp_group_ids = self._get_security_groups_for_port(context,
security_groups) security_groups)
if nvp_group_ids: if nvp_group_ids:
port.security_profiles(nvp_group_ids) port.security_profiles(nvp_group_ids)
port.admin_status_enabled(status) port.admin_status_enabled(status)
return port.update() return port.update()
def delete_port(self, context, port_id, **kwargs): def delete_port(self, context, port_id, **kwargs):
connection = self.get_connection() with self.get_connection() as connection:
lswitch_uuid = kwargs.get('lswitch_uuid', None) lswitch_uuid = kwargs.get('lswitch_uuid', None)
try: try:
if not lswitch_uuid: if not lswitch_uuid:
lswitch_uuid = self._lswitch_from_port(context, port_id) lswitch_uuid = self._lswitch_from_port(context, port_id)
LOG.debug("Deleting port %s from lswitch %s" LOG.debug("Deleting port %s from lswitch %s"
% (port_id, lswitch_uuid)) % (port_id, lswitch_uuid))
connection.lswitch_port(lswitch_uuid, port_id).delete() connection.lswitch_port(lswitch_uuid, port_id).delete()
except aiclib.core.AICException as ae: except aiclib.core.AICException as ae:
if ae.code == 404: if ae.code == 404:
LOG.info("LSwitchPort/Port %s not found in NVP." LOG.info("LSwitchPort/Port %s not found in NVP."
" Ignoring explicitly. Code: %s, Message: %s" " Ignoring explicitly. Code: %s, Message: %s"
% (port_id, ae.code, ae.message)) % (port_id, ae.code, ae.message))
else: else:
LOG.info("AICException deleting LSwitchPort/Port %s in NVP." LOG.info("AICException deleting LSwitchPort/Port %s in "
" Ignoring explicitly. Code: %s, Message: %s" "NVP. Ignoring explicitly. Code: %s, Message: %s"
% (port_id, ae.code, ae.message)) % (port_id, ae.code, ae.message))
except Exception as e: except Exception as e:
LOG.info("Failed to delete LSwitchPort/Port %s in NVP." LOG.info("Failed to delete LSwitchPort/Port %s in NVP."
" Ignoring explicitly. Message: %s" " Ignoring explicitly. Message: %s"
% (port_id, e.args[0])) % (port_id, e.args[0]))
def _collect_lport_info(self, lport, get_status): def _collect_lport_info(self, lport, get_status):
info = { info = {
@ -291,23 +315,23 @@ class NVPDriver(base.BaseDriver):
return info return info
def diag_port(self, context, port_id, get_status=False, **kwargs): def diag_port(self, context, port_id, get_status=False, **kwargs):
connection = self.get_connection() with self.get_connection() as connection:
lswitch_uuid = self._lswitch_from_port(context, port_id) lswitch_uuid = self._lswitch_from_port(context, port_id)
lswitch_port = connection.lswitch_port(lswitch_uuid, port_id) lswitch_port = connection.lswitch_port(lswitch_uuid, port_id)
query = lswitch_port.query() query = lswitch_port.query()
query.relations("LogicalPortAttachment") query.relations("LogicalPortAttachment")
results = query.results() results = query.results()
if results['result_count'] == 0: if results['result_count'] == 0:
return {'lport': "Logical port not found."} return {'lport': "Logical port not found."}
config = results['results'][0] config = results['results'][0]
relations = config.pop('_relations') relations = config.pop('_relations')
config['attachment'] = relations['LogicalPortAttachment']['type'] config['attachment'] = relations['LogicalPortAttachment']['type']
if get_status: if get_status:
config['status'] = lswitch_port.status() config['status'] = lswitch_port.status()
config['statistics'] = lswitch_port.statistics() config['statistics'] = lswitch_port.statistics()
return {'lport': self._collect_lport_info(config, get_status)} return {'lport': self._collect_lport_info(config, get_status)}
def _get_network_details(self, context, network_id, switches): def _get_network_details(self, context, network_id, switches):
name, phys_net, phys_type, segment_id = None, None, None, None name, phys_net, phys_type, segment_id = None, None, None, None
@ -326,55 +350,55 @@ class NVPDriver(base.BaseDriver):
def create_security_group(self, context, group_name, **group): def create_security_group(self, context, group_name, **group):
tenant_id = context.tenant_id tenant_id = context.tenant_id
connection = self.get_connection() with self.get_connection() as connection:
group_id = group.get('group_id') group_id = group.get('group_id')
profile = connection.securityprofile() profile = connection.securityprofile()
if group_name: if group_name:
profile.display_name(group_name) profile.display_name(group_name)
ingress_rules = group.get('port_ingress_rules', []) ingress_rules = group.get('port_ingress_rules', [])
egress_rules = group.get('port_egress_rules', []) egress_rules = group.get('port_egress_rules', [])
if (len(ingress_rules) + len(egress_rules) > if (len(ingress_rules) + len(egress_rules) >
self.limits['max_rules_per_group']): self.limits['max_rules_per_group']):
raise exceptions.DriverLimitReached(limit="rules per group") raise exceptions.DriverLimitReached(limit="rules per group")
if egress_rules: if egress_rules:
profile.port_egress_rules(egress_rules) profile.port_egress_rules(egress_rules)
if ingress_rules: if ingress_rules:
profile.port_ingress_rules(ingress_rules) profile.port_ingress_rules(ingress_rules)
tags = [dict(tag=group_id, scope="neutron_group_id"), tags = [dict(tag=group_id, scope="neutron_group_id"),
dict(tag=tenant_id, scope="os_tid")] dict(tag=tenant_id, scope="os_tid")]
LOG.debug("Creating security profile %s" % group_name) LOG.debug("Creating security profile %s" % group_name)
profile.tags(tags) profile.tags(tags)
return profile.create() return profile.create()
def delete_security_group(self, context, group_id, **kwargs): def delete_security_group(self, context, group_id, **kwargs):
guuid = self._get_security_group_id(context, group_id) guuid = self._get_security_group_id(context, group_id)
connection = self.get_connection() with self.get_connection() as connection:
LOG.debug("Deleting security profile %s" % group_id) LOG.debug("Deleting security profile %s" % group_id)
connection.securityprofile(guuid).delete() connection.securityprofile(guuid).delete()
def update_security_group(self, context, group_id, **group): def update_security_group(self, context, group_id, **group):
query = self._get_security_group(context, group_id) query = self._get_security_group(context, group_id)
connection = self.get_connection() with self.get_connection() as connection:
profile = connection.securityprofile(query.get('uuid')) profile = connection.securityprofile(query.get('uuid'))
ingress_rules = group.get('port_ingress_rules', ingress_rules = group.get('port_ingress_rules',
query.get('logical_port_ingress_rules')) query.get('logical_port_ingress_rules'))
egress_rules = group.get('port_egress_rules', egress_rules = group.get('port_egress_rules',
query.get('logical_port_egress_rules')) query.get('logical_port_egress_rules'))
if (len(ingress_rules) + len(egress_rules) > if (len(ingress_rules) + len(egress_rules) >
self.limits['max_rules_per_group']): self.limits['max_rules_per_group']):
raise exceptions.DriverLimitReached(limit="rules per group") raise exceptions.DriverLimitReached(limit="rules per group")
if group.get('name', None): if group.get('name', None):
profile.display_name(group['name']) profile.display_name(group['name'])
if group.get('port_ingress_rules', None) is not None: if group.get('port_ingress_rules', None) is not None:
profile.port_ingress_rules(ingress_rules) profile.port_ingress_rules(ingress_rules)
if group.get('port_egress_rules', None) is not None: if group.get('port_egress_rules', None) is not None:
profile.port_egress_rules(egress_rules) profile.port_egress_rules(egress_rules)
return profile.update() return profile.update()
def _update_security_group_rules(self, context, group_id, rule, operation, def _update_security_group_rules(self, context, group_id, rule, operation,
checks): checks):
@ -447,9 +471,9 @@ class NVPDriver(base.BaseDriver):
return None return None
def _lswitch_delete(self, context, lswitch_uuid): def _lswitch_delete(self, context, lswitch_uuid):
connection = self.get_connection() with self.get_connection() as connection:
LOG.debug("Deleting lswitch %s" % lswitch_uuid) LOG.debug("Deleting lswitch %s" % lswitch_uuid)
connection.lswitch(lswitch_uuid).delete() connection.lswitch(lswitch_uuid).delete()
def _config_provider_attrs(self, connection, switch, phys_net, def _config_provider_attrs(self, connection, switch, phys_net,
net_type, segment_id): net_type, segment_id):
@ -491,64 +515,65 @@ class NVPDriver(base.BaseDriver):
(context.tenant_id, network_name)) (context.tenant_id, network_name))
tenant_id = context.tenant_id tenant_id = context.tenant_id
connection = self.get_connection() with self.get_connection() as connection:
switch = connection.lswitch()
if network_name is None:
network_name = network_id
switch.display_name(network_name[:40])
tags = tags or []
tags.append({"tag": tenant_id, "scope": "os_tid"})
if network_id:
tags.append({"tag": network_id, "scope": "neutron_net_id"})
switch.tags(tags)
pnet = phys_net or CONF.NVP.default_tz
ptype = phys_type or CONF.NVP.default_tz_type
switch.transport_zone(pnet, ptype)
LOG.debug("Creating lswitch for network %s" % network_id)
switch = connection.lswitch() # When connecting to public or snet, we need switches that are
if network_name is None: # connected to their respective public/private transport zones
network_name = network_id # using a "bridge" connector. Public uses no VLAN, whereas private
switch.display_name(network_name[:40]) # uses VLAN 122 in netdev. Probably need this to be configurable
tags = tags or [] self._config_provider_attrs(connection, switch, phys_net,
tags.append({"tag": tenant_id, "scope": "os_tid"}) phys_type, segment_id)
if network_id: res = switch.create()
tags.append({"tag": network_id, "scope": "neutron_net_id"}) try:
switch.tags(tags) uuid = res["uuid"]
pnet = phys_net or CONF.NVP.default_tz return uuid
ptype = phys_type or CONF.NVP.default_tz_type except TypeError:
switch.transport_zone(pnet, ptype) LOG.exception("Unexpected return from NVP: %s" % res)
LOG.debug("Creating lswitch for network %s" % network_id) raise
# When connecting to public or snet, we need switches that are
# connected to their respective public/private transport zones
# using a "bridge" connector. Public uses no VLAN, whereas private
# uses VLAN 122 in netdev. Probably need this to be configurable
self._config_provider_attrs(connection, switch, phys_net, phys_type,
segment_id)
res = switch.create()
try:
uuid = res["uuid"]
return uuid
except TypeError:
LOG.exception("Unexpected return from NVP: %s" % res)
raise
def _lswitches_for_network(self, context, network_id): def _lswitches_for_network(self, context, network_id):
connection = self.get_connection() with self.get_connection() as connection:
query = connection.lswitch().query() query = connection.lswitch().query()
query.tagscopes(['os_tid', 'neutron_net_id']) query.tagscopes(['os_tid', 'neutron_net_id'])
query.tags([context.tenant_id, network_id]) query.tags([context.tenant_id, network_id])
return query return query
def _lswitch_from_port(self, context, port_id): def _lswitch_from_port(self, context, port_id):
connection = self.get_connection() with self.get_connection() as connection:
query = connection.lswitch_port("*").query() query = connection.lswitch_port("*").query()
query.relations("LogicalSwitchConfig") query.relations("LogicalSwitchConfig")
query.uuid(port_id) query.uuid(port_id)
port = query.results() port = query.results()
if port['result_count'] > 1: if port['result_count'] > 1:
raise Exception("Could not identify lswitch for port %s" % port_id) raise Exception("Could not identify lswitch for port %s" %
if port['result_count'] < 1: port_id)
raise Exception("No lswitch found for port %s" % port_id) if port['result_count'] < 1:
return port['results'][0]["_relations"]["LogicalSwitchConfig"]["uuid"] raise Exception("No lswitch found for port %s" % port_id)
cfg = port['results'][0]["_relations"]["LogicalSwitchConfig"]
return cfg["uuid"]
def _get_security_group(self, context, group_id): def _get_security_group(self, context, group_id):
connection = self.get_connection() with self.get_connection() as connection:
query = connection.securityprofile().query() query = connection.securityprofile().query()
query.tagscopes(['os_tid', 'neutron_group_id']) query.tagscopes(['os_tid', 'neutron_group_id'])
query.tags([context.tenant_id, group_id]) query.tags([context.tenant_id, group_id])
query = query.results() query = query.results()
if query['result_count'] != 1: if query['result_count'] != 1:
raise sg_ext.SecurityGroupNotFound(id=group_id) raise sg_ext.SecurityGroupNotFound(id=group_id)
return query['results'][0] return query['results'][0]
def _get_security_group_id(self, context, group_id): def _get_security_group_id(self, context, group_id):
return self._get_security_group(context, group_id)['uuid'] return self._get_security_group(context, group_id)['uuid']
@ -567,24 +592,25 @@ class NVPDriver(base.BaseDriver):
if rule.get(key): if rule.get(key):
rule_clone[key] = rule[key] rule_clone[key] = rule[key]
connection = self.get_connection() with self.get_connection() as connection:
secrule = connection.securityrule(ethertype, **rule_clone) secrule = connection.securityrule(ethertype, **rule_clone)
direction = rule.get('direction', '') direction = rule.get('direction', '')
if direction not in ['ingress', 'egress']: if direction not in ['ingress', 'egress']:
raise AttributeError( raise AttributeError(
"Direction not specified as 'ingress' or 'egress'.") "Direction not specified as 'ingress' or 'egress'.")
return (direction, secrule) return (direction, secrule)
def _check_rule_count_per_port(self, context, group_id): def _check_rule_count_per_port(self, context, group_id):
connection = self.get_connection() with self.get_connection() as connection:
ports = connection.lswitch_port("*").query().security_profile_uuid( ports = connection.lswitch_port("*").query().security_profile_uuid(
'=', self._get_security_group_id( '=', self._get_security_group_id(
context, group_id)).results().get('results', []) context, group_id)).results().get('results', [])
groups = (port.get('security_profiles', []) for port in ports) groups = (port.get('security_profiles', []) for port in ports)
return max([self._check_rule_count_for_groups( return max([self._check_rule_count_for_groups(
context, (connection.securityprofile(gp).read() for gp in group)) context, (connection.securityprofile(gp).read()
for group in groups] or [0]) for gp in group))
for group in groups] or [0])
def _check_rule_count_for_groups(self, context, groups): def _check_rule_count_for_groups(self, context, groups):
return sum(len(group['logical_port_ingress_rules']) + return sum(len(group['logical_port_ingress_rules']) +

View File

@ -123,3 +123,8 @@ class RedisConnectionFailure(exceptions.NeutronException):
class RedisSlaveWritesForbidden(exceptions.NeutronException): class RedisSlaveWritesForbidden(exceptions.NeutronException):
message = _("No write actions can be applied to Slave redis nodes.") message = _("No write actions can be applied to Slave redis nodes.")
class NoBackendConnectionsDefined(exceptions.NeutronException):
message = _("This driver cannot be used without a backend connection "
"definition. %(msg)")

View File

@ -124,10 +124,10 @@ class TestNVPDriverCreateNetwork(TestNVPDriver):
@contextlib.contextmanager @contextlib.contextmanager
def _stubs(self): def _stubs(self):
with contextlib.nested( with contextlib.nested(
mock.patch("%s.get_connection" % self.d_pkg), mock.patch("%s._connection" % self.d_pkg),
) as (get_connection,): ) as (conn,):
connection = self._create_connection() connection = self._create_connection()
get_connection.return_value = connection conn.return_value = connection
yield connection yield connection
def test_create_network(self): def test_create_network(self):
@ -151,8 +151,8 @@ class TestNVPDriverProviderNetwork(TestNVPDriver):
@contextlib.contextmanager @contextlib.contextmanager
def _stubs(self, tz): def _stubs(self, tz):
with contextlib.nested( with contextlib.nested(
mock.patch("%s.get_connection" % self.d_pkg), mock.patch("%s._connection" % self.d_pkg),
) as (get_connection,): ) as (conn,):
connection = self._create_connection() connection = self._create_connection()
switch = self._create_lswitch(1, False) switch = self._create_lswitch(1, False)
switch.transport_zone = mock.Mock() switch.transport_zone = mock.Mock()
@ -161,7 +161,7 @@ class TestNVPDriverProviderNetwork(TestNVPDriver):
tz_query = mock.Mock() tz_query = mock.Mock()
tz_query.query = mock.Mock(return_value=tz_results) tz_query.query = mock.Mock(return_value=tz_results)
connection.transportzone = mock.Mock(return_value=tz_query) connection.transportzone = mock.Mock(return_value=tz_query)
get_connection.return_value = connection conn.return_value = connection
yield connection, switch yield connection, switch
def test_config_provider_attrs_flat_net(self): def test_config_provider_attrs_flat_net(self):
@ -286,11 +286,11 @@ class TestNVPDriverDeleteNetwork(TestNVPDriver):
@contextlib.contextmanager @contextlib.contextmanager
def _stubs(self, network_exists=True): def _stubs(self, network_exists=True):
with contextlib.nested( with contextlib.nested(
mock.patch("%s.get_connection" % self.d_pkg), mock.patch("%s._connection" % self.d_pkg),
mock.patch("%s._lswitches_for_network" % self.d_pkg), mock.patch("%s._lswitches_for_network" % self.d_pkg),
) as (get_connection, switch_list): ) as (conn, switch_list):
connection = self._create_connection() connection = self._create_connection()
get_connection.return_value = connection conn.return_value = connection
if network_exists: if network_exists:
ret = {"results": [{"uuid": self.lswitch_uuid}]} ret = {"results": [{"uuid": self.lswitch_uuid}]}
else: else:
@ -318,12 +318,12 @@ class TestNVPDriverDeleteNetworkWithExceptions(TestNVPDriver):
@contextlib.contextmanager @contextlib.contextmanager
def _stubs(self, network_exists=True, exception=None): def _stubs(self, network_exists=True, exception=None):
with contextlib.nested( with contextlib.nested(
mock.patch("%s.get_connection" % self.d_pkg), mock.patch("%s._connection" % self.d_pkg),
mock.patch("%s._lswitches_for_network" % self.d_pkg), mock.patch("%s._lswitches_for_network" % self.d_pkg),
mock.patch("%s._lswitch_delete" % self.d_pkg), mock.patch("%s._lswitch_delete" % self.d_pkg),
) as (get_connection, switch_list, switch_delete): ) as (conn, switch_list, switch_delete):
connection = self._create_connection() connection = self._create_connection()
get_connection.return_value = connection conn.return_value = connection
if network_exists: if network_exists:
ret = {"results": [{"uuid": self.lswitch_uuid}]} ret = {"results": [{"uuid": self.lswitch_uuid}]}
else: else:
@ -372,13 +372,14 @@ class TestNVPDriverCreatePort(TestNVPDriver):
@contextlib.contextmanager @contextlib.contextmanager
def _stubs(self, has_lswitch=True, maxed_ports=False, net_details=None): def _stubs(self, has_lswitch=True, maxed_ports=False, net_details=None):
with contextlib.nested( with contextlib.nested(
mock.patch("%s.get_connection" % self.d_pkg), mock.patch("%s._connection" % self.d_pkg),
mock.patch("%s._next_connection" % self.d_pkg),
mock.patch("%s._lswitches_for_network" % self.d_pkg), mock.patch("%s._lswitches_for_network" % self.d_pkg),
mock.patch("%s._get_network_details" % self.d_pkg), mock.patch("%s._get_network_details" % self.d_pkg),
) as (get_connection, get_switches, get_net_dets): ) as (conn, next_conn, get_switches, get_net_dets):
connection = self._create_connection(has_switches=has_lswitch, connection = self._create_connection(has_switches=has_lswitch,
maxed_ports=maxed_ports) maxed_ports=maxed_ports)
get_connection.return_value = connection conn.return_value = connection
get_switches.return_value = connection.lswitch().query() get_switches.return_value = connection.lswitch().query()
get_net_dets.return_value = net_details get_net_dets.return_value = net_details
yield connection yield connection
@ -517,11 +518,12 @@ class TestNVPDriverUpdatePort(TestNVPDriver):
@contextlib.contextmanager @contextlib.contextmanager
def _stubs(self): def _stubs(self):
with contextlib.nested( with contextlib.nested(
mock.patch("%s.get_connection" % self.d_pkg), mock.patch("%s._connection" % self.d_pkg),
) as (get_connection,): mock.patch("%s._next_connection" % self.d_pkg),
) as (conn, next_conn):
connection = self._create_connection() connection = self._create_connection()
connection.securityprofile = self._create_security_profile() connection.securityprofile = self._create_security_profile()
get_connection.return_value = connection conn.return_value = connection
yield connection yield connection
def test_update_port(self): def test_update_port(self):
@ -550,10 +552,10 @@ class TestNVPDriverLswitchesForNetwork(TestNVPDriver):
@contextlib.contextmanager @contextlib.contextmanager
def _stubs(self, single_switch=True): def _stubs(self, single_switch=True):
with contextlib.nested( with contextlib.nested(
mock.patch("%s.get_connection" % self.d_pkg), mock.patch("%s._connection" % self.d_pkg),
) as (get_connection,): ) as (conn,):
connection = self._create_connection(switch_count=1) connection = self._create_connection(switch_count=1)
get_connection.return_value = connection conn.return_value = connection
yield connection yield connection
def test_get_lswitches(self): def test_get_lswitches(self):
@ -606,10 +608,11 @@ class TestNVPDriverDeletePort(TestNVPDriver):
@contextlib.contextmanager @contextlib.contextmanager
def _stubs(self, switch_count=1): def _stubs(self, switch_count=1):
with contextlib.nested( with contextlib.nested(
mock.patch("%s.get_connection" % self.d_pkg), mock.patch("%s._connection" % self.d_pkg),
) as (get_connection,): mock.patch("%s._next_connection" % self.d_pkg),
) as (conn, next_conn):
connection = self._create_connection(switch_count=switch_count) connection = self._create_connection(switch_count=switch_count)
get_connection.return_value = connection conn.return_value = connection
yield connection yield connection
def test_delete_port(self): def test_delete_port(self):
@ -645,11 +648,11 @@ class TestNVPDriverDeletePortWithExceptions(TestNVPDriver):
@contextlib.contextmanager @contextlib.contextmanager
def _stubs(self, switch_exception=None, delete_exception=None): def _stubs(self, switch_exception=None, delete_exception=None):
with contextlib.nested( with contextlib.nested(
mock.patch("%s.get_connection" % self.d_pkg), mock.patch("%s._connection" % self.d_pkg),
mock.patch("%s._lswitch_from_port" % self.d_pkg), mock.patch("%s._lswitch_from_port" % self.d_pkg),
) as (get_connection, switch): ) as (conn, switch):
connection = self._create_connection() connection = self._create_connection()
get_connection.return_value = connection conn.return_value = connection
if switch_exception: if switch_exception:
switch.side_effect = switch_exception switch.side_effect = switch_exception
else: else:
@ -729,11 +732,12 @@ class TestNVPDriverCreateSecurityGroup(TestNVPDriver):
@contextlib.contextmanager @contextlib.contextmanager
def _stubs(self): def _stubs(self):
with contextlib.nested( with contextlib.nested(
mock.patch("%s.get_connection" % self.d_pkg), mock.patch("%s._connection" % self.d_pkg),
) as (get_connection,): mock.patch("%s._next_connection" % self.d_pkg),
) as (conn, next_conn):
connection = self._create_connection() connection = self._create_connection()
connection.securityprofile = self._create_security_profile() connection.securityprofile = self._create_security_profile()
get_connection.return_value = connection conn.return_value = connection
yield connection yield connection
def test_security_group_create(self): def test_security_group_create(self):
@ -783,11 +787,12 @@ class TestNVPDriverDeleteSecurityGroup(TestNVPDriver):
@contextlib.contextmanager @contextlib.contextmanager
def _stubs(self): def _stubs(self):
with contextlib.nested( with contextlib.nested(
mock.patch("%s.get_connection" % self.d_pkg), mock.patch("%s._connection" % self.d_pkg),
) as (get_connection,): mock.patch("%s._next_connection" % self.d_pkg),
) as (conn, next_conn):
connection = self._create_connection() connection = self._create_connection()
connection.securityprofile = self._create_security_profile() connection.securityprofile = self._create_security_profile()
get_connection.return_value = connection conn.return_value = connection
yield connection yield connection
def test_security_group_delete(self): def test_security_group_delete(self):
@ -812,11 +817,12 @@ class TestNVPDriverUpdateSecurityGroup(TestNVPDriver):
@contextlib.contextmanager @contextlib.contextmanager
def _stubs(self): def _stubs(self):
with contextlib.nested( with contextlib.nested(
mock.patch("%s.get_connection" % self.d_pkg), mock.patch("%s._connection" % self.d_pkg),
) as (get_connection,): mock.patch("%s._next_connection" % self.d_pkg),
) as (conn, next_conn):
connection = self._create_connection() connection = self._create_connection()
connection.securityprofile = self._create_security_profile() connection.securityprofile = self._create_security_profile()
get_connection.return_value = connection conn.return_value = connection
yield connection yield connection
def test_security_group_update(self): def test_security_group_update(self):
@ -872,14 +878,15 @@ class TestNVPDriverCreateSecurityGroupRule(TestNVPDriver):
@contextlib.contextmanager @contextlib.contextmanager
def _stubs(self): def _stubs(self):
with contextlib.nested( with contextlib.nested(
mock.patch("%s.get_connection" % self.d_pkg), mock.patch("%s._connection" % self.d_pkg),
) as (get_connection,): mock.patch("%s._next_connection" % self.d_pkg),
) as (conn, next_conn):
connection = self._create_connection() connection = self._create_connection()
connection.securityprofile = self._create_security_profile() connection.securityprofile = self._create_security_profile()
connection.securityrule = self._create_security_rule() connection.securityrule = self._create_security_rule()
connection.lswitch_port().query.return_value = ( connection.lswitch_port().query.return_value = (
self._create_lport_query(1, [self.profile_id])) self._create_lport_query(1, [self.profile_id]))
get_connection.return_value = connection conn.return_value = connection
yield connection yield connection
def test_security_rule_create(self): def test_security_rule_create(self):
@ -955,13 +962,13 @@ class TestNVPDriverDeleteSecurityGroupRule(TestNVPDriver):
rulelist['logical_port_%s_rules' % rule.pop('direction')].append( rulelist['logical_port_%s_rules' % rule.pop('direction')].append(
rule) rule)
with contextlib.nested( with contextlib.nested(
mock.patch("%s.get_connection" % self.d_pkg), mock.patch("%s._connection" % self.d_pkg),
) as (get_connection,): ) as (conn,):
connection = self._create_connection() connection = self._create_connection()
connection.securityprofile = self._create_security_profile() connection.securityprofile = self._create_security_profile()
connection.securityrule = self._create_security_rule() connection.securityrule = self._create_security_rule()
connection.securityprofile().read().update(rulelist) connection.securityprofile().read().update(rulelist)
get_connection.return_value = connection conn.return_value = connection
yield connection yield connection
def test_delete_security_group(self): def test_delete_security_group(self):
@ -1023,16 +1030,40 @@ class TestNVPGetConnection(TestNVPDriver):
http_timeout=10, http_timeout=10,
retries=1, retries=1,
backoff=0)) backoff=0))
with mock.patch("aiclib.nvp.Connection") as (aiclib_conn): with contextlib.nested(
yield aiclib_conn mock.patch("aiclib.nvp.Connection"),
mock.patch("%s._next_connection" % self.d_pkg)
) as (aiclib_conn, next_conn):
yield aiclib_conn, next_conn
cfg.CONF.clear_override("controller_connection", "NVP") cfg.CONF.clear_override("controller_connection", "NVP")
def test_get_connection(self): def test_get_connection(self):
with self._stubs(has_conn=False) as aiclib_conn: with self._stubs(has_conn=False) as (aiclib_conn, next_conn):
self.driver.get_connection() with self.driver.get_connection():
pass
self.assertTrue(aiclib_conn.called) self.assertTrue(aiclib_conn.called)
self.assertFalse(next_conn.called)
def test_get_connection_connection_defined(self): def test_get_connection_connection_defined(self):
with self._stubs(has_conn=True) as aiclib_conn: with self._stubs(has_conn=True) as (aiclib_conn, next_conn):
self.driver.get_connection() with self.driver.get_connection():
pass
self.assertFalse(aiclib_conn.called) self.assertFalse(aiclib_conn.called)
self.assertFalse(next_conn.called)
def test_get_connection_iterates(self):
with self._stubs(has_conn=True) as (aiclib_conn, next_conn):
try:
with self.driver.get_connection():
raise Exception("Failure")
except Exception:
pass
self.assertFalse(aiclib_conn.called)
self.assertTrue(next_conn.called)
class TestNVPGetConnectionNoneDefined(TestNVPDriver):
def test_get_connection(self):
with self.assertRaises(q_exc.NoBackendConnectionsDefined):
with self.driver.get_connection():
pass

View File

@ -52,13 +52,13 @@ class TestOptimizedNVPDriverDeleteNetwork(TestOptimizedNVPDriver):
@contextlib.contextmanager @contextlib.contextmanager
def _stubs(self, switch_count=1): def _stubs(self, switch_count=1):
with contextlib.nested( with contextlib.nested(
mock.patch("%s.get_connection" % self.d_pkg), mock.patch("%s._connection" % self.d_pkg),
mock.patch("%s._lswitch_select_by_nvp_id" % self.d_pkg), mock.patch("%s._lswitch_select_by_nvp_id" % self.d_pkg),
mock.patch("%s._lswitches_for_network" % self.d_pkg), mock.patch("%s._lswitches_for_network" % self.d_pkg),
) as (get_connection, select_switch, get_switches): ) as (conn, select_switch, get_switches):
connection = self._create_connection() connection = self._create_connection()
switch = self._create_lswitch_mock() switch = self._create_lswitch_mock()
get_connection.return_value = connection conn.return_value = connection
select_switch.return_value = switch select_switch.return_value = switch
get_switches.return_value = [switch] * switch_count get_switches.return_value = [switch] * switch_count
self.context.session.delete = mock.Mock(return_value=None) self.context.session.delete = mock.Mock(return_value=None)
@ -105,14 +105,14 @@ class TestOptimizedNVPDriverDeleteNetworkWithExceptions(
@contextlib.contextmanager @contextlib.contextmanager
def _stubs(self, switch_count=1, error_code=500): def _stubs(self, switch_count=1, error_code=500):
with contextlib.nested( with contextlib.nested(
mock.patch("%s.get_connection" % self.d_pkg), mock.patch("%s._connection" % self.d_pkg),
mock.patch("%s._lswitch_select_by_nvp_id" % self.d_pkg), mock.patch("%s._lswitch_select_by_nvp_id" % self.d_pkg),
mock.patch("%s._lswitches_for_network" % self.d_pkg), mock.patch("%s._lswitches_for_network" % self.d_pkg),
mock.patch("%s._lswitch_delete" % self.d_pkg) mock.patch("%s._lswitch_delete" % self.d_pkg)
) as (get_connection, select_switch, get_switches, delete_switch): ) as (conn, select_switch, get_switches, delete_switch):
connection = self._create_connection() connection = self._create_connection()
switch = self._create_lswitch_mock() switch = self._create_lswitch_mock()
get_connection.return_value = connection conn.return_value = connection
select_switch.return_value = switch select_switch.return_value = switch
get_switches.return_value = [switch] * switch_count get_switches.return_value = [switch] * switch_count
delete_switch.side_effect = aiclib.core.AICException( delete_switch.side_effect = aiclib.core.AICException(
@ -151,17 +151,17 @@ class TestOptimizedNVPDriverDeletePortMultiSwitch(TestOptimizedNVPDriver):
@contextlib.contextmanager @contextlib.contextmanager
def _stubs(self, port_count=2, exception=None): def _stubs(self, port_count=2, exception=None):
with contextlib.nested( with contextlib.nested(
mock.patch("%s.get_connection" % self.d_pkg), mock.patch("%s._connection" % self.d_pkg),
mock.patch("%s._lport_select_by_id" % self.d_pkg), mock.patch("%s._lport_select_by_id" % self.d_pkg),
mock.patch("%s._lswitch_select_by_nvp_id" % self.d_pkg), mock.patch("%s._lswitch_select_by_nvp_id" % self.d_pkg),
mock.patch("%s._lswitches_for_network" % self.d_pkg), mock.patch("%s._lswitches_for_network" % self.d_pkg),
mock.patch("%s._lport_delete" % self.d_pkg), mock.patch("%s._lport_delete" % self.d_pkg),
) as (get_connection, select_port, select_switch, ) as (conn, select_port, select_switch,
two_switch, port_delete): two_switch, port_delete):
connection = self._create_connection() connection = self._create_connection()
port = self._create_lport_mock(port_count) port = self._create_lport_mock(port_count)
switch = self._create_lswitch_mock() switch = self._create_lswitch_mock()
get_connection.return_value = connection conn.return_value = connection
select_port.return_value = port select_port.return_value = port
select_switch.return_value = switch select_switch.return_value = switch
two_switch.return_value = [switch, switch] two_switch.return_value = [switch, switch]
@ -244,15 +244,15 @@ class TestOptimizedNVPDriverDeletePortSingleSwitch(TestOptimizedNVPDriver):
@contextlib.contextmanager @contextlib.contextmanager
def _stubs(self, port_count=2): def _stubs(self, port_count=2):
with contextlib.nested( with contextlib.nested(
mock.patch("%s.get_connection" % self.d_pkg), mock.patch("%s._connection" % self.d_pkg),
mock.patch("%s._lport_select_by_id" % self.d_pkg), mock.patch("%s._lport_select_by_id" % self.d_pkg),
mock.patch("%s._lswitch_select_by_nvp_id" % self.d_pkg), mock.patch("%s._lswitch_select_by_nvp_id" % self.d_pkg),
mock.patch("%s._lswitches_for_network" % self.d_pkg), mock.patch("%s._lswitches_for_network" % self.d_pkg),
) as (get_connection, select_port, select_switch, one_switch): ) as (conn, select_port, select_switch, one_switch):
connection = self._create_connection() connection = self._create_connection()
port = self._create_lport_mock(port_count) port = self._create_lport_mock(port_count)
switch = self._create_lswitch_mock() switch = self._create_lswitch_mock()
get_connection.return_value = connection conn.return_value = connection
select_port.return_value = port select_port.return_value = port
select_switch.return_value = switch select_switch.return_value = switch
one_switch.return_value = [switch] one_switch.return_value = [switch]
@ -274,16 +274,16 @@ class TestOptimizedNVPDriverCreatePort(TestOptimizedNVPDriver):
@contextlib.contextmanager @contextlib.contextmanager
def _stubs(self, has_lswitch=True, maxed_ports=False): def _stubs(self, has_lswitch=True, maxed_ports=False):
with contextlib.nested( with contextlib.nested(
mock.patch("%s.get_connection" % self.d_pkg), mock.patch("%s._connection" % self.d_pkg),
mock.patch("%s._lswitch_select_free" % self.d_pkg), mock.patch("%s._lswitch_select_free" % self.d_pkg),
mock.patch("%s._lswitch_select_first" % self.d_pkg), mock.patch("%s._lswitch_select_first" % self.d_pkg),
mock.patch("%s._lswitch_select_by_nvp_id" % self.d_pkg), mock.patch("%s._lswitch_select_by_nvp_id" % self.d_pkg),
mock.patch("%s._lswitch_create_optimized" % self.d_pkg), mock.patch("%s._lswitch_create_optimized" % self.d_pkg),
mock.patch("%s._get_network_details" % self.d_pkg) mock.patch("%s._get_network_details" % self.d_pkg)
) as (get_connection, select_free, select_first, ) as (conn, select_free, select_first,
select_by_id, create_opt, get_net_dets): select_by_id, create_opt, get_net_dets):
connection = self._create_connection() connection = self._create_connection()
get_connection.return_value = connection conn.return_value = connection
if has_lswitch: if has_lswitch:
select_first.return_value = mock.Mock(nvp_id=self.lswitch_uuid) select_first.return_value = mock.Mock(nvp_id=self.lswitch_uuid)
if not has_lswitch: if not has_lswitch:
@ -427,7 +427,7 @@ class TestOptimizedNVPDriverUpdatePort(TestOptimizedNVPDriver):
class TestCreateSecurityGroups(TestOptimizedNVPDriver): class TestCreateSecurityGroups(TestOptimizedNVPDriver):
def test_create_security_group(self): def test_create_security_group(self):
with mock.patch("%s.get_connection" % self.d_pkg): with mock.patch("%s._connection" % self.d_pkg):
self.driver.create_security_group(self.context, "newgroup") self.driver.create_security_group(self.context, "newgroup")
self.assertTrue(self.context.session.add.called) self.assertTrue(self.context.session.add.called)
@ -436,7 +436,7 @@ class TestDeleteSecurityGroups(TestOptimizedNVPDriver):
def test_delete_security_group(self): def test_delete_security_group(self):
mod_path = "quark.drivers.nvp_driver.NVPDriver" mod_path = "quark.drivers.nvp_driver.NVPDriver"
with contextlib.nested( with contextlib.nested(
mock.patch("%s.get_connection" % self.d_pkg), mock.patch("%s._connection" % self.d_pkg),
mock.patch("%s._query_security_group" % self.d_pkg), mock.patch("%s._query_security_group" % self.d_pkg),
mock.patch("%s.delete_security_group" % mod_path)): mock.patch("%s.delete_security_group" % mod_path)):
@ -452,10 +452,10 @@ class TestSecurityGroupRules(TestOptimizedNVPDriver):
def _stubs(self, rules=None): def _stubs(self, rules=None):
rules = rules or [] rules = rules or []
with contextlib.nested( with contextlib.nested(
mock.patch("%s.get_connection" % self.d_pkg), mock.patch("%s._connection" % self.d_pkg),
mock.patch("%s._query_security_group" % self.d_pkg), mock.patch("%s._query_security_group" % self.d_pkg),
mock.patch("%s._check_rule_count_per_port" % self.d_pkg), mock.patch("%s._check_rule_count_per_port" % self.d_pkg),
) as (get_connection, query_sec_group, rule_count): ) as (conn, query_sec_group, rule_count):
query_sec_group.return_value = (quark.drivers.optimized_nvp_driver. query_sec_group.return_value = (quark.drivers.optimized_nvp_driver.
SecurityProfile()) SecurityProfile())
connection = self._create_connection() connection = self._create_connection()
@ -464,7 +464,7 @@ class TestSecurityGroupRules(TestOptimizedNVPDriver):
connection.securityrule = self._create_security_rule() connection.securityrule = self._create_security_rule()
connection.lswitch_port().query.return_value = ( connection.lswitch_port().query.return_value = (
self._create_lport_query(1, [self.profile_id])) self._create_lport_query(1, [self.profile_id]))
get_connection.return_value = connection conn.return_value = connection
old_query = self.context.session.query old_query = self.context.session.query
sec_group = quark.db.models.SecurityGroup() sec_group = quark.db.models.SecurityGroup()