3 #Copyright (c) 2011 Intel, Inc.
5 #This program is free software; you can redistribute it and/or modify it
6 #under the terms of the GNU General Public License as published by the Free
7 #Software Foundation; version 2 of the License
9 #This program is distributed in the hope that it will be useful, but
10 #WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 # You should have received a copy of the GNU General Public License along
15 # with this program; if not, write to the Free Software Foundation, Inc., 59
16 # Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 # pylint: disable-msg=E0611, E1101, R0201
19 # E0611: no name in module, some attributes are set during running, so ignore it
20 # E1101: %s %r has no %r member, some attributes are set during running,
22 # R0201: Method could be a function
25 This mudule is entry for mic.
26 It defines a class named MicCmd inheriting Cmdln, and supplies interfaces like
27 'create, chroot, convert' and also some parameters for command 'mic'.
33 from argparse import ArgumentParser, SUPPRESS
35 from mic import msger, __version__ as VERSION
36 from mic.utils import misc, errors
37 from mic.conf import configmgr
38 from mic.plugin import pluginmgr
39 from mic.helpformat import MICHelpFormatter, subparser
43 def chroot_parser(parser):
44 """chroot into an image
47 mic chroot platform.img
48 mic chroot platform.img ls
50 parser.add_argument('imagefile', help='Path of image file')
51 parser.add_argument('-s', '--saveto', action = 'store', dest = 'saveto', default = None,
52 help = "Save the unpacked image to specified dir")
53 parser.add_argument('-c', '--cmd', dest = 'cmd', default = None,
54 help = "command which will be executed in chroot environment")
55 parser.set_defaults(alias="ch")
59 def create_parser(parser):
62 $ mic -d -v create auto handset_blackbay.ks
63 $ mic -d -v cr loop handset_blackbay.ks --logfile=mic.log
66 parent_parser = ArgumentParser(add_help=False)
67 parent_parser.add_argument('ksfile', help='Path of ksfile');
68 parent_parser.add_argument('--logfile', dest='logfile', default=None,
69 help='Path of logfile')
70 parent_parser.add_argument('-c', '--config', dest='config', default=None,
71 help='Specify config file for mic')
72 parent_parser.add_argument('-k', '--cachedir', action='store',
73 dest='cachedir', default=None,
74 help='Cache directory to store the downloaded')
75 parent_parser.add_argument('-o', '--outdir', action='store', dest='outdir',
76 default=None, help='Output directory')
77 parent_parser.add_argument('-A', '--arch', dest='arch', default=None,
78 help='Specify repo architecture')
79 parent_parser.add_argument('--release', dest='release', default=None, metavar='RID',
80 help='Generate a release of RID with all necessary'
81 ' files, when @BUILD_ID@ is contained in '
82 'kickstart file, it will be replaced by RID')
83 parent_parser.add_argument("--record-pkgs", dest="record_pkgs", default=None,
84 help='Record the info of installed packages, '
85 'multiple values can be specified which '
86 'joined by ",", valid values: "name", '
87 '"content", "license", "vcs"')
88 parent_parser.add_argument('--pkgmgr', dest='pkgmgr', default=None,
89 help='Specify backend package manager')
90 parent_parser.add_argument('--local-pkgs-path', dest='local_pkgs_path', default=None,
91 help='Path for local pkgs(rpms) to be installed')
92 parent_parser.add_argument('--runtime', dest='runtime', default=None,
93 help='Specify runtime mode, avaiable: bootstrap')
94 # --taring-to is alias to --pack-to
95 parent_parser.add_argument('--taring-to', dest='pack_to', default=None,
97 parent_parser.add_argument('--pack-to', dest='pack_to', default=None,
98 help='Pack the images together into the specified'
99 ' achive, extension supported: .zip, .tar, '
100 '.tar.gz, .tar.bz2, etc. by default, .tar '
102 parent_parser.add_argument('--copy-kernel', action='store_true', dest='copy_kernel',
103 help='Copy kernel files from image /boot directory'
104 ' to the image output directory.')
105 parent_parser.add_argument('--install-pkgs', action='store', dest='install_pkgs', default=None,
106 help='Specify what type of packages to be installed,'
107 ' valid: source, debuginfo, debugsource')
108 parent_parser.add_argument('--check-pkgs', action='store', dest='check_pkgs', default=[],
109 help='Check if given packages would be installed, '
110 'packages should be separated by comma')
111 parent_parser.add_argument('--tmpfs', action='store_true', dest='enabletmpfs',
112 help='Setup tmpdir as tmpfs to accelerate, experimental'
113 ' feature, use it if you have more than 4G memory')
114 parent_parser.add_argument('--repourl', action='append', dest='repourl', default=[],
116 parent_parser.add_argument('-R', '--repo', action='append',
117 dest='repo', default=[],
119 parent_parser.add_argument('--ignore-ksrepo', action='store_true',
120 dest='ignore_ksrepo', default=False,
122 parent_parser.add_argument('--strict-mode', action='store_true',
123 dest='strict_mode', default=False,
124 help='Abort creation of image, if there are some errors'
125 ' during rpm installation. ')
126 parser.set_defaults(alias="cr")
128 subparsers = parser.add_subparsers(title='Subcommands', dest='subcommand')
129 fs_parser = subparsers.add_parser('fs', parents=[parent_parser],
130 help='auto detect image type from magic header')
131 fs_parser.add_argument("--include-src", dest = "include_src",action = "store_true",
132 default = False, help = "Generate a image with source rpms included")
134 auto_parser = subparsers.add_parser('auto', parents=[parent_parser], help='create fs image')
135 loop_parser = subparsers.add_parser('loop', parents=[parent_parser], help='create loop image')
137 loop_parser.add_argument("--compress-disk-image", dest="compress_image",
138 choices=("gz", "bz2", "lzo"), default=None,
139 help="Same with --compress-image")
140 # alias to compress-image for compatibility
141 loop_parser.add_argument("--compress-image", dest="compress_image",
142 choices=("gz", "bz2", "lzo"), default=None,
143 help="Compress all loop images with 'gz' or 'bz2' or 'lzo',"
144 "Note: if you want to use 'lzo', package 'lzop' is needed to"
145 "be installed manually.")
146 loop_parser.add_argument("--shrink", action='store_true', default=False,
147 help="Whether to shrink loop images to minimal size")
149 qcow_parser = subparsers.add_parser('qcow', parents=[parent_parser], help='create qcow image')
154 """Script entry point."""
157 """log name, verion, hostname"""
160 msger.raw("%s %s (%s)" % (name,
162 misc.get_hostname_distro_str()))
164 def has_parameter(arg, arglist):
167 Check if argument requires parameter by analyzing
168 its action. Parameter is required only for 'store' and 'append' actions
170 if arg.startswith('-'):
172 if arg in (args['short'], args['long']):
173 if args.get('action') in (None, 'store', 'append'):
177 # Create top level parser
178 epilog = "Try 'mic SUBCOMMAND --help' for help on a specific subcommand."
179 description = "mic - the Image Creation tool"
180 parser = ArgumentParser(description=description, epilog=epilog,
181 formatter_class=MICHelpFormatter)
183 # List of global arguments
184 # The main purpose of this structure is to contain arguments
185 # of add_argument. This is used to do aliasing properly
186 # (see code under the comment 'replace aliases with real commands')
187 global_args = [{'short': '-V', 'long': '--version', 'action': 'version',
188 'version': '%(prog)s ' + VERSION},
189 {'short': '-d', 'long': '--debug', 'action': 'store_true',
190 'help': 'debug output'},
191 {'short': '-v', 'long': '--verbose', 'action': 'store_true',
192 'help': 'verbose output'},
193 {'short': '-i', 'long': '--interactive', 'action': 'store_true',
194 'dest': 'interactive', 'default': 'True', 'help': 'interactive output'},
195 {'short': '', 'long': '--non-interactive', 'action': 'store_false',
196 'dest': 'interactive', 'default': 'True', 'help': 'non-interactive output'},
199 for args in global_args:
201 for key in ('action', 'help', 'version', 'default', 'dest'):
203 parser_kwargs[key] = args[key]
205 if args['short'] is '':
206 parser.add_argument(args['long'], **parser_kwargs)
208 parser.add_argument(args['short'], args['long'], **parser_kwargs)
210 # hacked by the request of cmdln lovers
211 parser.format_usage = parser.format_help
213 # Create parsers for subcommands
214 subparsers = parser.add_subparsers(title='subcommands')
218 for name, obj in globals().iteritems():
219 if name.endswith('_parser') and callable(obj):
220 aliases[obj(subparsers).get_default('alias')] = name.split('_')[0]
222 # replace aliases with real commands
223 for i, arg in enumerate(argv[1:]):
224 if not arg.startswith('-'):
225 # argv[i] is previous argument to arg
226 if not has_parameter(argv[i], global_args) and arg in aliases:
227 argv[i+1] = aliases[arg]
231 args = parser.parse_args(argv[1:])
234 msger.enable_interactive()
236 msger.disable_interactive()
239 msger.set_loglevel('VERBOSE')
244 rpm.setVerbosity(rpm.RPMLOG_NOTICE)
248 msger.set_loglevel('DEBUG')
252 # Import target module and call 'main' from it
253 module = __import__("mic.%s" % args.module, fromlist=[args.module])
254 return module.main(parser, args, argv[1:])
257 if __name__ == "__main__":
259 sys.exit(main(sys.argv))
260 except KeyboardInterrupt:
261 msger.error('\n^C catched, program aborted.')
262 except IOError as ioerr:
263 # catch 'no space left' exception, etc
264 if ioerr.errno == errno.ENOSPC:
265 msger.error('\nNo space left on device')
267 except errors.Usage as usage:
268 msger.error(str(usage))
269 except errors.Abort as msg:
271 except errors.CreatorError as err:
272 if msger.get_loglevel() == 'DEBUG':
274 msger.error(traceback.format_exc())
276 msger.error(str(err))