summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorspisarski <s.pisarski@cablelabs.com>2018-01-11 10:24:32 -0700
committerspisarski <s.pisarski@cablelabs.com>2018-01-11 12:00:23 -0700
commit97cee572f017696415b212024fc28c85b892b0cd (patch)
treecbc2bafe602f31b8c19d890ab43e90165de10874
parentc0aee4c0d7620a32f5314ca938e4aca10c27adda (diff)
Fixed vm instance instantiation from Heat when using nested resources
* Simplified the configuration of file resources * Added integration test JIRA: SNAPS-255 Change-Id: I1065d9352865d7a9f946a5d9947e32e7340f20bc Signed-off-by: spisarski <s.pisarski@cablelabs.com>
-rw-r--r--docs/how-to-use/IntegrationTests.rst12
-rw-r--r--snaps/config/stack.py12
-rw-r--r--snaps/config/tests/stack_tests.py19
-rw-r--r--snaps/openstack/create_stack.py3
-rw-r--r--snaps/openstack/tests/create_stack_tests.py108
-rw-r--r--snaps/openstack/tests/heat/agent-group.yaml115
-rw-r--r--snaps/openstack/tests/heat/agent.yaml110
-rw-r--r--snaps/openstack/utils/heat_utils.py54
-rw-r--r--snaps/openstack/utils/tests/heat_utils_tests.py4
-rw-r--r--snaps/test_suite_builder.py9
10 files changed, 418 insertions, 28 deletions
diff --git a/docs/how-to-use/IntegrationTests.rst b/docs/how-to-use/IntegrationTests.rst
index b7aa864..eb627ad 100644
--- a/docs/how-to-use/IntegrationTests.rst
+++ b/docs/how-to-use/IntegrationTests.rst
@@ -419,6 +419,18 @@ create_stack_tests.py - CreateStackFloatingIpTests
| | | OpenStackVmInstance |
+---------------------------------------+---------------+-----------------------------------------------------------+
+create_stack_tests.py - CreateStackNestedResourceTests
+------------------------------------------------------
+
++---------------------------------------+---------------+-----------------------------------------------------------+
+| Test Name | Heat API | Description |
++=======================================+===============+===========================================================+
+| test_nested | 1 | Ensures that an OpenStackHeatStack with an external |
+| | | resource file with VMs with floating IPs can be accessed |
+| | | in the class OpenStackVmInstance and return the associated|
+| | | initialized OpenStackVmInstance objects |
++---------------------------------------+---------------+-----------------------------------------------------------+
+
create_stack_tests.py - CreateStackRouterTests
----------------------------------------------
diff --git a/snaps/config/stack.py b/snaps/config/stack.py
index fd427af..4d5db29 100644
--- a/snaps/config/stack.py
+++ b/snaps/config/stack.py
@@ -35,19 +35,17 @@ class StackConfig(object):
template_path attribute is None)
:param template_path: the location of the heat template file (required
if template attribute is None)
+ :param resource_files: List of file paths to the resources referred to
+ by the template
:param env_values: dict() of strings for substitution of template
default values (optional)
- :param files: Supplies the contents of files referenced in the template
- or the environment. This object must be a dict() of
- strings where the key is the file URI or filename and the
- value contains the file's contents (optional)
"""
self.name = kwargs.get('name')
self.template = kwargs.get('template')
self.template_path = kwargs.get('template_path')
+ self.resource_files = kwargs.get('resource_files')
self.env_values = kwargs.get('env_values')
- self.files = kwargs.get('files')
if 'stack_create_timeout' in kwargs:
self.stack_create_timeout = kwargs['stack_create_timeout']
@@ -60,6 +58,10 @@ class StackConfig(object):
if not self.template and not self.template_path:
raise StackConfigError('A Heat template is required')
+ if self.resource_files and not isinstance(self.resource_files, list):
+ raise StackConfigError(
+ 'resource_files must be a list when not None')
+
def __eq__(self, other):
return (self.name == other.name and
self.template == other.template and
diff --git a/snaps/config/tests/stack_tests.py b/snaps/config/tests/stack_tests.py
index cf6e7d8..773e9c2 100644
--- a/snaps/config/tests/stack_tests.py
+++ b/snaps/config/tests/stack_tests.py
@@ -39,11 +39,16 @@ class StackConfigUnitTests(unittest.TestCase):
with self.assertRaises(StackConfigError):
StackConfig(**{'name': 'foo'})
+ def test_resource_not_list(self):
+ with self.assertRaises(StackConfigError):
+ StackConfig(**{'name': 'foo', 'resource_files': 'bar'})
+
def test_config_minimum_template(self):
settings = StackConfig(**{'name': 'stack', 'template': 'foo'})
self.assertEqual('stack', settings.name)
self.assertEqual('foo', settings.template)
self.assertIsNone(settings.template_path)
+ self.assertIsNone(settings.resource_files)
self.assertIsNone(settings.env_values)
self.assertEqual(snaps.config.stack.STACK_COMPLETE_TIMEOUT,
settings.stack_create_timeout)
@@ -53,6 +58,7 @@ class StackConfigUnitTests(unittest.TestCase):
self.assertEqual('stack', settings.name)
self.assertIsNone(settings.template)
self.assertEqual('foo', settings.template_path)
+ self.assertIsNone(settings.resource_files)
self.assertIsNone(settings.env_values)
self.assertEqual(snaps.config.stack.STACK_COMPLETE_TIMEOUT,
settings.stack_create_timeout)
@@ -62,6 +68,7 @@ class StackConfigUnitTests(unittest.TestCase):
self.assertEqual('stack', settings.name)
self.assertEqual('foo', settings.template)
self.assertIsNone(settings.template_path)
+ self.assertIsNone(settings.resource_files)
self.assertIsNone(settings.env_values)
self.assertEqual(snaps.config.stack.STACK_COMPLETE_TIMEOUT,
settings.stack_create_timeout)
@@ -71,6 +78,18 @@ class StackConfigUnitTests(unittest.TestCase):
self.assertEqual('stack', settings.name)
self.assertEqual('foo', settings.template_path)
self.assertIsNone(settings.template)
+ self.assertIsNone(settings.resource_files)
+ self.assertIsNone(settings.env_values)
+ self.assertEqual(snaps.config.stack.STACK_COMPLETE_TIMEOUT,
+ settings.stack_create_timeout)
+
+ def test_resource(self):
+ settings = StackConfig(
+ name='stack', template_path='foo', resource_files=['foo', 'bar'])
+ self.assertEqual('stack', settings.name)
+ self.assertEqual('foo', settings.template_path)
+ self.assertIsNone(settings.template)
+ self.assertEqual(['foo', 'bar'], settings.resource_files)
self.assertIsNone(settings.env_values)
self.assertEqual(snaps.config.stack.STACK_COMPLETE_TIMEOUT,
settings.stack_create_timeout)
diff --git a/snaps/openstack/create_stack.py b/snaps/openstack/create_stack.py
index 74fde9d..d4a6b10 100644
--- a/snaps/openstack/create_stack.py
+++ b/snaps/openstack/create_stack.py
@@ -467,7 +467,8 @@ class OpenStackHeatStack(OpenStackCloudObject, object):
return False
if fail_status and status == fail_status:
- resources = heat_utils.get_resources(self.__heat_cli, self.__stack)
+ resources = heat_utils.get_resources(
+ self.__heat_cli, self.__stack.id)
logger.error('Stack %s failed', self.__stack.name)
for resource in resources:
if (resource.status !=
diff --git a/snaps/openstack/tests/create_stack_tests.py b/snaps/openstack/tests/create_stack_tests.py
index 2db89e5..6041735 100644
--- a/snaps/openstack/tests/create_stack_tests.py
+++ b/snaps/openstack/tests/create_stack_tests.py
@@ -506,6 +506,112 @@ class CreateStackFloatingIpTests(OSIntegrationTestCase):
self.assertEqual(0, len(vm_settings.floating_ip_settings))
+class CreateStackNestedResourceTests(OSIntegrationTestCase):
+ """
+ Tests to ensure that nested heat templates work
+ """
+
+ def setUp(self):
+
+ super(self.__class__, self).__start__()
+
+ self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
+
+ self.heat_creds = self.admin_os_creds
+ self.heat_creds.project_name = self.admin_os_creds.project_name
+
+ self.heat_cli = heat_utils.heat_client(self.heat_creds)
+ self.stack_creator = None
+
+ self.image_creator = OpenStackImage(
+ self.heat_creds, openstack_tests.cirros_image_settings(
+ name=self.guid + '-image',
+ image_metadata=self.image_metadata))
+ self.image_creator.create()
+
+ self.flavor_creator = OpenStackFlavor(
+ self.admin_os_creds,
+ FlavorConfig(
+ name=self.guid + '-flavor-name', ram=256, disk=10, vcpus=1))
+ self.flavor_creator.create()
+
+ env_values = {
+ 'public_network': self.ext_net_name,
+ 'agent_image': self.image_creator.image_settings.name,
+ 'agent_flavor': self.flavor_creator.flavor_settings.name,
+ }
+
+ heat_tmplt_path = pkg_resources.resource_filename(
+ 'snaps.openstack.tests.heat', 'agent-group.yaml')
+ heat_resource_path = pkg_resources.resource_filename(
+ 'snaps.openstack.tests.heat', 'agent.yaml')
+
+ stack_settings = StackConfig(
+ name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
+ template_path=heat_tmplt_path,
+ resource_files=[heat_resource_path],
+ env_values=env_values)
+
+ self.stack_creator = OpenStackHeatStack(
+ self.heat_creds, stack_settings,
+ [self.image_creator.image_settings])
+
+ self.vm_inst_creators = list()
+
+ def tearDown(self):
+ """
+ Cleans the stack and downloaded stack file
+ """
+ if self.stack_creator:
+ try:
+ self.stack_creator.clean()
+ except:
+ pass
+
+ if self.image_creator:
+ try:
+ self.image_creator.clean()
+ except:
+ pass
+
+ if self.flavor_creator:
+ try:
+ self.flavor_creator.clean()
+ except:
+ pass
+
+ for vm_inst_creator in self.vm_inst_creators:
+ try:
+ keypair_settings = vm_inst_creator.keypair_settings
+ if keypair_settings and keypair_settings.private_filepath:
+ expanded_path = os.path.expanduser(
+ keypair_settings.private_filepath)
+ os.chmod(expanded_path, 0o755)
+ os.remove(expanded_path)
+ except:
+ pass
+
+ super(self.__class__, self).__clean__()
+
+ def test_nested(self):
+ """
+ Tests the creation of an OpenStack stack from Heat template file and
+ the retrieval of two VM instance creators and attempt to connect via
+ SSH to the first one with a floating IP.
+ """
+ created_stack = self.stack_creator.create()
+ self.assertIsNotNone(created_stack)
+
+ self.vm_inst_creators = self.stack_creator.get_vm_inst_creators(
+ heat_keypair_option='private_key')
+ self.assertIsNotNone(self.vm_inst_creators)
+ self.assertEqual(1, len(self.vm_inst_creators))
+
+ for vm_inst_creator in self.vm_inst_creators:
+ self.assertTrue(
+ create_instance_tests.validate_ssh_client(vm_inst_creator))
+
+
class CreateStackRouterTests(OSIntegrationTestCase):
"""
Tests for the CreateStack class defined in create_stack.py where the
@@ -1056,7 +1162,7 @@ class CreateStackFailureTests(OSIntegrationTestCase):
self.stack_creator.create()
except StackError:
resources = heat_utils.get_resources(
- self.heat_cli, self.stack_creator.get_stack())
+ self.heat_cli, self.stack_creator.get_stack().id)
found = False
for resource in resources:
diff --git a/snaps/openstack/tests/heat/agent-group.yaml b/snaps/openstack/tests/heat/agent-group.yaml
new file mode 100644
index 0000000..540ea93
--- /dev/null
+++ b/snaps/openstack/tests/heat/agent-group.yaml
@@ -0,0 +1,115 @@
+##############################################################################
+# Copyright (c) 2017 Cable Television Laboratories, Inc. ("CableLabs")
+# and others. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at:
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+##############################################################################
+heat_template_version: 2013-05-23
+
+parameters:
+ public_network:
+ type: string
+ constraints:
+ - custom_constraint: neutron.network
+ agent_flavor:
+ type: string
+ agent_image:
+ type: string
+ volume_size:
+ type: number
+ description: Size of the volume to be created.
+ default: 1
+ constraints:
+ - range: { min: 1, max: 1024 }
+ description: must be between 1 and 1024 Gb.
+ agent_count:
+ type: number
+ default: 1
+ constraints:
+ - range: { min: 1, max: 512 }
+ description: must be between 1 and 512 agents.
+ availability_zone:
+ type: string
+ default: nova
+
+resources:
+ slaves:
+ type: OS::Heat::ResourceGroup
+ depends_on: [subnet, network_router_interface,
+ open_security_group, key_pair]
+ properties:
+ count: {get_param: agent_count}
+ resource_def: {
+ type: "agent.yaml",
+ properties: {
+ public_network: {get_param: public_network},
+ agent_network: {get_resource: network},
+ flavor: {get_param: agent_flavor},
+ image: {get_param: agent_image},
+ availability_zone: {get_param: availability_zone},
+ open_security_group: {get_resource: open_security_group},
+ key_name: {get_resource: key_pair},
+ volume_size: {get_param: volume_size}
+ }
+ }
+
+ network:
+ type: OS::Neutron::Net
+ properties:
+ name: network
+
+ subnet:
+ type: OS::Neutron::Subnet
+ properties:
+ network_id: { get_resource: network }
+ cidr: 172.16.0.0/16
+ gateway_ip: 172.16.0.1
+
+ network_router:
+ type: OS::Neutron::Router
+ properties:
+ external_gateway_info:
+ network: { get_param: public_network }
+
+ network_router_interface:
+ type: OS::Neutron::RouterInterface
+ properties:
+ router_id: { get_resource: network_router }
+ subnet_id: { get_resource: subnet }
+
+ key_pair:
+ type: OS::Nova::KeyPair
+ properties:
+ save_private_key: true
+ name: agent_keypair
+
+ open_security_group:
+ type: OS::Neutron::SecurityGroup
+ properties:
+ description: An open security group to allow all access to the slaves
+ rules:
+ - remote_ip_prefix: 0.0.0.0/0
+ protocol: tcp
+ port_range_min: 22
+ port_range_max: 22
+ - remote_ip_prefix: 0.0.0.0/0
+ protocol: icmp
+
+outputs:
+ slave_ips: {
+ description: "Slave addresses",
+ value: { get_attr: [ slaves, agent_ip] }
+ }
+ private_key:
+ description: "SSH Private Key"
+ value: { get_attr: [ key_pair, private_key ]}
diff --git a/snaps/openstack/tests/heat/agent.yaml b/snaps/openstack/tests/heat/agent.yaml
new file mode 100644
index 0000000..014b14f
--- /dev/null
+++ b/snaps/openstack/tests/heat/agent.yaml
@@ -0,0 +1,110 @@
+##############################################################################
+# Copyright (c) 2017 Cable Television Laboratories, Inc. ("CableLabs")
+# and others. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at:
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+##############################################################################
+heat_template_version: 2013-05-23
+
+parameters:
+ flavor:
+ type: string
+ default: test
+ image:
+ type: string
+ default: 'Ubuntu 16.04'
+ key_name:
+ type: string
+ default: test_key
+ username:
+ type: string
+ default: test_user
+ open_security_group:
+ type: string
+ volume_size:
+ type: number
+ description: Size of the volume to be created.
+ default: 1
+ constraints:
+ - range: { min: 1, max: 1024 }
+ description: must be between 1 and 1024 Gb.
+ agent_network:
+ type: string
+ constraints:
+ - custom_constraint: neutron.network
+ public_network:
+ type: string
+ constraints:
+ - custom_constraint: neutron.network
+ availability_zone:
+ type: string
+ default: nova
+
+resources:
+ agent:
+ type: "OS::Nova::Server"
+ properties:
+ name: agent
+ image: { get_param: image }
+ flavor: { get_param: flavor }
+ key_name: { get_param: key_name }
+ networks:
+ - port: { get_resource: agent_port }
+ user_data: { get_resource: agent_config }
+ user_data_format: RAW
+ availability_zone: { get_param: availability_zone}
+
+ agent_config:
+ type: "OS::Heat::CloudConfig"
+ properties:
+ cloud_config:
+ users:
+ - name: { get_param: username }
+ groups: users
+ shell: /bin/bash
+ sudo: "ALL=(ALL) NOPASSWD:ALL"
+ ssh_authorized_keys:
+ - ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDEbnDiqZ8RjQJJzJPf074J41XlYED+zYBzaUZ5UkkUquXzymyUmoWaFBXJP+XPu4Ns44U/S8614+JxGk96tjUdJlIjL0Ag8HP6KLtTNCabucKcEASpgJIVWqJvE3E9upZLIEiTGsF8I8S67T2qq1J1uvtxyeZmyjm7NMamjyFXE53dhR2EHqSutyKK1CK74NkRY9wr3qWUIt35kLdKSVSfrr4gOOicDALbIRu77skHIvrjt+wK1VWphBdMg6ytuq5mIE6pjWAU3Gwl4aTxOU0z43ARzCLq8HVf8s/dKjYMj8plNqaIfceMbaEUqpNHv/xbvtGNG7N0aB/a4pkUQL07
+ - default
+ package_update: false
+ package_upgrade: false
+ manage_etc_hosts: localhost
+
+ agent_port:
+ type: "OS::Neutron::Port"
+ properties:
+ network_id: { get_param: agent_network }
+ security_groups:
+ - { get_param: open_security_group }
+
+ floating_ip:
+ type: OS::Neutron::FloatingIP
+ properties:
+ floating_network_id: { get_param: public_network }
+ port_id: { get_resource: agent_port }
+
+ agent_volume:
+ type: OS::Cinder::Volume
+ properties:
+ size: { get_param: volume_size }
+
+ agent_volume_att:
+ type: OS::Cinder::VolumeAttachment
+ properties:
+ instance_uuid: { get_resource: agent }
+ volume_id: { get_resource: agent_volume}
+
+outputs:
+ agent_ip:
+ description: The floating IP address of the agent on the public network
+ value: { get_attr: [ floating_ip, floating_ip_address ] }
diff --git a/snaps/openstack/utils/heat_utils.py b/snaps/openstack/utils/heat_utils.py
index 8e49c53..e440717 100644
--- a/snaps/openstack/utils/heat_utils.py
+++ b/snaps/openstack/utils/heat_utils.py
@@ -13,6 +13,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import logging
+import os
import yaml
from heatclient.client import Client
@@ -117,8 +118,15 @@ def create_stack(heat_cli, stack_settings):
if stack_settings.env_values:
args['parameters'] = stack_settings.env_values
- if stack_settings.files:
- args['files'] = stack_settings.files
+ if stack_settings.resource_files:
+ resources = dict()
+ for res_file in stack_settings.resource_files:
+ heat_resource_contents = file_utils.read_file(res_file)
+ base_filename = os.path.basename(res_file)
+
+ if heat_resource_contents and base_filename:
+ resources[base_filename] = heat_resource_contents
+ args['files'] = resources
stack = heat_cli.stacks.create(**args)
@@ -134,25 +142,25 @@ def delete_stack(heat_cli, stack):
heat_cli.stacks.delete(stack.id)
-def __get_os_resources(heat_cli, stack):
+def __get_os_resources(heat_cli, res_id):
"""
Returns all of the OpenStack resource objects for a given stack
:param heat_cli: the OpenStack heat client
- :param stack: the SNAPS-OO Stack domain object
+ :param res_id: the resource ID
:return: a list
"""
- return heat_cli.resources.list(stack.id)
+ return heat_cli.resources.list(res_id)
-def get_resources(heat_cli, stack, res_type=None):
+def get_resources(heat_cli, res_id, res_type=None):
"""
Returns all of the OpenStack resource objects for a given stack
:param heat_cli: the OpenStack heat client
- :param stack: the SNAPS-OO Stack domain object
+ :param res_id: the SNAPS-OO Stack domain object
:param res_type: the type name to filter
:return: a list of Resource domain objects
"""
- os_resources = __get_os_resources(heat_cli, stack)
+ os_resources = __get_os_resources(heat_cli, res_id)
if os_resources:
out = list()
@@ -201,7 +209,7 @@ def get_stack_networks(heat_cli, neutron, stack):
"""
out = list()
- resources = get_resources(heat_cli, stack, 'OS::Neutron::Net')
+ resources = get_resources(heat_cli, stack.id, 'OS::Neutron::Net')
for resource in resources:
network = neutron_utils.get_network_by_id(neutron, resource.id)
if network:
@@ -220,7 +228,7 @@ def get_stack_routers(heat_cli, neutron, stack):
"""
out = list()
- resources = get_resources(heat_cli, stack, 'OS::Neutron::Router')
+ resources = get_resources(heat_cli, stack.id, 'OS::Neutron::Router')
for resource in resources:
router = neutron_utils.get_router_by_id(neutron, resource.id)
if router:
@@ -239,7 +247,7 @@ def get_stack_security_groups(heat_cli, neutron, stack):
"""
out = list()
- resources = get_resources(heat_cli, stack, 'OS::Neutron::SecurityGroup')
+ resources = get_resources(heat_cli, stack.id, 'OS::Neutron::SecurityGroup')
for resource in resources:
security_group = neutron_utils.get_security_group_by_id(
neutron, resource.id)
@@ -260,8 +268,8 @@ def get_stack_servers(heat_cli, nova, neutron, stack):
"""
out = list()
- resources = get_resources(heat_cli, stack, 'OS::Nova::Server')
- for resource in resources:
+ srvr_res = get_resources(heat_cli, stack.id, 'OS::Nova::Server')
+ for resource in srvr_res:
try:
server = nova_utils.get_server_object_by_id(
nova, neutron, resource.id)
@@ -270,6 +278,18 @@ def get_stack_servers(heat_cli, nova, neutron, stack):
except NotFound:
logger.warn('VmInst cannot be located with ID %s', resource.id)
+ res_grps = get_resources(heat_cli, stack.id, 'OS::Heat::ResourceGroup')
+ for res_grp in res_grps:
+ res_ress = get_resources(heat_cli, res_grp.id)
+ for res_res in res_ress:
+ res_res_srvrs = get_resources(
+ heat_cli, res_res.id, 'OS::Nova::Server')
+ for res_srvr in res_res_srvrs:
+ server = nova_utils.get_server_object_by_id(
+ nova, neutron, res_srvr.id)
+ if server:
+ out.append(server)
+
return out
@@ -283,7 +303,7 @@ def get_stack_keypairs(heat_cli, nova, stack):
"""
out = list()
- resources = get_resources(heat_cli, stack, 'OS::Nova::KeyPair')
+ resources = get_resources(heat_cli, stack.id, 'OS::Nova::KeyPair')
for resource in resources:
try:
keypair = nova_utils.get_keypair_by_id(nova, resource.id)
@@ -305,7 +325,7 @@ def get_stack_volumes(heat_cli, cinder, stack):
"""
out = list()
- resources = get_resources(heat_cli, stack, 'OS::Cinder::Volume')
+ resources = get_resources(heat_cli, stack.id, 'OS::Cinder::Volume')
for resource in resources:
try:
server = cinder_utils.get_volume_by_id(cinder, resource.id)
@@ -327,7 +347,7 @@ def get_stack_volume_types(heat_cli, cinder, stack):
"""
out = list()
- resources = get_resources(heat_cli, stack, 'OS::Cinder::VolumeType')
+ resources = get_resources(heat_cli, stack.id, 'OS::Cinder::VolumeType')
for resource in resources:
try:
vol_type = cinder_utils.get_volume_type_by_id(cinder, resource.id)
@@ -350,7 +370,7 @@ def get_stack_flavors(heat_cli, nova, stack):
"""
out = list()
- resources = get_resources(heat_cli, stack, 'OS::Nova::Flavor')
+ resources = get_resources(heat_cli, stack.id, 'OS::Nova::Flavor')
for resource in resources:
try:
flavor = nova_utils.get_flavor_by_id(nova, resource.id)
diff --git a/snaps/openstack/utils/tests/heat_utils_tests.py b/snaps/openstack/utils/tests/heat_utils_tests.py
index 7d43adf..67fbdec 100644
--- a/snaps/openstack/utils/tests/heat_utils_tests.py
+++ b/snaps/openstack/utils/tests/heat_utils_tests.py
@@ -164,7 +164,7 @@ class HeatUtilsCreateSimpleStackTests(OSComponentTestCase):
self.stack1.id)
self.assertEqual(self.stack1, stack_query_3)
- resources = heat_utils.get_resources(self.heat_client, self.stack1)
+ resources = heat_utils.get_resources(self.heat_client, self.stack1.id)
self.assertIsNotNone(resources)
self.assertEqual(4, len(resources))
@@ -359,7 +359,7 @@ class HeatUtilsCreateComplexStackTests(OSComponentTestCase):
Tests that a heat template with floating IPs and can have the proper
settings derived from settings_utils.py.
"""
- resources = heat_utils.get_resources(self.heat_client, self.stack)
+ resources = heat_utils.get_resources(self.heat_client, self.stack.id)
self.assertIsNotNone(resources)
self.assertEqual(12, len(resources))
diff --git a/snaps/test_suite_builder.py b/snaps/test_suite_builder.py
index 1990cd6..7b3ece7 100644
--- a/snaps/test_suite_builder.py
+++ b/snaps/test_suite_builder.py
@@ -91,8 +91,8 @@ from snaps.openstack.tests.create_security_group_tests import (
from snaps.openstack.tests.create_stack_tests import (
StackSettingsUnitTests, CreateStackSuccessTests, CreateStackNegativeTests,
CreateStackFlavorTests, CreateStackFloatingIpTests,
- CreateStackKeypairTests, CreateStackVolumeTests,
- CreateStackSecurityGroupTests)
+ CreateStackNestedResourceTests, CreateStackKeypairTests,
+ CreateStackVolumeTests, CreateStackSecurityGroupTests)
from snaps.openstack.tests.create_user_tests import (
UserSettingsUnitTests, CreateUserSuccessTests)
from snaps.openstack.tests.create_volume_tests import (
@@ -638,6 +638,11 @@ def add_openstack_integration_tests(suite, os_creds, ext_net_name,
flavor_metadata=flavor_metadata, image_metadata=image_metadata,
log_level=log_level))
suite.addTest(OSIntegrationTestCase.parameterize(
+ CreateStackNestedResourceTests, os_creds=os_creds,
+ ext_net_name=ext_net_name, use_keystone=use_keystone,
+ flavor_metadata=flavor_metadata, image_metadata=image_metadata,
+ log_level=log_level))
+ suite.addTest(OSIntegrationTestCase.parameterize(
AnsibleProvisioningTests, os_creds=os_creds,
ext_net_name=ext_net_name, use_keystone=use_keystone,
flavor_metadata=flavor_metadata, image_metadata=image_metadata,