kylin-system-updater/backend/SystemUpdater/Core/DataMigration.py

401 lines
13 KiB
Python
Executable File

#!/usr/bin/python3
# -*- coding: utf-8 -*-
import os
import logging
import sqlite3
from operator import itemgetter
from gettext import gettext as _
from optparse import OptionParser
DB_UPDATER = "/var/cache/kylin-update-manager/kylin-update-manager.db"
DB_UPGRADE = "/var/cache/kylin-system-updater/kylin-system-updater.db"
VER_DB = "/usr/share/kylin-system-updater/kylin-system-updater.db"
def dateMigration(options=None, old_db=None, old_db_cursor=None, new_db=None, new_db_cursor=None):
print(_("Loading Sqlite3Server..."))
if options==None:
old_path = DB_UPDATER
new_path = DB_UPGRADE
try:
if old_db==None and old_db_cursor==None:
old_db = sqlite3.connect(old_path, check_same_thread=False)
old_db_cursor = old_db.cursor()
if new_db==None and new_db_cursor==None:
new_db = sqlite3.connect(new_path, check_same_thread=False)
new_db_cursor = new_db.cursor()
except Exception as e:
print(e)
sql_commnd = ""
old_cfg_dict = {}
new_cfg_dict = {}
# step 1: 更新旧配置数据
try:
print("更新旧配置数据")
sql_commnd = "SELECT * FROM display where id=1"
old_db_cursor.execute(sql_commnd)
old_cfg = old_db_cursor.fetchone()
for od in old_db_cursor.description:
old_cfg_dict.update({str(od[0]):old_cfg[old_db_cursor.description.index(od)]})
new_db_cursor.execute(sql_commnd)
new_cfg = new_db_cursor.fetchone()
for od in new_db_cursor.description:
new_cfg_dict.update({str(od[0]):new_cfg[new_db_cursor.description.index(od)]})
if "download_limit" in new_cfg_dict.keys() and "download_limit_value" in new_cfg_dict.keys():
if new_cfg_dict['download_limit'] != None or new_cfg_dict['download_limit_value'] != None:
print("目标数据库有更新的配置项")
else:
sql_commnd = "UPDATE display set check_time='"+old_cfg_dict['check_time']+"' Where id=1"
new_db_cursor.execute(sql_commnd)
new_db.commit()
sql_commnd = "UPDATE display set update_time='"+old_cfg_dict['update_time']+"' Where id=1"
new_db_cursor.execute(sql_commnd)
new_db.commit()
sql_commnd = "UPDATE display set auto_check='"+old_cfg_dict['auto_check']+"' Where id=1"
new_db_cursor.execute(sql_commnd)
new_db.commit()
sql_commnd = "UPDATE display set system_version='"+old_cfg_dict['system_version']+"' Where id=1"
new_db_cursor.execute(sql_commnd)
new_db.commit()
if old_cfg_dict['auto_backup'] != None:
sql_commnd = "UPDATE display set auto_backup='"+old_cfg_dict['auto_backup']+"' Where id=1"
new_db_cursor.execute(sql_commnd)
new_db.commit()
if 'download_limit' in old_cfg_dict.keys() and old_cfg_dict['download_limit'] != None:
sql_commnd = "UPDATE display set download_limit='"+old_cfg_dict['download_limit']+"' Where id=1"
new_db_cursor.execute(sql_commnd)
new_db.commit()
if 'download_limit_value' in old_cfg_dict.keys() and old_cfg_dict['download_limit_value'] != None:
sql_commnd = "UPDATE display set download_limit_value='"+old_cfg_dict['download_limit_value']+"' Where id=1"
new_db_cursor.execute(sql_commnd)
new_db.commit()
except Exception as e:
print(e)
print("更新配置文件错误")
return
# step 2: 更新installed
try:
print("更新installed")
update_record_dict = {}
tmp_update_record_dict = []
sql_commnd = "SELECT * FROM installed"
old_db_cursor.execute(sql_commnd)
update_record = old_db_cursor.fetchall()
sql_commnd = "SELECT * FROM updateinfos"
new_db_cursor.execute(sql_commnd)
new_update_record = new_db_cursor.fetchall()
for ur in update_record:
id,appname,version,time,description,icon,statue,keyword,errorcode = ur
if errorcode in range(200):
errorcode = 'null'
update_record_dict.clear()
update_record_dict.update({"appname":appname})
update_record_dict.update({"version":version})
update_record_dict.update({"time":time})
update_record_dict.update({"description":description})
update_record_dict.update({"icon":icon})
update_record_dict.update({"statue":statue})
update_record_dict.update({"keyword":'1'})
update_record_dict.update({"errorcode":errorcode})
tmp_update_record_dict.append(update_record_dict.copy())
for ur in new_update_record:
id,appname,version,description,date,status,keyword,errorcode = ur
if errorcode in range(200):
errorcode = 'null'
update_record_dict.clear()
update_record_dict.update({"appname":appname})
update_record_dict.update({"version":version})
update_record_dict.update({"time":date})
update_record_dict.update({"description":description})
update_record_dict.update({"icon":None})
update_record_dict.update({"statue":status})
update_record_dict.update({"keyword":'1'})
update_record_dict.update({"errorcode":errorcode})
tmp_update_record_dict.append(update_record_dict.copy())
# 按时间排序
tmp_update_record_dict = sorted(tmp_update_record_dict, key=itemgetter('time'))
print("更新installed success")
except Exception as e:
print(e)
print("更新安装记录错误")
return
try:
# 删除 tmp
# DeleteTable(options.new_path+':'+'tmp')
# 创建表
sql_commnd = "create table IF NOT EXISTS tmp('id' INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,\
'appname' TEXT,\
'version' TEXT,\
'description' TEXT,\
'date' TEXT,\
'status' TEXT,\
'keyword' TEXT,\
'errorcode' TEXT) "
new_db_cursor.execute(sql_commnd)
# 更新数据
for urd in tmp_update_record_dict:
new_db_cursor.execute(
"insert into tmp (appname, version, description, date, status, keyword, errorcode) values(?,"
"?,?,?,?,?,?)",
(urd['appname'], urd['version'], urd['description'], urd['time'], urd['statue'], urd['keyword'], urd['errorcode']))
new_db.commit()
# 删除updateinfos
sql_commnd = "drop table updateinfos"
new_db_cursor.execute(sql_commnd)
new_db.commit()
# 修改表名
sql_commnd = "alter table tmp rename to updateinfos"
new_db_cursor.execute(sql_commnd)
new_db.commit()
except Exception as e:
print(e)
print("安装记录迁移错误")
return
print("数据迁移成功.")
def CleanTable(db_table):
db_path, table_name = str(db_table).split(":")
if not os.path.isfile(db_path):
print("db path error.")
exit(-1)
print(_("Loading Sqlite3Server..."))
try:
db = sqlite3.connect(db_path, check_same_thread=False)
db_cursor = db.cursor()
sql_commnd = 'delete from '+table_name
db_cursor.execute(sql_commnd)
db.commit()
print("clean %s success."%table_name)
except Exception as e:
print(e)
print("clean %s error."%table_name)
def DeleteTable(db_table):
db_path, table_name = str(db_table).split(":")
if not os.path.isfile(db_path):
print("db path error.")
exit(-1)
print(_("Loading Sqlite3Server..."))
try:
db = sqlite3.connect(db_path, check_same_thread=False)
db_cursor = db.cursor()
sql_commnd = 'drop table '+table_name
db_cursor.execute(sql_commnd)
db.commit()
print("delete %s success."%table_name)
except Exception as e:
print("delete %s error: %s"%(table_name,e))
def _has_first_migration(new_db, new_db_cursor):
try:
sql_commnd = "select * from sqlite_master where type='table' and name='display';"
new_db_cursor.execute(sql_commnd)
retval = new_db_cursor.fetchone()
for rv in retval:
if "firstmigration" in str(rv):
return True
except Exception as e:
print(e)
return False
def _is_first_migration(new_db, new_db_cursor):
try:
sql_commnd = "select firstmigration from display;"
new_db_cursor.execute(sql_commnd)
retval = new_db_cursor.fetchone()
if "yes" in retval:
return True
else :
return False
except Exception as e:
print(e)
return False
def _is_display_exist_fields(field, db, db_cursor):
try:
sql_commnd = "select * from sqlite_master where type='table' and name='display';"
db_cursor.execute(sql_commnd)
retval = db_cursor.fetchone()
for rv in retval:
if field in str(rv):
return True
except Exception as e:
print(e)
return False
return False
def _is_updateinfos_exist_fields(field, db, db_cursor):
try:
sql_commnd = "select * from sqlite_master where type='table' and name='updateinfos';"
db_cursor.execute(sql_commnd)
retval = db_cursor.fetchone()
for rv in retval:
if field in str(rv):
return True
except Exception as e:
print(e)
return False
return False
def _add_display_fields(fields_default, default_table = True):
try:
if "=" not in fields_default:
print("format: field=value")
return False
field, value = fields_default.split('=')
# print(_("Loading Sqlite3Server..."))
db = sqlite3.connect(DB_UPGRADE, check_same_thread=False)
db_cursor = db.cursor()
if default_table:
if _is_display_exist_fields(field, db, db_cursor):
print("field %s is exist."%field)
return False
# 字段不存在,新增字段
sql_commnd = "alter table display add column "+field+" TEXT;"
db_cursor.execute(sql_commnd)
sql_commnd = "UPDATE display SET "+field+"='"+value+"'"
db_cursor.execute(sql_commnd)
db.commit()
else:
if _is_updateinfos_exist_fields(field, db, db_cursor):
print("field %s is exist."%field)
return False
# 字段不存在,新增字段
sql_commnd = "alter table updateinfos add column "+field+" TEXT;"
db_cursor.execute(sql_commnd)
db.commit()
except Exception as e:
print(e)
return False
print("Succeeded in adding field: '%s' "%field)
return True
def _add_new_table(table):
table = str(table).strip()
if "=" not in table:
return False
opt, fields = table.split('=')
try:
if fields == 'tid_search':
db = sqlite3.connect(DB_UPGRADE, check_same_thread=False)
db_cursor = db.cursor()
sql_commnd = "create table IF NOT EXISTS tid_search('id' INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,\
'key' TEXT,\
'tid' TEXT) "
db_cursor.execute(sql_commnd)
db.commit()
db.close()
except Exception as e:
print(e)
return False
def CopyData():
try:
# 判断新字段是否存在
if (os.path.exists(VER_DB) and os.path.exists(DB_UPGRADE)):
print(_("Loading Sqlite3Server..."))
try:
new_db = sqlite3.connect(DB_UPGRADE, check_same_thread=False)
new_db_cursor = new_db.cursor()
ver_db = sqlite3.connect(VER_DB, check_same_thread=False)
ver_db_cursor = ver_db.cursor()
except Exception as e:
print(e)
if (_has_first_migration(new_db, new_db_cursor)): # 存在 firstmigration
if (_is_first_migration(new_db, new_db_cursor)):
# 数据迁移
dateMigration(new_db=new_db, new_db_cursor=new_db_cursor)
sql_commnd = "UPDATE display SET firstmigration='false';"
new_db_cursor.execute(sql_commnd)
new_db.commit()
else:
print("No data migration is required ...")
else:# 不存在firstmigration
# 新增 firstmigration 字段
sql_commnd = "alter table display add column firstmigration text;"
new_db_cursor.execute(sql_commnd)
sql_commnd = "UPDATE display SET firstmigration='true';"
new_db_cursor.execute(sql_commnd)
#数据迁移
dateMigration(new_db=new_db, new_db_cursor=new_db_cursor)
sql_commnd = "UPDATE display SET firstmigration='false';"
new_db_cursor.execute(sql_commnd)
new_db.commit()
else :
print("Not found kylin-system-updater.db, ensure that \'kylin-system-updater\' is successfully installed ... ")
exit(-1)
except Exception as e:
print(e)
if __name__ == "__main__":
# Begin parsing of options
parser = OptionParser()
parser.add_option ("-d", "--debug", action="store_true", default=False,
help=_("Show debug messages"))
parser.add_option ("-o", "--old-path", dest="old_path",
help=_("Enter the old database address"))
parser.add_option ("-n", "--new-path", dest="new_path",
help=_("Enter the new database address"))
parser.add_option ("-c", "--clean-table", dest="clean_table",
help=_("Clear the table"))
parser.add_option ("-r", "--delete-table", dest="delete_table",
help=_("Delete the table"))
parser.add_option ("-m", "--data-migration", default=False, action="store_true",
dest="data_migration", help=_("data migration"))
parser.add_option ("-f", "--add-display-fields",
dest="add_display_fields", help=_("add display fields"))
parser.add_option ("-u", "--add-updateinfos-fields",
dest="add_updateinfos_fields", help=_("add updateinfos fields"))
parser.add_option ("-t", "--add-new-table",
dest="add_new_table", help=_("add new table"))
(options, args) = parser.parse_args()
if options.clean_table:
if ":" not in options.clean_table:
print("format error: <database:table>")
else:
CleanTable(str(options.clean_table))
if options.delete_table:
if ":" not in options.delete_table:
print("format error: <database:table>")
else:
DeleteTable(str(options.delete_table))
if options.add_display_fields:
_add_display_fields(str(options.add_display_fields))
if options.add_updateinfos_fields:
_add_display_fields(str(options.add_updateinfos_fields), default_table = False)
if options.add_new_table:
_add_new_table(str(options.add_new_table))
if options.data_migration:
CopyData()
exit(0)
if options.old_path or options.new_path:
# 检查文件
if not options.old_path or not options.new_path:
print("parameter error")
exit(-1)
if not os.path.isfile(options.old_path):
print("The source database file does not exist")
exit(-1)
if not os.path.isfile(options.new_path):
print("The destination database file does not exist")
exit(-1)
dateMigration(options)