def test_create_configdrive_vfat(self): CONF.set_override('config_drive_format', 'vfat') imagefile = None try: self.mox.StubOutWithMock(utils, 'mkfs') self.mox.StubOutWithMock(utils, 'execute') self.mox.StubOutWithMock(utils, 'trycmd') utils.mkfs('vfat', mox.IgnoreArg(), label='config-2').AndReturn(None) utils.trycmd('mount', '-o', mox.IgnoreArg(), mox.IgnoreArg(), mox.IgnoreArg(), run_as_root=True).AndReturn((None, None)) utils.execute('umount', mox.IgnoreArg(), run_as_root=True).AndReturn(None) self.mox.ReplayAll() with configdrive.ConfigDriveBuilder(FakeInstanceMD()) as c: (fd, imagefile) = tempfile.mkstemp(prefix='cd_vfat_') os.close(fd) c.make_drive(imagefile) # NOTE(mikal): we can't check for a VFAT output here because the # filesystem creation stuff has been mocked out because it # requires root permissions finally: if imagefile: fileutils.delete_if_exists(imagefile)
def test_create_configdrive_vfat(self): CONF.set_override('config_drive_format', 'vfat') imagefile = None try: self.mox.StubOutWithMock(utils, 'mkfs') self.mox.StubOutWithMock(utils, 'execute') self.mox.StubOutWithMock(utils, 'trycmd') utils.mkfs('vfat', mox.IgnoreArg(), label='config-2').AndReturn(None) utils.trycmd('mount', '-o', mox.IgnoreArg(), mox.IgnoreArg(), mox.IgnoreArg(), run_as_root=True).AndReturn((None, None)) utils.execute('umount', mox.IgnoreArg(), run_as_root=True).AndReturn(None) self.mox.ReplayAll() with configdrive.ConfigDriveBuilder(FakeInstanceMD()) as c: (fd, imagefile) = tempfile.mkstemp(prefix='cd_vfat_') os.close(fd) c.make_drive(imagefile) # NOTE(mikal): we can't check for a VFAT output here because the # filesystem creation stuff has been mocked out because it # requires root permissions finally: if imagefile: fileutils.delete_if_exists(imagefile)
def _make_vfat(self, path, tmpdir): # NOTE(mikal): This is a little horrible, but I couldn't find an # equivalent to genisoimage for vfat filesystems. with open(path, 'wb') as f: f.truncate(CONFIGDRIVESIZE_BYTES) utils.mkfs('vfat', path, label='config-2') with utils.tempdir() as mountdir: mounted = False try: _, err = utils.trycmd( 'mount', '-o', 'loop,uid=%d,gid=%d' % (os.getuid(), os.getgid()), path, mountdir, run_as_root=True) if err: raise exception.ConfigDriveMountFailed(operation='mount', error=err) mounted = True # NOTE(mikal): I can't just use shutils.copytree here, # because the destination directory already # exists. This is annoying. for ent in os.listdir(tmpdir): shutil.copytree(os.path.join(tmpdir, ent), os.path.join(mountdir, ent)) finally: if mounted: utils.execute('umount', mountdir, run_as_root=True)
def _make_vfat(self, path, tmpdir): # NOTE(mikal): This is a little horrible, but I couldn't find an # equivalent to genisoimage for vfat filesystems. with open(path, 'wb') as f: f.truncate(CONFIGDRIVESIZE_BYTES) utils.mkfs('vfat', path, label='config-2') with utils.tempdir() as mountdir: mounted = False try: _, err = utils.trycmd('mount', '-o', 'loop,uid=%d,gid=%d' % (os.getuid(), os.getgid()), path, mountdir, run_as_root=True) if err: raise exception.ConfigDriveMountFailed(operation='mount', error=err) mounted = True # NOTE(mikal): I can't just use shutils.copytree here, # because the destination directory already # exists. This is annoying. for ent in os.listdir(tmpdir): shutil.copytree(os.path.join(tmpdir, ent), os.path.join(mountdir, ent)) finally: if mounted: utils.execute('umount', mountdir, run_as_root=True)
def _inner_get_dev(self): device = self._allocate_nbd() if not device: return False # NOTE(mikal): qemu-nbd will return an error if the device file is # already in use. LOG.debug('Get nbd device %(dev)s for %(imgfile)s', { 'dev': device, 'imgfile': self.image }) _out, err = utils.trycmd('qemu-nbd', '-c', device, self.image, run_as_root=True) if err: self.error = _('qemu-nbd error: %s') % err LOG.info(_LI('NBD mount error: %s'), self.error) return False # NOTE(vish): this forks into another process, so give it a chance # to set up before continuing pidfile = "/sys/block/%s/pid" % os.path.basename(device) for _i in range(CONF.timeout_nbd): if os.path.exists(pidfile): self.device = device break time.sleep(1) else: self.error = _('nbd device %s did not show up') % device LOG.info(_LI('NBD mount error: %s'), self.error) # Cleanup _out, err = utils.trycmd('qemu-nbd', '-d', device, run_as_root=True) if err: LOG.warning( _LW('Detaching from erroneous nbd device returned ' 'error: %s'), err) return False self.error = '' self.linked = True return True
def has_file(self, path): LOG.debug("Has file path=%s", path) canonpath = self._canonical_path(path) exists, _err = utils.trycmd('readlink', '-e', canonpath, run_as_root=True) return exists
def _inner_get_dev(self): device = self._allocate_nbd() if not device: return False # NOTE(mikal): qemu-nbd will return an error if the device file is # already in use. LOG.debug('Get nbd device %(dev)s for %(imgfile)s', {'dev': device, 'imgfile': self.image}) _out, err = utils.trycmd('qemu-nbd', '-c', device, self.image, run_as_root=True) if err: self.error = _('qemu-nbd error: %s') % err LOG.info(_LI('NBD mount error: %s'), self.error) return False # NOTE(vish): this forks into another process, so give it a chance # to set up before continuing pidfile = "/sys/block/%s/pid" % os.path.basename(device) for _i in range(CONF.timeout_nbd): if os.path.exists(pidfile): self.device = device break time.sleep(1) else: self.error = _('nbd device %s did not show up') % device LOG.info(_LI('NBD mount error: %s'), self.error) # Cleanup _out, err = utils.trycmd('qemu-nbd', '-d', device, run_as_root=True) if err: LOG.warning(_LW('Detaching from erroneous nbd device returned ' 'error: %s'), err) return False self.error = '' self.linked = True return True
def mnt_dev(self): """Mount the device into the file system.""" LOG.debug("Mount %(dev)s on %(dir)s", {'dev': self.mapped_device, 'dir': self.mount_dir}) _out, err = utils.trycmd('mount', self.mapped_device, self.mount_dir, discard_warnings=True, run_as_root=True) if err: self.error = _('Failed to mount filesystem: %s') % err LOG.debug(self.error) return False self.mounted = True return True
def _inner_get_dev(self): out, err = utils.trycmd('losetup', '--find', '--show', self.image, run_as_root=True) if err: self.error = _('Could not attach image to loopback: %s') % err LOG.info(_LI('Loop mount error: %s'), self.error) self.linked = False self.device = None return False self.device = out.strip() LOG.debug("Got loop device %s", self.device) self.linked = True return True
def _can_fallocate(self): """Check once per class, whether fallocate(1) is available, and that the instances directory supports fallocate(2). """ can_fallocate = getattr(self.__class__, 'can_fallocate', None) if can_fallocate is None: _out, err = utils.trycmd('fallocate', '-n', '-l', '1', self.path + '.fallocate_test') fileutils.delete_if_exists(self.path + '.fallocate_test') can_fallocate = not err self.__class__.can_fallocate = can_fallocate if not can_fallocate: LOG.error(_LE('Unable to preallocate_images=%(imgs)s at path: ' '%(path)s'), {'imgs': CONF.preallocate_images, 'path': self.path}) return can_fallocate
def map_dev(self): """Map partitions of the device to the file system namespace.""" assert (os.path.exists(self.device)) LOG.debug("Map dev %s", self.device) automapped_path = '/dev/%sp%s' % (os.path.basename( self.device), self.partition) if self.partition == -1: self.error = _('partition search unsupported with %s') % self.mode elif self.partition and not os.path.exists(automapped_path): map_path = '/dev/mapper/%sp%s' % (os.path.basename( self.device), self.partition) assert (not os.path.exists(map_path)) # Note kpartx can output warnings to stderr and succeed # Also it can output failures to stderr and "succeed" # So we just go on the existence of the mapped device _out, err = utils.trycmd('kpartx', '-a', self.device, run_as_root=True, discard_warnings=True) # Note kpartx does nothing when presented with a raw image, # so given we only use it when we expect a partitioned image, fail if not os.path.exists(map_path): if not err: err = _('partition %s not found') % self.partition self.error = _('Failed to map partitions: %s') % err else: self.mapped_device = map_path self.mapped = True elif self.partition and os.path.exists(automapped_path): # Note auto mapping can be enabled with the 'max_part' option # to the nbd or loop kernel modules. Beware of possible races # in the partition scanning for _loop_ devices though # (details in bug 1024586), which are currently uncatered for. self.mapped_device = automapped_path self.mapped = True self.automapped = True else: self.mapped_device = self.device self.mapped = True return self.mapped
def mnt_dev(self): """Mount the device into the file system.""" LOG.debug("Mount %(dev)s on %(dir)s", { 'dev': self.mapped_device, 'dir': self.mount_dir }) _out, err = utils.trycmd('mount', self.mapped_device, self.mount_dir, discard_warnings=True, run_as_root=True) if err: self.error = _('Failed to mount filesystem: %s') % err LOG.debug(self.error) return False self.mounted = True return True
def _can_fallocate(self): """Check once per class, whether fallocate(1) is available, and that the instances directory supports fallocate(2). """ can_fallocate = getattr(self.__class__, 'can_fallocate', None) if can_fallocate is None: _out, err = utils.trycmd('fallocate', '-n', '-l', '1', self.path + '.fallocate_test') fileutils.delete_if_exists(self.path + '.fallocate_test') can_fallocate = not err self.__class__.can_fallocate = can_fallocate if not can_fallocate: LOG.error( _LE('Unable to preallocate_images=%(imgs)s at path: ' '%(path)s'), { 'imgs': CONF.preallocate_images, 'path': self.path }) return can_fallocate
def map_dev(self): """Map partitions of the device to the file system namespace.""" assert(os.path.exists(self.device)) LOG.debug("Map dev %s", self.device) automapped_path = '/dev/%sp%s' % (os.path.basename(self.device), self.partition) if self.partition == -1: self.error = _('partition search unsupported with %s') % self.mode elif self.partition and not os.path.exists(automapped_path): map_path = '/dev/mapper/%sp%s' % (os.path.basename(self.device), self.partition) assert(not os.path.exists(map_path)) # Note kpartx can output warnings to stderr and succeed # Also it can output failures to stderr and "succeed" # So we just go on the existence of the mapped device _out, err = utils.trycmd('kpartx', '-a', self.device, run_as_root=True, discard_warnings=True) # Note kpartx does nothing when presented with a raw image, # so given we only use it when we expect a partitioned image, fail if not os.path.exists(map_path): if not err: err = _('partition %s not found') % self.partition self.error = _('Failed to map partitions: %s') % err else: self.mapped_device = map_path self.mapped = True elif self.partition and os.path.exists(automapped_path): # Note auto mapping can be enabled with the 'max_part' option # to the nbd or loop kernel modules. Beware of possible races # in the partition scanning for _loop_ devices though # (details in bug 1024586), which are currently uncatered for. self.mapped_device = automapped_path self.mapped = True self.automapped = True else: self.mapped_device = self.device self.mapped = True return self.mapped
def has_file(self, path): LOG.debug("Has file path=%s", path) canonpath = self._canonical_path(path) exists, _err = utils.trycmd("readlink", "-e", canonpath, run_as_root=True) return exists