Fix pylint tips
[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                     "liveusb": "usbimg",
178                     "loop": "img",
179                  }
180         if destformat in maptab:
181             imgname = os.path.splitext(os.path.basename(srcimg))[0]
182             dstname = "{0}.{1}".format(imgname, maptab[destformat])
183             if os.path.exists(dstname):
184                 if msger.ask("Converted image %s seems existed, "
185                              "remove and continue?" % dstname):
186                     os.unlink(dstname)
187                 else:
188                     raise errors.Abort("Canceled")
189
190         destimager.do_pack(srcimager.do_unpack(srcimg))
191
192     @cmdln.alias("ch")
193     @cmdln.option('-s', '--saveto',
194                   action = 'store', dest = 'saveto', default = None,
195                   help = "Save the unpacked image to specified dir")
196     @optparser_setup
197     def do_chroot(self, _subcmd, opts, *args):
198         """${cmd_name}: chroot into an image
199
200         Usage:
201             mic chroot [options] <imagefile> [command [arg]...]
202
203         ${cmd_option_list}
204         """
205         if not args:
206             # print help
207             handler = self._get_cmd_handler('chroot')
208             if hasattr(handler, "optparser"):
209                 handler.optparser.print_help()
210             return 1
211
212         targetimage = args[0]
213         if not os.path.exists(targetimage):
214             raise errors.CreatorError("Cannot find the image: %s"
215                                       % targetimage)
216
217         self._root_confirm()
218
219         configmgr.chroot['saveto'] = opts.saveto
220
221         imagetype = misc.get_image_type(targetimage)
222         if imagetype in ("ext3fsimg", "ext4fsimg", "btrfsimg"):
223             imagetype = "loop"
224
225         chrootclass = None
226         for pname, pcls in pluginmgr.get_plugins('imager').iteritems():
227             if pname == imagetype and hasattr(pcls, "do_chroot"):
228                 chrootclass = pcls
229                 break
230
231         if not chrootclass:
232             raise errors.CreatorError("Cannot support image type: %s" \
233                                       % imagetype)
234
235         chrootclass.do_chroot(targetimage, args[1:])
236
237
238 if __name__ == "__main__":
239     try:
240         MIC = MicCmd()
241         sys.exit(MIC.main())
242     except KeyboardInterrupt:
243         msger.error('\n^C catched, program aborted.')
244     except IOError as ioerr:
245         # catch 'no space left' exception, etc
246         if ioerr.errno == errno.ENOSPC:
247             msger.error('\nNo space left on device')
248         raise
249     except errors.Usage as usage:
250         msger.error(str(usage))
251     except errors.Abort as  msg:
252         msger.info(str(msg))
253     except errors.CreatorError as err:
254         if msger.get_loglevel() == 'DEBUG':
255             import traceback
256             msger.error(traceback.format_exc())
257         else:
258             msger.error(str(err))