Ejemplo n.º 1
0
 def downloadImage(self, base_info):
     try:
         download_task = {}
         if base_info.is_slug():
             download_task = {
                 "action": "download_and_deploy",
                 "app_key": base_info.service_key,
                 "app_version": base_info.version,
                 "namespace": base_info.namespace,
                 "dep_sids": json.dumps([])
             }
             for region in RegionInfo.valid_regions():
                 logger.info(region)
                 # TODO v2 api修改
                 regionClient.send_task(region, 'app_slug',
                                        json.dumps(download_task))
         else:
             download_task = {
                 "action": "download_and_deploy",
                 "image": base_info.image,
                 "namespace": base_info.namespace,
                 "dep_sids": json.dumps([])
             }
             for region in RegionInfo.valid_regions():
                 # TODO v2 api修改
                 regionClient.send_task(region, 'app_image',
                                        json.dumps(download_task))
     except Exception as e:
         logger.exception(e)
Ejemplo n.º 2
0
    def __init__(self, *args, **kwargs):
        super(AdminForm, self).__init__(*args, **kwargs)
        self.helper = FormHelper(self)
        self.helper.form_tag = False
        # 获取region
        init_region = RegionInfo.register_choices()[0][0]

        self.helper.layout = Layout(
            Div(Field('enter_alias',
                      css_class="form-control",
                      placeholder=u"企业名称"),
                Field('nick_name',
                      css_class="form-control",
                      placeholder=u"用户名(英文)"),
                Field('email', css_class="form-control", placeholder=u"管理员邮箱"),
                Hidden('machine_region', value=init_region),
                Field('password',
                      css_class="form-control",
                      placeholder=u"请输入至少8位数密码"),
                Field('password_repeat',
                      css_class="form-control",
                      placeholder=u"请再输入一次密码"),
                HTML(
                    """<div class="form-group" style="text-align:left;"><a href="http://doc.goodrain.com/cloudbang-agreement/201656" target="_blank">《云帮企业版用户服务协议》</a></div>"""
                ),
                FormActions(
                    Submit('register',
                           u'同意协议,创建账号',
                           css_class='btn btn-lg btn-success btn-block')),
                css_class="login-wrap"))
        self.helper.form_id = 'form-normal-reg'
        self.helper.form_class = 'form-horizontal'
Ejemplo n.º 3
0
    def __init__(self, request, *args, **kwargs):
        self.tenantName = kwargs.get('tenantName', None)
        self.serviceAlias = kwargs.get('serviceAlias', None)

        if self.tenantName is not None:
            try:
                self.tenant = Tenants.objects.get(tenant_name=self.tenantName)
            except Tenants.DoesNotExist:
                logger.error("Tenant {0} is not exists".format(
                    self.tenantName))
                raise http.Http404

            if self.serviceAlias is not None:
                try:
                    self.service = TenantServiceInfo.objects.get(
                        tenant_id=self.tenant.tenant_id,
                        service_alias=self.serviceAlias)
                    if self.service.service_region not in RegionInfo.valid_regions(
                    ):
                        raise PermissionDenied
                except TenantServiceInfo.DoesNotExist:
                    logger.debug(
                        "Tenant {0} ServiceAlias {1} is not exists".format(
                            self.tenantName, self.serviceAlias))
                    raise http.Http404

        BaseView.__init__(self, request, *args, **kwargs)
Ejemplo n.º 4
0
    def validate(self, data):
        for k in ('source_region', 'dest_region'):
            v = data[k]
            if v not in RegionInfo.region_names():
                raise serializers.ValidationError(
                    "{0} filed value {1} is not in region_list".format(k, v))

        return data
Ejemplo n.º 5
0
 def set_direct_copy_options(self, envs, service_id, service_key, version):
     outer_ports = AppServicePort.objects.filter(service_key=service_key,
                                                 app_version=version,
                                                 is_outer_service=True,
                                                 protocol='http')
     service_alias = "gr" + service_id[-6:]
     for env in envs:
         if env.attr_name == 'SITE_URL' or env.attr_name == 'TRUSTED_DOMAIN':
             if self.cookie_region in RegionInfo.valid_regions():
                 env.options = 'direct_copy'
                 if len(outer_ports) > 0:
                     port = RegionInfo.region_port(self.response_region)
                     domain = RegionInfo.region_domain(self.response_region)
                     if env.attr_name == 'SITE_URL':
                         env.attr_value = 'http://{}.{}.{}{}:{}'.format(outer_ports[0].container_port, service_alias,
                                                                        self.tenantName, domain, port)
                     else:
                         env.attr_value = '{}.{}.{}{}:{}'.format(outer_ports[0].container_port, service_alias,
                                                                 self.tenantName, domain, port)
Ejemplo n.º 6
0
    def copy_envs(self, service_info, current_service):
        s = current_service
        baseService = BaseTenantService()
        envs = AppServiceEnv.objects.filter(service_key=service_info.service_key, app_version=service_info.version)
        outer_ports = AppServicePort.objects.filter(service_key=service_info.service_key,
                                                    app_version=service_info.version,
                                                    is_outer_service=True,
                                                    protocol='http')
        for env in envs:
            if env.attr_name == 'SITE_URL':
                if self.region_name in RegionInfo.valid_regions():
                    port = RegionInfo.region_port(self.region_name)
                    domain = RegionInfo.region_domain(self.region_name)
                    env.options="direct_copy"
                    if len(outer_ports)>0:
                        env.attr_value = 'http://{}.{}.{}{}:{}'.format(outer_ports[0].container_port, current_service.serviceAlias,self.tenant_name, domain, port)
                    logger.debug("SITE_URL = {} options = {}".format(env.attr_value, env.options))
            elif env.attr_name == "TRUSTED_DOMAIN":
                if self.region_name in RegionInfo.valid_regions():
                    port = RegionInfo.region_port(self.region_name)
                    domain = RegionInfo.region_domain(self.region_name)
                    env.options = 'direct_copy'
                    if len(outer_ports) > 0:
                        env.attr_value = '{}.{}.{}{}:{}'.format(outer_ports[0].container_port, current_service.serviceAlias, self.tenant_name, domain, port)
                    logger.debug("TRUSTED_DOMAIN = {} options = {}".format(env.attr_value, env.options))

            baseService.saveServiceEnvVar(s.tenant_id, s.service_id, env.container_port, env.name,
                                          env.attr_name, env.attr_value, env.is_change, env.scope)
Ejemplo n.º 7
0
    def set_region_info(self, context):
        arrival_regions = []
        for region in RegionInfo.regions():
            if region['name'] == self.response_region:
                context['current_region'] = region
            else:
                if region[
                        'name'] == 'aws-jp-1' and self.tenant.pay_level == 'free' and self.tenant.balance == 0:
                    continue
                arrival_regions.append(region)

        context['arrival_regions'] = tuple(arrival_regions)
        return context
Ejemplo n.º 8
0
 def calculate_real_used_resource(self, tenant):
     totalMemory = 0
     tenant_region_list = TenantRegionInfo.objects.filter(
         tenant_id=tenant.tenant_id, is_active=True, is_init=True)
     for tenant_region in tenant_region_list:
         logger.debug(tenant_region.region_name)
         if tenant_region.region_name in RegionInfo.valid_regions():
             res = region_api.get_tenant_resources(
                 tenant_region.region_name, tenant.tenant_name,
                 tenant.enterprise_id)
             bean = res["bean"]
             memory = int(bean["memory"])
             totalMemory += memory
     return totalMemory
Ejemplo n.º 9
0
    def check_region(self):
        region = self.request.GET.get('region', None)
        if region is not None:
            if region in RegionInfo.region_names():
                if region == 'aws-bj-1' and self.tenant.region != 'aws-bj-1':
                    raise Http404
                self.response_region = region
            else:
                raise Http404

        try:
            t_region, created = TenantRegionInfo.objects.get_or_create(
                tenant_id=self.tenant.tenant_id,
                region_name=self.response_region)
            self.tenant_region = t_region
        except Exception, e:
            logger.error(e)
Ejemplo n.º 10
0
    def __init__(self, *args, **kwargs):
        super(LeftSideBarMixin, self).__init__(*args, **kwargs)
        if hasattr(self, 'tenant') and hasattr(self, 'user'):
            pass
        else:
            raise ImportWarning(
                "LeftSideBarMixin should inherit before AuthedView")

        self.cookie_region = self.request.COOKIES.get('region', None)
        region_names = [region["name"] for region in RegionInfo.regions()]
        if self.cookie_region is None:
            if self.tenant.region in region_names:
                self.response_region = self.tenant.region
            else:
                self.response_region = region_names[0]
        else:
            self.response_region = self.cookie_region
        self.cookie_tenant_name = self.request.COOKIES.get('tenant_name', None)
        self.response_tenant_name = self.tenant.tenant_name if self.cookie_tenant_name is None else self.cookie_tenant_name
Ejemplo n.º 11
0
 def calculate_real_used_resource(self, tenant):
     totalMemory = 0
     totalDisk = 0
     tenant_region_list = TenantRegionInfo.objects.filter(
         tenant_id=tenant.tenant_id, is_active=True, is_init=True)
     for tenant_region in tenant_region_list:
         logger.debug(tenant_region.region_name)
         if tenant_region.region_name in RegionInfo.valid_regions():
             data = {"tenant_name": [tenant.tenant_name]}
             res = region_api.get_region_tenants_resources(
                 tenant_region.region_name, data, tenant.enterprise_id)
             d_list = res["list"]
             memory = 0
             disk = 0
             if d_list:
                 resource = d_list[0]
                 memory = int(resource["memory"])
                 disk = int(resource["disk"])
             totalMemory += memory
             totalDisk += disk
     return totalMemory, totalDisk
Ejemplo n.º 12
0
 def set_tenant_default_env(self, envs, outer_ports):
     for env in envs:
         if env.attr_name == 'SITE_URL':
             if self.cookie_region in RegionInfo.valid_regions():
                 port = RegionInfo.region_port(self.cookie_region)
                 domain = RegionInfo.region_domain(self.cookie_region)
                 env.options = 'direct_copy'
                 if len(outer_ports) > 0:
                     env.attr_value = 'http://{}.{}.{}{}:{}'.format(outer_ports[0].container_port, self.serviceAlias, self.tenantName, domain, port)
                 logger.debug("SITE_URL = {} options = {}".format(env.attr_value, env.options))
         elif env.attr_name == 'TRUSTED_DOMAIN':
             if self.cookie_region in RegionInfo.valid_regions():
                 port = RegionInfo.region_port(self.cookie_region)
                 domain = RegionInfo.region_domain(self.cookie_region)
                 env.options = 'direct_copy'
                 if len(outer_ports) > 0:
                     env.attr_value = '{}.{}.{}{}:{}'.format(outer_ports[0].container_port, self.serviceAlias, self.tenantName, domain, port)
                 logger.debug("TRUSTED_DOMAIN = {} options = {}".format(env.attr_value, env.options))
Ejemplo n.º 13
0
    def __init__(self, *args, **kwargs):
        init_phone = ""
        init_email = ""
        init_tenant = ""
        init_region = ""
        selected_region = ""
        next_url = None
        origin = None
        prefix_url = ""
        if len(kwargs) > 0:
            if kwargs.get("initial") is not None:
                initalObj = kwargs.get("initial")
                init_phone = initalObj["phone"]
                init_email = initalObj["email"]
                init_tenant = initalObj["tenant"]
                init_region = initalObj["region"]
            if kwargs.get("region_level") is not None:
                selected_region = kwargs["region_level"]["region"]
                kwargs.pop("region_level")
            if kwargs.get("next_url") is not None:
                next_url = kwargs["next_url"]
                prefix_url += "&next={0}".format(next_url)
                kwargs.pop("next_url")
            if kwargs.get("origin") is not None:
                origin = kwargs["origin"]
                prefix_url += "&origin={0}".format(origin)
                kwargs.pop("origin")
        if len(prefix_url) > 1:
            prefix_url = "?" + prefix_url[1:]
        if len(args) > 0:
            if type(args) is tuple:
                if args[0].get("initial") is not None:
                    initalObj = args[0]["initial"]
                    if type(initalObj) is list:
                        initalObj = initalObj(0)
                    init_phone = initalObj["phone"]
                    init_email = initalObj["email"]
                    init_tenant = initalObj["tenant"]
                    init_region = initalObj["region"]
        super(RegisterForm, self).__init__(*args, **kwargs)
        self.helper = FormHelper(self)
        self.helper.form_tag = False

        text_phone = "手机号"
        text_email = "请输入邮箱地址"
        text_tenant = "团队域名"
        if init_phone is not None and init_phone != "":
            self.fields['phone'].widget.attrs['readonly'] = True
            text_phone = init_phone
        if init_email is not None and init_email != "":
            self.fields['email'].widget.attrs['readonly'] = True
            text_email = init_email
        if init_tenant is not None and init_tenant != "":
            self.fields['tenant'].widget.attrs['readonly'] = True
            text_tenant = init_tenant
        if init_region is not None and init_region != "":
            self.fields['machine_region'].initial = init_region
            self.fields['machine_region'].widget.attrs['readonly'] = True
        if selected_region is not None and selected_region != "":
            self.fields['machine_region'].initial = selected_region

        init_region = RegionInfo.register_choices()[0][0]
        # 对于社区版注册表单进行处理
        is_private = sn.instance.is_private()
        tenant_name = None
        if is_private:
            tenant_num = Tenants.objects.count()
            if tenant_num == 1:
                tenant_list = Tenants.objects.all()
                tenant = tenant_list[0]
                tenant_name = tenant.tenant_name

        # if settings.MODULES["Sms_Check"]:
        if settings.MODULES["WeChat_Module"]:
            self.helper.layout = Layout(
                Div(
                    Field('tenant',
                          "",
                          placeholder='请输入团队名(可使用小写英文字母、数字、下划线及中划线)',
                          css_class="form-control") if tenant_name is None else
                    Field('tenant',
                          "",
                          placeholder='请输入团队名(可使用小写英文字母、数字、下划线及中划线)',
                          css_class="form-control",
                          readonly="readonly",
                          value=tenant_name),
                    Field('nick_name',
                          css_class="form-control",
                          placeholder='请输入用户名(可使用小写英文字母、数字、下划线及中划线)'),
                    Field('email',
                          css_class="form-control",
                          placeholder='请输入邮箱(选填)'),
                    HTML("<hr/>"),
                    # 默认为ali-sh
                    Hidden('machine_region', value=init_region),
                    Hidden('next', value=next_url),
                    Hidden('origin', value=origin),
                    Field('password',
                          css_class="form-control",
                          placeholder='请设置密码,至少包含8位字符'),
                    Field('password_repeat',
                          css_class="form-control",
                          placeholder='请再输入一次密码'),
                    Field('phone',
                          css_class="form-control",
                          placeholder='请输入手机号'),
                    AppendedText(
                        'captcha_code',
                        '<img id="captcha_code" src="/captcha" /> <a href="javascript:void(0)" onclick="refresh();">看不清,换一张</a>  ',
                        css_class='input-xlarge',
                        placeholder='图片验证码'),
                    AppendedText(
                        'phone_code',
                        '<a href="javascript:void(0)" id="PhoneCodeBtn" onclick="getPhoneCode();">点击发送验证码</a>  ',
                        css_class='input-xlarge',
                        placeholder='手机验证码'),
                    HTML(
                        """<div class="linkfw text-center">点击注册表示你已阅读并同意《<a href="http://www.goodrain.com/goodrainlaws.html" target="_blank">云帮服务条款</a>》</div>"""
                    ),
                    FormActions(
                        Submit('register',
                               u'注册',
                               css_class='btn btn-lg btn-success btn-block')),
                    HTML("""<p class="text-center">或使用以下账号注册</p>"""),
                    HTML(
                        """<a href="/wechat/login{0}" class="weixin"><img src="static/www/images/weixin.png">微信</a>"""
                        .format(prefix_url)),
                    HTML(
                        """<div class="linkregister text-center">直接<a href="/login{0}">登录</a></div>"""
                        .format(prefix_url)),
                    # HTML("""<a href="http://www.goodrain.com/" class="linkgood text-center">goodrain.com</a>"""),
                    css_class="login-wrap"))
        else:
            self.helper.layout = Layout(
                Div(
                    Field('tenant',
                          "",
                          placeholder='请输入团队名(可使用小写英文字母、数字、下划线及中划线)',
                          css_class="form-control") if tenant_name is None else
                    Field('tenant',
                          "",
                          placeholder='请输入团队名(可使用小写英文字母、数字、下划线及中划线)',
                          css_class="form-control",
                          readonly="readonly",
                          value=tenant_name),
                    Field('nick_name',
                          css_class="form-control",
                          placeholder='请输入用户名(可使用小写英文字母、数字、下划线及中划线)'),
                    Field('email',
                          css_class="form-control",
                          placeholder='请输入邮箱(选填)'),
                    HTML("<hr/>"),
                    Hidden('machine_region', value=init_region),
                    Hidden('next', value=next_url),
                    Hidden('origin', value=origin),
                    Field('password',
                          css_class="form-control",
                          placeholder='请设置密码,至少包含8位字符'),
                    Field('password_repeat',
                          css_class="form-control",
                          placeholder='请再输入一次密码'),
                    Field('phone',
                          css_class="form-control",
                          placeholder='请输入手机号'),
                    AppendedText(
                        'captcha_code',
                        '<img id="captcha_code" src="/captcha" /> <a href="javascript:void(0)" onclick="refresh();">看不清,换一张</a>  ',
                        css_class='input-xlarge',
                        placeholder='验证码'),
                    AppendedText(
                        'phone_code',
                        '<a href="javascript:void(0)" id="PhoneCodeBtn" onclick="getPhoneCode();">点击发送验证码</a>  ',
                        css_class='input-xlarge',
                        placeholder='手机验证码'),
                    HTML(
                        """<div class="linkfw text-center">点击注册表示你已阅读并同意《<a href="http://www.goodrain.com/goodrainlaws.html" target="_blank">云帮服务条款</a>》</div>"""
                    ),
                    FormActions(
                        Submit('register',
                               u'注册',
                               css_class='btn btn-lg btn-success btn-block')),
                    HTML(
                        """<div class="linkregister text-center">直接<a href="/login{0}">登录</a></div>"""
                        .format(prefix_url)),
                    # HTML("""<a href="http://www.goodrain.com/" class="linkgood text-center">goodrain.com</a>"""),
                    css_class="login-wrap"))
        self.helper.form_id = 'form-normal-reg'
        self.helper.form_class = 'form-horizontal'
Ejemplo n.º 14
0
    def get(self, request, *args, **kwargs):
        import datetime
        # 获取cookie中的csrf
        csrftoken = request.COOKIES.get('csrftoken')
        if csrftoken is None:
            csrftoken = "csrf"
        # 获取statue
        state = request.GET.get("state")
        # 解码toke, type
        logger.debug("account.wechat", state)
        logger.debug("account.wechat",
                     "is_weixin:{0}".format(str(is_weixin(request))))
        # 查询数据库
        err_url = settings.WECHAT_CALLBACK.get("index")
        try:
            wechat_state = WeChatState.objects.get(pk=state)
        except Exception as e:
            logger.exception("account.wechat", e)
            logger.error("account.wechat",
                         "wechatstate is missing,id={0}".format(state))
            return self.redirect_to(err_url)
        cry_state = wechat_state.state

        state_array = AuthCode.decode(str(cry_state),
                                      'we_chat_login').split(',')
        oldcsrftoken = state_array[0]
        origin = state_array[1]
        next_url = state_array[2]
        config = state_array[3]
        origin_url = None
        if len(state_array) == 5:
            origin_url = state_array[4]
        logger.debug("account.wechat", oldcsrftoken)
        logger.debug("account.wechat", origin)
        logger.debug("account.wechat", next_url)
        logger.debug("account.wechat", config)
        logger.debug("account.wechat", origin_url)

        if csrftoken != oldcsrftoken:
            return self.redirect_to(err_url)
        # 获取的code
        code = request.GET.get("code")
        logger.info(code)
        if code is None:
            return self.redirect_to(err_url)
        # 根据code获取access_token
        wechat_config = WeChatConfig.objects.get(config=config)
        access_token, open_id = OpenWeChatAPI.access_token_oauth2_static(
            wechat_config.app_id, wechat_config.app_secret, code)
        logger.info(access_token)
        if access_token is None:
            # 登录失败,跳转到失败页面
            return self.redirect_to(err_url)
        # 检查用户的open_id是否已经存在
        need_new = False
        wechat_user = None
        try:
            wechat_user = WeChatUser.objects.get(open_id=open_id)
        except WeChatUser.DoesNotExist:
            logger.warning(
                "account.wechat",
                "open_id is first to access console. now regist...")
            need_new = True

        # 添加wechatuser
        if need_new:
            jsondata = OpenWeChatAPI.query_userinfo_static(
                open_id, access_token)
            nick_name = jsondata.get("nickname")
            if nick_name:
                nick_name = nick_name.encode("utf-8")
            wechat_user = WeChatUser(open_id=jsondata.get("openid"),
                                     nick_name=nick_name,
                                     union_id=jsondata.get("unionid"),
                                     sex=jsondata.get("sex"),
                                     city=jsondata.get("city"),
                                     province=jsondata.get("province"),
                                     country=jsondata.get("country"),
                                     headimgurl=jsondata.get("headimgurl"),
                                     config=config)
            wechat_user.save()

        # 根据微信的union_id判断用户是否已经注册
        need_new = False
        user = None
        try:
            user = Users.objects.get(union_id=wechat_user.union_id)
        except Users.DoesNotExist:
            logger.warning(
                "account.wechat",
                "union id is first to access console. now create user...")
            need_new = True
        # 用户表中不存在对应用户,判断是否已经解绑
        if need_new:
            try:
                binding = WeChatUnBind.objects.get(
                    union_id=wechat_user.union_id, status=0)
                user = Users.objects.get(pk=binding.user_id)
                user.union_id = wechat_user.union_id
                user.save()
                need_new = False
            except WeChatUnBind.DoesNotExist:
                pass

        # 创建租户
        if need_new:
            union_id = wechat_user.union_id
            tmp_union_id = md5fun(union_id)
            begin_index = len(tmp_union_id) - 8
            tenant_name = tmp_union_id[begin_index:]
            tenant_name = tenant_name.replace("_", "-").lower()
            email = tenant_name + "@wechat.com"
            logger.debug(
                "account.wechat",
                "new wx regist user.email:{0} tenant_name:{1}".format(
                    email, tenant_name))
            # 创建用户,邮箱为openid后8位@wechat.comemail=email,
            # 统计当前wx数量
            count = Users.objects.filter(rf="open_wx").count()
            count += 1989
            nick_name = "wxgd0" + str(count)
            user = Users(nick_name=nick_name,
                         phone="",
                         client_ip=get_client_ip(request),
                         rf="open_wx",
                         status=2,
                         union_id=union_id)
            user.set_password("wechatpwd")
            user.save()
            monitorhook.registerMonitor(user, 'register')
            # 创建租户,默认为alish
            region = RegionInfo.register_choices()[0][0]

            # add by tanm
            regions = [region]
            enterprise_svc.create_and_init_tenant(user.user_id, tenant_name,
                                                  regions, user.enterprise_id)

            # create gitlab user
            if user.email is not None and user.email != "":
                codeRepositoriesService.createUser(user, email, password,
                                                   nick_name, nick_name)
        logger.info(user)
        if user is None:
            logger.error("account.wechat", "微信用户登录失败!")
            return self.redirect_to(err_url)
        # 微信用户登录
        user = authenticate(union_id=user.union_id)
        login(request, user)
        self.user = request.user

        # 回跳到云市
        if next_url is not None \
                and next_url != "" \
                and next_url != "none" \
                and next_url != "None":
            if origin == "app":
                logger.debug("account.wechat",
                             "now return to cloud market login..")
                if origin_url is None or origin_url == "redirect_url" or origin_url == "":
                    origin_url = settings.APP_SERVICE_API.get("url")
                if not origin_url.startswith("http://"):
                    origin_url = "http://" + origin_url
                # 返回参数
                payload = {
                    "nick_name": user.nick_name,
                    "user_id": str(user.user_id),
                    "next_url": next_url,
                    "action": "register" if need_new else "login"
                }
                if wechat_user is not None:
                    payload["wechat_name"] = wechat_user.nick_name
                ticket = AuthCode.encode(json.dumps(payload), "goodrain")
                next_url = "{0}/login/{1}/success?ticket={2}".format(
                    origin_url, sn.instance.cloud_assistant, ticket)
                # next_url = settings.APP_SERVICE_API.get("url") + '/login/goodrain/success?ticket=' + ticket
                logger.debug("account.wechat", next_url)
            return redirect(next_url)

        return self.redirect_view()
Ejemplo n.º 15
0
class RegisterForm(forms.Form):
    '''
    邀请注册表单
    '''
    email = forms.EmailField(
        required=False,
        max_length=32,
        label="",
        # ajax_check=True,
        # widget=widgets.EmailInput(attrs={"data-remote-error": u"邮件地址已存在"})
    )
    tenant = forms.CharField(
        required=True,
        max_length=40,
        label="",
        validators=[is_standard_word_extend, is_sensitive],
        # min_length=3, ajax_check=True, pattern=standard_regex_string,
        # widget=widgets.TextInput(attrs={"data-remote-error": u"已存在"})
    )
    nick_name = forms.CharField(
        required=True,
        max_length=24,
        label="",
        validators=[is_standard_word, is_sensitive],
        # pattern=standard_regex_string, ajax_check=True,
        # widget=widgets.TextInput(attrs={"data-remote-error": u"昵称已存在"})
    )
    password = forms.CharField(required=True,
                               label='',
                               widget=forms.PasswordInput,
                               validators=[password_len])
    password_repeat = forms.CharField(required=True,
                                      label='',
                                      widget=forms.PasswordInput,
                                      validators=[password_len])
    phone = forms.CharField(required=True, label='', validators=[is_phone])

    if settings.MODULES["Sms_Check"]:
        phone_code = forms.CharField(
            required=False,
            label='',
        )

    captcha_code = forms.CharField(
        required=True,
        label='',
    )
    real_captcha_code = forms.CharField(
        required=True,
        label='',
    )

    invite_tag = forms.CharField(
        required=False,
        label='',
    )

    # ('aws-bj-1', 'Amazon北京'),
    # ('aws-bj-1', '亚马逊[北京]'),
    # ('0', {'label':'亚马逊[北京](正在建设)', 'disabled': True})
    machine_region = forms.ChoiceField(label="",
                                       choices=RegionInfo.register_choices(),
                                       initial="ali-sh",
                                       widget=SelectWithDisabled)

    error_messages = {
        'nick_name_used': u"该用户名已存在",
        'email_used': u"邮件地址已被注册",
        'tenant_used': u"团队名已存在",
        'password_repeat': u"两次输入的密码不一致",
        'phone_used': u"手机号已存在",
        'phone_empty': u"手机号为空",
        'phone_captch_error': u"手机验证码已失效",
        'phone_code_error': u"手机验证码错误",
        'captcha_code_error': u"验证码有误",
        'machine_region_error': u"请选择数据中心",
    }

    def __init__(self, *args, **kwargs):
        init_phone = ""
        init_email = ""
        init_tenant = ""
        init_region = ""
        selected_region = ""
        next_url = None
        origin = None
        prefix_url = ""
        if len(kwargs) > 0:
            if kwargs.get("initial") is not None:
                initalObj = kwargs.get("initial")
                init_phone = initalObj["phone"]
                init_email = initalObj["email"]
                init_tenant = initalObj["tenant"]
                init_region = initalObj["region"]
            if kwargs.get("region_level") is not None:
                selected_region = kwargs["region_level"]["region"]
                kwargs.pop("region_level")
            if kwargs.get("next_url") is not None:
                next_url = kwargs["next_url"]
                prefix_url += "&next={0}".format(next_url)
                kwargs.pop("next_url")
            if kwargs.get("origin") is not None:
                origin = kwargs["origin"]
                prefix_url += "&origin={0}".format(origin)
                kwargs.pop("origin")
        if len(prefix_url) > 1:
            prefix_url = "?" + prefix_url[1:]
        if len(args) > 0:
            if type(args) is tuple:
                if args[0].get("initial") is not None:
                    initalObj = args[0]["initial"]
                    if type(initalObj) is list:
                        initalObj = initalObj(0)
                    init_phone = initalObj["phone"]
                    init_email = initalObj["email"]
                    init_tenant = initalObj["tenant"]
                    init_region = initalObj["region"]
        super(RegisterForm, self).__init__(*args, **kwargs)
        self.helper = FormHelper(self)
        self.helper.form_tag = False

        text_phone = "手机号"
        text_email = "请输入邮箱地址"
        text_tenant = "团队域名"
        if init_phone is not None and init_phone != "":
            self.fields['phone'].widget.attrs['readonly'] = True
            text_phone = init_phone
        if init_email is not None and init_email != "":
            self.fields['email'].widget.attrs['readonly'] = True
            text_email = init_email
        if init_tenant is not None and init_tenant != "":
            self.fields['tenant'].widget.attrs['readonly'] = True
            text_tenant = init_tenant
        if init_region is not None and init_region != "":
            self.fields['machine_region'].initial = init_region
            self.fields['machine_region'].widget.attrs['readonly'] = True
        if selected_region is not None and selected_region != "":
            self.fields['machine_region'].initial = selected_region

        init_region = RegionInfo.register_choices()[0][0]
        # 对于社区版注册表单进行处理
        is_private = sn.instance.is_private()
        tenant_name = None
        if is_private:
            tenant_num = Tenants.objects.count()
            if tenant_num == 1:
                tenant_list = Tenants.objects.all()
                tenant = tenant_list[0]
                tenant_name = tenant.tenant_name

        # if settings.MODULES["Sms_Check"]:
        if settings.MODULES["WeChat_Module"]:
            self.helper.layout = Layout(
                Div(
                    Field('tenant',
                          "",
                          placeholder='请输入团队名(可使用小写英文字母、数字、下划线及中划线)',
                          css_class="form-control") if tenant_name is None else
                    Field('tenant',
                          "",
                          placeholder='请输入团队名(可使用小写英文字母、数字、下划线及中划线)',
                          css_class="form-control",
                          readonly="readonly",
                          value=tenant_name),
                    Field('nick_name',
                          css_class="form-control",
                          placeholder='请输入用户名(可使用小写英文字母、数字、下划线及中划线)'),
                    Field('email',
                          css_class="form-control",
                          placeholder='请输入邮箱(选填)'),
                    HTML("<hr/>"),
                    # 默认为ali-sh
                    Hidden('machine_region', value=init_region),
                    Hidden('next', value=next_url),
                    Hidden('origin', value=origin),
                    Field('password',
                          css_class="form-control",
                          placeholder='请设置密码,至少包含8位字符'),
                    Field('password_repeat',
                          css_class="form-control",
                          placeholder='请再输入一次密码'),
                    Field('phone',
                          css_class="form-control",
                          placeholder='请输入手机号'),
                    AppendedText(
                        'captcha_code',
                        '<img id="captcha_code" src="/captcha" /> <a href="javascript:void(0)" onclick="refresh();">看不清,换一张</a>  ',
                        css_class='input-xlarge',
                        placeholder='图片验证码'),
                    AppendedText(
                        'phone_code',
                        '<a href="javascript:void(0)" id="PhoneCodeBtn" onclick="getPhoneCode();">点击发送验证码</a>  ',
                        css_class='input-xlarge',
                        placeholder='手机验证码'),
                    HTML(
                        """<div class="linkfw text-center">点击注册表示你已阅读并同意《<a href="http://www.goodrain.com/goodrainlaws.html" target="_blank">云帮服务条款</a>》</div>"""
                    ),
                    FormActions(
                        Submit('register',
                               u'注册',
                               css_class='btn btn-lg btn-success btn-block')),
                    HTML("""<p class="text-center">或使用以下账号注册</p>"""),
                    HTML(
                        """<a href="/wechat/login{0}" class="weixin"><img src="static/www/images/weixin.png">微信</a>"""
                        .format(prefix_url)),
                    HTML(
                        """<div class="linkregister text-center">直接<a href="/login{0}">登录</a></div>"""
                        .format(prefix_url)),
                    # HTML("""<a href="http://www.goodrain.com/" class="linkgood text-center">goodrain.com</a>"""),
                    css_class="login-wrap"))
        else:
            self.helper.layout = Layout(
                Div(
                    Field('tenant',
                          "",
                          placeholder='请输入团队名(可使用小写英文字母、数字、下划线及中划线)',
                          css_class="form-control") if tenant_name is None else
                    Field('tenant',
                          "",
                          placeholder='请输入团队名(可使用小写英文字母、数字、下划线及中划线)',
                          css_class="form-control",
                          readonly="readonly",
                          value=tenant_name),
                    Field('nick_name',
                          css_class="form-control",
                          placeholder='请输入用户名(可使用小写英文字母、数字、下划线及中划线)'),
                    Field('email',
                          css_class="form-control",
                          placeholder='请输入邮箱(选填)'),
                    HTML("<hr/>"),
                    Hidden('machine_region', value=init_region),
                    Hidden('next', value=next_url),
                    Hidden('origin', value=origin),
                    Field('password',
                          css_class="form-control",
                          placeholder='请设置密码,至少包含8位字符'),
                    Field('password_repeat',
                          css_class="form-control",
                          placeholder='请再输入一次密码'),
                    Field('phone',
                          css_class="form-control",
                          placeholder='请输入手机号'),
                    AppendedText(
                        'captcha_code',
                        '<img id="captcha_code" src="/captcha" /> <a href="javascript:void(0)" onclick="refresh();">看不清,换一张</a>  ',
                        css_class='input-xlarge',
                        placeholder='验证码'),
                    AppendedText(
                        'phone_code',
                        '<a href="javascript:void(0)" id="PhoneCodeBtn" onclick="getPhoneCode();">点击发送验证码</a>  ',
                        css_class='input-xlarge',
                        placeholder='手机验证码'),
                    HTML(
                        """<div class="linkfw text-center">点击注册表示你已阅读并同意《<a href="http://www.goodrain.com/goodrainlaws.html" target="_blank">云帮服务条款</a>》</div>"""
                    ),
                    FormActions(
                        Submit('register',
                               u'注册',
                               css_class='btn btn-lg btn-success btn-block')),
                    HTML(
                        """<div class="linkregister text-center">直接<a href="/login{0}">登录</a></div>"""
                        .format(prefix_url)),
                    # HTML("""<a href="http://www.goodrain.com/" class="linkgood text-center">goodrain.com</a>"""),
                    css_class="login-wrap"))
        self.helper.form_id = 'form-normal-reg'
        self.helper.form_class = 'form-horizontal'

    def clean(self):
        email = self.cleaned_data.get('email')
        tenant = self.cleaned_data.get('tenant')
        nick_name = self.cleaned_data.get('nick_name')
        password = self.cleaned_data.get('password')
        password_repeat = self.cleaned_data.get('password_repeat')
        phone = self.cleaned_data.get('phone')
        phone_code = self.cleaned_data.get('phone_code')
        captcha_code = self.cleaned_data.get('captcha_code')
        real_captcha_code = self.cleaned_data.get('real_captcha_code')
        invite_tag = self.cleaned_data.get('invite_tag')
        machine_region = self.cleaned_data.get('machine_region')

        # 校验邮箱,为空不做校验
        if email is not None and email != "":
            try:
                Users.objects.get(email=email)
                raise forms.ValidationError(self.error_messages['email_used'],
                                            code='email_used',
                                            params={'email': email})
            except Users.DoesNotExist:
                pass

        # 判断是否邀请注册,邀请注册不校验租户
        if invite_tag is None or invite_tag == "":
            try:
                Tenants.objects.get(tenant_name=tenant)
                if not sn.instance.is_private():
                    raise forms.ValidationError(
                        self.error_messages['tenant_used'],
                        code='tenant_used',
                        params={'tenant': tenant})
            except Tenants.DoesNotExist:
                pass

        # 数据中心不做校验,默认为ali-sh
        if machine_region is None or machine_region == "" or machine_region == "1":
            pass
            # machine_region = "ali-sh"
            # raise forms.ValidationError(
            #     self.error_messages['machine_region_error'],
            #     code='machine_region_error',
            # )

        try:
            Users.objects.get(nick_name=nick_name)
            raise forms.ValidationError(self.error_messages['nick_name_used'],
                                        code='nick_name_used')
        except Users.DoesNotExist:
            pass

        if password_repeat != password:
            raise forms.ValidationError(
                self.error_messages['password_repeat'],
                code='password_repeat',
            )

        # 手机号码为空不做校验,不为空校验是否已经存在
        if phone is not None and phone != "":
            phoneNumber = Users.objects.filter(phone=phone).count()
            logger.debug('form_valid.register', phoneNumber)
            if phoneNumber > 0:
                raise forms.ValidationError(self.error_messages['phone_used'],
                                            code='phone_used')
        else:
            pass
            # raise forms.ValidationError(
            #     self.error_messages['phone_empty'],
            #     code='phone_empty'
            # )

        if phone is not None and phone != "":
            if settings.MODULES["Sms_Check"]:
                phoneCodes = PhoneCode.objects.filter(
                    phone=phone).order_by('-ID')[:1]
                if len(phoneCodes) > 0:
                    phoneCode = phoneCodes[0]
                    last = int(phoneCode.create_time.strftime("%s"))
                    now = int(time.time())
                    if now - last > 300:
                        logger.info('form_valid.register',
                                    phone + "too long time")
                        raise forms.ValidationError(
                            self.error_messages['phone_captch_error'],
                            code='phone_captch_error')
                    if phoneCode.code != phone_code:
                        logger.info('form_valid.register',
                                    phone + " different")
                        raise forms.ValidationError(
                            self.error_messages['phone_code_error'],
                            code='phone_code_error')
                else:
                    raise forms.ValidationError(
                        self.error_messages['phone_code_error'],
                        code='phone_code_error')
        else:
            logger.info('form_valid.register', " phone is None")
            pass
            # raise forms.ValidationError(
            #     self.error_messages['phone_empty'],
            #     code='phone_empty'
            # )

        if real_captcha_code is None or captcha_code is None or real_captcha_code.lower(
        ) != captcha_code.lower():
            raise forms.ValidationError(
                self.error_messages['captcha_code_error'],
                code='captcha_code_error')

        return self.cleaned_data
Ejemplo n.º 16
0
    def post(self, request, *args, **kwargs):
        """注册管理员"""
        admin_form = AdminForm(request.POST)
        import datetime
        if admin_form.is_valid():
            email = request.POST.get('email')
            nick_name = request.POST.get('nick_name')
            password = request.POST.get('password')
            password_repeat = request.POST.get('password_repeat')
            region = request.POST.get('machine_region')
            if region is None or region == "" or region == "1":
                region = RegionInfo.register_choices()[0][0]

            # 企业名称
            enter_alias = request.POST.get('enter_alias', '')

            # 租户信息
            tenant_name = nick_name
            # 清理之前所有的租户
            tenant_count = Tenants.objects.all().count()
            if tenant_count > 0:
                logger.error("account.register", "租户已存在,请先清理租户!")
                context = self.get_context()
                admin_form.add_error("", "租户已存在,请先清理租户!")
                context["form"] = admin_form
                return TemplateResponse(request, 'www/wizard/admin.html',
                                        context)
                # Tenants.objects.all().delete()

            regions = regionConfig.regions()
            if region not in [r['name'] for r in regions]:
                logger.error("account.register", "配置文件中未找到待初始化的数据中心配置信息!")
                context = self.get_context()
                admin_form.add_error("", "配置文件中未找到待初始化的数据中心配置信息!")
                context["form"] = admin_form
                return TemplateResponse(request, 'www/wizard/admin.html',
                                        context)

            # 添加本地企业信息
            enterprise = enterprise_svc.create_enterprise(
                enterprise_alias=enter_alias)

            # 添加用户
            user = Users(email=email,
                         nick_name=nick_name,
                         client_ip=get_client_ip(request),
                         rf='admin',
                         is_active=False,
                         enterprise_id=enterprise.enterprise_id)
            user.set_password(password)
            user.save()
            monitorhook.registerMonitor(user, 'register')
            # 添加django用户
            tmpname = nick_name + "_token"
            oauth_user = OAuthUser.objects.create(username=tmpname)
            oauth_user.set_password(password)
            oauth_user.is_staff = True
            oauth_user.save()

            # 初始化企业与团队信息
            region_names = [region]
            enterprise_svc.create_and_init_tenant(user.user_id, tenant_name,
                                                  region_names,
                                                  enterprise.enterprise_id)

            # 第一个用户默认作为云帮管理员
            superadmin = SuperAdminUser()
            superadmin.email = email
            superadmin.save()

            # create gitlab user
            if user.email is not None and user.email != "":
                codeRepositoriesService.createUser(user, email, password,
                                                   nick_name, nick_name)

            # 登录系统
            user = authenticate(username=nick_name, password=password)
            login(request, user)
            self.user = request.user

            # 发送数据到app进行注册
            data = {
                "username": nick_name,
                "email": email,
                "password": password,
            }
            json_data = json.dumps(data)

            try:
                # for num in range(0, 3):
                appClient.timeout = 5
                res, body = appClient.post_admin_info(json_data)
                if res is None:
                    logger.error("account.register", "register app failed!")
                else:
                    logger.debug("account.register", res)
                    logger.debug("account.register", body)
                    if res.status == 200:
                        logger.debug("account.register",
                                     "register app success!")
                    else:
                        logger.error("account.register",
                                     "register app failed!")
            except Exception as e:
                logger.exception("account.register", e)

            url = '/apps/{0}'.format(tenant_name)
            if settings.MODULES["Package_Show"]:
                selected_pay_level = ""
                pl = request.GET.get("pl", "")
                region_levels = pl.split(":")
                if len(region_levels) == 2:
                    selected_pay_level = region_levels[1]
                url = '/payed/{0}/select?selected={1}'.format(
                    tenant_name, selected_pay_level)
            logger.debug(url)
            return self.redirect_to(url)
        else:
            context = self.get_context()
            context["form"] = admin_form
            return TemplateResponse(request, 'www/wizard/admin.html', context)
Ejemplo n.º 17
0
    def post(self, request, *args, **kwargs):
        result = {}
        try:
            tenant_id = self.tenant.tenant_id
            region_name = request.POST["region_name"]
            buy_memory = request.POST["buy_memory"]
            buy_disk = request.POST["buy_disk"]
            buy_net = 0
            buy_period = request.POST["buy_period"]
            action = request.POST["action"]
            regions = RegionInfo.region_names()
            period = int(buy_period)
            pay_model = "month"
            if period > 0 and regions.index(region_name) >= 0:
                feerule = settings.REGION_FEE_RULE[region_name]
                logger.debug(feerule)
                one1 = float(feerule["memory_money"]) * int(buy_memory)
                one2 = float(feerule["disk_money"]) * int(buy_disk)
                one3 = float(feerule["net_money"]) * int(buy_net)
                onehour = one1 + one2
                buy_money = 0
                tmp_perod = period
                if period >= 12:
                    pay_model = "year"
                    buy_money = onehour * 24 * period * 1.5 * 30 + one3
                    tmp_perod = period / 12
                else:
                    buy_money = onehour * 24 * period * 2 * 30 + one3

                needTotalMoney = round(buy_money, 2)
                logger.debug(needTotalMoney)
                tenant = Tenants.objects.get(tenant_id=tenant_id)
                if tenant.balance > needTotalMoney:
                    tenant.balance = tenant.balance - Decimal(needTotalMoney)
                    tenant.save()
                    logger.debug(tenant_id + "cost money" +
                                 str(needTotalMoney))
                    TenantConsume(tenant_id=tenant_id,
                                  total_memory=int(buy_memory) *
                                  int(buy_period),
                                  cost_money=needTotalMoney,
                                  payed_money=needTotalMoney,
                                  pay_status='payed').save()

                    statTime = datetime.datetime.now() + datetime.timedelta(
                        hours=1)
                    endTime = datetime.datetime.now() + relativedelta(
                        months=int(buy_period))
                    if action == "append":
                        trpms = TenantRegionPayModel.objects.filter(
                            tenant_id=tenant_id).order_by('-ID')[:1]
                        if len(trpms) > 0:
                            trpm = trpms[0]
                            statTime = trpm.buy_end_time + datetime.timedelta(
                                hours=1)
                            endTime = trpm.buy_end_time + relativedelta(
                                months=int(buy_period))

                    start_time = statTime.strftime("%Y-%m-%d %H:00:00")
                    end_time = endTime.strftime("%Y-%m-%d %H:00:00")
                    data = {}
                    data["tenant_id"] = tenant_id
                    data["region_name"] = region_name
                    data["pay_model"] = pay_model
                    data["buy_period"] = tmp_perod
                    data["buy_memory"] = buy_memory
                    data["buy_disk"] = buy_disk
                    data["buy_net"] = buy_net
                    data["buy_start_time"] = start_time
                    data["buy_end_time"] = end_time
                    data["buy_money"] = buy_money
                    data["create_time"] = datetime.datetime.now().strftime(
                        "%Y-%m-%d %H:%M:%S")
                    TenantRegionPayModel(**data).save()
                    result["status"] = "success"
                    monitorhook.buyPayModelMonitor(self.tenant, self.user,
                                                   'buy_pay_model')
                else:
                    result["status"] = "nomoney"
            else:
                result["status"] = "par"
        except Exception as e:
            logger.exception(e)
            result["status"] = "failure"
        return JsonResponse(result, status=200)
Ejemplo n.º 18
0
    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})