def scrub_cow(self, path=None, display=None): """ Scrub or display details for a cow device Example: %(prog)s (cmd)s scrub-cow -d /dev/mapper/lunr--volume-my--snap-cow """ config = {} if self.verbose == 1: log.setLevel(logging.INFO) if self.verbose > 1: log.setLevel(logging.DEBUG) config['display-exceptions'] = True if display: if self.verbose < 2: log.setLevel(logging.INFO) log.info("Display Only, Not Scrubbing") config['display-only'] = True try: # Init the Scrub object with our command line options scrub = Scrub(LunrConfig({'scrub': config})) # Scrub the cow scrub.scrub_cow(path) except ScrubError, e: log.error(str(e)) return 1
def test_writable_cow_multiline_table(self): # Let's do some silly math size = directio.size(self._ramdisk) megs = size / 1024 / 1024 megs = megs - megs % 4 # 12 megs for a volume, 4 for lvm itself alloc = megs - 12 - 4 vg = self.conf.string('volume', 'volume_group', None) # Reserve a 4m hole at the front, and 8m at the end execute('lvcreate', vg, size='4m', name='tmpvol') execute('lvcreate', vg, size='%sm' % alloc, name='wasted') execute('lvremove', '%s/tmpvol' % vg, force=None) foo = execute('pvs', self._ramdisk) foo = execute('vgs', vg) foo = execute('lvs', vg) volume_id = str(uuid4()) self.volume.create(volume_id) volume = self.volume.get(volume_id) execute('lvremove', '%s/wasted' % vg, force=None) dmname = '%s-%s' % (re.sub('-', '--', vg), re.sub('-', '--', volume_id)) foo = execute('dmsetup', 'table', dmname) self.assert_('\n' in foo) backup_id = str(uuid4()) snapshot = self.volume.create_snapshot(volume_id, backup_id, '123456') scrub = Scrub(LunrConfig()) (cow_name, cow_path) = scrub.get_writable_cow(snapshot, volume) execute('dmsetup', 'remove', cow_name) self.assertTrue(True)
def test_writable_cow_multiline_table(self): # Let's do some silly math size = directio.size(self._ramdisk) megs = size / 1024 / 1024 megs = megs - megs % 4 # 12 megs for a volume, 4 for lvm itself alloc = megs - 12 - 4 vg = self.conf.string('volume', 'volume_group', None) # Reserve a 4m hole at the front, and 8m at the end execute('lvcreate', vg, size='4m', name='tmpvol') execute('lvcreate', vg, size='%sm' % alloc, name='wasted') execute('lvremove', '%s/tmpvol' % vg, force=None) foo = execute('pvs', self._ramdisk) foo = execute('vgs', vg) foo = execute('lvs', vg) volume_id = str(uuid4()) self.volume.create(volume_id) volume = self.volume.get(volume_id) execute('lvremove', '%s/wasted' % vg, force=None) dmname = '%s-%s' % (re.sub('-', '--', vg), re.sub( '-', '--', volume_id)) foo = execute('dmsetup', 'table', dmname) self.assert_('\n' in foo) backup_id = str(uuid4()) snapshot = self.volume.create_snapshot(volume_id, backup_id, '123456') scrub = Scrub(LunrConfig()) (cow_name, cow_path) = scrub.get_writable_cow(snapshot, volume) execute('dmsetup', 'remove', cow_name) self.assertTrue(True)
def __init__(self, conf): self.volume_group = conf.string('volume', 'volume_group', 'lunr-volume') self.device_prefix = conf.string('volume', 'device_prefix', '/dev') self.run_dir = conf.string('storage', 'run_dir', conf.path('run')) self.convert_gbs = conf.int('glance', 'convert_gbs', 100) self.glance_mgmt_urls = conf.list('glance', 'glance_mgmt_urls', None) self.glance_base_multiplier = conf.float('glance', 'base_convert_multiplier', 2.0) self.glance_custom_multiplier = conf.float( 'glance', 'custom_convert_multiplier', 4.0) self.skip_fork = conf.bool('storage', 'skip_fork', False) self.scrub = Scrub(conf) self.conf = conf self.max_snapshot_bytes = conf.int('volume', 'max_snapshot_bytes', None) if self.max_snapshot_bytes: self.sector_size = conf.int('volume', 'sector_size', 512) max_bytes = (self.max_snapshot_bytes - self.max_snapshot_bytes % self.sector_size) if max_bytes != self.max_snapshot_bytes: logger.info("Setting max_snapshot_size to %s" % max_bytes) self.max_snapshot_bytes = max_bytes self.has_old_mkfs = self.old_mkfs()
def test_snapshot_scrub(self): block_size = 32768 # Create a Volume volume_id = str(uuid4()) self.volume.create(volume_id) # Get the volume information volume = self.volume.get(volume_id) # Fill the volume with 'ZERG's with directio.open(volume['path']) as file: size = directio.size(volume['path']) for i in xrange(0, size / block_size): # 32768 / 4 = 8192 file.write('ZERG' * (block_size / 4)) # Create a snap-shot with a timestamp of 123456 backup_id = str(uuid4()) snapshot = self.volume.create_snapshot(volume_id, backup_id, '123456') # Now that the snapshot is made, simulate users making writes # to the origin during a normal backup. This should generate # exceptions in the cow with directio.open(volume['path']) as file: # Overwrite all the zergs. for i in xrange(0, size / block_size): file.write('A' * block_size) # Tell scrub we don't want it to remove the cow after scrubbing scrub = Scrub(LunrConfig()) # Build the cow-zero (cow_name, cow_path) = scrub.get_writable_cow(snapshot, volume) with directio.open(cow_path) as file: size = directio.size(cow_path) for i in xrange(0, size / block_size): block = file.read(block_size) if 'ZERG' in block: self.assert_(True) break with directio.open(self._ramdisk) as file: size = directio.size(self._ramdisk) for i in xrange(0, size / block_size): block = file.read(block_size) if 'ZERG' in block: self.assert_(True) break # Scrub the cow of all exceptions scrub.scrub_cow(cow_path) scrub.remove_cow(cow_name) # Remove & scrub the volume. LVM removes snapshot itself. self.volume.remove_lvm_volume(volume) # Read full disk for hidden zergs. with directio.open(self._ramdisk) as file: size = directio.size(self._ramdisk) for i in xrange(0, size / block_size): block = file.read(block_size) if 'ZERG' in block: self.fail("Found zergs on disk: %s" % self._ramdisk)