c55c5f1df33f7c8017c8a5c7c1cafdab5af054ef
[tools/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 import os, sys, errno
19 from mic import msger, creator
20 from mic.utils import cmdln, misc, errors
21 from mic.conf import configmgr
22 from mic.plugin import pluginmgr
23 from mic.__version__ import VERSION
24
25 class MicCmd(cmdln.Cmdln):
26     """
27     Usage: mic SUBCOMMAND [OPTS] [ARGS...]
28
29     mic Means the Image Creation tool
30     Try 'mic help SUBCOMAND' for help on a specific subcommand.
31
32     ${command_list}
33     global ${option_list}
34     ${help_list}
35     """
36
37     name = 'mic'
38     version = VERSION
39
40     def get_optparser(self):
41         optparser = cmdln.CmdlnOptionParser(self, version=self.version)
42         optparser.add_option('-d', '--debug', action='store_true',
43                              dest='debug',
44                              help='print debug message')
45         optparser.add_option('-v', '--verbose', action='store_true',
46                              dest='verbose',
47                              help='verbose information')
48         return optparser
49
50     def postoptparse(self):
51         if self.options.verbose:
52             msger.set_loglevel('verbose')
53
54         if self.options.debug:
55             try:
56                 import rpm
57                 rpm.setVerbosity(rpm.RPMLOG_NOTICE)
58             except ImportError:
59                 pass
60
61             msger.set_loglevel('debug')
62
63     def help_create(self):
64         cr = creator.Creator()
65         cr.optparser = cr.get_optparser()
66         doc = cr.__doc__
67         doc = cr._help_reindent(doc)
68         doc = cr._help_preprocess(doc, None)
69         doc = doc.replace(cr.name, "${cmd_name}", 1)
70         doc = doc.rstrip() + '\n'
71         return doc
72
73     @cmdln.alias("cr")
74     def do_create(self, argv):
75         try:
76             cr = creator.Creator()
77             cr.main(argv[1:])
78         except:
79             raise
80
81     def _root_confirm(self):
82         if os.geteuid() != 0:
83             msger.error('Root permission is required to continue, abort')
84
85     @cmdln.alias("cv")
86     @cmdln.option("-S", "--shell",
87                   action="store_true", dest="shell", default=False,
88                   help="Launch shell before packaging the converted image")
89     def do_convert(self, subcmd, opts, *args):
90         """${cmd_name}: convert image format
91
92         Usage:
93             mic convert <imagefile> <destformat>
94
95         ${cmd_option_list}
96         """
97
98         if not args:
99             # print help
100             handler = self._get_cmd_handler('convert')
101             if hasattr(handler, "optparser"):
102                 handler.optparser.print_help()
103             return 1
104
105         if len(args) == 1:
106             raise errors.Usage("It need 2 arguments (1 given)")
107         elif len(args) == 2:
108             (srcimg, destformat) = args
109         else:
110             raise errors.Usage("Extra argument given")
111
112         if not os.path.exists(srcimg):
113             raise errors.CreatorError("Cannot find the image: %s" % srcimg)
114
115         self._root_confirm()
116
117         configmgr.convert['shell'] = opts.shell
118
119         srcformat = misc.get_image_type(srcimg)
120         if srcformat == "ext3fsimg":
121             srcformat = "loop"
122
123         srcimager = None
124         destimager = None
125         for iname, icls in pluginmgr.get_plugins('imager').iteritems():
126            if iname == srcformat and hasattr(icls, "do_unpack"):
127                srcimager = icls
128            if iname == destformat and hasattr(icls, "do_pack"):
129                destimager = icls
130
131         if (srcimager and destimager) is None:
132            raise errors.CreatorError("Can't convert from %s to %s" \
133                                      % (srcformat, destformat))
134         else:
135             base_on = srcimager.do_unpack(srcimg)
136             destimager.do_pack(base_on)
137
138     @cmdln.alias("ch")
139     def do_chroot(self, subcmd, opts, *args):
140         """${cmd_name}: chroot into an image
141
142         Usage:
143             mic chroot <imagefile>
144
145         ${cmd_option_list}
146         """
147
148         if not args:
149             # print help
150             handler = self._get_cmd_handler('chroot')
151             if hasattr(handler, "optparser"):
152                 handler.optparser.print_help()
153             return 1
154
155         if len(args) == 1:
156             targetimage = args[0]
157         else:
158             raise errors.Usage("Extra argument given")
159
160         if not os.path.exists(targetimage):
161             raise errors.CreatorError("Cannot find the image: %s"
162                                       % targetimage)
163
164         self._root_confirm()
165
166         imagetype = misc.get_image_type(targetimage)
167         if imagetype in ("ext3fsimg", "ext4fsimg", "btrfsimg"):
168             imagetype = "loop"
169
170         chrootclass = None
171         for pname, pcls in pluginmgr.get_plugins('imager').iteritems():
172             if pname == imagetype and hasattr(pcls, "do_chroot"):
173                 chrootclass = pcls
174                 break
175
176         if not chrootclass:
177             raise errors.CreatorError("Cannot support image type: %s" \
178                                       % imagetype)
179
180         chrootclass.do_chroot(targetimage)
181
182 if __name__ == "__main__":
183     try:
184         mic = MicCmd()
185         sys.exit(mic.main())
186
187     except KeyboardInterrupt:
188         msger.error('\n^C catched, program aborted.')
189
190     # catch 'no space left' exception, etc
191     except IOError, e:
192         if e.errno == errno.ENOSPC:
193             msger.error('\nNo space left on device')
194         raise
195
196     except errors.Usage, usage:
197         msger.error(str(usage))
198
199     except errors.Abort, msg:
200         msger.info(str(msg))
201
202     except errors.CreatorError, err:
203         if msger.get_loglevel() == 'debug':
204             import traceback
205             msger.error(traceback.format_exc())
206         else:
207             msger.error('\n'+str(err))