Skip to content

Commit

Permalink
feat: IP选择器查询主机状态接口增加实时功能 (closed TencentBlueKing#2271)
Browse files Browse the repository at this point in the history
  • Loading branch information
Huayeaaa committed Jun 14, 2024
1 parent 8c9cf74 commit 61782f6
Show file tree
Hide file tree
Showing 6 changed files with 83 additions and 4 deletions.
12 changes: 12 additions & 0 deletions apps/core/ipchooser/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ class CommonEnum(EnhanceEnum):
"bk_host_name",
"os_type",
"status",
"ap_id",
]

@classmethod
Expand Down Expand Up @@ -84,3 +85,14 @@ class HostBTNodeDetectionConditionValue(EnhanceEnum):
@classmethod
def _get_member__alias_map(cls) -> Dict[Enum, str]:
return {cls.ENABLE: _("启用"), cls.DISABLE: _("停用")}


class GseAgentStatusType(EnhanceEnum):
"""对外展示的 Agent 状态"""

RUNNING = 1
TERMINATED = 0

@classmethod
def _get_member__alias_map(cls) -> Dict[Enum, str]:
return {cls.RUNNING: _("正常"), cls.TERMINATED: _("异常")}
46 changes: 44 additions & 2 deletions apps/core/ipchooser/handlers/host_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,14 @@
specific language governing permissions and limitations under the License.
"""
import typing
from collections import defaultdict

from django_mysql.models import QuerySet

from apps.adapters.api.gse import get_gse_api_helper
from apps.core.gray.tools import GrayTools
from apps.node_man.models import GlobalSettings

from .. import constants, types
from ..tools import base
from .base import BaseHandler
Expand All @@ -23,12 +28,14 @@ def details_base(
scope_list: types.ScopeList,
or_conditions: typing.List[types.Condition],
limit_host_ids: typing.Optional[typing.List[int]] = None,
show_agent_realtime_state: bool = False,
) -> typing.List[types.FormatHostInfo]:
"""
获取主机详情
:param scope_list: 资源范围数组
:param or_conditions: 逻辑或查询条件
:param limit_host_ids: 限制检索的主机 ID 列表
:param show_agent_realtime_state: 是否展示Agent实时状态
:return:
"""
host_queryset: QuerySet = base.HostQuerySqlHelper.multiple_cond_sql(
Expand All @@ -40,6 +47,40 @@ def details_base(
# 获取主机信息
host_fields: typing.List[str] = constants.CommonEnum.DEFAULT_HOST_FIELDS.value
untreated_host_infos: typing.List[types.HostInfo] = list(host_queryset.values(*host_fields))

if show_agent_realtime_state:
enable = GlobalSettings.get_config(
key=GlobalSettings.KeyEnum.IP_CHOOSER_ENABLE_SHOW_REALTIME_AGENT_STATE.value, default=False
)
if not enable:
return BaseHandler.format_hosts(untreated_host_infos)
agent_id__host_id_map: typing.Dict[str, int] = {}
host_id__agent_state_code_map: typing.Dict[int, int] = {}
agent_id__agent_state_info_map: typing.Dict[str, typing.Dict] = {}
gray_tools_instance: GrayTools = GrayTools()
gse_version__hosts_info_map: typing.Dict[str, typing.List[typing.Dict]] = defaultdict(list)
for host_info in untreated_host_infos:
gse_version = gray_tools_instance.get_host_ap_gse_version(host_info["bk_biz_id"], host_info["ap_id"])
agent_id = get_gse_api_helper(gse_version).get_agent_id(host_info)
agent_id__host_id_map[agent_id] = host_info["bk_host_id"]
gse_version__hosts_info_map[gse_version].append(
{
"bk_agent_id": host_info["bk_agent_id"],
"ip": host_info["inner_ip"] or host_info["inner_ipv6"],
"bk_cloud_id": host_info["bk_cloud_id"],
}
)
for gse_version, hosts_info in gse_version__hosts_info_map.items():
gse_api_helper = get_gse_api_helper(gse_version)
agent_id__agent_state_info_map.update(gse_api_helper.list_agent_state(hosts_info))
for agent_id, agent_state_info in agent_id__agent_state_info_map.items():
host_id__agent_state_code_map.update(
{agent_id__host_id_map[agent_id]: agent_state_info["bk_agent_alive"]}
)
for host in untreated_host_infos:
bk_host_id = host["bk_host_id"]
host["status"] = constants.GseAgentStatusType(host_id__agent_state_code_map[bk_host_id]).name

return BaseHandler.format_hosts(untreated_host_infos)

@classmethod
Expand Down Expand Up @@ -107,12 +148,13 @@ def check(

@classmethod
def details(
cls, scope_list: types.ScopeList, host_list: typing.List[types.FormatHostInfo]
cls, scope_list: types.ScopeList, host_list: typing.List[types.FormatHostInfo], show_agent_realtime_state: bool
) -> typing.List[types.FormatHostInfo]:
"""
根据主机关键信息获取机器详情信息
:param scope_list: 资源范围数组
:param host_list: 主机关键信息列表
:param show_agent_realtime_state: 是否展示Agent实时状态
:return:
"""
bk_host_id_set: typing.Set[int] = set()
Expand All @@ -129,4 +171,4 @@ def details(
{"key": "bk_host_id", "val": bk_host_id_set},
{"key": "cloud_inner_ip", "val": cloud_inner_ip_set},
]
return cls.details_base(scope_list, or_conditions)
return cls.details_base(scope_list, or_conditions, show_agent_realtime_state=show_agent_realtime_state)
1 change: 1 addition & 0 deletions apps/core/ipchooser/serializers/host_sers.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ class Meta:

class HostDetailsRequestSer(base.ScopeSelectorBaseSer):
host_list = serializers.ListField(child=base.HostInfoWithMetaSer(), default=[])
agent_realtime_state = serializers.BooleanField(label=_("agent实时状态"), required=False, default=False)

class Meta:
swagger_schema_fields = {"example": mock_data.API_HOST_DETAILS_REQUEST}
Expand Down
22 changes: 21 additions & 1 deletion apps/core/ipchooser/tests/test_handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,15 @@
from django.test import TestCase

from apps.core.ipchooser.handlers.host_handler import HostHandler
from apps.mock_data.api_mkd.gse.utils import GseApiMockClient, get_gse_api_helper
from apps.node_man import models
from apps.node_man.tests.utils import MockClient, cmdb_or_cache_biz, create_host
from env.constants import GseVersion


class TestHostHandler(TestCase):
@patch("apps.node_man.handlers.cmdb.CmdbHandler.cmdb_or_cache_biz", cmdb_or_cache_biz)
@patch("apps.node_man.handlers.cmdb.client_v2", MockClient)
@patch("apps.core.ipchooser.query.resource.CCApi", MockClient.cc)
def test_check(self):
create_host(1, bk_host_id=1000, ip="127.0.0.1", bk_cloud_id=0)
res = HostHandler.check(
Expand Down Expand Up @@ -56,3 +58,21 @@ def test_check(self):
key_list=[],
)
self.assertEqual(res[0]["ipv6"], "0000:0000:0000:0000:0000:ffff:7f00:0002")

@patch("apps.core.ipchooser.query.resource.CCApi", MockClient.cc)
@patch(
"apps.core.ipchooser.handlers.host_handler.get_gse_api_helper",
get_gse_api_helper(GseVersion.V2.value, GseApiMockClient()),
)
def test_details(self):
models.GlobalSettings.set_config(
key=models.GlobalSettings.KeyEnum.IP_CHOOSER_ENABLE_SHOW_REALTIME_AGENT_STATE.value, value=True
)
create_host(100)
res = HostHandler().details(
scope_list=[{"scope_type": "biz", "scope_id": f"{i}", "bk_biz_id": i} for i in range(27, 40)],
host_list=[{"host_id": 1, "meta": {"scope_type": "biz", "scope_id": "28", "bk_biz_id": 28}}],
show_agent_realtime_state=True,
)
self.assertEqual(res[0]["alive"], 1)
self.assertEqual(res[0]["bk_agent_alive"], 1)
4 changes: 3 additions & 1 deletion apps/core/ipchooser/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,8 @@ def check(self, request, *args, **kwargs):
def details(self, request, *args, **kwargs):
return Response(
host_handler.HostHandler.details(
scope_list=self.validated_data["scope_list"], host_list=self.validated_data["host_list"]
scope_list=self.validated_data["scope_list"],
host_list=self.validated_data["host_list"],
show_agent_realtime_state=self.validated_data["agent_realtime_state"],
)
)
2 changes: 2 additions & 0 deletions apps/node_man/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,8 @@ class KeyEnum(Enum):
PLUGIN_PROC_START_CHECK_SECS = "PLUGIN_PROC_START_CHECK_SECS"
# 查询服务实例时module_id阈值,当小于该阈值时以单module_id并发查询
SERVICE_INSTANCE_MODULE_ID_THRESHOLD = "SERVICE_INSTANCE_MODULE_ID_THRESHOLD"
# IP选择器详情接口是否实时展示agent状态
IP_CHOOSER_ENABLE_SHOW_REALTIME_AGENT_STATE = "IP_CHOOSER_ENABLE_SHOW_REALTIME_AGENT_STATE"

key = models.CharField(_("键"), max_length=255, db_index=True, primary_key=True)
v_json = JSONField(_("值"))
Expand Down

0 comments on commit 61782f6

Please sign in to comment.