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