def destroy_assembly(self, ctxt, assem_id): update_assembly(ctxt, assem_id, {'status': STATES.DELETING}) assem = objects.registry.Assembly.get_by_id(ctxt, assem_id) app_obj = get_app_by_assem_id(ctxt, assem.id) LOG.debug("Deleting app %s" % app_obj.name) logs_resource_id = assem.uuid stack_id = self._find_id_if_stack_exists(assem) try: workflow = objects.registry.Workflow.get_by_assembly_id(assem_id) workflow_id = workflow.id wf_found = True except exception.ResourceNotFound: # get_by_assembly_id would result in ResourceNotFound exception # if assembly is created directly. In that case use assembly_id # with TenantLogger workflow_id = assem.uuid wf_found = False # TODO(devkulkarni) Delete t_logger when returning from this call. # This needs to be implemented as a context since there are # multiple return paths from this method. t_logger = tlog.TenantLogger(ctxt, assem, workflow_id, deployer_log_dir, 'delete') msg = "Deleting Assembly %s Workflow %s" % (assem.uuid, workflow_id) t_logger.log(logging.DEBUG, msg) LOG.debug(msg) if stack_id is None: t_logger.upload() self._clean_up_artifacts(ctxt, t_logger, logs_resource_id, assem) if not wf_found: assem.destroy(ctxt) return else: # Get the heat client heat_clnt = get_heat_client(ctxt, app_obj) try: t_logger.log(logging.DEBUG, "Deleting Heat stack.") LOG.debug("Deleting Heat stack %s", stack_id) heat_clnt.stacks.delete(stack_id) except exc.HTTPNotFound: # stack already deleted t_logger.log(logging.ERROR, "Heat stack not found.") t_logger.upload() self._clean_up_artifacts(ctxt, t_logger, logs_resource_id, assem) if not wf_found: assem.destroy(ctxt) return except Exception as e: LOG.exception(e) update_assembly(ctxt, assem_id, {'status': STATES.ERROR_STACK_DELETE_FAILED}) t_logger.log(logging.ERROR, "Error deleting heat stack.") t_logger.upload() return wait_interval = cfg.CONF.deployer.wait_interval growth_factor = cfg.CONF.deployer.growth_factor stack_name = self._get_stack_name(assem) t_logger.log(logging.DEBUG, "Checking if Heat stack was deleted.") for count in range(cfg.CONF.deployer.max_attempts): try: # Must use stack_name for expecting a 404 heat_clnt.stacks.get(stack_name) except exc.HTTPNotFound: t_logger.log(logging.DEBUG, "Stack delete successful.") t_logger.upload() self._clean_up_artifacts(ctxt, t_logger, logs_resource_id, assem) if not wf_found: assem.destroy(ctxt) return time.sleep(wait_interval) wait_interval *= growth_factor update_assembly(ctxt, assem_id, {'status': STATES.ERROR_STACK_DELETE_FAILED}) t_logger.log(logging.ERROR, "Error deleting heat stack.") t_logger.upload()
def deploy(self, ctxt, assembly_id, image_loc, image_name, ports): app_obj = get_app_by_assem_id(ctxt, assembly_id) LOG.debug("Deploying app %s" % app_obj.name) save_du_ref_for_scaling(ctxt, assembly_id, du=image_loc) # Get the heat client heat_clnt = get_heat_client(ctxt, app_obj) # Get reference to OpenStackClients as it is used to get a reference # to neutron client for getting networking parameters osc = clients.OpenStackClients(ctxt) assem = objects.registry.Assembly.get_by_id(ctxt, assembly_id) workflow = objects.registry.Workflow.get_by_assembly_id(assembly_id) # TODO(devkulkarni) Delete t_logger when returning from this call. # This needs to be implemented as a decorator since there are # multiple return paths from this method. t_logger = tlog.TenantLogger(ctxt, assem, workflow.id, deployer_log_dir, 'deploy') msg = "Deploying Assembly %s Workflow %s" % (assem.uuid, workflow.id) t_logger.log(logging.DEBUG, msg) LOG.debug("Image loc:%s, image_name:%s" % (image_loc, image_name)) parameters = self._get_parameters(ctxt, cfg.CONF.api.image_format, image_loc, image_name, assem, ports, osc, t_logger) LOG.debug(parameters) if parameters is None: return template = self._get_template(ctxt, cfg.CONF.api.image_format, cfg.CONF.worker.image_storage, image_loc, image_name, assem, ports, t_logger) LOG.debug(template) if template is None: return stack_name = self._get_stack_name(assem) stack_id = self._find_id_if_stack_exists(assem) if assem.status == STATES.DELETING: t_logger.log(logging.DEBUG, "Assembly being deleted..returning") t_logger.upload() return if stack_id is not None: try: heat_clnt.stacks.update(stack_id, stack_name=stack_name, template=template, parameters=parameters) except Exception as e: LOG.error("Error updating Heat Stack for," " assembly %s" % assembly_id) LOG.exception(e) update_assembly(ctxt, assembly_id, {'status': STATES.ERROR}) t_logger.log(logging.ERROR, "Error updating heat stack.") t_logger.upload() return else: try: getfile_key = "robust-du-handling.sh" file_cnt = None try: file_cnt = catalog.get_from_contrib(getfile_key) except exception.ObjectNotFound as onf_ex: LOG.exception(onf_ex) update_assembly(ctxt, assem.id, {'status': STATES.ERROR}) t_logger.log(logging.ERROR, "Error reading %s" % getfile_key) t_logger.upload() return get_file_dict = {} get_file_dict[getfile_key] = file_cnt created_stack = heat_clnt.stacks.create(stack_name=stack_name, template=template, parameters=parameters, files=get_file_dict) except Exception as exp: LOG.error("Error creating Heat Stack for," " assembly %s" % assembly_id) LOG.exception(exp) update_assembly(ctxt, assembly_id, {'status': STATES.ERROR_STACK_CREATE_FAILED}) t_logger.log(logging.ERROR, "Error creating heat stack.") t_logger.upload() return stack_id = created_stack['stack']['id'] LOG.debug("Stack id: %s" % stack_id) comp_name = 'Heat_Stack_for_%s' % assem.name comp_description = 'Heat Stack %s' % ( yaml.safe_load(template).get('description')) try: objects.registry.Component.assign_and_create( ctxt, assem, comp_name, 'heat_stack', comp_description, created_stack['stack']['links'][0]['href'], stack_id) except sqla_exc.IntegrityError: LOG.error("IntegrityError in creating Heat Stack component," " assembly %s may be deleted" % assembly_id) update_assembly(ctxt, assembly_id, {'status': STATES.ERROR}) t_logger.log(logging.ERROR, "Error creating heat stack.") t_logger.upload() return update_assembly(ctxt, assembly_id, {'status': STATES.DEPLOYING}) result = self._check_stack_status(ctxt, assembly_id, heat_clnt, stack_id, ports, t_logger) assem.status = result t_logger.upload() if result == STATES.DEPLOYMENT_COMPLETE: self._destroy_other_assemblies(ctxt, assembly_id, heat_clnt)
def _get_tenant_logger(self, stage): return tenant_logger.TenantLogger(self.context, self.assembly, log_dir, stage)