[TIC-CORE] change the license from apache 2.0 to flora 1.1
[archive/20170607/tools/tic-core.git] / tic / command.py
1 #!/usr/bin/python
2 # Copyright (c) 2016 Samsung Electronics Co., Ltd
3 #
4 # Licensed under the Flora License, Version 1.1 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
7 #
8 #     http://floralicense.org/license/
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 #
16 # Contributors:
17 # - S-Core Co., Ltd
18
19 import os
20 import logging
21 import hashlib
22
23 from tic.dependency import get_installed_packages
24 from tic.parser.recipe_parser import default_recipe, RecipeParser
25 from tic.parser.repo_parser import RepodataParser
26 from tic.parser.view_parser import make_view_data
27 from tic.utils.error import TICError
28 from tic.utils.file import copyfile
29 from tic.repo import get_repodata_from_repos
30 from tic.pykickstarter import KSoption, kswriter
31 from tic.utils import process
32 from tic.utils import misc
33 from tic.utils import file
34 from tic.config import configmgr
35
36 DEFAULT_CACHEDIR=configmgr.setting['tempdir']
37 DEFAULT_ANALYSISDIR=os.path.join(DEFAULT_CACHEDIR, 'analysis')
38 DEFAULT_KICKSTARTDIR=os.path.join(DEFAULT_CACHEDIR, 'kickstart')
39
40 def analyze(recipe_list):
41     logger = logging.getLogger(__name__)
42     if not recipe_list:
43         logger.info('Use default recipe because there is no import data')
44         recipe_list = default_recipe.getDefaultParameter()
45     
46     recipe_parser = RecipeParser(recipe_list)
47     recipe_parser.parse()
48     recipe_info = recipe_parser.getMergedRecipe()
49     
50     start_time = misc.get_timestamp()
51     #Download repodata from repositories (Remote/Local)
52     repoinfo = get_repodata_from_repos(recipe_info.get('Repositories'), DEFAULT_CACHEDIR)
53     logger.info('time to get repodata from repo: %d ms', misc.get_timestamp() - start_time)
54     
55     checksum_list=[]
56     for repo in repoinfo:
57         checksum_list.append(repo['checksum'])
58     all_checksum = hashlib.sha256('_'.join(checksum_list)).hexdigest()
59     analysis_file=os.path.join(DEFAULT_ANALYSISDIR, all_checksum, 'analysis.json')
60     pkg_group=None
61     if os.path.exists(analysis_file):
62         pkg_group=file.read_json(analysis_file)
63
64     if not pkg_group or not pkg_group.get('pkg_dict'):
65         start_time = misc.get_timestamp()
66         # Parse the xml files for the analysis of package (.rpm)
67         repo_parser = RepodataParser('armv7l', repoinfo)
68         pkg_group = repo_parser.parse()
69         logger.info('packages: %d, provides: %d, files: %d', len(pkg_group['pkg_dict']), len(pkg_group['provides']), len(pkg_group['files']))
70         logger.info('time to parse repodata: %d ms', misc.get_timestamp() - start_time)
71         # dump to cached file
72         file.write_json_flock(analysis_file, pkg_group)
73     else:
74         logger.info('use a cache parsing data - %s', analysis_file)
75
76     start_time = misc.get_timestamp()
77     # Make a data for TIC (Tizen image creation)
78     view_data = make_view_data(pkg_group)
79     # analyze install-dependency
80     inst_packages = get_installed_packages(recipe_info, repoinfo, pkg_group)
81     logger.info('installed package: %d', len(inst_packages))
82     logger.info('time to analyze dependency: %d ms', misc.get_timestamp() - start_time)
83
84     result = {'view': view_data,
85               'data': {'packages': pkg_group.get('pkg_dict'),
86                        'provides': pkg_group.get('provides'),
87                        'files': pkg_group.get('files'),
88                        'groups': pkg_group.get('groups'),
89                        'conflicts': pkg_group.get('conflicts')},
90               'recipes': recipe_parser.getRepositories(),
91               'defaultpackages': inst_packages}
92     return result
93
94 def imports(recipe_list):
95     logger = logging.getLogger(__name__)
96     if not recipe_list:
97         logger.info('Use default recipe because there is no import data')
98         recipe_list = default_recipe.getDefaultParameter()
99     
100     recipe_parser = RecipeParser(recipe_list)
101     recipe_parser.parse()
102     result = {'recipes': recipe_parser.getRepositories()}
103     #result = {'imports': recipe_parser.getMergedRepositories()}
104     return result
105
106 def exports(export_type, recipes, packages, outdir, filename=None):
107     logger = logging.getLogger(__name__)
108     #TODO validation should be checked before request
109     if not export_type:
110         export_type='ks'
111         logger.info('set default export format(.ks)')
112
113     if not recipes:
114         raise TICError(configmgr.message['recipes_not_define'])
115     if not packages or type(packages) is not list:
116         raise TICError(configmgr.message['no_package_to_install'])
117     
118     recipe_parser = RecipeParser(recipes)
119     recipe_parser.parse()
120     result = None
121     if export_type == 'recipe':
122         recipe_path = recipe_parser.export2Recipe(packages, outdir, filename)
123         logger.info('export the recipe to %s' % recipe_path)
124         result = {'path': recipe_path}
125     elif export_type == 'ks':
126         # 1. create yaml files
127         yaml_info = recipe_parser.export2Yaml(packages, DEFAULT_KICKSTARTDIR)
128         # 2. create kickstart(.ks) using kickstarter tool
129         options = KSoption(yaml_info.configs, yaml_info.repos, yaml_info.cachedir)
130         kswriter(options)
131         # check whether the ks exists
132         recipe_info = recipe_parser.getMergedRecipe()
133         baseline=recipe_info['Recipe'].get('Baseline')
134         ksname= ''.join([recipe_info['Recipe'].get('FileName'), '.ks'])
135         kspath=os.path.join(yaml_info.cachedir, baseline, ksname)
136         logger.info('the kickstarter created the ks file (%s)' % kspath)
137         if not os.path.exists(kspath):
138             raise TICError('No ks file was created from kickstarter')
139         # copy the ks to output directory
140         output=copyfile(kspath, outdir, filename)
141         logger.info('export the ks to %s' % output)
142         result = {'path':output, 'arch':recipe_info['Recipe'].get('Architecture')}
143     return result
144
145 def createimage(recipes, ksfile, outdir):
146     logger = logging.getLogger(__name__)
147     
148     if recipes:
149         logger.info('the recipes option is not yet supported')
150         return
151     
152     if not os.path.exists(ksfile) or os.path.isdir(ksfile):
153         raise TICError('kickstart file does not exist')
154     
155     mic_command=['mic', 'cr', 'auto', ksfile]
156     if outdir:
157         mic_command.append('--outdir=%s' % outdir)
158     
159     process.run(mic_command, 2)