def test_restore_ports(): from console.services.app_actions.app_restore import AppRestore tn = Tenants() tn.tenant_id = "c1a29fe4d7b0413993dc859430cf743d" svc = TenantServiceInfo() svc.service_id = "5a9209f3a3e94695b23fbd8b16a07d2b" backup_data = { "service_ports": [{ "lb_mapping_port": 0, "protocol": "http", "mapping_port": 80, "tenant_id": "c1a29fe4d7b0413993dc859430cf743d", "port_alias": "GR063B3980", "container_port": 80, "is_outer_service": False, "is_inner_service": False, "service_id": "5a9209f3a3e94695b23fbd8b16a07d2b", "ID": 513 }], } service_ports = backup_data["service_ports"] raw_ports = [port["port_alias"] for port in service_ports] app_restore = AppRestore(tn, svc) app_restore.ports(service_ports) ports = port_repo.get_service_ports(tn.tenant_id, svc.service_id) for port in ports: assert port.port_alias in raw_ports
def create_service(self, service_id, tenant_id, service_alias, service, creater, region, service_origin='assistant'): """创建console服务""" tenantServiceInfo = {} tenantServiceInfo["service_id"] = service_id tenantServiceInfo["tenant_id"] = tenant_id tenantServiceInfo["service_key"] = service.service_key tenantServiceInfo["service_alias"] = service_alias tenantServiceInfo["service_cname"] = service_alias tenantServiceInfo["service_region"] = region tenantServiceInfo["desc"] = service.desc tenantServiceInfo["category"] = service.category tenantServiceInfo["image"] = service.image tenantServiceInfo["cmd"] = service.cmd tenantServiceInfo["setting"] = service.setting tenantServiceInfo["extend_method"] = service.extend_method tenantServiceInfo["env"] = service.env tenantServiceInfo["min_node"] = service.min_node tenantServiceInfo["min_cpu"] = service.min_cpu tenantServiceInfo["min_memory"] = service.min_memory tenantServiceInfo["inner_port"] = service.inner_port tenantServiceInfo["version"] = service.version tenantServiceInfo["namespace"] = service.namespace tenantServiceInfo["update_version"] = service.update_version volume_path = "" host_path = "" if bool(service.volume_mount_path): volume_path = service.volume_mount_path host_path = "/grdata/tenant/" + tenant_id + "/service/" + service_id tenantServiceInfo["volume_mount_path"] = volume_path tenantServiceInfo["host_path"] = host_path if service.service_key == 'application': tenantServiceInfo["deploy_version"] = "" else: tenantServiceInfo["deploy_version"] = datetime.datetime.now( ).strftime('%Y%m%d%H%M%S') tenantServiceInfo["create_time"] = datetime.datetime.now().strftime( '%Y-%m-%d %H:%M:%S') tenantServiceInfo["git_project_id"] = 0 tenantServiceInfo["service_type"] = service.service_type tenantServiceInfo["creater"] = creater tenantServiceInfo[ "total_memory"] = service.min_node * service.min_memory tenantServiceInfo["service_origin"] = service_origin tenantServiceInfo["port_type"] = "multi_outer" # tenantServiceInfo["port_type"] = "one_outer" newTenantService = TenantServiceInfo(**tenantServiceInfo) newTenantService.save() return newTenantService
def test_list_by_svc_share_uuids(): tenant_id = "6d1c06e1d9e84d57aeb42ea80d49018a" service_id = "560ca84003254737a426d0bd5f513afd" service_cname = "WordPress" group_id = 20 service = TenantServiceInfo() service.tenant_id = tenant_id service.service_id = service_id service.service_cname = service_cname service.save() service_source = ServiceSourceInfo() service_source.team_id = tenant_id service_source.service_id = service_id service_source.service_share_uuid = "2669c2cec6bc7bf5aab29a0ea2703d66" service_source.save() group_relation = ServiceGroupRelation() group_relation.service_id = service_id group_relation.group_id = group_id group_relation.save() from console.repositories.app import service_repo result = service_repo.list_by_svc_share_uuids( group_id, ["2669c2cec6bc7bf5aab29a0ea2703d66"]) service = result[0] assert service.get("service_id") == service_id assert service.get("service_cname") == service_cname
def test_envs_changes(): from console.services.app_actions.properties_changes import PropertiesChanges from console.repositories.app_config import env_var_repo tenant_id = "c1a29fe4d7b0413993dc859430cf743d" service_id = "03289ae373e65e4a1a22046d7f76ca5e" tenantServiceEnvVar = {} tenantServiceEnvVar["tenant_id"] = tenant_id tenantServiceEnvVar["service_id"] = service_id tenantServiceEnvVar['container_port'] = 0 tenantServiceEnvVar["name"] = "NGINX_VERSION" tenantServiceEnvVar["attr_name"] = "NGINX_VERSION" tenantServiceEnvVar["attr_value"] = "1.15.12-1~stretch" tenantServiceEnvVar["is_change"] = False tenantServiceEnvVar["scope"] = "inner" env_var_repo.add_service_env(**tenantServiceEnvVar) envs = [ { "is_change": True, "name": "\u65e5\u5fd7\u8f93\u51fa\u65b9\u5f0f", "attr_value": "file", "attr_name": "DESTINATION" }, { "is_change": True, "name": "\u8be6\u7ec6\u9519\u8bef\u65e5\u5fd7", "attr_value": "true", "attr_name": "TRACEALLEXCEPTIONS" }, { "is_change": True, "name": "NGINX_VERSION", "attr_value": "1.15.12-1~stretch", "attr_name": "NGINX_VERSION" }, ] service = TenantServiceInfo() service.tenant_id = tenant_id service.service_id = service_id properties_changes = PropertiesChanges(service) env_changes = properties_changes.env_changes(envs) print env_changes assert 2 == len(env_changes["add"]) assert next( iter( filter(lambda x: x["attr_name"] == "DESTINATION", env_changes["add"])), None) assert next( iter( filter(lambda x: x["attr_name"] == "TRACEALLEXCEPTIONS", env_changes["add"])), None)
def test_record_not_found(mocker): with pytest.raises(RecordNotFound): from console.services.app_actions.properties_changes import PropertiesChanges service_source = ServiceSourceInfo() service_source.group_key = "dummy group_key" mocker.patch( "console.repositories.app.service_source_repo.get_service_source", return_value=service_source) properties_changes = PropertiesChanges(TenantServiceInfo()) properties_changes.get_property_changes("eid", "version")
def test_restore_env(): from console.services.app_actions.app_restore import AppRestore tn = Tenants() tn.tenant_id = "c1a29fe4d7b0413993dc859430cf743d" svc = TenantServiceInfo() svc.service_id = "36966cedcad44358a12f1707dece18da" backup_data = { "service_env_vars": [{ "name": "PHPIZE_DEPS", "tenant_id": "c1a29fe4d7b0413993dc859430cf743d", "attr_name": "PHPIZE_DEPS", "container_port": 0, "create_time": "2019-05-14 18:04:26", "attr_value": "autoconf", "is_change": True, "scope": "inner", "service_id": "36966cedcad44358a12f1707dece18da", "ID": 1080 }, { "name": "PHP_EXTRA_CONFIGURE_ARGS", "tenant_id": "c1a29fe4d7b0413993dc859430cf743d", "attr_name": "PHP_EXTRA_CONFIGURE_ARGS", "container_port": 0, "create_time": "2019-05-14 18:04:26", "attr_value": "--with-apxs2 --disable-cgi", "is_change": True, "scope": "inner", "service_id": "36966cedcad44358a12f1707dece18da", "ID": 1081 }] } service_env_vars = backup_data["service_env_vars"] raw_envs = [env["name"] for env in service_env_vars] app_restore = AppRestore(tn, svc) service_env_vars = service_env_vars app_restore.envs(service_env_vars) envs = env_var_repo.get_service_env(tn.tenant_id, svc.service_id) for env in envs: assert env.name in raw_envs
def test_rbd_app_not_found(mocker): from console.services.app_actions.properties_changes import PropertiesChanges with open("{}/tests/console/svcupgrade/app_template.json".format(settings.BASE_DIR)) as json_file: app_template = json.load(json_file) rain_app = RainbondCenterApp() rain_app.app_template = json.dumps(app_template) mocker.patch("console.repositories.market_app_repo.rainbond_app_repo.get_enterpirse_app_by_key_and_version", return_value=rain_app) service_source = ServiceSourceInfo() service_source.group_key = "dummy group_key" mocker.patch("console.repositories.app.service_source_repo.get_service_source", return_value=service_source) with pytest.raises(RbdAppNotFound): properties_changes = PropertiesChanges(TenantServiceInfo(), Tenants()) properties_changes.get_property_changes("eid", "version")
def __init_third_party_app(self, region, end_point): """ 初始化创建外置服务的默认数据,未存入数据库 """ tenant_service = TenantServiceInfo() tenant_service.service_region = region tenant_service.service_key = "application" tenant_service.desc = "third party service" tenant_service.category = "application" tenant_service.image = "third_party" tenant_service.cmd = "" tenant_service.setting = "" tenant_service.extend_method = "stateless" tenant_service.env = "" tenant_service.min_node = len(end_point) tenant_service.min_memory = 0 tenant_service.min_cpu = 0 tenant_service.version = "81701" tenant_service.namespace = "third_party" tenant_service.update_version = 1 tenant_service.port_type = "multi_outer" tenant_service.create_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') tenant_service.deploy_version = "" tenant_service.git_project_id = 0 tenant_service.service_type = "application" tenant_service.total_memory = 0 tenant_service.volume_mount_path = "" tenant_service.host_path = "" tenant_service.service_source = AppConstants.THIRD_PARTY tenant_service.create_status = "creating" return tenant_service
def __init_market_app(self, tenant_id, region, user, app, tenant_service_group_id): """ 初始化应用市场创建的应用默认数据 """ is_slug = bool(app["image"].startswith('goodrain.me/runner') and app["language"] not in ("dockerfile", "docker")) tenant_service = TenantServiceInfo() tenant_service.tenant_id = tenant_id tenant_service.service_id = make_uuid() tenant_service.service_cname = app["service_cname"] tenant_service.service_alias = "gr" + tenant_service.service_id[-6:] tenant_service.creater = user.pk if is_slug: tenant_service.image = app["image"] else: tenant_service.image = app.get("share_image", app["image"]) tenant_service.service_region = region tenant_service.service_key = app["service_key"] tenant_service.desc = "market app " tenant_service.category = "app_publish" tenant_service.setting = "" tenant_service.extend_method = app["extend_method"] tenant_service.env = "," tenant_service.min_node = app["extend_method_map"]["min_node"] tenant_service.min_memory = app["extend_method_map"]["min_memory"] tenant_service.min_cpu = baseService.calculate_service_cpu( region, tenant_service.min_memory) tenant_service.inner_port = 0 tenant_service.version = app["version"] if is_slug: if app.get("service_slug", None): tenant_service.namespace = app["service_slug"]["namespace"] else: if app.get("service_image", None): tenant_service.namespace = app["service_image"]["namespace"] tenant_service.update_version = 1 tenant_service.port_type = "multi_outer" tenant_service.create_time = datetime.datetime.now().strftime( '%Y-%m-%d %H:%M:%S') tenant_service.deploy_version = "" tenant_service.git_project_id = 0 tenant_service.service_type = "application" tenant_service.total_memory = tenant_service.min_node * tenant_service.min_memory tenant_service.volume_mount_path = "" tenant_service.host_path = "/grdata/tenant/" + tenant_id + "/service/" + tenant_service.service_id tenant_service.code_from = "" tenant_service.language = "" tenant_service.service_source = AppConstants.MARKET tenant_service.create_status = "creating" tenant_service.tenant_service_group_id = tenant_service_group_id self.__init_service_source(tenant_service, app) # 存储并返回 tenant_service.save() return tenant_service
def __init_compose_service(self, tenant, user, service_cname, image, region): """ 初始化docker compose创建的应用默认数据 """ tenant_service = TenantServiceInfo() tenant_service.tenant_id = tenant.tenant_id tenant_service.service_id = make_uuid() tenant_service.service_cname = service_cname tenant_service.service_alias = "gr" + tenant_service.service_id[-6:] tenant_service.creater = user.pk tenant_service.image = image tenant_service.service_region = region tenant_service.service_key = "0000" tenant_service.desc = "docker compose application" tenant_service.category = "app_publish" tenant_service.setting = "" tenant_service.extend_method = "stateless" tenant_service.env = "," tenant_service.min_node = 1 tenant_service.min_memory = 128 tenant_service.min_cpu = baseService.calculate_service_cpu(region, 128) tenant_service.inner_port = 0 tenant_service.version = "latest" tenant_service.namespace = "goodrain" tenant_service.update_version = 1 tenant_service.port_type = "multi_outer" tenant_service.create_time = datetime.datetime.now().strftime( '%Y-%m-%d %H:%M:%S') tenant_service.deploy_version = "" tenant_service.git_project_id = 0 tenant_service.service_type = "application" tenant_service.total_memory = 128 tenant_service.volume_mount_path = "" tenant_service.host_path = "/grdata/tenant/" + tenant.tenant_id + "/service/" + tenant_service.service_id tenant_service.code_from = "image_manual" tenant_service.language = "docker-compose" tenant_service.service_source = AppConstants.DOCKER_COMPOSE tenant_service.create_status = "checked" return tenant_service
def preprocess(self, services): need_create_service = [] is_pass = True data = {} ts_list = [] for ts in services: service_key = ts.get("service_key") service_version = ts.get("service_version") service_name = ts.get("service_name") if not service_name: data["status"] = "failure" is_pass = False return need_create_service, is_pass, data service_model_list = ServiceInfo.objects.filter(service_key=service_key, version=service_version) if not service_model_list: data["status"] = "notexist" is_pass = False return need_create_service, is_pass, data service = service_model_list[0] temp_ts = TenantServiceInfo() temp_ts.min_memory = service.min_memory temp_ts.min_node = service.min_node ts_list.append(temp_ts) res = tenantUsedResource.predict_batch_services_memory(self.tenant, ts_list, self.response_region) if not res: data["status"] = "over_memory" data["tenant_type"] = self.tenant.pay_type is_pass = False return need_create_service, is_pass, data for s in services: service_key = s.get("service_key") service_version = s.get("service_version") service_name = s.get("service_name") if not service_name: data["status"] = "failure" is_pass = False return need_create_service, is_pass, data service_model_list = ServiceInfo.objects.filter(service_key=service_key, version=service_version) if not service_model_list: data["status"] = "notexist" is_pass = False return need_create_service, is_pass, data service = service_model_list[0] # calculate resource tempService = TenantServiceInfo() tempService.min_memory = service.min_memory tempService.service_region = self.response_region tempService.min_node = service.min_node diffMemory = service.min_memory * service.min_node rt_type, flag = tenantUsedResource.predict_next_memory(self.tenant, tempService, diffMemory, False) if not flag: if rt_type == "memory": data["status"] = "over_memory" data["tenant_type"] = self.tenant.pay_type else: data["status"] = "over_money" is_pass = False return need_create_service, is_pass, data ccpu = int(service.min_memory / 128) * 20 service.min_cpu = ccpu service.service_cname = service_name need_create_service.append(service) data["status"] = "success" return need_create_service, is_pass, data
def post(self, request, *args, **kwargs): tenant_id = self.tenant.tenant_id service_id = make_uuid(tenant_id) service_alias = "gr" + service_id[-6:] result = {} try: success = tenant_svc.init_for_region(self.response_region, self.tenantName, tenant_id, self.user) if not success: result["status"] = "failure" return JsonResponse(result, status=200) service_key = request.POST.get("service_key", None) if service_key is None: result["status"] = "notexist" return JsonResponse(result, status=200) app_version = request.POST.get("app_version", None) if app_version is None: result["status"] = "notexist" return JsonResponse(result, status=200) service_cname = request.POST.get("create_app_name", None) if service_cname is None: result["status"] = "empty" return JsonResponse(result, status=200) service = None if app_version: try: service = ServiceInfo.objects.get(service_key=service_key, version=app_version) except ServiceInfo.DoesNotExist: pass else: service_list = ServiceInfo.objects.filter( service_key=service_key) if len(service_list) > 0: service = list(service_list)[0] app_version = service.version if service is None: result["status"] = "notexist" return JsonResponse(result, status=200) # calculate resource min_cpu = baseService.calculate_service_cpu( self.response_region, service.min_memory) service.min_cpu = min_cpu tempService = TenantServiceInfo() tempService.min_memory = service.min_memory tempService.service_region = self.response_region tempService.min_node = service.min_node diffMemory = service.min_node * service.min_memory rt_type, flag = tenantUsedResource.predict_next_memory( self.tenant, tempService, diffMemory, False) if not flag: if rt_type == "memory": result["status"] = "over_memory" result["tenant_type"] = self.tenant.pay_type else: result["status"] = "over_money" return JsonResponse(result, status=200) pre_paid_period = int(request.POST.get("pre_paid_period", 0)) disk = int(request.POST.get("disk_num", 0)) * 1024 # create console service newTenantService = baseService.create_service( service_id, tenant_id, service_alias, service_cname, service, self.user.pk, region=self.response_region) sai = attach_info_mamage.create_service_attach_info( newTenantService, newTenantService.min_memory * newTenantService.min_node, 0) create_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') # 创建预付费订单 if sai.pre_paid_money > 0: ServiceFeeBill.objects.create( tenant_id=tenant_id, service_id=service_id, prepaid_money=sai.pre_paid_money, pay_status="unpayed", cost_type="first_create", node_memory=newTenantService.min_memory, node_num=newTenantService.min_node, disk=disk, buy_period=pre_paid_period * 24 * 30, create_time=create_time, pay_time=create_time) group_id = request.POST.get("select_group_id", "") # 创建关系 if group_id != "": group_id = int(group_id) if group_id > 0: ServiceGroupRelation.objects.create( service_id=service_id, group_id=group_id, tenant_id=self.tenant.tenant_id, region_name=self.response_region) monitorhook.serviceMonitor(self.user.nick_name, newTenantService, 'create_service', True) result["status"] = "success" result["service_id"] = service_id result["service_alias"] = service_alias # 添加安装步骤记录 ServiceCreateStep.objects.create(tenant_id=tenant_id, service_id=service_id, app_step=11) except Exception as e: logger.exception(e) # tempTenantService = TenantServiceInfo.objects.filter(service_id=service_id)[0] TenantServiceInfo.objects.filter(service_id=service_id).delete() TenantServiceAuth.objects.filter(service_id=service_id).delete() TenantServiceRelation.objects.filter( service_id=service_id).delete() ServiceGroupRelation.objects.filter(service_id=service_id).delete() ServiceAttachInfo.objects.filter(service_id=service_id).delete() # monitorhook.serviceMonitor(self.user.nick_name, tempTenantService, 'create_service_error', False) result["status"] = "failure" return JsonResponse(result, status=200)
def post(self, request, *args, **kwargs): service_alias = "" service_code_from = "" tenant_id = self.tenant.tenant_id service_id = make_uuid(tenant_id) data = {} try: success = tenant_svc.init_for_region(self.response_region, self.tenantName, tenant_id, self.user) if not success: data["status"] = "failure" return JsonResponse(data, status=200) service_desc = "" service_cname = request.POST.get("create_app_name", "") service_code_from = request.POST.get("service_code_from", "") if service_code_from is None or service_code_from == "": data["status"] = "code_from" return JsonResponse(data, status=200) service_cname = service_cname.rstrip().lstrip() if service_cname is None or service_cname == "": data["status"] = "empty" return JsonResponse(data, status=200) # get base service service = ServiceInfo.objects.get(service_key="application") # 根据页面参数获取节点数和每个节点的内存大小 # min_memory = int(request.POST.get("service_min_memory", 128)) # # 将G转换为M # if min_memory < 128: # min_memory *= 1024 # min_node = int(request.POST.get("service_min_node", 1)) # service.min_memory = min_memory # service.min_node = min_node service.min_cpu = baseService.calculate_service_cpu( self.response_region, service.min_memory) service_alias = "gr" + service_id[-6:] # calculate resource tempService = TenantServiceInfo() tempService.min_memory = service.min_memory tempService.service_region = self.response_region tempService.min_node = service.min_node tempService.service_alias = service_alias diffMemory = service.min_node * service.min_memory rt_type, flag = tenantUsedResource.predict_next_memory( self.tenant, tempService, diffMemory, False) if not flag: if rt_type == "memory": data["status"] = "over_memory" data["tenant_type"] = self.tenant.pay_type else: data["status"] = "over_money" return JsonResponse(data, status=200) # save service attach info pre_paid_period = int(request.POST.get("pre_paid_period", 0)) disk = int(request.POST.get("disk_num", 0)) * 1024 create_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') # create console service service.desc = service_desc newTenantService = baseService.create_service( service_id, tenant_id, service_alias, service_cname, service, self.user.pk, region=self.response_region) monitorhook.serviceMonitor(self.user.nick_name, newTenantService, 'create_service', True) baseService.addServicePort(newTenantService, False, container_port=5000, protocol='http', port_alias=service_alias.upper() + str(5000), is_inner_service=False, is_outer_service=True) sai = attach_info_mamage.create_service_attach_info( newTenantService, newTenantService.min_memory * newTenantService.min_node, disk) if sai.pre_paid_money > 0: ServiceFeeBill.objects.create(tenant_id=tenant_id, service_id=service_id, prepaid_money=sai.pre_paid_money, pay_status="unpayed", cost_type="first_create", node_memory=service.min_memory, node_num=service.min_node, disk=disk, buy_period=pre_paid_period * 24 * 30, create_time=create_time, pay_time=create_time) # code repos # 自建git (gitlab_self)与gitlab_manual一样 if service_code_from == "gitlab_self": service_code_from = "gitlab_manual" if service_code_from == "gitlab_new": codeRepositoriesService.initRepositories( self.tenant, self.user, newTenantService, service_code_from, "", "", "") elif service_code_from == "gitlab_exit": code_clone_url = request.POST.get("service_code_clone_url", "") code_id = request.POST.get("service_code_id", "") code_version = request.POST.get("service_code_version", "master") if code_id == "" or code_clone_url == "" or code_version == "": data["status"] = "code_repos" TenantServiceInfo.objects.get( service_id=service_id).delete() return JsonResponse(data, status=200) codeRepositoriesService.initRepositories( self.tenant, self.user, newTenantService, service_code_from, code_clone_url, code_id, code_version) elif service_code_from == "gitlab_manual": code_clone_url = request.POST.get("service_code_clone_url", "") code_version = request.POST.get("service_code_version", "master") code_id = 0 if code_clone_url == "" or code_version == "": data["status"] = "code_repos" TenantServiceInfo.objects.get( service_id=service_id).delete() return JsonResponse(data, status=200) codeRepositoriesService.initRepositories( self.tenant, self.user, newTenantService, service_code_from, code_clone_url, code_id, code_version) elif service_code_from == "github": code_id = request.POST.get("service_code_id", "") code_clone_url = request.POST.get("service_code_clone_url", "") code_version = request.POST.get("service_code_version", "master") if code_id == "" or code_clone_url == "" or code_version == "": data["status"] = "code_repos" TenantServiceInfo.objects.get( service_id=service_id).delete() return JsonResponse(data, status=200) codeRepositoriesService.initRepositories( self.tenant, self.user, newTenantService, service_code_from, code_clone_url, code_id, code_version) group_id = request.POST.get("select_group_id", "") # 创建关系 if group_id != "": group_id = int(group_id) if group_id > 0: ServiceGroupRelation.objects.create( service_id=service_id, group_id=group_id, tenant_id=self.tenant.tenant_id, region_name=self.response_region) monitorhook.serviceMonitor(self.user.nick_name, newTenantService, 'init_region_service', True) data["status"] = "success" data["service_alias"] = service_alias data["service_id"] = service_id except Exception as e: logger.exception("create console service failed!") logger.exception(e) tempTenantService = TenantServiceInfo.objects.get( service_id=service_id) codeRepositoriesService.deleteProject(tempTenantService) TenantServiceInfo.objects.filter(service_id=service_id).delete() TenantServiceAuth.objects.filter(service_id=service_id).delete() TenantServiceRelation.objects.filter( service_id=service_id).delete() ServiceGroupRelation.objects.filter(service_id=service_id) ServiceAttachInfo.objects.filter(service_id=service_id) monitorhook.serviceMonitor(self.user.nick_name, tempTenantService, 'create_service_error', False) data["status"] = "failure" return JsonResponse(data, status=200)
def post(self, request, *args, **kwargs): result = {} tenant_id = self.tenant.tenant_id compose_file_id = request.POST.get("compose_file_id", "") group_id = request.POST.get("group_id", "") try: # judge region tenant is init success = tenant_svc.init_for_region(self.response_region, self.tenantName, tenant_id, self.user) if not success: result["status"] = "failure" return JsonResponse(result, status=200) # if tenantAccountService.isOwnedMoney(self.tenant, self.response_region): # result["status"] = "owed" # return JsonResponse(result, status=200) if group_id == "": result["status"] = "no_group" return JsonResponse(result, status=200) services_attach_infos = request.POST.get("services_attach_infos", "") services_attach_infos = self.json_loads(services_attach_infos) deps = {} services_list = [] for service_attach_info in services_attach_infos: service_cname = service_attach_info.get("app_name") service_id = service_attach_info.get("service_id") deps[service_cname] = service_id ts = TenantServiceInfo() min_memory = int( service_attach_info.get("service_min_memory", 128)) # 将G转换为M if min_memory < 128: min_memory *= 1024 min_node = int(service_attach_info.get("service_min_node", 1)) ts.min_memory = min_memory ts.min_node = min_node services_list.append(ts) res = tenantUsedResource.predict_batch_services_memory( self.tenant, services_list, self.response_region) if not res: result["status"] = "over_memory" result["tenant_type"] = self.tenant.pay_type return JsonResponse(result, status=200) for service_attach_info in services_attach_infos: service_cname = service_attach_info.get("app_name", "") if service_cname == "": result["status"] = "empty" return JsonResponse(result, status=200) min_memory = int( service_attach_info.get("service_min_memory", 128)) # 将G转换为M if min_memory < 128: min_memory *= 1024 min_node = int(service_attach_info.get("service_min_node", 1)) # calculate resource tempService = TenantServiceInfo() tempService.min_memory = min_memory tempService.service_region = self.response_region tempService.min_node = int(min_node) diffMemory = min_memory # 判断是否超出资源 rt_type, flag = tenantUsedResource.predict_next_memory( self.tenant, tempService, diffMemory, False) if not flag: if rt_type == "memory": result["status"] = "over_memory" result["tenant_type"] = self.tenant.pay_type else: result["status"] = "over_money" return JsonResponse(result, status=200) service_id = service_attach_info.get("service_id", None) if service_id is None: result["status"] = "no_service" return JsonResponse(result, status=200) service_alias = "gr" + service_id[-6:] service_image = service_attach_info.get("service_image") version = "" if ":" in service_image: index = service_image.index(":") version = service_image[index + 1:] else: version = "latest" service = ServiceInfo() service.service_key = "0000" service.desc = "" service.category = "app_publish" service.image = service_image service.cmd = "" service.setting = "" service.extend_method = "stateless" service.env = "," service.min_node = min_node cm = min_memory if min_memory != "": cm = int(min_memory) service.min_memory = cm service.min_cpu = baseService.calculate_service_cpu( self.response_region, cm) service.inner_port = 0 service.volume_mount_path = "" service.version = version service.namespace = "goodrain" service.update_version = 1 service.volume_mount_path = "" service.service_type = "application" # service host_path service.host_path = "/grdata/tenant/" + self.tenant.tenant_id + "/service/" + service_id # 创建服务 newTenantService = baseService.create_service( service_id, tenant_id, service_alias, service_cname, service, self.user.pk, region=self.response_region) newTenantService.code_from = "image_manual" newTenantService.language = "docker-compose" newTenantService.save() sai = attach_info_mamage.create_service_attach_info( newTenantService, newTenantService.min_memory * newTenantService.min_node, 0) monitorhook.serviceMonitor(self.user.nick_name, newTenantService, 'create_service', True) ServiceGroupRelation.objects.create( service_id=service_id, group_id=int(group_id), tenant_id=tenant_id, region_name=self.response_region) result[service_id] = { "service_id": service_id, "service_cname": service_cname, "service_alias": service_alias } result["status"] = "success" result["group_id"] = group_id result["compose_file_id"] = compose_file_id except Exception as e: ServiceGroupRelation.objects.filter( group_id=int(group_id)).delete() logger.exception(e) return JsonResponse(result, status=200)
def __init_docker_image_app(self, region): """ 初始化docker image创建的应用默认数据,未存入数据库 """ tenant_service = TenantServiceInfo() tenant_service.service_region = region tenant_service.service_key = "0000" tenant_service.desc = "docker run application" tenant_service.category = "app_publish" # tenant_service.image = "goodrain.me/runner" # tenant_service.cmd = "start web" tenant_service.setting = "" tenant_service.extend_method = "stateless" tenant_service.env = "," tenant_service.min_node = 1 tenant_service.min_memory = 128 tenant_service.min_cpu = baseService.calculate_service_cpu(region, 128) tenant_service.inner_port = 0 tenant_service.version = "latest" tenant_service.namespace = "goodrain" tenant_service.update_version = 1 tenant_service.port_type = "multi_outer" tenant_service.create_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') tenant_service.deploy_version = "" tenant_service.git_project_id = 0 tenant_service.service_type = "application" tenant_service.total_memory = 128 tenant_service.volume_mount_path = "" tenant_service.host_path = "" tenant_service.code_from = "image_manual" tenant_service.language = "docker-image" tenant_service.create_status = "creating" return tenant_service
def __init_source_code_app(self, region): """ 初始化源码创建的应用默认数据,未存入数据库 """ tenant_service = TenantServiceInfo() tenant_service.service_region = region tenant_service.service_key = "application" tenant_service.desc = "application info" tenant_service.category = "application" tenant_service.image = "goodrain.me/runner" tenant_service.cmd = "" tenant_service.setting = "" tenant_service.extend_method = "stateless" tenant_service.env = "" tenant_service.min_node = 1 tenant_service.min_memory = 128 tenant_service.min_cpu = baseService.calculate_service_cpu(region, 128) tenant_service.inner_port = 5000 tenant_service.version = "81701" tenant_service.namespace = "goodrain" tenant_service.update_version = 1 tenant_service.port_type = "multi_outer" tenant_service.create_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') tenant_service.deploy_version = "" tenant_service.git_project_id = 0 tenant_service.service_type = "application" tenant_service.total_memory = 128 tenant_service.volume_mount_path = "" tenant_service.host_path = "" tenant_service.service_source = AppConstants.SOURCE_CODE tenant_service.create_status = "creating" return tenant_service
def post(self, request, service_name, *args, **kwargs): """ 创建云市服务接口 --- parameters: - name: service_name description: 服务名称 required: true type: string paramType: path - name: tenant_name description: 租户名称 required: true type: string paramType: form - name: region description: 数据中心 required: true type: string paramType: form - name: service_key description: 镜像key required: true type: string paramType: form - name: version description: 镜像version required: true type: string paramType: form - name: user_id description: 创建人id required: true type: int paramType: form - name: username description: 创建人姓名 required: true type: string paramType: form - name: service_memory description: 服务的内存大小 required: false type: int paramType: form - name: service_node description: 节点个数 required: false type: int paramType: form - name: dep_info description: 套餐依赖服务的设置(json) required: false type: string paramType: form - name: env_list description: 服务的环境参数 required: false type: array paramType: form - name: limit description: 是否检查资源限制 required: false type: bool paramType: form """ logger.debug("openapi.cloudservice", request.data) tenant_name = request.data.get("tenant_name", None) if tenant_name is None: return Response(status=405, data={"success": False, "msg": u"租户名称为空"}) # 数据中心 region = request.data.get("region", None) if region is None: return Response(status=406, data={"success": False, "msg": u"数据中心名称为空"}) # 根据service_key, version创建服务 service_key = request.data.get("service_key", None) if service_key is None: return Response(status=408, data={"success": False, "msg": u"镜像key为空!"}) # 服务描述 version = request.data.get("version", None) if version is None: return Response(status=409, data={"success": False, "msg": u"镜像version为空!"}) # 非必填字段 user_id = request.data.get("user_id", "1") username = request.data.get("username", "system") service_memory = request.data.get("service_memory", "") service_node = request.data.get("service_node", 1) dep_info = request.data.get("dep_info", "[]") dep_info_json = json.loads(dep_info) dep_service_info = {"{0}-{1}".format(x.get("service_key"), x.get("app_version")): x for x in dep_info_json} logger.debug("openapi.cloudservice", "now create service: service_name:{0}, tenant_name:{1}, region:{2}, key:{3}, version:{4}".format(service_name, tenant_name, region, service_key, version)) r = re.compile("^[a-z][a-z0-9-]*[a-z0-9]$") if not r.match(service_name): return Response(status=412, data={"success": False, "msg": u"服务名称不合法!"}) # 根据租户名称获取租户信息 try: tenant = Tenants.objects.get(tenant_name=tenant_name) except Tenants.DoesNotExist: logger.error("openapi.cloudservice", "Tenant {0} is not exists".format(tenant_name)) return Response(status=413, data={"success": False, "msg": u"查询不到租户"}) # 检查租户是否欠费 # if tenantAccountService.isOwnedMoney(tenant, region): # 检查服务名称是否存在 num = TenantServiceInfo.objects.filter(tenant_id=tenant.tenant_id, service_alias=service_name).count() if num > 0: logger.error("openapi.cloudservice", "Tenant {0} region {1} service:{2} is exists=!".format(tenant_name, region, service_name)) return Response(status=414, data={"success": False, "msg": u"服务名称已经存在"}) # 检查对应region上的tenant是否创建 init_region_tenant = manager.init_region_tenant(region, tenant_name, tenant.tenant_id, username) if not init_region_tenant: logger.error("openapi.cloudservice", "Tenant {0} region {1} init failed!".format(tenant_name, region)) return Response(status=470, data={"success": False, "msg": u"init region tenant failed!"}) # 没有模版从app下载模版\根据模版查询服务依赖信息 status, success, dep_map, msg = manager.download_service(service_key, version) if status == 500: logger.error("openapi.cloudservice", msg) return Response(status=status, data={"success": success, "msg": msg}) # relation_list 从后向前安装服务 dep_required_memory = 0 dep_service_list = None if len(dep_map) > 0: dep_query = Q() for tmp_key, tmp_version in dep_map.items(): dep_query = dep_query | (Q(service_key=tmp_key) & Q(version=tmp_version)) dep_service_list = ServiceInfo.objects.filter(dep_query) if len(dep_service_list) > 0: # 计算依赖服务需要的资源 for dep_service_tmp in list(dep_service_list): tmp_key = "{0}-{1}".format(dep_service_tmp.service_key, dep_service_tmp.version) dep_info = dep_service_info.get(tmp_key) if dep_info is not None: dep_required_memory += int(dep_info["memory"]) * int(dep_info["node"]) else: dep_required_memory += int(dep_service_tmp.min_memory) # dep_required_memory = reduce(lambda x, y: x + y, [s.min_memory for s in dep_service_list]) # 生成随机service_id service_id = crypt.make_uuid(tenant.tenant_id) # 查询服务模版 service = ServiceInfo.objects.get(service_key=service_key, version=version) service.desc = '' if service_memory != "": cm = int(service_memory) if cm >= 128: ccpu = int(cm / 128) * 20 service.min_cpu = ccpu service.min_memory = cm # 计算服务资源 tenant_service_info = TenantServiceInfo() tenant_service_info.min_memory = service.min_memory tenant_service_info.service_region = region tenant_service_info.min_node = service.min_node if int(service_node) > 1: tenant_service_info.min_node = int(service_node) diffMemory = dep_required_memory + service.min_node * service.min_memory # 是否检查资源限制 limit = request.data.get("limit", True) if limit: rt_type, flag = manager.predict_next_memory(tenant, tenant_service_info, diffMemory, False) if not flag: if rt_type == "memory": logger.error("openapi.cloudservice", "Tenant {0} region {1} service:{2} memory!".format(tenant_name, region, service_name)) return Response(status=416, data={"success": False, "msg": u"内存已经到最大值"}) else: logger.error("openapi.cloudservice", "Tenant {0} region {1} service:{2} memory!".format(tenant_name, region, service_name)) return Response(status=417, data={"success": False, "msg": u"资源已经到最大值"}) logger.debug("openapi.cloudservice", "now install dep service and service,memory:{0}".format(diffMemory)) # 创建依赖的服务 dep_sids = [] tenant_service_list = [] if dep_service_list is not None: # 服务从后向前安装 dep_service_list.reverse() for dep_service in dep_service_list: dep_service_id = crypt.make_uuid(dep_service.service_key) logger.debug("openapi.cloudservice", "install dep service:{0}".format(dep_service_id)) try: depTenantService = manager.create_service(dep_service_id, tenant.tenant_id, dep_service.service_name.lower() + "_" + service_name, dep_service, user_id, region=region, service_origin='cloud') # 更新服务节点、内存 tmp_key = "{0}-{1}".format(dep_service_tmp.service_key, dep_service_tmp.version) dep_info = dep_service_info.get(tmp_key) if dep_info is not None: depTenantService.min_node = int(dep_info["node"]) depTenantService.min_memory = int(dep_info["memory"]) depTenantService.save() manager.add_service_extend(depTenantService, dep_service) monitorhook.serviceMonitor(username, depTenantService, 'create_service', True) tenant_service_list.append(depTenantService) dep_sids.append(dep_service_id) except Exception as e: logger.exception("openapi.cloudservice", e) TenantServiceInfo.objects.filter(service_id=service_id).delete() TenantServiceAuth.objects.filter(service_id=service_id).delete() TenantServiceEnvVar.objects.filter(service_id=service_id).delete() TenantServiceRelation.objects.filter(service_id=service_id).delete() TenantServiceVolume.objects.filter(service_id=service_id).delete() return Response(status=418, data={"success": False, "msg": u"创建控制台依赖服务失败!"}) logger.debug("openapi.cloudservice", "install dep service:{0} over".format(dep_service_id)) logger.debug("openapi.cloudservice", "install dep region service,region:{0}".format(region)) try: manager.create_region_service(depTenantService, tenant_name, region, username) monitorhook.serviceMonitor(username, depTenantService, 'init_region_service', True) except Exception as e: logger.error("openapi.cloudservice", "create region service failed!", e) return Response(status=419, data={"success": False, "msg": u"创建region服务失败!"}) logger.debug("openapi.cloudservice", "install dep region service,region:{0} over".format(region)) logger.debug("openapi.cloudservice", "install dep relation") # 依赖关系 todo 无法处理多层依赖关系, manager.create_service_dependency(tenant.tenant_id, service_id, dep_service_id, region) logger.debug("openapi.cloudservice", "install dep relation over") # 添加goodrain_web_api反馈 monitorhook.serviceMonitor(username, depTenantService, 'create_service', True, origin='goodrain_web_api') # create console service logger.debug("openapi.cloudservice", "install current service now") try: newTenantService = manager.create_service(service_id, tenant.tenant_id, service_name, service, user_id, region=region, service_origin='cloud') need_update = False if service_memory != "" and int(service_memory) > 128: newTenantService.min_memory = int(service_memory) need_update = True if int(service_node) > 1: newTenantService.min_node = int(service_node) need_update = True if need_update: newTenantService.save() if len(dep_service_list) > 0: self.saveAdapterEnv(newTenantService) manager.add_service_extend(newTenantService, service) monitorhook.serviceMonitor(username, newTenantService, 'create_service', True) except Exception as e: logger.error("openapi.cloudservice", "create console service failed!", e) TenantServiceInfo.objects.filter(service_id=service_id).delete() TenantServiceAuth.objects.filter(service_id=service_id).delete() TenantServiceEnvVar.objects.filter(service_id=service_id).delete() TenantServiceRelation.objects.filter(service_id=service_id).delete() TenantServiceVolume.objects.filter(service_id=service_id).delete() return Response(status=418, data={"success": False, "msg": u"创建控制台服务失败!"}) logger.debug("openapi.cloudservice", "install current service now success!") env_list = request.data.get("env_list", None) # query service port service_port_list = TenantServicesPort.objects.filter(service_id=newTenantService.service_id, is_outer_service=True, protocol='http') if env_list is not None: env_var_list = TenantServiceEnvVar.objects.filter(service_id=service_id, tenant_id=tenant.tenant_id, is_change=True) env_var_map = {x.attr_name: x for x in list(env_var_list)} for env_var in env_list: attr_name = env_var.get("attr_name") attr_value = env_var.get("attr_value") env = env_var_map.get(attr_name, None) if attr_name == "SITE_URL": port = RegionInfo.region_port(region) domain = RegionInfo.region_domain(region) if len(service_port_list) > 0: port_value = service_port_list[0].container_port attr_value = 'http://{}.{}.{}{}:{}'.format(port_value, service_name, tenant.tenant_name, domain, port) logger.debug("openapi.cloudservice", "SITE_URL = {}".format(env.attr_value)) elif attr_name == "TRUSTED_DOMAIN": port = RegionInfo.region_port(region) domain = RegionInfo.region_domain(region) if len(service_port_list) > 0: port_value = service_port_list[0].container_port attr_value = '{}.{}.{}{}:{}'.format(port_value, service_name, tenant.tenant_name, domain, port) logger.debug("openapi.cloudservice", "TRUSTED_DOMAIN = {}".format(env.attr_value)) if env is not None: env.attr_value = attr_value else: env = TenantServiceEnvVar( tenant_id=tenant.tenant_id, service_id=service_id, container_port=env_var.get("container_port"), name=env_var.get("name"), attr_name=attr_name, attr_value=attr_value, is_change=env_var.get("is_change"), scope=env_var.get("scope"), ) env.save() logger.debug("openapi.cloudservice", "install service env success!") # create region service logger.debug("openapi.cloudservice", "install region service {0}!".format(region)) try: manager.create_region_service(newTenantService, tenant_name, region, username, dep_sids=json.dumps(dep_sids)) monitorhook.serviceMonitor(username, newTenantService, 'init_region_service', True) except Exception as e: logger.error("openapi.cloudservice", "create region service failed!", e) return Response(status=419, data={"success": False, "msg": u"创建region服务失败!"}) logger.debug("openapi.cloudservice", "install region service {0} success!".format(region)) # 发送goodrain_web_api反馈 # 1、依赖信息 tmp_info = [] for dep_service in tenant_service_list: tmp_array = {"dep_id": dep_service.service_id, "dep_name": dep_service.service_alias} tmp_info.append(tmp_array) tmp_data = { "service_region": region, "deps": tmp_info } monitorhook.serviceMonitor(username, newTenantService, 'create_service', True, origin='goodrain_web_api', info=json.dumps(tmp_data)) wild_domain = "" if region in settings.WILD_DOMAINS.keys(): wild_domain = settings.WILD_DOMAINS[newTenantService.service_region] http_port_str = "" if region in settings.WILD_PORTS.keys(): http_port_str = settings.WILD_PORTS[region] http_port_str = ":" + http_port_str # 只有http服务返回url access_url = "" if len(service_port_list) > 0: port_value = service_port_list[0].container_port access_url = "http://{0}.{1}.{2}{3}{4}".format(port_value, newTenantService.service_alias, tenant_name, wild_domain, http_port_str) logger.debug("openapi.cloudservice", "service access url {0}".format(access_url)) json_data = {} json_data["cloud_assistant"] = sn.instance.cloud_assistant json_data["url"] = access_url json_data["service"] = newTenantService.to_dict() json_data["dep_service"] = map(lambda x: x.to_dict(), tenant_service_list) # 服务env+依赖服务env dep_service_ids = [x.service_id for x in tenant_service_list] if service_id not in dep_service_ids: dep_service_ids.append(service_id) env_var_list = TenantServiceEnvVar.objects.filter(service_id__in=dep_service_ids).exclude(attr_name="GD_ADAPTER") env_list = [] # 过滤掉不显示字段 for env_var in list(env_var_list): if env_var.name in ["GD_ADAPTER", "GR_PROXY"]: continue env_list.append(env_var) json_data["env_list"] = map(lambda x: x.to_dict(), env_list) # 服务port+依赖服务port # port_list = TenantServicesPort.objects.filter(service_id__in=dep_service_ids) # json_data["port_list"] = port_list # 服务volume+依赖服务 # TenantServiceVolume.objects.filter(service_id__in=dep_service_ids) # 依赖的环境变量 return Response(status=200, data={"success": True, "service": json_data})
def create_tenant_service(self, **kwargs): tenant_service = TenantServiceInfo(**kwargs) tenant_service.save() return tenant_service
def create(self, service_base): TenantServiceInfo(**service_base).save()