diff --git a/REFERENCE.md b/REFERENCE.md index bf9c969..39de250 100644 --- a/REFERENCE.md +++ b/REFERENCE.md @@ -1,247 +1,249 @@ # Reference ## Resource types * [`zfs`](#zfs): Manage zfs. Create destroy and set properties on zfs instances. **Autorequires:** If Puppet is managing the zpool at the root of this zfs in * [`zpool`](#zpool): Manage zpools. Create and delete zpools. The provider WILL NOT SYNC, only report differences. Supports vdevs with mirrors, raidz, logs and s ## Resource types ### zfs Manage zfs. Create destroy and set properties on zfs instances. **Autorequires:** If Puppet is managing the zpool at the root of this zfs instance, the zfs resource will autorequire it. If Puppet is managing any parent zfs instances, the zfs resource will autorequire them. #### Examples ##### Using zfs. ```puppet zfs { 'tstpool': ensure => present, } ``` #### Properties The following properties are available in the `zfs` type. ##### `ensure` Valid values: present, absent The basic property that the resource should be in. Default value: present ##### `aclinherit` The aclinherit property. Valid values are `discard`, `noallow`, `restricted`, `passthrough`, `passthrough-x`. ##### `aclmode` The aclmode property. Valid values are `discard`, `groupmask`, `passthrough`. ##### `acltype` The acltype propery. Valid values are 'noacl' and 'posixacl'. Only supported on Linux. ##### `atime` The atime property. Valid values are `on`, `off`. ##### `canmount` The canmount property. Valid values are `on`, `off`, `noauto`. ##### `checksum` The checksum property. Valid values are `on`, `off`, `fletcher2`, `fletcher4`, `sha256`. ##### `compression` The compression property. Valid values are `on`, `off`, `lzjb`, `gzip`, `gzip-[1-9]`, `zle`. ##### `copies` The copies property. Valid values are `1`, `2`, `3`. ##### `dedup` The dedup property. Valid values are `on`, `off`. ##### `devices` The devices property. Valid values are `on`, `off`. ##### `exec` The exec property. Valid values are `on`, `off`. ##### `logbias` The logbias property. Valid values are `latency`, `throughput`. ##### `mountpoint` The mountpoint property. Valid values are ``, `legacy`, `none`. ##### `nbmand` The nbmand property. Valid values are `on`, `off`. ##### `primarycache` The primarycache property. Valid values are `all`, `none`, `metadata`. ##### `quota` The quota property. Valid values are ``, `none`. ##### `readonly` The readonly property. Valid values are `on`, `off`. ##### `recordsize` The recordsize property. Valid values are powers of two between 512 and 128k. ##### `refquota` The refquota property. Valid values are ``, `none`. ##### `refreservation` The refreservation property. Valid values are ``, `none`. ##### `reservation` The reservation property. Valid values are ``, `none`. ##### `secondarycache` The secondarycache property. Valid values are `all`, `none`, `metadata`. ##### `setuid` The setuid property. Valid values are `on`, `off`. ##### `shareiscsi` The shareiscsi property. Valid values are `on`, `off`, `type=`. ##### `sharenfs` The sharenfs property. Valid values are `on`, `off`, share(1M) options ##### `sharesmb` The sharesmb property. Valid values are `on`, `off`, sharemgr(1M) options ##### `snapdir` The snapdir property. Valid values are `hidden`, `visible`. ##### `version` The version property. Valid values are `1`, `2`, `3`, `4`, `current`. ##### `volsize` The volsize property. Valid values are `` ##### `vscan` The vscan property. Valid values are `on`, `off`. ##### `xattr` The xattr property. Valid values are `on`, `off`. ##### `zoned` The zoned property. Valid values are `on`, `off`. #### Parameters The following parameters are available in the `zfs` type. ##### `name` namevar The full name for this filesystem (including the zpool). ### zpool Manage zpools. Create and delete zpools. The provider WILL NOT SYNC, only report differences. Supports vdevs with mirrors, raidz, logs and spares. #### Examples ##### Using zpool. ```puppet zpool { 'tstpool': ensure => present, disk => '/ztstpool/dsk', } ``` #### Properties The following properties are available in the `zpool` type. ##### `ensure` Valid values: present, absent The basic property that the resource should be in. Default value: present ##### `disk` The disk(s) for this pool. Can be an array or a space separated string. +Use disk/device names as displayed by "zpool status". On Linux/ZOL, use +full device pathes as displayed by "zpool status -P". ##### `mirror` List of all the devices to mirror for this pool. Each mirror should be a space separated string: mirror => [\"disk1 disk2\", \"disk3 disk4\"], ##### `raidz` List of all the devices to raid for this pool. Should be an array of space separated strings: raidz => [\"disk1 disk2\", \"disk3 disk4\"], ##### `spare` Spare disk(s) for this pool. ##### `log` Log disks for this pool. This type does not currently support mirroring of log disks. #### Parameters The following parameters are available in the `zpool` type. ##### `pool` namevar The name for this pool. ##### `raid_parity` Determines parity when using the `raidz` parameter. diff --git a/lib/puppet/provider/zpool/zpool.rb b/lib/puppet/provider/zpool/zpool.rb index 8de7edb..3380530 100644 --- a/lib/puppet/provider/zpool/zpool.rb +++ b/lib/puppet/provider/zpool/zpool.rb @@ -1,131 +1,139 @@ Puppet::Type.type(:zpool).provide(:zpool) do desc 'Provider for zpool.' commands zpool: 'zpool' # NAME SIZE ALLOC FREE CAP HEALTH ALTROOT def self.instances zpool(:list, '-H').split("\n").map do |line| name, _size, _alloc, _free, _cap, _health, _altroot = line.split(%r{\s+}) new(name: name, ensure: :present) end end def process_zpool_data(pool_array) if pool_array == [] return Hash.new(:absent) end # get the name and get rid of it pool = {} pool[:pool] = pool_array[0] pool_array.shift tmp = [] # order matters here :( pool_array.reverse_each do |value| sym = nil case value when 'spares' sym = :spare when 'logs' sym = :log when %r{^mirror|^raidz1|^raidz2} sym = (value =~ %r{^mirror}) ? :mirror : :raidz pool[:raid_parity] = 'raidz2' if value =~ %r{^raidz2} else tmp << value sym = :disk if value == pool_array.first end if sym pool[sym] = (pool[sym]) ? pool[sym].unshift(tmp.reverse.join(' ')) : [tmp.reverse.join(' ')] tmp.clear end end pool end # rubocop:disable Style/AccessorMethodName # rubocop:disable Style/NumericPredicate def get_pool_data # https://docs.oracle.com/cd/E19082-01/817-2271/gbcve/index.html # we could also use zpool iostat -v mypool for a (little bit) cleaner output - out = execute("zpool status #{@resource[:pool]}", failonfail: false, combine: false) + zpool_opts = case Facter.value(:kernel) + # use full device names ("-P") on Linux/ZOL to prevent + # mismatches between creation and display paths: + when 'Linux' + '-P' + else + '' + end + out = execute("zpool status #{zpool_opts} #{@resource[:pool]}", failonfail: false, combine: false) zpool_data = out.lines.select { |line| line.index("\t") == 0 }.map { |l| l.strip.split("\s")[0] } zpool_data.shift zpool_data end def current_pool @current_pool = process_zpool_data(get_pool_data) unless defined?(@current_pool) && @current_pool @current_pool end def flush @current_pool = nil end # Adds log and spare def build_named(name) prop = @resource[name.to_sym] if prop [name] + prop.map { |p| p.split(' ') }.flatten else [] end end # query for parity and set the right string def raidzarity (@resource[:raid_parity]) ? @resource[:raid_parity] : 'raidz1' end # handle mirror or raid def handle_multi_arrays(prefix, array) array.map { |a| [prefix] + a.split(' ') }.flatten end # builds up the vdevs for create command def build_vdevs disk = @resource[:disk] mirror = @resource[:mirror] raidz = @resource[:raidz] if disk disk.map { |d| d.split(' ') }.flatten elsif mirror handle_multi_arrays('mirror', mirror) elsif raidz handle_multi_arrays(raidzarity, raidz) end end def create zpool(*([:create, @resource[:pool]] + build_vdevs + build_named('spare') + build_named('log'))) end def destroy zpool :destroy, @resource[:pool] end def exists? if current_pool[:pool] == :absent false else true end end [:disk, :mirror, :raidz, :log, :spare].each do |field| define_method(field) do current_pool[field] end # rubocop:disable Style/SignalException define_method(field.to_s + '=') do |should| fail "zpool #{field} can't be changed. should be #{should}, currently is #{current_pool[field]}" end end end