Пример #1
0
    def run(cls, info):
        vagrantfile_source = os.path.join(assets, 'Vagrantfile')
        vagrantfile = os.path.join(info.vagrant['folder'], 'Vagrantfile')
        shutil.copy(vagrantfile_source, vagrantfile)

        import random
        mac_address = '080027{mac:06X}'.format(mac=random.randrange(16**6))
        from common.tools import sed_i
        sed_i(vagrantfile, '\\[MAC_ADDRESS\\]', mac_address)

        metadata_source = os.path.join(assets, 'metadata.json')
        metadata = os.path.join(info.vagrant['folder'], 'metadata.json')
        shutil.copy(metadata_source, metadata)

        from common.tools import log_check_call
        disk_name = 'box-disk1.{ext}'.format(ext=info.volume.extension)
        disk_link = os.path.join(info.vagrant['folder'], disk_name)
        log_check_call(['ln', '-s', info.volume.image_path, disk_link])

        ovf_path = os.path.join(info.vagrant['folder'], 'box.ovf')
        cls.write_ovf(info, ovf_path, mac_address, disk_name)

        box_files = os.listdir(info.vagrant['folder'])
        log_check_call([
            'tar', '--create', '--gzip', '--dereference', '--file',
            info.vagrant['box_path'], '--directory', info.vagrant['folder']
        ] + box_files)
        import logging
        logging.getLogger(__name__).info(
            'The vagrant box has been placed at {box_path}'.format(
                box_path=info.vagrant['box_path']))
Пример #2
0
    def run(cls, info):
        ssh_dir = os.path.join(info.root, "home/vagrant/.ssh")
        os.mkdir(ssh_dir)

        authorized_keys_source_path = os.path.join(assets, "authorized_keys")
        with open(authorized_keys_source_path, "r") as authorized_keys_source:
            insecure_public_key = authorized_keys_source.read()

        authorized_keys_path = os.path.join(ssh_dir, "authorized_keys")
        with open(authorized_keys_path, "a") as authorized_keys:
            authorized_keys.write(insecure_public_key)

        import stat

        os.chmod(ssh_dir, stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR)
        os.chmod(authorized_keys_path, stat.S_IRUSR | stat.S_IWUSR)

        # We can't do this directly with python, since getpwnam gets its info from the host
        from common.tools import log_check_call

        log_check_call(
            [
                "chroot",
                info.root,
                "chown",
                "vagrant:vagrant",
                "/home/vagrant/.ssh",
                "/home/vagrant/.ssh/authorized_keys",
            ]
        )
Пример #3
0
 def install_remote(cls, info, remote_packages):
     import os
     from common.tools import log_check_call
     from subprocess import CalledProcessError
     try:
         env = os.environ.copy()
         env['DEBIAN_FRONTEND'] = 'noninteractive'
         log_check_call([
             'chroot', info.root, 'apt-get', 'install',
             '--no-install-recommends', '--assume-yes'
         ] + map(str, remote_packages),
                        env=env)
     except CalledProcessError as e:
         import logging
         disk_stat = os.statvfs(info.root)
         root_free_mb = disk_stat.f_bsize * disk_stat.f_bavail / 1024 / 1024
         disk_stat = os.statvfs(os.path.join(info.root, 'boot'))
         boot_free_mb = disk_stat.f_bsize * disk_stat.f_bavail / 1024 / 1024
         free_mb = min(root_free_mb, boot_free_mb)
         if free_mb < 50:
             msg = ('apt exited with a non-zero status, '
                    'this may be because\nthe image volume is '
                    'running out of disk space ({free}MB left)').format(
                        free=free_mb)
             logging.getLogger(__name__).warn(msg)
         else:
             if e.returncode == 100:
                 msg = (
                     'apt exited with status code 100. '
                     'This can sometimes occur when package retrieval times out or a package extraction failed. '
                     'apt might succeed if you try bootstrapping again.')
                 logging.getLogger(__name__).warn(msg)
         raise e
Пример #4
0
	def run(cls, info):
		executable, options, arguments = get_bootstrap_args(info)
		if hasattr(info, 'tarball'):
			options.extend(['--unpack-tarball=' + info.tarball])

		from common.tools import log_check_call
		log_check_call(executable + options + arguments)
Пример #5
0
	def install_remote(cls, info, remote_packages):
		import os
		from common.tools import log_check_call
		from subprocess import CalledProcessError
		try:
			env = os.environ.copy()
			env['DEBIAN_FRONTEND'] = 'noninteractive'
			log_check_call(['chroot', info.root,
			                'apt-get', 'install',
			                           '--no-install-recommends',
			                           '--assume-yes']
			               + map(str, remote_packages),
			               env=env)
		except CalledProcessError as e:
			import logging
			disk_stat = os.statvfs(info.root)
			root_free_mb = disk_stat.f_bsize * disk_stat.f_bavail / 1024 / 1024
			disk_stat = os.statvfs(os.path.join(info.root, 'boot'))
			boot_free_mb = disk_stat.f_bsize * disk_stat.f_bavail / 1024 / 1024
			free_mb = min(root_free_mb, boot_free_mb)
			if free_mb < 50:
				msg = ('apt exited with a non-zero status, '
				       'this may be because\nthe image volume is '
				       'running out of disk space ({free}MB left)').format(free=free_mb)
				logging.getLogger(__name__).warn(msg)
			else:
				if e.returncode == 100:
					msg = ('apt exited with status code 100. '
					       'This can sometimes occur when package retrieval times out or a package extraction failed. '
					       'apt might succeed if you try bootstrapping again.')
					logging.getLogger(__name__).warn(msg)
			raise e
Пример #6
0
 def run(cls, info):
     from common.tools import log_check_call
     for raw_command in info.manifest.plugins['image_commands']['commands']:
         command = map(
             lambda part: part.format(root=info.root, **info.manifest_vars),
             raw_command)
         log_check_call(command)
Пример #7
0
	def install_local(cls, info, local_packages):
		from shutil import copy
		from common.tools import log_check_call
		import os

		absolute_package_paths = []
		chrooted_package_paths = []
		for package_src in local_packages:
			pkg_name = os.path.basename(package_src.path)
			package_rel_dst = os.path.join('tmp', pkg_name)
			package_dst = os.path.join(info.root, package_rel_dst)
			copy(package_src.path, package_dst)
			absolute_package_paths.append(package_dst)
			package_path = os.path.join('/', package_rel_dst)
			chrooted_package_paths.append(package_path)

		env = os.environ.copy()
		env['DEBIAN_FRONTEND'] = 'noninteractive'
		log_check_call(['chroot', info.root,
		                'dpkg', '--install']
		               + chrooted_package_paths,
		               env=env)

		for path in absolute_package_paths:
			os.remove(path)
Пример #8
0
	def _before_map(self, event):
		volume = event.volume
		try:
			mappings = log_check_call(['/sbin/kpartx', '-l', volume.device_path])
			import re
			regexp = re.compile('^(?P<name>.+[^\d](?P<p_idx>\d+)) : '
			                    '(?P<start_blk>\d) (?P<num_blks>\d+) '
			                    '{device_path} (?P<blk_offset>\d+)$'
			                    .format(device_path=volume.device_path))
			log_check_call(['/sbin/kpartx', '-a', volume.device_path])
			import os.path
			for mapping in mappings:
				match = regexp.match(mapping)
				if match is None:
					raise PartitionError('Unable to parse kpartx output: {line}'.format(line=mapping))
				partition_path = os.path.join('/dev/mapper', match.group('name'))
				p_idx = int(match.group('p_idx')) - 1
				self.partitions[p_idx].map(partition_path)

			for idx, partition in enumerate(self.partitions):
				if partition.fsm.current not in ['mapped', 'formatted']:
					raise PartitionError('kpartx did not map partition #{idx}'.format(idx=idx + 1))

		except PartitionError as e:
			for partition in self.partitions:
				if not partition.fsm.can('unmap'):
					partition.unmap()
			log_check_call(['/sbin/kpartx', '-d', volume.device_path])
			raise e
Пример #9
0
		def mount(self, prefix):
			mount_dir = os.path.join(prefix, self.destination)
			if isinstance(self.source, AbstractPartition):
				self.source.mount(destination=mount_dir)
			else:
				log_check_call(['/bin/mount'] + self.opts + [self.source, mount_dir])
			self.mount_dir = mount_dir
Пример #10
0
	def run(cls, info):
		vagrantfile_source = os.path.join(assets, 'Vagrantfile')
		vagrantfile = os.path.join(info.vagrant['folder'], 'Vagrantfile')
		shutil.copy(vagrantfile_source, vagrantfile)

		import random
		mac_address = '080027{mac:06X}'.format(mac=random.randrange(16 ** 6))
		from common.tools import sed_i
		sed_i(vagrantfile, '\\[MAC_ADDRESS\\]', mac_address)

		metadata_source = os.path.join(assets, 'metadata.json')
		metadata = os.path.join(info.vagrant['folder'], 'metadata.json')
		shutil.copy(metadata_source, metadata)

		from common.tools import log_check_call
		disk_name = 'box-disk1.{ext}'.format(ext=info.volume.extension)
		disk_link = os.path.join(info.vagrant['folder'], disk_name)
		log_check_call(['ln', '-s', info.volume.image_path, disk_link])

		ovf_path = os.path.join(info.vagrant['folder'], 'box.ovf')
		cls.write_ovf(info, ovf_path, mac_address, disk_name)

		box_files = os.listdir(info.vagrant['folder'])
		log_check_call(['tar', '--create', '--gzip', '--dereference',
		                '--file', info.vagrant['box_path'],
		                '--directory', info.vagrant['folder']]
		               + box_files
		               )
		import logging
		logging.getLogger(__name__).info('The vagrant box has been placed at {box_path}'
		                                 .format(box_path=info.vagrant['box_path']))
Пример #11
0
    def run(cls, info):
        executable, options, arguments = get_bootstrap_args(info)
        if hasattr(info, 'tarball'):
            options.extend(['--unpack-tarball=' + info.tarball])

        from common.tools import log_check_call
        log_check_call(executable + options + arguments)
Пример #12
0
	def _before_link_dm_node(self, e):
		"""Links the volume using the device mapper
		This allows us to create a 'window' into the volume that acts like a volum in itself.
		Mainly it is used to fool grub into thinking that it is working with a real volume,
		rather than a loopback device or a network block device.

		Args:
			e (_e_obj): Event object containing arguments to create()
			            Arguments are:
			            logical_start_sector (int): The sector the volume should start at in the new volume
			            start_sector (int): The offset at which the volume should begin to be mapped in the new volume
			            sectors (int): The number of sectors that should be mapped
			            Read more at: http://manpages.debian.org/cgi-bin/man.cgi?query=dmsetup&apropos=0&sektion=0&manpath=Debian+7.0+wheezy&format=html&locale=en

		Raises:
			VolumeError
		"""
		import os.path
		from common.fs import get_partitions
		# Fetch information from /proc/partitions
		proc_partitions = get_partitions()
		device_name = os.path.basename(self.device_path)
		device_partition = proc_partitions[device_name]

		# The sector the volume should start at in the new volume
		logical_start_sector = getattr(e, 'logical_start_sector', 0)

		# The offset at which the volume should begin to be mapped in the new volume
		start_sector = getattr(e, 'start_sector', 0)

		# The number of sectors that should be mapped
		sectors = getattr(e, 'sectors', int(self.size / 512) - start_sector)

		# This is the table  we send to dmsetup, so that it may create a decie mapping for us.
		table = ('{log_start_sec} {sectors} linear {major}:{minor} {start_sec}'
		         .format(log_start_sec=logical_start_sector,
		                 sectors=sectors,
		                 major=device_partition['major'],
		                 minor=device_partition['minor'],
		                 start_sec=start_sector))
		import string
		import os.path
		# Figure out the device letter and path
		for letter in string.ascii_lowercase:
			dev_name = 'vd' + letter
			dev_path = os.path.join('/dev/mapper', dev_name)
			if not os.path.exists(dev_path):
				self.dm_node_name = dev_name
				self.dm_node_path = dev_path
				break

		if not hasattr(self, 'dm_node_name'):
			raise VolumeError('Unable to find a free block device path for mounting the bootstrap volume')

		# Create the device mapping
		log_check_call(['dmsetup', 'create', self.dm_node_name], table)
		# Update the device_path but remember the old one for when we unlink the volume again
		self.unlinked_device_path = self.device_path
		self.device_path = self.dm_node_path
Пример #13
0
    def _before_mount(self, e):
        """Mount the partition
		"""
        log_check_call([
            'mount', '--types', self.filesystem, self.device_path,
            e.destination
        ])
        self.mount_dir = e.destination
Пример #14
0
 def _before_create(self, e):
     # Create the partition and then set the name of the partition afterwards
     super(GPTPartition, self)._before_create(e)
     # partition name only works for gpt, for msdos that becomes the part-type (primary, extended, logical)
     name_command = ('name {idx} {name}'.format(idx=self.get_index(),
                                                name=self.name))
     log_check_call(
         ['parted', '--script', e.volume.device_path, '--', name_command])
Пример #15
0
	def run(cls, info):
		from base.fs.partitions.unformatted import UnformattedPartition
		import re
		# Disable the time based filesystem check
		for partition in info.volume.partition_map.partitions:
			if not isinstance(partition, UnformattedPartition):
				if re.match('^ext[2-4]$', partition.filesystem) is not None:
					log_check_call(['tune2fs', '-i', '0', partition.device_path])
Пример #16
0
	def _before_create(self, e):
		super(GPTPartition, self)._before_create(e)
		# partition name only works for gpt, for msdos that becomes the part-type (primary, extended, logical)
		name_command = ('name {idx} {name}'
		                .format(idx=self.get_index(),
		                        name=self.name))
		log_check_call(['/sbin/parted', '--script', e.volume.device_path,
		                '--', name_command])
Пример #17
0
	def run(cls, info):
		log_check_call(['chroot', info.root,
		                'apt-get', 'clean'])

		lists = os.path.join(info.root, 'var/lib/apt/lists')
		for list_file in [os.path.join(lists, f) for f in os.listdir(lists)]:
			if os.path.isfile(list_file):
				os.remove(list_file)
Пример #18
0
	def _before_unmap(self, event):
		volume = event.volume
		for partition in self.partitions:
			if partition.fsm.cannot('unmap'):
				msg = 'The partition {partition} prevents the unmap procedure'.format(partition=partition)
				raise PartitionError(msg)
		log_check_call(['/sbin/kpartx', '-d', volume.device_path])
		for partition in self.partitions:
			partition.unmap()
Пример #19
0
		def unmount(self):
			"""Performs the unmount operation or asks the partition to unmount itself
			"""
			# If its a partition, it can unmount itself
			if isinstance(self.source, AbstractPartition):
				self.source.unmount()
			else:
				log_check_call(['umount', self.mount_dir])
			del self.mount_dir
Пример #20
0
        def unmount(self):
            """Performs the unmount operation or asks the partition to unmount itself
			"""
            # If its a partition, it can unmount itself
            if isinstance(self.source, AbstractPartition):
                self.source.unmount()
            else:
                log_check_call(['umount', self.mount_dir])
            del self.mount_dir
Пример #21
0
	def _before_unmount(self, e):
		"""Unmount any mounts associated with this partition
		"""
		# Unmount the mounts in descending order of mounpoint path length
		# You cannot unmount /dev before you have unmounted /dev/pts
		for destination in sorted(self.mounts.iterkeys(), key=len, reverse=True):
			self.mounts[destination].unmount()
		log_check_call(['umount', self.mount_dir])
		del self.mount_dir
Пример #22
0
	def _before_create(self, event):
		volume = event.volume
		# Disk alignment still plays a role in virtualized environment,
		# but I honestly have no clue as to what best practice is here, so we choose 'none'
		log_check_call(['parted', '--script', '--align', 'none', volume.device_path,
		                '--', 'mklabel', 'msdos'])
		# Create the partitions
		for partition in self.partitions:
			partition.create(volume)
Пример #23
0
	def run(cls, info):
		bundle_name = 'bundle-{id}'.format(id=info.run_id)
		info.bundle_path = os.path.join(info.workspace, bundle_name)
		log_check_call(['/usr/bin/euca-bundle-image',
		                '--image', info.volume.image_path,
		                '--user', info.credentials['user-id'],
		                '--privatekey', info.credentials['private-key'],
		                '--cert', info.credentials['certificate'],
		                '--ec2cert', cert_ec2,
		                '--destination', info.bundle_path,
		                '--prefix', info.ami_name])
Пример #24
0
    def _before_unmount(self, e):
        """Unmount any mounts associated with this partition
		"""
        # Unmount the mounts in descending order of mounpoint path length
        # You cannot unmount /dev before you have unmounted /dev/pts
        for destination in sorted(self.mounts.iterkeys(),
                                  key=len,
                                  reverse=True):
            self.mounts[destination].unmount()
        log_check_call(['umount', self.mount_dir])
        del self.mount_dir
Пример #25
0
	def run(cls, info):
		ssh_hostkeys = ['ssh_host_dsa_key',
		                'ssh_host_rsa_key']
		if info.manifest.system['release'] != 'squeeze':
			ssh_hostkeys.append('ssh_host_ecdsa_key')

		private = [os.path.join(info.root, 'etc/ssh', name) for name in ssh_hostkeys]
		public = [path + '.pub' for path in private]

		from common.tools import log_check_call
		log_check_call(['shred', '--remove'] + private + public)
Пример #26
0
	def run(cls, info):
		ssh_hostkeys = ['ssh_host_dsa_key',
		                'ssh_host_rsa_key']
		if info.manifest.system['release'] != 'squeeze':
			ssh_hostkeys.append('ssh_host_ecdsa_key')

		private = [os.path.join(info.root, 'etc/ssh', name) for name in ssh_hostkeys]
		public = [path + '.pub' for path in private]

		from common.tools import log_check_call
		log_check_call(['/usr/bin/shred', '--remove'] + private + public)
Пример #27
0
		def mount(self, prefix):
			"""Performs the mount operation or forwards it to another partition
			Args:
				prefix (str): Path prefix of the mountpoint
			"""
			mount_dir = os.path.join(prefix, self.destination)
			# If the source is another partition, we tell that partition to mount itself
			if isinstance(self.source, AbstractPartition):
				self.source.mount(destination=mount_dir)
			else:
				log_check_call(['mount'] + self.opts + [self.source, mount_dir])
			self.mount_dir = mount_dir
Пример #28
0
	def _before_create(self, e):
		from common.tools import log_check_call
		create_command = ('mkpart primary {start} {end}'
		                  .format(start=str(self.get_start()),
		                          end=str(self.get_end())))
		log_check_call(['/sbin/parted', '--script', '--align', 'none', e.volume.device_path,
		                '--', create_command])

		for flag in self.flags:
			log_check_call(['/sbin/parted', '--script', e.volume.device_path,
			                '--', ('set {idx} {flag} on'
			                       .format(idx=str(self.get_index()), flag=flag))])
Пример #29
0
    def _before_unlink_dm_node(self, e):
        """Unlinks the device mapping

		Args:
			e (_e_obj): Event object containing arguments to create()
		"""
        log_check_call(['dmsetup', 'remove', self.dm_node_name])
        # Delete the no longer valid information
        del self.dm_node_name
        del self.dm_node_path
        # Reset the device_path
        self.device_path = self.unlinked_device_path
Пример #30
0
	def _before_unlink_dm_node(self, e):
		"""Unlinks the device mapping

		Args:
			e (_e_obj): Event object containing arguments to create()
		"""
		log_check_call(['dmsetup', 'remove', self.dm_node_name])
		# Delete the no longer valid information
		del self.dm_node_name
		del self.dm_node_path
		# Reset the device_path
		self.device_path = self.unlinked_device_path
Пример #31
0
    def run(cls, info):
        import stat
        rwxr_xr_x = (stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR | stat.S_IRGRP
                     | stat.S_IXGRP | stat.S_IROTH | stat.S_IXOTH)
        from shutil import copy
        for name, src in info.initd['install'].iteritems():
            dst = os.path.join(info.root, 'etc/init.d', name)
            copy(src, dst)
            os.chmod(dst, rwxr_xr_x)
            log_check_call(['chroot', info.root, 'insserv', '--default', name])

        for name in info.initd['disable']:
            log_check_call(['chroot', info.root, 'insserv', '--remove', name])
Пример #32
0
        def mount(self, prefix):
            """Performs the mount operation or forwards it to another partition
			Args:
				prefix (str): Path prefix of the mountpoint
			"""
            mount_dir = os.path.join(prefix, self.destination)
            # If the source is another partition, we tell that partition to mount itself
            if isinstance(self.source, AbstractPartition):
                self.source.mount(destination=mount_dir)
            else:
                log_check_call(['mount'] + self.opts +
                               [self.source, mount_dir])
            self.mount_dir = mount_dir
Пример #33
0
	def run(cls, info):
		bundle_name = 'bundle-{id}'.format(id=info.run_id)
		info.bundle_path = os.path.join(info.workspace, bundle_name)
		arch = {'i386': 'i386', 'amd64': 'x86_64'}.get(info.manifest.system['architecture'])
		log_check_call(['euca-bundle-image',
		                '--image', info.volume.image_path,
		                '--arch', arch,
		                '--user', info.credentials['user-id'],
		                '--privatekey', info.credentials['private-key'],
		                '--cert', info.credentials['certificate'],
		                '--ec2cert', cert_ec2,
		                '--destination', info.bundle_path,
		                '--prefix', info.ami_name])
Пример #34
0
	def run(cls, info):
		from subprocess import CalledProcessError
		from common.tools import log_check_call
		try:
			log_check_call(['chroot', info.root,
			                'dpkg-query', '-W', 'openssh-server'])
			from common.tools import sed_i
			sshdconfig_path = os.path.join(info.root, 'etc/ssh/sshd_config')
			sed_i(sshdconfig_path, 'PermitRootLogin yes', 'PermitRootLogin no')
		except CalledProcessError:
			import logging
			logging.getLogger(__name__).warn('The OpenSSH server has not been installed, '
			                                 'not disabling SSH root login.')
Пример #35
0
	def run(cls, info):
		from common.fs.loopbackvolume import LoopbackVolume
		from common.tools import log_check_call

		boot_dir = os.path.join(info.root, 'boot')
		grub_dir = os.path.join(boot_dir, 'grub')

		from common.fs import remount
		p_map = info.volume.partition_map

		def link_fn():
			info.volume.link_dm_node()
			if isinstance(p_map, partitionmaps.none.NoPartitions):
				p_map.root.device_path = info.volume.device_path

		def unlink_fn():
			info.volume.unlink_dm_node()
			if isinstance(p_map, partitionmaps.none.NoPartitions):
				p_map.root.device_path = info.volume.device_path

		# GRUB cannot deal with installing to loopback devices
		# so we fake a real harddisk with dmsetup.
		# Guide here: http://ebroder.net/2009/08/04/installing-grub-onto-a-disk-image/
		if isinstance(info.volume, LoopbackVolume):
			remount(info.volume, link_fn)
		try:
			[device_path] = log_check_call(['readlink', '-f', info.volume.device_path])
			device_map_path = os.path.join(grub_dir, 'device.map')
			partition_prefix = 'msdos'
			if isinstance(p_map, partitionmaps.gpt.GPTPartitionMap):
				partition_prefix = 'gpt'
			with open(device_map_path, 'w') as device_map:
				device_map.write('(hd0) {device_path}\n'.format(device_path=device_path))
				if not isinstance(p_map, partitionmaps.none.NoPartitions):
					for idx, partition in enumerate(info.volume.partition_map.partitions):
						device_map.write('(hd0,{prefix}{idx}) {device_path}\n'
						                 .format(device_path=partition.device_path,
						                         prefix=partition_prefix,
						                         idx=idx + 1))

			# Install grub
			log_check_call(['/usr/sbin/chroot', info.root,
			                '/usr/sbin/grub-install', device_path])
			log_check_call(['/usr/sbin/chroot', info.root, '/usr/sbin/update-grub'])
		except Exception as e:
			if isinstance(info.volume, LoopbackVolume):
				remount(info.volume, unlink_fn)
			raise e

		if isinstance(info.volume, LoopbackVolume):
			remount(info.volume, unlink_fn)
Пример #36
0
	def run(cls, info):
		from common.fs.loopbackvolume import LoopbackVolume
		from common.tools import log_check_call

		boot_dir = os.path.join(info.root, 'boot')
		grub_dir = os.path.join(boot_dir, 'grub')

		from common.fs import remount
		p_map = info.volume.partition_map

		def link_fn():
			info.volume.link_dm_node()
			if isinstance(p_map, partitionmaps.none.NoPartitions):
				p_map.root.device_path = info.volume.device_path

		def unlink_fn():
			info.volume.unlink_dm_node()
			if isinstance(p_map, partitionmaps.none.NoPartitions):
				p_map.root.device_path = info.volume.device_path

		# GRUB cannot deal with installing to loopback devices
		# so we fake a real harddisk with dmsetup.
		# Guide here: http://ebroder.net/2009/08/04/installing-grub-onto-a-disk-image/
		if isinstance(info.volume, LoopbackVolume):
			remount(info.volume, link_fn)
		try:
			[device_path] = log_check_call(['readlink', '-f', info.volume.device_path])
			device_map_path = os.path.join(grub_dir, 'device.map')
			partition_prefix = 'msdos'
			if isinstance(p_map, partitionmaps.gpt.GPTPartitionMap):
				partition_prefix = 'gpt'
			with open(device_map_path, 'w') as device_map:
				device_map.write('(hd0) {device_path}\n'.format(device_path=device_path))
				if not isinstance(p_map, partitionmaps.none.NoPartitions):
					for idx, partition in enumerate(info.volume.partition_map.partitions):
						device_map.write('(hd0,{prefix}{idx}) {device_path}\n'
						                 .format(device_path=partition.device_path,
						                         prefix=partition_prefix,
						                         idx=idx + 1))

			# Install grub
			log_check_call(['chroot', info.root,
			                'grub-install', device_path])
			log_check_call(['chroot', info.root, 'update-grub'])
		except Exception as e:
			if isinstance(info.volume, LoopbackVolume):
				remount(info.volume, unlink_fn)
			raise e

		if isinstance(info.volume, LoopbackVolume):
			remount(info.volume, unlink_fn)
Пример #37
0
	def run(cls, info):
		import stat
		rwxr_xr_x = (stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR |
		             stat.S_IRGRP                | stat.S_IXGRP |
		             stat.S_IROTH                | stat.S_IXOTH)
		from shutil import copy
		for name, src in info.initd['install'].iteritems():
			dst = os.path.join(info.root, 'etc/init.d', name)
			copy(src, dst)
			os.chmod(dst, rwxr_xr_x)
			log_check_call(['chroot', info.root, 'insserv', '--default', name])

		for name in info.initd['disable']:
			log_check_call(['chroot', info.root, 'insserv', '--remove', name])
Пример #38
0
 def run(cls, info):
     bundle_name = 'bundle-{id}'.format(id=info.run_id)
     info.bundle_path = os.path.join(info.workspace, bundle_name)
     arch = {
         'i386': 'i386',
         'amd64': 'x86_64'
     }.get(info.manifest.system['architecture'])
     log_check_call([
         'euca-bundle-image', '--image', info.volume.image_path, '--arch',
         arch, '--user', info.credentials['user-id'], '--privatekey',
         info.credentials['private-key'], '--cert',
         info.credentials['certificate'], '--ec2cert', cert_ec2,
         '--destination', info.bundle_path, '--prefix', info.ami_name
     ])
Пример #39
0
	def run(cls, info):
		if 'metadata_sources' in info.manifest.plugins['cloud_init']:
			sources = info.manifest.plugins['cloud_init']['metadata_sources']
		else:
			source_mapping = {'ec2': 'Ec2'}
			sources = source_mapping.get(info.manifest.provider, None)
			if sources is None:
				import logging
				msg = ('No cloud-init metadata source mapping found for provider `{provider}\', '
				       'skipping selections setting.').format(info.manifest.provider)
				logging.getLogger(__name__).warn(msg)
				return
		sources = "cloud-init      cloud-init/datasources  multiselect     " + sources
		log_check_call(['chroot', info.root, 'debconf-set-selections'], sources)
Пример #40
0
	def run(cls, info):
		manifest_file = os.path.join(info.bundle_path, info.ami_name + '.manifest.xml')
		if info.host['region'] == 'us-east-1':
			s3_url = 'https://s3.amazonaws.com/'
		else:
			s3_url = 'https://s3-{region}.amazonaws.com/'.format(region=info.host['region'])
		log_check_call(['/usr/bin/euca-upload-bundle',
		                '--bucket', info.manifest.image['bucket'],
		                '--manifest', manifest_file,
		                '--access-key', info.credentials['access-key'],
		                '--secret-key', info.credentials['secret-key'],
		                '--url', s3_url,
		                '--region', info.host['region'],
		                '--ec2cert', cert_ec2])
Пример #41
0
	def run(cls, info):
		init_scripts_dir = os.path.join(assets, 'init.d')
		install = info.initd['install']
		from subprocess import CalledProcessError
		try:
			log_check_call(['chroot', info.root,
			                'dpkg-query', '-W', 'openssh-server'])
			if info.manifest.system['release'] == 'squeeze':
				install['generate-ssh-hostkeys'] = os.path.join(init_scripts_dir, 'squeeze/generate-ssh-hostkeys')
			else:
				install['generate-ssh-hostkeys'] = os.path.join(init_scripts_dir, 'generate-ssh-hostkeys')
		except CalledProcessError:
			import logging
			logging.getLogger(__name__).warn('The OpenSSH server has not been installed, '
			                                 'not installing SSH host key generation script.')
Пример #42
0
	def run(cls, info):
		from common.tools import sed_i
		from common.tools import log_check_call
		locale_gen = os.path.join(info.root, 'etc/locale.gen')
		locale_str = '{locale}.{charmap} {charmap}'.format(locale=info.manifest.system['locale'],
		                                                   charmap=info.manifest.system['charmap'])
		search = '# ' + locale_str
		sed_i(locale_gen, search, locale_str)

		log_check_call(['chroot', info.root, 'locale-gen'])

		lang = '{locale}.{charmap}'.format(locale=info.manifest.system['locale'],
		                                   charmap=info.manifest.system['charmap'])
		log_check_call(['chroot', info.root,
		                'update-locale', 'LANG=' + lang])
Пример #43
0
	def _before_format(self, e):
		"""Formats the partition
		"""
		# If there is no explicit format_command define we simply call mkfs.fstype
		if self.format_command is None:
			format_command = ['mkfs.{fs}', '{device_path}']
		else:
			format_command = self.format_command
		variables = {'fs': self.filesystem,
		             'device_path': self.device_path,
		             'size': self.size,
		             }
		command = map(lambda part: part.format(**variables), format_command)
		# Format the partition
		log_check_call(command)
Пример #44
0
    def run(cls, info):
        from common.tools import sed_i
        from common.tools import log_check_call
        locale_gen = os.path.join(info.root, 'etc/locale.gen')
        locale_str = '{locale}.{charmap} {charmap}'.format(
            locale=info.manifest.system['locale'],
            charmap=info.manifest.system['charmap'])
        search = '# ' + locale_str
        sed_i(locale_gen, search, locale_str)

        log_check_call(['chroot', info.root, 'locale-gen'])

        lang = '{locale}.{charmap}'.format(
            locale=info.manifest.system['locale'],
            charmap=info.manifest.system['charmap'])
        log_check_call(['chroot', info.root, 'update-locale', 'LANG=' + lang])
Пример #45
0
	def run(cls, info):
		from common.tools import log_check_call
		from subprocess import CalledProcessError
		missing_packages = []
		for package in info.host_dependencies:
			try:
				log_check_call(['/usr/bin/dpkg-query', '-s', package])
			except CalledProcessError:
				missing_packages.append(package)
		if len(missing_packages) > 0:
			pkgs = '\', `'.join(missing_packages)
			if len(missing_packages) > 1:
				msg = "The packages `{packages}\' are not installed".format(packages=pkgs)
			else:
				msg = "The package `{packages}\' is not installed".format(packages=pkgs)
			raise TaskError(msg)
Пример #46
0
    def _before_format(self, e):
        """Formats the partition
		"""
        # If there is no explicit format_command define we simply call mkfs.fstype
        if self.format_command is None:
            format_command = ['mkfs.{fs}', '{device_path}']
        else:
            format_command = self.format_command
        variables = {
            'fs': self.filesystem,
            'device_path': self.device_path,
            'size': self.size,
        }
        command = map(lambda part: part.format(**variables), format_command)
        # Format the partition
        log_check_call(command)
Пример #47
0
	def _before_create(self, e):
		"""Creates the partition
		"""
		from common.tools import log_check_call
		# The create command is failry simple, start and end are just Bytes objects coerced into strings
		create_command = ('mkpart primary {start} {end}'
		                  .format(start=str(self.get_start()),
		                          end=str(self.get_end())))
		# Create the partition
		log_check_call(['parted', '--script', '--align', 'none', e.volume.device_path,
		                '--', create_command])

		# Set any flags on the partition
		for flag in self.flags:
			log_check_call(['parted', '--script', e.volume.device_path,
			                '--', ('set {idx} {flag} on'
			                       .format(idx=str(self.get_index()), flag=flag))])
Пример #48
0
    def get_uuid(self):
        """Gets the UUID of the partition

		Returns:
			str. The UUID of the partition
		"""
        [uuid] = log_check_call(
            ['blkid', '-s', 'UUID', '-o', 'value', self.device_path])
        return uuid
Пример #49
0
 def run(cls, info):
     init_scripts_dir = os.path.join(assets, 'init.d')
     install = info.initd['install']
     from subprocess import CalledProcessError
     try:
         log_check_call(
             ['chroot', info.root, 'dpkg-query', '-W', 'openssh-server'])
         if info.manifest.system['release'] == 'squeeze':
             install['generate-ssh-hostkeys'] = os.path.join(
                 init_scripts_dir, 'squeeze/generate-ssh-hostkeys')
         else:
             install['generate-ssh-hostkeys'] = os.path.join(
                 init_scripts_dir, 'generate-ssh-hostkeys')
     except CalledProcessError:
         import logging
         logging.getLogger(__name__).warn(
             'The OpenSSH server has not been installed, '
             'not installing SSH host key generation script.')
Пример #50
0
    def run(cls, info):
        info.packages.add('bzip2')
        info.packages.add('build-essential')
        info.packages.add('dkms')

        from common.tools import log_check_call
        [kernel_version] = log_check_call(['chroot', info.root, 'uname', '-r'])
        kernel_headers_pkg = 'linux-headers-{version}'.format(
            version=kernel_version)
        info.packages.add(kernel_headers_pkg)
Пример #51
0
 def run(cls, info):
     manifest_file = os.path.join(info.bundle_path,
                                  info.ami_name + '.manifest.xml')
     if info.host['region'] == 'us-east-1':
         s3_url = 'https://s3.amazonaws.com/'
     elif info.host['region'] == 'cn-north-1':
         s3_url = 'https://s3.cn-north-1.amazonaws.com.cn'
     else:
         s3_url = 'https://s3-{region}.amazonaws.com/'.format(
             region=info.host['region'])
     info.manifest.manifest_location = info.manifest.image[
         'bucket'] + '/' + info.ami_name + '.manifest.xml'
     log_check_call([
         'euca-upload-bundle', '--bucket', info.manifest.image['bucket'],
         '--manifest', manifest_file, '--access-key',
         info.credentials['access-key'], '--secret-key',
         info.credentials['secret-key'], '--url', s3_url, '--region',
         info.host['region'], '--ec2cert', cert_ec2
     ])
Пример #52
0
    def run(cls, info):
        import stat
        rwxr_xr_x = (stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR | stat.S_IRGRP
                     | stat.S_IXGRP | stat.S_IROTH | stat.S_IXOTH)
        x_all = stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH

        grubd = os.path.join(info.root, 'etc/grub.d')
        for cfg in [os.path.join(grubd, f) for f in os.listdir(grubd)]:
            os.chmod(cfg, os.stat(cfg).st_mode & ~x_all)

        from shutil import copy
        script_src = os.path.join(assets, 'grub.d/40_custom')
        script_dst = os.path.join(info.root, 'etc/grub.d/40_custom')
        copy(script_src, script_dst)
        os.chmod(script_dst, rwxr_xr_x)

        from base.fs.partitionmaps.none import NoPartitions
        if not isinstance(info.volume.partition_map, NoPartitions):
            from common.tools import sed_i
            root_idx = info.volume.partition_map.root.get_index()
            grub_device = 'GRUB_DEVICE=/dev/xvda{idx}'.format(idx=root_idx)
            sed_i(script_dst, '^GRUB_DEVICE=/dev/xvda$', grub_device)
            grub_root = '\troot (hd0,{idx})'.format(idx=root_idx - 1)
            sed_i(script_dst, '^\troot \(hd0\)$', grub_root)

        if info.manifest.volume['backing'] == 's3':
            from common.tools import sed_i
            sed_i(script_dst, '^GRUB_DEVICE=/dev/xvda$',
                  'GRUB_DEVICE=/dev/xvda1')

        from common.tools import sed_i
        grub_def = os.path.join(info.root, 'etc/default/grub')
        sed_i(grub_def, '^GRUB_TIMEOUT=[0-9]+', 'GRUB_TIMEOUT=0\n'
              'GRUB_HIDDEN_TIMEOUT=true')

        from common.tools import log_check_call
        log_check_call(['chroot', info.root, 'update-grub'])
        log_check_call([
            'chroot', info.root, 'ln', '--symbolic', '/boot/grub/grub.cfg',
            '/boot/grub/menu.lst'
        ])
Пример #53
0
	def run(cls, info):
		with open(os.path.join(info.root, 'etc/hostname')) as handle:
			hostname = handle.read().strip()
		with open(os.path.join(info.root, 'etc/hosts'), 'a') as handle:
			handle.write('127.0.0.1\t{hostname}\n'.format(hostname=hostname))

		from shutil import copy
		pp_manifest = info.manifest.plugins['puppet']['manifest']
		manifest_rel_dst = os.path.join('tmp', os.path.basename(pp_manifest))
		manifest_dst = os.path.join(info.root, manifest_rel_dst)
		copy(pp_manifest, manifest_dst)

		manifest_path = os.path.join('/', manifest_rel_dst)
		from common.tools import log_check_call
		log_check_call(['chroot', info.root,
		                'puppet', 'apply', manifest_path])
		os.remove(manifest_dst)

		from common.tools import sed_i
		hosts_path = os.path.join(info.root, 'etc/hosts')
		sed_i(hosts_path, '127.0.0.1\s*{hostname}\n?'.format(hostname=hostname), '')
Пример #54
0
 def run(cls, info):
     from common.tools import log_check_call
     from subprocess import CalledProcessError
     import re
     missing_packages = []
     for command, package in info.host_dependencies.items():
         try:
             log_check_call(['type ' + command], shell=True)
         except CalledProcessError:
             if re.match('^https?:\/\/', package):
                 msg = ('The command `{command}\' is not available, '
                        'you can download the software at `{package}\'.'.
                        format(command=command, package=package))
             else:
                 msg = ('The command `{command}\' is not available, '
                        'it is located in the package `{package}\'.'.format(
                            command=command, package=package))
             missing_packages.append(msg)
     if len(missing_packages) > 0:
         msg = '\n'.join(missing_packages)
         raise TaskError(msg)
Пример #55
0
    def run(cls, info):
        ssh_dir = os.path.join(info.root, 'home/vagrant/.ssh')
        os.mkdir(ssh_dir)

        authorized_keys_source_path = os.path.join(assets, 'authorized_keys')
        with open(authorized_keys_source_path, 'r') as authorized_keys_source:
            insecure_public_key = authorized_keys_source.read()

        authorized_keys_path = os.path.join(ssh_dir, 'authorized_keys')
        with open(authorized_keys_path, 'a') as authorized_keys:
            authorized_keys.write(insecure_public_key)

        import stat
        os.chmod(ssh_dir, stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR)
        os.chmod(authorized_keys_path, stat.S_IRUSR | stat.S_IWUSR)

        # We can't do this directly with python, since getpwnam gets its info from the host
        from common.tools import log_check_call
        log_check_call([
            'chroot', info.root, 'chown', 'vagrant:vagrant',
            '/home/vagrant/.ssh', '/home/vagrant/.ssh/authorized_keys'
        ])
Пример #56
0
    def install_local(cls, info, local_packages):
        from shutil import copy
        from common.tools import log_check_call
        import os

        absolute_package_paths = []
        chrooted_package_paths = []
        for package_src in local_packages:
            pkg_name = os.path.basename(package_src.path)
            package_rel_dst = os.path.join('tmp', pkg_name)
            package_dst = os.path.join(info.root, package_rel_dst)
            copy(package_src.path, package_dst)
            absolute_package_paths.append(package_dst)
            package_path = os.path.join('/', package_rel_dst)
            chrooted_package_paths.append(package_path)

        env = os.environ.copy()
        env['DEBIAN_FRONTEND'] = 'noninteractive'
        log_check_call(['chroot', info.root, 'dpkg', '--install'] +
                       chrooted_package_paths,
                       env=env)

        for path in absolute_package_paths:
            os.remove(path)