def post(self, request, group_id, record_id, *args, **kwargs): """提交回滚任务""" service_ids = parse_item(request, 'service_ids', required=True, error='service_ids is a required parameter') # 判断是不是最后一条升级记录 app_record = AppUpgradeRecord.objects.filter( tenant_id=self.tenant.tenant_id, group_id=int(group_id), status__in=(UpgradeStatus.UPGRADED.value, UpgradeStatus.ROLLBACK.value, UpgradeStatus.PARTIAL_UPGRADED.value, UpgradeStatus.PARTIAL_ROLLBACK.value, UpgradeStatus.UPGRADE_FAILED.value, UpgradeStatus.ROLLBACK_FAILED.value)).order_by('-create_time').first() if not app_record or app_record.ID != int(record_id): raise AbortRequest(msg="This upgrade cannot be rolled back", msg_show=u"本次升级无法回滚") service_records = app_record.service_upgrade_records.filter( status__in=(UpgradeStatus.UPGRADED.value, UpgradeStatus.ROLLBACK.value, UpgradeStatus.UPGRADE_FAILED.value, UpgradeStatus.ROLLBACK_FAILED.value), upgrade_type=ServiceUpgradeRecord.UpgradeType.UPGRADE.value, service_id__in=service_ids) services = service_repo.get_services_by_service_ids_and_group_key( app_record.group_key, service_records.values_list('service_id', flat=True) or []) market_services = [ upgrade_service.market_service_and_restore_backup(self.tenant, service, app_record.version) for service in services ] upgrade_service.send_rolling_request(market_services, self.tenant, self.user, app_record, service_records) upgrade_repo.change_app_record_status(app_record, UpgradeStatus.ROLLING.value) return MessageResponse(msg="success", bean=upgrade_service.serialized_upgrade_record(app_record))
def synchronous_upgrade_status(self, tenant, record): """ 同步升级状态 :type tenant: www.models.main.Tenants :type record: AppUpgradeRecord """ from console.services.app_actions import event_service # 升级中,回滚中 才需要同步 synchronization_type = { UpgradeStatus.UPGRADING.value, UpgradeStatus.ROLLING.value } if record.status not in synchronization_type: return # 回滚时只同步升级类型的记录 q = Q(upgrade_type=ServiceUpgradeRecord.UpgradeType.UPGRADE.value ) if record.status == UpgradeStatus.ROLLING.value else Q() service_records = record.service_upgrade_records.filter(q).all() event_service_mapping = { record.event_id: record for record in service_records if record.status in synchronization_type and record.event_id } events = event_repo.get_events_by_event_ids( event_service_mapping.keys()) # 去数据中心同步事件 event_service.sync_region_service_event_status(tenant.region, tenant.tenant_name, events) for event in events: service_record = event_service_mapping[event.event_id] self._change_service_record_status(event, service_record) service_status = set( service_records.values_list('status', flat=True) or []) judging_status = { # 升级中 UpgradeStatus.UPGRADING.value: self._judging_status_upgrading, # 回滚中 UpgradeStatus.ROLLING.value: self._judging_status_rolling, } status = judging_status[record.status](service_status) if status: upgrade_repo.change_app_record_status(record, status)
def synchronous_upgrade_status(self, tenant, region_name, record): """ 同步升级状态 :type tenant: www.models.main.Tenants :type record: AppUpgradeRecord """ # 升级中,回滚中 才需要同步 synchronization_type = { UpgradeStatus.UPGRADING.value, UpgradeStatus.ROLLING.value } if record.status not in synchronization_type: return # 回滚时只同步升级类型的记录 q = Q(upgrade_type=ServiceUpgradeRecord.UpgradeType.UPGRADE.value ) if record.status == UpgradeStatus.ROLLING.value else Q() service_records = record.service_upgrade_records.filter(q).all() event_service_mapping = { record.event_id: record for record in service_records if record.status in synchronization_type and record.event_id } event_ids = list(event_service_mapping.keys()) body = region_api.get_tenant_events(region_name, tenant.tenant_name, event_ids) events = body.get("list", []) for event in events: service_record = event_service_mapping[event["EventID"]] self._change_service_record_status(event["Status"], service_record) service_status = set( service_records.values_list('status', flat=True) or []) judging_status = { # 升级中 UpgradeStatus.UPGRADING.value: self._judging_status_upgrading, # 回滚中 UpgradeStatus.ROLLING.value: self._judging_status_rolling, } status = judging_status[record.status](service_status) if status: upgrade_repo.change_app_record_status(record, status)
def deploy(self, tenant, region_name, user, record: AppUpgradeRecord): if not record.can_deploy(): raise ErrAppUpgradeRecordCanNotDeploy # failed events component_records = component_upgrade_record_repo.list_by_app_record_id(record.ID) component_records = [record for record in component_records] failed_component_records = { record.event_id: record for record in component_records if record.status in [UpgradeStatus.PARTIAL_UPGRADED.value, UpgradeStatus.PARTIAL_ROLLBACK.value, UpgradeStatus.DEPLOY_FAILED.value] } component_ids = [record.service_id for record in failed_component_records.values()] try: events = app_manage_service.batch_operations(tenant, region_name, user, "deploy", component_ids) status = UpgradeStatus.UPGRADING.value \ if record.record_type == UpgradeType.UPGRADE.value else UpgradeStatus.ROLLING.value upgrade_repo.change_app_record_status(record, status) except ServiceHandleException as e: upgrade_repo.change_app_record_status(record, UpgradeStatus.DEPLOY_FAILED.value) raise ErrAppUpgradeDeployFailed(e.msg) except Exception as e: upgrade_repo.change_app_record_status(record, UpgradeStatus.DEPLOY_FAILED.value) raise e self._update_component_records(record, failed_component_records.values(), events)
def post(self, request, group_id, *args, **kwargs): """提交升级任务""" rq_args = ( { 'key': 'upgrade_record_id', 'required': True, 'error': 'upgrade_record_id is a required parameter' }, { 'key': 'group_key', 'required': True, 'error': 'group_key is a required parameter' }, { 'key': 'version', 'required': True, 'error': 'version is a required parameter' }, { 'key': 'services', 'required': True, 'error': 'services is a required parameter' }, ) data = parse_date(request, rq_args) group_key = data['group_key'] version = data['version'] app_record = get_object_or_404( AppUpgradeRecord, msg="Upgrade record not found", tenant_id=self.tenant.tenant_id, group_id=int(group_id), group_key=group_key, status=UpgradeStatus.NOT.value, pk=data['upgrade_record_id'], ) # 处理新增的服务 add_service_infos = { service['service']['service_key']: service['upgrade_info'] for service in data['services'] if service['service']['type'] == UpgradeType.ADD.value and service['upgrade_info'] } install_info = {} if add_service_infos: old_app = rainbond_app_repo.get_rainbond_app_by_key_version( group_key=group_key, version=version) new_app = deepcopy(old_app) # mock app信息 template = json.loads(new_app.app_template) template['apps'] = add_service_infos.values() new_app.app_template = json.dumps(template) # 查询某一个云市应用下的所有服务 services = group_service.get_rainbond_services( int(group_id), group_key) try: market_app_service.check_package_app_resource( self.tenant, self.response_region, new_app) install_info = market_app_service.install_service_when_upgrade_app( self.tenant, self.response_region, self.user, group_id, new_app, old_app, services, True) except (ResourceNotEnoughException, AccountOverdueException) as re: logger.exception(re) return MessageResponse(msg="resource is not enough", msg_show=re.message, status_code=412, error_code=10406) upgrade_service.create_add_service_record(app_record, install_info['events'], add_service_infos) # 处理需要升级的服务 upgrade_service_infos = { service['service']['service_id']: service['upgrade_info'] for service in data['services'] if service['service']['type'] == UpgradeType.UPGRADE.value and service['upgrade_info'] } app_record.version = version app_record.old_version = upgrade_service.get_old_version( group_key, upgrade_service_infos.keys()) app_record.save() services = service_repo.get_services_by_service_ids_and_group_key( data['group_key'], upgrade_service_infos.keys()) market_services = [ upgrade_service.market_service_and_create_backup( self.tenant, service, app_record.version) for service in services ] upgrade_service.upgrade_database(market_services) upgrade_service.send_upgrade_request(market_services, self.tenant, self.user, app_record, upgrade_service_infos) upgrade_repo.change_app_record_status(app_record, UpgradeStatus.UPGRADING.value) # 处理依赖关系 if add_service_infos: market_app_service.save_service_deps_when_upgrade_app( self.tenant, install_info['service_key_dep_key_map'], install_info['key_service_map'], install_info['apps'], install_info['app_map'], ) return MessageResponse( msg="success", bean=upgrade_service.serialized_upgrade_record(app_record))
def openapi_upgrade_app_models(self, user, team, region_name, oauth_instance, app_id, data): from console.services.market_app_service import market_app_service update_versions = data["update_versions"] for update_version in update_versions: app_model_id = update_version["app_model_id"] app_model_version = update_version["app_model_version"] market_name = update_version["market_name"] # TODO: get upgrade component will set upgrade_group_id. # Otherwise, there is a problem with multiple installs and upgrades of an application. services = group_service.get_rainbond_services( int(app_id), app_model_id) if not services: continue exist_component = services.first() pc = PropertiesChanges(exist_component, team, all_component_one_model=services) recode_kwargs = { "tenant_id": team.tenant_id, "group_id": int(app_id), "group_key": app_model_id, "is_from_cloud": bool(market_name), "market_name": market_name, } # 获取升级信息 upgrade_info, add_info = self.get_upgrade_info( team, services, app_model_id, app_model_version, market_name) # 生成升级记录 app_record = self.get_or_create_upgrade_record(**recode_kwargs) self.synchronous_upgrade_status(team, region_name, app_record) app_record = AppUpgradeRecord.objects.get(ID=app_record.ID) # 处理新增的组件 install_info = {} if add_info: old_app = app_market_service.get_market_app_model_version( pc.market, app_model_id, app_model_version, get_template=True) new_app = deepcopy(old_app) # mock app信息 template = json.loads(new_app.template) template['apps'] = list(add_info.values()) new_app.template = json.dumps(template) # 查询某一个云市应用下的所有组件 try: install_info = market_app_service.install_service_when_upgrade_app( team, region_name, user, app_id, new_app, old_app, services, True, exist_component.tenant_service_group_id, pc.install_from_cloud, pc.market_name) except ResourceNotEnoughException as re: raise re except AccountOverdueException as re: logger.exception(re) raise ServiceHandleException(msg="resource is not enough", msg_show=re.message, status_code=412, error_code=10406) upgrade_service.create_add_service_record( app_record, install_info['events'], add_info) app_record.version = app_model_version app_record.old_version = pc.current_version app_record.save() # 处理升级组件 upgrade_services = service_repo.get_services_by_service_ids_and_group_key( app_model_id, list(upgrade_info.keys())) market_services = [ self.market_service_and_create_backup(team, service, app_record.version, upgrade_services) for service in upgrade_services ] # 处理依赖关系 if add_info: market_app_service.save_service_deps_when_upgrade_app( team, install_info['service_key_dep_key_map'], install_info['key_service_map'], install_info['apps'], install_info['app_map'], ) upgrade_service.upgrade_database(market_services) upgrade_service.send_upgrade_request(market_services, team, user, app_record, upgrade_info, oauth_instance) upgrade_repo.change_app_record_status( app_record, UpgradeStatus.UPGRADING.value)
def post(self, request, group_id, *args, **kwargs): """提交升级任务""" rq_args = ( { 'key': 'upgrade_record_id', 'required': True, 'error': 'upgrade_record_id is a required parameter' }, { 'key': 'group_key', 'required': True, 'error': 'group_key is a required parameter' }, { 'key': 'version', 'required': True, 'error': 'version is a required parameter' }, { 'key': 'services', 'required': True, 'error': 'services is a required parameter' }, ) data = parse_date(request, rq_args) app_record = get_object_or_404( AppUpgradeRecord, msg="Upgrade record not found", tenant_id=self.tenant.tenant_id, group_id=int(group_id), group_key=data['group_key'], status=UpgradeStatus.NOT.value, pk=data['upgrade_record_id'], ) app_record.version = data['version'] app_record.save() # 处理新增的服务 add_service_infos = [ service['upgrade_info'] for service in data['services'] if service['service']['type'] == UpgradeType.ADD.value ] if add_service_infos: app = rainbond_app_repo.get_rainbond_app_by_key_version( group_key=data['group_key'], version=app_record.version) # mock app信息 template = json.loads(app.app_template) template['apps'] = add_service_infos app.app_template = json.dumps(template) market_app_service.check_package_app_resource( self.tenant, self.response_region, app) market_app_service.install_service(self.tenant, self.response_region, self.user, group_id, app, True) # 处理需要升级的服务 upgrade_service_infos = { service['service']['service_id']: service['upgrade_info'] for service in data['services'] if service['service']['type'] == UpgradeType.UPGRADE.value } services = service_repo.get_services_by_service_ids_and_group_key( data['group_key'], upgrade_service_infos.keys()) market_services = [ upgrade_service.market_service_and_create_backup( self.tenant, service, app_record.version) for service in services ] upgrade_service.upgrade_database(market_services) upgrade_service.send_upgrade_request(market_services, self.tenant, self.user, app_record, upgrade_service_infos) upgrade_repo.change_app_record_status(app_record, UpgradeStatus.UPGRADING.value) return MessageResponse( msg="success", bean=upgrade_service.serialized_upgrade_record(app_record))
def post(self, request, group_id, *args, **kwargs): """提交升级任务""" rq_args = ( { 'key': 'upgrade_record_id', 'required': True, 'error': 'upgrade_record_id is a required parameter' }, { 'key': 'group_key', 'required': True, 'error': 'group_key is a required parameter' }, { 'key': 'version', 'required': True, 'error': 'version is a required parameter' }, { 'key': 'services', 'required': True, 'error': 'services is a required parameter' }, ) data = parse_date(request, rq_args) group_key = data['group_key'] version = data['version'] app_record = get_object_or_404( AppUpgradeRecord, msg="Upgrade record not found", tenant_id=self.tenant.tenant_id, group_id=int(group_id), group_key=group_key, status=UpgradeStatus.NOT.value, pk=data['upgrade_record_id'], ) old_services = group_service.get_rainbond_services(group_id, group_key) pc = PropertiesChanges(old_services.first(), self.tenant, all_component_one_model=old_services) if pc.install_from_cloud: old_app_model, old_app = app_market_service.cloud_app_model_to_db_model( pc.market, group_key, version) else: old_app_model, old_app = rainbond_app_repo.get_rainbond_app_and_version( self.tenant.enterprise_id, group_key, version) if not old_app_model: raise ServiceHandleException(msg="app is not exist", msg_show="应用市场应用不存在,无法进行升级") if not old_app: raise ServiceHandleException(msg="app version is not exist", msg_show="应用市场应用版本不存在,无法进行升级") old_app.template = old_app.app_template old_app.app_name = old_app_model.app_name new_app = deepcopy(old_app) template = json.loads(new_app.template) # 处理新增的组件 add_service_infos = { service['service']['service_key']: service['upgrade_info'] for service in data['services'] if service['service']['type'] == UpgradeType.ADD.value and service['upgrade_info'] } # 安装插件 plugins = template.get("plugins", None) if plugins: market_app_service.create_plugin_for_tenant( self.response_region, self.user, self.tenant, plugins) else: logger.debug(plugins) install_info = {} if add_service_infos: # mock app信息 template['apps'] = list(add_service_infos.values()) new_app.template = json.dumps(template) # 查询某一个云市应用下的所有组件 services = group_service.get_rainbond_services( int(group_id), group_key) try: install_info = market_app_service.install_service_when_upgrade_app( self.tenant, self.response_region, self.user, group_id, new_app, old_app, services, True, pc.install_from_cloud, pc.market_name) except ResourceNotEnoughException as re: raise re except AccountOverdueException as re: logger.exception(re) return MessageResponse(msg="resource is not enough", msg_show=re.message, status_code=412, error_code=10406) upgrade_service.create_add_service_record(app_record, install_info['events'], add_service_infos) # 处理需要升级的组件 upgrade_service_infos = { service['service']['service_id']: service['upgrade_info'] for service in data['services'] if service['service']['type'] == UpgradeType.UPGRADE.value and service['upgrade_info'] } # 升级应用配置组 market_app_service.save_app_config_groups_when_upgrade_app( self.region_name, self.tenant, group_id, upgrade_service_infos) app_record.version = version app_record.old_version = pc.current_version app_record.save() services = service_repo.get_services_by_service_ids_and_group_key( data['group_key'], list(upgrade_service_infos.keys())) market_services = [ upgrade_service.market_service_and_create_backup( self.tenant, service, app_record.version, all_component_one_model=services) for service in services ] # 处理依赖关系 if add_service_infos: market_app_service.save_service_deps_when_upgrade_app( self.tenant, install_info['service_key_dep_key_map'], install_info['key_service_map'], install_info['apps'], install_info['app_map'], ) upgrade_service.upgrade_database(market_services) upgrade_service.send_upgrade_request(market_services, self.tenant, self.user, app_record, upgrade_service_infos, self.oauth_instance) upgrade_repo.change_app_record_status(app_record, UpgradeStatus.UPGRADING.value) return MessageResponse( msg="success", bean=upgrade_service.serialized_upgrade_record(app_record))