Merge "Switch Ironic to openstacksdk for Neutron"
This commit is contained in:
commit
30a9d33577
@ -233,7 +233,6 @@ default:
|
|||||||
iso8601=WARNING
|
iso8601=WARNING
|
||||||
keystoneauth.session=INFO
|
keystoneauth.session=INFO
|
||||||
keystonemiddleware.auth_token=INFO
|
keystonemiddleware.auth_token=INFO
|
||||||
neutronclient=WARNING
|
|
||||||
oslo_messaging=INFO
|
oslo_messaging=INFO
|
||||||
paramiko=WARNING
|
paramiko=WARNING
|
||||||
qpid.messaging=INFO
|
qpid.messaging=INFO
|
||||||
@ -241,6 +240,7 @@ default:
|
|||||||
sqlalchemy=WARNING
|
sqlalchemy=WARNING
|
||||||
stevedore=INFO
|
stevedore=INFO
|
||||||
urllib3.connectionpool=WARNING
|
urllib3.connectionpool=WARNING
|
||||||
|
openstack=WARNING
|
||||||
default_management_interface = None
|
default_management_interface = None
|
||||||
default_network_interface = None
|
default_network_interface = None
|
||||||
default_portgroup_mode = active-backup
|
default_portgroup_mode = active-backup
|
||||||
|
@ -16,8 +16,8 @@
|
|||||||
|
|
||||||
import functools
|
import functools
|
||||||
|
|
||||||
from keystoneauth1 import exceptions as kaexception
|
from keystoneauth1 import exceptions as ks_exception
|
||||||
from keystoneauth1 import loading as kaloading
|
from keystoneauth1 import loading as ks_loading
|
||||||
from keystoneauth1 import service_token
|
from keystoneauth1 import service_token
|
||||||
from keystoneauth1 import token_endpoint
|
from keystoneauth1 import token_endpoint
|
||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
@ -35,15 +35,15 @@ def ks_exceptions(f):
|
|||||||
def wrapper(*args, **kwargs):
|
def wrapper(*args, **kwargs):
|
||||||
try:
|
try:
|
||||||
return f(*args, **kwargs)
|
return f(*args, **kwargs)
|
||||||
except kaexception.EndpointNotFound:
|
except ks_exception.EndpointNotFound:
|
||||||
service_type = kwargs.get('service_type', 'baremetal')
|
service_type = kwargs.get('service_type', 'baremetal')
|
||||||
endpoint_type = kwargs.get('endpoint_type', 'internal')
|
endpoint_type = kwargs.get('endpoint_type', 'internal')
|
||||||
raise exception.CatalogNotFound(
|
raise exception.CatalogNotFound(
|
||||||
service_type=service_type, endpoint_type=endpoint_type)
|
service_type=service_type, endpoint_type=endpoint_type)
|
||||||
except (kaexception.Unauthorized, kaexception.AuthorizationFailure):
|
except (ks_exception.Unauthorized, ks_exception.AuthorizationFailure):
|
||||||
raise exception.KeystoneUnauthorized()
|
raise exception.KeystoneUnauthorized()
|
||||||
except (kaexception.NoMatchingPlugin,
|
except (ks_exception.NoMatchingPlugin,
|
||||||
kaexception.MissingRequiredOptions) as e:
|
ks_exception.MissingRequiredOptions) as e:
|
||||||
raise exception.ConfigInvalid(str(e))
|
raise exception.ConfigInvalid(str(e))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
LOG.exception('Keystone request failed: %(msg)s',
|
LOG.exception('Keystone request failed: %(msg)s',
|
||||||
@ -63,7 +63,7 @@ def get_session(group, **session_kwargs):
|
|||||||
:param group: name of the config section to load session options from
|
:param group: name of the config section to load session options from
|
||||||
|
|
||||||
"""
|
"""
|
||||||
return kaloading.load_session_from_conf_options(
|
return ks_loading.load_session_from_conf_options(
|
||||||
CONF, group, **session_kwargs)
|
CONF, group, **session_kwargs)
|
||||||
|
|
||||||
|
|
||||||
@ -81,9 +81,9 @@ def get_auth(group, **auth_kwargs):
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
auth = kaloading.load_auth_from_conf_options(CONF, group,
|
auth = ks_loading.load_auth_from_conf_options(CONF, group,
|
||||||
**auth_kwargs)
|
**auth_kwargs)
|
||||||
except kaexception.MissingRequiredOptions:
|
except ks_exception.MissingRequiredOptions:
|
||||||
LOG.error('Failed to load auth plugin from group %s', group)
|
LOG.error('Failed to load auth plugin from group %s', group)
|
||||||
raise
|
raise
|
||||||
return auth
|
return auth
|
||||||
@ -100,8 +100,8 @@ def get_adapter(group, **adapter_kwargs):
|
|||||||
:param group: name of the config section to load adapter options from
|
:param group: name of the config section to load adapter options from
|
||||||
|
|
||||||
"""
|
"""
|
||||||
return kaloading.load_adapter_from_conf_options(CONF, group,
|
return ks_loading.load_adapter_from_conf_options(CONF, group,
|
||||||
**adapter_kwargs)
|
**adapter_kwargs)
|
||||||
|
|
||||||
|
|
||||||
def get_endpoint(group, **adapter_kwargs):
|
def get_endpoint(group, **adapter_kwargs):
|
||||||
|
@ -13,11 +13,9 @@
|
|||||||
import copy
|
import copy
|
||||||
import ipaddress
|
import ipaddress
|
||||||
|
|
||||||
from keystoneauth1 import loading as ks_loading
|
import openstack
|
||||||
from neutronclient.common import exceptions as neutron_exceptions
|
from openstack.connection import exceptions as openstack_exc
|
||||||
from neutronclient.v2_0 import client as clientv20
|
|
||||||
from oslo_log import log
|
from oslo_log import log
|
||||||
from oslo_utils import uuidutils
|
|
||||||
import retrying
|
import retrying
|
||||||
|
|
||||||
from ironic.api.controllers.v1 import types
|
from ironic.api.controllers.v1 import types
|
||||||
@ -43,9 +41,6 @@ VNIC_SMARTNIC = 'smart-nic'
|
|||||||
PHYSNET_PARAM_NAME = 'provider:physical_network'
|
PHYSNET_PARAM_NAME = 'provider:physical_network'
|
||||||
"""Name of the neutron network API physical network parameter."""
|
"""Name of the neutron network API physical network parameter."""
|
||||||
|
|
||||||
SEGMENTS_PARAM_NAME = 'segments'
|
|
||||||
"""Name of the neutron network API segments parameter."""
|
|
||||||
|
|
||||||
|
|
||||||
def _get_neutron_session():
|
def _get_neutron_session():
|
||||||
global _NEUTRON_SESSION
|
global _NEUTRON_SESSION
|
||||||
@ -56,54 +51,35 @@ def _get_neutron_session():
|
|||||||
return _NEUTRON_SESSION
|
return _NEUTRON_SESSION
|
||||||
|
|
||||||
|
|
||||||
# TODO(pas-ha) remove deprecated options handling in Rocky
|
def get_client(token=None, context=None, auth_from_config=False):
|
||||||
# until then it might look ugly due to all if's.
|
"""Retrieve a neutron client connection.
|
||||||
def get_client(token=None, context=None):
|
|
||||||
|
:param context: request context,
|
||||||
|
instance of ironic.common.context.RequestContext
|
||||||
|
:param auth_from_config: (boolean) When True, use auth values from
|
||||||
|
conf parameters
|
||||||
|
:returns: A neutron client.
|
||||||
|
"""
|
||||||
if not context:
|
if not context:
|
||||||
context = ironic_context.RequestContext(auth_token=token)
|
context = ironic_context.RequestContext(auth_token=token)
|
||||||
# NOTE(pas-ha) neutronclient supports passing both session
|
|
||||||
# and the auth to client separately, makes things easier
|
|
||||||
session = _get_neutron_session()
|
session = _get_neutron_session()
|
||||||
service_auth = keystone.get_auth('neutron')
|
service_auth = keystone.get_auth('neutron')
|
||||||
|
|
||||||
endpoint = keystone.get_endpoint('neutron', session=session,
|
endpoint = keystone.get_endpoint('neutron', session=session,
|
||||||
auth=service_auth)
|
auth=service_auth)
|
||||||
|
|
||||||
user_auth = None
|
user_auth = None
|
||||||
if CONF.neutron.auth_type != 'none' and context.auth_token:
|
if (not auth_from_config and CONF.neutron.auth_type != 'none'
|
||||||
|
and context.auth_token):
|
||||||
user_auth = keystone.get_service_auth(context, endpoint, service_auth)
|
user_auth = keystone.get_service_auth(context, endpoint, service_auth)
|
||||||
return clientv20.Client(session=session,
|
|
||||||
auth=user_auth or service_auth,
|
sess = keystone.get_session('neutron', timeout=CONF.neutron.timeout,
|
||||||
endpoint_override=endpoint,
|
auth=user_auth or service_auth)
|
||||||
retries=CONF.neutron.retries,
|
conn = openstack.connection.Connection(session=sess, oslo_conf=CONF)
|
||||||
global_request_id=context.global_id,
|
|
||||||
timeout=CONF.neutron.request_timeout)
|
return conn.global_request(context.global_id).network
|
||||||
|
|
||||||
|
|
||||||
def _get_conf_client(context):
|
def update_neutron_port(context, port_id, attrs, client=None):
|
||||||
"""Retrieve a neutron client connection using conf parameters.
|
|
||||||
|
|
||||||
:param context: request context,
|
|
||||||
instance of ironic.common.context.RequestContext
|
|
||||||
:returns: A neutron client.
|
|
||||||
"""
|
|
||||||
|
|
||||||
auth = ks_loading.load_auth_from_conf_options(CONF, 'neutron')
|
|
||||||
session = ks_loading.load_session_from_conf_options(
|
|
||||||
CONF,
|
|
||||||
'neutron',
|
|
||||||
auth=auth)
|
|
||||||
endpoint = keystone.get_endpoint('neutron', session=session,
|
|
||||||
auth=auth)
|
|
||||||
return clientv20.Client(session=session,
|
|
||||||
auth=auth,
|
|
||||||
endpoint_override=endpoint,
|
|
||||||
retries=CONF.neutron.retries,
|
|
||||||
global_request_id=context.global_id,
|
|
||||||
timeout=CONF.neutron.request_timeout)
|
|
||||||
|
|
||||||
|
|
||||||
def update_neutron_port(context, port_id, update_body, client=None):
|
|
||||||
"""Undate a neutron port
|
"""Undate a neutron port
|
||||||
|
|
||||||
Uses neutron client from conf client to update a neutron client
|
Uses neutron client from conf client to update a neutron client
|
||||||
@ -112,15 +88,20 @@ def update_neutron_port(context, port_id, update_body, client=None):
|
|||||||
:param context: request context,
|
:param context: request context,
|
||||||
instance of ironic.common.context.RequestContext
|
instance of ironic.common.context.RequestContext
|
||||||
:param port_id: Neutron port ID.
|
:param port_id: Neutron port ID.
|
||||||
:param update_body: Body of update
|
:param attrs: The attributes to update on the port
|
||||||
:param client: Optional Neutron client
|
:param client: Optional Neutron client
|
||||||
"""
|
"""
|
||||||
if not client:
|
if not client:
|
||||||
# verify that user can see the port before updating it
|
# verify that user can see the port before updating it
|
||||||
get_client(context=context).show_port(port_id)
|
get_client(context=context).get_port(port_id)
|
||||||
client = _get_conf_client(context)
|
# Set user_auth=False to ensure auth values from ironic.conf is used
|
||||||
|
# prevents issues where a non-admin user is not allowed to manage
|
||||||
|
# Neutron ports.
|
||||||
|
client = get_client(context=context, auth_from_config=True)
|
||||||
|
|
||||||
return client.update_port(port_id, update_body)
|
attrs = attrs.get('port', attrs)
|
||||||
|
|
||||||
|
return client.update_port(port_id, **attrs)
|
||||||
|
|
||||||
|
|
||||||
def unbind_neutron_port(port_id, client=None, context=None):
|
def unbind_neutron_port(port_id, client=None, context=None):
|
||||||
@ -136,21 +117,20 @@ def unbind_neutron_port(port_id, client=None, context=None):
|
|||||||
:raises: NetworkError
|
:raises: NetworkError
|
||||||
"""
|
"""
|
||||||
|
|
||||||
body_unbind = {'port': {'binding:host_id': '',
|
attrs_unbind = {'binding:host_id': '', 'binding:profile': {}}
|
||||||
'binding:profile': {}}}
|
attrs_reset_mac = {'mac_address': None}
|
||||||
body_reset_mac = {'port': {'mac_address': None}}
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
update_neutron_port(context, port_id, body_unbind, client)
|
update_neutron_port(context, port_id, attrs_unbind, client)
|
||||||
# NOTE(hjensas): We need to reset the mac address in a separate step.
|
# NOTE(hjensas): We need to reset the mac address in a separate step.
|
||||||
# Exception PortBound will be raised by neutron as it refuses to
|
# Exception PortBound will be raised by neutron as it refuses to
|
||||||
# update the mac address of a bound port if we attempt to unbind and
|
# update the mac address of a bound port if we attempt to unbind and
|
||||||
# reset the mac in the same call.
|
# reset the mac in the same call.
|
||||||
update_neutron_port(context, port_id, body_reset_mac, client)
|
update_neutron_port(context, port_id, attrs_reset_mac, client)
|
||||||
# NOTE(vsaienko): Ignore if port was deleted before calling vif detach.
|
# NOTE(vsaienko): Ignore if port was deleted before calling vif detach.
|
||||||
except neutron_exceptions.PortNotFoundClient:
|
except openstack_exc.ResourceNotFound:
|
||||||
LOG.info('Port %s was not found while unbinding.', port_id)
|
LOG.info('Port %s was not found while unbinding.', port_id)
|
||||||
except neutron_exceptions.NeutronClientException as e:
|
except openstack_exc.OpenStackCloudException as e:
|
||||||
msg = (_('Unable to clear binding profile for '
|
msg = (_('Unable to clear binding profile for '
|
||||||
'neutron port %(port_id)s. Error: '
|
'neutron port %(port_id)s. Error: '
|
||||||
'%(err)s') % {'port_id': port_id, 'err': e})
|
'%(err)s') % {'port_id': port_id, 'err': e})
|
||||||
@ -168,12 +148,12 @@ def update_port_address(port_id, address, context=None):
|
|||||||
:raises: FailedToUpdateMacOnPort
|
:raises: FailedToUpdateMacOnPort
|
||||||
"""
|
"""
|
||||||
client = get_client(context=context)
|
client = get_client(context=context)
|
||||||
port_req_body = {'port': {'mac_address': address}}
|
port_attrs = {'mac_address': address}
|
||||||
|
|
||||||
try:
|
try:
|
||||||
msg = (_("Failed to get the current binding on Neutron "
|
msg = (_("Failed to get the current binding on Neutron "
|
||||||
"port %s.") % port_id)
|
"port %s.") % port_id)
|
||||||
port = client.show_port(port_id).get('port', {})
|
port = client.get_port(port_id)
|
||||||
binding_host_id = port.get('binding:host_id')
|
binding_host_id = port.get('binding:host_id')
|
||||||
binding_profile = port.get('binding:profile')
|
binding_profile = port.get('binding:profile')
|
||||||
|
|
||||||
@ -186,17 +166,17 @@ def update_port_address(port_id, address, context=None):
|
|||||||
unbind_neutron_port(port_id, context=context)
|
unbind_neutron_port(port_id, context=context)
|
||||||
|
|
||||||
msg = (_("Failed to update MAC address on Neutron port %s.") % port_id)
|
msg = (_("Failed to update MAC address on Neutron port %s.") % port_id)
|
||||||
update_neutron_port(context, port_id, port_req_body)
|
update_neutron_port(context, port_id, port_attrs)
|
||||||
|
|
||||||
# Restore original binding:profile and host_id
|
# Restore original binding:profile and host_id
|
||||||
if binding_host_id:
|
if binding_host_id:
|
||||||
msg = (_("Failed to update binding:host_id and profile on Neutron "
|
msg = (_("Failed to update binding:host_id and profile on Neutron "
|
||||||
"port %s.") % port_id)
|
"port %s.") % port_id)
|
||||||
port_req_body = {'port': {'binding:host_id': binding_host_id,
|
port_attrs = {'binding:host_id': binding_host_id,
|
||||||
'binding:profile': binding_profile}}
|
'binding:profile': binding_profile}
|
||||||
|
|
||||||
update_neutron_port(context, port_id, port_req_body)
|
update_neutron_port(context, port_id, port_attrs)
|
||||||
except (neutron_exceptions.NeutronClientException, exception.NetworkError):
|
except (openstack_exc.OpenStackCloudException, exception.NetworkError):
|
||||||
LOG.exception(msg)
|
LOG.exception(msg)
|
||||||
raise exception.FailedToUpdateMacOnPort(port_id=port_id)
|
raise exception.FailedToUpdateMacOnPort(port_id=port_id)
|
||||||
|
|
||||||
@ -213,20 +193,18 @@ def _verify_security_groups(security_groups, client):
|
|||||||
if not security_groups:
|
if not security_groups:
|
||||||
return
|
return
|
||||||
try:
|
try:
|
||||||
neutron_sec_groups = (
|
neutron_sec_groups = set(
|
||||||
client.list_security_groups(id=security_groups, fields='id').get(
|
x.id for x in client.security_groups(id=security_groups))
|
||||||
'security_groups', []))
|
except openstack_exc.OpenStackCloudException as e:
|
||||||
except neutron_exceptions.NeutronClientException as e:
|
|
||||||
msg = (_("Could not retrieve security groups from neutron: %(exc)s") %
|
msg = (_("Could not retrieve security groups from neutron: %(exc)s") %
|
||||||
{'exc': e})
|
{'exc': e})
|
||||||
LOG.exception(msg)
|
LOG.exception(msg)
|
||||||
raise exception.NetworkError(msg)
|
raise exception.NetworkError(msg)
|
||||||
|
|
||||||
if set(security_groups).issubset(x['id'] for x in neutron_sec_groups):
|
if set(security_groups).issubset(neutron_sec_groups):
|
||||||
return
|
return
|
||||||
|
|
||||||
missing_sec_groups = set(security_groups).difference(
|
missing_sec_groups = set(security_groups).difference(neutron_sec_groups)
|
||||||
x['id'] for x in neutron_sec_groups)
|
|
||||||
msg = (_('Could not find these security groups (specified via ironic '
|
msg = (_('Could not find these security groups (specified via ironic '
|
||||||
'config) in neutron: %(ir-sg)s')
|
'config) in neutron: %(ir-sg)s')
|
||||||
% {'ir-sg': list(missing_sec_groups)})
|
% {'ir-sg': list(missing_sec_groups)})
|
||||||
@ -245,20 +223,17 @@ def _add_ip_addresses_for_ipv6_stateful(context, port, client):
|
|||||||
:param port: A neutron port
|
:param port: A neutron port
|
||||||
:param client: Neutron client
|
:param client: Neutron client
|
||||||
"""
|
"""
|
||||||
fixed_ips = port['port']['fixed_ips']
|
fixed_ips = port.fixed_ips
|
||||||
if (not fixed_ips
|
if (not fixed_ips
|
||||||
or ipaddress.ip_address(
|
or ipaddress.ip_address(fixed_ips[0]['ip_address']).version != 6):
|
||||||
fixed_ips[0]['ip_address']).version != 6):
|
|
||||||
return
|
return
|
||||||
|
subnet = client.get_subnet(fixed_ips[0]['subnet_id'])
|
||||||
subnet = client.show_subnet(
|
if subnet and subnet.ipv6_address_mode == 'dhcpv6-stateful':
|
||||||
port['port']['fixed_ips'][0]['subnet_id']).get('subnet')
|
|
||||||
if subnet and subnet['ipv6_address_mode'] == 'dhcpv6-stateful':
|
|
||||||
for i in range(1, CONF.neutron.dhcpv6_stateful_address_count):
|
for i in range(1, CONF.neutron.dhcpv6_stateful_address_count):
|
||||||
fixed_ips.append({'subnet_id': subnet['id']})
|
fixed_ips.append({'subnet_id': subnet['id']})
|
||||||
|
|
||||||
body = {'port': {'fixed_ips': fixed_ips}}
|
attrs = {'fixed_ips': fixed_ips}
|
||||||
update_neutron_port(context, port['port']['id'], body)
|
update_neutron_port(context, port.id, attrs, client=client)
|
||||||
|
|
||||||
|
|
||||||
def add_ports_to_network(task, network_uuid, security_groups=None):
|
def add_ports_to_network(task, network_uuid, security_groups=None):
|
||||||
@ -291,27 +266,22 @@ def add_ports_to_network(task, network_uuid, security_groups=None):
|
|||||||
{'net_iface': task.driver.network.__class__.__name__,
|
{'net_iface': task.driver.network.__class__.__name__,
|
||||||
'node': node.uuid, 'network_uuid': network_uuid})
|
'node': node.uuid, 'network_uuid': network_uuid})
|
||||||
|
|
||||||
body = {
|
attrs = {'network_id': network_uuid,
|
||||||
'port': {
|
'admin_state_up': True,
|
||||||
'network_id': network_uuid,
|
'binding:vnic_type': VNIC_BAREMETAL,
|
||||||
'admin_state_up': True,
|
}
|
||||||
'binding:vnic_type': VNIC_BAREMETAL,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
# separate out fields that can only be updated by admins
|
# separate out fields that can only be updated by admins
|
||||||
update_body = {
|
update_attrs = {'binding:host_id': node.uuid,
|
||||||
'port': {
|
'device_owner': 'baremetal:none',
|
||||||
'binding:host_id': node.uuid,
|
}
|
||||||
'device_owner': 'baremetal:none',
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if security_groups:
|
if security_groups:
|
||||||
body['port']['security_groups'] = security_groups
|
attrs['security_groups'] = security_groups
|
||||||
|
|
||||||
# Since instance_uuid will not be available during cleaning
|
# Since instance_uuid will not be available during cleaning
|
||||||
# operations, we need to check that and populate them only when
|
# operations, we need to check that and populate them only when
|
||||||
# available
|
# available
|
||||||
body['port']['device_id'] = node.instance_uuid or node.uuid
|
attrs['device_id'] = node.instance_uuid or node.uuid
|
||||||
|
|
||||||
ports = {}
|
ports = {}
|
||||||
failures = []
|
failures = []
|
||||||
@ -329,23 +299,24 @@ def add_ports_to_network(task, network_uuid, security_groups=None):
|
|||||||
|
|
||||||
for ironic_port in ports_to_create:
|
for ironic_port in ports_to_create:
|
||||||
# Start with a clean state for each port
|
# Start with a clean state for each port
|
||||||
port_body = copy.deepcopy(body)
|
port_attrs = copy.deepcopy(attrs)
|
||||||
update_port_body = copy.deepcopy(update_body)
|
update_port_attrs = copy.deepcopy(update_attrs)
|
||||||
|
|
||||||
# Skip ports that are missing required information for deploy.
|
# Skip ports that are missing required information for deploy.
|
||||||
if not validate_port_info(node, ironic_port):
|
if not validate_port_info(node, ironic_port):
|
||||||
failures.append(ironic_port.uuid)
|
failures.append(ironic_port.uuid)
|
||||||
continue
|
continue
|
||||||
update_port_body['port']['mac_address'] = ironic_port.address
|
|
||||||
|
update_port_attrs['mac_address'] = ironic_port.address
|
||||||
binding_profile = {'local_link_information':
|
binding_profile = {'local_link_information':
|
||||||
[portmap[ironic_port.uuid]]}
|
[portmap[ironic_port.uuid]]}
|
||||||
update_port_body['port']['binding:profile'] = binding_profile
|
update_port_attrs['binding:profile'] = binding_profile
|
||||||
|
|
||||||
if not ironic_port.pxe_enabled:
|
if not ironic_port.pxe_enabled:
|
||||||
LOG.debug("Adding port %(port)s to network %(net)s for "
|
LOG.debug("Adding port %(port)s to network %(net)s for "
|
||||||
"provisioning without an IP allocation.",
|
"provisioning without an IP allocation.",
|
||||||
{'port': ironic_port.uuid,
|
{'port': ironic_port.uuid, 'net': network_uuid})
|
||||||
'net': network_uuid})
|
port_attrs['fixed_ips'] = []
|
||||||
port_body['fixed_ips'] = []
|
|
||||||
|
|
||||||
is_smart_nic = is_smartnic_port(ironic_port)
|
is_smart_nic = is_smartnic_port(ironic_port)
|
||||||
if is_smart_nic:
|
if is_smart_nic:
|
||||||
@ -354,29 +325,29 @@ def add_ports_to_network(task, network_uuid, security_groups=None):
|
|||||||
'port %(port_id)s, hostname %(hostname)s',
|
'port %(port_id)s, hostname %(hostname)s',
|
||||||
{'port_id': ironic_port.uuid,
|
{'port_id': ironic_port.uuid,
|
||||||
'hostname': link_info['hostname']})
|
'hostname': link_info['hostname']})
|
||||||
update_port_body['port']['binding:host_id'] = link_info['hostname']
|
update_port_attrs['binding:host_id'] = link_info['hostname']
|
||||||
|
|
||||||
# TODO(hamdyk): use portbindings.VNIC_SMARTNIC from neutron-lib
|
# TODO(hamdyk): use portbindings.VNIC_SMARTNIC from neutron-lib
|
||||||
port_body['port']['binding:vnic_type'] = VNIC_SMARTNIC
|
port_attrs['binding:vnic_type'] = VNIC_SMARTNIC
|
||||||
|
|
||||||
client_id = ironic_port.extra.get('client-id')
|
client_id = ironic_port.extra.get('client-id')
|
||||||
if client_id:
|
if client_id:
|
||||||
client_id_opt = {'opt_name': DHCP_CLIENT_ID,
|
extra_dhcp_opts = port_attrs.get('extra_dhcp_opts', [])
|
||||||
'opt_value': client_id}
|
extra_dhcp_opts.append(
|
||||||
extra_dhcp_opts = port_body['port'].get('extra_dhcp_opts', [])
|
{'opt_name': DHCP_CLIENT_ID, 'opt_value': client_id})
|
||||||
extra_dhcp_opts.append(client_id_opt)
|
port_attrs['extra_dhcp_opts'] = extra_dhcp_opts
|
||||||
port_body['port']['extra_dhcp_opts'] = extra_dhcp_opts
|
|
||||||
try:
|
try:
|
||||||
if is_smart_nic:
|
if is_smart_nic:
|
||||||
wait_for_host_agent(
|
wait_for_host_agent(
|
||||||
client, update_port_body['port']['binding:host_id'])
|
client, update_port_attrs['binding:host_id'])
|
||||||
port = client.create_port(port_body)
|
port = client.create_port(**port_attrs)
|
||||||
update_neutron_port(task.context, port['port']['id'],
|
update_neutron_port(task.context, port.id, update_port_attrs)
|
||||||
update_port_body)
|
|
||||||
if CONF.neutron.dhcpv6_stateful_address_count > 1:
|
if CONF.neutron.dhcpv6_stateful_address_count > 1:
|
||||||
_add_ip_addresses_for_ipv6_stateful(task.context, port, client)
|
_add_ip_addresses_for_ipv6_stateful(task.context, port, client)
|
||||||
if is_smart_nic:
|
if is_smart_nic:
|
||||||
wait_for_port_status(client, port['port']['id'], 'ACTIVE')
|
wait_for_port_status(client, port.id, 'ACTIVE')
|
||||||
except neutron_exceptions.NeutronClientException as e:
|
except openstack_exc.OpenStackCloudException as e:
|
||||||
failures.append(ironic_port.uuid)
|
failures.append(ironic_port.uuid)
|
||||||
LOG.warning("Could not create neutron port for node's "
|
LOG.warning("Could not create neutron port for node's "
|
||||||
"%(node)s port %(ir-port)s on the neutron "
|
"%(node)s port %(ir-port)s on the neutron "
|
||||||
@ -384,7 +355,7 @@ def add_ports_to_network(task, network_uuid, security_groups=None):
|
|||||||
{'net': network_uuid, 'node': node.uuid,
|
{'net': network_uuid, 'node': node.uuid,
|
||||||
'ir-port': ironic_port.uuid, 'exc': e})
|
'ir-port': ironic_port.uuid, 'exc': e})
|
||||||
else:
|
else:
|
||||||
ports[ironic_port.uuid] = port['port']['id']
|
ports[ironic_port.uuid] = port.id
|
||||||
|
|
||||||
if failures:
|
if failures:
|
||||||
if len(failures) == len(ports_to_create):
|
if len(failures) == len(ports_to_create):
|
||||||
@ -439,15 +410,14 @@ def remove_neutron_ports(task, params):
|
|||||||
node_uuid = task.node.uuid
|
node_uuid = task.node.uuid
|
||||||
|
|
||||||
try:
|
try:
|
||||||
response = client.list_ports(**params)
|
ports = client.ports(**params)
|
||||||
except neutron_exceptions.NeutronClientException as e:
|
except openstack_exc.OpenStackCloudException as e:
|
||||||
msg = (_('Could not get given network VIF for %(node)s '
|
msg = (_('Could not get given network VIF for %(node)s '
|
||||||
'from neutron, possible network issue. %(exc)s') %
|
'from neutron, possible network issue. %(exc)s') %
|
||||||
{'node': node_uuid, 'exc': e})
|
{'node': node_uuid, 'exc': e})
|
||||||
LOG.exception(msg)
|
LOG.exception(msg)
|
||||||
raise exception.NetworkError(msg)
|
raise exception.NetworkError(msg)
|
||||||
|
|
||||||
ports = response.get('ports', [])
|
|
||||||
if not ports:
|
if not ports:
|
||||||
LOG.debug('No ports to remove for node %s', node_uuid)
|
LOG.debug('No ports to remove for node %s', node_uuid)
|
||||||
return
|
return
|
||||||
@ -460,14 +430,14 @@ def remove_neutron_ports(task, params):
|
|||||||
if is_smartnic_port(port):
|
if is_smartnic_port(port):
|
||||||
wait_for_host_agent(client, port['binding:host_id'])
|
wait_for_host_agent(client, port['binding:host_id'])
|
||||||
try:
|
try:
|
||||||
client.delete_port(port['id'])
|
client.delete_port(port)
|
||||||
# NOTE(mgoddard): Ignore if the port was deleted by nova.
|
# NOTE(mgoddard): Ignore if the port was deleted by nova.
|
||||||
except neutron_exceptions.PortNotFoundClient:
|
except openstack_exc.ResourceNotFound:
|
||||||
LOG.info('Port %s was not found while deleting.', port['id'])
|
LOG.info('Port %s was not found while deleting.', port.id)
|
||||||
except neutron_exceptions.NeutronClientException as e:
|
except openstack_exc.OpenStackCloudException as e:
|
||||||
msg = (_('Could not remove VIF %(vif)s of node %(node)s, possibly '
|
msg = (_('Could not remove VIF %(vif)s of node %(node)s, possibly '
|
||||||
'a network issue: %(exc)s') %
|
'a network issue: %(exc)s') %
|
||||||
{'vif': port['id'], 'node': node_uuid, 'exc': e})
|
{'vif': port.id, 'node': node_uuid, 'exc': e})
|
||||||
LOG.exception(msg)
|
LOG.exception(msg)
|
||||||
raise exception.NetworkError(msg)
|
raise exception.NetworkError(msg)
|
||||||
|
|
||||||
@ -508,11 +478,9 @@ def get_neutron_port_data(port_id, vif_id, client=None, context=None):
|
|||||||
client = get_client(context=context)
|
client = get_client(context=context)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
port_config = client.show_port(
|
port_config = client.get_port(vif_id)
|
||||||
vif_id, fields=['id', 'name', 'dns_assignment', 'fixed_ips',
|
|
||||||
'mac_address', 'network_id'])
|
|
||||||
|
|
||||||
except neutron_exceptions.NeutronClientException as e:
|
except openstack_exc.OpenStackCloudException as e:
|
||||||
msg = (_('Unable to get port info for %(port_id)s. Error: '
|
msg = (_('Unable to get port info for %(port_id)s. Error: '
|
||||||
'%(err)s') % {'port_id': vif_id, 'err': e})
|
'%(err)s') % {'port_id': vif_id, 'err': e})
|
||||||
LOG.exception(msg)
|
LOG.exception(msg)
|
||||||
@ -521,17 +489,14 @@ def get_neutron_port_data(port_id, vif_id, client=None, context=None):
|
|||||||
LOG.debug('Received port %(port)s data: %(info)s',
|
LOG.debug('Received port %(port)s data: %(info)s',
|
||||||
{'port': vif_id, 'info': port_config})
|
{'port': vif_id, 'info': port_config})
|
||||||
|
|
||||||
port_config = port_config['port']
|
|
||||||
|
|
||||||
port_id = port_config['name'] or port_id
|
port_id = port_config['name'] or port_id
|
||||||
|
|
||||||
network_id = port_config.get('network_id')
|
network_id = port_config.network_id
|
||||||
|
|
||||||
try:
|
try:
|
||||||
network_config = client.show_network(
|
network_config = client.get_network(network_id)
|
||||||
network_id, fields=['id', 'mtu', 'subnets'])
|
|
||||||
|
|
||||||
except neutron_exceptions.NeutronClientException as e:
|
except openstack_exc.OpenStackCloudException as e:
|
||||||
msg = (_('Unable to get network info for %(network_id)s. Error: '
|
msg = (_('Unable to get network info for %(network_id)s. Error: '
|
||||||
'%(err)s') % {'network_id': network_id, 'err': e})
|
'%(err)s') % {'network_id': network_id, 'err': e})
|
||||||
LOG.exception(msg)
|
LOG.exception(msg)
|
||||||
@ -540,8 +505,6 @@ def get_neutron_port_data(port_id, vif_id, client=None, context=None):
|
|||||||
LOG.debug('Received network %(network)s data: %(info)s',
|
LOG.debug('Received network %(network)s data: %(info)s',
|
||||||
{'network': network_id, 'info': network_config})
|
{'network': network_id, 'info': network_config})
|
||||||
|
|
||||||
network_config = network_config['network']
|
|
||||||
|
|
||||||
subnets_config = {}
|
subnets_config = {}
|
||||||
|
|
||||||
network_data = {
|
network_data = {
|
||||||
@ -563,17 +526,14 @@ def get_neutron_port_data(port_id, vif_id, client=None, context=None):
|
|||||||
subnet_id = fixed_ip['subnet_id']
|
subnet_id = fixed_ip['subnet_id']
|
||||||
|
|
||||||
try:
|
try:
|
||||||
subnet_config = client.show_subnet(
|
subnet_config = client.get_subnet(subnet_id)
|
||||||
subnet_id, fields=['id', 'name', 'enable_dhcp',
|
|
||||||
'dns_nameservers', 'host_routes',
|
|
||||||
'ip_version', 'gateway_ip', 'cidr'])
|
|
||||||
|
|
||||||
LOG.debug('Received subnet %(subnet)s data: %(info)s',
|
LOG.debug('Received subnet %(subnet)s data: %(info)s',
|
||||||
{'subnet': subnet_id, 'info': subnet_config})
|
{'subnet': subnet_id, 'info': subnet_config})
|
||||||
|
|
||||||
subnets_config[subnet_id] = subnet_config['subnet']
|
subnets_config[subnet_id] = subnet_config
|
||||||
|
|
||||||
except neutron_exceptions.NeutronClientException as e:
|
except openstack_exc.OpenStackCloudException as e:
|
||||||
msg = (_('Unable to get subnet info for %(subnet_id)s. Error: '
|
msg = (_('Unable to get subnet info for %(subnet_id)s. Error: '
|
||||||
'%(err)s') % {'subnet_id': subnet_id, 'err': e})
|
'%(err)s') % {'subnet_id': subnet_id, 'err': e})
|
||||||
LOG.exception(msg)
|
LOG.exception(msg)
|
||||||
@ -582,7 +542,7 @@ def get_neutron_port_data(port_id, vif_id, client=None, context=None):
|
|||||||
subnet_config = subnets_config[subnet_id]
|
subnet_config = subnets_config[subnet_id]
|
||||||
|
|
||||||
subnet_network, netmask = _uncidr(
|
subnet_network, netmask = _uncidr(
|
||||||
subnet_config['cidr'], subnet_config['ip_version'] == 6)
|
subnet_config.cidr, subnet_config.ip_version == 6)
|
||||||
|
|
||||||
network = {
|
network = {
|
||||||
'id': fixed_ip['subnet_id'],
|
'id': fixed_ip['subnet_id'],
|
||||||
@ -728,8 +688,9 @@ def validate_network(uuid_or_name, net_type=_('network'), context=None):
|
|||||||
|
|
||||||
client = get_client(context=context)
|
client = get_client(context=context)
|
||||||
network = _get_network_by_uuid_or_name(client, uuid_or_name,
|
network = _get_network_by_uuid_or_name(client, uuid_or_name,
|
||||||
net_type=net_type, fields=['id'])
|
net_type=net_type)
|
||||||
return network['id']
|
|
||||||
|
return network.id
|
||||||
|
|
||||||
|
|
||||||
def validate_port_info(node, port):
|
def validate_port_info(node, port):
|
||||||
@ -781,12 +742,12 @@ def _validate_agent(client, **kwargs):
|
|||||||
:raises: NetworkError in case of failure contacting Neutron.
|
:raises: NetworkError in case of failure contacting Neutron.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
agents = client.list_agents(**kwargs)['agents']
|
agents = client.agents(**kwargs)
|
||||||
for agent in agents:
|
for agent in agents:
|
||||||
if agent['alive']:
|
if agent.is_alive:
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
except neutron_exceptions.NeutronClientException:
|
except openstack_exc.OpenStackCloudException:
|
||||||
raise exception.NetworkError('Failed to contact Neutron server')
|
raise exception.NetworkError('Failed to contact Neutron server')
|
||||||
|
|
||||||
|
|
||||||
@ -807,67 +768,58 @@ def is_smartnic_port(port_data):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def _get_network_by_uuid_or_name(client, uuid_or_name, net_type=_('network'),
|
def _get_network_by_uuid_or_name(client, uuid_or_name, net_type=_('network')):
|
||||||
**params):
|
|
||||||
"""Return a neutron network by UUID or name.
|
"""Return a neutron network by UUID or name.
|
||||||
|
|
||||||
:param client: A Neutron client object.
|
:param client: A Neutron client object.
|
||||||
:param uuid_or_name: network UUID or name
|
:param uuid_or_name: network UUID or name
|
||||||
:param net_type: human-readable network type for error messages
|
:param net_type: human-readable network type for error messages
|
||||||
:param params: Additional parameters to pass to the neutron client
|
|
||||||
list_networks method.
|
|
||||||
:returns: A dict describing the neutron network.
|
:returns: A dict describing the neutron network.
|
||||||
:raises: NetworkError on failure to contact Neutron
|
:raises: NetworkError on failure to contact Neutron
|
||||||
:raises: InvalidParameterValue for missing or duplicated network
|
:raises: InvalidParameterValue for missing or duplicated network
|
||||||
"""
|
"""
|
||||||
if uuidutils.is_uuid_like(uuid_or_name):
|
|
||||||
params['id'] = uuid_or_name
|
|
||||||
else:
|
|
||||||
params['name'] = uuid_or_name
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
networks = client.list_networks(**params)
|
network = client.find_network(uuid_or_name, ignore_missing=False)
|
||||||
except neutron_exceptions.NeutronClientException as exc:
|
except openstack_exc.DuplicateResource:
|
||||||
raise exception.NetworkError(_('Could not retrieve network list: %s') %
|
network_ids = [net.id for net in client.networks(name=uuid_or_name)]
|
||||||
exc)
|
|
||||||
|
|
||||||
LOG.debug('Got list of networks matching %(cond)s: %(result)s',
|
|
||||||
{'cond': params, 'result': networks})
|
|
||||||
networks = networks.get('networks', [])
|
|
||||||
if not networks:
|
|
||||||
raise exception.InvalidParameterValue(
|
|
||||||
_('%(type)s with name or UUID %(uuid_or_name)s was not found') %
|
|
||||||
{'type': net_type, 'uuid_or_name': uuid_or_name})
|
|
||||||
elif len(networks) > 1:
|
|
||||||
network_ids = [n['id'] for n in networks]
|
|
||||||
raise exception.InvalidParameterValue(
|
raise exception.InvalidParameterValue(
|
||||||
_('More than one %(type)s was found for name %(name)s: %(nets)s') %
|
_('More than one %(type)s was found for name %(name)s: %(nets)s') %
|
||||||
{'name': uuid_or_name, 'nets': ', '.join(network_ids),
|
{'name': uuid_or_name, 'nets': ', '.join(network_ids),
|
||||||
'type': net_type})
|
'type': net_type})
|
||||||
return networks[0]
|
except openstack_exc.ResourceNotFound:
|
||||||
|
raise exception.InvalidParameterValue(
|
||||||
|
_('%(type)s with name or UUID %(uuid_or_name)s was not found') %
|
||||||
|
{'type': net_type, 'uuid_or_name': uuid_or_name})
|
||||||
|
except openstack_exc.OpenStackCloudException as exc:
|
||||||
|
raise exception.NetworkError(_('Could not retrieve network: %s') % exc)
|
||||||
|
|
||||||
|
LOG.debug('Got network matching %(uuid_or_name)s: %(result)s',
|
||||||
|
{'uuid_or_name': uuid_or_name, 'result': network})
|
||||||
|
|
||||||
|
return network
|
||||||
|
|
||||||
|
|
||||||
def _get_port_by_uuid(client, port_uuid, **params):
|
def _get_port_by_uuid(client, port_uuid):
|
||||||
"""Return a neutron port by UUID.
|
"""Return a neutron port by UUID.
|
||||||
|
|
||||||
:param client: A Neutron client object.
|
:param client: A Neutron client object.
|
||||||
:param port_uuid: UUID of a Neutron port to query.
|
:param port_uuid: UUID of a Neutron port to query.
|
||||||
:param params: Additional parameters to pass to the neutron client
|
|
||||||
show_port method.
|
|
||||||
:returns: A dict describing the neutron port.
|
:returns: A dict describing the neutron port.
|
||||||
:raises: InvalidParameterValue if the port does not exist.
|
:raises: InvalidParameterValue if the port does not exist.
|
||||||
:raises: NetworkError on failure to contact Neutron.
|
:raises: NetworkError on failure to contact Neutron.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
port = client.show_port(port_uuid, **params)
|
port = client.get_port(port_uuid)
|
||||||
except neutron_exceptions.PortNotFoundClient:
|
except openstack_exc.ResourceNotFound:
|
||||||
raise exception.InvalidParameterValue(
|
raise exception.InvalidParameterValue(
|
||||||
_('Neutron port %(port_uuid)s was not found') %
|
_('Neutron port %(port_uuid)s was not found') %
|
||||||
{'port_uuid': port_uuid})
|
{'port_uuid': port_uuid})
|
||||||
except neutron_exceptions.NeutronClientException as exc:
|
except openstack_exc.OpenStackCloudException as exc:
|
||||||
raise exception.NetworkError(_('Could not retrieve neutron port: %s') %
|
raise exception.NetworkError(_('Could not retrieve neutron port: %s') %
|
||||||
exc)
|
exc)
|
||||||
return port['port']
|
|
||||||
|
return port
|
||||||
|
|
||||||
|
|
||||||
def get_physnets_by_port_uuid(client, port_uuid):
|
def get_physnets_by_port_uuid(client, port_uuid):
|
||||||
@ -882,27 +834,25 @@ def get_physnets_by_port_uuid(client, port_uuid):
|
|||||||
:raises: NetworkError if the network query fails.
|
:raises: NetworkError if the network query fails.
|
||||||
:raises: InvalidParameterValue for missing network.
|
:raises: InvalidParameterValue for missing network.
|
||||||
"""
|
"""
|
||||||
port = _get_port_by_uuid(client, port_uuid, fields=['network_id'])
|
port = _get_port_by_uuid(client, port_uuid)
|
||||||
network_uuid = port['network_id']
|
network_uuid = port.network_id
|
||||||
|
|
||||||
fields = [PHYSNET_PARAM_NAME, SEGMENTS_PARAM_NAME]
|
network = _get_network_by_uuid_or_name(client, network_uuid)
|
||||||
network = _get_network_by_uuid_or_name(client, network_uuid, fields=fields)
|
|
||||||
|
|
||||||
if SEGMENTS_PARAM_NAME in network:
|
if network.segments is not None:
|
||||||
# A network with multiple segments will have a 'segments' parameter
|
# A network with multiple segments will have a 'segments' parameter
|
||||||
# which will contain a list of segments. Each segment should have a
|
# which will contain a list of segments. Each segment should have a
|
||||||
# 'provider:physical_network' parameter which contains the physical
|
# 'provider:physical_network' parameter which contains the physical
|
||||||
# network of the segment.
|
# network of the segment.
|
||||||
segments = network[SEGMENTS_PARAM_NAME]
|
return set(segment[PHYSNET_PARAM_NAME]
|
||||||
|
for segment in network.segments
|
||||||
|
if segment[PHYSNET_PARAM_NAME])
|
||||||
else:
|
else:
|
||||||
# A network with a single segment will have a
|
# A network with a single segment will have a
|
||||||
# 'provider:physical_network' parameter which contains the network's
|
# 'provider:physical_network' parameter which contains the network's
|
||||||
# physical network.
|
# physical network.
|
||||||
segments = [network]
|
return (set([network.provider_physical_network])
|
||||||
|
if network.provider_physical_network else set())
|
||||||
return set(segment[PHYSNET_PARAM_NAME]
|
|
||||||
for segment in segments
|
|
||||||
if segment[PHYSNET_PARAM_NAME])
|
|
||||||
|
|
||||||
|
|
||||||
@retrying.retry(
|
@retrying.retry(
|
||||||
@ -963,10 +913,10 @@ def wait_for_port_status(client, port_id, status):
|
|||||||
"""
|
"""
|
||||||
LOG.debug('Validating Port %(port_id)s status is %(status)s',
|
LOG.debug('Validating Port %(port_id)s status is %(status)s',
|
||||||
{'port_id': port_id, 'status': status})
|
{'port_id': port_id, 'status': status})
|
||||||
port_info = _get_port_by_uuid(client, port_id)
|
port = _get_port_by_uuid(client, port_id)
|
||||||
LOG.debug('Port %(port_id)s status is: %(status)s',
|
LOG.debug('Port %(port_id)s status is: %(status)s',
|
||||||
{'port_id': port_id, 'status': port_info['status']})
|
{'port_id': port_id, 'status': port.status})
|
||||||
if port_info['status'] == status:
|
if port.status == status:
|
||||||
return True
|
return True
|
||||||
raise exception.NetworkError(
|
raise exception.NetworkError(
|
||||||
'Port %(port_id)s failed to reach status %(status)s' % {
|
'Port %(port_id)s failed to reach status %(status)s' % {
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
import copy
|
import copy
|
||||||
|
|
||||||
from keystoneauth1 import loading as kaloading
|
from keystoneauth1 import loading as ks_loading
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
from oslo_log import log
|
from oslo_log import log
|
||||||
|
|
||||||
@ -30,9 +30,9 @@ def register_auth_opts(conf, group, service_type=None):
|
|||||||
Registers only basic auth options shared by all auth plugins.
|
Registers only basic auth options shared by all auth plugins.
|
||||||
The rest are registered at runtime depending on auth plugin used.
|
The rest are registered at runtime depending on auth plugin used.
|
||||||
"""
|
"""
|
||||||
kaloading.register_session_conf_options(conf, group)
|
ks_loading.register_session_conf_options(conf, group)
|
||||||
kaloading.register_auth_conf_options(conf, group)
|
ks_loading.register_auth_conf_options(conf, group)
|
||||||
kaloading.register_adapter_conf_options(conf, group)
|
ks_loading.register_adapter_conf_options(conf, group)
|
||||||
conf.set_default('valid_interfaces', DEFAULT_VALID_INTERFACES, group=group)
|
conf.set_default('valid_interfaces', DEFAULT_VALID_INTERFACES, group=group)
|
||||||
# TODO(pas-ha) use os-service-type to try find the service_type by the
|
# TODO(pas-ha) use os-service-type to try find the service_type by the
|
||||||
# config group name assuming it is a project name (e.g. 'glance')
|
# config group name assuming it is a project name (e.g. 'glance')
|
||||||
@ -56,16 +56,16 @@ def add_auth_opts(options, service_type=None):
|
|||||||
opts.append(new_opt)
|
opts.append(new_opt)
|
||||||
|
|
||||||
opts = copy.deepcopy(options)
|
opts = copy.deepcopy(options)
|
||||||
opts.insert(0, kaloading.get_auth_common_conf_options()[0])
|
opts.insert(0, ks_loading.get_auth_common_conf_options()[0])
|
||||||
# NOTE(dims): There are a lot of auth plugins, we just generate
|
# NOTE(dims): There are a lot of auth plugins, we just generate
|
||||||
# the config options for a few common ones
|
# the config options for a few common ones
|
||||||
plugins = ['password', 'v2password', 'v3password']
|
plugins = ['password', 'v2password', 'v3password']
|
||||||
for name in plugins:
|
for name in plugins:
|
||||||
plugin = kaloading.get_plugin_loader(name)
|
plugin = ks_loading.get_plugin_loader(name)
|
||||||
add_options(opts, kaloading.get_auth_plugin_conf_options(plugin))
|
add_options(opts, ks_loading.get_auth_plugin_conf_options(plugin))
|
||||||
add_options(opts, kaloading.get_session_conf_options())
|
add_options(opts, ks_loading.get_session_conf_options())
|
||||||
if service_type:
|
if service_type:
|
||||||
adapter_opts = kaloading.get_adapter_conf_options(
|
adapter_opts = ks_loading.get_adapter_conf_options(
|
||||||
include_deprecated=False)
|
include_deprecated=False)
|
||||||
# adding defaults for valid interfaces
|
# adding defaults for valid interfaces
|
||||||
cfg.set_defaults(adapter_opts, service_type=service_type,
|
cfg.set_defaults(adapter_opts, service_type=service_type,
|
||||||
|
@ -29,7 +29,11 @@ opts = [
|
|||||||
cfg.IntOpt('retries',
|
cfg.IntOpt('retries',
|
||||||
default=3,
|
default=3,
|
||||||
mutable=True,
|
mutable=True,
|
||||||
help=_('Client retries in the case of a failed request.')),
|
deprecated_for_removal=True,
|
||||||
|
deprecated_reason=_('Replaced by status_code_retries and '
|
||||||
|
'status_code_retry_delay.'),
|
||||||
|
help=_('DEPRECATED: Client retries in the case of a failed '
|
||||||
|
'request.')),
|
||||||
cfg.StrOpt('cleaning_network',
|
cfg.StrOpt('cleaning_network',
|
||||||
mutable=True,
|
mutable=True,
|
||||||
help=_('Neutron network UUID or name for the ramdisk to be '
|
help=_('Neutron network UUID or name for the ramdisk to be '
|
||||||
|
@ -96,10 +96,10 @@ def update_opt_defaults():
|
|||||||
'eventlet.wsgi.server=INFO',
|
'eventlet.wsgi.server=INFO',
|
||||||
'iso8601=WARNING',
|
'iso8601=WARNING',
|
||||||
'requests=WARNING',
|
'requests=WARNING',
|
||||||
'neutronclient=WARNING',
|
|
||||||
'glanceclient=WARNING',
|
'glanceclient=WARNING',
|
||||||
'urllib3.connectionpool=WARNING',
|
'urllib3.connectionpool=WARNING',
|
||||||
'keystonemiddleware.auth_token=INFO',
|
'keystonemiddleware.auth_token=INFO',
|
||||||
'keystoneauth.session=INFO',
|
'keystoneauth.session=INFO',
|
||||||
|
'openstack=WARNING',
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
import ipaddress
|
import ipaddress
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from neutronclient.common import exceptions as neutron_client_exc
|
from openstack.connection import exceptions as openstack_exc
|
||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
|
|
||||||
from ironic.common import exception
|
from ironic.common import exception
|
||||||
@ -62,11 +62,10 @@ class NeutronDHCPApi(base.BaseDHCP):
|
|||||||
super(NeutronDHCPApi, self).update_port_dhcp_opts(
|
super(NeutronDHCPApi, self).update_port_dhcp_opts(
|
||||||
port_id, dhcp_options, token=token, context=context)
|
port_id, dhcp_options, token=token, context=context)
|
||||||
try:
|
try:
|
||||||
neutron_client = neutron.get_client(token=token,
|
neutron_client = neutron.get_client(token=token, context=context)
|
||||||
context=context)
|
|
||||||
|
|
||||||
fip = None
|
fip = None
|
||||||
port = neutron_client.show_port(port_id).get('port')
|
port = neutron_client.get_port(port_id)
|
||||||
try:
|
try:
|
||||||
if port:
|
if port:
|
||||||
# TODO(TheJulia): We need to retool this down the
|
# TODO(TheJulia): We need to retool this down the
|
||||||
@ -90,9 +89,9 @@ class NeutronDHCPApi(base.BaseDHCP):
|
|||||||
else:
|
else:
|
||||||
LOG.error('Requested to update port for port %s, '
|
LOG.error('Requested to update port for port %s, '
|
||||||
'however port lacks an IP address.', port_id)
|
'however port lacks an IP address.', port_id)
|
||||||
port_req_body = {'port': {'extra_dhcp_opts': update_opts}}
|
port_attrs = {'extra_dhcp_opts': update_opts}
|
||||||
neutron.update_neutron_port(context, port_id, port_req_body)
|
neutron.update_neutron_port(context, port_id, port_attrs)
|
||||||
except neutron_client_exc.NeutronClientException:
|
except openstack_exc.OpenStackCloudException:
|
||||||
LOG.exception("Failed to update Neutron port %s.", port_id)
|
LOG.exception("Failed to update Neutron port %s.", port_id)
|
||||||
raise exception.FailedToUpdateDHCPOptOnPort(port_id=port_id)
|
raise exception.FailedToUpdateDHCPOptOnPort(port_id=port_id)
|
||||||
|
|
||||||
@ -160,10 +159,10 @@ class NeutronDHCPApi(base.BaseDHCP):
|
|||||||
LOG.debug("Waiting %d seconds for Neutron.", port_delay)
|
LOG.debug("Waiting %d seconds for Neutron.", port_delay)
|
||||||
time.sleep(port_delay)
|
time.sleep(port_delay)
|
||||||
|
|
||||||
def _get_fixed_ip_address(self, port_uuid, client):
|
def _get_fixed_ip_address(self, port_id, client):
|
||||||
"""Get a Neutron port's fixed ip address.
|
"""Get a Neutron port's fixed ip address.
|
||||||
|
|
||||||
:param port_uuid: Neutron port id.
|
:param port_id: Neutron port id.
|
||||||
:param client: Neutron client instance.
|
:param client: Neutron client instance.
|
||||||
:returns: Neutron port ip address.
|
:returns: Neutron port ip address.
|
||||||
:raises: NetworkError
|
:raises: NetworkError
|
||||||
@ -172,10 +171,10 @@ class NeutronDHCPApi(base.BaseDHCP):
|
|||||||
"""
|
"""
|
||||||
ip_address = None
|
ip_address = None
|
||||||
try:
|
try:
|
||||||
neutron_port = client.show_port(port_uuid).get('port')
|
neutron_port = client.get_port(port_id)
|
||||||
except neutron_client_exc.NeutronClientException:
|
except openstack_exc.OpenStackCloudException:
|
||||||
raise exception.NetworkError(
|
raise exception.NetworkError(
|
||||||
_('Could not retrieve neutron port: %s') % port_uuid)
|
_('Could not retrieve neutron port: %s') % port_id)
|
||||||
|
|
||||||
fixed_ips = neutron_port.get('fixed_ips')
|
fixed_ips = neutron_port.get('fixed_ips')
|
||||||
|
|
||||||
@ -192,18 +191,18 @@ class NeutronDHCPApi(base.BaseDHCP):
|
|||||||
return ip_address
|
return ip_address
|
||||||
else:
|
else:
|
||||||
LOG.error("Neutron returned invalid IP "
|
LOG.error("Neutron returned invalid IP "
|
||||||
"address %(ip_address)s on port %(port_uuid)s.",
|
"address %(ip_address)s on port %(port_id)s.",
|
||||||
{'ip_address': ip_address,
|
{'ip_address': ip_address, 'port_id': port_id})
|
||||||
'port_uuid': port_uuid})
|
|
||||||
raise exception.InvalidIPAddress(ip_address=ip_address)
|
raise exception.InvalidIPv4Address(ip_address=ip_address)
|
||||||
except ValueError as exc:
|
except ValueError as exc:
|
||||||
LOG.error("An Invalid IP address was supplied and failed "
|
LOG.error("An Invalid IP address was supplied and failed "
|
||||||
"basic validation: %s", exc)
|
"basic validation: %s", exc)
|
||||||
raise exception.InvalidIPAddress(ip_address=ip_address)
|
raise exception.InvalidIPAddress(ip_address=ip_address)
|
||||||
else:
|
else:
|
||||||
LOG.error("No IP address assigned to Neutron port %s.",
|
LOG.error("No IP address assigned to Neutron port %s.",
|
||||||
port_uuid)
|
port_id)
|
||||||
raise exception.FailedToGetIPAddressOnPort(port_id=port_uuid)
|
raise exception.FailedToGetIPAddressOnPort(port_id=port_id)
|
||||||
|
|
||||||
def _get_port_ip_address(self, task, p_obj, client):
|
def _get_port_ip_address(self, task, p_obj, client):
|
||||||
"""Get ip address of ironic port/portgroup assigned by Neutron.
|
"""Get ip address of ironic port/portgroup assigned by Neutron.
|
||||||
@ -244,8 +243,7 @@ class NeutronDHCPApi(base.BaseDHCP):
|
|||||||
ip_addresses = []
|
ip_addresses = []
|
||||||
for obj in pobj_list:
|
for obj in pobj_list:
|
||||||
try:
|
try:
|
||||||
vif_ip_address = self._get_port_ip_address(task, obj,
|
vif_ip_address = self._get_port_ip_address(task, obj, client)
|
||||||
client)
|
|
||||||
ip_addresses.append(vif_ip_address)
|
ip_addresses.append(vif_ip_address)
|
||||||
except (exception.FailedToGetIPAddressOnPort,
|
except (exception.FailedToGetIPAddressOnPort,
|
||||||
exception.InvalidIPv4Address,
|
exception.InvalidIPv4Address,
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
|
|
||||||
import collections
|
import collections
|
||||||
|
|
||||||
from neutronclient.common import exceptions as neutron_exceptions
|
from openstack.connection import exceptions as openstack_exc
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
from oslo_log import log
|
from oslo_log import log
|
||||||
|
|
||||||
@ -267,47 +267,40 @@ def plug_port_to_tenant_network(task, port_like_obj, client=None):
|
|||||||
# NOTE(sambetts) Only update required binding: attributes,
|
# NOTE(sambetts) Only update required binding: attributes,
|
||||||
# because other port attributes may have been set by the user or
|
# because other port attributes may have been set by the user or
|
||||||
# nova.
|
# nova.
|
||||||
body = {
|
port_attrs = {'binding:vnic_type': neutron.VNIC_BAREMETAL,
|
||||||
'port': {
|
'binding:host_id': node.uuid,
|
||||||
'binding:vnic_type': neutron.VNIC_BAREMETAL,
|
'mac_address': port_like_obj.address}
|
||||||
'binding:host_id': node.uuid,
|
|
||||||
'mac_address': port_like_obj.address
|
|
||||||
}
|
|
||||||
}
|
|
||||||
binding_profile = {'local_link_information': local_link_info}
|
binding_profile = {'local_link_information': local_link_info}
|
||||||
if local_group_info:
|
if local_group_info:
|
||||||
binding_profile['local_group_information'] = local_group_info
|
binding_profile['local_group_information'] = local_group_info
|
||||||
body['port']['binding:profile'] = binding_profile
|
port_attrs['binding:profile'] = binding_profile
|
||||||
|
|
||||||
if client_id_opt:
|
if client_id_opt:
|
||||||
body['port']['extra_dhcp_opts'] = [client_id_opt]
|
port_attrs['extra_dhcp_opts'] = [client_id_opt]
|
||||||
|
|
||||||
is_smart_nic = neutron.is_smartnic_port(port_like_obj)
|
is_smart_nic = neutron.is_smartnic_port(port_like_obj)
|
||||||
if is_smart_nic:
|
if is_smart_nic:
|
||||||
link_info = local_link_info[0]
|
link_info = local_link_info[0]
|
||||||
LOG.debug('Setting hostname as host_id in case of Smart NIC, '
|
LOG.debug('Setting hostname as host_id in case of Smart NIC, '
|
||||||
'port %(port_id)s, hostname %(hostname)s',
|
'port %(port_id)s, hostname %(hostname)s',
|
||||||
{'port_id': vif_id,
|
{'port_id': vif_id, 'hostname': link_info['hostname']})
|
||||||
'hostname': link_info['hostname']})
|
port_attrs['binding:host_id'] = link_info['hostname']
|
||||||
body['port']['binding:host_id'] = link_info['hostname']
|
port_attrs['binding:vnic_type'] = neutron.VNIC_SMARTNIC
|
||||||
body['port']['binding:vnic_type'] = neutron.VNIC_SMARTNIC
|
|
||||||
|
|
||||||
if not client:
|
if not client:
|
||||||
client = neutron.get_client(context=task.context)
|
client = neutron.get_client(context=task.context)
|
||||||
|
|
||||||
if is_smart_nic:
|
if is_smart_nic:
|
||||||
neutron.wait_for_host_agent(client, body['port']['binding:host_id'])
|
neutron.wait_for_host_agent(client, port_attrs['binding:host_id'])
|
||||||
|
|
||||||
try:
|
try:
|
||||||
neutron.update_neutron_port(task.context, vif_id, body)
|
neutron.update_neutron_port(task.context, vif_id, port_attrs)
|
||||||
if is_smart_nic:
|
if is_smart_nic:
|
||||||
neutron.wait_for_port_status(client, vif_id, 'ACTIVE')
|
neutron.wait_for_port_status(client, vif_id, 'ACTIVE')
|
||||||
except neutron_exceptions.ConnectionFailed as e:
|
except openstack_exc.OpenStackCloudException as e:
|
||||||
msg = (_('Could not add public network VIF %(vif)s '
|
msg = (_('Could not add public network VIF %(vif)s '
|
||||||
'to node %(node)s, possible network issue. %(exc)s') %
|
'to node %(node)s, possible network issue. %(exc)s') %
|
||||||
{'vif': vif_id,
|
{'vif': vif_id, 'node': node.uuid, 'exc': e})
|
||||||
'node': node.uuid,
|
|
||||||
'exc': e})
|
|
||||||
LOG.error(msg)
|
LOG.error(msg)
|
||||||
raise exception.NetworkError(msg)
|
raise exception.NetworkError(msg)
|
||||||
|
|
||||||
@ -467,8 +460,7 @@ class NeutronVIFPortIDMixin(VIFPortIDMixin):
|
|||||||
original_port = objects.Port.get_by_id(context, port_obj.id)
|
original_port = objects.Port.get_by_id(context, port_obj.id)
|
||||||
updated_client_id = port_obj.extra.get('client-id')
|
updated_client_id = port_obj.extra.get('client-id')
|
||||||
|
|
||||||
if (original_port.extra.get('client-id')
|
if original_port.extra.get('client-id') != updated_client_id:
|
||||||
!= updated_client_id):
|
|
||||||
# DHCP Option with opt_value=None will remove it
|
# DHCP Option with opt_value=None will remove it
|
||||||
# from the neutron port
|
# from the neutron port
|
||||||
if vif:
|
if vif:
|
||||||
@ -485,8 +477,7 @@ class NeutronVIFPortIDMixin(VIFPortIDMixin):
|
|||||||
"No VIF found for instance %(instance)s "
|
"No VIF found for instance %(instance)s "
|
||||||
"port %(port)s when attempting to update port "
|
"port %(port)s when attempting to update port "
|
||||||
"client-id.",
|
"client-id.",
|
||||||
{'port': port_uuid,
|
{'port': port_uuid, 'instance': node.instance_uuid})
|
||||||
'instance': node.instance_uuid})
|
|
||||||
|
|
||||||
if portgroup_obj and ((set(port_obj.obj_what_changed())
|
if portgroup_obj and ((set(port_obj.obj_what_changed())
|
||||||
& {'pxe_enabled', 'portgroup_id'}) or vif):
|
& {'pxe_enabled', 'portgroup_id'}) or vif):
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
Flat network interface. Useful for shared, flat networks.
|
Flat network interface. Useful for shared, flat networks.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from neutronclient.common import exceptions as neutron_exceptions
|
from openstack.connection import exceptions as openstack_exc
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
from oslo_log import log
|
from oslo_log import log
|
||||||
|
|
||||||
@ -62,17 +62,13 @@ class FlatNetwork(common.NeutronVIFPortIDMixin,
|
|||||||
)
|
)
|
||||||
if not vif_port_id:
|
if not vif_port_id:
|
||||||
continue
|
continue
|
||||||
body = {
|
port_attrs = {'binding:host_id': task.node.uuid,
|
||||||
'port': {
|
'binding:vnic_type': neutron.VNIC_BAREMETAL,
|
||||||
'binding:host_id': task.node.uuid,
|
'mac_address': port_like_obj.address}
|
||||||
'binding:vnic_type': neutron.VNIC_BAREMETAL,
|
|
||||||
'mac_address': port_like_obj.address
|
|
||||||
}
|
|
||||||
}
|
|
||||||
try:
|
try:
|
||||||
neutron.update_neutron_port(task.context,
|
neutron.update_neutron_port(task.context,
|
||||||
vif_port_id, body)
|
vif_port_id, port_attrs)
|
||||||
except neutron_exceptions.NeutronClientException as e:
|
except openstack_exc.OpenStackCloudException as e:
|
||||||
msg = (_('Unable to set binding:host_id for '
|
msg = (_('Unable to set binding:host_id for '
|
||||||
'neutron port %(port_id)s. Error: '
|
'neutron port %(port_id)s. Error: '
|
||||||
'%(err)s') % {'port_id': vif_port_id, 'err': e})
|
'%(err)s') % {'port_id': vif_port_id, 'err': e})
|
||||||
|
@ -21,7 +21,7 @@ from unittest import mock
|
|||||||
|
|
||||||
from glanceclient import client as glance_client
|
from glanceclient import client as glance_client
|
||||||
from glanceclient import exc as glance_exc
|
from glanceclient import exc as glance_exc
|
||||||
from keystoneauth1 import loading as kaloading
|
from keystoneauth1 import loading as ks_loading
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
from oslo_utils import uuidutils
|
from oslo_utils import uuidutils
|
||||||
import retrying
|
import retrying
|
||||||
@ -353,8 +353,8 @@ class CheckImageServiceTestCase(base.TestCase):
|
|||||||
self.context = context.RequestContext(global_request_id='global')
|
self.context = context.RequestContext(global_request_id='global')
|
||||||
self.service = image_service.GlanceImageService(None, self.context)
|
self.service = image_service.GlanceImageService(None, self.context)
|
||||||
# NOTE(pas-ha) register keystoneauth dynamic options manually
|
# NOTE(pas-ha) register keystoneauth dynamic options manually
|
||||||
plugin = kaloading.get_plugin_loader('password')
|
plugin = ks_loading.get_plugin_loader('password')
|
||||||
opts = kaloading.get_auth_plugin_conf_options(plugin)
|
opts = ks_loading.get_auth_plugin_conf_options(plugin)
|
||||||
self.cfg_fixture.register_opts(opts, group='glance')
|
self.cfg_fixture.register_opts(opts, group='glance')
|
||||||
self.config(auth_type='password',
|
self.config(auth_type='password',
|
||||||
auth_url='viking',
|
auth_url='viking',
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
from unittest import mock
|
from unittest import mock
|
||||||
|
|
||||||
from keystoneauth1 import loading as kaloading
|
from keystoneauth1 import loading as ks_loading
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
from oslo_config import fixture
|
from oslo_config import fixture
|
||||||
|
|
||||||
@ -38,8 +38,8 @@ class KeystoneTestCase(base.TestCase):
|
|||||||
# NOTE(pas-ha) this is due to auth_plugin options
|
# NOTE(pas-ha) this is due to auth_plugin options
|
||||||
# being dynamically registered on first load,
|
# being dynamically registered on first load,
|
||||||
# but we need to set the config before
|
# but we need to set the config before
|
||||||
plugin = kaloading.get_plugin_loader('password')
|
plugin = ks_loading.get_plugin_loader('password')
|
||||||
opts = kaloading.get_auth_plugin_conf_options(plugin)
|
opts = ks_loading.get_auth_plugin_conf_options(plugin)
|
||||||
self.cfg_fixture.register_opts(opts, group=self.test_group)
|
self.cfg_fixture.register_opts(opts, group=self.test_group)
|
||||||
self.config(auth_url='http://127.0.0.1:9898',
|
self.config(auth_url='http://127.0.0.1:9898',
|
||||||
username='fake_user',
|
username='fake_user',
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -12,7 +12,7 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
from keystoneauth1 import loading as kaloading
|
from keystoneauth1 import loading as ks_loading
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
|
|
||||||
from ironic.conf import auth as ironic_auth
|
from ironic.conf import auth as ironic_auth
|
||||||
@ -31,8 +31,8 @@ class AuthConfTestCase(base.TestCase):
|
|||||||
# NOTE(pas-ha) this is due to auth_plugin options
|
# NOTE(pas-ha) this is due to auth_plugin options
|
||||||
# being dynamically registered on first load,
|
# being dynamically registered on first load,
|
||||||
# but we need to set the config before
|
# but we need to set the config before
|
||||||
plugin = kaloading.get_plugin_loader('password')
|
plugin = ks_loading.get_plugin_loader('password')
|
||||||
opts = kaloading.get_auth_plugin_conf_options(plugin)
|
opts = ks_loading.get_auth_plugin_conf_options(plugin)
|
||||||
self.cfg_fixture.register_opts(opts, group=self.test_group)
|
self.cfg_fixture.register_opts(opts, group=self.test_group)
|
||||||
self.config(auth_url='http://127.0.0.1:9898',
|
self.config(auth_url='http://127.0.0.1:9898',
|
||||||
username='fake_user',
|
username='fake_user',
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
from unittest import mock
|
from unittest import mock
|
||||||
|
|
||||||
from neutronclient.common import exceptions as neutron_client_exc
|
from openstack.connection import exceptions as openstack_exc
|
||||||
from oslo_utils import uuidutils
|
from oslo_utils import uuidutils
|
||||||
|
|
||||||
from ironic.common import dhcp_factory
|
from ironic.common import dhcp_factory
|
||||||
@ -59,7 +59,7 @@ class TestNeutron(db_base.DbTestCase):
|
|||||||
{'opt_name': 'server-ip-address',
|
{'opt_name': 'server-ip-address',
|
||||||
'opt_value': '1.1.1.1'}]
|
'opt_value': '1.1.1.1'}]
|
||||||
port_id = 'fake-port-id'
|
port_id = 'fake-port-id'
|
||||||
expected = {'port': {'extra_dhcp_opts': opts}}
|
expected = {'extra_dhcp_opts': opts}
|
||||||
port_data = {
|
port_data = {
|
||||||
"id": port_id,
|
"id": port_id,
|
||||||
"fixed_ips": [
|
"fixed_ips": [
|
||||||
@ -68,7 +68,7 @@ class TestNeutron(db_base.DbTestCase):
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
client_mock.return_value.show_port.return_value = {'port': port_data}
|
client_mock.return_value.get_port.return_value = port_data
|
||||||
|
|
||||||
api = dhcp_factory.DHCPFactory()
|
api = dhcp_factory.DHCPFactory()
|
||||||
with task_manager.acquire(self.context, self.node.uuid) as task:
|
with task_manager.acquire(self.context, self.node.uuid) as task:
|
||||||
@ -94,12 +94,13 @@ class TestNeutron(db_base.DbTestCase):
|
|||||||
'ip_version': 6}]
|
'ip_version': 6}]
|
||||||
port_id = 'fake-port-id'
|
port_id = 'fake-port-id'
|
||||||
expected = {
|
expected = {
|
||||||
'port': {
|
'extra_dhcp_opts': [
|
||||||
'extra_dhcp_opts': [{
|
{
|
||||||
'opt_name': 'bootfile-url',
|
'opt_name': 'bootfile-url',
|
||||||
'opt_value': 'tftp://::1/file.name',
|
'opt_value': 'tftp://::1/file.name',
|
||||||
'ip_version': 6}]
|
'ip_version': 6
|
||||||
}
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
port_data = {
|
port_data = {
|
||||||
"id": port_id,
|
"id": port_id,
|
||||||
@ -109,7 +110,7 @@ class TestNeutron(db_base.DbTestCase):
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
client_mock.return_value.show_port.return_value = {'port': port_data}
|
client_mock.return_value.get_port.return_value = port_data
|
||||||
|
|
||||||
api = dhcp_factory.DHCPFactory()
|
api = dhcp_factory.DHCPFactory()
|
||||||
with task_manager.acquire(self.context, self.node.uuid) as task:
|
with task_manager.acquire(self.context, self.node.uuid) as task:
|
||||||
@ -132,9 +133,8 @@ class TestNeutron(db_base.DbTestCase):
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
client_mock.return_value.show_port.return_value = {'port': port_data}
|
client_mock.return_value.get_port.return_value = port_data
|
||||||
update_mock.side_effect = (
|
update_mock.side_effect = openstack_exc.OpenStackCloudException()
|
||||||
neutron_client_exc.NeutronClientException())
|
|
||||||
|
|
||||||
api = dhcp_factory.DHCPFactory()
|
api = dhcp_factory.DHCPFactory()
|
||||||
with task_manager.acquire(self.context, self.node.uuid) as task:
|
with task_manager.acquire(self.context, self.node.uuid) as task:
|
||||||
@ -262,10 +262,10 @@ class TestNeutron(db_base.DbTestCase):
|
|||||||
"device_id": 'bece68a3-2f8b-4e66-9092-244493d6aba7',
|
"device_id": 'bece68a3-2f8b-4e66-9092-244493d6aba7',
|
||||||
}
|
}
|
||||||
fake_client = mock.Mock()
|
fake_client = mock.Mock()
|
||||||
fake_client.show_port.return_value = {'port': port_data}
|
fake_client.get_port.return_value = port_data
|
||||||
result = api._get_fixed_ip_address(port_id, fake_client)
|
result = api._get_fixed_ip_address(port_id, fake_client)
|
||||||
self.assertEqual(expected, result)
|
self.assertEqual(expected, result)
|
||||||
fake_client.show_port.assert_called_once_with(port_id)
|
fake_client.get_port.assert_called_once_with(port_id)
|
||||||
|
|
||||||
def test__get_fixed_ip_address_ipv6(self):
|
def test__get_fixed_ip_address_ipv6(self):
|
||||||
port_id = 'fake-port-id'
|
port_id = 'fake-port-id'
|
||||||
@ -286,10 +286,10 @@ class TestNeutron(db_base.DbTestCase):
|
|||||||
"device_id": 'bece68a3-2f8b-4e66-9092-244493d6aba7',
|
"device_id": 'bece68a3-2f8b-4e66-9092-244493d6aba7',
|
||||||
}
|
}
|
||||||
fake_client = mock.Mock()
|
fake_client = mock.Mock()
|
||||||
fake_client.show_port.return_value = {'port': port_data}
|
fake_client.get_port.return_value = port_data
|
||||||
result = api._get_fixed_ip_address(port_id, fake_client)
|
result = api._get_fixed_ip_address(port_id, fake_client)
|
||||||
self.assertEqual(expected, result)
|
self.assertEqual(expected, result)
|
||||||
fake_client.show_port.assert_called_once_with(port_id)
|
fake_client.get_port.assert_called_once_with(port_id)
|
||||||
|
|
||||||
def test__get_fixed_ip_address_invalid_ip(self):
|
def test__get_fixed_ip_address_invalid_ip(self):
|
||||||
port_id = 'fake-port-id'
|
port_id = 'fake-port-id'
|
||||||
@ -309,22 +309,23 @@ class TestNeutron(db_base.DbTestCase):
|
|||||||
"device_id": 'bece68a3-2f8b-4e66-9092-244493d6aba7',
|
"device_id": 'bece68a3-2f8b-4e66-9092-244493d6aba7',
|
||||||
}
|
}
|
||||||
fake_client = mock.Mock()
|
fake_client = mock.Mock()
|
||||||
fake_client.show_port.return_value = {'port': port_data}
|
fake_client.get_port.return_value = port_data
|
||||||
self.assertRaises(exception.InvalidIPAddress,
|
self.assertRaises(exception.InvalidIPAddress,
|
||||||
api._get_fixed_ip_address,
|
api._get_fixed_ip_address,
|
||||||
port_id, fake_client)
|
port_id, fake_client)
|
||||||
fake_client.show_port.assert_called_once_with(port_id)
|
fake_client.get_port.assert_called_once_with(port_id)
|
||||||
|
|
||||||
def test__get_fixed_ip_address_with_exception(self):
|
def test__get_fixed_ip_address_with_exception(self):
|
||||||
port_id = 'fake-port-id'
|
port_id = 'fake-port-id'
|
||||||
api = dhcp_factory.DHCPFactory().provider
|
api = dhcp_factory.DHCPFactory().provider
|
||||||
|
|
||||||
fake_client = mock.Mock()
|
fake_client = mock.Mock()
|
||||||
fake_client.show_port.side_effect = (
|
fake_client.get_port.side_effect = (
|
||||||
neutron_client_exc.NeutronClientException())
|
openstack_exc.OpenStackCloudException())
|
||||||
|
|
||||||
self.assertRaises(exception.NetworkError,
|
self.assertRaises(exception.NetworkError,
|
||||||
api._get_fixed_ip_address, port_id, fake_client)
|
api._get_fixed_ip_address, port_id, fake_client)
|
||||||
fake_client.show_port.assert_called_once_with(port_id)
|
fake_client.get_port.assert_called_once_with(port_id)
|
||||||
|
|
||||||
@mock.patch('ironic.dhcp.neutron.NeutronDHCPApi._get_fixed_ip_address',
|
@mock.patch('ironic.dhcp.neutron.NeutronDHCPApi._get_fixed_ip_address',
|
||||||
autospec=True)
|
autospec=True)
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
from unittest import mock
|
from unittest import mock
|
||||||
|
|
||||||
from neutronclient.common import exceptions as neutron_exceptions
|
from openstack.connection import exceptions as openstack_exc
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
from oslo_utils import uuidutils
|
from oslo_utils import uuidutils
|
||||||
|
|
||||||
@ -178,9 +178,9 @@ class TestFlatInterface(db_base.DbTestCase):
|
|||||||
utils.create_test_port(self.context, node_id=self.node.id,
|
utils.create_test_port(self.context, node_id=self.node.id,
|
||||||
address='52:54:00:cf:2d:33', extra=extra,
|
address='52:54:00:cf:2d:33', extra=extra,
|
||||||
uuid=uuidutils.generate_uuid())
|
uuid=uuidutils.generate_uuid())
|
||||||
exp_body = {'port': {'binding:host_id': self.node.uuid,
|
exp_body = {'binding:host_id': self.node.uuid,
|
||||||
'binding:vnic_type': neutron.VNIC_BAREMETAL,
|
'binding:vnic_type': neutron.VNIC_BAREMETAL,
|
||||||
'mac_address': '52:54:00:cf:2d:33'}}
|
'mac_address': '52:54:00:cf:2d:33'}
|
||||||
with task_manager.acquire(self.context, self.node.id) as task:
|
with task_manager.acquire(self.context, self.node.id) as task:
|
||||||
self.interface._bind_flat_ports(task)
|
self.interface._bind_flat_ports(task)
|
||||||
update_mock.assert_called_once_with(self.context, 'foo', exp_body)
|
update_mock.assert_called_once_with(self.context, 'foo', exp_body)
|
||||||
@ -194,12 +194,12 @@ class TestFlatInterface(db_base.DbTestCase):
|
|||||||
utils.create_test_port(
|
utils.create_test_port(
|
||||||
self.context, node_id=self.node.id, address='52:54:00:cf:2d:33',
|
self.context, node_id=self.node.id, address='52:54:00:cf:2d:33',
|
||||||
extra={'vif_port_id': 'bar'}, uuid=uuidutils.generate_uuid())
|
extra={'vif_port_id': 'bar'}, uuid=uuidutils.generate_uuid())
|
||||||
exp_body1 = {'port': {'binding:host_id': self.node.uuid,
|
exp_body1 = {'binding:host_id': self.node.uuid,
|
||||||
'binding:vnic_type': neutron.VNIC_BAREMETAL,
|
'binding:vnic_type': neutron.VNIC_BAREMETAL,
|
||||||
'mac_address': '52:54:00:cf:2d:33'}}
|
'mac_address': '52:54:00:cf:2d:33'}
|
||||||
exp_body2 = {'port': {'binding:host_id': self.node.uuid,
|
exp_body2 = {'binding:host_id': self.node.uuid,
|
||||||
'binding:vnic_type': neutron.VNIC_BAREMETAL,
|
'binding:vnic_type': neutron.VNIC_BAREMETAL,
|
||||||
'mac_address': '52:54:00:cf:2d:31'}}
|
'mac_address': '52:54:00:cf:2d:31'}
|
||||||
with task_manager.acquire(self.context, self.node.id) as task:
|
with task_manager.acquire(self.context, self.node.id) as task:
|
||||||
self.interface._bind_flat_ports(task)
|
self.interface._bind_flat_ports(task)
|
||||||
update_mock.assert_has_calls([
|
update_mock.assert_has_calls([
|
||||||
@ -235,7 +235,7 @@ class TestFlatInterface(db_base.DbTestCase):
|
|||||||
|
|
||||||
@mock.patch.object(neutron, 'update_neutron_port', autospec=True)
|
@mock.patch.object(neutron, 'update_neutron_port', autospec=True)
|
||||||
def test__bind_flat_ports_set_binding_host_id_raise(self, update_mock):
|
def test__bind_flat_ports_set_binding_host_id_raise(self, update_mock):
|
||||||
update_mock.side_effect = (neutron_exceptions.ConnectionFailed())
|
update_mock.side_effect = openstack_exc.OpenStackCloudException()
|
||||||
extra = {'vif_port_id': 'foo'}
|
extra = {'vif_port_id': 'foo'}
|
||||||
utils.create_test_port(self.context, node_id=self.node.id,
|
utils.create_test_port(self.context, node_id=self.node.id,
|
||||||
address='52:54:00:cf:2d:33', extra=extra,
|
address='52:54:00:cf:2d:33', extra=extra,
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
import copy
|
import copy
|
||||||
from unittest import mock
|
from unittest import mock
|
||||||
|
|
||||||
from neutronclient.common import exceptions as neutron_exceptions
|
from openstack.connection import exceptions as openstack_exc
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
from oslo_utils import uuidutils
|
from oslo_utils import uuidutils
|
||||||
|
|
||||||
@ -25,6 +25,7 @@ from ironic.drivers import base as drivers_base
|
|||||||
from ironic.drivers.modules.network import neutron
|
from ironic.drivers.modules.network import neutron
|
||||||
from ironic.tests.unit.db import base as db_base
|
from ironic.tests.unit.db import base as db_base
|
||||||
from ironic.tests.unit.objects import utils
|
from ironic.tests.unit.objects import utils
|
||||||
|
from ironic.tests.unit import stubs
|
||||||
|
|
||||||
CONF = cfg.CONF
|
CONF = cfg.CONF
|
||||||
CLIENT_ID1 = '20:00:55:04:01:fe:80:00:00:00:00:00:00:00:02:c9:02:00:23:13:92'
|
CLIENT_ID1 = '20:00:55:04:01:fe:80:00:00:00:00:00:00:00:02:c9:02:00:23:13:92'
|
||||||
@ -53,8 +54,9 @@ class NeutronInterfaceTestCase(db_base.DbTestCase):
|
|||||||
self.context, node_id=self.node.id,
|
self.context, node_id=self.node.id,
|
||||||
address='52:54:00:cf:2d:32',
|
address='52:54:00:cf:2d:32',
|
||||||
extra={'vif_port_id': uuidutils.generate_uuid()})
|
extra={'vif_port_id': uuidutils.generate_uuid()})
|
||||||
self.neutron_port = {'id': '132f871f-eaec-4fed-9475-0d54465e0f00',
|
self.neutron_port = stubs.FakeNeutronPort(
|
||||||
'mac_address': '52:54:00:cf:2d:32'}
|
id='132f871f-eaec-4fed-9475-0d54465e0f00',
|
||||||
|
mac_address='52:54:00:cf:2d:32')
|
||||||
|
|
||||||
@mock.patch('%s.vif_list' % VIFMIXINPATH, autospec=True)
|
@mock.patch('%s.vif_list' % VIFMIXINPATH, autospec=True)
|
||||||
def test_vif_list(self, mock_vif_list):
|
def test_vif_list(self, mock_vif_list):
|
||||||
@ -171,7 +173,7 @@ class NeutronInterfaceTestCase(db_base.DbTestCase):
|
|||||||
validate_mock):
|
validate_mock):
|
||||||
self.port.internal_info = {'provisioning_vif_port_id': 'vif-port-id'}
|
self.port.internal_info = {'provisioning_vif_port_id': 'vif-port-id'}
|
||||||
self.port.save()
|
self.port.save()
|
||||||
add_ports_mock.return_value = {self.port.uuid: self.neutron_port['id']}
|
add_ports_mock.return_value = {self.port.uuid: self.neutron_port.id}
|
||||||
with task_manager.acquire(self.context, self.node.id) as task:
|
with task_manager.acquire(self.context, self.node.id) as task:
|
||||||
self.interface.add_provisioning_network(task)
|
self.interface.add_provisioning_network(task)
|
||||||
rollback_mock.assert_called_once_with(
|
rollback_mock.assert_called_once_with(
|
||||||
@ -183,7 +185,7 @@ class NeutronInterfaceTestCase(db_base.DbTestCase):
|
|||||||
CONF.neutron.provisioning_network,
|
CONF.neutron.provisioning_network,
|
||||||
'provisioning network', context=task.context)
|
'provisioning network', context=task.context)
|
||||||
self.port.refresh()
|
self.port.refresh()
|
||||||
self.assertEqual(self.neutron_port['id'],
|
self.assertEqual(self.neutron_port.id,
|
||||||
self.port.internal_info['provisioning_vif_port_id'])
|
self.port.internal_info['provisioning_vif_port_id'])
|
||||||
|
|
||||||
@mock.patch.object(neutron_common, 'validate_network',
|
@mock.patch.object(neutron_common, 'validate_network',
|
||||||
@ -194,7 +196,7 @@ class NeutronInterfaceTestCase(db_base.DbTestCase):
|
|||||||
rollback_mock, validate_mock):
|
rollback_mock, validate_mock):
|
||||||
self.port.internal_info = {'provisioning_vif_port_id': 'vif-port-id'}
|
self.port.internal_info = {'provisioning_vif_port_id': 'vif-port-id'}
|
||||||
self.port.save()
|
self.port.save()
|
||||||
add_ports_mock.return_value = {self.port.uuid: self.neutron_port['id']}
|
add_ports_mock.return_value = {self.port.uuid: self.neutron_port.id}
|
||||||
# Make sure that changing the network UUID works
|
# Make sure that changing the network UUID works
|
||||||
for provisioning_network_uuid in [
|
for provisioning_network_uuid in [
|
||||||
'3aea0de6-4b92-44da-9aa0-52d134c83fdf',
|
'3aea0de6-4b92-44da-9aa0-52d134c83fdf',
|
||||||
@ -215,7 +217,7 @@ class NeutronInterfaceTestCase(db_base.DbTestCase):
|
|||||||
provisioning_network_uuid,
|
provisioning_network_uuid,
|
||||||
'provisioning network', context=task.context)
|
'provisioning network', context=task.context)
|
||||||
self.port.refresh()
|
self.port.refresh()
|
||||||
self.assertEqual(self.neutron_port['id'],
|
self.assertEqual(self.neutron_port.id,
|
||||||
self.port.internal_info['provisioning_vif_port_id'])
|
self.port.internal_info['provisioning_vif_port_id'])
|
||||||
|
|
||||||
@mock.patch.object(neutron_common, 'validate_network',
|
@mock.patch.object(neutron_common, 'validate_network',
|
||||||
@ -230,7 +232,7 @@ class NeutronInterfaceTestCase(db_base.DbTestCase):
|
|||||||
|
|
||||||
self.config(provisioning_network_security_groups=sg_ids,
|
self.config(provisioning_network_security_groups=sg_ids,
|
||||||
group='neutron')
|
group='neutron')
|
||||||
add_ports_mock.return_value = {self.port.uuid: self.neutron_port['id']}
|
add_ports_mock.return_value = {self.port.uuid: self.neutron_port.id}
|
||||||
with task_manager.acquire(self.context, self.node.id) as task:
|
with task_manager.acquire(self.context, self.node.id) as task:
|
||||||
self.interface.add_provisioning_network(task)
|
self.interface.add_provisioning_network(task)
|
||||||
rollback_mock.assert_called_once_with(
|
rollback_mock.assert_called_once_with(
|
||||||
@ -240,7 +242,7 @@ class NeutronInterfaceTestCase(db_base.DbTestCase):
|
|||||||
security_groups=(
|
security_groups=(
|
||||||
CONF.neutron.provisioning_network_security_groups))
|
CONF.neutron.provisioning_network_security_groups))
|
||||||
self.port.refresh()
|
self.port.refresh()
|
||||||
self.assertEqual(self.neutron_port['id'],
|
self.assertEqual(self.neutron_port.id,
|
||||||
self.port.internal_info['provisioning_vif_port_id'])
|
self.port.internal_info['provisioning_vif_port_id'])
|
||||||
|
|
||||||
@mock.patch.object(neutron_common, 'validate_network',
|
@mock.patch.object(neutron_common, 'validate_network',
|
||||||
@ -290,7 +292,7 @@ class NeutronInterfaceTestCase(db_base.DbTestCase):
|
|||||||
@mock.patch.object(neutron_common, 'add_ports_to_network', autospec=True)
|
@mock.patch.object(neutron_common, 'add_ports_to_network', autospec=True)
|
||||||
def test_add_cleaning_network(self, add_ports_mock, rollback_mock,
|
def test_add_cleaning_network(self, add_ports_mock, rollback_mock,
|
||||||
validate_mock):
|
validate_mock):
|
||||||
add_ports_mock.return_value = {self.port.uuid: self.neutron_port['id']}
|
add_ports_mock.return_value = {self.port.uuid: self.neutron_port.id}
|
||||||
with task_manager.acquire(self.context, self.node.id) as task:
|
with task_manager.acquire(self.context, self.node.id) as task:
|
||||||
res = self.interface.add_cleaning_network(task)
|
res = self.interface.add_cleaning_network(task)
|
||||||
rollback_mock.assert_called_once_with(
|
rollback_mock.assert_called_once_with(
|
||||||
@ -300,7 +302,7 @@ class NeutronInterfaceTestCase(db_base.DbTestCase):
|
|||||||
CONF.neutron.cleaning_network,
|
CONF.neutron.cleaning_network,
|
||||||
'cleaning network', context=task.context)
|
'cleaning network', context=task.context)
|
||||||
self.port.refresh()
|
self.port.refresh()
|
||||||
self.assertEqual(self.neutron_port['id'],
|
self.assertEqual(self.neutron_port.id,
|
||||||
self.port.internal_info['cleaning_vif_port_id'])
|
self.port.internal_info['cleaning_vif_port_id'])
|
||||||
|
|
||||||
@mock.patch.object(neutron_common, 'validate_network',
|
@mock.patch.object(neutron_common, 'validate_network',
|
||||||
@ -309,7 +311,7 @@ class NeutronInterfaceTestCase(db_base.DbTestCase):
|
|||||||
@mock.patch.object(neutron_common, 'add_ports_to_network', autospec=True)
|
@mock.patch.object(neutron_common, 'add_ports_to_network', autospec=True)
|
||||||
def test_add_cleaning_network_from_node(self, add_ports_mock,
|
def test_add_cleaning_network_from_node(self, add_ports_mock,
|
||||||
rollback_mock, validate_mock):
|
rollback_mock, validate_mock):
|
||||||
add_ports_mock.return_value = {self.port.uuid: self.neutron_port['id']}
|
add_ports_mock.return_value = {self.port.uuid: self.neutron_port.id}
|
||||||
# Make sure that changing the network UUID works
|
# Make sure that changing the network UUID works
|
||||||
for cleaning_network_uuid in ['3aea0de6-4b92-44da-9aa0-52d134c83fdf',
|
for cleaning_network_uuid in ['3aea0de6-4b92-44da-9aa0-52d134c83fdf',
|
||||||
'438be438-6aae-4fb1-bbcb-613ad7a38286']:
|
'438be438-6aae-4fb1-bbcb-613ad7a38286']:
|
||||||
@ -326,7 +328,7 @@ class NeutronInterfaceTestCase(db_base.DbTestCase):
|
|||||||
cleaning_network_uuid,
|
cleaning_network_uuid,
|
||||||
'cleaning network', context=task.context)
|
'cleaning network', context=task.context)
|
||||||
self.port.refresh()
|
self.port.refresh()
|
||||||
self.assertEqual(self.neutron_port['id'],
|
self.assertEqual(self.neutron_port.id,
|
||||||
self.port.internal_info['cleaning_vif_port_id'])
|
self.port.internal_info['cleaning_vif_port_id'])
|
||||||
|
|
||||||
@mock.patch.object(neutron_common, 'validate_network',
|
@mock.patch.object(neutron_common, 'validate_network',
|
||||||
@ -334,7 +336,7 @@ class NeutronInterfaceTestCase(db_base.DbTestCase):
|
|||||||
@mock.patch.object(neutron_common, 'rollback_ports', autospec=True)
|
@mock.patch.object(neutron_common, 'rollback_ports', autospec=True)
|
||||||
@mock.patch.object(neutron_common, 'add_ports_to_network', autospec=True)
|
@mock.patch.object(neutron_common, 'add_ports_to_network', autospec=True)
|
||||||
def test_add_cleaning_network_with_sg(self, add_ports_mock, rollback_mock):
|
def test_add_cleaning_network_with_sg(self, add_ports_mock, rollback_mock):
|
||||||
add_ports_mock.return_value = {self.port.uuid: self.neutron_port['id']}
|
add_ports_mock.return_value = {self.port.uuid: self.neutron_port.id}
|
||||||
sg_ids = []
|
sg_ids = []
|
||||||
for i in range(2):
|
for i in range(2):
|
||||||
sg_ids.append(uuidutils.generate_uuid())
|
sg_ids.append(uuidutils.generate_uuid())
|
||||||
@ -348,7 +350,7 @@ class NeutronInterfaceTestCase(db_base.DbTestCase):
|
|||||||
task, CONF.neutron.cleaning_network)
|
task, CONF.neutron.cleaning_network)
|
||||||
self.assertEqual(res, add_ports_mock.return_value)
|
self.assertEqual(res, add_ports_mock.return_value)
|
||||||
self.port.refresh()
|
self.port.refresh()
|
||||||
self.assertEqual(self.neutron_port['id'],
|
self.assertEqual(self.neutron_port.id,
|
||||||
self.port.internal_info['cleaning_vif_port_id'])
|
self.port.internal_info['cleaning_vif_port_id'])
|
||||||
|
|
||||||
@mock.patch.object(neutron_common, 'validate_network',
|
@mock.patch.object(neutron_common, 'validate_network',
|
||||||
@ -485,7 +487,7 @@ class NeutronInterfaceTestCase(db_base.DbTestCase):
|
|||||||
@mock.patch.object(neutron_common, 'rollback_ports', autospec=True)
|
@mock.patch.object(neutron_common, 'rollback_ports', autospec=True)
|
||||||
@mock.patch.object(neutron_common, 'add_ports_to_network', autospec=True)
|
@mock.patch.object(neutron_common, 'add_ports_to_network', autospec=True)
|
||||||
def test_add_rescuing_network_with_sg(self, add_ports_mock, rollback_mock):
|
def test_add_rescuing_network_with_sg(self, add_ports_mock, rollback_mock):
|
||||||
add_ports_mock.return_value = {self.port.uuid: self.neutron_port['id']}
|
add_ports_mock.return_value = {self.port.uuid: self.neutron_port.id}
|
||||||
sg_ids = []
|
sg_ids = []
|
||||||
for i in range(2):
|
for i in range(2):
|
||||||
sg_ids.append(uuidutils.generate_uuid())
|
sg_ids.append(uuidutils.generate_uuid())
|
||||||
@ -499,7 +501,7 @@ class NeutronInterfaceTestCase(db_base.DbTestCase):
|
|||||||
task, CONF.neutron.rescuing_network)
|
task, CONF.neutron.rescuing_network)
|
||||||
self.assertEqual(add_ports_mock.return_value, res)
|
self.assertEqual(add_ports_mock.return_value, res)
|
||||||
self.port.refresh()
|
self.port.refresh()
|
||||||
self.assertEqual(self.neutron_port['id'],
|
self.assertEqual(self.neutron_port.id,
|
||||||
self.port.internal_info['rescuing_vif_port_id'])
|
self.port.internal_info['rescuing_vif_port_id'])
|
||||||
|
|
||||||
@mock.patch.object(neutron_common, 'validate_network',
|
@mock.patch.object(neutron_common, 'validate_network',
|
||||||
@ -583,21 +585,20 @@ class NeutronInterfaceTestCase(db_base.DbTestCase):
|
|||||||
@mock.patch.object(neutron, 'LOG', autospec=True)
|
@mock.patch.object(neutron, 'LOG', autospec=True)
|
||||||
def test_configure_tenant_networks_multiple_ports_one_vif_id(
|
def test_configure_tenant_networks_multiple_ports_one_vif_id(
|
||||||
self, log_mock, client_mock, update_mock, wait_agent_mock):
|
self, log_mock, client_mock, update_mock, wait_agent_mock):
|
||||||
expected_body = {
|
expected_attrs = {
|
||||||
'port': {
|
'binding:vnic_type': 'baremetal',
|
||||||
'binding:vnic_type': 'baremetal',
|
'binding:host_id': self.node.uuid,
|
||||||
'binding:host_id': self.node.uuid,
|
'binding:profile': {
|
||||||
'binding:profile': {'local_link_information':
|
'local_link_information': [self.port.local_link_connection]
|
||||||
[self.port.local_link_connection]},
|
},
|
||||||
'mac_address': '52:54:00:cf:2d:32'
|
'mac_address': '52:54:00:cf:2d:32'
|
||||||
}
|
|
||||||
}
|
}
|
||||||
with task_manager.acquire(self.context, self.node.id) as task:
|
with task_manager.acquire(self.context, self.node.id) as task:
|
||||||
self.interface.configure_tenant_networks(task)
|
self.interface.configure_tenant_networks(task)
|
||||||
client_mock.assert_called_once_with(context=task.context)
|
client_mock.assert_called_once_with(context=task.context)
|
||||||
update_mock.assert_called_once_with(self.context,
|
update_mock.assert_called_once_with(self.context,
|
||||||
self.port.extra['vif_port_id'],
|
self.port.extra['vif_port_id'],
|
||||||
expected_body)
|
expected_attrs)
|
||||||
|
|
||||||
@mock.patch.object(neutron_common, 'wait_for_host_agent', autospec=True)
|
@mock.patch.object(neutron_common, 'wait_for_host_agent', autospec=True)
|
||||||
@mock.patch.object(neutron_common, 'update_neutron_port', autospec=True)
|
@mock.patch.object(neutron_common, 'update_neutron_port', autospec=True)
|
||||||
@ -605,8 +606,8 @@ class NeutronInterfaceTestCase(db_base.DbTestCase):
|
|||||||
def test_configure_tenant_networks_update_fail(self, client_mock,
|
def test_configure_tenant_networks_update_fail(self, client_mock,
|
||||||
update_mock,
|
update_mock,
|
||||||
wait_agent_mock):
|
wait_agent_mock):
|
||||||
update_mock.side_effect = neutron_exceptions.ConnectionFailed(
|
update_mock.side_effect = openstack_exc.OpenStackCloudException(
|
||||||
reason='meow')
|
message='meow')
|
||||||
with task_manager.acquire(self.context, self.node.id) as task:
|
with task_manager.acquire(self.context, self.node.id) as task:
|
||||||
self.assertRaisesRegex(
|
self.assertRaisesRegex(
|
||||||
exception.NetworkError, 'Could not add',
|
exception.NetworkError, 'Could not add',
|
||||||
@ -645,27 +646,23 @@ class NeutronInterfaceTestCase(db_base.DbTestCase):
|
|||||||
port.extra = extra
|
port.extra = extra
|
||||||
port.save()
|
port.save()
|
||||||
|
|
||||||
expected_body = {
|
expected_attrs = {'binding:vnic_type': 'baremetal',
|
||||||
'port': {
|
'binding:host_id': self.node.uuid}
|
||||||
'binding:vnic_type': 'baremetal',
|
port1_attrs = copy.deepcopy(expected_attrs)
|
||||||
'binding:host_id': self.node.uuid,
|
port1_attrs['binding:profile'] = {
|
||||||
}
|
|
||||||
}
|
|
||||||
port1_body = copy.deepcopy(expected_body)
|
|
||||||
port1_body['port']['binding:profile'] = {
|
|
||||||
'local_link_information': [self.port.local_link_connection]
|
'local_link_information': [self.port.local_link_connection]
|
||||||
}
|
}
|
||||||
port1_body['port']['mac_address'] = '52:54:00:cf:2d:32'
|
port1_attrs['mac_address'] = '52:54:00:cf:2d:32'
|
||||||
port2_body = copy.deepcopy(expected_body)
|
port2_attrs = copy.deepcopy(expected_attrs)
|
||||||
port2_body['port']['binding:profile'] = {
|
port2_attrs['binding:profile'] = {
|
||||||
'local_link_information': [second_port.local_link_connection]
|
'local_link_information': [second_port.local_link_connection]
|
||||||
}
|
}
|
||||||
port2_body['port']['mac_address'] = '52:54:00:cf:2d:33'
|
port2_attrs['mac_address'] = '52:54:00:cf:2d:33'
|
||||||
if is_client_id:
|
if is_client_id:
|
||||||
port1_body['port']['extra_dhcp_opts'] = (
|
port1_attrs['extra_dhcp_opts'] = [{'opt_name': '61',
|
||||||
[{'opt_name': '61', 'opt_value': client_ids[0]}])
|
'opt_value': client_ids[0]}]
|
||||||
port2_body['port']['extra_dhcp_opts'] = (
|
port2_attrs['extra_dhcp_opts'] = [{'opt_name': '61',
|
||||||
[{'opt_name': '61', 'opt_value': client_ids[1]}])
|
'opt_value': client_ids[1]}]
|
||||||
with task_manager.acquire(self.context, self.node.id) as task:
|
with task_manager.acquire(self.context, self.node.id) as task:
|
||||||
self.interface.configure_tenant_networks(task)
|
self.interface.configure_tenant_networks(task)
|
||||||
client_mock.assert_called_once_with(context=task.context)
|
client_mock.assert_called_once_with(context=task.context)
|
||||||
@ -676,8 +673,8 @@ class NeutronInterfaceTestCase(db_base.DbTestCase):
|
|||||||
portid1 = self.port.extra['vif_port_id']
|
portid1 = self.port.extra['vif_port_id']
|
||||||
portid2 = second_port.extra['vif_port_id']
|
portid2 = second_port.extra['vif_port_id']
|
||||||
update_mock.assert_has_calls(
|
update_mock.assert_has_calls(
|
||||||
[mock.call(self.context, portid1, port1_body),
|
[mock.call(self.context, portid1, port1_attrs),
|
||||||
mock.call(self.context, portid2, port2_body)],
|
mock.call(self.context, portid2, port2_attrs)],
|
||||||
any_order=True
|
any_order=True
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -729,24 +726,20 @@ class NeutronInterfaceTestCase(db_base.DbTestCase):
|
|||||||
)
|
)
|
||||||
local_group_info = {'a': 'b'}
|
local_group_info = {'a': 'b'}
|
||||||
glgi_mock.return_value = local_group_info
|
glgi_mock.return_value = local_group_info
|
||||||
expected_body = {
|
expected_attrs = {'binding:vnic_type': 'baremetal',
|
||||||
'port': {
|
'binding:host_id': self.node.uuid}
|
||||||
'binding:vnic_type': 'baremetal',
|
call1_attrs = copy.deepcopy(expected_attrs)
|
||||||
'binding:host_id': self.node.uuid,
|
call1_attrs['binding:profile'] = {
|
||||||
}
|
'local_link_information': [self.port.local_link_connection]
|
||||||
}
|
}
|
||||||
call1_body = copy.deepcopy(expected_body)
|
call1_attrs['mac_address'] = '52:54:00:cf:2d:32'
|
||||||
call1_body['port']['binding:profile'] = {
|
call2_attrs = copy.deepcopy(expected_attrs)
|
||||||
'local_link_information': [self.port.local_link_connection],
|
call2_attrs['binding:profile'] = {
|
||||||
}
|
|
||||||
call1_body['port']['mac_address'] = '52:54:00:cf:2d:32'
|
|
||||||
call2_body = copy.deepcopy(expected_body)
|
|
||||||
call2_body['port']['binding:profile'] = {
|
|
||||||
'local_link_information': [port1.local_link_connection,
|
'local_link_information': [port1.local_link_connection,
|
||||||
port2.local_link_connection],
|
port2.local_link_connection],
|
||||||
'local_group_information': local_group_info
|
'local_group_information': local_group_info
|
||||||
}
|
}
|
||||||
call2_body['port']['mac_address'] = 'ff:54:00:cf:2d:32'
|
call2_attrs['mac_address'] = 'ff:54:00:cf:2d:32'
|
||||||
with task_manager.acquire(self.context, self.node.id) as task:
|
with task_manager.acquire(self.context, self.node.id) as task:
|
||||||
# Override task.portgroups here, to have ability to check
|
# Override task.portgroups here, to have ability to check
|
||||||
# that mocked get_local_group_information was called with
|
# that mocked get_local_group_information was called with
|
||||||
@ -757,9 +750,9 @@ class NeutronInterfaceTestCase(db_base.DbTestCase):
|
|||||||
glgi_mock.assert_called_once_with(task, pg)
|
glgi_mock.assert_called_once_with(task, pg)
|
||||||
update_mock.assert_has_calls(
|
update_mock.assert_has_calls(
|
||||||
[mock.call(self.context, self.port.extra['vif_port_id'],
|
[mock.call(self.context, self.port.extra['vif_port_id'],
|
||||||
call1_body),
|
call1_attrs),
|
||||||
mock.call(self.context, pg.extra['vif_port_id'],
|
mock.call(self.context, pg.extra['vif_port_id'],
|
||||||
call2_body)]
|
call2_attrs)]
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_need_power_on_true(self):
|
def test_need_power_on_true(self):
|
||||||
@ -778,7 +771,7 @@ class NeutronInterfaceTestCase(db_base.DbTestCase):
|
|||||||
@mock.patch.object(neutron_common, 'add_ports_to_network', autospec=True)
|
@mock.patch.object(neutron_common, 'add_ports_to_network', autospec=True)
|
||||||
def test_add_inspection_network(self, add_ports_mock, rollback_mock,
|
def test_add_inspection_network(self, add_ports_mock, rollback_mock,
|
||||||
validate_mock):
|
validate_mock):
|
||||||
add_ports_mock.return_value = {self.port.uuid: self.neutron_port['id']}
|
add_ports_mock.return_value = {self.port.uuid: self.neutron_port.id}
|
||||||
with task_manager.acquire(self.context, self.node.id) as task:
|
with task_manager.acquire(self.context, self.node.id) as task:
|
||||||
res = self.interface.add_inspection_network(task)
|
res = self.interface.add_inspection_network(task)
|
||||||
rollback_mock.assert_called_once_with(
|
rollback_mock.assert_called_once_with(
|
||||||
@ -788,7 +781,7 @@ class NeutronInterfaceTestCase(db_base.DbTestCase):
|
|||||||
CONF.neutron.inspection_network,
|
CONF.neutron.inspection_network,
|
||||||
'inspection network', context=task.context)
|
'inspection network', context=task.context)
|
||||||
self.port.refresh()
|
self.port.refresh()
|
||||||
self.assertEqual(self.neutron_port['id'],
|
self.assertEqual(self.neutron_port.id,
|
||||||
self.port.internal_info['inspection_vif_port_id'])
|
self.port.internal_info['inspection_vif_port_id'])
|
||||||
|
|
||||||
@mock.patch.object(neutron_common, 'validate_network',
|
@mock.patch.object(neutron_common, 'validate_network',
|
||||||
@ -797,7 +790,7 @@ class NeutronInterfaceTestCase(db_base.DbTestCase):
|
|||||||
@mock.patch.object(neutron_common, 'add_ports_to_network', autospec=True)
|
@mock.patch.object(neutron_common, 'add_ports_to_network', autospec=True)
|
||||||
def test_add_inspection_network_from_node(self, add_ports_mock,
|
def test_add_inspection_network_from_node(self, add_ports_mock,
|
||||||
rollback_mock, validate_mock):
|
rollback_mock, validate_mock):
|
||||||
add_ports_mock.return_value = {self.port.uuid: self.neutron_port['id']}
|
add_ports_mock.return_value = {self.port.uuid: self.neutron_port.id}
|
||||||
# Make sure that changing the network UUID works
|
# Make sure that changing the network UUID works
|
||||||
for inspection_network_uuid in [
|
for inspection_network_uuid in [
|
||||||
'3aea0de6-4b92-44da-9aa0-52d134c83fdf',
|
'3aea0de6-4b92-44da-9aa0-52d134c83fdf',
|
||||||
@ -815,7 +808,7 @@ class NeutronInterfaceTestCase(db_base.DbTestCase):
|
|||||||
inspection_network_uuid,
|
inspection_network_uuid,
|
||||||
'inspection network', context=task.context)
|
'inspection network', context=task.context)
|
||||||
self.port.refresh()
|
self.port.refresh()
|
||||||
self.assertEqual(self.neutron_port['id'],
|
self.assertEqual(self.neutron_port.id,
|
||||||
self.port.internal_info['inspection_vif_port_id'])
|
self.port.internal_info['inspection_vif_port_id'])
|
||||||
|
|
||||||
@mock.patch.object(neutron_common, 'validate_network',
|
@mock.patch.object(neutron_common, 'validate_network',
|
||||||
@ -824,7 +817,7 @@ class NeutronInterfaceTestCase(db_base.DbTestCase):
|
|||||||
@mock.patch.object(neutron_common, 'add_ports_to_network', autospec=True)
|
@mock.patch.object(neutron_common, 'add_ports_to_network', autospec=True)
|
||||||
def test_add_inspection_network_with_sg(self, add_ports_mock,
|
def test_add_inspection_network_with_sg(self, add_ports_mock,
|
||||||
rollback_mock):
|
rollback_mock):
|
||||||
add_ports_mock.return_value = {self.port.uuid: self.neutron_port['id']}
|
add_ports_mock.return_value = {self.port.uuid: self.neutron_port.id}
|
||||||
sg_ids = []
|
sg_ids = []
|
||||||
for i in range(2):
|
for i in range(2):
|
||||||
sg_ids.append(uuidutils.generate_uuid())
|
sg_ids.append(uuidutils.generate_uuid())
|
||||||
@ -839,7 +832,7 @@ class NeutronInterfaceTestCase(db_base.DbTestCase):
|
|||||||
task, CONF.neutron.inspection_network)
|
task, CONF.neutron.inspection_network)
|
||||||
self.assertEqual(res, add_ports_mock.return_value)
|
self.assertEqual(res, add_ports_mock.return_value)
|
||||||
self.port.refresh()
|
self.port.refresh()
|
||||||
self.assertEqual(self.neutron_port['id'],
|
self.assertEqual(self.neutron_port.id,
|
||||||
self.port.internal_info['inspection_vif_port_id'])
|
self.port.internal_info['inspection_vif_port_id'])
|
||||||
|
|
||||||
@mock.patch.object(neutron_common, 'validate_network',
|
@mock.patch.object(neutron_common, 'validate_network',
|
||||||
|
@ -76,3 +76,185 @@ class FakeImage(dict):
|
|||||||
self[key] = value
|
self[key] = value
|
||||||
else:
|
else:
|
||||||
raise AttributeError(key)
|
raise AttributeError(key)
|
||||||
|
|
||||||
|
|
||||||
|
class FakeNeutronPort(dict):
|
||||||
|
def __init__(self, **attrs):
|
||||||
|
PORT_ATTRS = ['admin_state_up',
|
||||||
|
'allowed_address_pairs',
|
||||||
|
'binding:host_id',
|
||||||
|
'binding:profile',
|
||||||
|
'binding:vif_details',
|
||||||
|
'binding:vif_type',
|
||||||
|
'binding:vnic_type',
|
||||||
|
'data_plane_status',
|
||||||
|
'description',
|
||||||
|
'device_id',
|
||||||
|
'device_owner',
|
||||||
|
'dns_assignment',
|
||||||
|
'dns_domain',
|
||||||
|
'dns_name',
|
||||||
|
'extra_dhcp_opts',
|
||||||
|
'fixed_ips',
|
||||||
|
'id',
|
||||||
|
'mac_address',
|
||||||
|
'name', 'network_id',
|
||||||
|
'port_security_enabled',
|
||||||
|
'security_group_ids',
|
||||||
|
'status',
|
||||||
|
'tenant_id',
|
||||||
|
'qos_network_policy_id',
|
||||||
|
'qos_policy_id',
|
||||||
|
'tags',
|
||||||
|
'uplink_status_propagation']
|
||||||
|
|
||||||
|
raw = dict.fromkeys(PORT_ATTRS)
|
||||||
|
raw.update(attrs)
|
||||||
|
super(FakeNeutronPort, self).__init__(raw)
|
||||||
|
|
||||||
|
def __getattr__(self, key):
|
||||||
|
try:
|
||||||
|
return self[key]
|
||||||
|
except KeyError:
|
||||||
|
raise AttributeError(key)
|
||||||
|
|
||||||
|
def __setattr__(self, key, value):
|
||||||
|
if key in self:
|
||||||
|
self[key] = value
|
||||||
|
else:
|
||||||
|
raise AttributeError(key)
|
||||||
|
|
||||||
|
|
||||||
|
class FakeNeutronSubnet(dict):
|
||||||
|
def __init__(self, **attrs):
|
||||||
|
SUBNET_ATTRS = ['id',
|
||||||
|
'name',
|
||||||
|
'network_id',
|
||||||
|
'cidr',
|
||||||
|
'tenant_id',
|
||||||
|
'enable_dhcp',
|
||||||
|
'dns_nameservers',
|
||||||
|
'allocation_pools',
|
||||||
|
'host_routes',
|
||||||
|
'ip_version',
|
||||||
|
'gateway_ip',
|
||||||
|
'ipv6_address_mode',
|
||||||
|
'ipv6_ra_mode',
|
||||||
|
'subnetpool_id']
|
||||||
|
|
||||||
|
raw = dict.fromkeys(SUBNET_ATTRS)
|
||||||
|
raw.update(attrs)
|
||||||
|
super(FakeNeutronSubnet, self).__init__(raw)
|
||||||
|
|
||||||
|
def __getattr__(self, key):
|
||||||
|
try:
|
||||||
|
return self[key]
|
||||||
|
except KeyError:
|
||||||
|
raise AttributeError(key)
|
||||||
|
|
||||||
|
def __setattr__(self, key, value):
|
||||||
|
if key in self:
|
||||||
|
self[key] = value
|
||||||
|
else:
|
||||||
|
raise AttributeError(key)
|
||||||
|
|
||||||
|
|
||||||
|
class FakeNeutronNetwork(dict):
|
||||||
|
def __init__(self, **attrs):
|
||||||
|
NETWORK_ATTRS = ['id',
|
||||||
|
'name',
|
||||||
|
'status',
|
||||||
|
'tenant_id',
|
||||||
|
'admin_state_up',
|
||||||
|
'segments',
|
||||||
|
'shared',
|
||||||
|
'subnets',
|
||||||
|
'provider:network_type',
|
||||||
|
'provider:physical_network',
|
||||||
|
'provider:segmentation_id',
|
||||||
|
'router:external',
|
||||||
|
'availability_zones',
|
||||||
|
'availability_zone_hints',
|
||||||
|
'is_default']
|
||||||
|
|
||||||
|
raw = dict.fromkeys(NETWORK_ATTRS)
|
||||||
|
raw.update(attrs)
|
||||||
|
raw.update({
|
||||||
|
'provider_physical_network': attrs.get(
|
||||||
|
'provider:physical_network', None)})
|
||||||
|
super(FakeNeutronNetwork, self).__init__(raw)
|
||||||
|
|
||||||
|
def __getattr__(self, key):
|
||||||
|
try:
|
||||||
|
return self[key]
|
||||||
|
except KeyError:
|
||||||
|
raise AttributeError(key)
|
||||||
|
|
||||||
|
def __setattr__(self, key, value):
|
||||||
|
if key in self:
|
||||||
|
self[key] = value
|
||||||
|
else:
|
||||||
|
raise AttributeError(key)
|
||||||
|
|
||||||
|
|
||||||
|
class FakeNeutronAgent(dict):
|
||||||
|
def __init__(self, **attrs):
|
||||||
|
AGENT_ATTRS = ['admin_state_up',
|
||||||
|
'agents',
|
||||||
|
'agent_type',
|
||||||
|
'alive',
|
||||||
|
'availability_zone',
|
||||||
|
'binary',
|
||||||
|
'configurations',
|
||||||
|
'created_at',
|
||||||
|
'description',
|
||||||
|
'heartbeat_timestamp',
|
||||||
|
'host',
|
||||||
|
'id',
|
||||||
|
'resources_synced',
|
||||||
|
'started_at',
|
||||||
|
'topic']
|
||||||
|
|
||||||
|
raw = dict.fromkeys(AGENT_ATTRS)
|
||||||
|
raw.update(attrs)
|
||||||
|
raw.update({'is_alive': attrs.get('alive', False)})
|
||||||
|
super(FakeNeutronAgent, self).__init__(raw)
|
||||||
|
|
||||||
|
def __getattr__(self, key):
|
||||||
|
try:
|
||||||
|
return self[key]
|
||||||
|
except KeyError:
|
||||||
|
raise AttributeError(key)
|
||||||
|
|
||||||
|
def __setattr__(self, key, value):
|
||||||
|
if key in self:
|
||||||
|
self[key] = value
|
||||||
|
else:
|
||||||
|
raise AttributeError(key)
|
||||||
|
|
||||||
|
|
||||||
|
class FakeNeutronSecurityGroup(dict):
|
||||||
|
def __init__(self, **attrs):
|
||||||
|
SECURITY_GROUP_ATTRS = ['id',
|
||||||
|
'name',
|
||||||
|
'description',
|
||||||
|
'stateful',
|
||||||
|
'project_id',
|
||||||
|
'tenant_id',
|
||||||
|
'security_group_rules']
|
||||||
|
|
||||||
|
raw = dict.fromkeys(SECURITY_GROUP_ATTRS)
|
||||||
|
raw.update(attrs)
|
||||||
|
super(FakeNeutronSecurityGroup, self).__init__(raw)
|
||||||
|
|
||||||
|
def __getattr__(self, key):
|
||||||
|
try:
|
||||||
|
return self[key]
|
||||||
|
except KeyError:
|
||||||
|
raise AttributeError(key)
|
||||||
|
|
||||||
|
def __setattr__(self, key, value):
|
||||||
|
if key in self:
|
||||||
|
self[key] = value
|
||||||
|
else:
|
||||||
|
raise AttributeError(key)
|
||||||
|
@ -52,7 +52,7 @@ msgpack-python==0.5.6
|
|||||||
munch==2.5.0
|
munch==2.5.0
|
||||||
netaddr==0.7.19
|
netaddr==0.7.19
|
||||||
netifaces==0.10.9
|
netifaces==0.10.9
|
||||||
openstacksdk==0.37.0
|
openstacksdk==0.48.0
|
||||||
os-client-config==2.1.0
|
os-client-config==2.1.0
|
||||||
os-service-types==1.7.0
|
os-service-types==1.7.0
|
||||||
os-traits==0.4.0
|
os-traits==0.4.0
|
||||||
@ -101,7 +101,6 @@ python-editor==1.0.4
|
|||||||
python-glanceclient==2.8.0
|
python-glanceclient==2.8.0
|
||||||
python-keystoneclient==4.0.0
|
python-keystoneclient==4.0.0
|
||||||
python-mimeparse==1.6.0
|
python-mimeparse==1.6.0
|
||||||
python-neutronclient==6.7.0
|
|
||||||
python-subunit==1.4.0
|
python-subunit==1.4.0
|
||||||
python-swiftclient==3.2.0
|
python-swiftclient==3.2.0
|
||||||
pytz==2013.6
|
pytz==2013.6
|
||||||
|
@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
deprecations:
|
||||||
|
- |
|
||||||
|
With the switch from neutronclient to openstacksdk the ``[neutron]/retries``
|
||||||
|
option has been deprecated, use ``[neutron]/status_code_retries`` and
|
||||||
|
``[neutron]/status_code_retry_delay`` instead.
|
||||||
|
other:
|
||||||
|
- |
|
||||||
|
Communication with neutron is now using openstacksdk, removing the
|
||||||
|
dependency on neutronclient.
|
@ -8,7 +8,6 @@ automaton>=1.9.0 # Apache-2.0
|
|||||||
eventlet!=0.18.3,!=0.20.1,>=0.18.2 # MIT
|
eventlet!=0.18.3,!=0.20.1,>=0.18.2 # MIT
|
||||||
WebOb>=1.7.1 # MIT
|
WebOb>=1.7.1 # MIT
|
||||||
python-cinderclient!=4.0.0,>=3.3.0 # Apache-2.0
|
python-cinderclient!=4.0.0,>=3.3.0 # Apache-2.0
|
||||||
python-neutronclient>=6.7.0 # Apache-2.0
|
|
||||||
python-glanceclient>=2.8.0 # Apache-2.0
|
python-glanceclient>=2.8.0 # Apache-2.0
|
||||||
keystoneauth1>=4.2.0 # Apache-2.0
|
keystoneauth1>=4.2.0 # Apache-2.0
|
||||||
ironic-lib>=4.3.0 # Apache-2.0
|
ironic-lib>=4.3.0 # Apache-2.0
|
||||||
@ -43,4 +42,4 @@ jsonschema>=3.2.0 # MIT
|
|||||||
psutil>=3.2.2 # BSD
|
psutil>=3.2.2 # BSD
|
||||||
futurist>=1.2.0 # Apache-2.0
|
futurist>=1.2.0 # Apache-2.0
|
||||||
tooz>=2.7.0 # Apache-2.0
|
tooz>=2.7.0 # Apache-2.0
|
||||||
openstacksdk>=0.37.0 # Apache-2.0
|
openstacksdk>=0.48.0 # Apache-2.0
|
||||||
|
Loading…
Reference in New Issue
Block a user