Code improvements and fixes

* Removed heat templates
* Improved Docstring content
* Added code to assert errors when failing
* Removed private variable names
* Removed test_402_heat_stack_list function
This commit is contained in:
Jose Delarosa
2019-10-28 23:30:51 -05:00
parent 08b5b70854
commit 80d1f1086d
3 changed files with 50 additions and 192 deletions

View File

@@ -26,13 +26,14 @@ from novaclient import exceptions
import zaza.model
import zaza.openstack.charm_tests.test_utils as test_utils
import zaza.openstack.utilities.openstack as openstack_utils
import zaza.charm_lifecycle.utils as charm_lifecycle_utils
# Resource and name constants
IMAGE_NAME = 'cirros-image-1'
KEYPAIR_NAME = 'testkey'
STACK_NAME = 'hello_world'
RESOURCE_TYPE = 'server'
TEMPLATES_PATH = 'tests/files'
TEMPLATES_PATH = 'files'
FLAVOR_NAME = 'm1.tiny'
@@ -54,7 +55,11 @@ class HeatBasicDeployment(test_utils.OpenStackBaseTest):
@property
def services(self):
"""Return a list services for OpenStack release."""
"""Return a list services for OpenStack release.
:returns: List of services
:rtype: [str]
"""
services = ['heat-api', 'heat-api-cfn', 'heat-engine']
return services
@@ -71,15 +76,14 @@ class HeatBasicDeployment(test_utils.OpenStackBaseTest):
# Confirm image is created and has status of 'active'
if not image_new:
message = 'glance image create failed'
logging.error(message)
assert False, 'glance image create failed'
# Verify new image name
images_list = list(self.glance_client.images.list())
if images_list[0].name != IMAGE_NAME:
message = ('glance image create failed or unexpected '
'image name {}'.format(images_list[0].name))
logging.error(message)
assert False, message
def _keypair_create(self):
"""Create a keypair or get a keypair if it exists."""
@@ -95,7 +99,7 @@ class HeatBasicDeployment(test_utils.OpenStackBaseTest):
key.private_key)
logging.info('Keypair created')
else:
logging.info('Keypair not created')
assert False, 'Keypair not created'
def _stack_create(self):
"""Create a heat stack from a heat template, verify its status."""
@@ -108,7 +112,13 @@ class HeatBasicDeployment(test_utils.OpenStackBaseTest):
else:
os_release = 'queens'
file_rel_path = os.path.join(TEMPLATES_PATH, os_release, t_name)
# Get location of template files in charm-heat
bundle_path = charm_lifecycle_utils.BUNDLE_DIR
if bundle_path[-1:] == "/":
bundle_path = bundle_path[0:-1]
file_rel_path = os.path.join(os.path.dirname(bundle_path),
TEMPLATES_PATH, os_release, t_name)
file_abs_path = os.path.abspath(file_rel_path)
t_url = urlparse.urlparse(file_abs_path, scheme='file').geturl()
logging.info('template url: {}'.format(t_url))
@@ -143,10 +153,10 @@ class HeatBasicDeployment(test_utils.OpenStackBaseTest):
# Create the stack.
try:
_stack = self.heat_client.stacks.create(**fields)
logging.info('Stack data: {}'.format(_stack))
_stack_id = _stack['stack']['id']
logging.info('Creating new stack, ID: {}'.format(_stack_id))
stack = self.heat_client.stacks.create(**fields)
logging.info('Stack data: {}'.format(stack))
stack_id = stack['stack']['id']
logging.info('Creating new stack, ID: {}'.format(stack_id))
except Exception as e:
# Generally, an api or cloud config error if this is hit.
msg = 'Failed to create heat stack: {}'.format(e)
@@ -158,45 +168,46 @@ class HeatBasicDeployment(test_utils.OpenStackBaseTest):
# find resources (a valid hypervisor) to fit the instance, in
# which case the heat stack self-deletes! Confirm anyway...
openstack_utils.resource_reaches_status(self.heat_client.stacks,
_stack_id,
stack_id,
expected_status="COMPLETE",
msg="Stack status wait")
_stacks = list(self.heat_client.stacks.list())
logging.info('All stacks: {}'.format(_stacks))
# List stack
stacks = list(self.heat_client.stacks.list())
logging.info('All stacks: {}'.format(stacks))
# Confirm stack still exists.
# Get stack information
try:
_stack = self.heat_client.stacks.get(STACK_NAME)
stack = self.heat_client.stacks.get(STACK_NAME)
except Exception as e:
# Generally, a resource availability issue if this is hit.
msg = 'Failed to get heat stack: {}'.format(e)
logging.error(msg)
assert False, msg
# Confirm stack name.
logging.info('Expected, actual stack name: {}, '
'{}'.format(STACK_NAME, _stack.stack_name))
if STACK_NAME != _stack.stack_name:
'{}'.format(STACK_NAME, stack.stack_name))
if STACK_NAME != stack.stack_name:
msg = 'Stack name mismatch, {} != {}'.format(STACK_NAME,
_stack.stack_name)
logging.error(msg)
stack.stack_name)
assert False, msg
def _stack_resource_compute(self):
"""Confirm the stack has created a nova resource and check status."""
logging.info('Confirming heat stack resource status...')
# Confirm existence of a heat-generated nova compute resource.
_resource = self.heat_client.resources.get(STACK_NAME, RESOURCE_TYPE)
_server_id = _resource.physical_resource_id
if _server_id:
resource = self.heat_client.resources.get(STACK_NAME, RESOURCE_TYPE)
server_id = resource.physical_resource_id
if server_id:
logging.debug('Heat template spawned nova instance, '
'ID: {}'.format(_server_id))
'ID: {}'.format(server_id))
else:
msg = 'Stack failed to spawn a nova compute resource (instance).'
logging.error(msg)
# Confirm nova instance reaches ACTIVE status.
openstack_utils.resource_reaches_status(self.nova_client.servers,
_server_id,
server_id,
expected_status="ACTIVE",
msg="nova instance")
logging.info('Nova instance reached ACTIVE status')
@@ -228,47 +239,26 @@ class HeatBasicDeployment(test_utils.OpenStackBaseTest):
assert unit.workload_status == "active"
zaza.model.run_action(unit.entity_id, "domain-setup")
zaza.model.block_until_unit_wl_status(unit.entity_id, "active")
unit = zaza.model.get_unit_from_name(unit.entity_id)
assert unit.workload_status == "active"
def test_400_heat_resource_types_list(self):
"""Check default resource list behavior and confirm functionality."""
logging.info('Checking default heat resource list...')
try:
types = list(self.heat_client.resource_types.list())
types = self.heat_client.resource_types.list()
if type(types) is list:
logging.info('Resource type list check is ok.')
else:
msg = 'Resource type list is not a list!'
logging.error('{}'.format(msg))
raise
assert False, msg
if len(types) > 0:
logging.info('Resource type list is populated '
'({}, ok).'.format(len(types)))
else:
msg = 'Resource type list length is zero!'
logging.error(msg)
raise
assert False, msg
except Exception as e:
msg = 'Resource type list failed: {}'.format(e)
logging.error(msg)
raise
def test_402_heat_stack_list(self):
"""Check default heat stack list behavior, confirm functionality."""
logging.info('Checking default heat stack list...')
try:
stacks = list(self.heat_client.stacks.list())
if type(stacks) is list:
logging.info("Stack list check is ok.")
else:
msg = 'Stack list returned something other than a list.'
logging.error(msg)
raise
except Exception as e:
msg = 'Heat stack list failed: {}'.format(e)
logging.error(msg)
raise
assert False, msg
def test_410_heat_stack_create_delete(self):
"""Create stack, confirm nova compute resource, delete stack."""
@@ -290,8 +280,8 @@ class HeatBasicDeployment(test_utils.OpenStackBaseTest):
"--format json "
"grep auth_encryption_key /etc/heat/heat.conf")
if ret:
msg = "juju run returned error: ({}) -> {}".format(ret, output)
logging.error("Error: {}".format(msg))
msg = "juju run error: ret: {}, output: {}".format(ret, output)
self.assertEqual(ret, 0, msg)
output = json.loads(output)
keys = {}
for r in output:
@@ -310,10 +300,13 @@ class HeatBasicDeployment(test_utils.OpenStackBaseTest):
(Otherwise the self.run(...) command could have been used for the unit
:param str command: The command to run.
:param int timeout: Seconds to wait before timing out.
:return: A 2-tuple containing the output of the command and the exit
code of the command.
:param command: The command to run.
:type command: str
:param timeout: Seconds to wait before timing out.
:type timeout: int
:raises: subprocess.CalledProcessError.
:returns: A pair containing the output of the command and exit value
:rtype: (str, int)
"""
cmd = ['juju', 'run', '--timeout', "{}s".format(timeout),
] + command.split()

View File

@@ -1,66 +0,0 @@
#
# This is a hello world HOT template just defining a single compute
# server.
#
heat_template_version: 2013-05-23
description: >
Hello world HOT template that just defines a single server.
Contains just base features to verify base HOT support.
parameters:
key_name:
type: string
description: Name of an existing key pair to use for the server
constraints:
- custom_constraint: nova.keypair
flavor:
type: string
description: Flavor for the server to be created
default: m1.tiny
constraints:
- custom_constraint: nova.flavor
image:
type: string
description: Image ID or image name to use for the server
constraints:
- custom_constraint: glance.image
admin_pass:
type: string
description: Admin password
hidden: true
constraints:
- length: { min: 6, max: 8 }
description: Password length must be between 6 and 8 characters
- allowed_pattern: "[a-zA-Z0-9]+"
description: Password must consist of characters and numbers only
- allowed_pattern: "[A-Z]+[a-zA-Z0-9]*"
description: Password must start with an uppercase character
db_port:
type: number
description: Database port number
default: 50000
constraints:
- range: { min: 40000, max: 60000 }
description: Port number must be between 40000 and 60000
resources:
server:
type: OS::Nova::Server
properties:
key_name: { get_param: key_name }
image: { get_param: image }
flavor: { get_param: flavor }
admin_pass: { get_param: admin_pass }
user_data:
str_replace:
template: |
#!/bin/bash
echo db_port
params:
db_port: { get_param: db_port }
outputs:
server_networks:
description: The networks of the deployed server
value: { get_attr: [server, networks] }

View File

@@ -1,69 +0,0 @@
#
# This is a hello world HOT template just defining a single compute
# server.
#
heat_template_version: 2013-05-23
description: >
Hello world HOT template that just defines a single server.
Contains just base features to verify base HOT support.
parameters:
key_name:
type: string
description: Name of an existing key pair to use for the server
constraints:
- custom_constraint: nova.keypair
flavor:
type: string
description: Flavor for the server to be created
default: m1.tiny
constraints:
- custom_constraint: nova.flavor
image:
type: string
description: Image ID or image name to use for the server
constraints:
- custom_constraint: glance.image
admin_pass:
type: string
description: Admin password
hidden: true
constraints:
- length: { min: 6, max: 8 }
description: Password length must be between 6 and 8 characters
- allowed_pattern: "[a-zA-Z0-9]+"
description: Password must consist of characters and numbers only
- allowed_pattern: "[A-Z]+[a-zA-Z0-9]*"
description: Password must start with an uppercase character
db_port:
type: number
description: Database port number
default: 50000
constraints:
- range: { min: 40000, max: 60000 }
description: Port number must be between 40000 and 60000
resources:
server:
type: OS::Nova::Server
properties:
key_name: { get_param: key_name }
image: { get_param: image }
flavor: { get_param: flavor }
admin_pass: { get_param: admin_pass }
# See https://docs.openstack.org/heat/queens/template_guide/contrib.html#OS::Nova::Server-prop-networks
networks:
- allocate_network: none
user_data:
str_replace:
template: |
#!/bin/bash
echo db_port
params:
db_port: { get_param: db_port }
outputs:
server_networks:
description: The networks of the deployed server
value: { get_attr: [server, networks] }