/puppet-mdadm

Puppet module for managing md raid arrays

Primary LanguageRubyMIT LicenseMIT

Puppet Mdadm Module

Puppet module for managing md raid arrays.

Build Status

Usage

Include with default parameters:

include mdadm

Include with the singleton pattern:

class { '::mdadm' : }

If you don't want the mdadm monitor running you can either ensure that it is stopped:

class { '::mdadm' :
  service_ensure => 'stopped',
}

or you can just leave the service unmanaged and stop it through some other means:

class { '::mdadm' :
  service_managed => false,
}

Md Arrays

The custom type mdadm is available for creating, assembling or stopping raid arrays. The name or title should be the raid device name. Required values are an array of underlying devices, and the raid level. All other parameters are optional.

The available parameters are the following:

Parameters

See puppet doc

Creating an array

From scratch, you can create a striped array of two underlying devices with the following:

mdadm { '/dev/md1' :
  ensure    => 'created',
  devices   => ['/dev/sdb', '/dev/sdc'],
  level     => 0,
}

If one or both of the two devices were previously members of an array, (mdadm discovered superblock information on them), then the above would fail.

If you are sure that you want to recreate the array, you can force the creation of it by passing force => true.

mdadm { '/dev/md1' :
  ensure    => 'created',
  devices   => ['/dev/sdb', '/dev/sdc'],
  level     => 0,
  force     => true,
}

If all underlying devices were members of the same array, this is not a destructive action. However, if they were members of different arrays you WILL LOSE DATA.

A more conservative approach would be to attempt to assemble the array first. This way if they were previously members of the same array, then the assembly will proceed, otherwise it will fail.

Assembling an array

mdadm { '/dev/md1' :
  ensure    => 'assembled',
  devices   => ['/dev/sdb', '/dev/sdc'],
  level     => 0,
}

Stopping an array

This will stop the array but is not destructive. You can reassemble the array later with the same devices.

mdadm { '/dev/md1' :
  ensure    => 'stopped', # absent is a synomym
  devices   => ['/dev/sdb', '/dev/sdc'],
  level     => 0,
}

Metadata

You can specify the metadata superblock type by passing the metadata parameter. See mdadm(8) for more info. The default is v0.9. It only makes sense for the create operation.

mdadm { '/dev/md1' :
  ensure    => 'created',
  devices   => ['/dev/sdb', '/dev/sdc'],
  level     => 0,
  metadata  => '0.9',
}

Generating the conf

By default, the mdadm type will generate the mdadm.conf file. This is so that the device can be mounted at boot. If you don't want this to happen or you wish to manage the file yourself, you can pass generate_conf => false.

mdadm { '/dev/md1' :
  ensure        => 'assembled',
  devices       => ['/dev/sdb', '/dev/sdc'],
  level         => 0,
  generate_conf => false,
}

Updating ramfs

By default, the mdadm type will update initrd with the update-initramfs -u command. The reason for this is to allow devices created by md to be seen by the kernel at boot to allow for devices to be mounted as the root device if desired. It also seems to fix an issue seen in more recent kernels/mdadm. What happens is you create an md device of say /dev/md1, you don't update initrd, the kernel on boot sees that certain devices are members of an array but doesn't know the array name (/dev/md1) and so it assigns an arbitrary name, /dev/md126, and starts the array. This can cause entries in /etc/fstab to not be found, causing mount on boot problems.

The solution is to just update initrd with the devices created by md, so this option defaults to true.

You can disable by passing update_initramfs => false.

mdadm { '/dev/md1' :
  ensure           => 'assembled',
  devices          => ['/dev/sdb', '/dev/sdc'],
  level            => 0,
  update_initramfs => false,
}

Defined Type mdadm::array

Because the mdadm provider relies upon the mdadm command to be present on the system and while the mdadm type autorequires the mdadm package, there is no way to ensure that the package gets installed.

The mdadm::array is a simple wrapper that includes the mdadm class to ensure the mdadm package is installed. It doesn't do any parameter validation, it just passes the parameters to the mdadm type.

So if you don't want to have to do this:

# Ensure mdadm is present
include mdadm

# Create array
mdadm { '/dev/md1':
  ensure  => 'created',
  devices => ['/dev/sdb', '/dev/sdc'],
  level   => 0,
}

Instead you can just use the wrapper:

mdadm::array { '/dev/md1':
  ensure  => 'created',
  devices => ['/dev/sdb', '/dev/sdc'],
  level   => 0,
}

Functions

check_devices()

This function can be used to check whether a given device exists. You pass it an array of devices, it expects them to start with '/dev/' and a string of comma separated devices on the system, specifically the $blockdevices fact. Returns true if all devices exist and false otherwise.

$result = check_devices(['/dev/sdb', '/dev/sdc'], $::blockdevices)

if $result {
  ...do something
}

This is useful if you are booting a system but your blockdevices aren't available at boot and you still want to have the mdadm::array configured in puppet. The mdadm type will error out if the devices aren't available so this function allows you to pass on applying that resource until the blockdevices become available.

Limitations

Resizing Raid Arrays

The mdadm type is pretty basic, it will not attempt to manage a device once it is created other than to stop the array. You cannot add spares to the array by appending additional devices to the devices parameter. Nor will it remove devices from a raid array when they are removed from the devices parameter.

Filesystem Creation

Currently the mdadm type does not create a filesystem on a raid array. If you are looking to setup a raided mountpoint using this type and the puppet mount type you will need to create the filesystem for any new arrays. Assembled arrays should already have a filesystem.

If you want something a bit more robust than your own exec, check out the filesystem type in the excellent PuppetLabs LVM module

For example, this would be a complete setup:

mdadm { '/dev/md1' :
  ensure  => 'created',
  devices => ['/dev/sdb', '/dev/sdc'],
  level   => 0,
  before  => Filesystem['/dev/md1']
}

filesystem { '/dev/md1' :
  ensure  => 'present',
  fs_type => 'ext4',
  before  => Mount['/mnt']
}

mount { '/mnt' :
  ensure  => 'mounted',
  atboot  => true,
  device  => '/dev/md1',
  fstype  => 'ext4',
  options => 'defaults',
}

License

See LICENSE file.