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 mic import msger, creator, __version__ as VERSION
34 from mic.utils import cmdln, misc, errors
35 from mic.conf import configmgr
36 from mic.plugin import pluginmgr
39 def optparser_setup(func):
40 """Setup optparser for a function"""
41 if not hasattr(func, "optparser"):
42 func.optparser = cmdln.SubCmdOptionParser()
43 func.optparser.disable_interspersed_args()
47 class MicCmd(cmdln.Cmdln):
49 Usage: mic SUBCOMMAND [OPTS] [ARGS...]
51 mic Means the Image Creation tool
52 Try 'mic help SUBCOMMAND' for help on a specific subcommand.
61 def print_version(self):
62 """log name, verion, hostname"""
64 msger.raw("%s %s (%s)" % (self.name,
66 misc.get_hostname_distro_str()))
68 def get_optparser(self):
69 optparser = cmdln.CmdlnOptionParser(self, version=self.version)
70 # hook optparse print_version here
71 optparser.print_version = self.print_version
72 optparser.add_option('-d', '--debug', action='store_true',
74 help='print debug message')
75 optparser.add_option('-v', '--verbose', action='store_true',
77 help='verbose information')
78 optparser.add_option('-i', '--interactive', action='store_true',
79 dest='interactive', default='True',
80 help='interactive output')
81 optparser.add_option('--non-interactive', action='store_false',
82 dest='interactive', default='True',
83 help='non-interactive output')
86 def postoptparse(self):
87 if self.options.interactive:
88 msger.enable_interactive()
90 msger.disable_interactive()
92 if self.options.verbose:
93 msger.set_loglevel('VERBOSE')
95 if self.options.debug:
98 rpm.setVerbosity(rpm.RPMLOG_NOTICE)
102 msger.set_loglevel('DEBUG')
106 def help_create(self):
107 """Get help info from doc string.
108 Fill symbols with real parameters
110 crobj = creator.Creator()
111 crobj.optparser = crobj.get_optparser()
113 doc = crobj.help_reindent(doc)
114 doc = crobj.help_preprocess(doc, None)
115 doc = doc.replace(crobj.name, "${cmd_name}", 1)
116 doc = doc.rstrip() + '\n'
120 def do_create(self, argv):
121 """Main for creating image"""
122 crobj = creator.Creator()
125 def _root_confirm(self):
126 """Make sure command is called by root
127 There are a lot of commands needed to be run during creating images,
128 some of them must be run with root privilege like mount, kpartx"""
129 if os.geteuid() != 0:
130 msger.error('Root permission is required to continue, abort')
133 @cmdln.option("-S", "--shell",
134 action="store_true", dest="shell", default=False,
135 help="Launch shell before packaging the converted image")
136 def do_convert(self, _subcmd, opts, *args):
137 """${cmd_name}: convert image format
140 mic convert <imagefile> <destformat>
144 if not args or len(args) != 2:
146 handler = self._get_cmd_handler('convert')
147 if hasattr(handler, "optparser"):
148 handler.optparser.print_help()
149 raise errors.Usage("2 arguments and only 2 are required")
151 (srcimg, destformat) = args
153 if not os.path.exists(srcimg):
154 raise errors.CreatorError("Cannot find the image: %s" % srcimg)
158 configmgr.convert['shell'] = opts.shell
160 srcformat = misc.get_image_type(srcimg)
161 if srcformat == "ext3fsimg":
166 for iname, icls in pluginmgr.get_plugins('imager').iteritems():
167 if iname == srcformat and hasattr(icls, "do_unpack"):
169 if iname == destformat and hasattr(icls, "do_pack"):
172 if (srcimager and destimager) is None:
173 raise errors.CreatorError("Can't convert from %s to %s" \
174 % (srcformat, destformat))
179 if destformat in maptab:
180 imgname = os.path.splitext(os.path.basename(srcimg))[0]
181 dstname = "{0}.{1}".format(imgname, maptab[destformat])
182 if os.path.exists(dstname):
183 if msger.ask("Converted image %s seems existed, "
184 "remove and continue?" % dstname):
187 raise errors.Abort("Canceled")
189 destimager.do_pack(srcimager.do_unpack(srcimg))
192 @cmdln.option('-s', '--saveto',
193 action = 'store', dest = 'saveto', default = None,
194 help = "Save the unpacked image to specified dir")
196 def do_chroot(self, _subcmd, opts, *args):
197 """${cmd_name}: chroot into an image
200 mic chroot [options] <imagefile> [command [arg]...]
206 handler = self._get_cmd_handler('chroot')
207 if hasattr(handler, "optparser"):
208 handler.optparser.print_help()
211 targetimage = args[0]
212 if not os.path.exists(targetimage):
213 raise errors.CreatorError("Cannot find the image: %s"
218 configmgr.chroot['saveto'] = opts.saveto
220 imagetype = misc.get_image_type(targetimage)
221 if imagetype in ("ext3fsimg", "ext4fsimg", "btrfsimg"):
225 for pname, pcls in pluginmgr.get_plugins('imager').iteritems():
226 if pname == imagetype and hasattr(pcls, "do_chroot"):
231 raise errors.CreatorError("Cannot support image type: %s" \
234 chrootclass.do_chroot(targetimage, args[1:])
237 if __name__ == "__main__":
241 except KeyboardInterrupt:
242 msger.error('\n^C catched, program aborted.')
243 except IOError as ioerr:
244 # catch 'no space left' exception, etc
245 if ioerr.errno == errno.ENOSPC:
246 msger.error('\nNo space left on device')
248 except errors.Usage as usage:
249 msger.error(str(usage))
250 except errors.Abort as msg:
252 except errors.CreatorError as err:
253 if msger.get_loglevel() == 'DEBUG':
255 msger.error(traceback.format_exc())
257 msger.error(str(err))