Apply nova server constraints for resources

Add nova server custom constraint for related
resources.

Change-Id: I0acade2d0b30a9fde1e59cfa7cc5ffb7e0a36850
Implements: blueprint nova-custom-constraints
This commit is contained in:
huangtianhua 2014-11-13 17:41:07 +08:00
parent 5432982c79
commit 8a56cafe2b
10 changed files with 87 additions and 35 deletions

View File

@ -53,7 +53,10 @@ class ElasticIp(resource.Resource):
INSTANCE_ID: properties.Schema(
properties.Schema.STRING,
_('Instance ID to associate with EIP.'),
update_allowed=True
update_allowed=True,
constraints=[
constraints.CustomConstraint('nova.server')
]
),
}
@ -190,7 +193,10 @@ class ElasticIpAssociation(resource.Resource):
INSTANCE_ID: properties.Schema(
properties.Schema.STRING,
_('Instance ID to associate with EIP specified by EIP property.'),
update_allowed=True
update_allowed=True,
constraints=[
constraints.CustomConstraint('nova.server')
]
),
EIP: properties.Schema(
properties.Schema.STRING,
@ -354,7 +360,7 @@ class ElasticIpAssociation(resource.Resource):
def _validate_update_properties(self, prop_diff):
# according to aws doc, when update allocation_id or eip,
# if you also change the InstanceId or NetworkInterfaceId,
# should go to Replacement flow
# should go to Replacement flow
if self.ALLOCATION_ID in prop_diff or self.EIP in prop_diff:
instance_id = prop_diff.get(self.INSTANCE_ID)
ni_id = prop_diff.get(self.NETWORK_INTERFACE_ID)

View File

@ -50,7 +50,10 @@ class Restarter(signal_responder.SignalResponder):
INSTANCE_ID: properties.Schema(
properties.Schema.STRING,
_('Instance ID to be restarted.'),
required=True
required=True,
constraints=[
constraints.CustomConstraint('nova.server')
]
),
}

View File

@ -16,6 +16,7 @@ from oslo.utils import excutils
from heat.common.i18n import _
from heat.common.i18n import _LE
from heat.engine import attributes
from heat.engine import constraints
from heat.engine import properties
from heat.engine import resource
from heat.engine import support
@ -109,7 +110,10 @@ class NovaFloatingIpAssociation(resource.Resource):
properties.Schema.STRING,
_('Server to assign floating IP to.'),
required=True,
update_allowed=True
update_allowed=True,
constraints=[
constraints.CustomConstraint('nova.server')
]
),
FLOATING_IP: properties.Schema(
properties.Schema.STRING,

View File

@ -115,6 +115,9 @@ class SoftwareDeployment(signal_responder.SignalResponder):
SERVER: properties.Schema(
properties.Schema.STRING,
_('ID of Nova server to apply configuration to.'),
constraints=[
constraints.CustomConstraint('nova.server')
]
),
INPUT_VALUES: properties.Schema(
properties.Schema.MAP,

View File

@ -420,7 +420,10 @@ class VolumeAttachment(resource.Resource):
properties.Schema.STRING,
_('The ID of the instance to which the volume attaches.'),
immutable=True,
required=True
required=True,
constraints=[
constraints.CustomConstraint('nova.server')
]
),
VOLUME_ID: properties.Schema(
properties.Schema.STRING,

View File

@ -183,10 +183,20 @@ class EIPTest(common.HeatTestCase):
self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state)
return rsrc
def _mock_server_get(self, server='WebServer', mock_server=None,
multiple=False, mock_again=False):
if not mock_again:
nova.NovaClientPlugin._create().AndReturn(self.fc)
if multiple:
self.fc.servers.get(server).MultipleTimes().AndReturn(
mock_server)
else:
self.fc.servers.get(server).AndReturn(mock_server)
def test_eip(self):
nova.NovaClientPlugin._create().AndReturn(self.fc)
self.fc.servers.get('WebServer').AndReturn(self.fc.servers.list()[0])
self.fc.servers.get('WebServer')
mock_server = self.fc.servers.list()[0]
self._mock_server_get(mock_server=mock_server)
self._mock_server_get(mock_again=True)
self.m.ReplayAll()
@ -211,12 +221,12 @@ class EIPTest(common.HeatTestCase):
self.m.VerifyAll()
def test_eip_update(self):
nova.NovaClientPlugin._create().AndReturn(self.fc)
server_old = self.fc.servers.list()[0]
self.fc.servers.get('WebServer').AndReturn(server_old)
self._mock_server_get(mock_server=server_old)
server_update = self.fc.servers.list()[1]
self.fc.servers.get('5678').MultipleTimes().AndReturn(server_update)
self._mock_server_get(server='5678', mock_server=server_update,
multiple=True, mock_again=True)
self.m.ReplayAll()
t = template_format.parse(eip_template)
@ -243,9 +253,8 @@ class EIPTest(common.HeatTestCase):
self.m.VerifyAll()
def test_association_eip(self):
nova.NovaClientPlugin._create().AndReturn(self.fc)
self.fc.servers.get('WebServer').MultipleTimes() \
.AndReturn(self.fc.servers.list()[0])
server = self.fc.servers.list()[0]
self._mock_server_get(mock_server=server, multiple=True)
self.m.ReplayAll()
@ -319,8 +328,7 @@ class EIPTest(common.HeatTestCase):
self.fc.floating_ips.create().AndReturn(floating_ip)
server = self.fc.servers.list()[0]
nova.NovaClientPlugin._create().AndReturn(self.fc)
self.fc.servers.get('WebServer').MultipleTimes().AndReturn(server)
self._mock_server_get(mock_server=server, multiple=True)
self.m.StubOutWithMock(self.fc.servers, 'add_floating_ip')
self.fc.servers.add_floating_ip(server, floating_ip.ip, None).\
@ -415,6 +423,16 @@ class AllocTest(common.HeatTestCase):
"id": "22c26451-cf27-4d48-9031-51f5e397b84e"
}})
def _mock_server_get(self, server='WebServer', mock_server=None,
multiple=False, mock_again=False):
if not mock_again:
nova.NovaClientPlugin._create().AndReturn(self.fc)
if multiple:
self.fc.servers.get(server).MultipleTimes().AndReturn(
mock_server)
else:
self.fc.servers.get(server).AndReturn(mock_server)
def create_eip(self, t, stack, resource_name):
resource_defns = stack.t.resource_definitions(stack)
rsrc = eip.ElasticIp(resource_name,
@ -545,10 +563,9 @@ class AllocTest(common.HeatTestCase):
})
def test_neutron_eip(self):
nova.NovaClientPlugin._create().AndReturn(self.fc)
self.fc.servers.get('WebServer').AndReturn(self.fc.servers.list()[0])
self.fc.servers.get('WebServer')
mock_server = self.fc.servers.list()[0]
self._mock_server_get(mock_server=mock_server)
self._mock_server_get(mock_again=True)
self.m.ReplayAll()
t = template_format.parse(eip_template)
@ -565,7 +582,6 @@ class AllocTest(common.HeatTestCase):
self.assertRaises(exception.InvalidTemplateAttribute,
rsrc.FnGetAtt, 'Foo')
finally:
scheduler.TaskRunner(rsrc.destroy)()
@ -599,6 +615,10 @@ class AllocTest(common.HeatTestCase):
self.m.VerifyAll()
def test_association_allocationid_with_instance(self):
server = self.fc.servers.list()[0]
self._mock_server_get(server='1fafbe59-2332-4f5f-bfa4-517b4d6c1b65',
mock_server=server,
multiple=True)
self.mock_show_network()
self.mock_create_floatingip()
@ -625,6 +645,9 @@ class AllocTest(common.HeatTestCase):
self.m.VerifyAll()
def test_validate_properties_EIP_and_AllocationId(self):
self._mock_server_get(server='1fafbe59-2332-4f5f-bfa4-517b4d6c1b65',
multiple=True)
self.m.ReplayAll()
template, stack = self._setup_test_stack(
stack_name='validate_EIP_AllocationId')
@ -639,6 +662,8 @@ class AllocTest(common.HeatTestCase):
properties.pop('EIP')
self._validate_properties(stack, template, expected)
self.m.VerifyAll()
def test_validate_EIP_and_InstanceId(self):
template, stack = self._setup_test_stack(
stack_name='validate_EIP_InstanceId')
@ -663,10 +688,8 @@ class AllocTest(common.HeatTestCase):
self._validate_properties(stack, template, expected)
def test_delete_association_successful_if_create_failed(self):
nova.NovaClientPlugin._create().AndReturn(self.fc)
server = self.fc.servers.list()[0]
self.fc.servers.get('WebServer').MultipleTimes() \
.AndReturn(server)
self._mock_server_get(mock_server=server, multiple=True)
self.m.StubOutWithMock(self.fc.servers, 'add_floating_ip')
self.fc.servers.add_floating_ip(server, '11.0.0.1').AndRaise(
fakes.fake_exception(400))
@ -691,12 +714,14 @@ class AllocTest(common.HeatTestCase):
self.m.VerifyAll()
def test_update_association_with_InstanceId(self):
nova.NovaClientPlugin._create().AndReturn(self.fc)
server = self.fc.servers.list()[0]
self.fc.servers.get('WebServer').MultipleTimes() \
.AndReturn(server)
self._mock_server_get(mock_server=server, multiple=True)
server_update = self.fc.servers.list()[1]
self.fc.servers.get('5678').AndReturn(server_update)
self._mock_server_get(server='5678',
mock_server=server_update,
multiple=True,
mock_again=True)
self.m.ReplayAll()
@ -719,10 +744,8 @@ class AllocTest(common.HeatTestCase):
self.m.VerifyAll()
def test_update_association_with_EIP(self):
nova.NovaClientPlugin._create().AndReturn(self.fc)
server = self.fc.servers.list()[0]
self.fc.servers.get('WebServer').MultipleTimes() \
.AndReturn(server)
self._mock_server_get(mock_server=server, multiple=True)
self.m.ReplayAll()
@ -744,10 +767,8 @@ class AllocTest(common.HeatTestCase):
self.m.VerifyAll()
def test_update_association_with_AllocationId_or_EIP(self):
nova.NovaClientPlugin._create().AndReturn(self.fc)
server = self.fc.servers.list()[0]
self.fc.servers.get('WebServer').MultipleTimes()\
.AndReturn(server)
self._mock_server_get(mock_server=server, multiple=True)
self.mock_list_instance_ports('WebServer')
self.mock_show_network()
@ -801,6 +822,8 @@ class AllocTest(common.HeatTestCase):
self.mock_update_floatingip(
port='a000228d-b40b-4124-8394-a4082ae1b76b')
update_server = self.fc.servers.list()[0]
self._mock_server_get(server='5678', mock_server=update_server)
self.mock_list_instance_ports('5678')
self.mock_show_network()
self.mock_no_router_for_vpc()

View File

@ -70,6 +70,8 @@ class NovaFloatingIPTest(common.HeatTestCase):
self.m.StubOutWithMock(self.novaclient.servers, 'add_floating_ip')
self.m.StubOutWithMock(self.novaclient.servers, 'remove_floating_ip')
self.stub_keystoneclient()
nova.NovaClientPlugin.get_server = mock.Mock(
return_value=mock.MagicMock())
def _make_obj(self, **kwargs):
mock = self.m.CreateMockAnything()

View File

@ -14,6 +14,7 @@
import mock
from heat.common import template_format
from heat.engine.clients.os import nova
from heat.engine.resources import instance
from heat.engine import scheduler
from heat.tests import common
@ -47,6 +48,8 @@ class RestarterTest(common.HeatTestCase):
resource_defns = stack.t.resource_definitions(stack)
restarter = instance.Restarter(
'restarter', resource_defns['restarter'], stack)
nova.NovaClientPlugin.get_server = mock.Mock(
return_value=mock.MagicMock())
restarter.handle_create = mock.Mock(return_value=None)
return restarter

View File

@ -17,6 +17,7 @@ import six
from heat.common import exception as exc
from heat.common.i18n import _
from heat.engine.clients.os import nova
from heat.engine import parser
from heat.engine.resources.software_config import software_deployment as sd
from heat.engine import rsrc_defn
@ -106,6 +107,8 @@ class SoftwareDeploymentTest(common.HeatTestCase):
stack_user_project_id='65728b74-cfe7-4f17-9c15-11d4f686e591'
)
nova.NovaClientPlugin.get_server = mock.Mock(
return_value=mock.MagicMock())
self.patchobject(sd.SoftwareDeployment, '_create_user')
self.patchobject(sd.SoftwareDeployment, '_create_keypair')
self.patchobject(sd.SoftwareDeployment, '_delete_user')

View File

@ -750,6 +750,8 @@ class VolumeTest(BaseVolumeTest):
"range (min: 1, max: None)", six.text_type(error))
def test_volume_attachment_updates_not_supported(self):
nova.NovaClientPlugin.get_server = mock.Mock(
return_value=mock.MagicMock())
fv = FakeVolume('creating', 'available')
fva = FakeVolume('attaching', 'in-use')
stack_name = 'test_volume_attach_stack'