diff --git a/apps/backend/subscription/steps/agent_adapter/config_context/context_helper.py b/apps/backend/subscription/steps/agent_adapter/config_context/context_helper.py index 7e355732b..9f80f5b12 100644 --- a/apps/backend/subscription/steps/agent_adapter/config_context/context_helper.py +++ b/apps/backend/subscription/steps/agent_adapter/config_context/context_helper.py @@ -99,8 +99,8 @@ def __post_init__(self): self.host.node_type == constants.NodeType.PROXY ], cloud_id=self.host.bk_cloud_id, - zone_id=self.ap.region_id, - city_id=self.ap.city_id, + zone_id=str(self.host.bk_idc_area_id or self.ap.region_id), + city_id=self.host.idc_city_id or self.ap.city_id, # 管控区域为0, 且使用到Proxy场景的Agent需要设置为true # 暂时不考虑当直连区域的安装通道机器并不是 Proxy 的场景 enable_static_access=["false", "true"][ diff --git a/apps/backend/subscription/steps/agent_adapter/legacy.py b/apps/backend/subscription/steps/agent_adapter/legacy.py index a9a1e4cc5..fe1078c50 100644 --- a/apps/backend/subscription/steps/agent_adapter/legacy.py +++ b/apps/backend/subscription/steps/agent_adapter/legacy.py @@ -607,8 +607,8 @@ def generate_gse_config( "inner_ip": host.inner_ip, "outer_ip": host.outer_ip, "proxy_servers": [host.inner_ip], - "region_id": ap.region_id, - "city_id": ap.city_id, + "region_id": str(host.bk_idc_area_id) or ap.region_id, + "city_id": host.idc_city_id or ap.city_id, "dataipc": dataipc, "peer_exchange_switch_for_agent": host.extra_data.get("peer_exchange_switch_for_agent", 0), "bt_speed_limit": host.extra_data.get("bt_speed_limit"), diff --git a/apps/backend/tests/subscription/agent_adapter/test_adapter.py b/apps/backend/tests/subscription/agent_adapter/test_adapter.py index 62f4b6013..8cb77beca 100644 --- a/apps/backend/tests/subscription/agent_adapter/test_adapter.py +++ b/apps/backend/tests/subscription/agent_adapter/test_adapter.py @@ -190,3 +190,25 @@ def test_get_config__extra_env(self): config: str = self.get_config(self.agent_step_adapter.get_main_config_filename()) self.assertTrue('"bind_ip": "::"' in config) self.assertTrue('"enable_compression": false' in config) + + +class Agent2GenerateConfigTestCase(Agent2StepAdapterTestCase): + @classmethod + def setUpTestData(cls): + super().setUpTestData() + + def test_get_config(self): + # 使用主机的区域ID和城市ID + self.host = models.Host.objects.get(bk_host_id=common_unit.host.DEFAULT_HOST_ID) + self.host.bk_idc_area_id = common_unit.host.DEFAULT_HOST_ID + self.host.idc_city_id = str(common_unit.host.DEFAULT_HOST_ID) + config: str = self.get_config(self.agent_step_adapter.get_main_config_filename()) + self.assertTrue('"zone_id": "1"' in config) + self.assertTrue('"city_id": "1"' in config) + + # 使用接入点的区域ID和城市ID + self.host.bk_idc_area_id = None + self.host.idc_city_id = "" + config: str = self.get_config(self.agent_step_adapter.get_main_config_filename()) + self.assertTrue('"zone_id": "test"' in config) + self.assertTrue('"city_id": "test"' in config) diff --git a/apps/node_man/constants.py b/apps/node_man/constants.py index 6d0d31868..5e6014949 100644 --- a/apps/node_man/constants.py +++ b/apps/node_man/constants.py @@ -696,6 +696,8 @@ class BkappRunEnvType(Enum): "bk_supplier_account", "bk_cpu_architecture", "dept_name", + "bk_idc_area_id", + "idc_city_id", ] # 限流窗口配置,用于控制CMDB订阅触发的变更频率 diff --git a/apps/node_man/migrations/0084_auto_20240930_1658.py b/apps/node_man/migrations/0084_auto_20240930_1658.py new file mode 100644 index 000000000..866376644 --- /dev/null +++ b/apps/node_man/migrations/0084_auto_20240930_1658.py @@ -0,0 +1,32 @@ +# -*- coding: utf-8 -*- +""" +TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-节点管理(BlueKing-BK-NODEMAN) available. +Copyright (C) 2017-2022 THL A29 Limited, a Tencent company. All rights reserved. +Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +You may obtain a copy of the License at https://opensource.org/licenses/MIT +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on +an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. +""" + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('node_man', '0083_subscription_operate_info'), + ] + + operations = [ + migrations.AddField( + model_name='host', + name='bk_idc_area_id', + field=models.IntegerField(db_index=True, null=True, verbose_name='区域ID'), + ), + migrations.AddField( + model_name='host', + name='idc_city_id', + field=models.CharField(blank=True, db_index=True, default='', max_length=16, null=True, verbose_name='城市ID'), + ), + ] diff --git a/apps/node_man/models.py b/apps/node_man/models.py index 7c9a84ddb..5e57afb32 100644 --- a/apps/node_man/models.py +++ b/apps/node_man/models.py @@ -269,6 +269,8 @@ class Host(models.Model): created_at = models.DateTimeField(_("创建时间"), auto_now_add=True, db_index=True) updated_at = models.DateTimeField(_("更新时间"), null=True, auto_now=False, db_index=True) dept_name = models.CharField(_("运维部门"), max_length=128, db_index=True, blank=True, null=True, default="") + bk_idc_area_id = models.IntegerField(_("区域ID"), null=True, db_index=True) + idc_city_id = models.CharField(_("城市ID"), max_length=16, db_index=True, blank=True, null=True, default="") extra_data = JSONField(_("额外数据"), blank=True, null=True) diff --git a/apps/node_man/periodic_tasks/sync_cmdb_host.py b/apps/node_man/periodic_tasks/sync_cmdb_host.py index b08c12b57..f0ba61dff 100644 --- a/apps/node_man/periodic_tasks/sync_cmdb_host.py +++ b/apps/node_man/periodic_tasks/sync_cmdb_host.py @@ -177,6 +177,8 @@ def _generate_host(biz_id, host, ap_id, is_os_type_priority=False, is_sync_cmdb_ else constants.NodeType.PAGENT, ap_id=ap_id, dept_name=host.get("dept_name", ""), + bk_idc_area_id=host.get("bk_idc_area_id"), + idc_city_id=host.get("idc_city_id", ""), ) identify_data = models.IdentityData( @@ -279,6 +281,8 @@ def update_or_create_host_base(biz_id, ap_map_config, is_gse2_gray, task_id, cmd "inner_ipv6": (host.get("bk_host_innerip_v6") or "").split(",")[0], "outer_ipv6": (host.get("bk_host_outerip_v6") or "").split(",")[0], "dept_name": host.get("dept_name", ""), + "bk_idc_area_id": host.get("bk_idc_area_id"), + "idc_city_id": host.get("idc_city_id", ""), } outer_ip = host.get("bk_host_outerip") or "" outer_ip_list = outer_ip.split(",") diff --git a/apps/node_man/tests/test_pericdic_tasks/test_sync_cmdb_host.py b/apps/node_man/tests/test_pericdic_tasks/test_sync_cmdb_host.py index c9920c7e1..732e737f5 100644 --- a/apps/node_man/tests/test_pericdic_tasks/test_sync_cmdb_host.py +++ b/apps/node_man/tests/test_pericdic_tasks/test_sync_cmdb_host.py @@ -9,6 +9,7 @@ specific language governing permissions and limitations under the License. """ import copy +import random from unittest.mock import patch from apps.backend.views import LPUSH_AND_EXPIRE_FUNC @@ -139,3 +140,28 @@ def test_sync_multi_outer_ip_host(self): for data in agent_extra_data: extra_data = data["extra_data"] self.assertEqual(extra_data.get("bk_host_multi_outerip"), None) + + +class TestSyncCMDBAreaIdAndCityId(CustomBaseTestCase): + @staticmethod + def list_biz_hosts(*args, **kwargs): + return_value = MockClient.cc.list_resource_pool_hosts(*args, **kwargs) + host_info = return_value["info"] + for host in host_info: + host["bk_idc_area_id"] = random.randint(1, 3) + host["idc_city_id"] = str(random.randint(20, 30)) + return return_value + + def start_patch(self): + MockClient.cc.list_biz_hosts = self.list_biz_hosts + + @patch("apps.node_man.periodic_tasks.sync_cmdb_host.client_v2", MockClient) + def test_sync_area_id_and_city_id(self): + self.start_patch() + sync_cmdb_host_periodic_task(bk_biz_id=2) + hosts = Host.objects.values("bk_idc_area_id", "idc_city_id") + bk_idc_area_ids = list(range(1, 4)) + idc_city_ids = [str(idc_city_id) for idc_city_id in range(20, 31)] + for host in hosts: + self.assertIn(host["bk_idc_area_id"], bk_idc_area_ids) + self.assertIn(host["idc_city_id"], idc_city_ids)