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