Skip to content

Commit

Permalink
fix(backend): SQLServer工具箱参数调整 #3630
Browse files Browse the repository at this point in the history
  • Loading branch information
iSecloud authored and zhangzhw8 committed Mar 21, 2024
1 parent bfc9034 commit 4d02a52
Show file tree
Hide file tree
Showing 13 changed files with 164 additions and 32 deletions.
5 changes: 1 addition & 4 deletions dbm-ui/backend/db_meta/models/spec.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
from backend.configuration.models import SystemSettings
from backend.constants import INT_MAX
from backend.db_meta.enums import ClusterType, MachineType
from backend.db_services.ipchooser.constants import BkOsType

logger = logging.getLogger("root")

Expand Down Expand Up @@ -64,7 +63,7 @@ def capacity(self):
"""
mount_point__size: Dict[str, int] = {disk["mount_point"]: disk["size"] for disk in self.storage_spec}
if self.spec_cluster_type == ClusterType.TenDBCluster:
return mount_point__size.get("data1") or mount_point__size["/data"] / 2
return mount_point__size.get("/data1") or mount_point__size["/data"] / 2

if self.spec_cluster_type in [
ClusterType.TwemproxyTendisSSDInstance,
Expand Down Expand Up @@ -115,8 +114,6 @@ def _get_apply_params_detail(
],
"count": count,
"affinity": affinity,
# TODO: 后续os_type字段是否需要存储到单个规格上,比如一个集群可能用到不同的操作系统?
"os_type": BkOsType.db_type_to_os_type(ClusterType.cluster_type_to_db_type(self.spec_cluster_type)),
}
if location_spec:
# 将bk_sub_zone_id转成str,本身为空也不影响
Expand Down
2 changes: 1 addition & 1 deletion dbm-ui/backend/db_services/dbbase/resources/query.py
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,7 @@ def _list_clusters(
"domain": Q(immute_domain__icontains=query_params.get("domain")),
"version": Q(major_version=query_params.get("version")),
"region": Q(region=query_params.get("region")),
"cluster_ids": Q(id__in=query_params.get("cluster_ids")),
"cluster_ids": Q(id__in=query_params.get("cluster_ids", "").split(",")),
"creator": Q(creator__icontains=query_params.get("creator")),
# 域名精确查询,主要用于工具箱手动填入域名查询
"exact_domain": Q(immute_domain=query_params.get("exact_domain")),
Expand Down
17 changes: 8 additions & 9 deletions dbm-ui/backend/db_services/dbbase/resources/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,14 @@


class ListResourceSLZ(serializers.Serializer):
id = serializers.IntegerField(required=False)
name = serializers.CharField(required=False)
ip = serializers.CharField(required=False)
domain = serializers.CharField(required=False)
creator = serializers.CharField(required=False)
version = serializers.CharField(required=False)
region = serializers.CharField(required=False)
cluster_ids = serializers.ListField(child=serializers.IntegerField(), required=False, allow_empty=True)
id = serializers.IntegerField(help_text=_("集群ID"), required=False)
name = serializers.CharField(help_text=_("集群名"), required=False)
ip = serializers.CharField(help_text=_("部署IP"), required=False)
domain = serializers.CharField(help_text=_("集群域名"), required=False)
creator = serializers.CharField(help_text=_("创建者"), required=False)
version = serializers.CharField(help_text=_("集群版本"), required=False)
region = serializers.CharField(help_text=_("部署地域"), required=False)
cluster_ids = serializers.CharField(help_text=_("集群ID批量查询(逗号分割)"), required=False)
exact_domain = serializers.CharField(help_text=_("精确域名查询"), required=False)


Expand All @@ -39,7 +39,6 @@ class ListMongoDBResourceSLZ(ListResourceSLZ):

class ListSQLServerResourceSLZ(ListResourceSLZ):
db_module_id = serializers.IntegerField(required=False)
cluster_ids = serializers.ListField(child=serializers.IntegerField(), required=False, allow_empty=True)


class ClusterSLZ(serializers.ModelSerializer):
Expand Down
59 changes: 47 additions & 12 deletions dbm-ui/backend/db_services/dbpermission/db_account/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
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 typing import Type, Union
from typing import Union

from django.utils.translation import ugettext as _
from rest_framework import status
Expand Down Expand Up @@ -38,7 +38,10 @@


class BaseDBAccountViewSet(viewsets.SystemViewSet):
account_type = None
account_type: str = None
account_meta: AccountMeta = AccountMeta
account_rule_meta: AccountRuleMeta = AccountRuleMeta
account_handler: AccountHandler = AccountHandler

@staticmethod
def instance_getter(request, view):
Expand All @@ -53,7 +56,7 @@ def _get_custom_permissions(self):
return [ResourceActionPermission([account_action], ResourceEnum.BUSINESS, self.instance_getter)]

def _view_common_handler(
self, request, bk_biz_id: int, meta: Union[Type[AccountMeta], Type[AccountRuleMeta]], func: str
self, request, bk_biz_id: int, meta: Union[AccountMeta, AccountRuleMeta], func: str
) -> Response:
"""
- 视图通用处理函数, 方便统一管理
Expand All @@ -70,35 +73,55 @@ def _view_common_handler(
"context": {},
}
meta_init_data = meta.from_dict(validated_data)
return Response(getattr(AccountHandler(**base_info), func)(meta_init_data))
return Response(getattr(self.account_handler(**base_info), func)(meta_init_data))

@common_swagger_auto_schema(
operation_summary=_("创建账号"), request_body=CreateAccountSerializer(), tags=[SWAGGER_TAG]
)
@action(methods=["POST"], detail=False, serializer_class=CreateAccountSerializer)
def create_account(self, request, bk_biz_id):
return self._view_common_handler(request, bk_biz_id, AccountMeta, AccountHandler.create_account.__name__)
return self._view_common_handler(
request=request,
bk_biz_id=bk_biz_id,
meta=self.account_meta,
func=self.account_handler.create_account.__name__,
)

@common_swagger_auto_schema(
operation_summary=_("删除账号"), request_body=DeleteAccountSerializer(), tags=[SWAGGER_TAG]
)
@action(methods=["DELETE"], detail=False, serializer_class=DeleteAccountSerializer)
def delete_account(self, request, bk_biz_id):
return self._view_common_handler(request, bk_biz_id, AccountMeta, AccountHandler.delete_account.__name__)
return self._view_common_handler(
request=request,
bk_biz_id=bk_biz_id,
meta=self.account_meta,
func=self.account_handler.delete_account.__name__,
)

@common_swagger_auto_schema(
operation_summary=_("修改密码"), request_body=UpdateAccountSerializer(), tags=[SWAGGER_TAG]
)
@action(methods=["POST"], detail=False, serializer_class=UpdateAccountSerializer)
def update_password(self, request, bk_biz_id):
return self._view_common_handler(request, bk_biz_id, AccountMeta, AccountHandler.update_password.__name__)
return self._view_common_handler(
request=request,
bk_biz_id=bk_biz_id,
meta=self.account_meta,
func=self.account_handler.update_password.__name__,
)

@common_swagger_auto_schema(
operation_summary=_("添加账号规则"), request_body=AddAccountRuleSerializer(), tags=[SWAGGER_TAG]
)
@action(methods=["POST"], detail=False, serializer_class=AddAccountRuleSerializer)
def add_account_rule(self, request, bk_biz_id):
return self._view_common_handler(request, bk_biz_id, AccountRuleMeta, AccountHandler.add_account_rule.__name__)
return self._view_common_handler(
request=request,
bk_biz_id=bk_biz_id,
meta=self.account_rule_meta,
func=self.account_handler.add_account_rule.__name__,
)

@common_swagger_auto_schema(
operation_summary=_("查询账号规则清单"),
Expand All @@ -109,7 +132,10 @@ def add_account_rule(self, request, bk_biz_id):
@action(methods=["GET"], detail=False, serializer_class=FilterAccountRulesSerializer)
def list_account_rules(self, request, bk_biz_id):
return self._view_common_handler(
request, bk_biz_id, AccountRuleMeta, AccountHandler.list_account_rules.__name__
request=request,
bk_biz_id=bk_biz_id,
meta=self.account_rule_meta,
func=self.account_handler.list_account_rules.__name__,
)

@common_swagger_auto_schema(
Expand All @@ -121,7 +147,10 @@ def list_account_rules(self, request, bk_biz_id):
@action(methods=["POST"], detail=False, serializer_class=QueryAccountRulesSerializer)
def query_account_rules(self, request, bk_biz_id):
return self._view_common_handler(
request, bk_biz_id, AccountRuleMeta, AccountHandler.query_account_rules.__name__
request=request,
bk_biz_id=bk_biz_id,
meta=self.account_rule_meta,
func=self.account_handler.query_account_rules.__name__,
)

@common_swagger_auto_schema(
Expand All @@ -130,7 +159,10 @@ def query_account_rules(self, request, bk_biz_id):
@action(methods=["POST"], detail=False, serializer_class=ModifyMySQLAccountRuleSerializer)
def modify_account_rule(self, request, bk_biz_id):
return self._view_common_handler(
request, bk_biz_id, AccountRuleMeta, AccountHandler.modify_account_rule.__name__
request=request,
bk_biz_id=bk_biz_id,
meta=self.account_rule_meta,
func=self.account_handler.modify_account_rule.__name__,
)

@common_swagger_auto_schema(
Expand All @@ -139,5 +171,8 @@ def modify_account_rule(self, request, bk_biz_id):
@action(methods=["DELETE"], detail=False, serializer_class=DeleteAccountRuleSerializer)
def delete_account_rule(self, request, bk_biz_id):
return self._view_common_handler(
request, bk_biz_id, AccountRuleMeta, AccountHandler.delete_account_rule.__name__
request=request,
bk_biz_id=bk_biz_id,
meta=self.account_rule_meta,
func=self.account_handler.delete_account_rule.__name__,
)
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,12 @@ def validate(self, attrs):
if not SqlserverDtsInfo.objects.filter(id=attrs["dts_id"]).count():
raise serializers.ValidationError(_("迁移记录{}不存在").format(attrs["dts_id"]))
return attrs


class QueryMigrateRecordsSerializer(serializers.Serializer):
cluster_name = serializers.CharField(help_text=_("集群名称"), required=False, default="")


class QueryMigrateRecordsResponseSerializer(serializers.Serializer):
class Meta:
swagger_schema_fields = {"example": []}
36 changes: 36 additions & 0 deletions dbm-ui/backend/db_services/sqlserver/data_migrate/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,26 @@
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.
"""
import itertools
from typing import Dict, List

from django.forms.models import model_to_dict
from django.utils.translation import ugettext as _
from rest_framework import status
from rest_framework.decorators import action
from rest_framework.response import Response

from backend.bk_web import viewsets
from backend.bk_web.swagger import common_swagger_auto_schema
from backend.db_meta.models import Cluster
from backend.db_meta.models.sqlserver_dts import SqlserverDtsInfo
from backend.db_services.sqlserver.data_migrate.handlers import SQLServerDataMigrateHandler
from backend.db_services.sqlserver.data_migrate.serializers import (
ForceFailedMigrateSerializer,
ManualTerminateSyncResponseSerializer,
ManualTerminateSyncSerializer,
QueryMigrateRecordsResponseSerializer,
QueryMigrateRecordsSerializer,
)
from backend.iam_app.handlers.drf_perm.base import DBManagePermission

Expand Down Expand Up @@ -52,3 +60,31 @@ def force_failed_migrate(self, request, *args, **kwargs):
data = self.params_validate(self.get_serializer_class())
SQLServerDataMigrateHandler.force_failed_migrate(dts_id=data["dts_id"])
return Response()

@common_swagger_auto_schema(
operation_summary=_("获取迁移记录"),
query_serializer=QueryMigrateRecordsSerializer(),
tags=[SWAGGER_TAG],
responses={status.HTTP_200_OK: QueryMigrateRecordsResponseSerializer()},
)
@action(methods=["GET"], detail=False, serializer_class=QueryMigrateRecordsSerializer)
def query_migrate_records(self, request, bk_biz_id):
data = self.params_validate(self.get_serializer_class())
# (不分页)获取全量的迁移记录
migrate_records = [model_to_dict(dts) for dts in SqlserverDtsInfo.objects.filter(bk_biz_id=bk_biz_id)]
cluster_tuple_ids = [[record["source_cluster_id"], record["target_cluster_id"]] for record in migrate_records]
clusters = Cluster.objects.filter(id__in=list(set(itertools.chain(*cluster_tuple_ids))))
cluster_id__cluster_domain = {cluster.id: cluster.immute_domain for cluster in clusters}
# 完善迁移记录信息
filter_migrate_records: List[Dict] = []
for record in migrate_records:
source_domain = cluster_id__cluster_domain[record["source_cluster_id"]]
target_domain = cluster_id__cluster_domain[record["target_cluster_id"]]
# 过滤集群域名
if data["cluster_name"] not in source_domain and data["cluster_name"] not in target_domain:
continue
filter_migrate_records.append(
{**record, "source_cluster_domain": source_domain, "target_cluster_domain": target_domain}
)

return Response(filter_migrate_records)
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,12 @@
"""

import logging
from typing import Any, Optional

from backend.components import DBPrivManagerApi
from backend.db_services.dbpermission.db_account.dataclass import AccountMeta
from backend.db_services.dbpermission.db_account.handlers import AccountHandler
from backend.flow.utils.sqlserver.sqlserver_db_function import create_sqlserver_login_sid

logger = logging.getLogger("root")

Expand All @@ -21,4 +25,19 @@ class SQLServerDBAccountHandler(AccountHandler):
封装账号相关的处理操作
"""

pass
def create_account(self, account: AccountMeta) -> Optional[Any]:
"""
- 新建一个账号, sqlserver需要sid
@param account: 账号元信息
"""
resp = DBPrivManagerApi.create_account(
{
"cluster_type": self.account_type,
"bk_biz_id": self.bk_biz_id,
"operator": self.operator,
"user": account.user,
"psw": account.password,
"sid": create_sqlserver_login_sid(),
}
)
return resp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@
"""
from backend.db_services.dbpermission.constants import AccountType
from backend.db_services.dbpermission.db_account.views import BaseDBAccountViewSet
from backend.db_services.sqlserver.permission.db_account.handlers import SQLServerDBAccountHandler


class DBAccountViewSet(BaseDBAccountViewSet):
account_type = AccountType.SQLServer
account_handler = SQLServerDBAccountHandler
16 changes: 14 additions & 2 deletions dbm-ui/backend/db_services/sqlserver/rollback/handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"""
from collections import defaultdict
from datetime import datetime, timedelta
from typing import Any, Dict, List
from typing import Any, Dict, List, Set

from django.utils.translation import ugettext as _

Expand Down Expand Up @@ -89,16 +89,28 @@ def query_backup_logs(self, start_time: datetime, end_time: datetime):
if log["data_schema_grant"] == "all":
backup_id__logs[log["backup_id"]].append(log)

# 对每一份备份记录去重,相同的backup id不能出现重复的dbname
backup_id__valid_logs: Dict[str, List] = defaultdict(list)
for backup_id, logs in backup_id__logs.items():
dbname_set: Set[str] = set()
for log in logs:
if log["dbname"] not in dbname_set:
backup_id__valid_logs[backup_id].append(log)
dbname_set.add(log["dbname"])

# 对每个聚合记录补充信息
backup_logs: List[Dict[str, Any]] = []
for backup_id, logs in backup_id__logs.items():
for backup_id, logs in backup_id__valid_logs.items():
start_time = min(map(str2datetime, [log["backup_begin_time"] for log in logs]))
end_time = max(map(str2datetime, [log["backup_end_time"] for log in logs]))
backup_log_info = {
"start_time": datetime2str(start_time),
"end_time": datetime2str(end_time),
"backup_id": backup_id,
"logs": logs,
"complete": len(logs) == logs[0]["file_cnt"],
"expected_cnt": logs[0]["file_cnt"],
"real_cnt": len(logs),
# 是否只取第一个log的角色就好了?
"role": logs[0]["role"],
}
Expand Down
2 changes: 1 addition & 1 deletion dbm-ui/backend/flow/utils/sqlserver/payload_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def get_sqlserver_drs_account(bk_cloud_id: int):
获取sqlserver在drs的admin账号密码
"""
if env.DRS_USERNAME:
return {"user": env.DRS_USERNAME, "pwd": env.DRS_PASSWORD}
return {"drs_user": env.DRS_USERNAME, "drs_pwd": env.DRS_PASSWORD}

bk_cloud_name = AsymmetricCipherConfigType.get_cipher_cloud_name(bk_cloud_id)
drs = DBExtension.get_latest_extension(bk_cloud_id=bk_cloud_id, extension_type=ExtensionType.DRS)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,9 @@ def insert_ip_into_apply_infos(cls, ticket_data, infos: List[Dict]):


class SQLServerHaApplyResourceParamBuilder(SQLServerSingleApplyResourceParamBuilder):
def format(self):
super().format()

def post_callback(self):
next_flow = self.ticket.next_flow()
infos = next_flow.details["ticket_data"]["infos"]
Expand Down
Loading

0 comments on commit 4d02a52

Please sign in to comment.