Package VMBuilder :: Package plugins :: Package ubuntu :: Module dapper
[frames] | no frames]

Source Code for Module VMBuilder.plugins.ubuntu.dapper

  1  # 
  2  #    Uncomplicated VM Builder 
  3  #    Copyright (C) 2007-2010 Canonical Ltd. 
  4  # 
  5  #    See AUTHORS for list of contributors 
  6  # 
  7  #    This program is free software: you can redistribute it and/or modify 
  8  #    it under the terms of the GNU General Public License version 3, as 
  9  #    published by the Free Software Foundation. 
 10  # 
 11  #    This program is distributed in the hope that it will be useful, 
 12  #    but WITHOUT ANY WARRANTY; without even the implied warranty of 
 13  #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 14  #    GNU General Public License for more details. 
 15  # 
 16  #    You should have received a copy of the GNU General Public License 
 17  #    along with this program.  If not, see <http://www.gnu.org/licenses/>. 
 18  # 
 19  import glob 
 20  import logging 
 21  import os 
 22  import suite 
 23  import shutil 
 24  import tempfile 
 25  import VMBuilder.disk as disk 
 26  from   VMBuilder.util import run_cmd 
 27  from   VMBuilder.exception import VMBuilderException 
 28   
29 -class Dapper(suite.Suite):
30 updategrub = "/sbin/update-grub" 31 grubroot = "/lib/grub" 32 valid_flavours = { 'i386' : ['386', '686', '686-smp', 'k7', 'k7-smp', 'server', 'server-bigiron'], 33 'amd64' : ['amd64-generic', 'amd64-k8', 'amd64-k8-smp', 'amd64-server', 'amd64-xeon']} 34 default_flavour = { 'i386' : 'server', 'amd64' : 'amd64-server' } 35 disk_prefix = 'hd' 36 xen_kernel_flavour = None 37 virtio_net = False 38 chpasswd_cmd = [ 'chpasswd', '--md5' ] 39 preferred_filesystem = 'ext3' 40
41 - def pre_install(self):
42 pass
43
44 - def check_kernel_flavour(self, arch, flavour):
45 return flavour in self.valid_flavours[arch]
46
47 - def check_arch_validity(self, arch):
48 return arch in self.valid_flavours.keys()
49
50 - def install(self, destdir):
51 raise VMBuilderException('Do not call this method!') 52 53 # These are still missing after the refactoring. 54 logging.debug("Creating device.map") 55 self.install_device_map() 56 57 logging.debug("Copy host settings") 58 self.copy_settings() 59 60 if hasattr(self.context, 'ec2') and self.context.ec2: 61 logging.debug("Configuring for ec2") 62 self.install_ec2()
63
64 - def create_manifest(self):
65 manifest = self.context.get_setting('manifest') 66 if manifest: 67 logging.debug("Creating manifest") 68 manifest_contents = self.run_in_target('dpkg-query', '-W', '--showformat=${Package} ${Version}\n') 69 fp = open(manifest, 'w') 70 fp.write(manifest_contents) 71 fp.close 72 self.call_hook('fix_ownership', manifest)
73
74 - def update(self):
75 self.run_in_target('apt-get', '-y', '--force-yes', 'dist-upgrade', 76 env={ 'DEBIAN_FRONTEND' : 'noninteractive' })
77
78 - def install_authorized_keys(self):
79 ssh_key = self.context.get_setting('ssh-key') 80 if ssh_key: 81 os.mkdir('%s/root/.ssh' % self.context.chroot_dir, 0700) 82 shutil.copy(ssh_key, '%s/root/.ssh/authorized_keys' % self.context.chroot_dir) 83 os.chmod('%s/root/.ssh/authorized_keys' % self.context.chroot_dir, 0644) 84 85 user = self.context.get_setting('user') 86 ssh_user_key = self.context.get_setting('ssh-user-key') 87 if ssh_user_key: 88 os.mkdir('%s/home/%s/.ssh' % (self.context.chroot_dir, user), 0700) 89 shutil.copy(ssh_user_key, '%s/home/%s/.ssh/authorized_keys' % (self.context.chroot_dir, user)) 90 os.chmod('%s/home/%s/.ssh/authorized_keys' % (self.context.chroot_dir, user), 0644) 91 self.run_in_target('chown', '-R', '%s:%s' % ((user,)*2), '/home/%s/.ssh/' % (user)) 92 93 if ssh_user_key or ssh_key: 94 addpkg = self.context.get_setting('addpkg') 95 addpkg += ['openssh-server'] 96 self.context.set_setting('addpkg', addpkg)
97
98 - def mount_dev_proc(self):
99 run_cmd('mount', '--bind', '/dev', '%s/dev' % self.context.chroot_dir) 100 self.context.add_clean_cb(self.unmount_dev) 101 102 run_cmd('mount', '--bind', '/dev/pts', '%s/dev/pts' % self.context.chroot_dir) 103 self.context.add_clean_cb(self.unmount_dev_pts) 104 105 self.run_in_target('mount', '-t', 'proc', 'proc', '/proc') 106 self.context.add_clean_cb(self.unmount_proc)
107
108 - def unmount_proc(self):
109 self.context.cancel_cleanup(self.unmount_proc) 110 run_cmd('umount', '%s/proc' % self.context.chroot_dir)
111
112 - def unmount_dev_pts(self):
113 self.context.cancel_cleanup(self.unmount_dev_pts) 114 run_cmd('umount', '%s/dev/pts' % self.context.chroot_dir)
115
116 - def unmount_dev(self):
117 self.context.cancel_cleanup(self.unmount_dev) 118 run_cmd('umount', '%s/dev' % self.context.chroot_dir)
119
120 - def update_passwords(self):
121 # Set the user password, using md5 122 user = self.context.get_setting('user') 123 passwd = self.context.get_setting('pass') 124 self.run_in_target(stdin=('%s:%s\n' % (user, passwd)), *self.chpasswd_cmd) 125 126 # Lock root account only if we didn't set the root password 127 rootpass = self.context.get_setting('rootpass') 128 if rootpass: 129 self.run_in_target(stdin=('%s:%s\n' % ('root', rootpass)), *self.chpasswd_cmd) 130 else: 131 self.run_in_target('usermod', '-L', 'root') 132 133 lock_user = self.context.get_setting('lock-user') 134 if lock_user: 135 logging.info('Locking %s' % (user, )) 136 self.run_in_target('usermod', '-L', user)
137
138 - def create_initial_user(self):
139 uid = self.context.get_setting('uid') 140 name = self.context.get_setting('name') 141 user = self.context.get_setting('user') 142 if uid: 143 self.run_in_target('adduser', '--disabled-password', '--uid', uid, '--gecos', name, user) 144 else: 145 self.run_in_target('adduser', '--disabled-password', '--gecos', name, user) 146 147 self.run_in_target('addgroup', '--system', 'admin') 148 self.run_in_target('adduser', user, 'admin') 149 150 self.install_from_template('/etc/sudoers', 'sudoers') 151 for group in ['adm', 'audio', 'cdrom', 'dialout', 'floppy', 'video', 'plugdev', 'dip', 'netdev', 'powerdev', 'lpadmin', 'scanner']: 152 self.run_in_target('adduser', user, group, ignore_fail=True) 153 154 self.update_passwords()
155
156 - def kernel_name(self):
157 flavour = self.context.get_setting('flavour') 158 arch = self.context.get_setting('arch') 159 return 'linux-image-%s' % (flavour or self.default_flavour[arch],)
160
162 hostname = self.context.get_setting('hostname') 163 domain = self.context.get_setting('domain') 164 self.context.install_file('/etc/hostname', hostname) 165 self.install_from_template('/etc/hosts', 'etc_hosts', { 'hostname' : hostname, 'domain' : domain })
166
167 - def config_interfaces(self, nics):
168 self.install_from_template('/etc/network/interfaces', 'interfaces', 169 { 'ip' : nics[0].type == 'dhcp' and 'dhcp' or nics[0].ip, 170 'mask' : nics[0].netmask, 171 'net' : nics[0].network, 172 'bcast' : nics[0].broadcast, 173 'gw' : nics[0].gateway, 174 'dns' : nics[0].dns, 175 'domain' : self.context.get_setting('domain') })
176
178 os.unlink('%s/usr/sbin/policy-rc.d' % self.context.chroot_dir)
179
180 - def prevent_daemons_starting(self):
181 os.chmod(self.install_from_template('/usr/sbin/policy-rc.d', 'nostart-policy-rc.d'), 0755)
182
183 - def seed(self, seedfile):
184 """Seed debconf with the contents of a seedfile""" 185 logging.info('Seeding with "%s"' % seedfile) 186 187 self.run_in_target('debconf-set-selections', stdin=open(seedfile, 'r').read())
188
189 - def install_extras(self):
190 seedfile = self.context.get_setting('seedfile') 191 if seedfile: 192 self.seed(seedfile) 193 194 addpkg = self.context.get_setting('addpkg') 195 removepkg = self.context.get_setting('removepkg') 196 if not addpkg and not removepkg: 197 return 198 199 cmd = ['apt-get', 'install', '-y', '--force-yes'] 200 cmd += addpkg or [] 201 cmd += ['%s-' % pkg for pkg in removepkg or []] 202 self.run_in_target(env={ 'DEBIAN_FRONTEND' : 'noninteractive' }, *cmd)
203
204 - def unmount_volatile(self):
205 for mntpnt in glob.glob('%s/lib/modules/*/volatile' % self.context.chroot_dir): 206 logging.debug("Unmounting %s" % mntpnt) 207 run_cmd('umount', mntpnt)
208
209 - def install_menu_lst(self, disks):
210 self.run_in_target(self.updategrub, '-y') 211 self.mangle_grub_menu_lst(disks) 212 self.run_in_target(self.updategrub) 213 self.run_in_target('grub-set-default', '0')
214
215 - def mangle_grub_menu_lst(self, disks):
216 bootdev = disk.bootpart(disks) 217 run_cmd('sed', '-ie', 's/^# kopt=root=\([^ ]*\)\(.*\)/# kopt=root=\/dev\/hd%s%d\\2/g' % (bootdev.disk.devletters(), bootdev.get_index()+1), '%s/boot/grub/menu.lst' % self.context.chroot_dir) 218 run_cmd('sed', '-ie', 's/^# groot.*/# groot %s/g' % bootdev.get_grub_id(), '%s/boot/grub/menu.lst' % self.context.chroot_dir) 219 run_cmd('sed', '-ie', '/^# kopt_2_6/ d', '%s/boot/grub/menu.lst' % self.context.chroot_dir)
220
221 - def install_sources_list(self, final=False):
222 if final: 223 mirror = updates_mirror = self.context.get_setting('mirror') 224 security_mirror = self.context.get_setting('security-mirror') 225 else: 226 mirror, updates_mirror, security_mirror = self.install_mirrors() 227 228 components = self.context.get_setting('components') 229 ppa = self.context.get_setting('ppa') 230 suite = self.context.get_setting('suite') 231 self.install_from_template('/etc/apt/sources.list', 'sources.list', { 'mirror' : mirror, 232 'security_mirror' : security_mirror, 233 'updates_mirror' : updates_mirror, 234 'components' : components, 235 'ppa' : ppa, 236 'suite' : suite }) 237 238 # If setting up the final mirror, allow apt-get update to fail 239 # (since we might be on a complete different network than the 240 # final vm is going to be on). 241 self.run_in_target('apt-get', 'update', ignore_fail=final)
242
243 - def install_apt_proxy(self):
244 proxy = self.context.get_setting('proxy') 245 if proxy is not None: 246 self.context.install_file('/etc/apt/apt.conf', '// Proxy added by vmbuilder\nAcquire::http { Proxy "%s"; };' % proxy)
247
248 - def install_fstab(self, disks, filesystems):
249 self.install_from_template('/etc/fstab', 'dapper_fstab', { 'parts' : disk.get_ordered_partitions(disks), 'prefix' : self.disk_prefix })
250
251 - def install_device_map(self):
252 self.install_from_template('/boot/grub/device.map', 'devicemap', { 'prefix' : self.disk_prefix })
253
254 - def debootstrap(self):
255 arch = self.context.get_setting('arch') 256 cmd = ['/usr/sbin/debootstrap', '--arch=%s' % arch] 257 258 variant = self.context.get_setting('variant') 259 if variant: 260 cmd += ['--variant=%s' % variant] 261 262 suite = self.context.get_setting('suite') 263 cmd += [suite, self.context.chroot_dir, self.debootstrap_mirror()] 264 kwargs = { 'env' : { 'DEBIAN_FRONTEND' : 'noninteractive' } } 265 266 proxy = self.context.get_setting('proxy') 267 if proxy: 268 kwargs['env']['http_proxy'] = proxy 269 run_cmd(*cmd, **kwargs)
270
271 - def debootstrap_mirror(self):
272 iso = self.context.get_setting('iso') 273 if iso: 274 isodir = tempfile.mkdtemp() 275 self.context.add_clean_cb(lambda:os.rmdir(isodir)) 276 run_cmd('mount', '-o', 'loop', '-t', 'iso9660', iso, isodir) 277 self.context.add_clean_cmd('umount', isodir) 278 self.iso_mounted = True 279 280 return 'file://%s' % isodir 281 else: 282 return self.install_mirrors()[0]
283 284
285 - def install_mirrors(self):
286 install_mirror = self.context.get_setting('install-mirror') 287 if install_mirror: 288 mirror = install_mirror 289 else: 290 mirror = self.context.get_setting('mirror') 291 292 updates_mirror = mirror 293 294 install_security_mirror = self.context.get_setting('install-security-mirror') 295 if install_security_mirror: 296 security_mirror = install_security_mirror 297 else: 298 security_mirror = self.context.get_setting('security-mirror') 299 300 return (mirror, updates_mirror, security_mirror)
301
302 - def install_kernel(self, destdir):
303 run_cmd('chroot', destdir, 'apt-get', '--force-yes', '-y', 'install', self.kernel_name(), env={ 'DEBIAN_FRONTEND' : 'noninteractive' })
304
305 - def install_grub(self, chroot_dir):
306 self.install_from_template('/etc/kernel-img.conf', 'kernelimg', { 'updategrub' : self.updategrub }) 307 arch = self.context.get_setting('arch') 308 self.run_in_target('apt-get', '--force-yes', '-y', 'install', 'grub', env={ 'DEBIAN_FRONTEND' : 'noninteractive' }) 309 run_cmd('rsync', '-a', '%s%s/%s/' % (chroot_dir, self.grubroot, arch == 'amd64' and 'x86_64-pc' or 'i386-pc'), '%s/boot/grub/' % chroot_dir)
310
311 - def create_devices(self):
312 pass
313 # FIXME 314 # import VMBuilder.plugins.xen 315 316 # if isinstance(self.context.hypervisor, VMBuilder.plugins.xen.Xen): 317 # self.run_in_target('mknod', '/dev/xvda', 'b', '202', '0') 318 # self.run_in_target('mknod', '/dev/xvda1', 'b', '202', '1') 319 # self.run_in_target('mknod', '/dev/xvda2', 'b', '202', '2') 320 # self.run_in_target('mknod', '/dev/xvda3', 'b', '202', '3') 321 # self.run_in_target('mknod', '/dev/xvc0', 'c', '204', '191') 322
323 - def install_from_template(self, *args, **kwargs):
324 return self.context.install_from_template(*args, **kwargs)
325
326 - def run_in_target(self, *args, **kwargs):
327 return self.context.run_in_target(*args, **kwargs)
328
329 - def copy_to_target(self, infile, destpath):
330 logging.debug("Copying %s on host to %s in guest" % (infile, destpath)) 331 dir = '%s/%s' % (self.destdir, os.path.dirname(destpath)) 332 if not os.path.isdir(dir): 333 os.makedirs(dir) 334 if os.path.isdir(infile): 335 shutil.copytree(infile, '%s/%s' % (self.destdir, destpath)) 336 else: 337 shutil.copy(infile, '%s/%s' % (self.destdir, destpath))
338
339 - def post_mount(self, fs):
340 if fs.mntpnt == '/': 341 logging.debug("Creating /var/run in root filesystem") 342 os.makedirs('%s/var/run' % fs.mntpath) 343 logging.debug("Creating /var/lock in root filesystem") 344 os.makedirs('%s/var/lock' % fs.mntpath)
345
346 - def set_locale(self):
347 lang = self.context.get_setting('lang') 348 if lang: 349 self.install_from_template('/etc/default/locale', 'locale', { 'lang' : lang }) 350 if lang != "C": 351 self.run_in_target('locale-gen', lang) 352 self.run_in_target('dpkg-reconfigure', '-fnoninteractive', '-pcritical', 'libc6') 353 self.run_in_target('dpkg-reconfigure', '-fnoninteractive', '-pcritical', 'locales')
354
355 - def install_vmbuilder_log(self, logfile, rootdir):
356 shutil.copy(logfile, '%s/var/log/vmbuilder-install.log' % (rootdir,))
357
358 - def set_timezone(self):
359 timezone = self.context.get_setting('timezone') 360 if timezone: 361 self.install_from_template('/etc/timezone', 'timezone', { 'timezone' : timezone }) 362 self.run_in_target('dpkg-reconfigure', '-fnoninteractive', '-pcritical', 'locales')
363
364 - def install_ec2(self):
365 if self.context.ec2: 366 logging.debug('This suite does not support ec2')
367
368 - def disable_hwclock_access(self):
369 fp = open('%s/etc/default/rcS' % self.destdir, 'a') 370 fp.write('HWCLOCKACCESS=no') 371 fp.close()
372
374 return False
375