Apply neutron network constraint

Apply neutron network custom constraint for
resources.

And this patch changes the validation of neutron
network constraint to make sure it works if user using
nova_network.

Change-Id: I2decc44e180d5203ec226fd16692ff5fa59a9cab
Implements: blueprint apply-neutron-constraints
This commit is contained in:
huangtianhua 2014-11-19 14:33:08 +08:00
parent a991a70d7f
commit 4a206cf775
18 changed files with 249 additions and 81 deletions

View File

@ -248,6 +248,10 @@ class VolumeTypeNotFound(HeatException):
msg_fmt = _("The VolumeType (%(volume_type)s) could not be found.")
class NovaNetworkNotFound(HeatException):
msg_fmt = _("The Nova network (%(network)s) could not be found.")
class PhysicalResourceNameAmbiguity(HeatException):
msg_fmt = _(
"Multiple physical resources were found with name (%(name)s).")

View File

@ -129,12 +129,19 @@ class NeutronClientPlugin(client_plugin.ClientPlugin):
class NetworkConstraint(constraints.BaseCustomConstraint):
expected_exceptions = (exceptions.NeutronClientException,)
expected_exceptions = (exceptions.NeutronClientException,
exception.NovaNetworkNotFound,
exception.PhysicalResourceNameAmbiguity)
def validate_with_client(self, client, value):
neutron_client = client.client('neutron')
neutronV20.find_resourceid_by_name_or_id(
neutron_client, 'network', value)
try:
neutron_client = client.client('neutron')
except Exception:
# is not using neutron
client.client_plugin('nova').get_nova_network_id(value)
else:
neutronV20.find_resourceid_by_name_or_id(
neutron_client, 'network', value)
class PortConstraint(constraints.BaseCustomConstraint):

View File

@ -25,6 +25,7 @@ from novaclient import client as nc
from novaclient import exceptions
from novaclient import shell as novashell
from oslo.config import cfg
from oslo.utils import uuidutils
import six
from six.moves.urllib import parse as urlparse
@ -463,6 +464,30 @@ echo -e '%s\tALL=(ALL)\tNOPASSWD: ALL' >> /etc/sudoers
return ConsoleUrls(server)
def get_net_id_by_label(self, label):
try:
net_id = self.client().networks.find(label=label).id
except exceptions.NotFound as ex:
LOG.debug('Nova network (%(net)s) not found: %(ex)s',
{'net': label, 'ex': ex})
raise exception.NovaNetworkNotFound(network=label)
except exceptions.NoUniqueMatch as exc:
LOG.debug('Nova network (%(net)s) is not unique matched: %(exc)s',
{'net': label, 'exc': exc})
raise exception.PhysicalResourceNameAmbiguity(name=label)
return net_id
def get_nova_network_id(self, net_identifier):
if uuidutils.is_uuid_like(net_identifier):
try:
net_id = self.client().networks.get(net_identifier).id
except exceptions.NotFound:
net_id = self.get_net_id_by_label(net_identifier)
else:
net_id = self.get_net_id_by_label(net_identifier)
return net_id
class ServerConstraint(constraints.BaseCustomConstraint):

View File

@ -14,6 +14,7 @@ import six
from heat.common.i18n import _
from heat.engine import attributes
from heat.engine import constraints
from heat.engine import properties
from heat.engine.resources.neutron import neutron
from heat.engine.resources.neutron import port
@ -44,13 +45,19 @@ class FloatingIP(neutron.NeutronResource):
support_status=support.SupportStatus(
support.DEPRECATED,
_('Use property %s.') % FLOATING_NETWORK),
required=False
required=False,
constraints=[
constraints.CustomConstraint('neutron.network')
],
),
FLOATING_NETWORK: properties.Schema(
properties.Schema.STRING,
_('Network to allocate floating IP from.'),
required=False,
support_status=support.SupportStatus(version='2014.2')
support_status=support.SupportStatus(version='2014.2'),
constraints=[
constraints.CustomConstraint('neutron.network')
],
),
VALUE_SPECS: properties.Schema(
properties.Schema.MAP,

View File

@ -97,7 +97,10 @@ class NetworkGateway(neutron.NeutronResource):
support_status=support.SupportStatus(
support.DEPRECATED,
_('Use property %s.') % NETWORK),
required=False
required=False,
constraints=[
constraints.CustomConstraint('neutron.network')
],
),
NETWORK: properties.Schema(
properties.Schema.STRING,
@ -105,7 +108,10 @@ class NetworkGateway(neutron.NeutronResource):
'The internal network to connect on '
'the network gateway.'),
required=False,
support_status=support.SupportStatus(version='2014.2')
support_status=support.SupportStatus(version='2014.2'),
constraints=[
constraints.CustomConstraint('neutron.network')
],
),
SEGMENTATION_TYPE: properties.Schema(
properties.Schema.STRING,

View File

@ -66,13 +66,19 @@ class Port(neutron.NeutronResource):
properties.Schema.STRING,
support_status=support.SupportStatus(
support.DEPRECATED,
_('Use property %s.') % NETWORK)
_('Use property %s.') % NETWORK),
constraints=[
constraints.CustomConstraint('neutron.network')
],
),
NETWORK: properties.Schema(
properties.Schema.STRING,
_('Network this port belongs to.'),
support_status=support.SupportStatus(version='2014.2')
support_status=support.SupportStatus(version='2014.2'),
constraints=[
constraints.CustomConstraint('neutron.network')
],
),
NAME: properties.Schema(

View File

@ -14,6 +14,7 @@
from heat.common import exception
from heat.common.i18n import _
from heat.engine import attributes
from heat.engine import constraints
from heat.engine import properties
from heat.engine.resources.neutron import neutron
from heat.engine.resources.neutron import subnet
@ -340,12 +341,18 @@ class RouterGateway(neutron.NeutronResource):
support_status=support.SupportStatus(
support.DEPRECATED,
_('Use property %s.') % NETWORK),
required=False
required=False,
constraints=[
constraints.CustomConstraint('neutron.network')
],
),
NETWORK: properties.Schema(
properties.Schema.STRING,
_('external network for the gateway.'),
required=False
required=False,
constraints=[
constraints.CustomConstraint('neutron.network')
],
),
}

View File

@ -66,12 +66,18 @@ class Subnet(neutron.NeutronResource):
support_status=support.SupportStatus(
support.DEPRECATED,
_('Use property %s.') % NETWORK),
required=False
required=False,
constraints=[
constraints.CustomConstraint('neutron.network')
],
),
NETWORK: properties.Schema(
properties.Schema.STRING,
_('The ID of the attached network.'),
required=False
required=False,
constraints=[
constraints.CustomConstraint('neutron.network')
],
),
CIDR: properties.Schema(
properties.Schema.STRING,

View File

@ -10,7 +10,6 @@
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from oslo.utils import uuidutils
from heat.common import exception
from heat.common.i18n import _
@ -129,7 +128,10 @@ class OSDBInstance(resource.Resource):
properties.Schema.STRING,
_('Name or UUID of the network to attach this NIC to. '
'Either %(port)s or %(net)s must be specified.') % {
'port': PORT, 'net': NET}
'port': PORT, 'net': NET},
constraints=[
constraints.CustomConstraint('neutron.network')
]
),
PORT: properties.Schema(
properties.Schema.STRING,
@ -298,13 +300,13 @@ class OSDBInstance(resource.Resource):
nic_dict = {}
net = nic.get(self.NET)
if net:
if uuidutils.is_uuid_like(net):
net_id = net
if self.is_using_neutron():
net_id = (self.client_plugin(
'neutron').find_neutron_resource(
nic, self.NET, 'network'))
else:
# using Nova for lookup to cover both neutron and
# nova-network cases
nova = self.client('nova')
net_id = nova.networks.find(label=net).id
net_id = (self.client_plugin(
'nova').get_nova_network_id(net))
nic_dict['net-id'] = net_id
port = nic.get(self.PORT)
if port:
@ -387,7 +389,6 @@ class OSDBInstance(resource.Resource):
if not self.resource_id:
return
instance = None
try:
instance = self.trove().instances.get(self.resource_id)
except Exception as ex:

View File

@ -95,7 +95,7 @@ class SaharaCluster(resource.Resource):
),
MANAGEMENT_NETWORK: properties.Schema(
properties.Schema.STRING,
_('Name or UUID of Neutron network.'),
_('Name or UUID of network.'),
constraints=[
constraints.CustomConstraint('neutron.network')
],
@ -147,8 +147,12 @@ class SaharaCluster(resource.Resource):
key_name = self.properties.get(self.KEY_NAME)
net_id = self.properties.get(self.MANAGEMENT_NETWORK)
if net_id:
net_id = self.client_plugin('neutron').find_neutron_resource(
self.properties, self.MANAGEMENT_NETWORK, 'network')
if self.is_using_neutron():
net_id = self.client_plugin('neutron').find_neutron_resource(
self.properties, self.MANAGEMENT_NETWORK, 'network')
else:
net_id = self.client_plugin('nova').get_nova_network_id(
net_id)
cluster = self.client().clusters.create(
self._cluster_name(),
@ -213,9 +217,6 @@ class SaharaCluster(resource.Resource):
self._validate_depr_keys(self.properties, self.IMAGE_ID, self.IMAGE)
# check if running on neutron and MANAGEMENT_NETWORK missing
# NOTE(pshchelo): on nova-network with MANAGEMENT_NETWORK present
# overall stack validation will fail due to neutron.network constraint,
# although the message will be not really relevant.
if (self.is_using_neutron() and
not self.properties.get(self.MANAGEMENT_NETWORK)):
msg = _("%s must be provided"

View File

@ -287,7 +287,7 @@ class SaharaClusterTemplate(resource.Resource):
),
MANAGEMENT_NETWORK: properties.Schema(
properties.Schema.STRING,
_('Name or UUID of Neutron network.'),
_('Name or UUID of network.'),
constraints=[
constraints.CustomConstraint('neutron.network')
],
@ -350,8 +350,12 @@ class SaharaClusterTemplate(resource.Resource):
image_id = self.properties.get(self.IMAGE_ID)
net_id = self.properties.get(self.MANAGEMENT_NETWORK)
if net_id:
net_id = self.client_plugin('neutron').find_neutron_resource(
self.properties, self.MANAGEMENT_NETWORK, 'network')
if self.is_using_neutron():
net_id = self.client_plugin('neutron').find_neutron_resource(
self.properties, self.MANAGEMENT_NETWORK, 'network')
else:
net_id = self.client_plugin('nova').get_nova_network_id(
net_id)
anti_affinity = self.properties.get(self.ANTI_AFFINITY)
cluster_configs = self.properties.get(self.CLUSTER_CONFIGS)
node_groups = self.properties.get(self.NODE_GROUPS)
@ -386,9 +390,6 @@ class SaharaClusterTemplate(resource.Resource):
if res:
return res
# check if running on neutron and MANAGEMENT_NETWORK missing
# NOTE(pshchelo): on nova-network with MANAGEMENT_NETWORK present
# overall stack validation will fail due to neutron.network constraint,
# although the message will be not really relevant.
if (self.is_using_neutron() and
not self.properties.get(self.MANAGEMENT_NETWORK)):
msg = _("%s must be provided"

View File

@ -93,7 +93,6 @@ class Server(stack_user.StackUser):
'name', 'show', 'addresses', 'networks', 'first_address',
'instance_name', 'accessIPv4', 'accessIPv6', 'console_urls',
)
properties_schema = {
NAME: properties.Schema(
properties.Schema.STRING,
@ -221,11 +220,17 @@ class Server(stack_user.StackUser):
_('ID of network to create a port on.'),
support_status=support.SupportStatus(
support.DEPRECATED,
_('Use property %s.') % NETWORK_ID)
_('Use property %s.') % NETWORK_ID),
constraints=[
constraints.CustomConstraint('neutron.network')
]
),
NETWORK_ID: properties.Schema(
properties.Schema.STRING,
_('Name or ID of network to create a port on.')
_('Name or ID of network to create a port on.'),
constraints=[
constraints.CustomConstraint('neutron.network')
]
),
NETWORK_FIXED_IP: properties.Schema(
properties.Schema.STRING,
@ -655,15 +660,17 @@ class Server(stack_user.StackUser):
for net_data in networks:
nic_info = {}
if net_data.get(self.NETWORK_UUID):
nic_info['net-id'] = net_data[self.NETWORK_UUID]
label_or_uuid = net_data.get(self.NETWORK_ID)
if label_or_uuid:
if uuidutils.is_uuid_like(label_or_uuid):
nic_info['net-id'] = label_or_uuid
net_identifier = (net_data.get(self.NETWORK_UUID) or
net_data.get(self.NETWORK_ID))
if net_identifier:
if self.is_using_neutron():
net_id = (self.client_plugin(
'neutron').resolve_network(
net_data, self.NETWORK_ID, self.NETWORK_UUID))
else:
network = self.nova().networks.find(label=label_or_uuid)
nic_info['net-id'] = network.id
net_id = (self.client_plugin(
'nova').get_nova_network_id(net_identifier))
nic_info['net-id'] = net_id
if net_data.get(self.NETWORK_FIXED_IP):
nic_info['v4-fixed-ip'] = net_data[self.NETWORK_FIXED_IP]
if net_data.get(self.NETWORK_PORT):

View File

@ -29,6 +29,7 @@ from heat.common import messaging
from heat.engine.clients.os import cinder
from heat.engine.clients.os import glance
from heat.engine.clients.os import keystone
from heat.engine.clients.os import neutron
from heat.engine.clients.os import nova
from heat.engine import environment
from heat.engine import resources
@ -191,3 +192,8 @@ class HeatTestCase(testscenarios.WithScenarios,
self.m.StubOutWithMock(nova.ServerConstraint, 'validate')
nova.ServerConstraint.validate(
mox.IgnoreArg(), mox.IgnoreArg()).MultipleTimes().AndReturn(True)
def stub_NetworkConstraint_validate(self):
self.m.StubOutWithMock(neutron.NetworkConstraint, 'validate')
neutron.NetworkConstraint.validate(
mox.IgnoreArg(), mox.IgnoreArg()).MultipleTimes().AndReturn(True)

View File

@ -1836,7 +1836,7 @@ class NeutronRouterTest(common.HeatTestCase):
mox.IsA(neutronclient.Client),
'network',
'fc68ea2c-b60b-4b4f-bd82-94ec81110766'
).AndReturn('fc68ea2c-b60b-4b4f-bd82-94ec81110766')
).MultipleTimes().AndReturn('fc68ea2c-b60b-4b4f-bd82-94ec81110766')
neutronclient.Client.add_gateway_router(
'3e46229d-8fce-4733-819a-b5fe630550f8',
{'network_id': 'fc68ea2c-b60b-4b4f-bd82-94ec81110766'}
@ -1867,7 +1867,7 @@ class NeutronRouterTest(common.HeatTestCase):
mox.IsA(neutronclient.Client),
'network',
'public'
).AndReturn('fc68ea2c-b60b-4b4f-bd82-94ec81110766')
).MultipleTimes().AndReturn('fc68ea2c-b60b-4b4f-bd82-94ec81110766')
neutronclient.Client.create_router({
"router": {
@ -2133,12 +2133,13 @@ class NeutronFloatingIPTest(common.HeatTestCase):
neutronclient.Client.delete_floatingip(
'fc68ea2c-b60b-4b4f-bd82-94ec81110766').AndRaise(
qe.NeutronClientException(status_code=404))
self.stub_NetworkConstraint_validate()
if resolve_neutron:
neutronV20.find_resourceid_by_name_or_id(
mox.IsA(neutronclient.Client),
'network',
'abcd1234'
).AndReturn('abcd1234')
).MultipleTimes().AndReturn('abcd1234')
stack = utils.parse_stack(tmpl)
@ -2176,6 +2177,7 @@ class NeutronFloatingIPTest(common.HeatTestCase):
self.m.VerifyAll()
def test_port(self):
self.stub_NetworkConstraint_validate()
neutronV20.find_resourceid_by_name_or_id(
mox.IsA(neutronclient.Client),
'network',
@ -2278,12 +2280,12 @@ class NeutronFloatingIPTest(common.HeatTestCase):
mox.IsA(neutronclient.Client),
'network',
'abcd1234'
).AndReturn('abcd1234')
).MultipleTimes().AndReturn('abcd1234')
neutronV20.find_resourceid_by_name_or_id(
mox.IsA(neutronclient.Client),
'network',
'xyz1234'
).AndReturn('xyz1234')
).MultipleTimes().AndReturn('xyz1234')
neutronV20.find_resourceid_by_name_or_id(
mox.IsA(neutronclient.Client),
'subnet',
@ -2475,7 +2477,7 @@ class NeutronFloatingIPTest(common.HeatTestCase):
mox.IsA(neutronclient.Client),
'network',
'xyz1234'
).AndReturn('xyz1234')
).MultipleTimes().AndReturn('xyz1234')
neutronV20.find_resourceid_by_name_or_id(
mox.IsA(neutronclient.Client),
'subnet',
@ -2502,7 +2504,7 @@ class NeutronFloatingIPTest(common.HeatTestCase):
mox.IsA(neutronclient.Client),
'network',
'abcd1234'
).AndReturn('abcd1234')
).MultipleTimes().AndReturn('abcd1234')
neutronclient.Client.create_floatingip({
'floatingip': {
'floating_network_id': u'abcd1234',
@ -2608,7 +2610,7 @@ class NeutronPortTest(common.HeatTestCase):
mox.IsA(neutronclient.Client),
'network',
'net1234'
).AndReturn('net1234')
).MultipleTimes().AndReturn('net1234')
neutronclient.Client.create_port({'port': {
'network_id': u'net1234',
'fixed_ips': [
@ -2644,7 +2646,7 @@ class NeutronPortTest(common.HeatTestCase):
mox.IsA(neutronclient.Client),
'network',
'net1234'
).AndReturn('net1234')
).MultipleTimes().AndReturn('net1234')
neutronV20.find_resourceid_by_name_or_id(
mox.IsA(neutronclient.Client),
'subnet',
@ -2685,7 +2687,7 @@ class NeutronPortTest(common.HeatTestCase):
mox.IsA(neutronclient.Client),
'network',
'net1234'
).AndReturn('net1234')
).MultipleTimes().AndReturn('net1234')
neutronclient.Client.create_port({'port': {
'network_id': u'net1234',
'name': utils.PhysName('test_stack', 'port'),
@ -2721,7 +2723,7 @@ class NeutronPortTest(common.HeatTestCase):
mox.IsA(neutronclient.Client),
'network',
'abcd1234'
).AndReturn('abcd1234')
).MultipleTimes().AndReturn('abcd1234')
neutronclient.Client.create_port({'port': {
'network_id': u'abcd1234',
'allowed_address_pairs': [{
@ -2755,7 +2757,7 @@ class NeutronPortTest(common.HeatTestCase):
mox.IsA(neutronclient.Client),
'network',
'abcd1234'
).AndReturn('abcd1234')
).MultipleTimes().AndReturn('abcd1234')
neutronclient.Client.create_port({'port': {
'network_id': u'abcd1234',
'allowed_address_pairs': [{
@ -2791,7 +2793,7 @@ class NeutronPortTest(common.HeatTestCase):
mox.IsA(neutronclient.Client),
'network',
'net1234'
).AndReturn('net1234')
).MultipleTimes().AndReturn('net1234')
neutronV20.find_resourceid_by_name_or_id(
mox.IsA(neutronclient.Client),
'subnet',
@ -2879,7 +2881,7 @@ class NeutronPortTest(common.HeatTestCase):
mox.IsA(neutronclient.Client),
'network',
'net1234'
).AndReturn('net1234')
).MultipleTimes().AndReturn('net1234')
neutronclient.Client.create_port(
{'port': props}
).AndReturn({'port': {
@ -2951,7 +2953,7 @@ class NeutronPortTest(common.HeatTestCase):
mox.IsA(neutronclient.Client),
'network',
'net1234'
).AndReturn('net1234')
).MultipleTimes().AndReturn('net1234')
neutronclient.Client.create_port(
{'port': props}
).AndReturn({'port': {
@ -3013,7 +3015,7 @@ class NeutronPortTest(common.HeatTestCase):
mox.IsA(neutronclient.Client),
'network',
'net1234'
).AndReturn('net1234')
).MultipleTimes().AndReturn('net1234')
neutronclient.Client.create_port({'port': {
'network_id': u'net1234',
'name': utils.PhysName('test_stack', 'port'),
@ -3075,7 +3077,7 @@ class NeutronPortTest(common.HeatTestCase):
mox.IsA(neutronclient.Client),
'network',
'net1234'
).AndReturn('net1234')
).MultipleTimes().AndReturn('net1234')
neutronclient.Client.create_port({'port': {
'network_id': u'net1234',
'name': utils.PhysName('test_stack', 'port'),
@ -3160,6 +3162,8 @@ class NeutronPortTest(common.HeatTestCase):
"status": "ACTIVE",
"id": "fc68ea2c-b60b-4b4f-bd82-94ec81110766"
}})
self.stub_NetworkConstraint_validate()
neutronclient.Client.update_port(
'fc68ea2c-b60b-4b4f-bd82-94ec81110766',
{'port': prop_update}

View File

@ -182,6 +182,7 @@ class NeutronNetworkGatewayTest(common.HeatTestCase):
'port_id': u'32acc49c-899e-44ea-8177-6f4157e12eb4'
}
})
self.stub_NetworkConstraint_validate()
if resolve_neutron:
neutronV20.find_resourceid_by_name_or_id(
mox.IsA(neutronclient.Client),
@ -206,12 +207,9 @@ class NeutronNetworkGatewayTest(common.HeatTestCase):
mox.IsA(neutronclient.Client),
'network',
'6af055d3-26f6-48dd-a597-7611d7e58d35'
).AndReturn('6af055d3-26f6-48dd-a597-7611d7e58d35')
neutronV20.find_resourceid_by_name_or_id(
mox.IsA(neutronclient.Client),
'network',
'6af055d3-26f6-48dd-a597-7611d7e58d35'
).AndReturn('6af055d3-26f6-48dd-a597-7611d7e58d35')
).MultipleTimes().AndReturn(
'6af055d3-26f6-48dd-a597-7611d7e58d35')
neutronclient.Client.disconnect_network_gateway(
'ed4c03b9-8251-4c09-acc4-e59ee9e6aa37', {
'network_id': u'6af055d3-26f6-48dd-a597-7611d7e58d35',
@ -275,6 +273,7 @@ class NeutronNetworkGatewayTest(common.HeatTestCase):
# network, then can delete the network_gateway successful
# without residue network_gateway
rsrc = self.mock_create_fail_network_not_found_delete_success()
self.stub_NetworkConstraint_validate()
self.m.ReplayAll()
rsrc.validate()
@ -508,6 +507,7 @@ class NeutronNetworkGatewayTest(common.HeatTestCase):
}
}
).AndRaise(qe.NeutronClientException)
self.stub_NetworkConstraint_validate()
self.m.ReplayAll()
@ -536,6 +536,7 @@ class NeutronNetworkGatewayTest(common.HeatTestCase):
rsrc = network_gateway.NetworkGateway(
'test_network_gateway',
resource_defns['NetworkGateway'], stack)
self.stub_NetworkConstraint_validate()
self.m.ReplayAll()
@ -557,6 +558,7 @@ class NeutronNetworkGatewayTest(common.HeatTestCase):
rsrc = network_gateway.NetworkGateway(
'test_network_gateway',
resource_defns['NetworkGateway'], stack)
self.stub_NetworkConstraint_validate()
self.m.ReplayAll()

View File

@ -112,6 +112,58 @@ class NovaClientPluginTests(NovaClientPluginTestCase):
self.nova_plugin.get_server, 'idontexist')
self.m.VerifyAll()
def test_get_network_id_by_label(self):
"""Tests the get_net_id_by_label function."""
net = self.m.CreateMockAnything()
net.id = str(uuid.uuid4())
self.nova_client.networks = self.m.CreateMockAnything()
self.nova_client.networks.find(label='net_label').AndReturn(
net)
self.nova_client.networks.find(label='idontexist').AndRaise(
nova_exceptions.NotFound(404))
self.nova_client.networks.find(label='notUnique').AndRaise(
nova_exceptions.NoUniqueMatch())
self.m.ReplayAll()
self.assertEqual(net.id,
self.nova_plugin.get_net_id_by_label('net_label'))
exc = self.assertRaises(
exception.NovaNetworkNotFound,
self.nova_plugin.get_net_id_by_label, 'idontexist')
expected = 'The Nova network (idontexist) could not be found'
self.assertIn(expected, six.text_type(exc))
exc = self.assertRaises(
exception.PhysicalResourceNameAmbiguity,
self.nova_plugin.get_net_id_by_label, 'notUnique')
expected = ('Multiple physical resources were found '
'with name (notUnique)')
self.assertIn(expected, six.text_type(exc))
self.m.VerifyAll()
def test_get_nova_network_id(self):
"""Tests the get_nova_network_id function."""
net = self.m.CreateMockAnything()
net.id = str(uuid.uuid4())
not_existent_net_id = str(uuid.uuid4())
self.nova_client.networks = self.m.CreateMockAnything()
self.nova_client.networks.get(net.id).AndReturn(net)
self.nova_client.networks.get(not_existent_net_id).AndRaise(
nova_exceptions.NotFound(404))
self.nova_client.networks.find(label=not_existent_net_id).AndRaise(
nova_exceptions.NotFound(404))
self.m.ReplayAll()
self.assertEqual(net.id,
self.nova_plugin.get_nova_network_id(net.id))
exc = self.assertRaises(
exception.NovaNetworkNotFound,
self.nova_plugin.get_nova_network_id, not_existent_net_id)
expected = ('The Nova network (%s) could not be found' %
not_existent_net_id)
self.assertIn(expected, six.text_type(exc))
self.m.VerifyAll()
def test_get_status(self):
server = self.m.CreateMockAnything()
server.status = 'ACTIVE'

View File

@ -149,12 +149,16 @@ class OSDBInstanceTest(common.HeatTestCase):
def _stubout_check_create_complete(self, fake_dbinstance):
self.fc.instances.get(fake_dbinstance.id).AndReturn(fake_dbinstance)
def _stubout_validate(self, instance, neutron=None):
def _stubout_validate(self, instance, neutron=None,
mock_net_constraint=False):
if mock_net_constraint:
self.stub_NetworkConstraint_validate()
trove.TroveClientPlugin._create().AndReturn(self.fc)
self.m.StubOutWithMock(self.fc, 'datastore_versions')
self.m.StubOutWithMock(self.fc.datastore_versions, 'list')
self.fc.datastore_versions.list(instance.properties['datastore_type']
).AndReturn([FakeVersion()])
if neutron is not None:
self.m.StubOutWithMock(instance, 'is_using_neutron')
instance.is_using_neutron().AndReturn(bool(neutron))
@ -550,7 +554,8 @@ class OSDBInstanceTest(common.HeatTestCase):
"network": "somenetuuid"
}]
instance = self._setup_test_clouddbinstance('dbinstance_test', t)
self._stubout_validate(instance, neutron=True)
self._stubout_validate(instance, neutron=True,
mock_net_constraint=True)
ex = self.assertRaises(
exception.StackValidationFailed, instance.validate)
@ -622,7 +627,13 @@ class OSDBInstanceTest(common.HeatTestCase):
t['resources']['MySqlCloudDB']['properties']['networks'] = [
{'network': net_id}]
instance = self._setup_test_clouddbinstance('dbinstance_test', t)
self.stub_NetworkConstraint_validate()
self._stubout_common_create()
self.m.StubOutWithMock(neutron.NeutronClientPlugin,
'find_neutron_resource')
neutron.NeutronClientPlugin.find_neutron_resource(
instance.properties.get('networks')[0],
'network', 'network').AndReturn(net_id)
self.fc.instances.create('test', 1, volume={'size': 30},
databases=[],
users=[],
@ -649,13 +660,14 @@ class OSDBInstanceTest(common.HeatTestCase):
t['resources']['MySqlCloudDB']['properties']['networks'] = [
{'network': 'somenetname'}]
instance = self._setup_test_clouddbinstance('dbinstance_test', t)
self.stub_NetworkConstraint_validate()
self._stubout_common_create()
self.patchobject(instance, 'is_using_neutron', return_value=False)
self.m.StubOutWithMock(nova.NovaClientPlugin, '_create')
nova.NovaClientPlugin._create().AndReturn(self.nova)
self.m.StubOutWithMock(self.nova, 'networks')
self.m.StubOutWithMock(self.nova.networks, 'find')
self.nova.networks.find(label='somenetname').AndReturn(FakeNet())
self.fc.instances.create('test', 1, volume={'size': 30},
databases=[],
users=[],

View File

@ -16,7 +16,6 @@ import copy
import mock
import mox
from novaclient import exceptions as nova_exceptions
from oslo.utils import uuidutils
import six
from six.moves.urllib import parse as urlparse
@ -26,6 +25,7 @@ from heat.common.i18n import _
from heat.common import template_format
from heat.db import api as db_api
from heat.engine.clients.os import glance
from heat.engine.clients.os import neutron
from heat.engine.clients.os import nova
from heat.engine.clients.os import swift
from heat.engine import environment
@ -1028,7 +1028,7 @@ class ServersTest(common.HeatTestCase):
self.m.StubOutWithMock(nova.NovaClientPlugin, '_create')
nova.NovaClientPlugin._create().AndReturn(self.fc)
self._mock_get_image_id_success('F17-x86_64-gold', 'image_id')
self.stub_NetworkConstraint_validate()
self.m.ReplayAll()
ex = self.assertRaises(exception.StackValidationFailed,
@ -1828,31 +1828,42 @@ class ServersTest(common.HeatTestCase):
return_server = self.fc.servers.list()[1]
server = self._create_test_server(return_server,
'test_server_create')
self.patchobject(server, 'is_using_neutron', return_value=True)
self.assertIsNone(server._build_nics([]))
self.assertIsNone(server._build_nics(None))
self.assertEqual([{'port-id': 'aaaabbbb'},
{'v4-fixed-ip': '192.0.2.0'}],
server._build_nics([{'port': 'aaaabbbb'},
{'fixed_ip': '192.0.2.0'}]))
self.patchobject(neutron.NeutronClientPlugin, 'resolve_network',
return_value='1234abcd')
self.assertEqual([{'net-id': '1234abcd'}],
server._build_nics([{'uuid': '1234abcd'}]))
self.patchobject(neutron.NeutronClientPlugin, 'resolve_network',
return_value='aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa')
self.assertEqual([{'net-id': 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa'}],
server._build_nics(
[{'network':
'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa'}]))
self.patchobject(server, 'is_using_neutron', return_value=False)
self.assertEqual([{'net-id': 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa'}],
server._build_nics([{'network': 'public'}]))
self.assertRaises(nova_exceptions.NoUniqueMatch,
server._build_nics,
([{'network': 'foo'}]))
expected = ('Multiple physical resources were found with name (foo)')
exc = self.assertRaises(
exception.PhysicalResourceNameAmbiguity,
server._build_nics, ([{'network': 'foo'}]))
self.assertIn(expected, six.text_type(exc))
expected = 'The Nova network (bar) could not be found'
exc = self.assertRaises(
exception.NovaNetworkNotFound,
server._build_nics, ([{'network': 'bar'}]))
self.assertIn(expected, six.text_type(exc))
self.assertRaises(nova_exceptions.NotFound,
server._build_nics,
([{'network': 'bar'}]))
self.m.VerifyAll()
def test_server_without_ip_address(self):
return_server = self.fc.servers.list()[3]
@ -2487,6 +2498,7 @@ class ServersTest(common.HeatTestCase):
return_server.interface_attach(None, new_networks[0]['network'],
new_networks[0]['fixed_ip']).AndReturn(
None)
self.stub_NetworkConstraint_validate()
self.m.ReplayAll()
scheduler.TaskRunner(server.update, update_template)()
@ -2522,6 +2534,7 @@ class ServersTest(common.HeatTestCase):
self.m.StubOutWithMock(return_server, 'interface_attach')
return_server.interface_attach(
new_networks[0]['port'], None, None).AndReturn(None)
self.stub_NetworkConstraint_validate()
self.m.ReplayAll()
@ -2584,6 +2597,7 @@ class ServersTest(common.HeatTestCase):
self.m.StubOutWithMock(return_server, 'interface_attach')
return_server.interface_attach(
new_networks[1]['port'], None, None).AndReturn(None)
self.stub_NetworkConstraint_validate()
self.m.ReplayAll()
scheduler.TaskRunner(server.update, update_template)()