Exemple #1
0
    def post(self, request, project_id, clb_id):
        # 获取配置
        record = CloudLoadBlancer.objects.retrieve_record(clb_id)
        # 校验使用集群权限
        clb_utils.can_use_cluster(request, project_id, record['cluster_id'])
        # 获取 repo 地址
        repo_domain = paas_cc.get_jfrog_domain(request.user.token.access_token,
                                               project_id,
                                               record['cluster_id'])
        if not repo_domain:
            repo_domain = settings.DEFAUT_MESOS_LB_JFROG_DOMAIN
        record['repo_domain'] = repo_domain
        mesos_json = json.loads(render_to_string('mesos.json', record))

        with client.ContextActivityLogClient(
                project_id=project_id,
                user=request.user.username,
                resource_type='lb',
                resource=record['resource_name'],
                description=_("集群:{}, 创建clb关联deployment:{}").format(
                    record['cluster_id'], record['resource_name']),
        ).log_add():
            clb_utils.create_mesos_deployment(request.user.token.access_token,
                                              project_id, record['cluster_id'],
                                              record['namespace'], mesos_json)
        # 更改状态
        self.update_clb_status(clb_id, clb_constants.CLB_CREATED_STATUS)

        return response.Response()
Exemple #2
0
    def retrieve(self, request, project_id, *args, **kwargs):
        cluster_id = request.query_params.get("cluster_id")

        check_cluster_perm(user=request.user,
                           project_id=project_id,
                           cluster_id=cluster_id,
                           request=request)

        # 获取镜像地址
        jfrog_domain = paas_cc.get_jfrog_domain(access_token=self.access_token,
                                                project_id=self.project_id,
                                                cluster_id=cluster_id)

        cluster_info = paas_cc.get_cluster(request.user.token.access_token,
                                           project_id, cluster_id)["data"]

        context = dict(cluster_id=cluster_id,
                       cluster_name=cluster_info["name"],
                       jfrog_domain=jfrog_domain,
                       expr="{{ .Values.__BCS__.SYS_JFROG_DOMAIN }}",
                       link=settings.HELM_DOC_TRICKS)
        note = _('''集群: {cluster}({cluster_id})的容器仓库域名为:{dept_domain},
        可在Chart直接引用 {expr} 更加方便, [详细说明]({link})''').format(
            cluster=context['cluster_name'],
            cluster_id=context['cluster_id'],
            dept_domain=context['jfrog_domain'],
            expr=context['expr'],
            link=context['link'])
        context["note"] = note
        return Response(data=context)
Exemple #3
0
    def retrieve(self, request, project_id, *args, **kwargs):
        cluster_id = request.query_params.get("cluster_id")

        check_cluster_perm(user=request.user,
                           project_id=project_id,
                           cluster_id=cluster_id,
                           request=request)

        # 获取镜像地址
        jfrog_domain = paas_cc.get_jfrog_domain(access_token=self.access_token,
                                                project_id=self.project_id,
                                                cluster_id=cluster_id)

        cluster_info = paas_cc.get_cluster(request.user.token.access_token,
                                           project_id, cluster_id)["data"]

        context = dict(cluster_id=cluster_id,
                       cluster_name=cluster_info["name"],
                       jfrog_domain=jfrog_domain,
                       expr="{{ .Values.__BCS__.SYS_JFROG_DOMAIN }}",
                       link=settings.HELM_DOC_TRICKS)
        note = '{pre_msg}: {cluster}({cluster_id}){dept_key}:{dept_domain},{chart} {expr} {suf_msg} {link}'.format(
            pre_msg=_("集群"),
            cluster=context['cluster_name'],
            cluster_id=context['cluster_id'],
            dept_key=_("的容器仓库域名为"),
            dept_domain=context['jfrog_domain'],
            chart=_("可在Chart直接引用"),
            expr=repr(context['expr']),
            suf_msg=_("更加方便, [详细说明]"),
            link=context['link'])
        context["note"] = note
        return Response(data=context)
Exemple #4
0
def create_imagepullsecret(access_token, project_id, project_code, cluster_id, namespace):
    # get dept domain
    dept_domain = paas_cc.get_jfrog_domain(access_token, project_id, cluster_id)
    # 判断是否为研发仓库,正式环境分为:研发仓库、生产仓库,这2个仓库的账号要分开申请
    is_bk_dept = True if dept_domain.startswith(settings.BK_JFROG_ACCOUNT_DOMAIN) else False
    dept_account = get_jfrog_account(access_token, project_code, project_id, is_bk_dept)
    # get user or pwd by dept account
    user = dept_account.get('user', '')
    pwd = dept_account.get('password', '')
    # compose config
    secret_config = {
        "kind": "secret",
        "metadata": {
            "name": MESOS_IMAGE_SECRET,
            "namespace": namespace
        },
        "datas": {
            "user": {
                "content": base64.b64encode(user.encode(encoding="utf-8")).decode()
            },
            "pwd": {
                "content": base64.b64encode(pwd.encode(encoding="utf-8")).decode()
            }
        },
        "apiVersion": "v4"
    }
    client = MesosClient(access_token, project_id, cluster_id, env=None)
    resp = client.create_secret(namespace, secret_config)
    if (resp.get('code') != ErrorCode.NoError) and ('already exists' not in resp.get('message', '')):
        raise error_codes.APIError(f'create secret error, result.get("message")')
Exemple #5
0
def render_helm_values(access_token, project_id, cluster_id, protocol_type, replica_count, namespace):
    """渲染helm values配置文件"""
    # check protocol exist
    http_enabled = "false"
    https_enabled = "false"
    http_port = DEFAULT_HTTP_PORT
    https_port = DEFAULT_HTTPS_PORT
    protocol_type_list = re.findall(r"[^,; ]+", protocol_type)
    for info in protocol_type_list:
        protocol_port = info.split(":")
        if "http" in protocol_port:
            http_enabled = "true"
            http_port = protocol_port[-1] if len(protocol_port) == 2 and protocol_port[-1] else DEFAULT_HTTP_PORT
        if "https" in protocol_port:
            https_enabled = "true"
            https_port = protocol_port[-1] if len(protocol_port) == 2 and protocol_port[-1] else DEFAULT_HTTPS_PORT
    jfrog_domain = paas_cc.get_jfrog_domain(access_token=access_token, project_id=project_id, cluster_id=cluster_id)
    # render
    template = K8S_NGINX_INGRESS_CONTROLLER_CHART_VALUES
    template = template.replace("__REPO_ADDR__", jfrog_domain)
    template = template.replace("__CONTROLLER_IMAGE_PATH__", CONTROLLER_IMAGE_PATH)
    # TODO: 先调整为固定版本,后续允许用户在前端选择相应的版本
    template = template.replace("__TAG__", "0.35.0")
    template = template.replace("__CONTROLLER_REPLICA_COUNT__", str(replica_count))
    template = template.replace("__BACKEND_IMAGE_PATH__", BACKEND_IMAGE_PATH)
    template = template.replace("__HTTP_ENABLED__", http_enabled)
    template = template.replace("__HTTP_PORT__", http_port)
    template = template.replace("__HTTPS_ENABLED__", https_enabled)
    template = template.replace("__HTTPS_PORT__", https_port)
    template = template.replace("__NAMESPACE__", namespace)

    return template
Exemple #6
0
    def init_mesos_ns_by_bcs(self, access_token, project_id, project_code, cluster_id, ns_name):
        """新建包含仓库账号信息的sercret配置文件并下发"""
        # 获取镜像仓库地址
        jfrog_domain = paas_cc.get_jfrog_domain(access_token, project_id, cluster_id)
        # 按项目申请仓库的账号信息

        # 判断是否为研发仓库,正式环境分为:研发仓库、生产仓库,这2个仓库的账号要分开申请
        if jfrog_domain.startswith(settings.BK_JFROG_ACCOUNT_DOMAIN):
            is_bk_jfrog = True
        else:
            is_bk_jfrog = False
        jfrog_account = get_jfrog_account(access_token, project_code, project_id, is_bk_jfrog)
        _user = jfrog_account.get('user', '')
        _pwd = jfrog_account.get('password', '')
        jfrog_config = {
            "kind": "secret",
            "metadata": {"name": MESOS_IMAGE_SECRET, "namespace": ns_name},
            "datas": {
                "user": {"content": base64.b64encode(_user.encode(encoding="utf-8")).decode()},
                "pwd": {"content": base64.b64encode(_pwd.encode(encoding="utf-8")).decode()},
            },
            "apiVersion": "v4",
        }

        # 下发secret配置文件
        client = MesosClient(access_token, project_id, cluster_id, env=None)
        result = client.create_secret(ns_name, jfrog_config)
        if result.get('code') != 0:
            client.delete_secret(ns_name, MESOS_IMAGE_SECRET)
            raise error_codes.ComponentError.f(_("创建registry secret失败,{}").format(result.get('message')))
Exemple #7
0
def get_image_url(image_url, use_custom_image_url, access_token, project_id, cluster_id):
    if use_custom_image_url:
        return image_url
    # 查询仓库地址
    repo_domain = paas_cc.get_jfrog_domain(access_token, project_id, cluster_id)
    if not repo_domain:
        repo_domain = inst_constants.DEFAULT_LB_REPO_DOMAIN
    if image_url:
        return f"{repo_domain}{image_url}"
    return f"{repo_domain}{inst_constants.DEFAULT_MESOS_LB_IMAGE_PATH}"
Exemple #8
0
def get_ns_variable(access_token, project_id, namespace_id):
    """获取命名空间相关的变量信息"""
    context = {}
    # 获取命名空间的信息
    resp = paas_cc.get_namespace(access_token, project_id, namespace_id)
    if resp.get('code') != 0:
        raise ValidationError('{}(namespace_id:{}):{}'.format(_("查询命名空间的信息出错"), namespace_id, resp.get('message')))
    data = resp.get('data')
    cluster_id = data.get('cluster_id')
    context['SYS_CLUSTER_ID'] = cluster_id
    context['SYS_NAMESPACE'] = data.get('name')
    has_image_secret = data.get('has_image_secret')
    # 获取镜像地址
    context['SYS_JFROG_DOMAIN'] = paas_cc.get_jfrog_domain(access_token, project_id, context['SYS_CLUSTER_ID'])
    context['SYS_IMAGE_REGISTRY_LIST'] = paas_cc.get_image_registry_list(access_token, cluster_id)
    bcs_context = get_bcs_context(access_token, project_id)
    context.update(bcs_context)
    # k8s 集群获取集群版本信息
    cluster_version = get_cluster_version(access_token, project_id, cluster_id)
    return has_image_secret, cluster_version, context
def collect_system_variable(access_token, project_id, namespace_id):
    sys_variables = {}

    # 获取标准日志采集的dataid
    data_info = get_data_id_by_project_id(project_id)
    sys_variables['SYS_STANDARD_DATA_ID'] = data_info.get('standard_data_id')
    sys_variables['SYS_NON_STANDARD_DATA_ID'] = data_info.get('non_standard_data_id')

    resp = paas_cc.get_project(access_token, project_id)
    if resp.get('code') != 0:
        logger.error(
            "查询project的信息出错(project_id:{project_id}):{message}".format(
                project_id=project_id, message=resp.get('message')
            )
        )
    project_info = resp["data"]
    sys_variables["SYS_CC_APP_ID"] = project_info["cc_app_id"]
    sys_variables['SYS_PROJECT_KIND'] = project_info["kind"]
    sys_variables['SYS_PROJECT_CODE'] = project_info["english_name"]

    resp = paas_cc.get_namespace(access_token, project_id, namespace_id)
    if resp.get('code') != 0:
        logger.error(
            "查询命名空间的信息出错(namespace_id:{project_id}-{namespace_id}):{message}".format(
                namespace_id=namespace_id, project_id=project_id, message=resp.get('message')
            )
        )
    namespace_info = resp["data"]

    sys_variables["SYS_NAMESPACE"] = namespace_info["name"]
    sys_variables["SYS_CLUSTER_ID"] = namespace_info["cluster_id"]
    sys_variables["SYS_PROJECT_ID"] = namespace_info["project_id"]
    # SYS_JFROG_DOMAIN
    # SYS_NON_STANDARD_DATA_ID

    # 获取镜像地址
    jfrog_domain = paas_cc.get_jfrog_domain(access_token, project_id, sys_variables['SYS_CLUSTER_ID'])
    sys_variables['SYS_JFROG_DOMAIN'] = jfrog_domain

    return sys_variables
Exemple #10
0
    def get_ns_variable(self):
        """获取命名空间相关的变量信息"""
        # 获取命名空间的信息
        resp = paas_cc.get_namespace(self.access_token, self.project_id,
                                     self.namespace_id)
        if resp.get("code") != 0:
            raise ValidationError("{}(namespace_id:{}):{}".format(
                _("查询命名空间的信息出错"), self.namespace_id, resp.get("message")))
        data = resp.get("data")
        self.context["SYS_CLUSTER_ID"] = data.get("cluster_id")
        self.context["SYS_NAMESPACE"] = data.get("name")
        self.has_image_secret = data.get("has_image_secret")
        # 获取镜像地址
        self.context["SYS_JFROG_DOMAIN"] = paas_cc.get_jfrog_domain(
            self.access_token, self.project_id, self.context["SYS_CLUSTER_ID"])

        self.context[
            "SYS_IMAGE_REGISTRY_LIST"] = paas_cc.get_image_registry_list(
                self.access_token, self.context["SYS_CLUSTER_ID"])

        bcs_context = get_bcs_context(self.access_token, self.project_id)
        self.context.update(bcs_context)
Exemple #11
0
def get_ns_variable(access_token, project_id, namespace_id):
    """获取命名空间相关的变量信息
    """
    context = {}
    # 获取命名空间的信息
    resp = paas_cc.get_namespace(access_token, project_id, namespace_id)
    if resp.get('code') != 0:
        raise ValidationError(u"查询命名空间的信息出错(namespace_id:%s):%s" %
                              (namespace_id, resp.get('message')))
    data = resp.get('data')
    cluster_id = data.get('cluster_id')
    context['SYS_CLUSTER_ID'] = cluster_id
    context['SYS_NAMESPACE'] = data.get('name')
    has_image_secret = data.get('has_image_secret')
    # 获取镜像地址
    jfrog_domain = paas_cc.get_jfrog_domain(access_token, project_id,
                                            context['SYS_CLUSTER_ID'])
    context['SYS_JFROG_DOMAIN'] = jfrog_domain

    bcs_context = get_bcs_context(access_token, project_id)
    context.update(bcs_context)
    # k8s 集群获取集群版本信息
    cluster_version = get_cluster_version(access_token, project_id, cluster_id)
    return has_image_secret, cluster_version, context
Exemple #12
0
def handle_lb(username, access_token, project_id, lb_info, cc_app_id):
    """
    1. 组装 lb 配置文件
    2. 调用 bcs api 创建 Deployment
    """
    cluster_id = lb_info.get('cluster_id')
    # 查询zk的信息
    zk_res = paas_cc.get_zk_config(access_token, project_id, cluster_id)
    if zk_res.get("code") != ErrorCode.NoError:
        logger.err('获取zk信息出错,%s' % zk_res)
        raise error_codes.APIError(_("获取zk信息出错"))
    try:
        zk_data = zk_res.get("data", [])[0]
    except Exception:
        logger.err('获取zk信息出错,%s' % zk_res)
        raise error_codes.APIError(_("获取zk信息出错"))
    bcs_zookeeper = zk_data.get('bcs_zookeeper')
    zookeeper = zk_data.get('zookeeper')

    # 查询仓库地址
    jfrog_domain = paas_cc.get_jfrog_domain(access_token, project_id,
                                            cluster_id)
    if not jfrog_domain:
        jfrog_domain = DEFAUT_LB_JFROG_DOMAIN

    # 调度约束
    try:
        intersection_item = json.loads(lb_info.get("data"))
    except Exception:
        logger.exception("命名空间中的调度约束信息出错")
        raise error_codes.JsonFormatError(_("命名空间中的调度约束信息出错"))
    new_intersection_item = handle_intersection_item(intersection_item)
    constraint = {"IntersectionItem": new_intersection_item}

    # vip 组装为labels
    try:
        ip_list = json.loads(lb_info.get('ip_list'))
    except Exception:
        logger.exception("命名空间中的IP集信息出错")
        raise error_codes.JsonFormatError(_("命名空间中的IP集信息出错"))
    labels = {}
    for i, ip in enumerate(ip_list):
        _key = "io.tencent.bcs.netsvc.requestip.%s" % i
        labels[_key] = ip

    lb_name = lb_info.get('name')
    # 配置文件中的变量赋值
    now_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')

    # 获取 namespace
    data_dict = lb_info['data_dict']
    if data_dict:
        data_dict = json.loads(data_dict)
    else:
        data_dict = {}
    if data_dict.get('image_url'):
        lb_jfrog_url = f'{jfrog_domain}{data_dict["image_url"]}'
    else:
        lb_jfrog_url = f'{jfrog_domain}/paas/public/mesos/bcs-loadbalance'
    resource_limit = data_dict.get('resources', {}).get('limits', {})
    ns_name = get_namespace_name(access_token, project_id, data_dict)
    # 获取data标准日志输出
    data_info = get_data_id_by_project_id(project_id)
    data_id = str(data_info.get('standard_data_id'))

    context = {
        'SYS_PROJECT_KIND': 2,  # 固定为mesos
        'SYS_STANDARD_DATA_ID': data_id,
        'SYS_CC_APP_ID': cc_app_id,
        'SYS_PROJECT_ID': project_id,
        'SYS_OPERATOR': username,
        'SYS_CLUSTER_ID': cluster_id,
        'SYS_BCSGROUP': lb_name,
        'SYS_CC_ZK': zookeeper,
        'SYS_BCS_ZK': bcs_zookeeper,
        'SYS_CREATOR': username,
        'SYS_UPDATOR': username,
        'SYS_CREATE_TIME': now_time,
        'SYS_UPDATE_TIME': now_time,
        'SYS_JFROG_DOMAIN_URL': lb_jfrog_url,
        'CPU': str(resource_limit.get('cpu', 1)),
        'MEMORY': str(resource_limit.get('memory', 1024)),
        'IMAGE_VERSION': data_dict.get('image_version') or '1.1.0',
        'FORWARD_MODE': data_dict.get('forward_mode') or 'haproxy',
        'SYS_NAMESPACE': ns_name,
        'ETH_VALUE': data_dict.get('eth_value') or 'eth1',
        'LB_ADMIN_PORT': DEFAULT_LB_ADMIN_PORT
    }

    # 组装 lb 配置文件
    lb_config = copy.deepcopy(LB_SYS_CONFIG)
    lb_config['spec']['instance'] = data_dict.get('instance', 1)
    lb_config['constraint'] = constraint
    lb_config['spec']['template']['metadata']['labels'] = labels
    lb_config['spec']['template']['spec']['containers'][0]['ports'][0]['hostPort'] = \
        data_dict.get('host_port') or 31000
    # 处理网络模式
    spec = lb_config.get('spec', {}).get('template', {}).get('spec', {})
    spec['networkMode'] = data_dict.get('networkMode')
    spec['networkType'] = data_dict.get('networkType')
    spec['custom_value'] = data_dict.get('custom_value')
    lb_config = handel_custom_network_mode(lb_config)

    lb_config = json.dumps(lb_config)
    try:
        config_profile = render_mako_context(lb_config, context)
    except Exception:
        logger.exception(u"LoadBalance配置文件变量替换错误\nconfig:%s\ncontext:%s" %
                         (lb_config, context))
        raise ValidationError(_("配置文件中有未替换的变量"))

    config_profile = json.loads(config_profile)
    # 调用bcs api 创建
    client = mesos.MesosClient(access_token, project_id, cluster_id, env=None)
    result = client.create_deployment(ns_name, config_profile)
    if not result.get('result'):
        error_msg = result.get('message', '')
        logger.error(f"命名空间[{ns_name}]下创建LoadBalance[{lb_name}]出错:{error_msg}")
        return False, error_msg
    return True, ''
Exemple #13
0
def get_cc_repo_domain(access_token, project_id, cluster_id):
    return paas_cc.get_jfrog_domain(access_token, project_id, cluster_id)