Merge release-0.28.17 from 'tools/mic'
[platform/upstream/mic.git] / mic / cmd_create.py
1 #!/usr/bin/python -tt\r
2 # vim: ai ts=4 sts=4 et sw=4\r
3 #\r
4 # Copyright (c) 2012 Intel, Inc.\r
5 #\r
6 # This program is free software; you can redistribute it and/or modify it\r
7 # under the terms of the GNU General Public License as published by the Free\r
8 # Software Foundation; version 2 of the License\r
9 #\r
10 # This program is distributed in the hope that it will be useful, but\r
11 # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\r
12 # or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\r
13 # for more details.\r
14 #\r
15 # You should have received a copy of the GNU General Public License along\r
16 # with this program; if not, write to the Free Software Foundation, Inc., 59\r
17 # Temple Place - Suite 330, Boston, MA 02111-1307, USA.\r
18 \r
19 """Implementation of subcmd: create\r
20 """\r
21 \r
22 import os\r
23 import os, sys, re\r
24 import pwd\r
25 import argparse\r
26 \r
27 from mic import msger\r
28 from mic.utils import errors, rpmmisc\r
29 from mic.conf import configmgr\r
30 from mic.plugin import pluginmgr\r
31 \r
32 def main(parser, args, argv):\r
33     """mic create entry point."""\r
34     #args is argparser namespace, argv is the input cmd line\r
35     if args is None:\r
36         raise errors.Usage("Invalid arguments")\r
37 \r
38     if not os.path.exists(args.ksfile):\r
39         raise errors.CreatorError("Can't find the file: %s" % args.ksfile)\r
40 \r
41     if os.geteuid() != 0:\r
42         msger.error("Root permission is required, abort")\r
43         \r
44     try:\r
45         w = pwd.getpwuid(os.geteuid())\r
46     except KeyError:\r
47         msger.warning("Might fail in compressing stage for undetermined user")\r
48     \r
49     abspath = lambda pth: os.path.abspath(os.path.expanduser(pth))\r
50     if args.logfile:\r
51         logfile_abs_path = abspath(args.logfile)\r
52         if os.path.isdir(logfile_abs_path):\r
53             raise errors.Usage("logfile's path %s should be file"\r
54                                % args.logfile)\r
55         configmgr.create['logfile'] = logfile_abs_path\r
56         configmgr.set_logfile()\r
57 \r
58     if args.subcommand == "auto":\r
59         do_auto(parser, args.ksfile, argv)\r
60         return\r
61 \r
62     if args.interactive:\r
63         msger.enable_interactive()\r
64     else:\r
65         msger.disable_interactive()\r
66 \r
67     if args.verbose:\r
68         msger.set_loglevel('VERBOSE')\r
69 \r
70     if args.debug:\r
71         try:\r
72             import rpm\r
73             rpm.setVerbosity(rpm.RPMLOG_NOTICE)\r
74         except ImportError:\r
75             pass\r
76 \r
77         msger.set_loglevel('DEBUG')\r
78 \r
79     if args.rpm_debug:\r
80         try:\r
81             import rpm\r
82             rpm.setVerbosity(rpm.RPMLOG_DEBUG)\r
83         except ImportError:\r
84             pass\r
85     #check the imager type\r
86     createrClass = None\r
87     for subcmd, klass in pluginmgr.get_plugins('imager').iteritems():\r
88         if subcmd == args.subcommand and hasattr(klass, 'do_create'):\r
89             createrClass = klass\r
90 \r
91     if createrClass is None:\r
92         raise errors.CreatorError("Can't support subcommand %s" % args.subcommand)\r
93 \r
94     if args.config:\r
95         configmgr.reset()\r
96         configmgr._siteconf = args.config\r
97 \r
98     if args.outdir is not None:\r
99         configmgr.create['outdir'] = abspath(args.outdir)\r
100     if args.cachedir is not None:\r
101         configmgr.create['cachedir'] = abspath(args.cachedir)\r
102     os.environ['ZYPP_LOCKFILE_ROOT'] = configmgr.create['cachedir']\r
103 \r
104     for cdir in ('outdir', 'cachedir'):\r
105         if os.path.exists(configmgr.create[cdir]) \\r
106           and not os.path.isdir(configmgr.create[cdir]):\r
107             raise errors.Usage('Invalid directory specified: %s' \\r
108                                % configmgr.create[cdir])\r
109         if not os.path.exists(configmgr.create[cdir]):\r
110             os.makedirs(configmgr.create[cdir])\r
111             if os.getenv('SUDO_UID', '') and os.getenv('SUDO_GID', ''):\r
112                 os.chown(configmgr.create[cdir],\r
113                          int(os.getenv('SUDO_UID')),\r
114                          int(os.getenv('SUDO_GID')))\r
115 \r
116     if args.local_pkgs_path is not None:\r
117         if not os.path.exists(args.local_pkgs_path):\r
118             raise errors.Usage('Local pkgs directory: \'%s\' not exist' \\r
119                           % args.local_pkgs_path)\r
120         configmgr.create['local_pkgs_path'] = args.local_pkgs_path\r
121 \r
122     if args.release:\r
123         configmgr.create['release'] = args.release.rstrip('/')\r
124 \r
125     if args.record_pkgs:\r
126         configmgr.create['record_pkgs'] = []\r
127         for infotype in args.record_pkgs.split(','):\r
128             if infotype not in ('name', 'content', 'license', 'vcs'):\r
129                 raise errors.Usage('Invalid pkg recording: %s, valid ones:'\r
130                                    ' "name", "content", "license", "vcs"' \\r
131                                    % infotype)\r
132 \r
133             configmgr.create['record_pkgs'].append(infotype)\r
134 \r
135     if args.strict_mode:\r
136       configmgr.create['strict_mode'] = args.strict_mode\r
137     if args.arch is not None:\r
138         supported_arch = sorted(rpmmisc.archPolicies.keys(), reverse=True)\r
139         if args.arch in supported_arch:\r
140             configmgr.create['arch'] = args.arch\r
141         else:\r
142             raise errors.Usage('Invalid architecture: "%s".\n'\r
143                                '  Supported architectures are: \n'\r
144                                '  %s' % (args.arch,\r
145                                            ', '.join(supported_arch)))\r
146 \r
147     if args.pkgmgr is not None:\r
148         configmgr.create['pkgmgr'] = args.pkgmgr\r
149 \r
150     if args.skip_set_hosts:\r
151         configmgr.create['skip_set_hosts']=args.skip_set_hosts\r
152     if args.postscripts_maxruntime:\r
153         configmgr.create['postscripts_maxruntime']=int(args.postscripts_maxruntime)\r
154     if args.block_recommends:\r
155         configmgr.create['block_recommends']=args.block_recommends\r
156     if args.runtime:\r
157         configmgr.set_runtime(args.runtime)\r
158 \r
159     if args.use_mic_in_bootstrap:\r
160         configmgr.create['use_mic_in_bootstrap'] = args.use_mic_in_bootstrap\r
161 \r
162     if args.pack_to is not None:\r
163         configmgr.create['pack_to'] = args.pack_to\r
164 \r
165     if args.copy_kernel:\r
166         configmgr.create['copy_kernel'] = args.copy_kernel\r
167 \r
168     if args.install_pkgs:\r
169         configmgr.create['install_pkgs'] = []\r
170         for pkgtype in args.install_pkgs.split(','):\r
171             if pkgtype not in ('source', 'debuginfo', 'debugsource'):\r
172                 raise errors.Usage('Invalid parameter specified: "%s", '\r
173                                    'valid values: source, debuginfo, '\r
174                                    'debusource' % pkgtype)\r
175 \r
176             configmgr.create['install_pkgs'].append(pkgtype)\r
177 \r
178     if args.check_pkgs:\r
179         for pkg in args.check_pkgs.split(','):\r
180             configmgr.create['check_pkgs'].append(pkg)\r
181 \r
182     if args.enabletmpfs:\r
183         configmgr.create['enabletmpfs'] = args.enabletmpfs\r
184 \r
185     if args.repourl:\r
186         for item in args.repourl:\r
187             try:\r
188                 key, val = item.split('=')\r
189             except:\r
190                 continue\r
191             configmgr.create['repourl'][key] = val\r
192 \r
193     if args.repo:\r
194         for optvalue in args.repo:\r
195             repo = {}\r
196             for item in optvalue.split(';'):\r
197                 try:\r
198                     key, val = item.split('=')\r
199                 except:\r
200                     continue\r
201                 repo[key.strip()] = val.strip()\r
202             if 'name' in repo:\r
203                 configmgr.create['extrarepos'][repo['name']] = repo\r
204 \r
205     if args.ignore_ksrepo:\r
206         configmgr.create['ignore_ksrepo'] = args.ignore_ksrepo\r
207     if args.run_script:\r
208         configmgr.create['run_script'] = args.run_script\r
209     if args.tpk_install:\r
210         configmgr.create['tpk_install'] = args.tpk_install\r
211 \r
212     creater = createrClass()\r
213     creater.do_create(args)\r
214 \r
215 def do_auto(parser, ksfile, argv):\r
216         """${cmd_name}: auto detect image type from magic header\r
217 \r
218         Usage:\r
219             ${name} ${cmd_name} <ksfile>\r
220 \r
221         ${cmd_option_list}\r
222         """\r
223         def parse_magic_line(re_str, pstr, ptype='mic'):\r
224             ptn = re.compile(re_str)\r
225             m = ptn.match(pstr)\r
226             if not m or not m.groups():\r
227                 return None\r
228 \r
229             inline_argv = m.group(1).strip()\r
230             if ptype == 'mic':\r
231                 m2 = re.search('(?P<format>\w+)', inline_argv)\r
232             elif ptype == 'mic2':\r
233                 m2 = re.search('(-f|--format(=)?)\s*(?P<format>\w+)',\r
234                                inline_argv)\r
235             else:\r
236                 return None\r
237 \r
238             if m2:\r
239                 cmdname = m2.group('format')\r
240                 inline_argv = inline_argv.replace(m2.group(0), '')\r
241                 return (cmdname, inline_argv)\r
242 \r
243             return None\r
244 \r
245         if not os.path.exists(ksfile):\r
246             raise errors.CreatorError("Can't find the file: %s" % ksfile)\r
247 \r
248         with open(ksfile, 'r') as rf:\r
249             first_line = rf.readline()\r
250 \r
251         mic_re = '^#\s*-\*-mic-options-\*-\s+(.*)\s+-\*-mic-options-\*-'\r
252         mic2_re = '^#\s*-\*-mic2-options-\*-\s+(.*)\s+-\*-mic2-options-\*-'\r
253 \r
254         result = parse_magic_line(mic_re, first_line, 'mic') \\r
255                  or parse_magic_line(mic2_re, first_line, 'mic2')\r
256         if not result:\r
257             raise errors.KsError("Invalid magic line in file: %s" % ksfile)\r
258         \r
259         ksargv = ' '.join(result).split()\r
260 \r
261         argv.remove("auto")\r
262         index = argv.index("create")\r
263         #insert the subcommand\r
264         argv.insert(index+1, ksargv[0])\r
265         options = argv + ksargv[1:]\r
266 \r
267         args = parser.parse_args(options)\r
268 \r
269         main(parser, args, options)\r
270 \r