提交 14a4da77 编写于 作者: Y Yiru Wang Mac

add querying install depend function

上级 14251b69
'''
Querying for install dependencies
Querying packages install depend for those package can be installed
'''
from packageship.libs.log import Log
from .searchdb import SearchDB
from .constants import ResponseCode
from .constants import ListNode
LOGGER = Log(__name__)
class InstallDepend():
'''
Description: quert install depend of package
changeLog:
'''
def __init__(self, db_list):
'''
:param db_list: A list of Database name to show the priority
'''
self.binary_dict = DictionaryOperations()
self.search_list = []
self.db_list = db_list
self.search_db = SearchDB(db_list)
def install_depend_result(self, binary_list, history_dicts=None):
'''
Description: init result dict and determint the loop end point
:param binary_list: A list of binary rpm package name
history_dicts: record the searching install depend history,
defualt is None
:return binary_dict.dictionary:
{binary_name: [
src,
dbname,
version,
[
parent_node_package_name
'install'
]
]}
'''
if not self.search_db.db_object_dict:
return ResponseCode.DIS_CONNECTION_DB, None
if not binary_list:
response_code = ResponseCode.INPUT_NONE,
return response_code, None
for binary in binary_list:
if binary:
self.search_list.append(binary)
else:
LOGGER.logger.warning("There is a NONE in input value:" + str(binary_list))
while self.search_list:
response_code = self.query_install(history_dicts)
return response_code, self.binary_dict.dictionary if response_code != \
ResponseCode.DIS_CONNECTION_DB else None
def query_install(self, history_dicts):
"""
Description: query a package install depend and append to result
:param history_dicts
:return response_code
changeLog:
"""
response_code, result_list = self.search_db.get_install_depend(self.search_list)
for search in self.search_list:
if search not in self.binary_dict.dictionary:
self.binary_dict.init_key(key=search, parent_node=[])
self.search_list.clear()
if result_list:
for result, dbname in result_list:
if not self.binary_dict.dictionary[result.search_name][ListNode.PARENT_LIST]:
self.binary_dict.init_key(key=result.search_name,
src=result.search_src_name,
version=result.search_version,
dbname=dbname)
else:
self.binary_dict.update_value(key=result.search_name,
src=result.search_src_name,
version=result.search_version,
dbname=dbname)
if result.depend_name:
if result.depend_name in self.binary_dict.dictionary:
self.binary_dict.update_value(key=result.depend_name,
parent_node=[result.search_name, 'install'])
elif history_dicts is not None and result.depend_name in history_dicts:
self.binary_dict.init_key(
key=result.depend_name,
src=history_dicts[result.depend_name][ListNode.SOURCE_NAME],
version=history_dicts[result.depend_name][ListNode.VERSION],
dbname=None,
parent_node=[[result.search_name, 'install']]
)
else:
self.binary_dict.init_key(key=result.depend_name,
parent_node=[[result.search_name, 'install']])
self.search_list.append(result.depend_name)
return response_code
class DictionaryOperations():
'''
Related to dictionary operations, creating dictionary, append dictionary
'''
def __init__(self):
self.dictionary = dict()
def init_key(self, key, src=None, version=None, dbname=None, parent_node=None):
'''
Creating dictionary
'''
if dbname:
self.dictionary[key] = [src, version, dbname, [['root', None]]]
else:
self.dictionary[key] = [src, version, dbname, parent_node]
def update_value(self, key, src=None, version=None, dbname=None, parent_node=None):
'''
append dictionary
'''
if src:
self.dictionary[key][ListNode.SOURCE_NAME] = src
if version:
self.dictionary[key][ListNode.VERSION] = version
if dbname:
self.dictionary[key][ListNode.DBNAME] = dbname
if parent_node:
self.dictionary[key][ListNode.PARENT_LIST].append(parent_node)
"""
A set for all query databases function
"""
from collections import namedtuple
import yaml
from flask import current_app
from sqlalchemy import text
from sqlalchemy.exc import SQLAlchemyError, DisconnectionError
from sqlalchemy.sql import literal_column
from packageship.libs.dbutils import DBHelper
from packageship.libs.log import Log
from packageship.application.models.package import bin_pack
from packageship.libs.exception import ContentNoneException, Error
from packageship.system_config import DATABASE_SUCCESS_FILE
from .constants import ResponseCode
LOGGER = Log(__name__)
class SearchDB():
"""
Description: query in database
changeLog:
"""
def __new__(cls, *args, **kwargs):
# pylint: disable=w0613
if not hasattr(cls, "_instance"):
cls._instance = super(SearchDB, cls).__new__(cls)
return cls._instance
def __init__(self, db_list):
self.db_object_dict = dict()
for db_name in db_list:
try:
with DBHelper(db_name=db_name) as data_base:
self.db_object_dict[db_name] = data_base
except DisconnectionError as connection_error:
current_app.logger.error(connection_error)
def get_install_depend(self, binary_list):
"""
Description: get a package install depend from database:
binary_name -> binary_id -> requires_set -> requires_id_set -> provides_set
-> install_depend_binary_id_key_list -> install_depend_binary_name_list
:param binary_lsit: a list of binary package name
:return install depend list
changeLog:
"""
if not self.db_object_dict:
return ResponseCode.DIS_CONNECTION_DB, None
if None in binary_list:
binary_list.remove(None)
search_set = set(binary_list)
result_list = []
get_list = []
if not search_set:
return ResponseCode.INPUT_NONE, None
for db_name, data_base in self.db_object_dict.items():
try:
name_in = literal_column('name').in_(search_set)
sql_com = text("""
SELECT DISTINCT
bin_pack.NAME AS depend_name,
bin_pack.version AS depend_version,
s2.NAME AS depend_src_name,
bin.NAME AS search_name,
s1.`name` AS search_src_name,
s1.version AS search_version
FROM
( SELECT id, NAME,srcIDkey FROM bin_pack WHERE {} ) bin
LEFT JOIN pack_requires ON bin.id = pack_requires.binIDkey
LEFT JOIN pack_provides ON pack_provides.id = pack_requires.depProIDkey
LEFT JOIN bin_pack ON bin_pack.id = pack_provides.binIDkey
LEFT JOIN src_pack s1 ON s1.id = bin.srcIDkey
LEFT JOIN src_pack s2 ON s2.id = bin_pack.srcIDkey;""".format(name_in))
install_set = data_base.session. \
execute(sql_com, {'name_{}'.format(i): v
for i, v in enumerate(search_set, 1)}).fetchall()
if install_set:
# find search_name in db_name
# depend_name's db_name will be found in next loop
for result in install_set:
result_list.append((result, db_name))
get_list.append(result.search_name)
get_set = set(get_list)
get_list.clear()
search_set.symmetric_difference_update(get_set)
if not search_set:
return ResponseCode.SUCCESS, result_list
else:
continue
except AttributeError as error_msg:
LOGGER.logger.error(error_msg)
except SQLAlchemyError as error_msg:
LOGGER.logger.error(error_msg)
return_tuple = namedtuple('return_tuple',
'depend_name depend_version depend_src_name \
search_name search_src_name search_version')
for binary_name in search_set:
result_list.append((return_tuple(None, None, None,
binary_name, None, None), 'NOT FOUND'))
return ResponseCode.SUCCESS, result_list
def get_src_name(self, binary_name):
"""
Description: get a package source name from database:
bianry_name ->binary_source_name -> source_name
input: search package's name, database preority list
return: database name, source name
changeLog:
"""
for db_name, data_base in self.db_object_dict.items():
try:
bin_obj = data_base.session.query(bin_pack).filter_by(
name=binary_name
).first()
source_name = bin_obj.src_pack.name
source_version = bin_obj.src_pack.version
if source_name is not None:
return ResponseCode.SUCCESS, db_name, \
source_name, source_version
except AttributeError as error_msg:
LOGGER.logger.error(error_msg)
except SQLAlchemyError as error_msg:
LOGGER.logger.error(error_msg)
return ResponseCode.DIS_CONNECTION_DB, None
return ResponseCode.PACK_NAME_NOT_FOUND, None, None, None
def db_priority():
"""
......
......@@ -8,17 +8,6 @@ from flask import current_app
from flask_restful import Resource
from sqlalchemy.exc import DisconnectionError
from packageship.application.apps.package.function.constants import ResponseCode
from packageship.application.apps.package.function.packages import get_packages
from packageship.application.apps.package.function.packages import update_single_package
from packageship.application.apps.package.function.packages import update_maintaniner_info
from packageship.application.apps.package.function.packages import get_single_package
from packageship.application.apps.package.function.searchdb import db_priority
from packageship.application.apps.package.serialize import PackagesSchema
from packageship.application.apps.package.serialize import GetpackSchema
from packageship.application.apps.package.serialize import PutpackSchema
from packageship.application.apps.package.serialize import DeletedbSchema
from packageship.application.apps.package.serialize import InitSystemSchema
from packageship.application.initsystem.data_import import InitDataBase
from packageship.libs.configutils.readconfig import ReadConfig
from packageship.libs.exception import Error
......@@ -26,9 +15,24 @@ from packageship.libs.exception import ContentNoneException
from packageship.libs.exception import DataMergeException
from packageship.libs.log import Log
from packageship.system_config import DATABASE_SUCCESS_FILE
from .function.constants import ResponseCode
from .function.packages import get_packages
from .function.packages import update_single_package
from .function.packages import update_maintaniner_info
from .function.packages import get_single_package
from .function.searchdb import db_priority
from .serialize import PackagesSchema
from .serialize import GetpackSchema
from .serialize import PutpackSchema
from .serialize import DeletedbSchema
from .serialize import InitSystemSchema
from .function.install_depend import InstallDepend as installdepend
from .serialize import InstallDependSchema
from .serialize import have_err_db_name
LOGGER = Log(__name__)
#pylint: disable = no-self-use
class Packages(Resource):
'''
......@@ -212,7 +216,7 @@ class InstallDepend(Resource):
changeLog:
'''
def post(self, *args, **kwargs):
def post(self):
'''
Description: Query a package's install depend(support
querying in one or more databases)
......@@ -220,22 +224,66 @@ class InstallDepend(Resource):
binaryName
dbPreority:the array for database preority
return:
resultList[
result[
binaryName: binary package name
srcName: the source package name for
that binary packge
dbName:
type: install install or build, which
depend on the function
parentNode: the binary package name which is
the install depend for binaryName
resultDict{
binary_name: //binary package name
[
src, //the source package name for
that binary packge
dbname,
version,
[
parent_node, //the binary package name which is
the install depend for binaryName
type //install install or build, which
depend on the function
]
]
]
}
exception:
changeLog:
'''
pass
schema = InstallDependSchema()
data = request.get_json()
validate_err = schema.validate(data)
if validate_err:
return jsonify(
ResponseCode.response_json(ResponseCode.PARAM_ERROR)
)
pkg_name = data.get("binaryName")
db_pri = db_priority()
if not db_pri:
return jsonify(
ResponseCode.response_json(
ResponseCode.FILE_NOT_FIND_ERROR
)
)
db_list = data.get("db_list") if data.get("db_list") \
else db_pri
if not all([pkg_name, db_list]):
return jsonify(
ResponseCode.response_json(ResponseCode.PARAM_ERROR)
)
if have_err_db_name(db_list, db_pri):
return jsonify(
ResponseCode.response_json(ResponseCode.DB_NAME_ERROR)
)
response_code, install_dict = \
installdepend(db_list).install_depend_result([pkg_name])
if not install_dict:
return jsonify(
ResponseCode.response_json(response_code)
)
return jsonify(
ResponseCode.response_json(ResponseCode.SUCCESS, data=install_dict)
)
class BuildDepend(Resource):
......@@ -330,7 +378,8 @@ class BeDepend(Resource):
srcName:
dbName:
type: beinstall or bebuild, which depend on the function
childNode: the binary package name which is the be built/installed depend for binaryName
childNode: the binary package name which is the be built/installed
depend for binaryName
]
]
exception:
......
......@@ -23,7 +23,7 @@ SYS_CONFIG_PATH = os.path.join('/', 'etc', 'pkgship', 'package.ini')
# BASE_PATH, 'application', 'initsystem', 'import_success_databse.yaml')
DATABASE_SUCCESS_FILE = os.path.join(
'/', 'var', 'run', 'import_success_databse.yaml')
'/', 'var', 'run', 'import_success_database.yaml')
# If the path of the imported database is not specified in the configuration file, the
# configuration in the system is used by default
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册