Change support_status to HIDDEN in res props

There are some resources' properties, where deprecation cycle
is over, so there's necessity to add translation rules for
such properties and change their support_status to HIDDEN.

For information about deprecation process read Heat docs [1].

[1] http://docs.openstack.org/developer/heat/supportstatus.html

Change-Id: I60e5ba28e89333faff263915a568a5e4d8f09505
This commit is contained in:
Peter Razumovsky 2015-10-15 18:27:03 +03:00
parent 588c85a5af
commit 547457828d
12 changed files with 204 additions and 70 deletions

View File

@ -47,10 +47,14 @@ class CloudNetwork(resource.Resource):
"""
support_status = support.SupportStatus(
status=support.DEPRECATED,
message=_('Use OS::Neutron::Net instead.'),
version='2015.1',
previous_status=support.SupportStatus(version='2014.1')
status=support.HIDDEN,
version='6.0.0',
previous_status=support.SupportStatus(
status=support.DEPRECATED,
message=_('Use OS::Neutron::Net instead.'),
version='2015.1',
previous_status=support.SupportStatus(version='2014.1')
)
)
PROPERTIES = (

View File

@ -58,10 +58,13 @@ class ExtraRoute(neutron.NeutronResource):
for resource in six.itervalues(self.stack):
# depend on any RouterInterface in this template with the same
# router_id as this router_id
if (resource.has_interface('OS::Neutron::RouterInterface') and
resource.properties['router_id'] ==
self.properties['router_id']):
deps += (self, resource)
if resource.has_interface('OS::Neutron::RouterInterface'):
dep_router_id = self.client_plugin().resolve_router({
'router': resource.properties.get('router'),
'router_id': None}, 'router', 'router_id')
router_id = self.properties[self.ROUTER_ID]
if dep_router_id == router_id:
deps += (self, resource)
# depend on any RouterGateway in this template with the same
# router_id as this router_id
elif (resource.has_interface('OS::Neutron::RouterGateway') and

View File

@ -92,10 +92,15 @@ class Router(neutron.NeutronResource):
'users only.'),
update_allowed=True,
support_status=support.SupportStatus(
status=support.DEPRECATED,
version='2015.1',
message=_('Use property %s.') % L3_AGENT_IDS,
previous_status=support.SupportStatus(version='2014.1')),
status=support.HIDDEN,
version='6.0.0',
previous_status=support.SupportStatus(
status=support.DEPRECATED,
version='2015.1',
message=_('Use property %s.') % L3_AGENT_IDS,
previous_status=support.SupportStatus(version='2014.1')
)
),
),
L3_AGENT_IDS: properties.Schema(
properties.Schema.LIST,
@ -150,6 +155,21 @@ class Router(neutron.NeutronResource):
),
}
def translation_rules(self):
if self.properties.get(self.L3_AGENT_ID):
return [
properties.TranslationRule(
self.properties,
properties.TranslationRule.ADD,
[self.L3_AGENT_IDS],
[self.properties.get(self.L3_AGENT_ID)]),
properties.TranslationRule(
self.properties,
properties.TranslationRule.DELETE,
[self.L3_AGENT_ID]
)
]
def validate(self):
super(Router, self).validate()
is_distributed = self.properties[self.DISTRIBUTED]
@ -277,10 +297,14 @@ class RouterInterface(neutron.NeutronResource):
properties.Schema.STRING,
_('ID of the router.'),
support_status=support.SupportStatus(
status=support.DEPRECATED,
message=_('Use property %s.') % ROUTER,
version='2015.1',
previous_status=support.SupportStatus(version='2013.1')
status=support.HIDDEN,
version='6.0.0',
previous_status=support.SupportStatus(
status=support.DEPRECATED,
message=_('Use property %s.') % ROUTER,
version='2015.1',
previous_status=support.SupportStatus(version='2013.1')
)
),
constraints=[
constraints.CustomConstraint('neutron.router')
@ -313,10 +337,14 @@ class RouterInterface(neutron.NeutronResource):
properties.Schema.STRING,
_('The port id, either subnet or port_id should be specified.'),
support_status=support.SupportStatus(
status=support.DEPRECATED,
message=_('Use property %s.') % PORT,
version='2015.1',
previous_status=support.SupportStatus(version='2014.1')
status=support.HIDDEN,
version='6.0.0',
previous_status=support.SupportStatus(
status=support.DEPRECATED,
message=_('Use property %s.') % PORT,
version='2015.1',
previous_status=support.SupportStatus(version='2014.1')
)
),
constraints=[
constraints.CustomConstraint('neutron.port')
@ -334,6 +362,18 @@ class RouterInterface(neutron.NeutronResource):
def translation_rules(self):
return [
properties.TranslationRule(
self.properties,
properties.TranslationRule.REPLACE,
[self.PORT],
value_path=[self.PORT_ID]
),
properties.TranslationRule(
self.properties,
properties.TranslationRule.REPLACE,
[self.ROUTER],
value_path=[self.ROUTER_ID]
),
properties.TranslationRule(
self.properties,
properties.TranslationRule.REPLACE,
@ -464,7 +504,12 @@ class RouterGateway(neutron.NeutronResource):
# depend on any RouterInterface in this template with the same
# router_id as this router_id
if resource.has_interface('OS::Neutron::RouterInterface'):
dep_router_id = resource.properties.get(
# Since RouterInterface translates router_id property to
# router, we should correctly resolve it for RouterGateway.
dep_router_id = self.client_plugin().resolve_router({
RouterInterface.ROUTER: resource.properties.get(
RouterInterface.ROUTER),
RouterInterface.ROUTER_ID: None}, RouterInterface.ROUTER,
RouterInterface.ROUTER_ID)
router_id = self.properties[self.ROUTER_ID]
if dep_router_id == router_id:

View File

@ -83,10 +83,14 @@ class VPNService(neutron.NeutronResource):
_('Unique identifier for the router to which the vpn service '
'will be inserted.'),
support_status=support.SupportStatus(
status=support.DEPRECATED,
message=_('Use property %s') % ROUTER,
version='2015.1',
previous_status=support.SupportStatus(version='2013.2')),
status=support.HIDDEN,
version='6.0.0',
previous_status=support.SupportStatus(
status=support.DEPRECATED,
message=_('Use property %s') % ROUTER,
version='2015.1',
previous_status=support.SupportStatus(version='2013.2'))
),
constraints=[
constraints.CustomConstraint('neutron.router')
]
@ -141,6 +145,12 @@ class VPNService(neutron.NeutronResource):
properties.TranslationRule.REPLACE,
[self.SUBNET],
value_path=[self.SUBNET_ID]
),
properties.TranslationRule(
self.properties,
properties.TranslationRule.REPLACE,
[self.ROUTER],
value_path=[self.ROUTER_ID]
)
]

View File

@ -85,10 +85,14 @@ class SaharaCluster(resource.Resource):
properties.Schema.STRING,
_('Name or UUID of the image used to boot Hadoop nodes.'),
support_status=support.SupportStatus(
status=support.DEPRECATED,
message=_('Use property %s.') % IMAGE_ID,
version='2015.1',
previous_status=support.SupportStatus(version='2014.2')),
status=support.HIDDEN,
version='6.0.0',
previous_status=support.SupportStatus(
status=support.DEPRECATED,
message=_('Use property %s.') % IMAGE_ID,
version='2015.1',
previous_status=support.SupportStatus(version='2014.2'))
),
constraints=[
constraints.CustomConstraint('glance.image')
],
@ -130,6 +134,14 @@ class SaharaCluster(resource.Resource):
entity = 'clusters'
def translation_rules(self):
return [properties.TranslationRule(
self.properties,
properties.TranslationRule.REPLACE,
[self.IMAGE_ID],
value_path=[self.IMAGE]
)]
def _validate_depr_keys(self, properties, key, depr_key):
value = properties.get(key)
depr_value = properties.get(depr_key)

View File

@ -54,11 +54,16 @@ class ZaqarQueue(resource.Resource):
_("ID of the queue."),
cache_mode=attributes.Schema.CACHE_NONE,
support_status=support.SupportStatus(
status=support.DEPRECATED,
message=_("Use get_resource|Ref command instead. "
"For example: { get_resource : <resource_name> }"),
version='2015.1',
previous_status=support.SupportStatus(version='2014.1')
status=support.HIDDEN,
version='6.0.0',
previous_status=support.SupportStatus(
status=support.DEPRECATED,
message=_("Use get_resource|Ref command instead. "
"For example: { get_resource : "
"<resource_name> }"),
version='2015.1',
previous_status=support.SupportStatus(version='2014.1')
)
)
),
HREF: attributes.Schema(

View File

@ -631,6 +631,12 @@ class NeutronFloatingIPTest(common.HeatTestCase):
'subnet',
'sub1234'
).MultipleTimes().AndReturn('sub1234')
neutronV20.find_resourceid_by_name_or_id(
mox.IsA(neutronclient.Client),
'router',
'None'
).MultipleTimes().AndReturn('None')
neutronclient.Client.create_port({'port': {
'network_id': u'xyz1234',
'fixed_ips': [

View File

@ -12,8 +12,10 @@
# under the License.
import copy
import mox
from neutronclient.common import exceptions as qe
from neutronclient.neutron import v2_0 as neutronV20
from neutronclient.v2_0 import client as neutronclient
from heat.common import exception
@ -88,6 +90,7 @@ class NeutronNetTest(common.HeatTestCase):
'remove_network_from_dhcp_agent')
self.m.StubOutWithMock(neutronclient.Client,
'list_dhcp_agent_hosting_networks')
self.m.StubOutWithMock(neutronV20, 'find_resourceid_by_name_or_id')
def create_net(self, t, stack, resource_name):
resource_defns = stack.t.resource_definitions(stack)
@ -97,6 +100,12 @@ class NeutronNetTest(common.HeatTestCase):
return rsrc
def test_net(self):
neutronV20.find_resourceid_by_name_or_id(
mox.IsA(neutronclient.Client),
'router',
'None'
).AndReturn('None')
# Create script
neutronclient.Client.create_network({
'network': {

View File

@ -170,7 +170,6 @@ class NeutronRouterTest(common.HeatTestCase):
props['l3_agent_ids'] = ['id1', 'id2']
stack = utils.parse_stack(t)
rsrc = stack['router']
rsrc.t['Properties'].pop('l3_agent_id')
exc = self.assertRaises(exception.ResourcePropertyConflict,
rsrc.validate)
self.assertIn('distributed, l3_agent_id/l3_agent_ids',
@ -184,9 +183,11 @@ class NeutronRouterTest(common.HeatTestCase):
props['l3_agent_ids'] = ['id1', 'id2']
stack = utils.parse_stack(t)
rsrc = stack['router']
exc = self.assertRaises(exception.ResourcePropertyConflict,
exc = self.assertRaises(exception.StackValidationFailed,
rsrc.validate)
self.assertIn('l3_agent_id, l3_agent_ids', six.text_type(exc))
self.assertIn('Non HA routers can only have one L3 agent',
six.text_type(exc))
self.assertIsNone(rsrc.properties.get(rsrc.L3_AGENT_ID))
def test_router_validate_ha_distribute(self):
t = template_format.parse(neutron_template)
@ -197,7 +198,7 @@ class NeutronRouterTest(common.HeatTestCase):
props['distributed'] = True
stack = utils.parse_stack(t)
rsrc = stack['router']
rsrc.t['Properties'].pop('l3_agent_id')
rsrc.t['Properties'].pop('l3_agent_ids')
exc = self.assertRaises(exception.ResourcePropertyConflict,
rsrc.validate)
self.assertIn('distributed, ha', six.text_type(exc))
@ -210,7 +211,6 @@ class NeutronRouterTest(common.HeatTestCase):
props['l3_agent_ids'] = ['id1', 'id2']
stack = utils.parse_stack(t)
rsrc = stack['router']
rsrc.t['Properties'].pop('l3_agent_id')
exc = self.assertRaises(exception.StackValidationFailed,
rsrc.validate)
self.assertIn('Non HA routers can only have one L3 agent.',
@ -403,7 +403,7 @@ class NeutronRouterTest(common.HeatTestCase):
prop_diff = {
"admin_state_up": False,
"name": "myrouter",
"l3_agent_id": "63b3fd83-2c5f-4dad-b3ae-e0f83a40f216"
"l3_agent_ids": ["63b3fd83-2c5f-4dad-b3ae-e0f83a40f216"]
}
props = copy.copy(rsrc.properties.data)
props.update(prop_diff)
@ -458,16 +458,14 @@ class NeutronRouterTest(common.HeatTestCase):
).AndRaise(qe.NeutronClientException(status_code=404))
t = template_format.parse(neutron_template)
stack = utils.parse_stack(t)
router_key = 'router_id'
self.stub_SubnetConstraint_validate()
self.stub_RouterConstraint_validate()
if resolve_router:
neutronV20.find_resourceid_by_name_or_id(
mox.IsA(neutronclient.Client),
'router',
'3e46229d-8fce-4733-819a-b5fe630550f8'
).AndReturn('3e46229d-8fce-4733-819a-b5fe630550f8')
router_key = 'router'
neutronV20.find_resourceid_by_name_or_id(
mox.IsA(neutronclient.Client),
'router',
'3e46229d-8fce-4733-819a-b5fe630550f8'
).AndReturn('3e46229d-8fce-4733-819a-b5fe630550f8')
router_key = 'router'
neutronV20.find_resourceid_by_name_or_id(
mox.IsA(neutronclient.Client),
'subnet',
@ -481,6 +479,13 @@ class NeutronRouterTest(common.HeatTestCase):
router_key: '3e46229d-8fce-4733-819a-b5fe630550f8',
subnet_key: '91e47a57-7508-46fe-afc9-fc454e8580e1'
})
# Ensure that properties correctly translates
if not resolve_router:
self.assertEqual('3e46229d-8fce-4733-819a-b5fe630550f8',
rsrc.properties.get(rsrc.ROUTER))
self.assertIsNone(rsrc.properties.get(rsrc.ROUTER_ID))
scheduler.TaskRunner(rsrc.delete)()
rsrc.state_set(rsrc.CREATE, rsrc.COMPLETE, 'to delete again')
scheduler.TaskRunner(rsrc.delete)()
@ -489,6 +494,12 @@ class NeutronRouterTest(common.HeatTestCase):
def test_router_interface_with_old_data(self):
self.stub_SubnetConstraint_validate()
self.stub_RouterConstraint_validate()
neutronV20.find_resourceid_by_name_or_id(
mox.IsA(neutronclient.Client),
'router',
'3e46229d-8fce-4733-819a-b5fe630550f8'
).AndReturn('3e46229d-8fce-4733-819a-b5fe630550f8')
neutronV20.find_resourceid_by_name_or_id(
mox.IsA(neutronclient.Client),
'subnet',
@ -513,8 +524,8 @@ class NeutronRouterTest(common.HeatTestCase):
rsrc = self.create_router_interface(
t, stack, 'router_interface', properties={
'router_id': '3e46229d-8fce-4733-819a-b5fe630550f8',
'subnet_id': '91e47a57-7508-46fe-afc9-fc454e8580e1'
'router': '3e46229d-8fce-4733-819a-b5fe630550f8',
'subnet': '91e47a57-7508-46fe-afc9-fc454e8580e1'
})
self.assertEqual('3e46229d-8fce-4733-819a-b5fe630550f8'
':subnet_id=91e47a57-7508-46fe-afc9-fc454e8580e1',
@ -536,18 +547,22 @@ class NeutronRouterTest(common.HeatTestCase):
self._test_router_interface_with_port(resolve_port=False)
def _test_router_interface_with_port(self, resolve_port=True):
port_key = 'port_id'
neutronV20.find_resourceid_by_name_or_id(
mox.IsA(neutronclient.Client),
'router',
'ae478782-53c0-4434-ab16-49900c88016c'
).AndReturn('ae478782-53c0-4434-ab16-49900c88016c')
port_key = 'port'
neutronV20.find_resourceid_by_name_or_id(
mox.IsA(neutronclient.Client),
'port',
'9577cafd-8e98-4059-a2e6-8a771b4d318e'
).AndReturn('9577cafd-8e98-4059-a2e6-8a771b4d318e')
neutronclient.Client.add_interface_router(
'ae478782-53c0-4434-ab16-49900c88016c',
{'port_id': '9577cafd-8e98-4059-a2e6-8a771b4d318e'}
).AndReturn(None)
if resolve_port:
port_key = 'port'
neutronV20.find_resourceid_by_name_or_id(
mox.IsA(neutronclient.Client),
'port',
'9577cafd-8e98-4059-a2e6-8a771b4d318e'
).AndReturn('9577cafd-8e98-4059-a2e6-8a771b4d318e')
neutronclient.Client.remove_interface_router(
'ae478782-53c0-4434-ab16-49900c88016c',
@ -566,9 +581,16 @@ class NeutronRouterTest(common.HeatTestCase):
rsrc = self.create_router_interface(
t, stack, 'router_interface', properties={
'router_id': 'ae478782-53c0-4434-ab16-49900c88016c',
'router': 'ae478782-53c0-4434-ab16-49900c88016c',
port_key: '9577cafd-8e98-4059-a2e6-8a771b4d318e'
})
# Ensure that properties correctly translates
if not resolve_port:
self.assertEqual('9577cafd-8e98-4059-a2e6-8a771b4d318e',
rsrc.properties.get(rsrc.PORT))
self.assertIsNone(rsrc.properties.get(rsrc.PORT_ID))
scheduler.TaskRunner(rsrc.delete)()
rsrc.state_set(rsrc.CREATE, rsrc.COMPLETE, 'to delete again')
scheduler.TaskRunner(rsrc.delete)()

View File

@ -117,6 +117,11 @@ class NeutronSubnetTest(common.HeatTestCase):
'network',
'None'
).AndReturn('None')
neutronV20.find_resourceid_by_name_or_id(
mox.IsA(neutronclient.Client),
'router',
'None'
).AndReturn('None')
stack = utils.parse_stack(t)
rsrc = self.create_subnet(t, stack, 'sub_net')
self.m.ReplayAll()
@ -169,6 +174,11 @@ class NeutronSubnetTest(common.HeatTestCase):
'network',
'None'
).AndReturn('None')
neutronV20.find_resourceid_by_name_or_id(
mox.IsA(neutronclient.Client),
'router',
'None'
).AndReturn('None')
self.m.ReplayAll()
scheduler.TaskRunner(rsrc.create)()
self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state)

View File

@ -136,16 +136,16 @@ class VPNServiceTest(common.HeatTestCase):
'subnet',
'sub123'
).AndReturn('sub123')
neutronV20.find_resourceid_by_name_or_id(
mox.IsA(neutronclient.Client),
'router',
'rou123'
).AndReturn('rou123')
if resolve_neutron:
snippet = template_format.parse(vpnservice_template)
else:
snippet = template_format.parse(vpnservice_template_deprecated)
if resolve_router:
neutronV20.find_resourceid_by_name_or_id(
mox.IsA(neutronclient.Client),
'router',
'rou123'
).AndReturn('rou123')
props = snippet['resources']['VPNService']['properties']
props['router'] = 'rou123'
del props['router_id']
@ -172,6 +172,11 @@ class VPNServiceTest(common.HeatTestCase):
self.m.ReplayAll()
scheduler.TaskRunner(rsrc.create)()
self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state)
# Ensure that property translates
if not resolve_router:
self.assertEqual('rou123', rsrc.properties.get(rsrc.ROUTER))
self.assertIsNone(rsrc.properties.get(rsrc.ROUTER_ID))
self.m.VerifyAll()
def test_create_failed(self):
@ -180,6 +185,11 @@ class VPNServiceTest(common.HeatTestCase):
'subnet',
'sub123'
).MultipleTimes().AndReturn('sub123')
neutronV20.find_resourceid_by_name_or_id(
mox.IsA(neutronclient.Client),
'router',
'rou123'
).MultipleTimes().AndReturn('rou123')
self.stub_RouterConstraint_validate()
neutronclient.Client.create_vpnservice(self.VPN_SERVICE_CONF).AndRaise(

View File

@ -182,7 +182,7 @@ class SaharaClusterTest(common.HeatTestCase):
self.assertEqual("neutron_management_network must be provided",
six.text_type(ex))
def test_validation_error_for_deprecated_properties(self):
def test_deprecated_properties_correctly_translates(self):
tmpl = '''
heat_template_version: 2013-05-23
description: Hadoop Cluster by Sahara
@ -195,11 +195,9 @@ resources:
hadoop_version: 2.3.0
cluster_template_id: some_cluster_template_id
image: some_image
default_image_id: test_image_id
key_name: admin
neutron_management_network: some_network
'''
ct = self._init_cluster(template_format.parse(tmpl))
ex = self.assertRaises(exception.ResourcePropertyConflict, ct.validate)
msg = 'Cannot define the following properties at the same time: '
self.assertIn(msg, six.text_type(ex))
ct = self._create_cluster(template_format.parse(tmpl))
self.assertEqual('some_image', ct.properties.get('default_image_id'))
self.assertIsNone(ct.properties.get('image'))