def _export_template_and_clone(self, req, id, body): LOG.debug("start export_template_and_clone,the plan id is %s" % id) context = req.environ['conveyor.context'] if not self.is_valid_body(body, 'export_template_and_clone'): LOG.debug("clone request body has not key:clone") raise exc.HTTPUnprocessableEntity() clone_body = body['export_template_and_clone'] destination = clone_body.get('destination') if not isinstance(destination, dict): msg = _("The parameter 'destination' must be a map.") raise exc.HTTPBadRequest(explanation=msg) sys_clone = clone_body.get('sys_clone', False) copy_data = clone_body.get('copy_data', True) resources = clone_body.get('resources') plan = db_api.plan_get(context, id) plan_status = plan['plan_status'] if plan_status not in (p_status.INITIATING, p_status.AVAILABLE, p_status.FINISHED, p_status.CREATING): msg = _("the plan %(plan_id)s in state %(state)s" "can't export_template_and_clone") % { 'plan_id': id, 'state': plan_status, } raise exc.HTTPBadRequest(explanation=msg) self.clone_api.export_template_and_clone(context, id, destination, resources, sys_clone, copy_data)
def read_plan_from_db(context, plan_id): # 1. query plan base info to db plan_dict = db_api.plan_get(context, plan_id) plan_obj = Plan.from_dict(plan_dict) plan_obj.rebuild_dependencies() return plan_obj.to_dict()
def _delete_plan(self, context, plan_id): LOG.info("Begin to delete plan with id of %s", plan_id) plan = db_api.plan_get(context, plan_id) if not plan: LOG.error('Delete plan %s failed' % plan_id) raise exception.PlanNotFound(plan_id=plan_id) plan_cls.update_plan_to_db(context, plan_id, {'plan_status': p_status.DELETING}) # delete heat stack info self.heat_api.clear_table(context, plan['stack_id'], plan_id) # delete template info try: db_api.plan_template_delete(context, plan_id) except exception.PlanNotFoundInDb: LOG.warn('Plan does not have template :%s', plan_id) except Exception as e: LOG.error('Delete plan %(id)s template info failed: %(err)s', { 'id': plan_id, 'err': e }) raise try: db_api.plan_cloned_resource_delete(context, plan_id) except exception.PlanNotFoundInDb: LOG.warn('Plan does not have cloned resources :%s', plan_id) except Exception as e: LOG.error('Delete plan %(id)s cloned resources failed: %(err)s', { 'id': plan_id, 'err': e }) raise try: db_api.plan_availability_zone_mapper_delete(context, plan_id) except exception.PlanNotFoundInDb: LOG.warn('Plan does not have az map :%s', plan_id) except Exception as e: LOG.error('Delete plan %(id)s az map failed: %(err)s', { 'id': plan_id, 'err': e }) raise # delete plan info try: db_api.plan_delete(context, plan_id) except exception.PlanNotFoundInDb: LOG.warn('Plan does not have az map :%s', plan_id) except Exception as e: LOG.error('Delete plan %(id)s az map failed: %(err)s', { 'id': plan_id, 'err': e }) raise LOG.info("Delete plan with id of %s succeed!", plan_id)
def _export_clone_template(self, req, id, body): LOG.debug(" start exporting template in API") context = req.environ['conveyor.context'] plan = db_api.plan_get(context, id) plan_status = plan['plan_status'] if plan_status not in (p_status.INITIATING, p_status.CREATING): msg = _('the plan %(plan_id)s in state %(state)s' " can't export template") % {'plan_id': id, 'state': plan_status} raise exc.HTTPBadRequest(explanation=msg) clone_body = body['export_clone_template'] sys_clone = clone_body.get('sys_clone', False) copy_data = clone_body.get('copy_data', True) self.clone_api.export_clone_template(context, id, sys_clone, copy_data)
def _delete_plan(self, context, plan_id): LOG.info("Begin to delete plan with id of %s", plan_id) plan = db_api.plan_get(context, plan_id) if not plan: LOG.error('Delete plan %s failed' % plan_id) raise exception.PlanNotFound(plan_id=plan_id) plan_cls.update_plan_to_db(context, plan_id, {'plan_status': p_status.DELETING}) # delete heat stack info self.heat_api.clear_table(context, plan['stack_id'], plan_id) # delete template info try: db_api.plan_template_delete(context, plan_id) except exception.PlanNotFoundInDb: LOG.warn('Plan does not have template :%s', plan_id) except Exception as e: LOG.error('Delete plan %(id)s template info failed: %(err)s', {'id': plan_id, 'err': e}) raise try: db_api.plan_cloned_resource_delete(context, plan_id) except exception.PlanNotFoundInDb: LOG.warn('Plan does not have cloned resources :%s', plan_id) except Exception as e: LOG.error('Delete plan %(id)s cloned resources failed: %(err)s', {'id': plan_id, 'err': e}) raise try: db_api.plan_availability_zone_mapper_delete(context, plan_id) except exception.PlanNotFoundInDb: LOG.warn('Plan does not have az map :%s', plan_id) except Exception as e: LOG.error('Delete plan %(id)s az map failed: %(err)s', {'id': plan_id, 'err': e}) raise # delete plan info try: db_api.plan_delete(context, plan_id) except exception.PlanNotFoundInDb: LOG.warn('Plan does not have az map :%s', plan_id) except Exception as e: LOG.error('Delete plan %(id)s az map failed: %(err)s', {'id': plan_id, 'err': e}) raise LOG.info("Delete plan with id of %s succeed!", plan_id)
def show(self, req, id): LOG.debug("Get plan with id of %s.", id) if not uuidutils.is_uuid_like(id): msg = _("Invalid id provided, id must be uuid.") raise exc.HTTPBadRequest(explanation=msg) context = req.environ['conveyor.context'] try: plan = db_api.plan_get(context, id) return {"plan": plan} except Exception as e: LOG.error(unicode(e)) raise exc.HTTPInternalServerError(explanation=unicode(e))
def _export_clone_template(self, req, id, body): LOG.debug(" start exporting template in API") context = req.environ['conveyor.context'] plan = db_api.plan_get(context, id) plan_status = plan['plan_status'] if plan_status not in (p_status.INITIATING, p_status.CREATING): msg = _('the plan %(plan_id)s in state %(state)s' " can't export template") % { 'plan_id': id, 'state': plan_status } raise exc.HTTPBadRequest(explanation=msg) clone_body = body['export_clone_template'] sys_clone = clone_body.get('sys_clone', False) copy_data = clone_body.get('copy_data', True) self.clone_api.export_clone_template(context, id, sys_clone, copy_data)
def force_delete_plan(self, context, plan_id): plan = db_api.plan_get(context, plan_id) stack_id = plan.get('stack_id', None) if plan else None self.heat_api.clear_table(context, stack_id, plan_id) try: db_api.plan_template_delete(context, plan_id) except exception.PlanNotFoundInDb: LOG.warn('Plan does not have template :%s', plan_id) except Exception as e: LOG.error('Delete plan %(id)s template info failed: %(err)s', { 'id': plan_id, 'err': e }) raise try: db_api.plan_cloned_resource_delete(context, plan_id) except exception.PlanNotFoundInDb: LOG.warn('Plan does not have cloned resources :%s', plan_id) except Exception as e: LOG.error('Delete plan %(id)s cloned resources failed: %(err)s', { 'id': plan_id, 'err': e }) raise try: db_api.plan_availability_zone_mapper_delete(context, plan_id) except exception.PlanNotFoundInDb: LOG.warn('Plan does not have az map :%s', plan_id) except Exception as e: LOG.error('Delete plan %(id)s az map failed: %(err)s', { 'id': plan_id, 'err': e }) raise # delete plan info try: db_api.plan_delete(context, plan_id) except exception.PlanNotFoundInDb: LOG.warn('Plan does not have az map :%s', plan_id) except Exception as e: LOG.error('Delete plan %(id)s az map failed: %(err)s', { 'id': plan_id, 'err': e }) raise
def _download_template(self, req, id, body): LOG.debug("download template of plan %s start in API from template", id) context = req.environ['conveyor.context'] plan = db_api.plan_get(context, id) plan_status = plan['plan_status'] if plan_status not in (p_status.AVAILABLE, p_status.CLONING, p_status.MIGRATING, p_status.FINISHED): msg = _("the plan %(plan_id)s in state %(state)s" "can't download template") % { 'plan_id': id, 'state': plan_status, } raise exc.HTTPBadRequest(explanation=msg) content = self.clone_api.download_template(context, id) LOG.debug('the content is %s' % content) return content
def _clone(self, req, id, body): LOG.error('begin time of clone is %s' % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))) LOG.debug("start execute clone plan in API,the plan id is %s" % id) context = req.environ['conveyor.context'] if not self.is_valid_body(body, 'clone'): LOG.debug("clone request body has not key:clone") raise exc.HTTPUnprocessableEntity() plan = db_api.plan_get(context, id) plan_status = plan['plan_status'] if plan_status not in ( p_status.AVAILABLE, p_status.MIGRATING, p_status.FINISHED, ): msg = _("the plan %(plan_id)s in state %(state)s can't clone") % { 'plan_id': id, 'state': plan_status, } raise exc.HTTPBadRequest(explanation=msg) clone_body = body['clone'] plan_id = clone_body.get('plan_id') az_map = clone_body.get('availability_zone_map') clone_resources = clone_body.get('clone_resources', []) clone_links = clone_body.get('clone_links', []) update_resources = clone_body.get('update_resources', []) replace_resources = clone_body.get('replace_resources', []) sys_clone = clone_body.get('sys_clone', False) data_copy = clone_body.get('copy_data', True) LOG.debug( "Clone Resources: %(res)s, " "the replaces: %(link)s, the update: %(up)s", { 'res': clone_resources, 'link': replace_resources, 'up': update_resources }) if not isinstance(az_map, dict): msg = _("The parameter 'destination' must be a map.") raise exc.HTTPBadRequest(explanation=msg) context = req.environ['conveyor.context'] self.clone_api.clone(context, plan_id, az_map, clone_resources, clone_links, update_resources, replace_resources, sys_clone, data_copy)
def delete_plan(self, context, plan_id): allowed_status = (p_status.INITIATING, p_status.CREATING, p_status.AVAILABLE, p_status.ERROR, p_status.FINISHED, p_status.EXPIRED) try: plan = db_api.plan_get(context, plan_id) if plan['plan_status'] not in allowed_status: msg = ("Plan isn't allowed to be deleted in %s status." % plan['plan_status']) LOG.error(msg) raise exception.PlanDeleteError(message=msg) except exception.PlanNotFoundInDb: LOG.error('The plan %s could not be found.', plan_id) raise exception.PlanNotFound(plan_id=plan_id) LOG.info("Begin to delete plan with id of %s", plan_id) plan_cls.update_plan_to_db(context, plan_id, {'plan_status': p_status.DELETING}) return self.plan_rpcapi.delete_plan(context, plan_id)
def force_delete_plan(self, context, plan_id): plan = db_api.plan_get(context, plan_id) stack_id = plan.get('stack_id', None) if plan else None self.heat_api.clear_table(context, stack_id, plan_id) try: db_api.plan_template_delete(context, plan_id) except exception.PlanNotFoundInDb: LOG.warn('Plan does not have template :%s', plan_id) except Exception as e: LOG.error('Delete plan %(id)s template info failed: %(err)s', {'id': plan_id, 'err': e}) raise try: db_api.plan_cloned_resource_delete(context, plan_id) except exception.PlanNotFoundInDb: LOG.warn('Plan does not have cloned resources :%s', plan_id) except Exception as e: LOG.error('Delete plan %(id)s cloned resources failed: %(err)s', {'id': plan_id, 'err': e}) raise try: db_api.plan_availability_zone_mapper_delete(context, plan_id) except exception.PlanNotFoundInDb: LOG.warn('Plan does not have az map :%s', plan_id) except Exception as e: LOG.error('Delete plan %(id)s az map failed: %(err)s', {'id': plan_id, 'err': e}) raise # delete plan info try: db_api.plan_delete(context, plan_id) except exception.PlanNotFoundInDb: LOG.warn('Plan does not have az map :%s', plan_id) except Exception as e: LOG.error('Delete plan %(id)s az map failed: %(err)s', {'id': plan_id, 'err': e}) raise
def _clone(self, req, id, body): LOG.error('begin time of clone is %s' % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))) LOG.debug("start execute clone plan in API,the plan id is %s" % id) context = req.environ['conveyor.context'] if not self.is_valid_body(body, 'clone'): LOG.debug("clone request body has not key:clone") raise exc.HTTPUnprocessableEntity() plan = db_api.plan_get(context, id) plan_status = plan['plan_status'] if plan_status not in (p_status.AVAILABLE, p_status.MIGRATING, p_status.FINISHED,): msg = _("the plan %(plan_id)s in state %(state)s can't clone") % { 'plan_id': id, 'state': plan_status, } raise exc.HTTPBadRequest(explanation=msg) clone_body = body['clone'] plan_id = clone_body.get('plan_id') az_map = clone_body.get('availability_zone_map') clone_resources = clone_body.get('clone_resources', []) clone_links = clone_body.get('clone_links', []) update_resources = clone_body.get('update_resources', []) replace_resources = clone_body.get('replace_resources', []) sys_clone = clone_body.get('sys_clone', False) data_copy = clone_body.get('copy_data', True) LOG.debug("Clone Resources: %(res)s, " "the replaces: %(link)s, the update: %(up)s", {'res': clone_resources, 'link': replace_resources, 'up': update_resources}) if not isinstance(az_map, dict): msg = _("The parameter 'destination' must be a map.") raise exc.HTTPBadRequest(explanation=msg) context = req.environ['conveyor.context'] self.clone_api.clone(context, plan_id, az_map, clone_resources, clone_links, update_resources, replace_resources, sys_clone, data_copy)
def update_plan(self, context, plan_id, values): if not isinstance(values, dict): msg = "Update plan failed. 'values' attribute must be a dict." LOG.error(msg) raise exception.PlanUpdateError(message=msg) allowed_status = (p_status.INITIATING, p_status.CREATING, p_status.AVAILABLE, p_status.FINISHED) try: plan = db_api.plan_get(context, plan_id) if 'updated_resources' in values.keys() \ and plan['plan_status'] not in allowed_status: msg = ("Plan are not allowed to be updated in %s status." % plan['plan_status']) LOG.error(msg) raise exception.PlanUpdateError(message=msg) except exception.PlanNotFoundInDb: LOG.error('Plan <%s> could not be found.', plan_id) raise exception.PlanNotFound(plan_id=plan_id) LOG.info("Update plan <%s> with values: %s", plan_id, values) return self.plan_rpcapi.update_plan(context, plan_id, values)
def update_plan_resources(self, context, plan_id, resources): LOG.info("Update resources of plan <%s> with values: %s", plan_id, resources) if not isinstance(resources, list): msg = "'resources' argument must be a list." LOG.error(msg) raise exception.PlanUpdateError(message=msg) # Verify plan allowed_status = (p_status.INITIATING, p_status.CREATING, p_status.AVAILABLE, p_status.FINISHED) try: plan = db_api.plan_get(context, plan_id) if plan['plan_status'] not in allowed_status: msg = ("Plan are not allowed to be updated in %s status." % plan['plan_status']) LOG.error(msg) raise exception.PlanUpdateError(message=msg) except exception.PlanNotFoundInDb: LOG.error('The plan <%s> could not be found.', plan_id) raise exception.PlanNotFound(plan_id=plan_id) # Verify resources for res in resources: if not isinstance(res, dict): msg = "Every resource to be updated must be a dict." LOG.error(msg) raise exception.PlanUpdateError(message=msg) action = res.get('action') if not action or action not in ('add', 'edit', 'delete'): msg = "%s action is unsupported." % action LOG.error(msg) raise exception.PlanUpdateError(message=msg) if action == 'add' and ('id' not in res.keys() or 'resource_type' not in res.keys()): msg = ("'id' and 'resource_type' of new resource " "must be provided when adding new resources.") LOG.error(msg) raise exception.PlanUpdateError(message=msg) elif action == 'edit' and (len(res) < 2 or 'resource_id' not in res.keys()): msg = ("'resource_id' and the fields to be edited " "must be provided when editing resources.") LOG.error(msg) raise exception.PlanUpdateError(message=msg) elif action == 'delete' and 'resource_id' not in res.keys(): msg = "'resource_id' must be provided when " \ "deleting resources." LOG.error(msg) raise exception.PlanUpdateError(message=msg) # Simply parse value. for k, v in res.items(): if v == 'true': res[k] = True elif v == 'false': res[k] = False elif isinstance(v, six.string_types): try: new_value = eval(v) if type(new_value) in (dict, list, numbers.Number): res[k] = new_value except Exception: pass return self.plan_rpcapi.update_plan_resources(context, plan_id, resources)