From ce0b4a501a183e45582e38c3602e803eecf11667 Mon Sep 17 00:00:00 2001 From: RogerWork Date: Thu, 11 Jan 2024 18:28:46 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8F=90=E4=BA=A4=E4=B8=80=E4=B8=AA=E5=8F=AF?= =?UTF-8?q?=E7=94=A8=E7=9A=84=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../migrations/0016_updatecommand_is_force.py | 18 +++++ .../0017_alter_updatecommand_options.py | 17 +++++ .../0018_alter_updatecommand_options.py | 17 +++++ update/models.py | 4 +- update/serializers.py | 3 +- update/urls.py | 6 +- update/utils/client_util.py | 48 +++++++------ update/utils/cmd_extcute.py | 69 ++++++++++--------- update/utils/db_compare.py | 15 +++- update/views.py | 47 +++++++++++-- 10 files changed, 180 insertions(+), 64 deletions(-) create mode 100644 update/migrations/0016_updatecommand_is_force.py create mode 100644 update/migrations/0017_alter_updatecommand_options.py create mode 100644 update/migrations/0018_alter_updatecommand_options.py diff --git a/update/migrations/0016_updatecommand_is_force.py b/update/migrations/0016_updatecommand_is_force.py new file mode 100644 index 0000000..6522736 --- /dev/null +++ b/update/migrations/0016_updatecommand_is_force.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2.7 on 2024-01-11 06:45 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('update', '0015_rename_version_release_release_and_more'), + ] + + operations = [ + migrations.AddField( + model_name='updatecommand', + name='is_force', + field=models.BooleanField(default=False, help_text='必选项', verbose_name='必选项'), + ), + ] diff --git a/update/migrations/0017_alter_updatecommand_options.py b/update/migrations/0017_alter_updatecommand_options.py new file mode 100644 index 0000000..28816da --- /dev/null +++ b/update/migrations/0017_alter_updatecommand_options.py @@ -0,0 +1,17 @@ +# Generated by Django 4.2.7 on 2024-01-11 07:19 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('update', '0016_updatecommand_is_force'), + ] + + operations = [ + migrations.AlterModelOptions( + name='updatecommand', + options={'ordering': ['id', 'desc', 'command', 'ver_id', 'process', 'run_num', 'is_sys', 'is_checked', 'is_force', 'is_delete', 'update_time'], 'verbose_name': '升级脚本', 'verbose_name_plural': '升级脚本'}, + ), + ] diff --git a/update/migrations/0018_alter_updatecommand_options.py b/update/migrations/0018_alter_updatecommand_options.py new file mode 100644 index 0000000..0dfc23f --- /dev/null +++ b/update/migrations/0018_alter_updatecommand_options.py @@ -0,0 +1,17 @@ +# Generated by Django 4.2.7 on 2024-01-11 07:24 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('update', '0017_alter_updatecommand_options'), + ] + + operations = [ + migrations.AlterModelOptions( + name='updatecommand', + options={'verbose_name': '升级脚本', 'verbose_name_plural': '升级脚本'}, + ), + ] diff --git a/update/models.py b/update/models.py index d7c687a..94f9be5 100644 --- a/update/models.py +++ b/update/models.py @@ -97,12 +97,14 @@ class UpdateCommand(BaseModels): id = models.AutoField(primary_key=True) desc = models.CharField(verbose_name='命令作用描述', max_length=200, null=False, help_text='命令作用描述') command = models.CharField(verbose_name='需执行的命令', max_length=2000, null=False, help_text='需执行的命令') - ver_id = models.IntegerField(verbose_name='支持此命令的版本id', null=False, default=0, help_text='支持此命令的版本id') + ver_id = models.IntegerField(verbose_name='支持此命令的版本id', null=False, default=0, + help_text='支持此命令的版本id') process = models.CharField(verbose_name='执行顺序', max_length=20, default='setup', help_text='执行顺序 setup 对比数据库前执行 teardown 对比数据库后执行') run_num = models.IntegerField(verbose_name='执行命令的顺', null=False, default=0, help_text='执行命令的顺') is_sys = models.BooleanField(verbose_name='系统命令', default=False, help_text='系统命令,默认执行前台不展示') is_checked = models.BooleanField(verbose_name='默认勾选', default=False, help_text='前台页面默认是否勾选') + is_force = models.BooleanField(verbose_name='必选项', default=False, help_text='必选项') is_delete = models.BooleanField(verbose_name='是否有效', default=True, help_text='是否有效') def __str__(self): diff --git a/update/serializers.py b/update/serializers.py index 2198946..732965e 100644 --- a/update/serializers.py +++ b/update/serializers.py @@ -40,4 +40,5 @@ class UpdateCommandSerializer(serializers.ModelSerializer): class Meta: model = UpdateCommand fields = ( - 'id', 'desc', 'command', 'ver_id', 'process', 'run_num', 'is_sys', 'is_checked', 'is_delete', 'update_time') + 'id', 'desc', 'command', 'ver_id', 'process', 'run_num', 'is_sys', 'is_checked', 'is_force', 'is_delete', + 'update_time') diff --git a/update/urls.py b/update/urls.py index f065874..263ae16 100644 --- a/update/urls.py +++ b/update/urls.py @@ -32,7 +32,11 @@ urlpatterns = [ # 测试用的接口 path('test/write_git_version_to_db/', write_git_version_to_db), path('test/write_cine_sql/', write_cine_sql), - path('test/db_compare/', compare_db_structor) + path('test/db_compare/', compare_db_structor), + path('test/get_cmd/', get_cmd), + path('test/setup_cmd/', setup_cmd), + path('test/teardown_cmd/', teardown_cmd), + path('test/get_client/', get_client) ] # &version=(?P[\S]*?) diff --git a/update/utils/client_util.py b/update/utils/client_util.py index ae405d1..5e86dbf 100644 --- a/update/utils/client_util.py +++ b/update/utils/client_util.py @@ -4,65 +4,73 @@ from smb.SMBConnection import SMBConnection from update.models import ClientRelease, Cinema import pymysql from pymysql.cursors import DictCursor +from dingxin_toolbox_drf.settings import BASE_DIR class ClientUtil: def __init__(self): self.smb_conn = SMBConnection('admin', 'admin', '', '', use_ntlm_v2=True) self.smb_host = '172.16.3.68' + self.local_path = os.path.join(BASE_DIR, 'dx', 'client') def get_test_client_file(self): self.smb_conn.connect(self.smb_host, 445) smb_files = self.smb_conn.listPath('data1', '/客户端/测试专用', pattern=r'client_v2.033*.7z') for file in smb_files: - if ClientRelease.objects.filter(origin_name=file).first(): + file_name = file.filename + print(file_name) + if ClientRelease.objects.filter(origin_name=file_name).first(): continue - local_file = open(rf'../../dx/client/{file}', 'wb') + local_file = open(os.path.join(self.local_path, file_name), 'wb') # 接收文件并写入本地文件 - self.smb_conn.retrieveFile('data1', rf'/客户端/测试专用/{file}', local_file) + self.smb_conn.retrieveFile('data1', rf'/客户端/测试专用/{file_name}', local_file) # 关闭本地文件 local_file.close() - self.write_db(file) + self.write_db(file_name, 'test') self.smb_conn.close() - return smb_files + # return smb_files def get_prd_client_file(self): self.smb_conn.connect(self.smb_host, 445) prd_smb_files = self.smb_conn.listPath('data1', '/客户端/结测常用客户端', pattern=r'client_v2.033*.7z') for file in prd_smb_files: - if ClientRelease.objects.filter(origin_name=file).first(): + file_name = file.filename + print(file_name) + if ClientRelease.objects.filter(origin_name=file_name).first(): continue - local_file = open(rf'../../dx/client/{file}', 'wb') + local_file = open(os.path.join(self.local_path, file_name), 'wb') # 接收文件并写入本地文件 - self.smb_conn.retrieveFile('data1', rf'/客户端/结测常用客户端/{file}', local_file) + self.smb_conn.retrieveFile('data1', rf'/客户端/结测常用客户端/{file_name}', local_file) # 关闭本地文件 local_file.close() - self.write_db(file) + self.write_db(file_name, 'prd') history_smb_files = self.smb_conn.listPath('data1', '/客户端/结测常用客户端/历史客户端', pattern=r'client_v2.033*.7z') for file in history_smb_files: - if ClientRelease.objects.filter(origin_name=file).first(): + file_name = file.filename + print(file_name) + if ClientRelease.objects.filter(origin_name=file_name).first(): continue - local_file = open(rf'../../dx/client/{file}', 'wb') + local_file = open(os.path.join(self.local_path, file_name), 'wb') # 接收文件并写入本地文件 - self.smb_conn.retrieveFile('data1', rf'/客户端/结测常用客户端/历史客户端/{file}', local_file) + self.smb_conn.retrieveFile('data1', rf'/客户端/结测常用客户端/历史客户端/{file_name}', local_file) # 关闭本地文件 local_file.close() - self.write_db(file) + self.write_db(file_name, 'prd') self.smb_conn.close() - return prd_smb_files + history_smb_files @staticmethod - def write_db(_file): + def write_db(_file, _type): # 写入数据库 - client_ver = _file[8:23] + origin_name = _file main_ver = _file[8:18] sub_ver = _file[19:23] - upload_ver = _file[:23] + '.7z' - _type = 'prd' - ClientRelease.objects.update(origin_name=_file, client_ver=client_ver, main_ver=main_ver, sub_ver=sub_ver, - upload_ver=upload_ver, client_type=_type) + upload_name = _file[:23] + '.7z' + client_ver = _file[8:23] + ver_id = int(_file[14:18]) + ClientRelease.objects.create(origin_name=origin_name, main_ver=main_ver, sub_ver=sub_ver, + upload_name=upload_name, client_type=_type, client_ver=client_ver, ver_id=ver_id) def update_client_file(self): prd_clients = self.get_prd_client_file() diff --git a/update/utils/cmd_extcute.py b/update/utils/cmd_extcute.py index e653b2a..af397d4 100644 --- a/update/utils/cmd_extcute.py +++ b/update/utils/cmd_extcute.py @@ -1,11 +1,15 @@ +import time + import paramiko from update.models import UpdateCommand from django.db.models import Q +from time import sleep class UpdateCommandUtil: def __init__(self): self.client = paramiko.SSHClient() + self.channel = None self.model = UpdateCommand def connect(self, cinema_ip): @@ -29,55 +33,54 @@ class UpdateCommandUtil: return self.model.objects.filter(Q(is_delete=False) & Q(is_sys=False) & Q(process='setup')).order_by('id').all() def get_no_sys_teardown_cmd(self): - return self.model.objects.filter(Q(is_delete=False) & Q(is_sys=False) & Q(process='teardown')).order_by('id').all() + return self.model.objects.filter(Q(is_delete=False) & Q(is_sys=False) & Q(process='teardown')).order_by( + 'id').all() + + def get_no_sys_sql_cmd(self): + return self.model.objects.filter(Q(is_delete=False) & Q(is_sys=False) & Q(process='sql')).order_by('id').all() + + def get_no_sys_client_cmd(self): + return self.model.objects.filter(Q(is_delete=False) & Q(is_sys=False) & Q(process='client')).order_by( + 'id').all() def get_checked_cmd(self, cmd_list): sys_result = self.get_sys_cmd() checked_setup_result = self.model.objects.filter( - Q(is_delete='0') & Q(id__in=cmd_list) & Q(process='setup')).order_by('id').all() + Q(is_delete='0') & Q(id__in=cmd_list) & Q(process='setup')).order_by('run_num').all() checked_teardown_result = self.model.objects.filter( - Q(is_delete='0') & Q(id__in=cmd_list) & Q(process='teardown')).order_by( - id).all() - sys_cmd = [sys['command'] for sys in sys_result] - checked_setup_cmd = [setup['command'] for setup in checked_setup_result] - checked_teardown_cmd = [teardown['command'] for teardown in checked_teardown_result] + Q(is_delete='0') & Q(id__in=cmd_list) & Q(process='teardown')).order_by('run_num').all() + sys_cmd = [sys.command for sys in sys_result] + checked_setup_cmd = [setup.command for setup in checked_setup_result] + checked_teardown_cmd = [teardown.command for teardown in checked_teardown_result] return {'sys': sys_cmd, 'setup': checked_setup_cmd, 'teardown': checked_teardown_cmd} - def exec_cmd(self, _exec_cmd_list): - self.connect() + def exec_cmd(self, cinema_ip, _exec_cmd_list): + self.connect(cinema_ip) for exec_cmd in _exec_cmd_list: + print(exec_cmd) stdin, stdout, stderr = self.client.exec_command(exec_cmd) print(stdout.read().decode('utf-8')) + print(stderr.read().decode('utf-8')) self.disconnect() - def exec_setup_cmd(self, cmd_list, _release): - exec_cmd_list = [] - exec_cmd_data = self.get_checked_cmd(cmd_list) - setup_cmd = exec_cmd_data['sys'] + exec_cmd_data['setup'] - for cmd in setup_cmd: - if '' in cmd: - cmd = cmd.replace('', _release) - exec_cmd_list.append(cmd) - elif cmd.startswith(''): - cmd = cmd.replace('', _release) - for c in cmd.split('###'): - exec_cmd_list.append(c) - else: - exec_cmd_list.append(cmd) - self.exec_cmd(exec_cmd_list) - - def exec_teardown_cmd(self, cmd_list, _release): + def exec_cmd_by_type(self, cinema_ip, _type, cmd_list, short_release): + print(cinema_ip, _type, cmd_list, short_release) exec_cmd_list = [] exec_cmd_data = self.get_checked_cmd(cmd_list) - teardown_cmd = exec_cmd_data['teardown'] - for cmd in teardown_cmd: - if '' in cmd: - cmd = cmd.replace('', _release) + if _type == 'setup': + cmds = exec_cmd_data['sys'] + exec_cmd_data['setup'] + elif _type == 'teardown': + cmds = exec_cmd_data['teardown'] + else: + cmds = exec_cmd_data['sys'] + for cmd in cmds: + if '' in cmd: + cmd = cmd.replace('', short_release) exec_cmd_list.append(cmd) elif cmd.startswith(''): - cmd = cmd.replace('', _release) - for c in cmd.split('###'): + cmd = cmd.replace('', '') + for c in cmd.split('|||'): exec_cmd_list.append(c) else: exec_cmd_list.append(cmd) - self.exec_cmd(exec_cmd_list) + self.exec_cmd(cinema_ip, exec_cmd_list) diff --git a/update/utils/db_compare.py b/update/utils/db_compare.py index 3ce4128..5108ca3 100644 --- a/update/utils/db_compare.py +++ b/update/utils/db_compare.py @@ -55,6 +55,7 @@ class DbCompare: sql_list = [] temp = [] alter = 0 + alter_definer = 0 for line in f.readlines(): if line.strip().startswith('ALTER TABLE'): temp.append(line) @@ -63,14 +64,21 @@ class DbCompare: pass elif line.strip().startswith('DROP COLUMN'): pass + elif line.strip().startswith('[PASS]'): + pass + elif line.strip().startswith('ALTER DEFINER'): + temp.append(line) + alter_definer = 1 elif line.strip() == '': - if len(temp) > 1: + if len(temp) > 1 and alter_definer == 0: sql_list.extend(temp) + if alter_definer == 1: + alter_definer = 0 sql_list.extend('\n') temp = [] alter = 0 else: - if alter == 1: + if alter == 1 or alter_definer == 1: temp.append(line) else: sql_list.append(line) @@ -110,8 +118,9 @@ class DbCompare: # 执行差异 def exec_diff_sql(self): self.gen_diff_file() + self.remove_drop() self.gen_create_file() - diff_cmd = f'mysql -h{self.target_server} -P{self.target_port} -u{self.target_user} -p{self.target_pwd} < {self.diff_sql_path}' + diff_cmd = f'mysql -h{self.target_server} -P{self.target_port} -u{self.target_user} -p{self.target_pwd} < {self.clear_diff_sql_path}' create_cmd = f'mysql -h{self.target_server} -P{self.target_port} -u{self.target_user} -p{self.target_pwd} < {self.create_sql_path}' diff_result = os.system(diff_cmd) print(diff_result) diff --git a/update/views.py b/update/views.py index 2b74f08..ed2d0bf 100644 --- a/update/views.py +++ b/update/views.py @@ -17,6 +17,7 @@ from rest_framework.decorators import action from update.utils.git_util import GitUtil from update.utils.cmd_extcute import UpdateCommandUtil from update.utils.db_compare import DbCompare +from update.utils.client_util import ClientUtil # CacheResponseMixin 一定要放第一位 @@ -85,14 +86,50 @@ def write_git_version_to_db(request): def write_cine_sql(request): - git_util = GitUtil('2.0.33.0333_Release') + git_util = GitUtil('2.0.33.0338_Release') git_util.handle_create_cine() return JsonResponse({'result': 'success'}) def compare_db_structor(request): - db_compare = DbCompare('172.16.3.205', '2.0.33.0338_Release') - db_compare.gen_diff_file() - db_compare.remove_drop() - db_compare.gen_create_file() + db_compare = DbCompare('172.16.3.88', '2.0.33.0338_Release') + # db_compare.gen_diff_file() + # db_compare.remove_drop() + # db_compare.gen_create_file() + db_compare.exec_diff_sql() + return JsonResponse({'result': 'success'}) + + +def get_cmd(request): + update_cmd = UpdateCommandUtil() + update_cmd.connect('172.16.3.112') + update_cmd.disconnect() + # cmd = update_cmd.get_all_cmd() + # cmd_ser = UpdateCommandSerializer(instance=cmd, many=True) + # return JsonResponse(data=cmd_ser.data, safe=False) + cmd_list = [10, 12, 13, 14, 15, 17, 19, 20] + r = update_cmd.get_checked_cmd(cmd_list) + print(r) + return JsonResponse({'result': 'success'}) + + +def setup_cmd(request): + update_cmd = UpdateCommandUtil() + cmd_list = [10, 11, 12, 13, 14, 15, 16, 17, 19, 20] + # exec_cmd_data = update_cmd.get_checked_cmd(cmd_list) + update_cmd.exec_cmd_by_type('172.16.3.88', 'setup', cmd_list, '2.0.33.0338_Release') + return JsonResponse({'result': 'success'}) + + +def teardown_cmd(request): + update_cmd = UpdateCommandUtil() + cmd_list = [10, 11, 12, 13, 14, 15, 16, 17, 19, 20] + # exec_cmd_data = update_cmd.get_checked_cmd(cmd_list) + update_cmd.exec_cmd_by_type('172.16.3.88', 'teardown', cmd_list, '2.0.33.0338_Release') + return JsonResponse({'result': 'success'}) + + +def get_client(request): + client_release = ClientUtil() + client_release.get_test_client_file() return JsonResponse({'result': 'success'})