1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 import logging
20 import os
21 import shutil
22 import stat
23 import VMBuilder
24 from VMBuilder import register_distro, Distro
25 from VMBuilder.util import run_cmd
26 from VMBuilder.exception import VMBuilderUserError, VMBuilderException
27
29 name = 'Debian'
30 arg = 'debian'
31 suites = ['potato', 'woody', 'sarge', 'etch', 'lenny',
32 'squeeze', 'wheezy', 'jessie', 'stretch' ]
33
34
35 valid_archs = { 'amd64' : ['amd64', 'i386' ],
36 'i386' : [ 'i386' ] }
37
38 xen_kernel = ''
39
41 group = self.setting_group('Package options')
42 group.add_setting('addpkg', type='list', metavar='PKG', help='Install PKG into the guest (can be specified multiple times).')
43 group.add_setting('removepkg', type='list', metavar='PKG', help='Remove PKG from the guest (can be specified multiple times)')
44 group.add_setting('seedfile', metavar="SEEDFILE", help='Seed the debconf database with the contents of this seed file before installing packages')
45
46 group = self.setting_group('General OS options')
47 self.host_arch = run_cmd('dpkg', '--print-architecture').rstrip()
48 group.add_setting('arch', extra_args=['-a'], default=self.host_arch, help='Specify the target architecture. Valid options: amd64 i386 (defaults to host arch)')
49 group.add_setting('hostname', default='debian', help='Set NAME as the hostname of the guest. Default: debian. Also uses this name as the VM name.')
50
51 group = self.setting_group('Installation options')
52 group.add_setting('suite', default='jessie', help='Suite to install. Valid options: %s [default: %%default]' % ' '.join(self.suites))
53 group.add_setting('flavour', extra_args=['--kernel-flavour'], help='Kernel flavour to use. Default and valid options depend on architecture and suite')
54 group.add_setting('variant', metavar='VARIANT', help='Passed to debootstrap --variant flag; use minbase, buildd, or fakechroot.')
55 group.add_setting('debootstrap-tarball', metavar='FILE', help='Passed to debootstrap --unpack-tarball flag.')
56 group.add_setting('iso', metavar='PATH', help='Use an iso image as the source for installation of file. Full path to the iso must be provided. If --mirror is also provided, it will be used in the final sources.list of the vm. This requires suite and kernel parameter to match what is available on the iso, obviously.')
57 group.add_setting('mirror', metavar='URL', help='Use Debian mirror at URL instead of the default, which is http://ftp.debian.org/debian for official arches and http://ports.ubuntu.com/ubuntu-ports otherwise')
58 group.add_setting('proxy', metavar='URL', help='Use proxy at URL for cached packages')
59 group.add_setting('install-mirror', metavar='URL', help='Use Debian mirror at URL for the installation only. Apt\'s sources.list will still use default or URL set by --mirror')
60 group.add_setting('security-mirror', metavar='URL', help='Use Debian security mirror at URL instead of the default, which is http://security.debian.org/debian-security.')
61 group.add_setting('install-security-mirror', metavar='URL', help='Use the security mirror at URL for installation only. Apt\'s sources.list will still use default or URL set by --security-mirror')
62 group.add_setting('components', type='list', metavar='COMPS', help='A comma seperated list of distro components to include (e.g. main,universe).')
63 group.add_setting('lang', metavar='LANG', default=get_locale(), help='Set the locale to LANG [default: %default]')
64 group.add_setting('timezone', metavar='TZ', default='UTC', help='Set the timezone to TZ in the vm. [default: %default]')
65
66 group = self.setting_group('Settings for the initial user')
67 group.add_setting('user', default='debian', help='Username of initial user [default: %default]')
68 group.add_setting('name', default='Debian', help='Full name of initial user [default: %default]')
69 group.add_setting('pass', default='debian', help='Password of initial user [default: %default]')
70 group.add_setting('rootpass', help='Initial root password (WARNING: this has strong security implications).')
71 group.add_setting('uid', type='int', help='Initial UID value.')
72 group.add_setting('gid', help='Initial GID value.')
73 group.add_setting('lock-user', type='bool', default=False, help='Lock the initial user [default: %default]')
74
75 group = self.setting_group('Other options')
76 group.add_setting('ssh-key', metavar='PATH', help='Add PATH to root\'s ~/.ssh/authorized_keys (WARNING: this has strong security implications).')
77 group.add_setting('ssh-user-key', help='Add PATH to the user\'s ~/.ssh/authorized_keys.')
78 group.add_setting('manifest', metavar='PATH', help='If passed, a manifest will be written to PATH')
79
85
87 """While not all of these are strictly checks, their failure would inevitably
88 lead to failure, and since we can check them before we start setting up disk
89 and whatnot, we might as well go ahead an do this now."""
90
91 suite = self.get_setting('suite')
92 if not suite in self.suites:
93 raise VMBuilderUserError('Invalid suite: "%s". Valid suites are: %s' % (suite, ' '.join(self.suites)))
94
95 modname = 'VMBuilder.plugins.debian.%s' % (suite, )
96 mod = __import__(modname, fromlist=[suite])
97 self.suite = getattr(mod, suite.capitalize())(self)
98
99 arch = self.get_setting('arch')
100 if arch not in self.valid_archs[self.host_arch] or \
101 not self.suite.check_arch_validity(arch):
102 raise VMBuilderUserError('%s is not a valid architecture. Valid architectures are: %s' % (arch,
103 ' '.join(self.valid_archs[self.host_arch])))
104
105 components = self.get_setting('components')
106 if not components:
107 self.set_config_value_list = ['main', 'contrib']
108 else:
109 if type(components) is str:
110 self.vm.components = self.vm.components.split(',')
111
112 self.context.virtio_net = self.use_virtio_net()
113
114
115 seedfile = self.context.get_setting('seedfile')
116 if seedfile and not os.path.exists(seedfile):
117 raise VMBuilderUserError("Seedfile '%s' does not exist" % seedfile)
118
119 lang = self.get_setting('lang')
120
121
122
123
124
125
126
130
151
155
158
162
165
166 - def post_mount(self, fs):
168
171
179
182
184 root_dev = VMBuilder.disk.bootpart(disks).get_grub_id()
185
186 tmpdir = '/tmp/vmbuilder-grub'
187 os.makedirs('%s%s' % (chroot_dir, tmpdir))
188 self.context.add_clean_cb(self.install_bootloader_cleanup)
189 devmapfile = os.path.join(tmpdir, 'device.map')
190 devmap = open('%s%s' % (chroot_dir, devmapfile), 'w')
191 for (disk, id) in zip(disks, range(len(disks))):
192 new_filename = os.path.join(tmpdir, os.path.basename(disk.filename))
193 open('%s%s' % (chroot_dir, new_filename), 'w').close()
194 run_cmd('mount', '--bind', disk.filename, '%s%s' % (chroot_dir, new_filename))
195 st = os.stat(disk.filename)
196 if stat.S_ISBLK(st.st_mode):
197 for (part, part_id) in zip(disk.partitions, range(len(disk.partitions))):
198 part_mountpnt = '%s%s%d' % (chroot_dir, new_filename, part_id+1)
199 open(part_mountpnt, 'w').close()
200 run_cmd('mount', '--bind', part.filename, part_mountpnt)
201 devmap.write("(hd%d) %s\n" % (id, new_filename))
202 devmap.close()
203 run_cmd('cat', '%s%s' % (chroot_dir, devmapfile))
204 self.suite.install_grub(chroot_dir)
205 self.run_in_target('grub', '--device-map=%s' % devmapfile, '--batch', stdin='''root %s
206 setup (hd0)
207 EOT''' % root_dev)
208 self.suite.install_menu_lst(disks)
209 self.install_bootloader_cleanup(chroot_dir)
210
212 if self.suite.xen_kernel_flavour:
213
214
215
216 if hasattr(self.context, 'ec2') and self.context.ec2:
217 logging.debug("selecting ec2 kernel")
218 self.xen_kernel = "2.6.ec2-kernel"
219 return self.xen_kernel
220 if not self.xen_kernel:
221 rmad = run_cmd('rmadison', 'linux-image-%s' % self.suite.xen_kernel_flavour)
222 version = ['0', '0','0', '0']
223
224 for line in rmad.splitlines():
225 sline = line.split('|')
226
227 if sline[2].strip().startswith(self.context.get_setting('suite')):
228 vt = sline[1].strip().split('.')
229 for i in range(4):
230 if int(vt[i]) > int(version[i]):
231 version = vt
232 break
233
234 if version[0] == '0':
235 raise VMBuilderException('Something is wrong, no valid xen kernel for the suite %s found by rmadison' % self.context.suite)
236
237 self.xen_kernel = '%s.%s.%s-%s' % (version[0],version[1],version[2],version[3])
238 return self.xen_kernel
239 else:
240 raise VMBuilderUserError('There is no valid xen kernel for the suite selected.')
241
245
248
251
257
263
266
269
272
275
277 lang = os.getenv('LANG')
278 if lang is None:
279 return 'C'
280
281
282 if lang.endswith('utf8'):
283 return lang[:-4] + 'UTF-8'
284 return lang
285
286 register_distro(Debian)
287