Add rescue related methods to network interface
Adds methods `add_rescuing_network` and `remove_rescuing_network` to add/remove rescuing network to `network` interface. These methods are not added to `flat` network interface. The 'flat' network uses same network for tenant and provisioning. It makes sense to use the same for rescuing as well; as opposed to a separate network like we have for cleaning. Change-Id: I8f4123bfe7d293e8ff6f3bfc2f25445a39c94c73 Related-bug: #1526449 Co-Authored-By: Jay Faulkner <jay@jvf.cc> Co-Authored-By: Mario Villaplana <mario.villaplana@gmail.com> Co-Authored-By: Jesse J. Cook <jesse.j.cook@member.fsf.org> Co-Authored-By: Aparna <aparnavtce@gmail.com> Co-Authored-By: Shivanand Tendulker <stendulker@gmail.com>
This commit is contained in:
parent
084da02a32
commit
fbee0981ad
@ -7,7 +7,9 @@
|
||||
# Authentication strategy used by ironic-api. "noauth" should
|
||||
# not be used in a production environment because all
|
||||
# authentication will be disabled. (string value)
|
||||
# Allowed values: noauth, keystone
|
||||
# Possible values:
|
||||
# noauth - <No description provided>
|
||||
# keystone - <No description provided>
|
||||
#auth_strategy = keystone
|
||||
|
||||
# Return server tracebacks in the API response for any error
|
||||
@ -362,7 +364,12 @@
|
||||
# Specifies the minimum level for which to send notifications.
|
||||
# If not set, no notifications will be sent. The default is
|
||||
# for this option to be unset. (string value)
|
||||
# Allowed values: debug, info, warning, error, critical
|
||||
# Possible values:
|
||||
# debug - <No description provided>
|
||||
# info - <No description provided>
|
||||
# warning - <No description provided>
|
||||
# error - <No description provided>
|
||||
# critical - <No description provided>
|
||||
#notification_level = <None>
|
||||
|
||||
# Directory where the ironic python module is installed.
|
||||
@ -397,7 +404,13 @@
|
||||
# doing a rolling upgrade from version N to version N+1, set
|
||||
# (to pin) this to N. To unpin (default), leave it unset and
|
||||
# the latest versions will be used. (string value)
|
||||
# Allowed values: pike, 9.2, 9.1, 9.0, 8.0, 10.0
|
||||
# Possible values:
|
||||
# pike - <No description provided>
|
||||
# 9.2 - <No description provided>
|
||||
# 9.1 - <No description provided>
|
||||
# 9.0 - <No description provided>
|
||||
# 8.0 - <No description provided>
|
||||
# 10.0 - <No description provided>
|
||||
#pin_release_version = <None>
|
||||
|
||||
# Path to the rootwrap configuration file to use for running
|
||||
@ -554,7 +567,10 @@
|
||||
#rpc_zmq_bind_address = *
|
||||
|
||||
# MatchMaker driver. (string value)
|
||||
# Allowed values: redis, sentinel, dummy
|
||||
# Possible values:
|
||||
# redis - <No description provided>
|
||||
# sentinel - <No description provided>
|
||||
# dummy - <No description provided>
|
||||
#rpc_zmq_matchmaker = redis
|
||||
|
||||
# Number of ZeroMQ contexts, defaults to 1. (integer value)
|
||||
@ -630,7 +646,9 @@
|
||||
# Default serialization mechanism for
|
||||
# serializing/deserializing outgoing/incoming messages (string
|
||||
# value)
|
||||
# Allowed values: json, msgpack
|
||||
# Possible values:
|
||||
# json - <No description provided>
|
||||
# msgpack - <No description provided>
|
||||
#rpc_zmq_serialization = json
|
||||
|
||||
# This option configures round-robin mode in zmq socket. True
|
||||
@ -821,12 +839,17 @@
|
||||
# Whether Ironic should collect the deployment logs on
|
||||
# deployment failure (on_failure), always or never. (string
|
||||
# value)
|
||||
# Allowed values: always, on_failure, never
|
||||
# Possible values:
|
||||
# always - <No description provided>
|
||||
# on_failure - <No description provided>
|
||||
# never - <No description provided>
|
||||
#deploy_logs_collect = on_failure
|
||||
|
||||
# The name of the storage backend where the logs will be
|
||||
# stored. (string value)
|
||||
# Allowed values: local, swift
|
||||
# Possible values:
|
||||
# local - <No description provided>
|
||||
# swift - <No description provided>
|
||||
#deploy_logs_storage_backend = local
|
||||
|
||||
# The path to the directory where the logs should be stored,
|
||||
@ -1596,7 +1619,9 @@
|
||||
# but it will be changed to "local" in the future. It is
|
||||
# recommended to set an explicit value for this option.
|
||||
# (string value)
|
||||
# Allowed values: netboot, local
|
||||
# Possible values:
|
||||
# netboot - <No description provided>
|
||||
# local - <No description provided>
|
||||
#default_boot_option = <None>
|
||||
|
||||
# Whether to upload the config drive to object store. Set this
|
||||
@ -1607,7 +1632,9 @@
|
||||
|
||||
# Type of object store endpoint type to be used as a backend
|
||||
# (string value)
|
||||
# Allowed values: swift, radosgw
|
||||
# Possible values:
|
||||
# swift - <No description provided>
|
||||
# radosgw - <No description provided>
|
||||
# Deprecated group/name - [glance]/temp_url_endpoint_type
|
||||
#object_store_endpoint_type = swift
|
||||
|
||||
@ -1694,7 +1721,9 @@
|
||||
|
||||
# DEPRECATED: Authentication strategy to use when connecting
|
||||
# to glance. (string value)
|
||||
# Allowed values: keystone, noauth
|
||||
# Possible values:
|
||||
# keystone - <No description provided>
|
||||
# noauth - <No description provided>
|
||||
# This option is deprecated for removal.
|
||||
# Its value may be silently ignored in the future.
|
||||
# Reason: To configure glance in noauth mode, set
|
||||
@ -1999,7 +2028,10 @@
|
||||
# for backward compatibility. When "auto" is specified,
|
||||
# default boot mode will be selected based on boot mode
|
||||
# settings on the system. (string value)
|
||||
# Allowed values: auto, bios, uefi
|
||||
# Possible values:
|
||||
# auto - <No description provided>
|
||||
# bios - <No description provided>
|
||||
# uefi - <No description provided>
|
||||
#default_boot_mode = auto
|
||||
|
||||
|
||||
@ -2191,7 +2223,9 @@
|
||||
#remote_image_server = <None>
|
||||
|
||||
# Share type of virtual media (string value)
|
||||
# Allowed values: CIFS, NFS
|
||||
# Possible values:
|
||||
# CIFS - <No description provided>
|
||||
# NFS - <No description provided>
|
||||
#remote_image_share_type = CIFS
|
||||
|
||||
# share name of remote_image_server (string value)
|
||||
@ -2209,23 +2243,32 @@
|
||||
# Port to be used for iRMC operations (port value)
|
||||
# Minimum value: 0
|
||||
# Maximum value: 65535
|
||||
# Allowed values: 443, 80
|
||||
# Possible values:
|
||||
# 443 - <No description provided>
|
||||
# 80 - <No description provided>
|
||||
#port = 443
|
||||
|
||||
# Authentication method to be used for iRMC operations (string
|
||||
# value)
|
||||
# Allowed values: basic, digest
|
||||
# Possible values:
|
||||
# basic - <No description provided>
|
||||
# digest - <No description provided>
|
||||
#auth_method = basic
|
||||
|
||||
# Timeout (in seconds) for iRMC operations (integer value)
|
||||
#client_timeout = 60
|
||||
|
||||
# Sensor data retrieval method. (string value)
|
||||
# Allowed values: ipmitool, scci
|
||||
# Possible values:
|
||||
# ipmitool - <No description provided>
|
||||
# scci - <No description provided>
|
||||
#sensor_method = ipmitool
|
||||
|
||||
# SNMP protocol version (string value)
|
||||
# Allowed values: v1, v2c, v3
|
||||
# Possible values:
|
||||
# v1 - <No description provided>
|
||||
# v2c - <No description provided>
|
||||
# v3 - <No description provided>
|
||||
#snmp_version = v2c
|
||||
|
||||
# SNMP port (port value)
|
||||
@ -2416,7 +2459,10 @@
|
||||
# token data is encrypted and authenticated in the cache. If
|
||||
# the value is not one of these options or empty, auth_token
|
||||
# will raise an exception on initialization. (string value)
|
||||
# Allowed values: None, MAC, ENCRYPT
|
||||
# Possible values:
|
||||
# None - <No description provided>
|
||||
# MAC - <No description provided>
|
||||
# ENCRYPT - <No description provided>
|
||||
#memcache_security_strategy = None
|
||||
|
||||
# (Optional, mandatory if memcache_security_strategy is
|
||||
@ -2603,7 +2649,9 @@
|
||||
#
|
||||
|
||||
# Backend to use for the metrics system. (string value)
|
||||
# Allowed values: noop, statsd
|
||||
# Possible values:
|
||||
# noop - <No description provided>
|
||||
# statsd - <No description provided>
|
||||
#backend = noop
|
||||
|
||||
# Prepend the hostname to all metric names. The format of
|
||||
@ -2667,7 +2715,9 @@
|
||||
# to neutron. Running neutron in noauth mode (related to but
|
||||
# not affected by this setting) is insecure and should only be
|
||||
# used for testing. (string value)
|
||||
# Allowed values: keystone, noauth
|
||||
# Possible values:
|
||||
# keystone - <No description provided>
|
||||
# noauth - <No description provided>
|
||||
# This option is deprecated for removal.
|
||||
# Its value may be silently ignored in the future.
|
||||
# Reason: To configure neutron for noauth mode, set
|
||||
@ -2782,6 +2832,25 @@
|
||||
# value)
|
||||
#region_name = <None>
|
||||
|
||||
# Neutron network UUID or name for booting the ramdisk for
|
||||
# rescue mode. This is not the network that the rescue ramdisk
|
||||
# will use post-boot -- the tenant network is used for that.
|
||||
# Required for "neutron" network interface, if rescue mode
|
||||
# will be used. It is not used for the "flat" or "noop"
|
||||
# network interfaces. If a name is provided, it must be unique
|
||||
# among all networks or rescue will fail. This option is part
|
||||
# of rescue feature work, which is not currently exposed to
|
||||
# users. (string value)
|
||||
#rescuing_network = <None>
|
||||
|
||||
# List of Neutron Security Group UUIDs to be applied during
|
||||
# the node rescue process. Optional for the "neutron" network
|
||||
# interface and not used for the "flat" or "noop" network
|
||||
# interfaces. If not specified, the default security group is
|
||||
# used. This option is part of rescue feature work, which is
|
||||
# not currently exposed to users. (list value)
|
||||
#rescuing_network_security_groups =
|
||||
|
||||
# Client retries in the case of a failed request. (integer
|
||||
# value)
|
||||
#retries = 3
|
||||
@ -3164,15 +3233,24 @@
|
||||
# value)
|
||||
#kafka_consumer_timeout = 1.0
|
||||
|
||||
# Pool Size for Kafka Consumers (integer value)
|
||||
# DEPRECATED: Pool Size for Kafka Consumers (integer value)
|
||||
# This option is deprecated for removal.
|
||||
# Its value may be silently ignored in the future.
|
||||
# Reason: Driver no longer uses connection pool.
|
||||
#pool_size = 10
|
||||
|
||||
# The pool size limit for connections expiration policy
|
||||
# (integer value)
|
||||
# DEPRECATED: The pool size limit for connections expiration
|
||||
# policy (integer value)
|
||||
# This option is deprecated for removal.
|
||||
# Its value may be silently ignored in the future.
|
||||
# Reason: Driver no longer uses connection pool.
|
||||
#conn_pool_min_size = 2
|
||||
|
||||
# The time-to-live in sec of idle connections in the pool
|
||||
# (integer value)
|
||||
# DEPRECATED: The time-to-live in sec of idle connections in
|
||||
# the pool (integer value)
|
||||
# This option is deprecated for removal.
|
||||
# Its value may be silently ignored in the future.
|
||||
# Reason: Driver no longer uses connection pool.
|
||||
#conn_pool_ttl = 1200
|
||||
|
||||
# Group id for Kafka consumer. Consumers in one group will
|
||||
@ -3271,7 +3349,9 @@
|
||||
# one we are currently connected to becomes unavailable. Takes
|
||||
# effect only if more than one RabbitMQ node is provided in
|
||||
# config. (string value)
|
||||
# Allowed values: round-robin, shuffle
|
||||
# Possible values:
|
||||
# round-robin - <No description provided>
|
||||
# shuffle - <No description provided>
|
||||
#kombu_failover_strategy = round-robin
|
||||
|
||||
# DEPRECATED: The RabbitMQ broker address where a single node
|
||||
@ -3310,7 +3390,10 @@
|
||||
#rabbit_password = guest
|
||||
|
||||
# The RabbitMQ login method. (string value)
|
||||
# Allowed values: PLAIN, AMQPLAIN, RABBIT-CR-DEMO
|
||||
# Possible values:
|
||||
# PLAIN - <No description provided>
|
||||
# AMQPLAIN - <No description provided>
|
||||
# RABBIT-CR-DEMO - <No description provided>
|
||||
#rabbit_login_method = AMQPLAIN
|
||||
|
||||
# DEPRECATED: The RabbitMQ virtual host. (string value)
|
||||
@ -3397,7 +3480,10 @@
|
||||
#host_connection_reconnect_delay = 0.25
|
||||
|
||||
# Connection factory implementation (string value)
|
||||
# Allowed values: new, single, read_write
|
||||
# Possible values:
|
||||
# new - <No description provided>
|
||||
# single - <No description provided>
|
||||
# read_write - <No description provided>
|
||||
#connection_factory = single
|
||||
|
||||
# Maximum number of connections to keep queued. (integer
|
||||
@ -3425,7 +3511,9 @@
|
||||
# Default serialization mechanism for
|
||||
# serializing/deserializing outgoing/incoming messages (string
|
||||
# value)
|
||||
# Allowed values: json, msgpack
|
||||
# Possible values:
|
||||
# json - <No description provided>
|
||||
# msgpack - <No description provided>
|
||||
#default_serializer_type = json
|
||||
|
||||
# Persist notification messages. (boolean value)
|
||||
@ -3497,7 +3585,10 @@
|
||||
#rpc_zmq_bind_address = *
|
||||
|
||||
# MatchMaker driver. (string value)
|
||||
# Allowed values: redis, sentinel, dummy
|
||||
# Possible values:
|
||||
# redis - <No description provided>
|
||||
# sentinel - <No description provided>
|
||||
# dummy - <No description provided>
|
||||
#rpc_zmq_matchmaker = redis
|
||||
|
||||
# Number of ZeroMQ contexts, defaults to 1. (integer value)
|
||||
@ -3573,7 +3664,9 @@
|
||||
# Default serialization mechanism for
|
||||
# serializing/deserializing outgoing/incoming messages (string
|
||||
# value)
|
||||
# Allowed values: json, msgpack
|
||||
# Possible values:
|
||||
# json - <No description provided>
|
||||
# msgpack - <No description provided>
|
||||
#rpc_zmq_serialization = json
|
||||
|
||||
# This option configures round-robin mode in zmq socket. True
|
||||
@ -3682,7 +3775,10 @@
|
||||
|
||||
# Content Type to send and receive data for REST based policy
|
||||
# check (string value)
|
||||
# Allowed values: application/x-www-form-urlencoded, application/json
|
||||
# Possible values:
|
||||
# application/x-www-form-urlencoded - <No description
|
||||
# provided>
|
||||
# application/json - <No description provided>
|
||||
#remote_content_type = application/x-www-form-urlencoded
|
||||
|
||||
# server identity verification for REST based policy check
|
||||
@ -3914,7 +4010,9 @@
|
||||
|
||||
# The IP version that will be used for PXE booting. Defaults
|
||||
# to 4. EXPERIMENTAL (string value)
|
||||
# Allowed values: 4, 6
|
||||
# Possible values:
|
||||
# 4 - <No description provided>
|
||||
# 6 - <No description provided>
|
||||
#ip_version = 4
|
||||
|
||||
# Download deploy images directly from swift using temporary
|
||||
|
@ -566,6 +566,7 @@ class NeutronNetworkInterfaceMixin(object):
|
||||
|
||||
_cleaning_network_uuid = None
|
||||
_provisioning_network_uuid = None
|
||||
_rescuing_network_uuid = None
|
||||
|
||||
def get_cleaning_network_uuid(self, context=None):
|
||||
if self._cleaning_network_uuid is None:
|
||||
@ -580,3 +581,12 @@ class NeutronNetworkInterfaceMixin(object):
|
||||
CONF.neutron.provisioning_network,
|
||||
_('provisioning network'), context=context)
|
||||
return self._provisioning_network_uuid
|
||||
|
||||
def get_rescuing_network_uuid(self, context=None):
|
||||
# TODO(stendulker): FlatNetwork should not use this method.
|
||||
# FlatNetwork uses tenant network for rescue operation.
|
||||
if self._rescuing_network_uuid is None:
|
||||
self._rescuing_network_uuid = validate_network(
|
||||
CONF.neutron.rescuing_network,
|
||||
_('rescuing network'), context=context)
|
||||
return self._rescuing_network_uuid
|
||||
|
@ -90,6 +90,26 @@ opts = [
|
||||
'used for the "flat" or "noop" network interfaces. '
|
||||
'If not specified, default security group '
|
||||
'is used.')),
|
||||
cfg.StrOpt('rescuing_network',
|
||||
help=_('Neutron network UUID or name for booting the ramdisk '
|
||||
'for rescue mode. This is not the network that the '
|
||||
'rescue ramdisk will use post-boot -- the tenant '
|
||||
'network is used for that. Required for "neutron" '
|
||||
'network interface, if rescue mode will be used. It '
|
||||
'is not used for the "flat" or "noop" network '
|
||||
'interfaces. If a name is provided, it must be unique '
|
||||
'among all networks or rescue will fail. This option '
|
||||
'is part of rescue feature work, which is not currently '
|
||||
'exposed to users.')),
|
||||
cfg.ListOpt('rescuing_network_security_groups',
|
||||
default=[],
|
||||
help=_('List of Neutron Security Group UUIDs to be applied '
|
||||
'during the node rescue process. Optional for the '
|
||||
'"neutron" network interface and not used for the '
|
||||
'"flat" or "noop" network interfaces. If not '
|
||||
'specified, the default security group is used. This '
|
||||
'option is part of rescue feature work, which is '
|
||||
'not currently exposed to users.')),
|
||||
]
|
||||
|
||||
|
||||
|
@ -1036,8 +1036,9 @@ class NetworkInterface(BaseInterface):
|
||||
"""Returns the currently used VIF associated with port or portgroup
|
||||
|
||||
We are booting the node only in one network at a time, and presence of
|
||||
cleaning_vif_port_id means we're doing cleaning, of
|
||||
provisioning_vif_port_id - provisioning.
|
||||
cleaning_vif_port_id means we're doing cleaning,
|
||||
of provisioning_vif_port_id - provisioning,
|
||||
of rescuing_vif_port_id - rescuing.
|
||||
Otherwise it's a tenant network.
|
||||
|
||||
:param task: A TaskManager instance.
|
||||
@ -1092,6 +1093,28 @@ class NetworkInterface(BaseInterface):
|
||||
:raises: NetworkError
|
||||
"""
|
||||
|
||||
def add_rescuing_network(self, task):
|
||||
"""Add the rescuing network to the node.
|
||||
|
||||
:param task: A TaskManager instance.
|
||||
:returns: a dictionary in the form {port.uuid: neutron_port['id']}
|
||||
:raises: NetworkError
|
||||
:raises: InvalidParameterValue, if the network interface configuration
|
||||
is invalid.
|
||||
"""
|
||||
return {}
|
||||
|
||||
def remove_rescuing_network(self, task):
|
||||
"""Removes the rescuing network from a node.
|
||||
|
||||
:param task: A TaskManager instance.
|
||||
:raises: NetworkError
|
||||
:raises: InvalidParameterValue, if the network interface configuration
|
||||
is invalid.
|
||||
:raises: MissingParameterValue, if some parameters are missing.
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
@six.add_metaclass(abc.ABCMeta)
|
||||
class StorageInterface(BaseInterface):
|
||||
|
@ -362,8 +362,9 @@ class VIFPortIDMixin(object):
|
||||
"""Returns the currently used VIF associated with port or portgroup
|
||||
|
||||
We are booting the node only in one network at a time, and presence of
|
||||
cleaning_vif_port_id means we're doing cleaning, of
|
||||
provisioning_vif_port_id - provisioning.
|
||||
cleaning_vif_port_id means we're doing cleaning,
|
||||
of provisioning_vif_port_id - provisioning,
|
||||
of rescuing_vif_port_id - rescuing.
|
||||
Otherwise it's a tenant network
|
||||
|
||||
:param task: A TaskManager instance.
|
||||
@ -373,6 +374,7 @@ class VIFPortIDMixin(object):
|
||||
|
||||
return (p_obj.internal_info.get('cleaning_vif_port_id') or
|
||||
p_obj.internal_info.get('provisioning_vif_port_id') or
|
||||
p_obj.internal_info.get('rescuing_vif_port_id') or
|
||||
self._get_vif_id_by_port_like_obj(p_obj) or None)
|
||||
|
||||
|
||||
|
@ -140,6 +140,46 @@ class NeutronNetwork(common.NeutronVIFPortIDMixin,
|
||||
port.internal_info = internal_info
|
||||
port.save()
|
||||
|
||||
def add_rescuing_network(self, task):
|
||||
"""Create neutron ports for each port to boot the rescue ramdisk.
|
||||
|
||||
:param task: a TaskManager instance.
|
||||
:returns: a dictionary in the form {port.uuid: neutron_port['id']}
|
||||
"""
|
||||
# If we have left over ports from a previous rescue, remove them
|
||||
neutron.rollback_ports(task, self.get_rescuing_network_uuid(
|
||||
context=task.context))
|
||||
LOG.info('Adding rescuing network to node %s', task.node.uuid)
|
||||
security_groups = CONF.neutron.rescuing_network_security_groups
|
||||
vifs = neutron.add_ports_to_network(
|
||||
task,
|
||||
self.get_rescuing_network_uuid(context=task.context),
|
||||
security_groups=security_groups)
|
||||
for port in task.ports:
|
||||
if port.uuid in vifs:
|
||||
internal_info = port.internal_info
|
||||
internal_info['rescuing_vif_port_id'] = vifs[port.uuid]
|
||||
port.internal_info = internal_info
|
||||
port.save()
|
||||
return vifs
|
||||
|
||||
def remove_rescuing_network(self, task):
|
||||
"""Deletes neutron port created for booting the rescue ramdisk.
|
||||
|
||||
:param task: a TaskManager instance.
|
||||
:raises: NetworkError
|
||||
"""
|
||||
LOG.info('Removing rescuing network from node %s',
|
||||
task.node.uuid)
|
||||
neutron.remove_ports_from_network(
|
||||
task, self.get_rescuing_network_uuid(context=task.context))
|
||||
for port in task.ports:
|
||||
if 'rescuing_vif_port_id' in port.internal_info:
|
||||
internal_info = port.internal_info
|
||||
del internal_info['rescuing_vif_port_id']
|
||||
port.internal_info = internal_info
|
||||
port.save()
|
||||
|
||||
def configure_tenant_networks(self, task):
|
||||
"""Configure tenant networks for a node.
|
||||
|
||||
|
@ -67,8 +67,9 @@ class NoopNetwork(base.NetworkInterface):
|
||||
"""Returns the currently used VIF associated with port or portgroup
|
||||
|
||||
We are booting the node only in one network at a time, and presence of
|
||||
cleaning_vif_port_id means we're doing cleaning, of
|
||||
provisioning_vif_port_id - provisioning.
|
||||
cleaning_vif_port_id means we're doing cleaning,
|
||||
of provisioning_vif_port_id - provisioning
|
||||
of rescuing_vif_port_id - rescuing.
|
||||
Otherwise it's a tenant network
|
||||
|
||||
:param task: A TaskManager instance.
|
||||
|
@ -129,6 +129,8 @@ class TestCase(oslo_test_base.BaseTestCase):
|
||||
group='neutron')
|
||||
self.config(provisioning_network=uuidutils.generate_uuid(),
|
||||
group='neutron')
|
||||
self.config(rescuing_network=uuidutils.generate_uuid(),
|
||||
group='neutron')
|
||||
self.config(enabled_drivers=['fake'])
|
||||
self.config(enabled_hardware_types=['fake-hardware'])
|
||||
self.config(enabled_network_interfaces=['flat', 'noop', 'neutron'])
|
||||
|
@ -153,6 +153,9 @@ class TestNetwork(db_base.DbTestCase):
|
||||
def test_get_node_vif_ids_during_provisioning(self):
|
||||
self._test_get_node_vif_ids_multitenancy('provisioning_vif_port_id')
|
||||
|
||||
def test_get_node_vif_ids_during_rescuing(self):
|
||||
self._test_get_node_vif_ids_multitenancy('rescuing_vif_port_id')
|
||||
|
||||
|
||||
class GetPortgroupByIdTestCase(db_base.DbTestCase):
|
||||
|
||||
|
@ -626,7 +626,7 @@ class TestVifPortIDMixin(db_base.DbTestCase):
|
||||
|
||||
def test_get_current_vif_internal_info_provisioning(self):
|
||||
internal_info = {'provisioning_vif_port_id': 'foo',
|
||||
'vif_port_id': 'bar'}
|
||||
'tenant_vif_port_id': 'bar'}
|
||||
self.port.internal_info = internal_info
|
||||
self.port.save()
|
||||
with task_manager.acquire(self.context, self.node.id) as task:
|
||||
@ -641,6 +641,15 @@ class TestVifPortIDMixin(db_base.DbTestCase):
|
||||
vif = self.interface.get_current_vif(task, self.port)
|
||||
self.assertEqual('bar', vif)
|
||||
|
||||
def test_get_current_vif_internal_info_rescuing(self):
|
||||
internal_info = {'rescuing_vif_port_id': 'foo',
|
||||
'tenant_vif_port_id': 'bar'}
|
||||
self.port.internal_info = internal_info
|
||||
self.port.save()
|
||||
with task_manager.acquire(self.context, self.node.id) as task:
|
||||
vif = self.interface.get_current_vif(task, self.port)
|
||||
self.assertEqual('foo', vif)
|
||||
|
||||
def test_get_current_vif_none(self):
|
||||
internal_info = extra = {}
|
||||
self.port.internal_info = internal_info
|
||||
|
@ -20,6 +20,7 @@ from oslo_utils import uuidutils
|
||||
from ironic.common import exception
|
||||
from ironic.common import neutron as neutron_common
|
||||
from ironic.conductor import task_manager
|
||||
from ironic.drivers import base as drivers_base
|
||||
from ironic.drivers.modules.network import neutron
|
||||
from ironic.tests.unit.conductor import mgr_utils
|
||||
from ironic.tests.unit.db import base as db_base
|
||||
@ -35,10 +36,19 @@ class NeutronInterfaceTestCase(db_base.DbTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(NeutronInterfaceTestCase, self).setUp()
|
||||
self.config(enabled_drivers=['fake'])
|
||||
self.config(enabled_hardware_types=['fake-hardware'])
|
||||
for iface in drivers_base.ALL_INTERFACES:
|
||||
name = 'fake'
|
||||
if iface == 'network':
|
||||
name = 'neutron'
|
||||
config_kwarg = {'enabled_%s_interfaces' % iface: [name],
|
||||
'default_%s_interface' % iface: name}
|
||||
self.config(**config_kwarg)
|
||||
|
||||
mgr_utils.mock_the_extension_manager()
|
||||
self.interface = neutron.NeutronNetwork()
|
||||
self.node = utils.create_test_node(self.context,
|
||||
driver='fake-hardware',
|
||||
network_interface='neutron')
|
||||
self.port = utils.create_test_port(
|
||||
self.context, node_id=self.node.id,
|
||||
@ -217,6 +227,82 @@ class NeutronInterfaceTestCase(db_base.DbTestCase):
|
||||
self.port.refresh()
|
||||
self.assertNotIn('cleaning_vif_port_id', self.port.internal_info)
|
||||
|
||||
@mock.patch.object(neutron_common, 'validate_network',
|
||||
side_effect=lambda n, t, context=None: n)
|
||||
@mock.patch.object(neutron_common, 'rollback_ports')
|
||||
@mock.patch.object(neutron_common, 'add_ports_to_network')
|
||||
def test_add_rescuing_network(self, add_ports_mock, rollback_mock,
|
||||
validate_mock):
|
||||
other_port = utils.create_test_port(
|
||||
self.context, node_id=self.node.id,
|
||||
address='52:54:00:cf:2d:33',
|
||||
uuid=uuidutils.generate_uuid(),
|
||||
extra={'vif_port_id': uuidutils.generate_uuid()})
|
||||
neutron_other_port = {'id': uuidutils.generate_uuid(),
|
||||
'mac_address': '52:54:00:cf:2d:33'}
|
||||
add_ports_mock.return_value = {
|
||||
other_port.uuid: neutron_other_port['id']}
|
||||
with task_manager.acquire(self.context, self.node.id) as task:
|
||||
res = self.interface.add_rescuing_network(task)
|
||||
add_ports_mock.assert_called_once_with(
|
||||
task, CONF.neutron.rescuing_network,
|
||||
security_groups=[])
|
||||
rollback_mock.assert_called_once_with(
|
||||
task, CONF.neutron.rescuing_network)
|
||||
self.assertEqual(add_ports_mock.return_value, res)
|
||||
validate_mock.assert_called_once_with(
|
||||
CONF.neutron.rescuing_network,
|
||||
'rescuing network', context=task.context)
|
||||
other_port.refresh()
|
||||
self.assertEqual(neutron_other_port['id'],
|
||||
other_port.internal_info['rescuing_vif_port_id'])
|
||||
self.assertNotIn('rescuing_vif_port_id', self.port.internal_info)
|
||||
|
||||
@mock.patch.object(neutron_common, 'validate_network',
|
||||
lambda n, t, context=None: n)
|
||||
@mock.patch.object(neutron_common, 'rollback_ports')
|
||||
@mock.patch.object(neutron_common, 'add_ports_to_network')
|
||||
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']}
|
||||
sg_ids = []
|
||||
for i in range(2):
|
||||
sg_ids.append(uuidutils.generate_uuid())
|
||||
self.config(rescuing_network_security_groups=sg_ids, group='neutron')
|
||||
with task_manager.acquire(self.context, self.node.id) as task:
|
||||
res = self.interface.add_rescuing_network(task)
|
||||
add_ports_mock.assert_called_once_with(
|
||||
task, CONF.neutron.rescuing_network,
|
||||
security_groups=CONF.neutron.rescuing_network_security_groups)
|
||||
rollback_mock.assert_called_once_with(
|
||||
task, CONF.neutron.rescuing_network)
|
||||
self.assertEqual(add_ports_mock.return_value, res)
|
||||
self.port.refresh()
|
||||
self.assertEqual(self.neutron_port['id'],
|
||||
self.port.internal_info['rescuing_vif_port_id'])
|
||||
|
||||
@mock.patch.object(neutron_common, 'validate_network',
|
||||
side_effect=lambda n, t, context=None: n)
|
||||
@mock.patch.object(neutron_common, 'remove_ports_from_network')
|
||||
def test_remove_rescuing_network(self, remove_ports_mock,
|
||||
validate_mock):
|
||||
other_port = utils.create_test_port(
|
||||
self.context, node_id=self.node.id,
|
||||
address='52:54:00:cf:2d:33',
|
||||
uuid=uuidutils.generate_uuid(),
|
||||
extra={'vif_port_id': uuidutils.generate_uuid()})
|
||||
other_port.internal_info = {'rescuing_vif_port_id': 'vif-port-id'}
|
||||
other_port.save()
|
||||
with task_manager.acquire(self.context, self.node.id) as task:
|
||||
self.interface.remove_rescuing_network(task)
|
||||
remove_ports_mock.assert_called_once_with(
|
||||
task, CONF.neutron.rescuing_network)
|
||||
validate_mock.assert_called_once_with(
|
||||
CONF.neutron.rescuing_network,
|
||||
'rescuing network', context=task.context)
|
||||
other_port.refresh()
|
||||
self.assertNotIn('rescuing_vif_port_id', self.port.internal_info)
|
||||
self.assertNotIn('rescuing_vif_port_id', other_port.internal_info)
|
||||
|
||||
@mock.patch.object(neutron_common, 'unbind_neutron_port')
|
||||
def test_unconfigure_tenant_networks(self, mock_unbind_port):
|
||||
with task_manager.acquire(self.context, self.node.id) as task:
|
||||
|
Loading…
x
Reference in New Issue
Block a user