Drop MIC liveusb image format support
[platform/upstream/mic.git] / tools / mic
1 #!/usr/bin/env python
2
3 #Copyright (c) 2011 Intel, Inc.
4 #
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
8 #
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
12 # for more details.
13 #
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.
17 #
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,
21 #        so ignore it
22 # R0201: Method could be a function
23
24 """
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'.
28 """
29 import os
30 import sys
31 import errno
32
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
37
38
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()
44     return func
45
46
47 class MicCmd(cmdln.Cmdln):
48     """
49     Usage: mic SUBCOMMAND [OPTS] [ARGS...]
50
51     mic Means the Image Creation tool
52     Try 'mic help SUBCOMMAND' for help on a specific subcommand.
53
54     ${command_list}
55     global ${option_list}
56     ${help_list}
57     """
58     name = 'mic'
59     version = VERSION
60
61     def print_version(self):
62         """log name, verion, hostname"""
63
64         msger.raw("%s %s (%s)" % (self.name,
65                                   self.version,
66                                   misc.get_hostname_distro_str()))
67
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',
73                              dest='debug',
74                              help='print debug message')
75         optparser.add_option('-v', '--verbose', action='store_true',
76                              dest='verbose',
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')
84         return optparser
85
86     def postoptparse(self):
87         if self.options.interactive:
88             msger.enable_interactive()
89         else:
90             msger.disable_interactive()
91
92         if self.options.verbose:
93             msger.set_loglevel('VERBOSE')
94
95         if self.options.debug:
96             try:
97                 import rpm
98                 rpm.setVerbosity(rpm.RPMLOG_NOTICE)
99             except ImportError:
100                 pass
101
102             msger.set_loglevel('DEBUG')
103
104         self.print_version()
105
106     def help_create(self):
107         """Get help info from doc string.
108            Fill symbols with real parameters
109         """
110         crobj = creator.Creator()
111         crobj.optparser = crobj.get_optparser()
112         doc = crobj.__doc__
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'
117         return doc
118
119     @cmdln.alias("cr")
120     def do_create(self, argv):
121         """Main for creating image"""
122         crobj = creator.Creator()
123         crobj.main(argv[1:])
124
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')
131
132     @cmdln.alias("cv")
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
138  
139         Usage:
140             mic convert <imagefile> <destformat>
141
142         ${cmd_option_list}
143         """
144         if not args or len(args) != 2:
145             # print help
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")
150
151         (srcimg, destformat) = args
152
153         if not os.path.exists(srcimg):
154             raise errors.CreatorError("Cannot find the image: %s" % srcimg)
155
156         self._root_confirm()
157
158         configmgr.convert['shell'] = opts.shell
159
160         srcformat = misc.get_image_type(srcimg)
161         if srcformat == "ext3fsimg":
162             srcformat = "loop"
163
164         srcimager = None
165         destimager = None
166         for iname, icls in pluginmgr.get_plugins('imager').iteritems():
167             if iname == srcformat and hasattr(icls, "do_unpack"):
168                 srcimager = icls
169             if iname == destformat and hasattr(icls, "do_pack"):
170                 destimager = icls
171
172         if (srcimager and destimager) is None:
173             raise errors.CreatorError("Can't convert from %s to %s" \
174                                   % (srcformat, destformat))
175         maptab = {
176                     "livecd": "iso",
177                     "loop": "img",
178                  }
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):
185                     os.unlink(dstname)
186                 else:
187                     raise errors.Abort("Canceled")
188
189         destimager.do_pack(srcimager.do_unpack(srcimg))
190
191     @cmdln.alias("ch")
192     @cmdln.option('-s', '--saveto',
193                   action = 'store', dest = 'saveto', default = None,
194                   help = "Save the unpacked image to specified dir")
195     @optparser_setup
196     def do_chroot(self, _subcmd, opts, *args):
197         """${cmd_name}: chroot into an image
198
199         Usage:
200             mic chroot [options] <imagefile> [command [arg]...]
201
202         ${cmd_option_list}
203         """
204         if not args:
205             # print help
206             handler = self._get_cmd_handler('chroot')
207             if hasattr(handler, "optparser"):
208                 handler.optparser.print_help()
209             return 1
210
211         targetimage = args[0]
212         if not os.path.exists(targetimage):
213             raise errors.CreatorError("Cannot find the image: %s"
214                                       % targetimage)
215
216         self._root_confirm()
217
218         configmgr.chroot['saveto'] = opts.saveto
219
220         imagetype = misc.get_image_type(targetimage)
221         if imagetype in ("ext3fsimg", "ext4fsimg", "btrfsimg"):
222             imagetype = "loop"
223
224         chrootclass = None
225         for pname, pcls in pluginmgr.get_plugins('imager').iteritems():
226             if pname == imagetype and hasattr(pcls, "do_chroot"):
227                 chrootclass = pcls
228                 break
229
230         if not chrootclass:
231             raise errors.CreatorError("Cannot support image type: %s" \
232                                       % imagetype)
233
234         chrootclass.do_chroot(targetimage, args[1:])
235
236
237 if __name__ == "__main__":
238     try:
239         MIC = MicCmd()
240         sys.exit(MIC.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')
247         raise
248     except errors.Usage as usage:
249         msger.error(str(usage))
250     except errors.Abort as  msg:
251         msger.info(str(msg))
252     except errors.CreatorError as err:
253         if msger.get_loglevel() == 'DEBUG':
254             import traceback
255             msger.error(traceback.format_exc())
256         else:
257             msger.error(str(err))