from tic.utils import process
from tic.utils import misc
from tic.utils import file
+from tic.config import configmgr
-DEFAULT_CACHEDIR='/var/tmp/tic-core'
-DEFAULT_ANALYSIS_CACHEDIR='/var/tmp/tic-core/analysis'
-DEFAULT_KICKSTARTDIR='/var/tmp/tic-core/kickstart'
+DEFAULT_CACHEDIR=configmgr.setting['tempdir']
+DEFAULT_ANALYSISDIR=os.path.join(DEFAULT_CACHEDIR, 'analysis')
+DEFAULT_KICKSTARTDIR=os.path.join(DEFAULT_CACHEDIR, 'kickstart')
def analyze(repo_list, recipe_list=None):
logger = logging.getLogger(__name__)
for repo in repoinfo:
checksum_list.append(repo['checksum'])
all_checksum = hashlib.sha256('_'.join(checksum_list)).hexdigest()
- analysis_file=os.path.join(DEFAULT_ANALYSIS_CACHEDIR, all_checksum, 'analysis.json')
+ analysis_file=os.path.join(DEFAULT_ANALYSISDIR, all_checksum, 'analysis.json')
pkg_group=None
if os.path.exists(analysis_file):
pkg_group=file.read_json(analysis_file)
--- /dev/null
+
+import os
+import ConfigParser
+
+DEFAULT_MSG_CONF = "/etc/tic-core/message.conf"
+DEFAULT_CONF = "/etc/tic-core/config.conf"
+
+class ConfigMgr(object):
+ DEFAULT_MESSAGE = {'message': {
+ 'repo_not_found': "The repository url cannot be found (%s)",
+ 'xml_parse_error': "There was a problem parsing the %s, please check the file (%s)",
+ 'yaml_parse_error': "There was a problem parsing the %s, please check the file (%s)",
+ 'recipe_parse_error': "There was a problem parsing the recipe, please check the recipe file (%s)",
+ 'package_not_exist': "The default package(%s) does not exist.",
+ 'dependency_not_exist': "The %s needed by %s does not exist. should be checked for repository",
+ 'server_error': "there was a problem servicing your request. please try again later" }
+ }
+
+ DEFAULT_TIC = {'setting': {
+ 'tempdir': '/var/tmp/tic-core',
+ 'cachedir': '/var/tmp/tic-core/cache',
+ 'logdir': '/var/tmp/tic-core/log'},
+ 'server': {
+ 'port': 8082},
+ 'regularexp': {
+ 'meta_prefix': "building-blocks",
+ 'meta_prefix_root': "building-blocks-root-",
+ 'meta_prefix_sub1': "building-blocks-sub1-",
+ 'meta_pattern': "-(?P<meta>root|sub1|sub2)-(?P<pkgname>.+)",
+ 'meta_sub1_pattern': "(?P<root>.+)-(?P<sub1>.+)",
+ 'meta_sub2_pattern': "(?P<root>.+)-(?P<sub1>.+)-(?P<sub2>.+)",
+ 'profile_pattern': "(?P<pkgname>.+)-profile_(?P<profile>[^-]+)-?(?P<extra>.+)?"}
+ }
+
+ _instance = None
+
+ def __new__(cls, *args, **kwargs):
+ if not cls._instance:
+ cls._instance = super(ConfigMgr, cls).__new__(cls, *args, **kwargs)
+ return cls._instance
+
+ def __init__(self, ):
+ self._reset()
+ for conf_path in [DEFAULT_CONF, DEFAULT_MSG_CONF]:
+ self._setConfig(conf_path)
+
+ def _reset(self):
+ for sec, vals in self.DEFAULT_TIC.iteritems():
+ setattr(self, sec, vals)
+ for sec, vals in self.DEFAULT_MESSAGE.iteritems():
+ setattr(self, sec, vals)
+
+ def _setConfig(self, conf):
+ configParser = ConfigParser.ConfigParser()
+ try:
+ if os.path.exists(conf):
+ configParser.read(conf)
+ for section in configParser.sections():
+ for option in configParser.options(section):
+ try:
+ opt_attr=getattr(self, section)
+ opt_attr[option]=configParser.get(section, option)
+ except:
+ pass
+ except Exception as e:
+ print(e)
+
+configmgr = ConfigMgr()
+
+if __name__ == '__main__':
+ temp_dict = {'aaa': 'bbb'}
+ temp= temp_dict.get(temp_dict.get(None))
+ print(configmgr.setting['cachedir'])
+ print(configmgr.message['repo_not_found'])
+ print(configmgr.regularexp['meta_prefix'])
+ print(configmgr.server['port'])
\ No newline at end of file
from lxml import etree
from tic.utils.error import TICError
from tic.utils.rpmmisc import meetRequireVersion, compare_ver
+from tic.utils.rpmmisc import Dependency
+from tic.config import configmgr
+
+DEFAULT_PROFILE = 'EMPTY'
def analyze_dependency(pkg_group):
def dep_dfs(pkg_id):
- logger = logging.getLogger(__name__)
+ #logger = logging.getLogger(__name__)
if pkg_list[pkg_id].get('dependency') is not None:
return pkg_list[pkg_id].get('dependency')
def get_installed_packages(recipe, repoinfo, pkg_group):
logger = logging.getLogger(__name__)
- def _select_rpm(capability, require):
+ def _select_rpm_from_files(fileList, require):
+ if not fileList or not require:
+ return None
+ # 1. sort
+ fileList.sort()
+ # 2-1. Choose the default rpm or the selected rpm
+ for fname in fileList:
+ file_info = pkg_dict.get(fname)
+ if fname in pkg_set or selected[file_info['id']] >= 1:
+ return file_info
+ # 2-2. Choose the rpm (it does not conflitcs)
+ for fname in fileList:
+ file_info = pkg_dict.get(fname)
+ if not _check_conflicts(file_info):
+ return file_info
+ return pkg_dict.get(fileList[0])
+
+ def _select_rpm(capability, require, recommends=None):
provide_list = []
# 1. Choose the rpm included in version from provides
if require.get('ver'):
return pkg_dict.get(provide_list[0].get('name'))
# 2 Select one of the rpms by priority
- # 2-1. Choose the default rpm or the selected rpm
- # TODO: default profile rpm should be selected
- for i in range(0, len(provide_list)):
- tmp_info = pkg_dict.get(provide_list[i].get('name'))
- if tmp_info['name'] in pkg_set or selected[tmp_info['id']] >= 1:
- return tmp_info
- # 2-2. Select the latest version of rpm
+ # 2-1. Choose the default rpm or the selected rpm
+ for pro in provide_list:
+ provide_info = pkg_dict.get(pro.get('name'))
+ if provide_info['name'] in pkg_set or selected[provide_info['id']] >= 1:
+ return provide_info
+
+ # 2-2. Choose the defualt profile
+ # TODO: should be supported
+ # if provide_info['profile'] == DEFAULT_PROFILE:
+ # return provide_info
+
+ # 2.3. Choose recommends pkg (pkg-name or capability)
+ if recommends:
+ for pro in provide_list:
+ provide_info = pkg_dict.get(pro.get('name'))
+ for reco in recommends:
+ # 2-3 Case. select a pkg that is named
+ if reco['name'] == provide_info['name']:
+ return provide_info
+ # 2-3 Case. select a pkg that provides
+ for cap in provide_info.get('provides'):
+ if reco['name'] == cap['name']:
+ return provide_info
+ # 2-4. Select the latest version of rpm
max_ver = None
- for i in range(0, len(provide_list)):
- if not _check_conflicts(pkg_dict.get(provide_list[i]['name'])):
+ for pro in provide_list:
+ if not _check_conflicts(pkg_dict.get(pro.get('name'))):
if max_ver:
- cap_info = provide_list[i].get('data')
+ cap_info = pro.get('data')
ret = compare_ver(max_ver.get('data'), cap_info)
- # cap_info is greater than max_ver
- if ret == -1:
- max_ver = provide_list[i]
+ if ret == 0: # equals
+ # string compare (compare string lexicographically using ASCII value)
+ if max_ver.get('name') > pro.get('name'):
+ max_ver = pro
+ elif ret == -1: # greater than max_ver
+ max_ver = pro
else:
- max_ver = provide_list[i]
+ max_ver = pro
# all of capability pkg are in conflict
if max_ver is None:
for con in conflicts[pro['name']]:
if not con['data'].get('ver') or meetRequireVersion(con['data'], pro):
#package conflict
+ logger.info('Conflict %s and %s' % (pkg_info['name'], con['name']))
return True
#2. If the conflict package defined by node is installed
pkg = pkg_dict[pro['name']]
if selected[pkg['id']] != 0:
if not con.get('ver') or meetRequireVersion(con, pkg['version']):
+ logger.info('Conflict %s and %s' % (pkg_info['name'], pkg['name']))
return True
elif con['name'] in pkg_dict:
pkg = pkg_dict[con['name']]
if selected[pkg['id']] != 0:
if not con.get('ver') or meetRequireVersion(con, pkg['version']):
+ logger.info('Conflict %s and %s' % (pkg_info['name'], pkg['name']))
return True
return False
_add_conflicts(pkg_info)
# Installation dependency analysis of rpm
- for dep_tag in ['recommends', 'requires']:
+ for dep_tag in [Dependency.REQUIRES, Dependency.RECOMMENDS]:
if pkg_info.get(dep_tag):
for req in pkg_info.get(dep_tag):
choose = None
if req['name'] in provides:
# capability : [provide_rpm_1, provide_rpm_2, ... ]
# Select the rpm that meets the condition (version)
- choose = _select_rpm(provides[req['name']], req)
+ if dep_tag == Dependency.REQUIRES:
+ choose = _select_rpm(provides[req['name']], req, pkg_info.get('recommends'))
+ else:
+ choose = _select_rpm(provides[req['name']], req)
elif req['name'] in files:
- choose = pkg_dict.get(files[req['name']][0])
+ choose = _select_rpm_from_files(files[req['name']], req)
+ #choose = pkg_dict.get(files[req['name']][0])
elif req['name'] in pkg_dict:
choose = pkg_dict.get(req['name'])
+
+ if dep_tag == Dependency.RECOMMENDS:
+ # A Recommends B: B is installed when A is installed and B has no conflicts.
+ if not choose or _check_conflicts(choose):
+ logger.info('%s recommended by %s is ignored for selection (Conflict)' % (req['name'], pkg_info['name']))
+ continue
if choose:
if selected[choose['id']] == 0:
_create_reference(pkg_info, choose)
else:
# the rpm does not exists
- logger.info('the capability(%s) needed by %s does not exist. should be checked for error' % (req['name'], pkg_info['name']))
+ logger.info(configmgr.message['dependency_not_exist'] % (req['name'], pkg_info['name']))
progress['status'] = False
break
tree = etree.parse(repo.get('comps'))
root = tree.getroot()
except etree.XMLSyntaxError as e:
- raise TICError('group.xml syntax error. %s', e)
+ logger.info(e)
+ raise TICError(configmgr.message['xml_parse_error'] % ('group.xml', repo['baseurl']))
# Convert groups to packages
for elm in root.findall('group'):
pro = provides.get(pkg_name)[0]
pkg_info = pkg_dict.get(pro['name'])
else:
- logger.info('the default package(%s) does not exist.' % pkg_name)
+ logger.info(configmgr.message['package_not_exist'] % pkg_name)
continue
pkg_info['selfChecked'] = True
from tic.utils import error
from tic.utils.file import write, make_dirs
import yaml
+from tic.config import configmgr
def get_default_recipe():
return recipe
def load_yaml(path):
+ logger = logging.getLogger(__name__)
try:
with file(path) as f:
return yaml.load(f)
- except IOError:
- raise error.TICError('cannot read meta file: %s' % path)
- except:
- raise error.TICError('yaml format error of meta file: %s' % path)
+ except IOError as err:
+ logger(err)
+ raise error.TICError(configmgr.message['server_error'])
+ except yaml.YAMLError as err:
+ logger(err)
+ raise error.TICError(configmgr.message['recipe_parse_error'] % os.path.basename(path))
def convert_recipe_to_yaml(recipe, filepath):
# Contributors:
# - S-Core Co., Ltd
+import re
+import logging
from lxml import etree
from tic.utils.error import TICError
from tic.utils.rpmmisc import archPolicies, default_arch
-import logging
-import re
+from tic.config import configmgr
-meta_prefix = 'building-blocks'
-meta_prefix_root = 'building-blocks-root-'
-meta_prefix_sub1 = 'building-blocks-sub1-'
-meta_pattern = re.compile(''.join(['^', meta_prefix, '-(?P<meta>root|sub1|sub2)-(?P<pkgname>.+)']), re.I)
-meta_sub1_pattern = re.compile("(?P<root>.+)-(?P<sub1>.+)")
-meta_sub2_pattern = re.compile("(?P<root>.+)-(?P<sub1>.+)-(?P<sub2>.+)")
+# meta pkg
+META_PREFIX = configmgr.regularexp['meta_prefix']
+META_PREFIX_ROOT = configmgr.regularexp['meta_prefix_root']
+META_PREFIX_SUB1 = configmgr.regularexp['meta_prefix_sub1']
+META_PATTERN = re.compile(''.join(['^', META_PREFIX, configmgr.regularexp['meta_pattern']]), re.I)
+META_SUB1_PATTERN = re.compile(configmgr.regularexp['meta_sub1_pattern'])
+META_SUB2_PATTERN = re.compile(configmgr.regularexp['meta_sub2_pattern'])
+# profile pkg
+PROFILE_PATTERN = re.compile(configmgr.regularexp['profile_pattern'])
class RepodataParser(object):
pkg_info['selfChecked'] = False # for web-ui tree
# Parsing meta-pkg using meta naming rule
- meta_match = meta_pattern.search(pkg_info['name'])
+ meta_match = META_PATTERN.search(pkg_info['name'])
if meta_match is not None:
#print(meta_match.group(0), ', ', meta_match.group('meta'), ', ', meta_match.group('pkgname'))
if meta_match.group('meta') == 'root':
meta_info['root'].append([pkg_info['name']])
pkg_info['meta'] = 'root'
elif meta_match.group('meta') == 'sub1':
- sub1_match = meta_sub1_pattern.search(meta_match.group('pkgname'))
+ sub1_match = META_SUB1_PATTERN.search(meta_match.group('pkgname'))
meta_info['sub1'].append([pkg_info['name'],
- ''.join([meta_prefix_root, sub1_match.group('root')])])
+ ''.join([META_PREFIX_ROOT, sub1_match.group('root')])])
pkg_info['meta'] = 'sub1'
elif meta_match.group('meta') == 'sub2':
- sub2_match = meta_sub2_pattern.search(meta_match.group('pkgname'))
+ sub2_match = META_SUB2_PATTERN.search(meta_match.group('pkgname'))
meta_info['sub2'].append([pkg_info['name'],
- ''.join([meta_prefix_root, sub2_match.group('root')]),
- ''.join([meta_prefix_sub1, sub2_match.group('root'),'-', sub2_match.group('sub1')])])
+ ''.join([META_PREFIX_ROOT, sub2_match.group('root')]),
+ ''.join([META_PREFIX_SUB1, sub2_match.group('root'),'-', sub2_match.group('sub1')])])
pkg_info['meta'] = 'sub2'
-
+
+ # check profile pkg
+ profile_match = PROFILE_PATTERN.search(pkg_info['name']);
+ if profile_match and profile_match.group('profile'):
+ pkg_info['profile'] = profile_match.group('profile')
+ else:
+ pkg_info['profile'] = None
ver_tag = pkg.find(tag_dic['version'])
pkg_info['version'] = {'epoch':ver_tag.attrib['epoch'],
return ret_list
def parse(self):
+ logger = logging.getLogger(__name__)
if not self.repodata_list:
return None
tree = etree.parse(repodata['primary'])
xml_list.append(tree.getroot())
except etree.XMLSyntaxError as e:
- raise TICError('primary.xml syntax error. %s', e)
+ logger.info(e)
+ raise TICError(configmgr.message['xml_parse_error'] % ('primary', repodata['baseurl']))
tag_dic = self._get_tagname(xml_list[0])
from tic.utils.error import TICError
from tic.utils.grabber import myurlgrab2
from tic.utils import misc
+from tic.config import configmgr
def _get_uncompressed_data_from_url(url, filename, proxies=None):
# download file
return file.copyfile_flock(file_path, filename)
def get_repodata_from_repos(repos, cachedir):
+ logger = logging.getLogger(__name__)
my_repodata = []
temp_path = os.path.join(cachedir, 'temp', str(misc.get_timestamp()))
for repo in repos:
try:
tree = etree.parse(repomd)
root = tree.getroot()
- except etree.XMLSyntaxError:
- raise TICError("Unable to parse repomd.xml. Please check the repomd from repository url(%s)", url)
+ except etree.XMLSyntaxError as e:
+ logger.info(e)
+ raise TICError(configmgr.message['xml_parse_error'] % ('repomd.xml', url))
# make cache_dir
repo_checksum = hashlib.sha256(open(repomd_file, 'rb').read()).hexdigest()
import logging
from tic import command
from tic.utils import error
+from tic.config import configmgr
app = Flask(__name__)
except ValueError as ve:
logger.error(ve)
resp = makeresponse(str(ve), ve)
-# except Exception as ex:
-# logger.error(ex)
-# resp = makeresponse(str(ex), ex)
+ except Exception as ex:
+ logger.error(ex)
+ resp = makeresponse(str(ex), ex)
return resp
print(url_for('index'))
print(url_for('analysis'))
print(url_for('exports'))
+ if isinstance(port_num, (str, unicode)):
+ port_num = int(port_num)
app.run(host='0.0.0.0', threaded=True, port=port_num)
def __repr__(self):
if not hasattr(self, 'keyword') or not self.keyword:
self.keyword = self.__class__.__name__
- return "<%s> %s" % (self.keyword, str(self))
-
-
-class RepoError(TICError):
- """ Error class for Repository related """
- keyword = 'Repository'
\ No newline at end of file
+ return "<%s> %s" % (self.keyword, str(self))
\ No newline at end of file
import urllib2
import contextlib
from urlgrabber import grabber
-from tic.utils.error import TICError, RepoError
+from tic.utils.error import TICError
from tic.utils import process
from tic.utils.file import copyfile
+from tic.config import configmgr
def myurlgrab2(url, filename):
logger = logging.getLogger(__name__)
if url.startswith("file:/"):
filepath = "/%s" % url.replace("file:", "").lstrip('/')
if not os.path.exists(filepath):
- raise RepoError("URLGrabber error: can't find file %s" % url)
+ logger.info('URLGrabber error: cannot find file %s' % url)
+ raise TICError("URLGrabber error: can't find file %s" % url)
if url.endswith('.rpm'):
return filepath
else:
with contextlib.closing(urllib2.urlopen(url)) as op:
with open(filename, 'w') as f:
f.write(op.read())
- logger.info('download file from ' + str(url))
+ logger.info('download file from %s' % str(url))
except urllib2.HTTPError as err:
if err.code == 404:
- msg = 'The requested url was not found (%s)' % url
+ msg = configmgr.message['repo_not_found'] % url
else:
msg = str(err)
+ logger.info(err)
raise TICError(msg)
+ except urllib2.URLError as err:
+ logger.info(err)
+ raise TICError(configmgr.message['server_error'])
return filename
def myurlgrab(url, filename, proxies, progress_obj = None):
if url.startswith("file:/"):
filepath = "/%s" % url.replace("file:", "").lstrip('/')
if not os.path.exists(filepath):
- raise RepoError("URLGrabber error: can't find file %s" % url)
+ raise TICError("URLGrabber error: can't find file %s" % url)
if url.endswith('.rpm'):
return filepath
else:
import rpm
+class Dependency(object):
+ REQUIRES='requires'
+ RECOMMENDS='recommends'
+ SUGGESTS='suggests'
+ PROVIDES='provides'
+ CONFILCTS='conflicts'
+
+
default_arch = ('noarch', 'src')
archPolicies = {
from tic.utils import file
from tic.utils import error
from tic.server import tic_server
+from tic.config import configmgr
__version__ = 0.1
__date__ = '2016-11-07'
parser_create.add_argument('-k', "--ks", dest="kickstart", metavar="kickstart", help="ks file to be used for image creation")
parser_create.add_argument('-o', "--outdir", dest="outdir", action="store", help="image output directory", default=os.getcwd())
- parser_start = subparsers.add_parser('start', help='start the tic-core demon on system. port 8082 is used by default ')
- parser_start.add_argument('-p', "--port", dest="port", action="store", help="port number", default=8082)
+ parser_start = subparsers.add_parser('start', help='start the tic-core demon on system.')
+ parser_start.add_argument('-p', "--port", dest="port", action="store", help="port number")
return parser
else:
logger.info('kickstart or recipes file is required')
elif args.subparser_name == 'start':
- tic_server.start(int(args.port))
+ if not args.port:
+ args.port = configmgr.server['port']
+ tic_server.start(args.port)
return 0
except KeyboardInterrupt:
### handle keyboard interrupt ###