X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=yardstick%2Forchestrator%2Fheat.py;h=5afa4151ebef8a36f14b825533604a5a36fc8291;hb=f3f75ea39678b6da24e5ed6a61f77586f71d0128;hp=1a8beaeb626c73f5848e1af77498378386baf283;hpb=35d2f095fa3948293e8f74e41b3fec39a05e7034;p=yardstick.git diff --git a/yardstick/orchestrator/heat.py b/yardstick/orchestrator/heat.py index 1a8beaeb6..5afa4151e 100644 --- a/yardstick/orchestrator/heat.py +++ b/yardstick/orchestrator/heat.py @@ -15,6 +15,7 @@ import datetime import getpass import logging import pkg_resources +import pprint import socket import tempfile import time @@ -22,25 +23,21 @@ import time from oslo_serialization import jsonutils from oslo_utils import encodeutils import shade +from shade._heat import event_utils import yardstick.common.openstack_utils as op_utils from yardstick.common import exceptions from yardstick.common import template_format +from yardstick.common import constants as consts log = logging.getLogger(__name__) -HEAT_KEY_UUID_LENGTH = 8 - PROVIDER_SRIOV = "sriov" _DEPLOYED_STACKS = {} -def get_short_key_uuid(uuid): - return str(uuid)[:HEAT_KEY_UUID_LENGTH] - - class HeatStack(object): """Represents a Heat stack (deployed template) """ @@ -50,19 +47,40 @@ class HeatStack(object): self._cloud = shade.openstack_cloud() self._stack = None + def _update_stack_tracking(self): + outputs = self._stack.outputs + self.outputs = {output['output_key']: output['output_value'] for output + in outputs} + if self.uuid: + _DEPLOYED_STACKS[self.uuid] = self._stack + def create(self, template, heat_parameters, wait, timeout): """Creates an OpenStack stack from a template""" with tempfile.NamedTemporaryFile('wb', delete=False) as template_file: - template_file.write(jsonutils.dumps(template)) + template_file.write(jsonutils.dump_as_bytes(template)) template_file.close() self._stack = self._cloud.create_stack( self.name, template_file=template_file.name, wait=wait, timeout=timeout, **heat_parameters) - outputs = self._stack.outputs - self.outputs = {output['output_key']: output['output_value'] for output - in outputs} - if self.uuid: - _DEPLOYED_STACKS[self.uuid] = self._stack + + self._update_stack_tracking() + + def get_failures(self): + return event_utils.get_events(self._cloud, self._stack.id, + event_args={'resource_status': 'FAILED'}) + + def get(self): + """Retrieves an existing stack from the target cloud + + Returns a bool indicating whether the stack exists in the target cloud + If the stack exists, it will be stored as self._stack + """ + self._stack = self._cloud.get_stack(self.name) + if not self._stack: + return False + + self._update_stack_tracking() + return True @staticmethod def stacks_exist(): @@ -74,7 +92,14 @@ class HeatStack(object): if self.uuid is None: return - ret = self._cloud.delete_stack(self.uuid, wait=wait) + try: + ret = self._cloud.delete_stack(self.uuid, wait=wait) + except TypeError: + # NOTE(ralonsoh): this exception catch solves a bug in Shade, which + # tries to retrieve and read the stack status when it's already + # deleted. + ret = True + _DEPLOYED_STACKS.pop(self.uuid) self._stack = None return ret @@ -315,21 +340,24 @@ name (i.e. %s). } } - def add_port(self, name, network_name, subnet_name, vnic_type, sec_group_id=None, + def add_port(self, name, network, sec_group_id=None, provider=None, allowed_address_pairs=None): """add to the template a named Neutron Port """ - log.debug("adding Neutron::Port '%s', network:'%s', subnet:'%s', vnic_type:'%s', " - "secgroup:%s", name, network_name, subnet_name, vnic_type, sec_group_id) + net_is_existing = network.net_flags.get(consts.IS_EXISTING) + depends_on = [] if net_is_existing else [network.subnet_stack_name] + fixed_ips = [{'subnet': network.subnet}] if net_is_existing else [ + {'subnet': {'get_resource': network.subnet_stack_name}}] + network_ = network.name if net_is_existing else { + 'get_resource': network.stack_name} self.resources[name] = { 'type': 'OS::Neutron::Port', - 'depends_on': [subnet_name], + 'depends_on': depends_on, 'properties': { 'name': name, - 'binding:vnic_type': vnic_type, - 'fixed_ips': [{'subnet': {'get_resource': subnet_name}}], - 'network_id': {'get_resource': network_name}, - 'replacement_policy': 'AUTO', + 'binding:vnic_type': network.vnic_type, + 'fixed_ips': fixed_ips, + 'network': network_, } } @@ -346,6 +374,8 @@ name (i.e. %s). self.resources[name]['properties'][ 'allowed_address_pairs'] = allowed_address_pairs + log.debug("adding Neutron::Port %s", self.resources[name]) + self._template['outputs'][name] = { 'description': 'Address for interface %s' % name, 'value': {'get_attr': [name, 'fixed_ips', 0, 'ip_address']} @@ -406,7 +436,7 @@ name (i.e. %s). } } - def add_keypair(self, name, key_uuid): + def add_keypair(self, name, key_id): """add to the template a Nova KeyPair""" log.debug("adding Nova::KeyPair '%s'", name) self.resources[name] = { @@ -418,7 +448,7 @@ name (i.e. %s). pkg_resources.resource_string( 'yardstick.resources', 'files/yardstick_key-' + - get_short_key_uuid(key_uuid) + '.pub'), + key_id + '.pub'), 'utf-8') } } @@ -473,7 +503,36 @@ name (i.e. %s). 'port_range_max': '65535'}, {'remote_ip_prefix': '::/0', 'ethertype': 'IPv6', - 'protocol': 'ipv6-icmp'} + 'protocol': 'ipv6-icmp'}, + {'remote_ip_prefix': '0.0.0.0/0', + 'direction': 'egress', + 'protocol': 'tcp', + 'port_range_min': '1', + 'port_range_max': '65535'}, + {'remote_ip_prefix': '0.0.0.0/0', + 'direction': 'egress', + 'protocol': 'udp', + 'port_range_min': '1', + 'port_range_max': '65535'}, + {'remote_ip_prefix': '0.0.0.0/0', + 'direction': 'egress', + 'protocol': 'icmp'}, + {'remote_ip_prefix': '::/0', + 'direction': 'egress', + 'ethertype': 'IPv6', + 'protocol': 'tcp', + 'port_range_min': '1', + 'port_range_max': '65535'}, + {'remote_ip_prefix': '::/0', + 'direction': 'egress', + 'ethertype': 'IPv6', + 'protocol': 'udp', + 'port_range_min': '1', + 'port_range_max': '65535'}, + {'remote_ip_prefix': '::/0', + 'direction': 'egress', + 'ethertype': 'IPv6', + 'protocol': 'ipv6-icmp'}, ] } } @@ -572,6 +631,9 @@ name (i.e. %s). return stack if stack.status != self.HEAT_STATUS_COMPLETE: + for event in stack.get_failures(): + log.error("%s", event.resource_status_reason) + log.error(pprint.pformat(self._template)) raise exceptions.HeatTemplateError(stack_name=self.name) log.info("Creating stack '%s' DONE in %d secs",