예제 #1
0
 def get_deployment_rs_name_list(cls, client, ns_name, inst_name, extra=None):
     """获取deployment关联的rs名称
     主要是用作查询关联的pod信息
     """
     extra = extra or {constants.REFERENCE_RESOURCE_LABEL: inst_name}
     extra = utils.base64_encode_params(extra)
     rs_resp = client.get_rs({'extra': extra, 'namespace': ns_name, 'field': 'resourceName'})
     if rs_resp.get('code') != ErrorCode.NoError:
         raise error_codes.APIError(rs_resp.get('message'))
     data = rs_resp.get('data') or []
     return [info['resourceName'] for info in data if info.get('resourceName')]
예제 #2
0
    def validate(self, data):
        context = get_mesos_context(self.context['client'],
                                    data['container_id'])

        if not context:
            raise error_codes.APIError(
                _("container_id不正确,请检查参数{}").format(
                    settings.COMMON_EXCEPTION_MSG))

        data.update(context)
        return data
예제 #3
0
 def get_master_ips(self, request, project_id, cluster_id):
     """get master inner ip info"""
     master_resp = paas_cc.get_master_node_list(
         request.user.token.access_token, project_id, cluster_id)
     if master_resp.get("code") != ErrorCode.NoError:
         raise error_codes.APIError(master_resp.get("message"))
     data = master_resp.get("data") or {}
     master_ip_info = data.get("results") or []
     return [
         info["inner_ip"] for info in master_ip_info if info.get("inner_ip")
     ]
예제 #4
0
def get_zk_config(access_token, project_id, cluster_id, environment=None):
    if not environment:
        cluster = get_cluster(access_token, project_id, cluster_id)
        if cluster.get("code") != 0:
            raise error_codes.APIError(cluster.get("message"))
        environment = cluster["data"]["environment"]

    url = f"{BCS_CC_API_PRE_URL}/zk_config/"
    params = {"access_token": access_token, "environment": environment}
    zk_config = http_get(url, params=params, timeout=20)
    return zk_config
예제 #5
0
 def mesos_container_num(self):
     client = bcs_mesos.MesosClient(self.access_token, self.project_id, self.cluster_id, None)
     host_pod_info = client.get_taskgroup(
         [self.node_ip], fields=','.join(['data.containerStatuses.containerID', 'data.hostIP'])
     )
     if host_pod_info.get('code') != ErrorCode.NoError:
         raise error_codes.APIError(host_pod_info.get('message'))
     count = 0
     for i in host_pod_info.get('data', []):
         count += len(i.get('data', {}).get('containerStatuses', []))
     return count
예제 #6
0
 def delete_via_bcs(self, request, project_id, cluster_id, kind_name, node_info):
     self.ip_list = list(node_info.keys())
     params = {
         'project_id': project_id,
         'cluster_id': cluster_id,
         'username': request.user.username,
         'node_info': node_info,
         'ip_list': self.ip_list,
         'kind': request.project['kind'],
         'kind_name': kind_name,
         'cc_app_id': request.project['cc_app_id'],
     }
     log = NodeUpdateLog.objects.create(
         project_id=project_id,
         cluster_id=cluster_id,
         token=request.user.token.access_token,
         node_id=','.join(node_info.values()),
         params=json.dumps(params),
         operator=request.user.username,
         oper_type=NodeOperType.NodeRemove,
         is_polling=True,
         is_finished=False,
     )
     config = self.get_request_config(op_type=constants.OpType.DELETE_NODE.value)
     control_ip = config.pop('control_ip', [])
     websvr = config.pop('websvr', [])
     try:
         task_info = ops.delete_cluster_node(
             request.user.token.access_token,
             project_id,
             kind_name,
             cluster_id,
             self.master_ip_list,
             self.ip_list,
             config,
             control_ip,
             request.project['cc_app_id'],
             request.user.username,
             websvr,
         )
     except Exception as err:
         logger.exception('request bcs ops error, detail: %s', err)
         task_info = {'code': ErrorCode.UnknownError}
     if task_info.get('code') != ErrorCode.NoError:
         log.set_finish_polling_status(True, False, CommonStatus.RemoveFailed)
         # 更改节点状态
         self.update_nodes(self.ip_list, status=CommonStatus.RemoveFailed)
     data = task_info.get('data') or {}
     task_id = data.get('task_id')
     if not task_id:
         raise error_codes.APIError(_("获取标准运维任务ID失败,返回任务为{},请联系管理员处理").format(task_id))
     log.set_task_id(task_id)
     self.save_task_url(log, data)
     return log
예제 #7
0
    def get_unit_info_by_name(cls, client, ns_name, pod_name, field):
        params = {'namespace': ns_name, 'name': pod_name}
        # 组装field
        field = field or constants.STORAGE_FIELD_LIST
        pod_resp = client.get_pod(extra=None,
                                  field=','.join(field),
                                  params=params)
        if pod_resp.get('code') != ErrorCode.NoError:
            raise error_codes.APIError(pod_resp.get('message'))

        return pod_resp.get('data')
예제 #8
0
 def has_cluster(self, request, project_id):
     """判断项目下是否有集群
     """
     resp = paas_cc.get_all_clusters(request.user.token.access_token,
                                     project_id)
     if resp.get('code') != ErrorCode.NoError:
         raise error_codes.APIError(resp.get('message'))
     # 存在集群时,不允许修改
     if resp.get('data', {}).get('count') > 0:
         return True
     return False
예제 #9
0
파일: base.py 프로젝트: ielgnaw/bk-bcs-saas
 def update_nodes_in_cluster(self, access_token, project_id, cluster_id,
                             node_ips, status):
     """update nodes status in the same cluster"""
     data = [{'inner_ip': ip, 'status': status} for ip in node_ips]
     resp = paas_cc.update_node_list(access_token,
                                     project_id,
                                     cluster_id,
                                     data=data)
     if resp.get('code') != ErrorCode.NoError:
         raise error_codes.APIError(resp.get('message'))
     return resp.get('data') or []
예제 #10
0
def get_zk_config(access_token, project_id, cluster_id, environment=None):
    if not environment:
        cluster = get_cluster(access_token, project_id, cluster_id)
        if cluster.get('code') != 0:
            raise error_codes.APIError(cluster.get('message'))
        environment = cluster['data']['environment']

    url = f'{CC_HOST}/zk_config/'
    params = {'access_token': access_token, 'environment': environment}
    zk_config = http_get(url, params=params, timeout=20)
    return zk_config
예제 #11
0
def get_namespace(access_token, project_id, cluster_id):
    """
    NOTE: mesos没有命名空间的概念,这样命名空间被应用等占用才会查询到命名空间
    """
    client = MesosClient(access_token, project_id, cluster_id, env=None)
    resp = client.get_used_namespace()
    if resp.get('code') != ErrorCode.NoError:
        raise error_codes.APIError(
            f'get namespace error, {resp.get("message")}')

    return resp.get('data') or []
예제 #12
0
    def reschedule_pod(self, pod_info, raise_exception=True):
        resp = self.client.rescheduler_mesos_taskgroup(
            pod_info['namespace'], pod_info['app_name'],
            pod_info['taskgroup_name'])
        if resp.get('code') != ErrorCode.NoError:
            logger.error("request rescheduler taskgroup api error, %s",
                         resp.get("message"))
            if raise_exception:
                raise error_codes.APIError(resp.get('message'))

        return resp
예제 #13
0
    def info(self, request, area_id):
        """get the area info"""
        resp = paas_cc.get_area_info(request.user.token.access_token, area_id)
        if resp.get('code') != ErrorCode.NoError:
            raise error_codes.APIError(
                f'request bcs cc area info api error, {resp.get("message")}')

        data = resp.get('data') or {}
        data['configuration'] = json.loads(data.pop('configuration', '{}'))

        return Response(data)
예제 #14
0
 def _delete_version(self, username: str, pwd: str, project_code: str,
                     name: str, version: str):
     # 兼容harbor中chart仓库项目名称
     project_name = DEFAULT_CHART_REPO_PROJECT_NAME or project_code
     try:
         client = bk_repo.BkRepoClient(username=username, password=pwd)
         client.delete_chart_version(project_name, project_code, name,
                                     version)
     except bk_repo.BkRepoDeleteVersionError as e:
         raise error_codes.APIError(
             f"delete chart: {name} version: {version} failed, {e}")
예제 #15
0
 def check_port_associated_with_service(self, request, project_id, version_id, port_id):
     """检查指定的 port 是否被 service 关联"""
     ventity = self.get_versioned_entity(project_id, version_id)
     svc_id_list = ventity.get_resource_id_list(MesosResourceName.service.value)
     svc_qsets = models.Service.objects.filter(id__in=svc_id_list)
     for svc in svc_qsets:
         ports = svc.get_ports_config()
         for p in ports:
             if str(p.get('id')) == str(port_id):
                 raise error_codes.APIError(_("端口在 Service[{}] 中已经被关联,不能删除").format(svc.name))
     return Response({})
예제 #16
0
 def update_cluster_nodes(self, node_ips, status=CommonStatus.Initializing):
     """更新阶段状态,并返回更新后的信息
     """
     data = [{'inner_ip': ip, 'status': status} for ip in node_ips]
     resp = paas_cc.update_node_list(self.access_token,
                                     self.project_id,
                                     self.cluster_id,
                                     data=data)
     if resp.get('code') != ErrorCode.NoError:
         raise error_codes.APIError(resp.get('message'))
     return resp.get('data') or []
예제 #17
0
 def get(self, request, project_id):
     """check cluster name exist
     """
     name = request.GET.get("name")
     cluster_resp = paas_cc.get_cluster_by_name(
         request.user.token.access_token, project_id, name)
     if cluster_resp.get('code') != ErrorCode.NoError:
         raise error_codes.APIError(cluster_resp.get('message'))
     data = cluster_resp.get('data') or {}
     return response.Response(
         {'is_exist': True if data.get('count') else False})
예제 #18
0
def delete(access_token, project_id, cluster_id, ns_name):
    client = K8SClient(access_token, project_id, cluster_id, env=None)
    resp = client.delete_namespace(ns_name)
    if resp.get('code') == ErrorCode.NoError:
        return
    if 'not found' in resp.get('message'):
        return
    # k8s 删除资源配额
    quota_client = NamespaceQuota(access_token, project_id, cluster_id)
    quota_client.delete_namespace_quota(ns_name)

    raise error_codes.APIError(f'delete namespace error, name: {ns_name}, {resp.get("message")}')
예제 #19
0
 def is_manager(self, request, project_id):
     """判断用户是否为项目管理员
     """
     resp = paas_auth.get_project_user(request.user.token.access_token,
                                       project_id,
                                       group_code='Manager')
     if resp.get('code') != ErrorCode.NoError:
         raise error_codes.APIError(resp.get('message'))
     data = resp.get('data') or []
     if request.user.username in data:
         return True
     return False
예제 #20
0
 def update_or_create_resource_quota(self, name, namespace, body):
     try:
         return self.update_resource_quota(name, namespace, body)
     except ApiException as e:
         logger.error("update resource quota error, %s", e)
         if e.status == 404:
             return self.create_resource_quota(namespace, body)
         raise
     except Exception as e:
         err_msg = f"request k8s resource quota api error, {e}"
         logger.error(err_msg)
         raise error_codes.APIError(err_msg)
예제 #21
0
 def delete_namespaced_custom_object(self, namespace, name):
     try:
         return self.api_instance.delete_namespaced_custom_object(
             self.api_group,
             self.api_version,
             namespace,
             self.api_plural,
             name,
             body=client.V1DeleteOptions())
     except Exception as e:
         raise error_codes.APIError(
             f"delete_namespaced_custom_object error: {e}")
예제 #22
0
 def handle(*args, **kwargs):
     try:
         resp = func(*args, **kwargs)
         return resp
     except ComponentError as error:
         response = getattr(error, "response", None)
         if response and keyword and keyword in response.text:
             raise error_codes.APIError(
                 _("当前集群API版本过低, 还不支持{},请{}").format(
                     module, settings.COMMON_CUSTOMER_SUPPORT_MSG))
         else:
             raise error
예제 #23
0
    def validate(self, data):
        # 默认是sh命令
        data.setdefault("command", "sh")

        # 优先使用container_id
        container_id = data.get("container_id")
        if container_id:
            # 有container_id才检查
            context = get_k8s_context(self.context["client"], container_id)
            if not context:
                raise error_codes.APIError(
                    _("container_id不正确或者容器不是运行状态,请检查参数{}").format(settings.COMMON_EXCEPTION_MSG)
                )

            data.update(context)
            return data

        # 其他使用namespace, pod, container
        if not all([data.get("namespace"), data.get("pod_name"), data.get("container_name")]):
            raise error_codes.APIError(_("container_id或namespace/pod_name/container_name不能同时为空"))
        return data
예제 #24
0
def validate_ns_by_tempalte_id(template_id,
                               ns_list,
                               access_token,
                               project_id,
                               instance_entity={}):
    """实例化,参数 ns_list 不能与 db 中已经实例化过的 ns 重复
    """
    namespace = paas_cc.get_namespace_list(access_token,
                                           project_id,
                                           limit=ALL_LIMIT)
    namespace = namespace.get('data', {}).get('results') or []
    namespace_dict = {str(i['id']): i['name'] for i in namespace}

    # hpa白名单控制
    cluster_id_list = list(set([i['cluster_id'] for i in namespace]))
    if K8sResourceName.K8sHPA.value in instance_entity:
        if not enabled_hpa_feature(cluster_id_list):
            raise error_codes.APIError(
                f"当前实例化包含HPA资源,{settings.GRAYSCALE_FEATURE_MSG}")

    # 查看模板下已经实例化过的 ns
    exist_instance_id = VersionInstance.objects.filter(
        template_id=template_id, is_deleted=False).values_list('id', flat=True)
    filter_ns = InstanceConfig.objects.filter(
        instance_id__in=exist_instance_id,
        is_deleted=False,
        is_bcs_success=True).exclude(
            ins_state=InsState.NO_INS.value).values_list('namespace',
                                                         flat=True)
    exist_ns = []
    # 查询每类资源已经实例化的ns,求合集,这些已经实例化过的ns不能再被实例化
    for cate in instance_entity:
        # HPA 编辑以模板集为准, 可以重复实例化
        if cate == K8sResourceName.K8sHPA.value:
            continue
        cate_data = instance_entity[cate]
        cate_name_list = [i.get('name') for i in cate_data if i.get('name')]
        cate_ns = filter_ns.filter(
            category=cate, name__in=cate_name_list).values_list('namespace',
                                                                flat=True)
        exist_ns.extend(list(cate_ns))

    new_ns_list = [str(_i) for _i in ns_list]
    # 列表的交集
    intersection_list = list(set(exist_ns).intersection(set(new_ns_list)))
    if not intersection_list:
        return True, [], namespace_dict

    ns_name_list = []
    for _n_id in intersection_list:
        _ns_name = namespace_dict.get(_n_id, _n_id)
        ns_name_list.append(_ns_name)
    return False, ns_name_list, namespace_dict
예제 #25
0
    def _validate_namespace_use_perm(self, request, project_id, namespace_list):
        """检查是否有命名空间的使用权限
        """
        namespace_map = self._get_namespace_map(project_id)
        for namespace in namespace_list:
            if namespace in self.NO_PERM_NS:
                raise error_codes.APIError(_("namespace operation is not allowed"))

            namespace_id = namespace_map.get(namespace)
            # 检查是否有命名空间的使用权限
            perm = bcs_perm.Namespace(request, project_id, namespace_id)
            perm.can_use(raise_exception=True)
예제 #26
0
    def _validate_namespace_use_perm(self, project_id: str, cluster_id: str,
                                     namespaces: List):
        """ 检查是否有命名空间的使用权限 """
        namespace_map = self._get_namespace_map(project_id)
        for ns in namespaces:
            if ns in constants.SM_NO_PERM_NAMESPACE:
                raise error_codes.APIError(_('不允许操作命名空间 {}').format(ns))

            namespace_id = namespace_map.get((cluster_id, ns))
            # 检查是否有命名空间的使用权限
            perm = bcs_perm.Namespace(self.request, project_id, namespace_id)
            perm.can_use(raise_exception=True)
예제 #27
0
 def get_cluster_base_config(self, cluster_id, version, environment='prod'):
     params = {'ver_id': version, 'environment': environment, 'kind': self.kind_name}
     base_cluster_config = paas_cc.get_base_cluster_config(self.access_token, self.project_id, params)
     if base_cluster_config.get('code') != ErrorCode.NoError:
         # delete created cluster record
         self.delete_cluster(cluster_id)
         raise error_codes.APIError(base_cluster_config.get('message'))
     config = json.loads(base_cluster_config.get('data', {}).get('configure', '{}'))
     if not config:
         raise error_codes.CheckFailed(_("获取集群基本配置失败"))
     config['version'] = version
     self.config = config
예제 #28
0
 def get_cluster_node(self, request, project_id, cluster_id):
     """get cluster node list
     """
     cluster_node_resp = paas_cc.get_node_list(
         request.user.token.access_token,
         project_id,
         cluster_id,
         params={'limit': cluster_constants.DEFAULT_NODE_LIMIT})
     if cluster_node_resp.get('code') != ErrorCode.NoError:
         raise error_codes.APIError(cluster_node_resp.get('message'))
     data = cluster_node_resp.get('data') or {}
     return data.get('results') or []
예제 #29
0
    def validate(self, data):
        container_id = data.get('container_id')
        if not container_id:
            return data

        # 有container_id才检查
        context = get_k8s_context(self.context['client'], container_id)
        if not context:
            raise error_codes.APIError(_("container_id不正确或者容器不是运行状态,请检查参数{}").format(settings.COMMON_EXCEPTION_MSG))

        data.update(context)
        return data
예제 #30
0
 def delete_cluster_via_bcs(self):
     # 获取集群下对应的master ip
     master_ip_list = self.get_cluster_master()
     params = {
         'project_id': self.project_id,
         'cluster_id': self.cluster_id,
         'cc_app_id': self.cc_app_id,
         'host_ips': master_ip_list,
         'project_code': self.project_info['english_name'],
         'username': self.username
     }
     # 创建记录
     log = ClusterInstallLog.objects.create(
         project_id=self.project_id,
         cluster_id=self.cluster_id,
         token=self.access_token,
         status=CommonStatus.Removing,
         params=json.dumps(params),
         operator=self.username,
         oper_type=ClusterOperType.ClusterRemove,
         is_polling=True,
     )
     task_info = ops.delete_cluster(self.access_token, self.project_id,
                                    self.kind_name, self.cluster_id,
                                    master_ip_list, self.control_ip,
                                    self.cc_app_id, self.username,
                                    self.websvr, self.config)
     if task_info.get('code') != ErrorCode.NoError:
         log.set_finish_polling_status(True, False,
                                       CommonStatus.RemoveFailed)
         self.update_cluster_status(status=CommonStatus.RemoveFailed)
         raise error_codes.APIError(task_info.get('message'))
     data = task_info.get('data') or {}
     task_id = data.get('task_id')
     if not task_id:
         raise error_codes.APIError(
             _("获取标准运维任务ID失败,返回任务ID为{},请联系管理员处理").format(task_id))
     log.set_task_id(task_id)
     self.save_task_url(log, data)
     return log