1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 import logging
20 import optparse
21 import os
22 import pwd
23 import shutil
24 import sys
25 import VMBuilder
26 import VMBuilder.util as util
27 from VMBuilder.disk import parse_size
28 import VMBuilder.hypervisor
29 from VMBuilder.exception import VMBuilderUserError, VMBuilderException
30
32 arg = 'cli'
33
35 try:
36 optparser = optparse.OptionParser()
37
38 self.set_usage(optparser)
39
40 optparser.add_option('--version', action='callback', callback=self.versioninfo, help='Show version information')
41
42 group = optparse.OptionGroup(optparser, 'Build options')
43 group.add_option('--debug', action='callback', callback=self.set_verbosity, help='Show debug information')
44 group.add_option('--verbose', '-v', action='callback', callback=self.set_verbosity, help='Show progress information')
45 group.add_option('--quiet', '-q', action='callback', callback=self.set_verbosity, help='Silent operation')
46 group.add_option('--overwrite', '-o', action='store_true', help='Configuration file')
47 group.add_option('--config', '-c', type='str', help='Configuration file')
48 group.add_option('--templates', metavar='DIR', help='Prepend DIR to template search path.')
49 group.add_option('--destdir', '-d', type='str', help='Destination directory')
50 group.add_option('--only-chroot', action='store_true', help="Only build the chroot. Don't install it on disk images or anything.")
51 group.add_option('--existing-chroot', help="Use existing chroot.")
52 optparser.add_option_group(group)
53
54 group = optparse.OptionGroup(optparser, 'Disk')
55 group.add_option('--rootsize', metavar='SIZE', default=4096, help='Size (in MB) of the root filesystem [default: %default]')
56 group.add_option('--optsize', metavar='SIZE', default=0, help='Size (in MB) of the /opt filesystem. If not set, no /opt filesystem will be added.')
57 group.add_option('--swapsize', metavar='SIZE', default=1024, help='Size (in MB) of the swap partition [default: %default]')
58 group.add_option('--raw', metavar='PATH', type='str', help="Specify a file (or block device) to as first disk image.")
59 group.add_option('--part', metavar='PATH', type='str', help="Allows to specify a partition table in PATH each line of partfile should specify (root first): \n mountpoint size \none per line, separated by space, where size is in megabytes. You can have up to 4 virtual disks, a new disk starts on a line containing only '---'. ie: \n root 2000 \n /boot 512 \n swap 1000 \n --- \n /var 8000 \n /var/log 2000")
60 optparser.add_option_group(group)
61
62 hypervisor, distro = self.handle_args(optparser, sys.argv[1:])
63
64 self.add_settings_from_context(optparser, distro)
65 self.add_settings_from_context(optparser, hypervisor)
66
67 hypervisor.register_hook('fix_ownership', self.fix_ownership)
68
69 config_files = ['/etc/vmbuilder.cfg', os.path.expanduser('~/.vmbuilder.cfg')]
70 (self.options, args) = optparser.parse_args(sys.argv[2:])
71
72 if os.geteuid() != 0:
73 raise VMBuilderUserError('Must run as root')
74
75 destdir = self.options.destdir or ('%s-%s' % (distro.arg, hypervisor.arg))
76 if os.path.exists(destdir):
77 if self.options.overwrite:
78 logging.debug('%s existed, but -o was specified. Nuking it.' % destdir)
79 shutil.rmtree(destdir)
80 else:
81 raise VMBuilderUserError('%s already exists' % destdir)
82
83 if self.options.config:
84 config_files.append(self.options.config)
85 util.apply_config_files_to_context(config_files, distro)
86 util.apply_config_files_to_context(config_files, hypervisor)
87
88 if self.options.templates:
89 distro.template_dirs.insert(0,'%s/%%s' % self.options.templates)
90 hypervisor.template_dirs.insert(0,'%s/%%s' % self.options.templates)
91
92 for option in dir(self.options):
93 if option.startswith('_') or option in ['ensure_value', 'read_module', 'read_file']:
94 continue
95 val = getattr(self.options, option)
96 option = option.replace('_', '-')
97 if val:
98 if distro.has_setting(option) and distro.get_setting_default(option) != val:
99 distro.set_setting_fuzzy(option, val)
100 elif hypervisor.has_setting(option) and hypervisor.get_setting_default(option) != val:
101 hypervisor.set_setting_fuzzy(option, val)
102
103 chroot_dir = None
104 if self.options.existing_chroot:
105 distro.set_chroot_dir(self.options.existing_chroot)
106 distro.call_hooks('preflight_check')
107 else:
108 chroot_dir = util.tmpdir()
109 distro.set_chroot_dir(chroot_dir)
110 distro.build_chroot()
111
112 if self.options.only_chroot:
113 print 'Chroot can be found in %s' % distro.chroot_dir
114 sys.exit(0)
115
116 self.set_disk_layout(hypervisor)
117 hypervisor.install_os()
118
119 os.mkdir(destdir)
120 self.fix_ownership(destdir)
121 hypervisor.finalise(destdir)
122
123
124
125
126 if chroot_dir:
127 util.run_cmd('rm', '-rf', '--one-file-system', chroot_dir)
128 except VMBuilderException, e:
129 logging.error(e)
130 raise
131 sys.exit(1)
132
134 """
135 Change ownership of file to $SUDO_USER.
136
137 @type path: string
138 @param path: file or directory to give to $SUDO_USER
139 """
140 if 'SUDO_USER' in os.environ:
141 logging.debug('Changing ownership of %s to %s' % (filename, os.environ['SUDO_USER']))
142 (uid, gid) = pwd.getpwnam(os.environ['SUDO_USER'])[2:4]
143 os.chown(filename, uid, gid)
144
145 - def add_settings_from_context(self, optparser, context):
146 setting_groups = set([setting.setting_group for setting in context._config.values()])
147 for setting_group in setting_groups:
148 optgroup = optparse.OptionGroup(optparser, setting_group.name)
149 for setting in setting_group._settings:
150 args = ['--%s' % setting.name]
151 args += setting.extra_args
152 kwargs = {}
153 if setting.help:
154 kwargs['help'] = setting.help
155 if len(setting.extra_args) > 0:
156 setting.help += " Config option: %s" % setting.name
157 if setting.metavar:
158 kwargs['metavar'] = setting.metavar
159 if setting.get_default():
160 kwargs['default'] = setting.get_default()
161 if type(setting) == VMBuilder.plugins.Plugin.BooleanSetting:
162 kwargs['action'] = 'store_true'
163 if type(setting) == VMBuilder.plugins.Plugin.ListSetting:
164 kwargs['action'] = 'append'
165 optgroup.add_option(*args, **kwargs)
166 optparser.add_option_group(optgroup)
167
171
173 optparser.set_usage('%prog hypervisor distro [options]')
174
175
182
190
192 default_filesystem = hypervisor.distro.preferred_filesystem()
193 if not self.options.part:
194 rootsize = parse_size(self.options.rootsize)
195 swapsize = parse_size(self.options.swapsize)
196 optsize = parse_size(self.options.optsize)
197 if hypervisor.preferred_storage == VMBuilder.hypervisor.STORAGE_FS_IMAGE:
198 tmpfile = util.tmpfile(keep=False)
199 hypervisor.add_filesystem(filename=tmpfile, size='%dM' % rootsize, type='ext3', mntpnt='/')
200 tmpfile = util.tmpfile(keep=False)
201 hypervisor.add_filesystem(filename=tmpfile, size='%dM' % swapsize, type='swap', mntpnt=None)
202 if optsize > 0:
203 tmpfile = util.tmpfile(keep=False)
204 hypervisor.add_filesystem(filename=tmpfile, size='%dM' % optsize, type='ext3', mntpnt='/opt')
205 else:
206 if self.options.raw:
207 disk = hypervisor.add_disk(filename=self.options.raw)
208 else:
209 size = rootsize + swapsize + optsize
210 tmpfile = util.tmpfile(keep=False)
211 disk = hypervisor.add_disk(tmpfile, size='%dM' % size)
212 offset = 0
213 disk.add_part(offset, rootsize, default_filesystem, '/')
214 offset += rootsize
215 disk.add_part(offset, swapsize, 'swap', 'swap')
216 offset += swapsize
217 if optsize > 0:
218 disk.add_part(offset, optsize, default_filesystem, '/opt')
219 else:
220
221 if hypervisor.preferred_storage == VMBuilder.hypervisor.STORAGE_FS_IMAGE:
222 try:
223 for line in file(self.options.part):
224 elements = line.strip().split(' ')
225 tmpfile = util.tmpfile(keep=False)
226 if elements[0] == 'root':
227 hypervisor.add_filesystem(elements[1], default_filesystem, filename=tmpfile, mntpnt='/')
228 elif elements[0] == 'swap':
229 hypervisor.add_filesystem(elements[1], type='swap', filename=tmpfile, mntpnt=None)
230 elif elements[0] == '---':
231
232 pass
233 elif len(elements) == 3:
234 hypervisor.add_filesystem(elements[1], type=default_filesystem, filename=tmpfile, mntpnt=elements[0], devletter='', device=elements[2], dummy=(int(elements[1]) == 0))
235 else:
236 hypervisor.add_filesystem(elements[1], type=default_filesystem, filename=tmpfile, mntpnt=elements[0])
237
238 except IOError, (errno, strerror):
239 self.optparser.error("%s parsing --part option: %s" % (errno, strerror))
240 else:
241 try:
242 curdisk = list()
243 size = 0
244 for line in file(self.options.part):
245 pair = line.strip().split(' ',1)
246 if pair[0] == '---':
247 self.do_disk(hypervisor, curdisk, size)
248 curdisk = list()
249 size = 0
250 elif pair[0] != '':
251 logging.debug("part: %s, size: %d" % (pair[0], int(pair[1])))
252 curdisk.append((pair[0], pair[1]))
253 size += int(pair[1])
254
255 self.do_disk(hypervisor, curdisk, size)
256
257 except IOError, (errno, strerror):
258 hypervisor.optparser.error("%s parsing --part option: %s" % (errno, strerror))
259
260 - def do_disk(self, hypervisor, curdisk, size):
261 default_filesystem = hypervisor.distro.preferred_filesystem()
262 disk = hypervisor.add_disk(util.tmpfile(keep=False), size+1)
263 logging.debug("do_disk - size: %d" % size)
264 offset = 0
265 for pair in curdisk:
266 logging.debug("do_disk - part: %s, size: %s, offset: %d" % (pair[0], pair[1], offset))
267 if pair[0] == 'root':
268 disk.add_part(offset, int(pair[1]), default_filesystem, '/')
269 elif pair[0] == 'swap':
270 disk.add_part(offset, int(pair[1]), pair[0], pair[0])
271 else:
272 disk.add_part(offset, int(pair[1]), default_filesystem, pair[0])
273 offset += int(pair[1])
274
276 arg = 'ubuntu-vm-builder'
277
279 optparser.set_usage('%prog hypervisor suite [options]')
280
281
284
292