def _stack_action(stack, parsed_args, heat_client, action, action_name=None): if parsed_args.wait: # find the last event to use as the marker events = event_utils.get_events(heat_client, stack_id=stack, event_args={'sort_dir': 'desc', 'limit': 1}) marker = events[0].id if events else None try: action(stack) except heat_exc.HTTPNotFound: msg = _('Stack not found: %s') % stack raise exc.CommandError(msg) if parsed_args.wait: s = heat_client.stacks.get(stack) stack_status, msg = event_utils.poll_for_events( heat_client, s.stack_name, action=action_name, marker=marker) if action_name: if stack_status == '%s_FAILED' % action_name: raise exc.CommandError(msg) else: if stack_status.endswith('_FAILED'): raise exc.CommandError(msg) return heat_client.stacks.get(stack)
def update(clients, **workflow_input): workflow_client = clients.workflow_engine tripleoclients = clients.tripleoclient plan_name = workflow_input['container'] with tripleoclients.messaging_websocket() as ws: execution = base.start_workflow( workflow_client, 'tripleo.package_update.v1.package_update_plan', workflow_input=workflow_input) for payload in base.wait_for_messages(workflow_client, ws, execution): assert payload['status'] == "SUCCESS", pprint.pformat(payload) orchestration_client = clients.orchestration events = event_utils.get_events(orchestration_client, stack_id=plan_name, event_args={ 'sort_dir': 'desc', 'limit': 1 }) marker = events[0].id if events else None time.sleep(10) create_result = utils.wait_for_stack_ready(orchestration_client, plan_name, marker, 'UPDATE', 1) if not create_result: shell.OpenStackShell().run(["stack", "failures", "list", plan_name]) raise exceptions.DeploymentError("Heat Stack update failed.")
def deploy_and_wait(log, clients, stack, plan_name, verbose_level, timeout=None, run_validations=False, skip_deploy_identifier=False, deployment_options={}): """Start the deploy and wait for it to finish""" orchestration_client = clients.orchestration if stack is None: log.info("Performing Heat stack create") action = 'CREATE' marker = None else: log.info("Performing Heat stack update") # Make sure existing parameters for stack are reused # Find the last top-level event to use for the first marker events = event_utils.get_events(orchestration_client, stack_id=plan_name, event_args={ 'sort_dir': 'desc', 'limit': 1 }) marker = events[0].id if events else None action = 'UPDATE' set_deployment_status(clients=clients, plan=plan_name, status='DEPLOYING') try: deploy(container=plan_name, run_validations=run_validations, skip_deploy_identifier=skip_deploy_identifier, timeout=timeout, verbosity=verbose_level) except Exception: set_deployment_status(clients=clients, plan=plan_name, status='DEPLOY_FAILED') raise # we always want the heat stack output while it's going. verbose_events = True # TODO(rabi) Simplify call to get events as we don't need to wait # for stack to be ready anymore i.e just get the events. create_result = utils.wait_for_stack_ready(orchestration_client, plan_name, marker, action, verbose_events) if not create_result: shell.OpenStackShell().run(["stack", "failures", "list", plan_name]) set_deployment_status(clients=clients, plan=plan_name, status='DEPLOY_FAILED') if stack is None: raise exceptions.DeploymentError("Heat Stack create failed.") else: raise exceptions.DeploymentError("Heat Stack update failed.")
def _stack_action(stack, parsed_args, heat_client, action, action_name=None): if parsed_args.wait: # find the last event to use as the marker events = event_utils.get_events(heat_client, stack_id=stack, event_args={'sort_dir': 'desc'}, limit=1) marker = events[0].id if events else None try: action(stack) except heat_exc.HTTPNotFound: msg = _('Stack not found: %s') % stack raise exc.CommandError(msg) if parsed_args.wait: s = heat_client.stacks.get(stack) stack_status, msg = event_utils.poll_for_events(heat_client, s.stack_name, action=action_name, marker=marker) if action_name: if stack_status == '%s_FAILED' % action_name: raise exc.CommandError(msg) else: if stack_status.endswith('_FAILED'): raise exc.CommandError(msg) return heat_client.stacks.get(stack)
def _wait_for_heat_complete(self, orchestration_client, stack_id, timeout): # Wait for the stack to go to COMPLETE. timeout_t = time.time() + 60 * timeout marker = None event_log_context = heat_utils.EventLogContext() kwargs = { 'sort_dir': 'asc', 'nested_depth': '6' } while True: time.sleep(2) events = event_utils.get_events( orchestration_client, stack_id=stack_id, event_args=kwargs, marker=marker) if events: marker = getattr(events[-1], 'id', None) events_log = heat_utils.event_log_formatter( events, event_log_context) print(events_log) status = orchestration_client.stacks.get(stack_id).status if status == 'FAILED': raise Exception('Stack create failed') if status == 'COMPLETE': break if time.time() > timeout_t: msg = 'Stack creation timeout: %d minutes elapsed' % (timeout) raise Exception(msg)
def wait_for_stack_ready(orchestration_client, stack_name, marker=None, action='CREATE', verbose=False): """Check the status of an orchestration stack Get the status of an orchestration stack and check whether it is complete or failed. :param orchestration_client: Instance of Orchestration client :type orchestration_client: heatclient.v1.client.Client :param stack_name: Name or UUID of stack to retrieve :type stack_name: string :param marker: UUID of the last stack event before the current action :type marker: string :param action: Current action to check the stack for COMPLETE :type action: string :param verbose: Whether to print events :type verbose: boolean """ stack = get_stack(orchestration_client, stack_name) if not stack: return False stack_name = stack.stack_name while True: events = event_utils.get_events(orchestration_client, stack_id=stack_name, nested_depth=2, event_args={ 'sort_dir': 'asc', 'marker': marker }) if len(events) >= 1: # set marker to last event that was received. marker = getattr(events[-1], 'id', None) if verbose: events_log = event_log_formatter(events) print(events_log) stack = get_stack(orchestration_client, stack_name) stack_status = stack.stack_status if stack_status == '%s_COMPLETE' % action: print("Stack %(name)s %(status)s" % dict(name=stack_name, status=stack_status)) return True elif stack_status == '%s_FAILED' % action: print("Stack %(name)s %(status)s" % dict(name=stack_name, status=stack_status)) return False time.sleep(5)
def _stack_event_summary(self, stack): try: events = event_utils.get_events(self.clients.heat, stack_id=stack.stack_name, nested_depth=1, event_args={'sort_dir': 'asc'}) except exc.CommandError: return [] return util.heat_event_log_formatter(reversed(events))
def wait_for_stack_ready(orchestration_client, stack_name, marker=None, action='CREATE', verbose=False): """Check the status of an orchestration stack Get the status of an orchestration stack and check whether it is complete or failed. :param orchestration_client: Instance of Orchestration client :type orchestration_client: heatclient.v1.client.Client :param stack_name: Name or UUID of stack to retrieve :type stack_name: string :param marker: UUID of the last stack event before the current action :type marker: string :param action: Current action to check the stack for COMPLETE :type action: string :param verbose: Whether to print events :type verbose: boolean """ stack = get_stack(orchestration_client, stack_name) if not stack: return False stack_name = stack.stack_name while True: events = event_utils.get_events(orchestration_client, stack_id=stack_name, nested_depth=2, event_args={'sort_dir': 'asc', 'marker': marker}) if len(events) >= 1: # set marker to last event that was received. marker = getattr(events[-1], 'id', None) if verbose: events_log = event_log_formatter(events) print(events_log) stack = get_stack(orchestration_client, stack_name) stack_status = stack.stack_status if stack_status == '%s_COMPLETE' % action: print("Stack %(name)s %(status)s" % dict( name=stack_name, status=stack_status)) return True elif stack_status == '%s_FAILED' % action: print("Stack %(name)s %(status)s" % dict( name=stack_name, status=stack_status)) return False time.sleep(5)
def deploy_and_wait(log, clients, stack, plan_name, verbose_level, timeout=None, run_validations=False, skip_deploy_identifier=False, deployment_options={}): """Start the deploy and wait for it to finish""" workflow_input = { "container": plan_name, "run_validations": run_validations, "skip_deploy_identifier": skip_deploy_identifier, "deployment_options": deployment_options, } if timeout is not None: workflow_input['timeout'] = timeout deploy(log, clients, **workflow_input) orchestration_client = clients.orchestration if stack is None: log.info("Performing Heat stack create") action = 'CREATE' marker = None else: log.info("Performing Heat stack update") # Make sure existing parameters for stack are reused # Find the last top-level event to use for the first marker events = event_utils.get_events(orchestration_client, stack_id=plan_name, event_args={ 'sort_dir': 'desc', 'limit': 1 }) marker = events[0].id if events else None action = 'UPDATE' time.sleep(10) verbose_events = verbose_level >= 1 create_result = utils.wait_for_stack_ready(orchestration_client, plan_name, marker, action, verbose_events) if not create_result: shell.OpenStackShell().run(["stack", "failures", "list", plan_name]) set_deployment_status(clients, 'failed', plan=plan_name) if stack is None: raise exceptions.DeploymentError("Heat Stack create failed.") else: raise exceptions.DeploymentError("Heat Stack update failed.")
def deploy_and_wait(log, clients, stack, plan_name, verbose_level, timeout=None): """Start the deploy and wait for it to finish""" workflow_input = { "container": plan_name, "queue_name": str(uuid.uuid4()), } if timeout is not None: workflow_input['timeout'] = timeout deploy(clients, **workflow_input) orchestration_client = clients.orchestration if stack is None: log.info("Performing Heat stack create") action = 'CREATE' marker = None else: log.info("Performing Heat stack update") # Make sure existing parameters for stack are reused # Find the last top-level event to use for the first marker events = event_utils.get_events(orchestration_client, stack_id=plan_name, event_args={ 'sort_dir': 'desc', 'limit': 1 }) marker = events[0].id if events else None action = 'UPDATE' time.sleep(10) verbose_events = verbose_level > 0 create_result = utils.wait_for_stack_ready(orchestration_client, plan_name, marker, action, verbose_events) if not create_result: if stack is None: raise exceptions.DeploymentError("Heat Stack create failed.") else: raise exceptions.DeploymentError("Heat Stack update failed.")
def update(clients, container): """Update the heat stack outputs for purposes of update/upgrade. This workflow assumes that previously the plan_management.update_deployment_plan workflow has already been run to process the templates and environments (the same way as 'deploy' command processes them). :param clients: Application client object. :type clients: Object :param container: Container name to pull from. :type container: String. """ tripleoclients = clients.tripleoclient orchestration_client = clients.orchestration object_client = tripleoclients.object_store plan.update_plan_environment_with_image_parameters( object_client, container) stack.stack_update(object_client, orchestration_client, _STACK_TIMEOUT, container) events = event_utils.get_events(orchestration_client, stack_id=container, event_args={'sort_dir': 'desc', 'limit': 1}) marker = events[0].id if events else None time.sleep(10) create_result = utils.wait_for_stack_ready( clients.orchestration, container, marker, 'UPDATE', verbose=True ) if not create_result: raise exceptions.DeploymentError( 'Heat Stack update failed, run the following command' ' `openstack --os-cloud undercloud stack failures list {}`' ' to investigate these failures further.'.format(container) )
def deploy_and_wait(log, clients, stack, plan_name, verbose_level, timeout=None): """Start the deploy and wait for it to finish""" workflow_input = { "container": plan_name, "queue_name": str(uuid.uuid4()), } if timeout is not None: workflow_input['timeout'] = timeout deploy(clients, **workflow_input) orchestration_client = clients.orchestration if stack is None: log.info("Performing Heat stack create") action = 'CREATE' marker = None else: log.info("Performing Heat stack update") # Make sure existing parameters for stack are reused # Find the last top-level event to use for the first marker events = event_utils.get_events(orchestration_client, stack_id=plan_name, event_args={'sort_dir': 'desc', 'limit': 1}) marker = events[0].id if events else None action = 'UPDATE' time.sleep(10) verbose_events = verbose_level > 0 create_result = utils.wait_for_stack_ready( orchestration_client, plan_name, marker, action, verbose_events) if not create_result: if stack is None: raise exceptions.DeploymentError("Heat Stack create failed.") else: raise exceptions.DeploymentError("Heat Stack update failed.")
def take_action(self, parsed_args): self.log.debug('take_action(%s)', parsed_args) client = self.app.client_manager.orchestration columns = ['id', 'resource_status', 'resource_status_reason', 'event_time', 'physical_resource_id'] kwargs = { 'resource_name': parsed_args.resource, 'filters': heat_utils.format_parameters(parsed_args.filter), 'sort_dir': 'asc' } if parsed_args.resource and parsed_args.nested_depth: msg = _('--nested-depth cannot be specified with --resource') raise exc.CommandError(msg) if parsed_args.nested_depth: columns.append('stack_name') nested_depth = parsed_args.nested_depth else: nested_depth = 0 if parsed_args.follow: if parsed_args.formatter != 'log': msg = _('--follow can only be specified with --format log') raise exc.CommandError(msg) marker = parsed_args.marker try: event_log_context = heat_utils.EventLogContext() while True: events = event_utils.get_events( client, stack_id=parsed_args.stack, event_args=kwargs, nested_depth=nested_depth, marker=marker) if events: marker = getattr(events[-1], 'id', None) events_log = heat_utils.event_log_formatter( events, event_log_context) self.app.stdout.write(events_log) self.app.stdout.write('\n') time.sleep(5) # this loop never exits except (KeyboardInterrupt, EOFError): # ctrl-c, ctrl-d return [], [] events = event_utils.get_events( client, stack_id=parsed_args.stack, event_args=kwargs, nested_depth=nested_depth, marker=parsed_args.marker, limit=parsed_args.limit) if parsed_args.sort: sorts = [] for sort in parsed_args.sort: if sort.startswith(":"): sorts.append(":".join(["event_time", sort.lstrip(":")])) else: sorts.append(sort) events = utils.sort_items(events, ','.join(sorts)) if parsed_args.formatter == 'log': return [], events if len(events): if hasattr(events[0], 'resource_name'): columns.insert(0, 'resource_name') columns.append('logical_resource_id') else: columns.insert(0, 'logical_resource_id') return ( columns, (utils.get_item_properties(s, columns) for s in events) )
def take_action(self, parsed_args): self.log.debug("take_action(%s)", parsed_args) heat_client = self.app.client_manager.orchestration try: if not parsed_args.yes and sys.stdin.isatty(): prompt_response = input( _("Are you sure you want to delete this stack(s) [y/N]? ") ).lower() if not prompt_response.startswith('y'): self.log.info('User did not confirm stack delete so ' 'taking no action.') return except KeyboardInterrupt: # ctrl-c self.log.info('User did not confirm stack delete ' '(ctrl-c) so taking no action.') return except EOFError: # ctrl-d self.log.info('User did not confirm stack delete ' '(ctrl-d) so taking no action.') return failure_count = 0 stacks_waiting = [] for sid in parsed_args.stack: marker = None if parsed_args.wait: try: # find the last event to use as the marker events = event_utils.get_events( heat_client, stack_id=sid, event_args={'sort_dir': 'desc'}, limit=1) if events: marker = events[0].id except heat_exc.CommandError as ex: failure_count += 1 print(ex) continue try: heat_client.stacks.delete(sid) stacks_waiting.append((sid, marker)) except heat_exc.HTTPNotFound: failure_count += 1 print(_('Stack not found: %s') % sid) except heat_exc.Forbidden: failure_count += 1 print(_('Forbidden: %s') % sid) if parsed_args.wait: for sid, marker in stacks_waiting: try: stack_status, msg = event_utils.poll_for_events( heat_client, sid, action='DELETE', marker=marker) except heat_exc.CommandError: continue if stack_status == 'DELETE_FAILED': failure_count += 1 print(msg) if failure_count: msg = (_('Unable to delete %(count)d of the %(total)d stacks.') % { 'count': failure_count, 'total': len(parsed_args.stack) }) raise exc.CommandError(msg)
def take_action(self, parsed_args): self.log.debug('take_action(%s)', parsed_args) client = self.app.client_manager.orchestration tpl_files, template = template_utils.process_template_path( parsed_args.template, object_request=http.authenticated_fetcher(client), existing=parsed_args.existing, fetch_child=parsed_args.files_container is None) env_files_list = [] env_files, env = ( template_utils.process_multiple_environments_and_files( env_paths=parsed_args.environment, env_list_tracker=env_files_list, fetch_env_files=parsed_args.files_container is None)) parameters = heat_utils.format_all_parameters( parsed_args.parameter, parsed_args.parameter_file, parsed_args.template) if parsed_args.pre_update: template_utils.hooks_to_env(env, parsed_args.pre_update, 'pre-update') fields = { 'stack_id': parsed_args.stack, 'parameters': parameters, 'existing': parsed_args.existing, 'template': template, 'files': dict(list(tpl_files.items()) + list(env_files.items())), 'environment': env } # If one or more environments is found, pass the listing to the server if env_files_list: fields['environment_files'] = env_files_list if parsed_args.files_container: fields['files_container'] = parsed_args.files_container if parsed_args.tags: fields['tags'] = parsed_args.tags if parsed_args.timeout: fields['timeout_mins'] = parsed_args.timeout if parsed_args.clear_parameter: fields['clear_parameters'] = list(parsed_args.clear_parameter) if parsed_args.rollback: rollback = parsed_args.rollback.strip().lower() if rollback not in ('enabled', 'disabled', 'keep'): msg = _('--rollback invalid value: %s') % parsed_args.rollback raise exc.CommandError(msg) if rollback != 'keep': fields['disable_rollback'] = rollback == 'disabled' if parsed_args.dry_run: if parsed_args.show_nested: fields['show_nested'] = parsed_args.show_nested changes = client.stacks.preview_update(**fields) fields = [ 'state', 'resource_name', 'resource_type', 'resource_identity' ] columns = sorted(changes.get("resource_changes", {}).keys()) data = [ heat_utils.json_formatter(changes["resource_changes"][key]) for key in columns ] return columns, data if parsed_args.wait: # find the last event to use as the marker events = event_utils.get_events(client, stack_id=parsed_args.stack, event_args={'sort_dir': 'desc'}, limit=1) marker = events[0].id if events else None if parsed_args.converge: fields['converge'] = True client.stacks.update(**fields) if parsed_args.wait: stack = client.stacks.get(parsed_args.stack) stack_status, msg = event_utils.poll_for_events(client, stack.stack_name, action='UPDATE', marker=marker) if stack_status == 'UPDATE_FAILED': raise exc.CommandError(msg) return _show_stack(client, parsed_args.stack, format='table', short=True)
def take_action(self, parsed_args): self.log.debug('take_action(%s)', parsed_args) client = self.app.client_manager.orchestration columns = ['id', 'resource_status', 'resource_status_reason', 'event_time', 'physical_resource_id'] kwargs = { 'resource_name': parsed_args.resource, 'filters': heat_utils.format_parameters(parsed_args.filter), 'sort_dir': 'asc' } if parsed_args.resource and parsed_args.nested_depth: msg = _('--nested-depth cannot be specified with --resource') raise exc.CommandError(msg) if parsed_args.nested_depth: columns.append('stack_name') nested_depth = parsed_args.nested_depth else: nested_depth = 0 if parsed_args.sort: sorts = [] sort_keys = [] for sort in parsed_args.sort: if sort.startswith(":"): sorts.append(":".join(["event_time", sort.lstrip(":")])) else: sorts.append(sort) sort_keys.append(sort.split(":")[0]) kwargs['sort_keys'] = sort_keys if ":" in parsed_args.sort[0]: kwargs['sort_dir'] = parsed_args.sort[0].split(":")[1] if parsed_args.follow: if parsed_args.formatter != 'log': msg = _('--follow can only be specified with --format log') raise exc.CommandError(msg) marker = parsed_args.marker try: event_log_context = heat_utils.EventLogContext() while True: events = event_utils.get_events( client, stack_id=parsed_args.stack, event_args=kwargs, nested_depth=nested_depth, marker=marker) if events: marker = getattr(events[-1], 'id', None) events_log = heat_utils.event_log_formatter( events, event_log_context) self.app.stdout.write(events_log) self.app.stdout.write('\n') time.sleep(5) # this loop never exits except (KeyboardInterrupt, EOFError): # ctrl-c, ctrl-d return [], [] events = event_utils.get_events( client, stack_id=parsed_args.stack, event_args=kwargs, nested_depth=nested_depth, marker=parsed_args.marker, limit=parsed_args.limit) if parsed_args.sort: events = utils.sort_items(events, ','.join(sorts)) if parsed_args.formatter == 'log': return [], events if len(events): if hasattr(events[0], 'resource_name'): columns.insert(0, 'resource_name') columns.append('logical_resource_id') else: columns.insert(0, 'logical_resource_id') return ( columns, (utils.get_item_properties(s, columns) for s in events) )
def _heat_deploy(self, stack, stack_name, template_path, parameters, environments, timeout): """Verify the Baremetal nodes are available and do a stack update""" self.log.debug("Processing environment files") env_files, env = ( template_utils.process_multiple_environments_and_files( environments)) if stack: update.add_breakpoints_cleanup_into_env(env) self.log.debug("Getting template contents") template_files, template = template_utils.get_template_contents( template_path) files = dict(list(template_files.items()) + list(env_files.items())) clients = self.app.client_manager orchestration_client = clients.tripleoclient.orchestration self.log.debug("Deploying stack: %s", stack_name) self.log.debug("Deploying template: %s", template) self.log.debug("Deploying parameters: %s", parameters) self.log.debug("Deploying environment: %s", env) self.log.debug("Deploying files: %s", files) stack_args = { 'stack_name': stack_name, 'template': template, 'environment': env, 'files': files, 'clear_parameters': env['parameter_defaults'].keys(), } if timeout: stack_args['timeout_mins'] = timeout if stack is None: self.log.info("Performing Heat stack create") action = 'CREATE' marker = None orchestration_client.stacks.create(**stack_args) else: self.log.info("Performing Heat stack update") # Make sure existing parameters for stack are reused stack_args['existing'] = 'true' # Find the last top-level event to use for the first marker events = event_utils.get_events(orchestration_client, stack_id=stack_name, event_args={'sort_dir': 'desc', 'limit': 1}) marker = events[0].id if events else None action = 'UPDATE' orchestration_client.stacks.update(stack.id, **stack_args) verbose_events = self.app_args.verbose_level > 0 create_result = utils.wait_for_stack_ready( orchestration_client, stack_name, marker, action, verbose_events) if not create_result: if stack is None: raise Exception("Heat Stack create failed.") else: raise Exception("Heat Stack update failed.")
def take_action(self, parsed_args): self.log.debug('take_action(%s)', parsed_args) client = self.app.client_manager.orchestration columns = ['id', 'resource_status', 'resource_status_reason', 'event_time', 'physical_resource_id'] kwargs = { 'resource_name': parsed_args.resource, 'limit': parsed_args.limit, 'marker': parsed_args.marker, 'filters': heat_utils.format_parameters(parsed_args.filter), 'sort_dir': 'asc' } if parsed_args.resource and parsed_args.nested_depth: msg = _('--nested-depth cannot be specified with --resource') raise exc.CommandError(msg) if parsed_args.nested_depth: # Until the API supports recursive event listing we'll have to do # the marker/limit filtering client-side del kwargs['marker'] del kwargs['limit'] columns.append('stack_name') nested_depth = parsed_args.nested_depth else: nested_depth = 0 if parsed_args.follow: if parsed_args.formatter != 'value': msg = _('--follow can only be specified with --format value') raise exc.CommandError(msg) marker = parsed_args.marker try: while True: kwargs['marker'] = marker events = event_utils.get_events( client, stack_id=parsed_args.stack, event_args=kwargs, nested_depth=nested_depth, marker=marker) if events: marker = getattr(events[-1], 'id', None) events_log = heat_utils.event_log_formatter(events) self.app.stdout.write(events_log) self.app.stdout.write('\n') time.sleep(5) # this loop never exits except (KeyboardInterrupt, EOFError): # ctrl-c, ctrl-d return [], [] events = event_utils.get_events( client, stack_id=parsed_args.stack, event_args=kwargs, nested_depth=nested_depth, marker=parsed_args.marker, limit=parsed_args.limit) if parsed_args.sort: events = utils.sort_items(events, ','.join(parsed_args.sort)) if parsed_args.formatter == 'value': events = heat_utils.event_log_formatter(events).split('\n') return [], [e.split(' ') for e in events] if len(events): if hasattr(events[0], 'resource_name'): columns.insert(0, 'resource_name') columns.append('logical_resource_id') else: columns.insert(0, 'logical_resource_id') return ( columns, (utils.get_item_properties(s, columns) for s in events) )
def take_action(self, parsed_args): self.log.debug('take_action(%s)', parsed_args) client = self.app.client_manager.orchestration tpl_files, template = template_utils.process_template_path( parsed_args.template, object_request=http.authenticated_fetcher(client), existing=parsed_args.existing) env_files, env = ( template_utils.process_multiple_environments_and_files( env_paths=parsed_args.environment)) parameters = heat_utils.format_all_parameters( parsed_args.parameter, parsed_args.parameter_file, parsed_args.template) if parsed_args.pre_update: template_utils.hooks_to_env(env, parsed_args.pre_update, 'pre-update') fields = { 'stack_id': parsed_args.stack, 'parameters': parameters, 'existing': parsed_args.existing, 'template': template, 'files': dict(list(tpl_files.items()) + list(env_files.items())), 'environment': env } if parsed_args.tags: fields['tags'] = parsed_args.tags if parsed_args.timeout: fields['timeout_mins'] = parsed_args.timeout if parsed_args.clear_parameter: fields['clear_parameters'] = list(parsed_args.clear_parameter) if parsed_args.rollback: rollback = parsed_args.rollback.strip().lower() if rollback not in ('enabled', 'disabled', 'keep'): msg = _('--rollback invalid value: %s') % parsed_args.rollback raise exc.CommandError(msg) if rollback != 'keep': fields['disable_rollback'] = rollback == 'disabled' if parsed_args.dry_run: changes = client.stacks.preview_update(**fields) fields = ['state', 'resource_name', 'resource_type', 'resource_identity'] columns = sorted(changes.get("resource_changes", {}).keys()) data = [heat_utils.json_formatter(changes["resource_changes"][key]) for key in columns] return columns, data if parsed_args.wait: # find the last event to use as the marker events = event_utils.get_events(client, stack_id=parsed_args.stack, event_args={'sort_dir': 'desc', 'limit': 1}) marker = events[0].id if events else None client.stacks.update(**fields) if parsed_args.wait: stack = client.stacks.get(parsed_args.stack) stack_status, msg = event_utils.poll_for_events( client, stack.stack_name, action='UPDATE', marker=marker) if stack_status == 'UPDATE_FAILED': raise exc.CommandError(msg) return _show_stack(client, parsed_args.stack, format='table', short=True)
def take_action(self, parsed_args): self.log.debug("take_action(%s)", parsed_args) heat_client = self.app.client_manager.orchestration try: if not parsed_args.yes and sys.stdin.isatty(): sys.stdout.write( _("Are you sure you want to delete this stack(s) [y/N]? ")) prompt_response = sys.stdin.readline().lower() if not prompt_response.startswith('y'): self.log.info(_LI('User did not confirm stack delete so ' 'taking no action.')) return except KeyboardInterrupt: # ctrl-c self.log.info(_LI('User did not confirm stack delete ' '(ctrl-c) so taking no action.')) return except EOFError: # ctrl-d self.log.info(_LI('User did not confirm stack delete ' '(ctrl-d) so taking no action.')) return failure_count = 0 stacks_waiting = [] for sid in parsed_args.stack: marker = None if parsed_args.wait: try: # find the last event to use as the marker events = event_utils.get_events(heat_client, stack_id=sid, event_args={ 'sort_dir': 'desc', 'limit': 1}) if events: marker = events[0].id except heat_exc.CommandError as ex: failure_count += 1 print(ex) continue try: heat_client.stacks.delete(sid) stacks_waiting.append((sid, marker)) except heat_exc.HTTPNotFound: failure_count += 1 print(_('Stack not found: %s') % sid) except heat_exc.Forbidden: failure_count += 1 print(_('Forbidden: %s') % sid) if parsed_args.wait: for sid, marker in stacks_waiting: try: stack_status, msg = event_utils.poll_for_events( heat_client, sid, action='DELETE', marker=marker) except heat_exc.CommandError: continue if stack_status == 'DELETE_FAILED': failure_count += 1 print(msg) if failure_count: msg = (_('Unable to delete %(count)d of the %(total)d stacks.') % {'count': failure_count, 'total': len(parsed_args.stack)}) raise exc.CommandError(msg)
def _heat_deploy(self, stack, stack_name, template_path, parameters, environments, timeout): """Verify the Baremetal nodes are available and do a stack update""" self.log.debug("Processing environment files") env_files, env = ( template_utils.process_multiple_environments_and_files( environments)) if stack: update.add_breakpoints_cleanup_into_env(env) self.log.debug("Getting template contents") template_files, template = template_utils.get_template_contents( template_path) files = dict(list(template_files.items()) + list(env_files.items())) clients = self.app.client_manager orchestration_client = clients.tripleoclient.orchestration self.log.debug("Deploying stack: %s", stack_name) self.log.debug("Deploying template: %s", template) self.log.debug("Deploying parameters: %s", parameters) self.log.debug("Deploying environment: %s", env) self.log.debug("Deploying files: %s", files) stack_args = { 'stack_name': stack_name, 'template': template, 'environment': env, 'files': files, 'clear_parameters': env['parameter_defaults'].keys(), } if timeout: stack_args['timeout_mins'] = timeout if stack is None: self.log.info("Performing Heat stack create") action = 'CREATE' marker = None orchestration_client.stacks.create(**stack_args) else: self.log.info("Performing Heat stack update") # Make sure existing parameters for stack are reused stack_args['existing'] = 'true' # Find the last top-level event to use for the first marker events = event_utils.get_events(orchestration_client, stack_id=stack_name, event_args={ 'sort_dir': 'desc', 'limit': 1 }) marker = events[0].id if events else None action = 'UPDATE' orchestration_client.stacks.update(stack.id, **stack_args) verbose_events = self.app_args.verbose_level > 0 create_result = utils.wait_for_stack_ready(orchestration_client, stack_name, marker, action, verbose_events) if not create_result: if stack is None: raise exceptions.DeploymentError("Heat Stack create failed.") else: raise exceptions.DeploymentError("Heat Stack update failed.")
def take_action(self, parsed_args): self.log.debug('take_action(%s)', parsed_args) client = self.app.client_manager.orchestration columns = [ 'id', 'resource_status', 'resource_status_reason', 'event_time', 'physical_resource_id' ] kwargs = { 'resource_name': parsed_args.resource, 'limit': parsed_args.limit, 'marker': parsed_args.marker, 'filters': heat_utils.format_parameters(parsed_args.filter), 'sort_dir': 'asc' } if parsed_args.resource and parsed_args.nested_depth: msg = _('--nested-depth cannot be specified with --resource') raise exc.CommandError(msg) if parsed_args.nested_depth: # Until the API supports recursive event listing we'll have to do # the marker/limit filtering client-side del kwargs['marker'] del kwargs['limit'] columns.append('stack_name') nested_depth = parsed_args.nested_depth else: nested_depth = 0 if parsed_args.follow: if parsed_args.formatter != 'value': msg = _('--follow can only be specified with --format value') raise exc.CommandError(msg) marker = parsed_args.marker try: while True: kwargs['marker'] = marker events = event_utils.get_events(client, stack_id=parsed_args.stack, event_args=kwargs, nested_depth=nested_depth, marker=marker) if events: marker = getattr(events[-1], 'id', None) events_log = heat_utils.event_log_formatter(events) self.app.stdout.write(events_log) self.app.stdout.write('\n') time.sleep(5) # this loop never exits except (KeyboardInterrupt, EOFError): # ctrl-c, ctrl-d return [], [] events = event_utils.get_events(client, stack_id=parsed_args.stack, event_args=kwargs, nested_depth=nested_depth, marker=parsed_args.marker, limit=parsed_args.limit) if parsed_args.sort: events = utils.sort_items(events, ','.join(parsed_args.sort)) if parsed_args.formatter == 'value': events = heat_utils.event_log_formatter(events).split('\n') return [], [e.split(' ') for e in events] if len(events): if hasattr(events[0], 'resource_name'): columns.insert(0, 'resource_name') columns.append('logical_resource_id') else: columns.insert(0, 'logical_resource_id') return (columns, (utils.get_item_properties(s, columns) for s in events))