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