def reconstruct_zfs_volume(self, name, volume): print('Attempting to reconstruct volume {}:'.format(name)) vol = Volume.objects.get(vol_guid=volume['guid']) if vol is None: print(' Volume not found in database - volumes.json and database not in sync') return False # 1. Check if we already imported that volume if vol.status != 'UNKNOWN': print ' Pool already imported and online' return True # 2. Try to import pool if self.notifier.zfs_import(vol.vol_name, vol.vol_guid): print ' Imported existing volume' return True # 3. Try to recreate pool grps = {} for catname in ('data', 'cache', 'spares', 'logs'): groups = volume['{}-vdevs'.format(catname)] for group in groups: print(' Group: {}'.format(group['name'])) grp = { 'type': group['type'], 'disks': [] } for vdev in group['disks']: sys.stdout.write('\t{} [{}]: '.format(vdev['name'], humanize_size(vdev['size']))) disk, match = self.guess_disk(vdev) if disk is None: print('not found') print(' Reconstruction of volume {} aborted due to lack of matching device'.format(name)) return False print('found {} [{} match]'.format(disk, match)) self.used_disks.append(disk) grp['disks'].append(disk) grps[group['name']] = grp self.notifier.init('volume', vol, groups=grps) # 3. Recreate datasets print(' Recreating datasets:') for dset in volume['datasets']: print('\t{}'.format(dset['name'])) self.notifier.create_zfs_dataset(dset['name']) # 4. Recreate zvols if len(volume['zvols']) > 0: print(' Recreating zvols:') for zvol in volume['zvols']: print('\t{} [{}]'.format(zvol['name'], humanize_size(zvol['size']))) self.notifier.create_zfs_vol(zvol['name'], zvol['size']) return True
def print_progress(message, done, percentage): global progress_old_done global progress_old_time if percentage > 1: percentage = 1 if progress_old_time is None: progress_old_time = datetime.datetime.now() now = datetime.datetime.now() progress_width = get_terminal_size()[0] - 22 filled_width = int(percentage * progress_width) avg_speed = (done - progress_old_done) # Erase 2 lines above sys.stdout.write('\033[2K\033[A\033[2K\r') sys.stdout.write('Status: {}\n'.format(message)) sys.stdout.write('[{}{}] {}/s {:.2%}'.format( '#' * filled_width, '_' * (progress_width - filled_width), humanize_size(avg_speed), percentage)) sys.stdout.flush() progress_old_done = done progress_old_time = datetime.datetime.now()
def get_file_handler( self, method, filename, size=None, progress=None, download_rate=None ): if progress is not None and self._pkgname: self.progress = (progress * self._baseprogress) / 100 if self.progress == 0: self.progress = 1 self.details = '%s<br />%s(%d%%)%s' % ( self._pkgname, '%s ' % humanize_size(size) if size else '', progress, ' %s/s' % humanize_size(download_rate) if download_rate else '', ) self.dump()
def volume_detach(request, vid): volume = models.Volume.objects.get(pk=vid) usedbytes = sum( [mp._get_used_bytes() for mp in volume.mountpoint_set.all()] ) usedsize = humanize_size(usedbytes) services = volume.has_attachments() if volume.vol_encrypt > 0: request.session["allow_gelikey"] = True if request.method == "POST": form = forms.VolumeExport( request.POST, instance=volume, services=services) if form.is_valid(): try: volume.delete( destroy=form.cleaned_data['mark_new'], cascade=form.cleaned_data.get('cascade', True)) return JsonResp( request, message=_("The volume has been successfully detached")) except ServiceFailed, e: return JsonResp(request, error=True, message=unicode(e))
def volume_detach(request, vid): _n = notifier() standby_offline = False if not _n.is_freenas() and _n.failover_licensed(): try: with client as c: c.call('failover.call_remote', 'core.ping') except Exception: standby_offline = True volume = models.Volume.objects.get(pk=vid) usedbytes = volume._get_used_bytes() usedsize = humanize_size(usedbytes) if usedbytes else None with client as c: services = { key: val for key, val in list(c.call('pool.attachments', volume.id).items()) if len(val) > 0 } if volume.vol_encrypt > 0: request.session["allow_gelikey"] = True if request.method == "POST": form = forms.VolumeExport( request.POST, instance=volume, services=services) if form.is_valid(): _n = notifier() if '__confirm' not in request.POST and not _n.is_freenas() and _n.failover_licensed(): remaining_volumes = models.Volume.objects.exclude(pk=vid) if not remaining_volumes.exists(): message = render_to_string('freeadmin/generic_model_confirm.html', { 'message': 'Warning: this pool is required for HA to function.<br />Do you want to continue?', }) return JsonResp(request, confirm=message) try: events = [] form.done(request, events) return JsonResp( request, message=_("The volume has been successfully detached"), events=events, ) except ServiceFailed as e: return JsonResp( request, form=form, error=True, message=e.value, events=["serviceFailed(\"%s\")" % e.service]) else: form = forms.VolumeExport(instance=volume, services=services) return render(request, 'storage/volume_detach.html', { 'standby_offline': standby_offline, 'volume': volume, 'form': form, 'used': usedsize, 'services': services, })
def _get_total_si(self): try: totalbytes = self._vfs.f_blocks * self._vfs.f_frsize return u"%s" % (humanize_size(totalbytes)) except: if self.mp_volume.is_decrypted(): return _(u"Error getting total space") else: return _("Locked")
def _get_avail_si(self): try: availbytes = self._vfs.f_bavail * self._vfs.f_frsize return u"%s" % (humanize_size(availbytes)) except: if self.mp_volume.is_decrypted(): return _(u"Error getting available space") else: return _("Locked")
def _get_used_si(self): try: usedbytes = self._get_used_bytes() return u"%s" % (humanize_size(usedbytes)) except: if self.mp_volume.is_decrypted(): return _(u"Error getting used space") else: return _("Locked")
def volume_detach(request, vid): _n = notifier() standby_offline = False if not _n.is_freenas() and _n.failover_licensed(): try: with client as c: c.call('failover.call_remote', 'core.ping') except Exception: standby_offline = True volume = models.Volume.objects.get(pk=vid) usedbytes = volume._get_used_bytes() usedsize = humanize_size(usedbytes) if usedbytes else None services = { key: val for key, val in list(volume.has_attachments().items()) if len(val) > 0 } if volume.vol_encrypt > 0: request.session["allow_gelikey"] = True if request.method == "POST": form = forms.VolumeExport(request.POST, instance=volume, services=services) if form.is_valid(): _n = notifier() if '__confirm' not in request.POST and not _n.is_freenas( ) and _n.failover_licensed(): message = render_to_string( 'freeadmin/generic_model_confirm.html', { 'message': 'Warning: this pool is required for HA to function.<br />Do you want to continue?', }) return JsonResp(request, confirm=message) try: events = [] volume.delete(destroy=form.cleaned_data['mark_new'], cascade=form.cleaned_data.get('cascade', True)) form.done(request, events) return JsonResp( request, message=_("The volume has been successfully detached"), events=events, ) except ServiceFailed as e: return JsonResp(request, error=True, message=str(e)) else: form = forms.VolumeExport(instance=volume, services=services) return render( request, 'storage/volume_detach.html', { 'standby_offline': standby_offline, 'volume': volume, 'form': form, 'used': usedsize, 'services': services, })
def humanize_size(self, number): """Temporary wrapper to return a human readable bytesize""" try: return fcommon.humanize_size(number) except Exception: logger.debug( 'fcommon.humanize_size: Failed to translate sizes', exc_info=True ) return number
def get_file_handler(self, method, filename, size=None, progress=None, download_rate=None): filename = filename.rsplit('/', 1)[-1] if progress is not None: self.progress = (progress * self._baseprogress) / 100 if self.progress == 0: self.progress = 1 self.details = '%s<br />%s(%d%%)%s' % ( filename, '%s ' % humanize_size(size) if size else '', progress, ' %s/s' % humanize_size(download_rate) if download_rate else '', ) self.dump()
def __init__(self, *args, **kwargs): super(DeviceForm, self).__init__(*args, **kwargs) self.fields['dtype'].widget.attrs['onChange'] = ( "deviceTypeToggle();" ) self.fields['VNC_bind'].choices = self.ipv4_list() diskchoices = {} _n = notifier() used_zvol = [] for volume in Volume.objects.filter(): zvols = _n.list_zfs_vols(volume.vol_name, sort='name') for zvol, attrs in zvols.items(): if "zvol/" + zvol not in used_zvol: diskchoices["zvol/" + zvol] = "%s (%s)" % ( zvol, humanize_size(attrs['volsize'])) self.fields['DISK_zvol'].choices = diskchoices.items() if self.instance.id: if self.instance.dtype == 'CDROM': self.fields['CDROM_path'].initial = self.instance.attributes.get('path', '') elif self.instance.dtype == 'DISK': self.fields['DISK_zvol'].initial = self.instance.attributes.get('path', '').replace('/dev/', '') self.fields['DISK_mode'].initial = self.instance.attributes.get('type') self.fields['DISK_sectorsize'].initial = self.instance.attributes.get('sectorsize', 0) elif self.instance.dtype == 'RAW': self.fields['DISK_raw'].initial = self.instance.attributes.get('path', '') self.fields['DISK_mode'].initial = self.instance.attributes.get('type') self.fields['DISK_sectorsize'].initial = self.instance.attributes.get('sectorsize', 0) if self.instance.vm.vm_type == 'Container Provider': self.fields['DISK_raw_boot'].widget = forms.CheckboxInput() self.fields['DISK_raw_size'].widget = forms.TextInput() self.fields['ROOT_password'].widget = forms.PasswordInput(render_value=True,) self.fields['DISK_raw_boot'].initial = self.instance.attributes.get('boot', False) self.fields['DISK_raw_size'].initial = self.instance.attributes.get('size', '') self.fields['ROOT_password'].initial = self.instance.attributes.get('rootpwd', '') elif self.instance.dtype == 'NIC': self.fields['NIC_type'].initial = self.instance.attributes.get('type') self.fields['NIC_mac'].initial = self.instance.attributes.get('mac') self.fields['NIC_attach'].initial = self.instance.attributes.get('nic_attach') elif self.instance.dtype == 'VNC': vnc_port = self.instance.attributes.get('vnc_port') vnc_port = 0 if vnc_port is None else vnc_port self.fields['VNC_wait'].initial = self.instance.attributes.get('wait') self.fields['VNC_port'].initial = vnc_port self.fields['VNC_resolution'].initial = self.instance.attributes.get('vnc_resolution') self.fields['VNC_bind'].initial = self.instance.attributes.get('vnc_bind') self.fields['VNC_password'].initial = self.instance.attributes.get('vnc_password') self.fields['VNC_web'].initial = self.instance.attributes.get('vnc_web')
def __init__(self, *args, **kwargs): super(DeviceForm, self).__init__(*args, **kwargs) self.fields['dtype'].widget.attrs['onChange'] = ("deviceTypeToggle();") self.fields['VNC_bind'].choices = self.ipv4_list() diskchoices = {} _n = notifier() used_zvol = [] for volume in Volume.objects.filter(): zvols = _n.list_zfs_vols(volume.vol_name, sort='name') for zvol, attrs in zvols.items(): if "zvol/" + zvol not in used_zvol: diskchoices["zvol/" + zvol] = "%s (%s)" % ( zvol, humanize_size(attrs['volsize'])) self.fields['DISK_zvol'].choices = diskchoices.items() if self.instance.id: if self.instance.dtype == 'CDROM': self.fields[ 'CDROM_path'].initial = self.instance.attributes.get( 'path', '') elif self.instance.dtype == 'DISK': self.fields[ 'DISK_zvol'].initial = self.instance.attributes.get( 'path', '').replace('/dev/', '') self.fields[ 'DISK_mode'].initial = self.instance.attributes.get('type') elif self.instance.dtype == "RAW": self.fields['DISK_raw'].initial = self.instance.attributes.get( 'path', '') self.fields[ 'DISK_mode'].initial = self.instance.attributes.get('type') elif self.instance.dtype == 'NIC': self.fields['NIC_type'].initial = self.instance.attributes.get( 'type') self.fields['NIC_mac'].initial = self.instance.attributes.get( 'mac') self.fields[ 'NIC_attach'].initial = self.instance.attributes.get( 'nic_attach') elif self.instance.dtype == 'VNC': vnc_port = self.instance.attributes.get('vnc_port') vnc_port = 0 if vnc_port is None else vnc_port self.fields['VNC_wait'].initial = self.instance.attributes.get( 'wait') self.fields['VNC_port'].initial = vnc_port self.fields[ 'VNC_resolution'].initial = self.instance.attributes.get( 'vnc_resolution') self.fields['VNC_bind'].initial = self.instance.attributes.get( 'vnc_bind')
def __init__(self, *args, **kwargs): super(DeviceForm, self).__init__(*args, **kwargs) self.fields['dtype'].widget.attrs['onChange'] = ( "deviceTypeToggle();" ) self.fields['VNC_bind'].choices = self.ipv4_list() self.fields['NIC_attach'].choices = choices.NICChoices( exclude_configured=False, include_vlan_parent=True, include_lagg_parent=False, ) diskchoices = {} with client as c: for zvol in c.call('pool.dataset.query', [('type', '=', 'VOLUME')]): diskchoices[f'zvol/{zvol["name"]}'] = "%s (%s)" % ( zvol['name'], humanize_size(zvol['volsize']['parsed']) ) self.fields['DISK_zvol'].choices = diskchoices.items() if self.instance.id: if self.instance.dtype == 'CDROM': self.fields['CDROM_path'].initial = self.instance.attributes.get('path', '') elif self.instance.dtype == 'DISK': self.fields['DISK_zvol'].initial = self.instance.attributes.get('path', '').replace('/dev/', '') self.fields['DISK_mode'].initial = self.instance.attributes.get('type') self.fields['DISK_sectorsize'].initial = self.instance.attributes.get('sectorsize', 0) elif self.instance.dtype == 'RAW': self.fields['DISK_raw'].initial = self.instance.attributes.get('path', '') self.fields['DISK_mode'].initial = self.instance.attributes.get('type') self.fields['DISK_sectorsize'].initial = self.instance.attributes.get('sectorsize', 0) self.fields['DISK_raw_boot'].widget = forms.CheckboxInput() self.fields['DISK_raw_size'].widget = forms.TextInput() self.fields['DISK_raw_boot'].initial = self.instance.attributes.get('boot', False) self.fields['DISK_raw_size'].initial = self.instance.attributes.get('size', '') elif self.instance.dtype == 'NIC': self.fields['NIC_type'].initial = self.instance.attributes.get('type') self.fields['NIC_mac'].initial = self.instance.attributes.get('mac') self.fields['NIC_attach'].initial = self.instance.attributes.get('nic_attach') elif self.instance.dtype == 'VNC': vnc_port = self.instance.attributes.get('vnc_port') vnc_port = 0 if vnc_port is None else vnc_port self.fields['VNC_wait'].initial = self.instance.attributes.get('wait') self.fields['VNC_port'].initial = vnc_port self.fields['VNC_resolution'].initial = self.instance.attributes.get('vnc_resolution') self.fields['VNC_bind'].initial = self.instance.attributes.get('vnc_bind') self.fields['VNC_password'].initial = self.instance.attributes.get('vnc_password') self.fields['VNC_web'].initial = self.instance.attributes.get('vnc_web')
def volume_detach(request, vid): volume = models.Volume.objects.get(pk=vid) usedbytes = sum( [mp._get_used_bytes() for mp in volume.mountpoint_set.all()]) usedsize = humanize_size(usedbytes) services = volume.has_attachments() if volume.vol_encrypt > 0: request.session["allow_gelikey"] = True if request.method == "POST": form = forms.VolumeExport(request.POST, instance=volume, services=services) if form.is_valid(): try: volume.delete(destroy=form.cleaned_data['mark_new'], cascade=form.cleaned_data.get('cascade', True)) return JsonResp( request, message=_("The volume has been successfully detached")) except ServiceFailed, e: return JsonResp(request, error=True, message=unicode(e))
def volume_detach(request, vid): volume = models.Volume.objects.get(pk=vid) usedbytes = volume._get_used_bytes() usedsize = humanize_size(usedbytes) if usedbytes else None services = { key: val for key, val in list(volume.has_attachments().items()) if len(val) > 0 } if volume.vol_encrypt > 0: request.session["allow_gelikey"] = True if request.method == "POST": form = forms.VolumeExport( request.POST, instance=volume, services=services) if form.is_valid(): try: events = [] volume.delete( destroy=form.cleaned_data['mark_new'], cascade=form.cleaned_data.get('cascade', True)) form.done(request, events) return JsonResp( request, message=_("The volume has been successfully detached"), events=events, ) except ServiceFailed as e: return JsonResp(request, error=True, message=str(e)) else: form = forms.VolumeExport(instance=volume, services=services) return render(request, 'storage/volume_detach.html', { 'volume': volume, 'form': form, 'used': usedsize, 'services': services, })
def __init__(self, *args, **kwargs): super(DeviceForm, self).__init__(*args, **kwargs) self.fields['dtype'].widget.attrs['onChange'] = ("deviceTypeToggle();") self.fields['VNC_bind'].choices = self.ipv4_list() diskchoices = {} _n = notifier() used_zvol = [] for volume in Volume.objects.filter(): zvols = _n.list_zfs_vols(volume.vol_name, sort='name') for zvol, attrs in zvols.items(): if "zvol/" + zvol not in used_zvol: diskchoices["zvol/" + zvol] = "%s (%s)" % ( zvol, humanize_size(attrs['volsize'])) self.fields['DISK_zvol'].choices = diskchoices.items() if self.instance.id: if self.instance.dtype == 'CDROM': self.fields[ 'CDROM_path'].initial = self.instance.attributes.get( 'path', '') elif self.instance.dtype == 'DISK': self.fields[ 'DISK_zvol'].initial = self.instance.attributes.get( 'path', '').replace('/dev/', '') self.fields[ 'DISK_mode'].initial = self.instance.attributes.get('type') self.fields[ 'DISK_sectorsize'].initial = self.instance.attributes.get( 'sectorsize', 0) elif self.instance.dtype == 'RAW': self.fields['DISK_raw'].initial = self.instance.attributes.get( 'path', '') self.fields[ 'DISK_mode'].initial = self.instance.attributes.get('type') self.fields[ 'DISK_sectorsize'].initial = self.instance.attributes.get( 'sectorsize', 0) if self.instance.vm.vm_type == 'Container Provider': self.fields['DISK_raw_boot'].widget = forms.CheckboxInput() self.fields['DISK_raw_size'].widget = forms.TextInput() self.fields['ROOT_password'].widget = forms.PasswordInput( render_value=True, ) self.fields[ 'DISK_raw_boot'].initial = self.instance.attributes.get( 'boot', False) self.fields[ 'DISK_raw_size'].initial = self.instance.attributes.get( 'size', '') self.fields[ 'ROOT_password'].initial = self.instance.attributes.get( 'rootpwd', '') elif self.instance.dtype == 'NIC': self.fields['NIC_type'].initial = self.instance.attributes.get( 'type') self.fields['NIC_mac'].initial = self.instance.attributes.get( 'mac') self.fields[ 'NIC_attach'].initial = self.instance.attributes.get( 'nic_attach') elif self.instance.dtype == 'VNC': vnc_port = self.instance.attributes.get('vnc_port') vnc_port = 0 if vnc_port is None else vnc_port self.fields['VNC_wait'].initial = self.instance.attributes.get( 'wait') self.fields['VNC_port'].initial = vnc_port self.fields[ 'VNC_resolution'].initial = self.instance.attributes.get( 'vnc_resolution') self.fields['VNC_bind'].initial = self.instance.attributes.get( 'vnc_bind') self.fields[ 'VNC_password'].initial = self.instance.attributes.get( 'vnc_password') self.fields['VNC_web'].initial = self.instance.attributes.get( 'vnc_web')
def _get_used_si(self): try: usedbytes = self._get_used_bytes() return u"%s" % (humanize_size(usedbytes)) except: return _(u"Error getting used space")
def _get_avail_si(self): try: availbytes = self._vfs.f_bavail * self._vfs.f_frsize return u"%s" % (humanize_size(availbytes)) except: return _(u"Error getting available space")
def _get_total_si(self): try: totalbytes = self._vfs.f_blocks * self._vfs.f_frsize return u"%s" % (humanize_size(totalbytes)) except: return _(u"Error getting total space")
def do_humanize_size(value): return humanize_size(value)
def __init__(self, *args, **kwargs): super(DeviceForm, self).__init__(*args, **kwargs) self.fields['dtype'].widget.attrs['onChange'] = ("deviceTypeToggle();") self.fields['VNC_bind'].choices = self.ipv4_list() self.fields['NIC_attach'].choices = choices.NICChoices( exclude_configured=False, include_vlan_parent=True, include_lagg_parent=False, ) diskchoices = {} with client as c: for zvol in c.call('pool.dataset.query', [('type', '=', 'VOLUME')]): diskchoices[f'zvol/{zvol["name"]}'] = "%s (%s)" % ( zvol['name'], humanize_size(zvol['volsize']['parsed'])) self.fields['DISK_zvol'].choices = diskchoices.items() if self.instance.id: if self.instance.dtype == 'CDROM': self.fields[ 'CDROM_path'].initial = self.instance.attributes.get( 'path', '') elif self.instance.dtype == 'DISK': self.fields[ 'DISK_zvol'].initial = self.instance.attributes.get( 'path', '').replace('/dev/', '') self.fields[ 'DISK_mode'].initial = self.instance.attributes.get('type') self.fields[ 'DISK_sectorsize'].initial = self.instance.attributes.get( 'sectorsize', 0) elif self.instance.dtype == 'RAW': self.fields['DISK_raw'].initial = self.instance.attributes.get( 'path', '') self.fields[ 'DISK_mode'].initial = self.instance.attributes.get('type') self.fields[ 'DISK_sectorsize'].initial = self.instance.attributes.get( 'sectorsize', 0) if self.instance.vm.vm_type == 'Container Provider': self.fields['DISK_raw_boot'].widget = forms.CheckboxInput() self.fields['DISK_raw_size'].widget = forms.TextInput() self.fields['ROOT_password'].widget = forms.PasswordInput( render_value=True, ) self.fields[ 'DISK_raw_boot'].initial = self.instance.attributes.get( 'boot', False) self.fields[ 'DISK_raw_size'].initial = self.instance.attributes.get( 'size', '') self.fields[ 'ROOT_password'].initial = self.instance.attributes.get( 'rootpwd', '') elif self.instance.dtype == 'NIC': self.fields['NIC_type'].initial = self.instance.attributes.get( 'type') self.fields['NIC_mac'].initial = self.instance.attributes.get( 'mac') self.fields[ 'NIC_attach'].initial = self.instance.attributes.get( 'nic_attach') elif self.instance.dtype == 'VNC': vnc_port = self.instance.attributes.get('vnc_port') vnc_port = 0 if vnc_port is None else vnc_port self.fields['VNC_wait'].initial = self.instance.attributes.get( 'wait') self.fields['VNC_port'].initial = vnc_port self.fields[ 'VNC_resolution'].initial = self.instance.attributes.get( 'vnc_resolution') self.fields['VNC_bind'].initial = self.instance.attributes.get( 'vnc_bind') self.fields[ 'VNC_password'].initial = self.instance.attributes.get( 'vnc_password') self.fields['VNC_web'].initial = self.instance.attributes.get( 'vnc_web')
def reconstruct_zfs_volume(self, name, volume): print('Attempting to reconstruct volume {}:'.format(name)) vol = Volume.objects.get(vol_guid=volume['guid']) if vol is None: print( ' Volume not found in database - volumes.json and database not in sync' ) return False # 1. Check if we already imported that volume if vol.status not in ('UNKNOWN', 'LOCKED'): print ' Pool already imported and online' return True # 2. Try to recreate pool grps = {} for catname in ('data', 'cache', 'spares', 'logs'): groups = volume['{}-vdevs'.format(catname)] for group in groups: print(' Group: {}'.format(group['name'])) grp = {'type': group['type'], 'disks': []} for vdev in group['disks']: sys.stdout.write('\t{} [{}]: '.format( vdev['name'], humanize_size(vdev['size']))) disk, match = self.guess_disk(vdev) if disk is None: print('not found') print( ' Reconstruction of volume {} aborted due to lack of matching device' .format(name)) return False print('found {} [{} match]'.format(disk, match)) self.used_disks.append(disk) self.notifier.unlabel_disk(disk) grp['disks'].append(disk) grps[group['name']] = grp self.notifier.init('volume', vol, groups=grps) # 3. Recreate datasets print(' Recreating datasets:') for dset in volume['datasets']: print('\t{}'.format(dset['name'])) self.notifier.create_zfs_dataset( dset['name'], {'mountpoint': dset['mountpoint']}, _restart_collectd=False) # 4. Recreate zvols if len(volume['zvols']) > 0: print(' Recreating zvols:') for zvol in volume['zvols']: print('\t{} [{}]'.format(zvol['name'], humanize_size(zvol['size']))) self.notifier.create_zfs_vol(zvol['name'], zvol['size']) return True