Puppet Plan: powerstore::create_volume_attach_host_with_fs

Defined in:
plans/create_volume_attach_host_with_fs.pp

Summary

A Bolt Plan that creates a volume, maps that new volume to an existing host, scans that host's iSCSI bus to ensure device nodes have been created, computes the device name as viewed by the host, partitions the new disk device, puts new file system on partition, mounts fresh file system at designated location

Overview

Examples:

Create a volume of the name ‘db_backups` and mount it upon the host `backup1` with the size of 250GB

bolt plan run powerstore::create_volume_attach_host_with_fs --targets powerstore host=backup1 volume_name=db_backups $volume_size=268435456000

Parameters:

  • host_name (String)

    An host as defined within the Bolt inventory that will be have the new volume mapped to mounted on with file systems created

  • volume_name (String)

    Name for the new volume that will be created on the powerstore array

  • mount_point (String) (defaults to: "/mnt/${volume_name}")

    Override the default mount point of where the created volume will be mounted on the host once a file system has successfully been created

  • volume_size (Integer) (defaults to: 26843545600)

    Override the default size (25G) of the newly created volume

  • targets (TargetSpec)

See Also:



27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'plans/create_volume_attach_host_with_fs.pp', line 27

plan powerstore::create_volume_attach_host_with_fs(
  TargetSpec                $targets,
  String                    $host_name,
  String                    $volume_name,
  String                    $mount_point  = "/mnt/${volume_name}",
  Integer                   $volume_size  = 26843545600
) {

  # A very quick and dirty implementation that creates a volume on an array
  # attaches the new volume to a host, then on the host scans the SCSI bus
  # for new iSCSI devices, partitions the new device, creates XFS file system,
  # and then mounts the disk

  # Before we go anywhere, ensure we'll be able to complete iSCSI operations on
  # remote hosts
  $package_status = [ 'iscsi-initiator-utils', 'device-mapper-multipath' ].map |$package| {
    run_task('package', get_target($host_name), {
      'name' => $package,
      'action' => 'status',
    }).first.value['status']
  }

  if 'uninstalled' in $package_status {
    fail_plan('Packages iscsi-initiator-utils and device-mapper-multipath must be present on the system for this plan to function')
  }

  # Gets the id of the host we want to attach volumes to
  #
  run_task('powerstore::host_collection_query', $targets, {
    'query_string' => "select=name,id&name=eq.${host_name}"
  }).each |$target_result| {
    get_target($target_result.target).set_var('host_id', $target_result.value[$host_name]['id'])
  }

  # Re-use a plan that was used previously to create a fresh volume
  #
  run_plan('powerstore::create_volume', $targets, {
    'volume_name' => $volume_name,
    'size'        => $volume_size
  })

  # Now that volume is created, capture its id for the attach operation and wwn
  # for later use on host
  #
  run_task('powerstore::volume_collection_query', $targets, {
    'query_string' => "select=name,id,wwn&name=eq.${volume_name}"
  }).each |$target_result| {
    get_target($target_result.target).set_var('volume_id', $target_result.value[$volume_name]['id'])
    get_target($target_result.target).set_var('wwn', $target_result.value[$volume_name]['wwn'])
  }

  # For every array we just created a volume on, attach volume to host
  #
  get_targets($targets).each |$target| {
    run_task('powerstore::host_attach', $target, {
      'id'        => vars($target)['host_id'],
      'volume_id' => vars($target)['volume_id']
    })
  }

  # For every array log run the commands on our host that are needed to finish
  # bootstrapping the volume by creating it a mount point, ensure the device
  # has created device nodes for the disks, partition the disk, create a file
  # system, mount the disk, and finally print out `df` output to verify it
  # worked
  #
  get_targets($targets).each |$target| {
    run_command('rescan-scsi-bus.sh', get_target($host_name))

    # Seems to take a second or two for `/dev/disk/by-id` to be populated
    ctrl::sleep(3)

    $wwid   = "3${regsubst(vars($target)['wwn'], '^naa.(.*$)', '\1')}"
    $device = "/dev/disk/by-id/dm-uuid-mpath-${wwid}"
    $part   = "/dev/disk/by-id/dm-uuid-part1-mpath-${wwid}"

    $check = run_command("df -h ${part}", get_target($host_name), '_catch_errors' => true).first

    unless $check.ok {
      run_command("/usr/bin/mkdir -p ${mount_point}", get_target($host_name))

      run_command("/usr/sbin/parted ${device} mklabel gpt", get_target($host_name))
      run_command("parted -a optimal ${device} mkpart primary 0% 100%", get_target($host_name))

      run_command('rescan-scsi-bus.sh', get_target($host_name))

      ctrl::sleep(3)

      run_command("/usr/sbin/mkfs.xfs ${part}", get_target($host_name))

      run_command("/usr/bin/mount ${part} ${mount_point}", get_target($host_name))

      $df = run_command("df -h ${mount_point} | tail -1", get_target($host_name)).first.value['stdout']
      out::message($df)
    } else {
      out::message('Volume already mounted on host...skipping...')
    }
  }
}