Enable to specify network for Trove Cluster
we should enable heat to specify network for trove cluster after [1] merged [1] https://review.openstack.org/#/c/179443/ Change-Id: I161b7cc1c4824f6aa4a4667bf2d909a2ead81cb4
This commit is contained in:
parent
ee8da54dbc
commit
2441a02c1c
@ -20,6 +20,7 @@ from heat.engine import constraints
|
||||
from heat.engine import properties
|
||||
from heat.engine import resource
|
||||
from heat.engine import support
|
||||
from heat.engine import translation
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
@ -62,9 +63,15 @@ class TroveCluster(resource.Resource):
|
||||
)
|
||||
|
||||
_INSTANCE_KEYS = (
|
||||
FLAVOR, VOLUME_SIZE,
|
||||
FLAVOR, VOLUME_SIZE, NETWORKS,
|
||||
) = (
|
||||
'flavor', 'volume_size',
|
||||
'flavor', 'volume_size', 'networks',
|
||||
)
|
||||
|
||||
_NICS_KEYS = (
|
||||
NET, PORT, V4_FIXED_IP
|
||||
) = (
|
||||
'network', 'port', 'fixed_ip'
|
||||
)
|
||||
|
||||
ATTRIBUTES = (
|
||||
@ -121,10 +128,50 @@ class TroveCluster(resource.Resource):
|
||||
constraints=[
|
||||
constraints.Range(1, 150),
|
||||
]
|
||||
)
|
||||
),
|
||||
NETWORKS: properties.Schema(
|
||||
properties.Schema.LIST,
|
||||
_("List of network interfaces to create on instance."),
|
||||
support_status=support.SupportStatus(version='10.0.0'),
|
||||
default=[],
|
||||
schema=properties.Schema(
|
||||
properties.Schema.MAP,
|
||||
schema={
|
||||
NET: properties.Schema(
|
||||
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},
|
||||
constraints=[
|
||||
constraints.CustomConstraint(
|
||||
'neutron.network')
|
||||
]
|
||||
),
|
||||
PORT: properties.Schema(
|
||||
properties.Schema.STRING,
|
||||
_('Name or UUID of Neutron port to '
|
||||
'attach this NIC to. Either %(port)s '
|
||||
'or %(net)s must be specified.')
|
||||
% {'port': PORT, 'net': NET},
|
||||
constraints=[
|
||||
constraints.CustomConstraint(
|
||||
'neutron.port')
|
||||
],
|
||||
),
|
||||
V4_FIXED_IP: properties.Schema(
|
||||
properties.Schema.STRING,
|
||||
_('Fixed IPv4 address for this NIC.'),
|
||||
constraints=[
|
||||
constraints.CustomConstraint('ip_addr')
|
||||
]
|
||||
),
|
||||
},
|
||||
),
|
||||
),
|
||||
}
|
||||
)
|
||||
)
|
||||
),
|
||||
}
|
||||
|
||||
attributes_schema = {
|
||||
@ -142,6 +189,30 @@ class TroveCluster(resource.Resource):
|
||||
|
||||
entity = 'clusters'
|
||||
|
||||
def translation_rules(self, properties):
|
||||
return [
|
||||
translation.TranslationRule(
|
||||
properties,
|
||||
translation.TranslationRule.RESOLVE,
|
||||
translation_path=[self.INSTANCES, self.NETWORKS, self.NET],
|
||||
client_plugin=self.client_plugin('neutron'),
|
||||
finder='find_resourceid_by_name_or_id',
|
||||
entity='network'),
|
||||
translation.TranslationRule(
|
||||
properties,
|
||||
translation.TranslationRule.RESOLVE,
|
||||
translation_path=[self.INSTANCES, self.NETWORKS, self.PORT],
|
||||
client_plugin=self.client_plugin('neutron'),
|
||||
finder='find_resourceid_by_name_or_id',
|
||||
entity='port'),
|
||||
translation.TranslationRule(
|
||||
properties,
|
||||
translation.TranslationRule.RESOLVE,
|
||||
translation_path=[self.INSTANCES, self.FLAVOR],
|
||||
client_plugin=self.client_plugin(),
|
||||
finder='find_flavor_by_name_or_id'),
|
||||
]
|
||||
|
||||
def _cluster_name(self):
|
||||
return self.properties[self.NAME] or self.physical_resource_name()
|
||||
|
||||
@ -152,11 +223,14 @@ class TroveCluster(resource.Resource):
|
||||
# convert instances to format required by troveclient
|
||||
instances = []
|
||||
for instance in self.properties[self.INSTANCES]:
|
||||
instances.append({
|
||||
'flavorRef': self.client_plugin().find_flavor_by_name_or_id(
|
||||
instance[self.FLAVOR]),
|
||||
'volume': {'size': instance[self.VOLUME_SIZE]}
|
||||
})
|
||||
instance_dict = {
|
||||
'flavorRef': instance[self.FLAVOR],
|
||||
'volume': {'size': instance[self.VOLUME_SIZE]},
|
||||
}
|
||||
instance_nics = self.get_instance_nics(instance)
|
||||
if instance_nics:
|
||||
instance_dict["nics"] = instance_nics
|
||||
instances.append(instance_dict)
|
||||
|
||||
args = {
|
||||
'name': self._cluster_name(),
|
||||
@ -168,6 +242,21 @@ class TroveCluster(resource.Resource):
|
||||
self.resource_id_set(cluster.id)
|
||||
return cluster.id
|
||||
|
||||
def get_instance_nics(self, instance):
|
||||
nics = []
|
||||
for nic in instance[self.NETWORKS]:
|
||||
nic_dict = {}
|
||||
if nic.get(self.NET):
|
||||
nic_dict['net-id'] = nic.get(self.NET)
|
||||
if nic.get(self.PORT):
|
||||
nic_dict['port-id'] = nic.get(self.PORT)
|
||||
ip = nic.get(self.V4_FIXED_IP)
|
||||
if ip:
|
||||
nic_dict['v4-fixed-ip'] = ip
|
||||
nics.append(nic_dict)
|
||||
|
||||
return nics
|
||||
|
||||
def _refresh_cluster(self, cluster_id):
|
||||
try:
|
||||
cluster = self.client().clusters.get(cluster_id)
|
||||
@ -256,6 +345,24 @@ class TroveCluster(resource.Resource):
|
||||
datastore_type, datastore_version,
|
||||
self.DATASTORE_TYPE, self.DATASTORE_VERSION)
|
||||
|
||||
# check validity of instances' NETWORKS
|
||||
is_neutron = self.is_using_neutron()
|
||||
for instance in self.properties[self.INSTANCES]:
|
||||
for nic in instance[self.NETWORKS]:
|
||||
# 'nic.get(self.PORT) is not None' including two cases:
|
||||
# 1. has set port value in template
|
||||
# 2. using 'get_resource' to reference a new resource
|
||||
if not is_neutron and nic.get(self.PORT) is not None:
|
||||
msg = (_("Can not use %s property on Nova-network.")
|
||||
% self.PORT)
|
||||
raise exception.StackValidationFailed(message=msg)
|
||||
|
||||
if (bool(nic.get(self.NET) is not None) ==
|
||||
bool(nic.get(self.PORT) is not None)):
|
||||
msg = (_("Either %(net)s or %(port)s must be provided.")
|
||||
% {'net': self.NET, 'port': self.PORT})
|
||||
raise exception.StackValidationFailed(message=msg)
|
||||
|
||||
def _resolve_attribute(self, name):
|
||||
if self.resource_id is None:
|
||||
return
|
||||
|
@ -18,6 +18,7 @@ from troveclient import exceptions as troveexc
|
||||
|
||||
from heat.common import exception
|
||||
from heat.common import template_format
|
||||
from heat.engine.clients.os import neutron
|
||||
from heat.engine.clients.os import trove
|
||||
from heat.engine.resources.openstack.trove import cluster
|
||||
from heat.engine import scheduler
|
||||
@ -38,10 +39,16 @@ resources:
|
||||
instances:
|
||||
- flavor: m1.heat
|
||||
volume_size: 1
|
||||
networks:
|
||||
- port: port1
|
||||
- flavor: m1.heat
|
||||
volume_size: 1
|
||||
networks:
|
||||
- port: port2
|
||||
- flavor: m1.heat
|
||||
volume_size: 1
|
||||
networks:
|
||||
- port: port3
|
||||
'''
|
||||
|
||||
|
||||
@ -86,6 +93,9 @@ class TroveClusterTest(common.HeatTestCase):
|
||||
self.client = mock_client.return_value
|
||||
self.troveclient = mock.Mock()
|
||||
self.troveclient.flavors.get.return_value = FakeFlavor(1, 'm1.heat')
|
||||
self.patchobject(neutron.NeutronClientPlugin,
|
||||
'find_resourceid_by_name_or_id',
|
||||
return_value='someportid')
|
||||
self.troveclient.datastore_versions.list.return_value = [FakeVersion()]
|
||||
self.patchobject(trove.TroveClientPlugin, 'client',
|
||||
return_value=self.troveclient)
|
||||
@ -106,9 +116,12 @@ class TroveClusterTest(common.HeatTestCase):
|
||||
expected_state = (tc.CREATE, tc.COMPLETE)
|
||||
self.assertEqual(expected_state, tc.state)
|
||||
args = self.client.clusters.create.call_args[1]
|
||||
self.assertEqual([{'flavorRef': 1, 'volume': {'size': 1}},
|
||||
{'flavorRef': 1, 'volume': {'size': 1}},
|
||||
{'flavorRef': 1, 'volume': {'size': 1}}],
|
||||
self.assertEqual([{'flavorRef': '1', 'volume': {'size': 1},
|
||||
'nics': [{'port-id': 'someportid'}]},
|
||||
{'flavorRef': '1', 'volume': {'size': 1},
|
||||
'nics': [{'port-id': 'someportid'}]},
|
||||
{'flavorRef': '1', 'volume': {'size': 1},
|
||||
'nics': [{'port-id': 'someportid'}]}],
|
||||
args['instances'])
|
||||
self.assertEqual('mongodb', args['datastore'])
|
||||
self.assertEqual('2.6.1', args['datastore_version'])
|
||||
|
@ -597,6 +597,63 @@ class TestTranslationRule(common.HeatTestCase):
|
||||
self.assertEqual('yellow', result)
|
||||
self.assertEqual('yellow', tran.resolved_translations['far.0.red'])
|
||||
|
||||
def test_resolve_rule_nested_list_populated(self):
|
||||
client_plugin, schema = self._test_resolve_rule_nested_list()
|
||||
data = {
|
||||
'instances': [{'networks': [{'port': 'port1', 'net': 'net1'}]}]
|
||||
}
|
||||
props = properties.Properties(schema, data)
|
||||
rule = translation.TranslationRule(
|
||||
props,
|
||||
translation.TranslationRule.RESOLVE,
|
||||
['instances', 'networks', 'port'],
|
||||
client_plugin=client_plugin,
|
||||
finder='find_name_id',
|
||||
entity='port'
|
||||
)
|
||||
tran = translation.Translation(props)
|
||||
tran.set_rules([rule])
|
||||
self.assertTrue(tran.has_translation('instances.networks.port'))
|
||||
result = tran.translate('instances.0.networks.0.port',
|
||||
data['instances'][0]['networks'][0]['port'])
|
||||
self.assertEqual('port1_id', result)
|
||||
self.assertEqual('port1_id', tran.resolved_translations[
|
||||
'instances.0.networks.0.port'])
|
||||
|
||||
def _test_resolve_rule_nested_list(self):
|
||||
class FakeClientPlugin(object):
|
||||
def find_name_id(self, entity=None, value=None):
|
||||
if entity == 'net':
|
||||
return 'net1_id'
|
||||
if entity == 'port':
|
||||
return 'port1_id'
|
||||
|
||||
schema = {
|
||||
'instances': properties.Schema(
|
||||
properties.Schema.LIST,
|
||||
schema=properties.Schema(
|
||||
properties.Schema.MAP,
|
||||
schema={
|
||||
'networks': properties.Schema(
|
||||
properties.Schema.LIST,
|
||||
schema=properties.Schema(
|
||||
properties.Schema.MAP,
|
||||
schema={
|
||||
'port': properties.Schema(
|
||||
properties.Schema.STRING,
|
||||
),
|
||||
'net': properties.Schema(
|
||||
properties.Schema.STRING,
|
||||
),
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
)
|
||||
)}
|
||||
|
||||
return FakeClientPlugin(), schema
|
||||
|
||||
def test_resolve_rule_list_with_function(self):
|
||||
client_plugin, schema = self._test_resolve_rule(is_list=True)
|
||||
join_func = cfn_funcs.Join(None,
|
||||
|
@ -0,0 +1,3 @@
|
||||
---
|
||||
features:
|
||||
- Allow to set networks of instances for OS::Trove::Cluster resource.
|
Loading…
Reference in New Issue
Block a user