Merge "Another method of install tpk." into devel
[tools/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 \r
86     #check the imager type\r
87     createrClass = None\r
88     for subcmd, klass in pluginmgr.get_plugins('imager').iteritems():\r
89         if subcmd == args.subcommand and hasattr(klass, 'do_create'):\r
90             createrClass = klass\r
91 \r
92     if createrClass is None:\r
93         raise errors.CreatorError("Can't support subcommand %s" % args.subcommand)\r
94 \r
95     if args.config:\r
96         configmgr.reset()\r
97         configmgr._siteconf = args.config\r
98 \r
99     if args.outdir is not None:\r
100         configmgr.create['outdir'] = abspath(args.outdir)\r
101     if args.cachedir is not None:\r
102         configmgr.create['cachedir'] = abspath(args.cachedir)\r
103     os.environ['ZYPP_LOCKFILE_ROOT'] = configmgr.create['cachedir']\r
104 \r
105     for cdir in ('outdir', 'cachedir'):\r
106         if os.path.exists(configmgr.create[cdir]) \\r
107           and not os.path.isdir(configmgr.create[cdir]):\r
108             raise errors.Usage('Invalid directory specified: %s' \\r
109                                % configmgr.create[cdir])\r
110         if not os.path.exists(configmgr.create[cdir]):\r
111             os.makedirs(configmgr.create[cdir])\r
112             if os.getenv('SUDO_UID', '') and os.getenv('SUDO_GID', ''):\r
113                 os.chown(configmgr.create[cdir],\r
114                          int(os.getenv('SUDO_UID')),\r
115                          int(os.getenv('SUDO_GID')))\r
116 \r
117     if args.local_pkgs_path is not None:\r
118         if not os.path.exists(args.local_pkgs_path):\r
119             raise errors.Usage('Local pkgs directory: \'%s\' not exist' \\r
120                           % args.local_pkgs_path)\r
121         configmgr.create['local_pkgs_path'] = args.local_pkgs_path\r
122 \r
123     if args.release:\r
124         configmgr.create['release'] = args.release.rstrip('/')\r
125 \r
126     if args.record_pkgs:\r
127         configmgr.create['record_pkgs'] = []\r
128         for infotype in args.record_pkgs.split(','):\r
129             if infotype not in ('name', 'content', 'license', 'vcs'):\r
130                 raise errors.Usage('Invalid pkg recording: %s, valid ones:'\r
131                                    ' "name", "content", "license", "vcs"' \\r
132                                    % infotype)\r
133 \r
134             configmgr.create['record_pkgs'].append(infotype)\r
135 \r
136     if args.strict_mode:\r
137       configmgr.create['strict_mode'] = args.strict_mode\r
138     if args.arch is not None:\r
139         supported_arch = sorted(rpmmisc.archPolicies.keys(), reverse=True)\r
140         if args.arch in supported_arch:\r
141             configmgr.create['arch'] = args.arch\r
142         else:\r
143             raise errors.Usage('Invalid architecture: "%s".\n'\r
144                                '  Supported architectures are: \n'\r
145                                '  %s' % (args.arch,\r
146                                            ', '.join(supported_arch)))\r
147 \r
148     if args.pkgmgr is not None:\r
149         configmgr.create['pkgmgr'] = args.pkgmgr\r
150 \r
151     if args.runtime:\r
152         configmgr.set_runtime(args.runtime)\r
153 \r
154     if args.use_mic_in_bootstrap:\r
155         configmgr.create['use_mic_in_bootstrap'] = args.use_mic_in_bootstrap\r
156 \r
157     if args.pack_to is not None:\r
158         configmgr.create['pack_to'] = args.pack_to\r
159 \r
160     if args.copy_kernel:\r
161         configmgr.create['copy_kernel'] = args.copy_kernel\r
162 \r
163     if args.install_pkgs:\r
164         configmgr.create['install_pkgs'] = []\r
165         for pkgtype in args.install_pkgs.split(','):\r
166             if pkgtype not in ('source', 'debuginfo', 'debugsource'):\r
167                 raise errors.Usage('Invalid parameter specified: "%s", '\r
168                                    'valid values: source, debuginfo, '\r
169                                    'debusource' % pkgtype)\r
170 \r
171             configmgr.create['install_pkgs'].append(pkgtype)\r
172 \r
173     if args.check_pkgs:\r
174         for pkg in args.check_pkgs.split(','):\r
175             configmgr.create['check_pkgs'].append(pkg)\r
176 \r
177     if args.enabletmpfs:\r
178         configmgr.create['enabletmpfs'] = args.enabletmpfs\r
179 \r
180     if args.repourl:\r
181         for item in args.repourl:\r
182             try:\r
183                 key, val = item.split('=')\r
184             except:\r
185                 continue\r
186             configmgr.create['repourl'][key] = val\r
187 \r
188     if args.repo:\r
189         for optvalue in args.repo:\r
190             repo = {}\r
191             for item in optvalue.split(';'):\r
192                 try:\r
193                     key, val = item.split('=')\r
194                 except:\r
195                     continue\r
196                 repo[key.strip()] = val.strip()\r
197             if 'name' in repo:\r
198                 configmgr.create['extrarepos'][repo['name']] = repo\r
199 \r
200     if args.ignore_ksrepo:\r
201         configmgr.create['ignore_ksrepo'] = args.ignore_ksrepo\r
202     if args.run_script:\r
203         configmgr.create['run_script'] = args.run_script\r
204     if args.tpk_install:\r
205         configmgr.create['tpk_install'] = args.tpk_install\r
206 \r
207     creater = createrClass()\r
208     creater.do_create(args)\r
209 \r
210 def do_auto(parser, ksfile, argv):\r
211         """${cmd_name}: auto detect image type from magic header\r
212 \r
213         Usage:\r
214             ${name} ${cmd_name} <ksfile>\r
215 \r
216         ${cmd_option_list}\r
217         """\r
218         def parse_magic_line(re_str, pstr, ptype='mic'):\r
219             ptn = re.compile(re_str)\r
220             m = ptn.match(pstr)\r
221             if not m or not m.groups():\r
222                 return None\r
223 \r
224             inline_argv = m.group(1).strip()\r
225             if ptype == 'mic':\r
226                 m2 = re.search('(?P<format>\w+)', inline_argv)\r
227             elif ptype == 'mic2':\r
228                 m2 = re.search('(-f|--format(=)?)\s*(?P<format>\w+)',\r
229                                inline_argv)\r
230             else:\r
231                 return None\r
232 \r
233             if m2:\r
234                 cmdname = m2.group('format')\r
235                 inline_argv = inline_argv.replace(m2.group(0), '')\r
236                 return (cmdname, inline_argv)\r
237 \r
238             return None\r
239 \r
240         if not os.path.exists(ksfile):\r
241             raise errors.CreatorError("Can't find the file: %s" % ksfile)\r
242 \r
243         with open(ksfile, 'r') as rf:\r
244             first_line = rf.readline()\r
245 \r
246         mic_re = '^#\s*-\*-mic-options-\*-\s+(.*)\s+-\*-mic-options-\*-'\r
247         mic2_re = '^#\s*-\*-mic2-options-\*-\s+(.*)\s+-\*-mic2-options-\*-'\r
248 \r
249         result = parse_magic_line(mic_re, first_line, 'mic') \\r
250                  or parse_magic_line(mic2_re, first_line, 'mic2')\r
251         if not result:\r
252             raise errors.KsError("Invalid magic line in file: %s" % ksfile)\r
253         \r
254         ksargv = ' '.join(result).split()\r
255 \r
256         argv.remove("auto")\r
257         index = argv.index("create")\r
258         #insert the subcommand\r
259         argv.insert(index+1, ksargv[0])\r
260         options = argv + ksargv[1:]\r
261 \r
262         args = parser.parse_args(options)\r
263 \r
264         main(parser, args, options)\r
265 \r