From 412ff53673c44fd75ac96363b0e353c1c65de64d Mon Sep 17 00:00:00 2001 From: Douglas Thrift Date: Mon, 26 Aug 2013 15:14:38 -0700 Subject: [PATCH 01/19] acu114901 - Bring in cookbook dependencies. --- Berksfile | 2 ++ metadata.rb | 2 ++ 2 files changed, 4 insertions(+) diff --git a/Berksfile b/Berksfile index c4bb297..e42fc66 100644 --- a/Berksfile +++ b/Berksfile @@ -1,3 +1,5 @@ site :opscode metadata + +cookbook "lvm", github: "arangamani-cookbooks/lvm", tag: "0.8.11" diff --git a/metadata.rb b/metadata.rb index 8a24d95..53c394a 100644 --- a/metadata.rb +++ b/metadata.rb @@ -6,3 +6,5 @@ long_description IO.read(File.join(File.dirname(__FILE__), 'README.md')) version IO.read(File.join(File.dirname(__FILE__), 'VERSION')) rescue '0.1.0' +depends 'xfs', '~> 1.1.0' +depends 'lvm' From 53f1f95716ab95a2c78b7defbb6b3e8a2b73817d Mon Sep 17 00:00:00 2001 From: Douglas Thrift Date: Tue, 3 Sep 2013 10:25:31 -0700 Subject: [PATCH 02/19] acu114901 - Checkpoint work on ephemeral_lvm so Kannan can take over. --- .kitchen.yml | 2 +- README.md | 2 +- Vagrantfile | 10 ++++++---- attributes/default.rb | 22 ++++++++++++++++++++++ metadata.rb | 4 ++-- recipes/default.rb | 9 ++++++++- 6 files changed, 40 insertions(+), 9 deletions(-) create mode 100644 attributes/default.rb diff --git a/.kitchen.yml b/.kitchen.yml index 7e6dddb..280af8f 100644 --- a/.kitchen.yml +++ b/.kitchen.yml @@ -15,5 +15,5 @@ platforms: suites: - name: default - run_list: ["recipe[ephemeral]"] + run_list: ["recipe[ephemeral_lvm]"] attributes: {} diff --git a/README.md b/README.md index fc5e8c5..293cd57 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# ephemeral cookbook +# ephemeral_lvm cookbook # Requirements diff --git a/Vagrantfile b/Vagrantfile index efc3138..6c2d8fa 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -6,14 +6,14 @@ Vagrant.configure("2") do |config| # options are documented and commented below. For a complete reference, # please see the online documentation at vagrantup.com. - config.vm.hostname = "ephemeral-berkshelf" + config.vm.hostname = "ephemeral-lvm-berkshelf" # Every Vagrant virtual environment requires a box to build off of. - config.vm.box = "RightImage_Ubuntu_12.04_x64_v13.5.0.1" + config.vm.box = "opscode-ubuntu-12.04" # The url from where the 'config.vm.box' box will be fetched if it # doesn't already exist on the user's system. - config.vm.box_url = "https://rightscale-vagrant.s3.amazonaws.com/virtualbox/ubuntu/12.04/RightImage_Ubuntu_12.04_x64_v13.5.0.1.box" + config.vm.box_url = "https://opscode-vm-bento.s3.amazonaws.com/vagrant/opscode_ubuntu-12.04_provisionerless.box" # Assign this VM to a host-only network IP, allowing you to access it # via the IP. Host-only networks can talk to the host machine as well as @@ -70,6 +70,8 @@ Vagrant.configure("2") do |config| # to skip installing and copying to Vagrant's shelf. # config.berkshelf.except = [] + config.omnibus.chef_version = :latest + config.vm.provision :chef_solo do |chef| chef.json = { :mysql => { @@ -80,7 +82,7 @@ Vagrant.configure("2") do |config| } chef.run_list = [ - "recipe[ephemeral::default]" + "recipe[ephemeral_lvm::default]" ] end end diff --git a/attributes/default.rb b/attributes/default.rb new file mode 100644 index 0000000..53e255e --- /dev/null +++ b/attributes/default.rb @@ -0,0 +1,22 @@ +# +# Cookbook Name:: ephemeral_lvm +# Attributes:: default +# +# Copyright (C) 2013 RightScale, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +default['ephemeral_lvm']['filesystem'] = "ext4" +default['ephemeral_lvm']['mount_point'] = "/mnt/ephemeral" +default['ephemeral_lvm']['logical_volume_size'] = "100%VG" diff --git a/metadata.rb b/metadata.rb index 53c394a..00acc33 100644 --- a/metadata.rb +++ b/metadata.rb @@ -1,8 +1,8 @@ -name 'ephemeral' +name 'ephemeral_lvm' maintainer 'RightScale, Inc.' maintainer_email 'cookbooks@rightscale.com' license 'Apache 2.0' -description 'Installs/Configures ephemeral' +description 'Installs/Configures ephemeral_lvm' long_description IO.read(File.join(File.dirname(__FILE__), 'README.md')) version IO.read(File.join(File.dirname(__FILE__), 'VERSION')) rescue '0.1.0' diff --git a/recipes/default.rb b/recipes/default.rb index 4bc4567..2c447a8 100644 --- a/recipes/default.rb +++ b/recipes/default.rb @@ -1,5 +1,5 @@ # -# Cookbook Name:: ephemeral +# Cookbook Name:: ephemeral_lvm # Recipe:: default # # Copyright (C) 2013 RightScale, Inc. @@ -16,3 +16,10 @@ # See the License for the specific language governing permissions and # limitations under the License. # + +if !node.attribute?('cloud') || !node['cloud'].attribute?('provider') + log "Not running on a known cloud, not setting up ephemeral LVM" +else + case node['cloud']['provider'] + end +end From 19071c8061e7a9abf3e019657ae4037d6058a842 Mon Sep 17 00:00:00 2001 From: Kannan Manickam Date: Wed, 4 Sep 2013 15:56:06 -0700 Subject: [PATCH 03/19] acu114901 - Initial implementation of ephemeral_lvm::default - It works inside vagrant --- .kitchen.yml | 27 ++++++++-- Berksfile | 3 +- attributes/default.rb | 13 +++-- recipes/default.rb | 51 +++++++++++++++++-- test/cookbooks/ephemeral_lvm-test/README.md | 19 +++++++ .../ephemeral_lvm-test/libraries/helper.rb | 51 +++++++++++++++++++ test/cookbooks/ephemeral_lvm-test/metadata.rb | 8 +++ .../ephemeral_lvm-test/recipes/prepare.rb | 31 +++++++++++ 8 files changed, 192 insertions(+), 11 deletions(-) create mode 100644 test/cookbooks/ephemeral_lvm-test/README.md create mode 100644 test/cookbooks/ephemeral_lvm-test/libraries/helper.rb create mode 100644 test/cookbooks/ephemeral_lvm-test/metadata.rb create mode 100644 test/cookbooks/ephemeral_lvm-test/recipes/prepare.rb diff --git a/.kitchen.yml b/.kitchen.yml index 280af8f..677be6c 100644 --- a/.kitchen.yml +++ b/.kitchen.yml @@ -1,7 +1,7 @@ --- driver_plugin: vagrant driver_config: - require_chef_omnibus: false + require_chef_omnibus: true platforms: - name: rightimage-ubuntu-12.04 @@ -12,8 +12,29 @@ platforms: driver_config: box: RightImage_CentOS_6.4_x64_v13.5.0.1 box_url: https://rightscale-vagrant.s3.amazonaws.com/virtualbox/centos/6.4/RightImage_CentOS_6.4_x64_v13.5.0.1.box +- name: ubuntu-12.04 + driver_config: + box: opscode-ubuntu-12.04 + box_url: https://opscode-vm-bento.s3.amazonaws.com/vagrant/opscode_ubuntu-12.04_provisionerless.box +- name: ubuntu-10.04 + driver_config: + box: opscode-ubuntu-10.04 + box_url: https://opscode-vm-bento.s3.amazonaws.com/vagrant/opscode_ubuntu-10.04_provisionerless.box +- name: centos-6.4 + driver_config: + box: opscode-centos-6.4 + box_url: https://opscode-vm-bento.s3.amazonaws.com/vagrant/opscode_centos-6.4_provisionerless.box +- name: centos-5.9 + driver_config: + box: opscode-centos-5.9 + box_url: https://opscode-vm-bento.s3.amazonaws.com/vagrant/opscode_centos-5.9_provisionerless.box suites: - name: default - run_list: ["recipe[ephemeral_lvm]"] - attributes: {} + run_list: ["recipe[ephemeral_lvm-test::prepare]", "recipe[ephemeral_lvm]"] + attributes: + cloud: + provider: vagrant + vagrant: + block_device_mapping_ephemeral0: loop0 + block_device_mapping_ephemeral1: loop1 diff --git a/Berksfile b/Berksfile index e42fc66..6e03d5a 100644 --- a/Berksfile +++ b/Berksfile @@ -2,4 +2,5 @@ site :opscode metadata -cookbook "lvm", github: "arangamani-cookbooks/lvm", tag: "0.8.11" +cookbook "lvm", github: "arangamani-cookbooks/lvm", tag: "0.8.11-rs" +cookbook "ephemeral_lvm-test", path: "./test/cookbooks/ephemeral_lvm-test", group: :integration diff --git a/attributes/default.rb b/attributes/default.rb index 53e255e..066c015 100644 --- a/attributes/default.rb +++ b/attributes/default.rb @@ -3,13 +3,13 @@ # Attributes:: default # # Copyright (C) 2013 RightScale, Inc. -# +# # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -17,6 +17,13 @@ # limitations under the License. # +# The ephemeral file system default['ephemeral_lvm']['filesystem'] = "ext4" +# The ephemeral mount point default['ephemeral_lvm']['mount_point'] = "/mnt/ephemeral" +# The ephemeral volume group name +default['ephemeral_lvm']['volume_group_name'] = "vg-data" +# The logical volume size of the ephemeral disk default['ephemeral_lvm']['logical_volume_size'] = "100%VG" +# The ephemeral logical volume name +default['ephemeral_lvm']['logical_volume_name'] = "lvol0" diff --git a/recipes/default.rb b/recipes/default.rb index 2c447a8..813ed72 100644 --- a/recipes/default.rb +++ b/recipes/default.rb @@ -3,13 +3,13 @@ # Recipe:: default # # Copyright (C) 2013 RightScale, Inc. -# +# # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -17,9 +17,52 @@ # limitations under the License. # +include_recipe "lvm" + +log "Cloud provider: #{node['cloud'].inspect}" if !node.attribute?('cloud') || !node['cloud'].attribute?('provider') log "Not running on a known cloud, not setting up ephemeral LVM" else - case node['cloud']['provider'] + ephemeral_devices = [] + cloud = node['cloud']['provider'] + # Detect the ephemeral disks available on the instance + # + # If the cloud plugin supports block device mapping on the node, obtain the + # information from the node for setting up block device + if node[cloud].keys.any? { |key| key.match(/block_device_mapping_ephemeral\d+/) } + ephemeral_devices = node[cloud].keys.collect do |key| + if key.match(/block_device_mapping_ephemeral\d+/) + node[cloud][key].match(/\/dev\//) ? node[cloud][key] : "/dev/#{node[cloud][key]}" + end + end + log "Ephemeral disks found for cloud '#{cloud}': #{ephemeral_devices.inspect}" + else + # Cloud specific ephemeral detection logic if the cloud doesn't support block_device_mapping + case cloud + when 'gce' + # TODO: Google specific stuff goes in here + else + log "Cloud '#{cloud}' doesn't have ephemeral disks or this cookbook doesn't support that cloud" + end + end + + if ephemeral_devices.empty? + log "No ephemeral disks found. Skipping setup." + else + # Create physical volumes for all ephemeral disks + ephemeral_devices.each do |device| + lvm_physical_volume device + end + + lvm_volume_group node['ephemeral_lvm']['volume_group_name'] do + physical_volumes ephemeral_devices + + logical_volume node['ephemeral_lvm']['logical_volume_name'] do + size node['ephemeral_lvm']['logical_volume_size'] + filesystem node['ephemeral_lvm']['filesystem'] + mount_point node['ephemeral_lvm']['mount_point'] + stripes ephemeral_devices.size if ephemeral_devices.size > 1 + end + end end end diff --git a/test/cookbooks/ephemeral_lvm-test/README.md b/test/cookbooks/ephemeral_lvm-test/README.md new file mode 100644 index 0000000..26f0f7e --- /dev/null +++ b/test/cookbooks/ephemeral_lvm-test/README.md @@ -0,0 +1,19 @@ +# ephemeral_lvm-test cookbook + +# Requirements +Requires the `ephemeral_lvm` cookbook. + +# Usage +This cookbook is only used to test the `ephemeral_lvm` cookbook. + +# Attributes +There are no attributes in this cookbook. + +# Recipes + +## prepare +This recipe prepares the server with some loop devices as ephemeral disks. + +# Author + +Author:: RightScale, Inc. () diff --git a/test/cookbooks/ephemeral_lvm-test/libraries/helper.rb b/test/cookbooks/ephemeral_lvm-test/libraries/helper.rb new file mode 100644 index 0000000..76856ab --- /dev/null +++ b/test/cookbooks/ephemeral_lvm-test/libraries/helper.rb @@ -0,0 +1,51 @@ +# +# Cookbook Name:: ephemeral_lvm-test +# Library:: helper +# +# Copyright (C) 2013 RightScale, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +module EphemeralLvmTest + module Helper + # Creates given loop devices + # + # @param devices [Array, String] the devices to create + # + # + def self.create_loop_devices(devices) + Array(devices).each do |device| + num = device.slice(/\d+/) + mk_vfile_cmd = "dd if=/dev/zero of=/vfile#{num} bs=1024 count=65536" + Mixlib::ShellOut.new(mk_vfile_cmd).run_command.error! + mk_loop_dev_cmd = "losetup #{device} /vfile#{num}" + Mixlib::ShellOut.new(mk_loop_dev_cmd).run_command.error! + end + end + + # Removes the given loop devices + # + # @param devices [Array, String] list of loop devices to remove + # + def self.remove_loop_devices(devices) + require 'fileutils' + Array(devices).each do |device| + Chef::Log.info "Removing loop device: #{device}" + num = device.slice(/\d+/) + Mixlib::ShellOut.new("losetup -d #{device}").run_command.error! + FileUtils.rm_rf("/vfile#{num}") + end + end + end +end diff --git a/test/cookbooks/ephemeral_lvm-test/metadata.rb b/test/cookbooks/ephemeral_lvm-test/metadata.rb new file mode 100644 index 0000000..9d30b58 --- /dev/null +++ b/test/cookbooks/ephemeral_lvm-test/metadata.rb @@ -0,0 +1,8 @@ +name 'ephemeral_lvm-test' +maintainer 'RightScale, Inc.' +maintainer_email 'cookbooks@rightscale.com' +license 'Apache 2.0' +description 'Installs/Configures ephemeral_lvm-test' +long_description IO.read(File.join(File.dirname(__FILE__), 'README.md')) +version '0.1.0' + diff --git a/test/cookbooks/ephemeral_lvm-test/recipes/prepare.rb b/test/cookbooks/ephemeral_lvm-test/recipes/prepare.rb new file mode 100644 index 0000000..00c56ea --- /dev/null +++ b/test/cookbooks/ephemeral_lvm-test/recipes/prepare.rb @@ -0,0 +1,31 @@ +# +# Cookbook Name:: ephemeral_lvm-test +# Recipe:: prepare +# +# Copyright (C) 2013 RightScale, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +if !node.attribute?('cloud') || !node['cloud'].attribute?('provider') + log "Not running on a known cloud, Skipping preparation." +else + cloud = node['cloud']['provider'] + ephemeral_devices = node[cloud].keys.collect do |key| + if key.match(/block_device_mapping_ephemeral\d+/) + node[cloud][key].match(/\/dev\//) ? node[cloud][key] : "/dev/#{node[cloud][key]}" + end + end + + EphemeralLvmTest::Helper.create_loop_devices(ephemeral_devices) +end From 6f3b611410849e1ce7b4765b454c82170bc78c9d Mon Sep 17 00:00:00 2001 From: Kannan Manickam Date: Wed, 4 Sep 2013 18:10:43 -0700 Subject: [PATCH 04/19] acu114901 - more updates * Added support for google * Added logic for giving the stripe size with multiple ephemeral disks --- attributes/default.rb | 2 ++ recipes/default.rb | 30 ++++++++++++++++++++++++++---- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/attributes/default.rb b/attributes/default.rb index 066c015..b624189 100644 --- a/attributes/default.rb +++ b/attributes/default.rb @@ -27,3 +27,5 @@ default['ephemeral_lvm']['logical_volume_size'] = "100%VG" # The ephemeral logical volume name default['ephemeral_lvm']['logical_volume_name'] = "lvol0" +# The stripe size in kilobytes to be used if more than one ephemeral disk is found +default['ephemeral_lvm']['stripe_size'] = 512 diff --git a/recipes/default.rb b/recipes/default.rb index 813ed72..02111cd 100644 --- a/recipes/default.rb +++ b/recipes/default.rb @@ -17,9 +17,10 @@ # limitations under the License. # +# Include the lvm::default recipe which sets up the resources/providers for lvm +# include_recipe "lvm" -log "Cloud provider: #{node['cloud'].inspect}" if !node.attribute?('cloud') || !node['cloud'].attribute?('provider') log "Not running on a known cloud, not setting up ephemeral LVM" else @@ -29,31 +30,49 @@ # # If the cloud plugin supports block device mapping on the node, obtain the # information from the node for setting up block device + # if node[cloud].keys.any? { |key| key.match(/block_device_mapping_ephemeral\d+/) } ephemeral_devices = node[cloud].keys.collect do |key| if key.match(/block_device_mapping_ephemeral\d+/) node[cloud][key].match(/\/dev\//) ? node[cloud][key] : "/dev/#{node[cloud][key]}" end end - log "Ephemeral disks found for cloud '#{cloud}': #{ephemeral_devices.inspect}" else # Cloud specific ephemeral detection logic if the cloud doesn't support block_device_mapping + # case cloud when 'gce' - # TODO: Google specific stuff goes in here + # According the GCE documentation, the instances have links for ephemeral disks as + # /dev/disk/by-id/google-ephemeral-disk-*. Refer + # https://developers.google.com/compute/docs/disks#scratchdisks for more information + # + ephemeral_devices = node[cloud]['attached_disks']['disks'].collect do |disk| + if disk['type'] == "EPHEMERAL" && disk['deviceName'].match(/ephemeral-disk-\d+/) + "/dev/disk/by-id/google-#{disk["deviceName"]}" + end + end else log "Cloud '#{cloud}' doesn't have ephemeral disks or this cookbook doesn't support that cloud" end end + # Remove nil elements from the ephemeral_devices array if any + ephemeral_devices.compact! + + if ephemeral_devices.empty? log "No ephemeral disks found. Skipping setup." else + log "Ephemeral disks found for cloud '#{cloud}': #{ephemeral_devices.inspect}" + # Create physical volumes for all ephemeral disks + # ephemeral_devices.each do |device| lvm_physical_volume device end + # Create the volume group and logical volume + # lvm_volume_group node['ephemeral_lvm']['volume_group_name'] do physical_volumes ephemeral_devices @@ -61,7 +80,10 @@ size node['ephemeral_lvm']['logical_volume_size'] filesystem node['ephemeral_lvm']['filesystem'] mount_point node['ephemeral_lvm']['mount_point'] - stripes ephemeral_devices.size if ephemeral_devices.size > 1 + if ephemeral_devices.size > 1 + stripes ephemeral_devices.size + stripe_size node['ephemeral_lvm']['stripe_size'] + end end end end From b4aa031c36ebb636ef10153f8b9e8bfff48b1081 Mon Sep 17 00:00:00 2001 From: Kannan Manickam Date: Thu, 5 Sep 2013 14:59:51 -0700 Subject: [PATCH 05/19] acu114901 - Added gce test and documented test suites --- .kitchen.yml | 42 +++++++++++++++---- .../ephemeral_lvm-test/attributes/default.rb | 21 ++++++++++ .../recipes/{prepare.rb => default.rb} | 15 +++---- .../ephemeral_lvm-test/recipes/gce.rb | 33 +++++++++++++++ 4 files changed, 92 insertions(+), 19 deletions(-) create mode 100644 test/cookbooks/ephemeral_lvm-test/attributes/default.rb rename test/cookbooks/ephemeral_lvm-test/recipes/{prepare.rb => default.rb} (64%) create mode 100644 test/cookbooks/ephemeral_lvm-test/recipes/gce.rb diff --git a/.kitchen.yml b/.kitchen.yml index 677be6c..b922637 100644 --- a/.kitchen.yml +++ b/.kitchen.yml @@ -4,14 +4,6 @@ driver_config: require_chef_omnibus: true platforms: -- name: rightimage-ubuntu-12.04 - driver_config: - box: RightImage_Ubuntu_12.04_x64_v13.5.0.1 - box_url: https://rightscale-vagrant.s3.amazonaws.com/virtualbox/ubuntu/12.04/RightImage_Ubuntu_12.04_x64_v13.5.0.1.box -- name: rightimage-centos-6.4 - driver_config: - box: RightImage_CentOS_6.4_x64_v13.5.0.1 - box_url: https://rightscale-vagrant.s3.amazonaws.com/virtualbox/centos/6.4/RightImage_CentOS_6.4_x64_v13.5.0.1.box - name: ubuntu-12.04 driver_config: box: opscode-ubuntu-12.04 @@ -30,11 +22,43 @@ platforms: box_url: https://opscode-vm-bento.s3.amazonaws.com/vagrant/opscode_centos-5.9_provisionerless.box suites: +# This test suite mimics the behavior of being in a cloud which supports block device mapping +# The loopback devices given in block_device_mapping_ephemeral should be included in +# the test/cookbooks/ephemeral_lvm-test cookbook's attributes so they get created while running +# the test. EC2 and openstack clouds follow this format. +# - name: default - run_list: ["recipe[ephemeral_lvm-test::prepare]", "recipe[ephemeral_lvm]"] + run_list: ["recipe[ephemeral_lvm-test]", "recipe[ephemeral_lvm]"] attributes: cloud: provider: vagrant vagrant: block_device_mapping_ephemeral0: loop0 block_device_mapping_ephemeral1: loop1 + +# This test mimics the behavior of being in a google compute engine. The ephemeral disks +# are mapped to /dev/disk/by-id/google-ephemeral-disk-. Loopback device matching the +# device index should be set in the test/cookbooks/ephemeral_lvm-test cookbook's attributes +# so they get created. For example, the following attributes will require the creation of +# loopback devices "/dev/loop0" and "/dev/loop1" +# +- name: gce + run_list: ["recipe[ephemeral_lvm-test::gce]", "recipe[ephemeral_lvm]"] + attributes: + cloud: + provider: gce + gce: + attached_disks: + disks: + - deviceName: boot + index: 0 + mode: READ_WRITE + type: EPHEMERAL + - deviceName: ephemeral-disk-0 + index: 1 + mode: READ_WRITE + type: EPHEMERAL + - deviceName: ephemeral-disk-1 + index: 2 + mode: READ_WRITE + type: EPHEMERAL diff --git a/test/cookbooks/ephemeral_lvm-test/attributes/default.rb b/test/cookbooks/ephemeral_lvm-test/attributes/default.rb new file mode 100644 index 0000000..a4d3655 --- /dev/null +++ b/test/cookbooks/ephemeral_lvm-test/attributes/default.rb @@ -0,0 +1,21 @@ +# +# Cookbook Name:: ephemeral_lvm-test +# Attributes:: default +# +# Copyright (C) 2013 RightScale, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# Ephemeral devices used for testing ephemeral_lvm cookbook +default['ephemeral_lvm-test']['devices'] = ["/dev/loop0", "/dev/loop1"] diff --git a/test/cookbooks/ephemeral_lvm-test/recipes/prepare.rb b/test/cookbooks/ephemeral_lvm-test/recipes/default.rb similarity index 64% rename from test/cookbooks/ephemeral_lvm-test/recipes/prepare.rb rename to test/cookbooks/ephemeral_lvm-test/recipes/default.rb index 00c56ea..f773a01 100644 --- a/test/cookbooks/ephemeral_lvm-test/recipes/prepare.rb +++ b/test/cookbooks/ephemeral_lvm-test/recipes/default.rb @@ -1,6 +1,6 @@ # # Cookbook Name:: ephemeral_lvm-test -# Recipe:: prepare +# Recipe:: default # # Copyright (C) 2013 RightScale, Inc. # @@ -17,15 +17,10 @@ # limitations under the License. # +# Create the loopback devices used for testing ephemeral_lvm +# if !node.attribute?('cloud') || !node['cloud'].attribute?('provider') - log "Not running on a known cloud, Skipping preparation." + log "Not running on a known cloud, Skipping test setup." else - cloud = node['cloud']['provider'] - ephemeral_devices = node[cloud].keys.collect do |key| - if key.match(/block_device_mapping_ephemeral\d+/) - node[cloud][key].match(/\/dev\//) ? node[cloud][key] : "/dev/#{node[cloud][key]}" - end - end - - EphemeralLvmTest::Helper.create_loop_devices(ephemeral_devices) + EphemeralLvmTest::Helper.create_loop_devices(node['ephemeral_lvm-test']['devices']) end diff --git a/test/cookbooks/ephemeral_lvm-test/recipes/gce.rb b/test/cookbooks/ephemeral_lvm-test/recipes/gce.rb new file mode 100644 index 0000000..c763f0c --- /dev/null +++ b/test/cookbooks/ephemeral_lvm-test/recipes/gce.rb @@ -0,0 +1,33 @@ +# +# Cookbook Name:: ephemeral_lvm-test +# Recipe:: gce +# +# Copyright (C) 2013 RightScale, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# Include the ephemeral_lvm-test::default recipe which sets up the loopback +# devices used in the test. +# +include_recipe "ephemeral_lvm-test" + +# Setup the links for ephemeral devices for google by id +# +node['ephemeral_lvm-test']['devices'].each do |device| + match = device.match(/\/dev\/loop(\d+)/) + device_index = match[1] unless match.nil? + link "/dev/disk/by-id/google-ephemeral-disk-#{device_index}" do + to device + end +end From f1649c161ab1e41436d1eb5078df4a7767624ce0 Mon Sep 17 00:00:00 2001 From: Kannan Manickam Date: Thu, 5 Sep 2013 18:03:29 -0700 Subject: [PATCH 06/19] acu114901 - added bats tests for verification --- .../ephemeral_lvm-test/recipes/gce.rb | 2 +- .../default/bats/verify_ephemeral.bats | 20 +++++++++++++++ .../gce/bats/verify_ephemeral.bats | 25 +++++++++++++++++++ 3 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 test/integration/default/bats/verify_ephemeral.bats create mode 100644 test/integration/gce/bats/verify_ephemeral.bats diff --git a/test/cookbooks/ephemeral_lvm-test/recipes/gce.rb b/test/cookbooks/ephemeral_lvm-test/recipes/gce.rb index c763f0c..6059786 100644 --- a/test/cookbooks/ephemeral_lvm-test/recipes/gce.rb +++ b/test/cookbooks/ephemeral_lvm-test/recipes/gce.rb @@ -26,7 +26,7 @@ # node['ephemeral_lvm-test']['devices'].each do |device| match = device.match(/\/dev\/loop(\d+)/) - device_index = match[1] unless match.nil? + match.nil? ? next : device_index = match[1] link "/dev/disk/by-id/google-ephemeral-disk-#{device_index}" do to device end diff --git a/test/integration/default/bats/verify_ephemeral.bats b/test/integration/default/bats/verify_ephemeral.bats new file mode 100644 index 0000000..d36ccc8 --- /dev/null +++ b/test/integration/default/bats/verify_ephemeral.bats @@ -0,0 +1,20 @@ +#/usr/bin/env bats + +@test "physical volumes are created for ephemeral devices" { + pvs | grep /dev/loop0 + pvs | grep /dev/loop1 +} + +@test "volume group is created for ephemeral devices" { + vgs | grep vg-data +} + +@test "logical volume is created for ephemeral devices on the correct volume group" { + lvs | grep vg-data | grep lvol0 +} + +@test "ephemeral logical volume is mounted to /mnt/ephemeral" { + mountpoint /mnt/ephemeral + mount | grep "/dev/mapper/vg--data-lvol0 on /mnt/ephemeral type ext4" + grep -P "/dev/mapper/vg--data-lvol0\s+/mnt/ephemeral\s+ext4" /etc/fstab +} diff --git a/test/integration/gce/bats/verify_ephemeral.bats b/test/integration/gce/bats/verify_ephemeral.bats new file mode 100644 index 0000000..337461f --- /dev/null +++ b/test/integration/gce/bats/verify_ephemeral.bats @@ -0,0 +1,25 @@ +#/usr/bin/env bats + +@test "google ephemeral disk by-id symbolic links exist" { + test -L /dev/disk/by-id/google-ephemeral-disk-0 + test -L /dev/disk/by-id/google-ephemeral-disk-1 +} + +@test "physical volumes are created for ephemeral devices" { + pvs | grep /dev/loop0 + pvs | grep /dev/loop1 +} + +@test "volume group is created for ephemeral devices" { + vgs | grep vg-data +} + +@test "logical volume is created for ephemeral devices on the correct volume group" { + lvs | grep vg-data | grep lvol0 +} + +@test "ephemeral logical volume is mounted to /mnt/ephemeral" { + mountpoint /mnt/ephemeral + mount | grep "/dev/mapper/vg--data-lvol0 on /mnt/ephemeral type ext4" + grep -P "/dev/mapper/vg--data-lvol0\s+/mnt/ephemeral\s+ext4" /etc/fstab +} From bcaa6924d092861c0a970971b2b262703f010b79 Mon Sep 17 00:00:00 2001 From: Kannan Manickam Date: Fri, 6 Sep 2013 14:43:41 -0700 Subject: [PATCH 07/19] acu114901 - support block_device mapping for xen hypervisors and minor updates --- .kitchen.yml | 4 +++ libraries/helper.rb | 30 +++++++++++++++++++ recipes/default.rb | 27 ++++++++++++----- .../default/bats/verify_ephemeral.bats | 8 +++-- .../gce/bats/verify_ephemeral.bats | 8 +++-- 5 files changed, 66 insertions(+), 11 deletions(-) create mode 100644 libraries/helper.rb diff --git a/.kitchen.yml b/.kitchen.yml index b922637..ea71715 100644 --- a/.kitchen.yml +++ b/.kitchen.yml @@ -32,6 +32,8 @@ suites: attributes: cloud: provider: vagrant + ephemeral_lvm: + filesystem: ext3 vagrant: block_device_mapping_ephemeral0: loop0 block_device_mapping_ephemeral1: loop1 @@ -47,6 +49,8 @@ suites: attributes: cloud: provider: gce + ephemeral_lvm: + filesystem: ext3 gce: attached_disks: disks: diff --git a/libraries/helper.rb b/libraries/helper.rb new file mode 100644 index 0000000..429cf4c --- /dev/null +++ b/libraries/helper.rb @@ -0,0 +1,30 @@ +# +# Cookbook Name:: ephemeral_lvm +# Library:: helper +# +# Copyright (C) 2013 RightScale, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +module EphemeralLvm + module Helper + def self.fix_device_mapping(devices, node_block_devices) + fixed_devices = devices.map do |device| + fixed_device = device.sub("/sd", "/xvd") + fixed_device if node_block_devices.include?(fixed_device.match(/\/dev\/([a-z]+)$/)[1]) + end + fixed_devices.compact + end + end +end diff --git a/recipes/default.rb b/recipes/default.rb index 02111cd..bac5004 100644 --- a/recipes/default.rb +++ b/recipes/default.rb @@ -26,7 +26,7 @@ else ephemeral_devices = [] cloud = node['cloud']['provider'] - # Detect the ephemeral disks available on the instance + # Detects the ephemeral disks available on the instance. # # If the cloud plugin supports block device mapping on the node, obtain the # information from the node for setting up block device @@ -37,6 +37,19 @@ node[cloud][key].match(/\/dev\//) ? node[cloud][key] : "/dev/#{node[cloud][key]}" end end + + # Removes nil elements from the ephemeral_devices array if any. + ephemeral_devices.compact! + + # Servers running on Xen hypervisor require the block device to be in /dev/xvdX instead of /dev/sdX + if node.attribute?('virtualization') && node['virtualization']['system'] == "xen" + Chef::Log.info "Mapping for devices: #{ephemeral_devices.inspect}" + ephemeral_devices = EphemeralLvm::Helper.fix_device_mapping( + ephemeral_devices, + node['block_device'].keys + ) + log "Ephemeral disks found for cloud '#{cloud}': #{ephemeral_devices.inspect}" + end else # Cloud specific ephemeral detection logic if the cloud doesn't support block_device_mapping # @@ -44,20 +57,20 @@ when 'gce' # According the GCE documentation, the instances have links for ephemeral disks as # /dev/disk/by-id/google-ephemeral-disk-*. Refer - # https://developers.google.com/compute/docs/disks#scratchdisks for more information + # https://developers.google.com/compute/docs/disks#scratchdisks for more information. # ephemeral_devices = node[cloud]['attached_disks']['disks'].collect do |disk| if disk['type'] == "EPHEMERAL" && disk['deviceName'].match(/ephemeral-disk-\d+/) "/dev/disk/by-id/google-#{disk["deviceName"]}" end end + # Removes nil elements from the ephemeral_devices array if any. + ephemeral_devices.compact! else log "Cloud '#{cloud}' doesn't have ephemeral disks or this cookbook doesn't support that cloud" end end - # Remove nil elements from the ephemeral_devices array if any - ephemeral_devices.compact! if ephemeral_devices.empty? @@ -65,13 +78,13 @@ else log "Ephemeral disks found for cloud '#{cloud}': #{ephemeral_devices.inspect}" - # Create physical volumes for all ephemeral disks - # + # Creates physical volumes for all ephemeral disks. ephemeral_devices.each do |device| lvm_physical_volume device end - # Create the volume group and logical volume + # Create the volume group and logical volume. If more than one ephemeral disks are found, + # they are created with LVM stripes with the stripe size set in the attributes. # lvm_volume_group node['ephemeral_lvm']['volume_group_name'] do physical_volumes ephemeral_devices diff --git a/test/integration/default/bats/verify_ephemeral.bats b/test/integration/default/bats/verify_ephemeral.bats index d36ccc8..defaea7 100644 --- a/test/integration/default/bats/verify_ephemeral.bats +++ b/test/integration/default/bats/verify_ephemeral.bats @@ -1,5 +1,9 @@ #/usr/bin/env bats +# On CentOS 5.9, most of the commands used here are not in PATH. So add them +# here. +export PATH=$PATH:/sbin:/usr/sbin + @test "physical volumes are created for ephemeral devices" { pvs | grep /dev/loop0 pvs | grep /dev/loop1 @@ -15,6 +19,6 @@ @test "ephemeral logical volume is mounted to /mnt/ephemeral" { mountpoint /mnt/ephemeral - mount | grep "/dev/mapper/vg--data-lvol0 on /mnt/ephemeral type ext4" - grep -P "/dev/mapper/vg--data-lvol0\s+/mnt/ephemeral\s+ext4" /etc/fstab + mount | grep "/dev/mapper/vg--data-lvol0 on /mnt/ephemeral type ext3" + grep -P "/dev/mapper/vg--data-lvol0\s+/mnt/ephemeral\s+ext3" /etc/fstab } diff --git a/test/integration/gce/bats/verify_ephemeral.bats b/test/integration/gce/bats/verify_ephemeral.bats index 337461f..396fccd 100644 --- a/test/integration/gce/bats/verify_ephemeral.bats +++ b/test/integration/gce/bats/verify_ephemeral.bats @@ -1,5 +1,9 @@ #/usr/bin/env bats +# On CentOS 5.9, most of the commands used here are not in PATH. So add them +# here. +export PATH=$PATH:/sbin:/usr/sbin + @test "google ephemeral disk by-id symbolic links exist" { test -L /dev/disk/by-id/google-ephemeral-disk-0 test -L /dev/disk/by-id/google-ephemeral-disk-1 @@ -20,6 +24,6 @@ @test "ephemeral logical volume is mounted to /mnt/ephemeral" { mountpoint /mnt/ephemeral - mount | grep "/dev/mapper/vg--data-lvol0 on /mnt/ephemeral type ext4" - grep -P "/dev/mapper/vg--data-lvol0\s+/mnt/ephemeral\s+ext4" /etc/fstab + mount | grep "/dev/mapper/vg--data-lvol0 on /mnt/ephemeral type ext3" + grep -P "/dev/mapper/vg--data-lvol0\s+/mnt/ephemeral\s+ext3" /etc/fstab } From 2c336bb634e4bd8a709ed7b13fe9c75789bd9b4a Mon Sep 17 00:00:00 2001 From: Kannan Manickam Date: Wed, 11 Sep 2013 18:14:52 -0700 Subject: [PATCH 08/19] Updated Berksfile and added tests for checking striping --- Berksfile | 2 +- recipes/default.rb | 5 ----- test/integration/default/bats/verify_ephemeral.bats | 8 ++++++++ test/integration/gce/bats/verify_ephemeral.bats | 9 +++++++++ 4 files changed, 18 insertions(+), 6 deletions(-) diff --git a/Berksfile b/Berksfile index 6e03d5a..0577558 100644 --- a/Berksfile +++ b/Berksfile @@ -2,5 +2,5 @@ site :opscode metadata -cookbook "lvm", github: "arangamani-cookbooks/lvm", tag: "0.8.11-rs" +cookbook "lvm", github: "arangamani-cookbooks/lvm", tag: "0.8.13-rs" cookbook "ephemeral_lvm-test", path: "./test/cookbooks/ephemeral_lvm-test", group: :integration diff --git a/recipes/default.rb b/recipes/default.rb index bac5004..ac92722 100644 --- a/recipes/default.rb +++ b/recipes/default.rb @@ -78,11 +78,6 @@ else log "Ephemeral disks found for cloud '#{cloud}': #{ephemeral_devices.inspect}" - # Creates physical volumes for all ephemeral disks. - ephemeral_devices.each do |device| - lvm_physical_volume device - end - # Create the volume group and logical volume. If more than one ephemeral disks are found, # they are created with LVM stripes with the stripe size set in the attributes. # diff --git a/test/integration/default/bats/verify_ephemeral.bats b/test/integration/default/bats/verify_ephemeral.bats index defaea7..507b58b 100644 --- a/test/integration/default/bats/verify_ephemeral.bats +++ b/test/integration/default/bats/verify_ephemeral.bats @@ -17,6 +17,14 @@ export PATH=$PATH:/sbin:/usr/sbin lvs | grep vg-data | grep lvol0 } +# The `lvs --segments --separator :` command outputs in the following format +# 'LV:VG:Attr:#Str:Type:SSize' where '#Str' is the number of stripes and 'Type' is 'striped' +# if the LVM is striped and 'linear' otherwise. +# +@test "logical volumes are striped" { + lvs --segments --separator : | grep -P "lvol0:vg-data.*:2:striped" +} + @test "ephemeral logical volume is mounted to /mnt/ephemeral" { mountpoint /mnt/ephemeral mount | grep "/dev/mapper/vg--data-lvol0 on /mnt/ephemeral type ext3" diff --git a/test/integration/gce/bats/verify_ephemeral.bats b/test/integration/gce/bats/verify_ephemeral.bats index 396fccd..6e6df42 100644 --- a/test/integration/gce/bats/verify_ephemeral.bats +++ b/test/integration/gce/bats/verify_ephemeral.bats @@ -22,6 +22,15 @@ export PATH=$PATH:/sbin:/usr/sbin lvs | grep vg-data | grep lvol0 } + +# The `lvs --segments --separator :` command outputs in the following format +# 'LV:VG:Attr:#Str:Type:SSize' where '#Str' is the number of stripes and 'Type' is 'striped' +# if the LVM is striped and 'linear' otherwise. +# +@test "logical volumes are striped" { + lvs --segments --separator : | grep -P "lvol0:vg-data.*:2:striped" +} + @test "ephemeral logical volume is mounted to /mnt/ephemeral" { mountpoint /mnt/ephemeral mount | grep "/dev/mapper/vg--data-lvol0 on /mnt/ephemeral type ext3" From 2133e946e3fdfff44d9bc76fdb5452fed6f95141 Mon Sep 17 00:00:00 2001 From: Kannan Manickam Date: Thu, 12 Sep 2013 14:40:53 -0700 Subject: [PATCH 09/19] Updated Readme --- README.md | 49 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 47 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 293cd57..dff8600 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,57 @@ # ephemeral_lvm cookbook +Sets up the ephemeral device on a cloud instance to be an LVM device, formats the device, and mounts it. # Requirements - -# Usage +* Chef 10 or higher +* Ephemeral supported cloud +* The [lvm](http://community.opscode.com/cookbooks/lvm) cookbook # Attributes +The following are the attributes used by the this cookbook. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameDescriptionDefault
node['ephemeral_lvm']['filesystem']The filesystem to be used on the ephemeral volume'ext3'
node['ephemeral_lvm']['mount_point']The mount point for the ephemeral volume'/mnt/ephemeral'
node['ephemeral_lvm']['volume_group_name']The volume group name for the ephemeral LVM'vg-data'
node['ephemeral_lvm']['logical_volume_size']The size to be used for the ephemeral LVM'100%VG' - This will use all avialable space in the volume group
node['ephemeral_lvm']['logical_volume_name']The name of the logical volume for ephemeral LVM'lvol0'
node['ephemeral_lvm']['stripe_size']The stripe size to be used for the ephemeral logical volume512
+ +# Usage +Once the required attributes are set, place the `ephemeral_lvm::default` in the runlist and the ephemeral devices will be # Recipes +## default +This recipe will identify the ephemeral devices available on the instance based on Ohai data. If no ephemeral devices found, this recipe will gracefully exit with a log message. If ephemeral devices are found, they will be setup to use LVM and a logical volume will be created, formatted, and mounted. If multiple ephemeral devices are found (e.g. m1.large on EC2 has 2 ephemeral devices with 420 GB each), they will be striped to create the LVM. # Author From 092fa8c03d5ea1990b0c28fae59ef2816fe05192 Mon Sep 17 00:00:00 2001 From: Kannan Manickam Date: Thu, 12 Sep 2013 18:29:40 -0700 Subject: [PATCH 10/19] Fixed typo in readme --- README.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index dff8600..067a0e9 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # ephemeral_lvm cookbook -Sets up the ephemeral device on a cloud instance to be an LVM device, formats the device, and mounts it. +Sets up the ephemeral device(s) on a cloud instance to be an LVM device, formats the device, and mounts it. # Requirements * Chef 10 or higher @@ -47,11 +47,15 @@ The following are the attributes used by the this cookbook. # Usage -Once the required attributes are set, place the `ephemeral_lvm::default` in the runlist and the ephemeral devices will be +Once the required attributes are set, place the `ephemeral_lvm::default` in the runlist and the ephemeral devices will +be setup. # Recipes ## default -This recipe will identify the ephemeral devices available on the instance based on Ohai data. If no ephemeral devices found, this recipe will gracefully exit with a log message. If ephemeral devices are found, they will be setup to use LVM and a logical volume will be created, formatted, and mounted. If multiple ephemeral devices are found (e.g. m1.large on EC2 has 2 ephemeral devices with 420 GB each), they will be striped to create the LVM. +This recipe will identify the ephemeral devices available on the instance based on Ohai data. If no ephemeral devices +found, this recipe will gracefully exit with a log message. If ephemeral devices are found, they will be setup to use +LVM and a logical volume will be created, formatted, and mounted. If multiple ephemeral devices are found +(e.g. m1.large on EC2 has 2 ephemeral devices with 420 GB each), they will be striped to create the LVM. # Author From a5d94441870514e23ff0b360c8b23e87aae5802f Mon Sep 17 00:00:00 2001 From: Kannan Manickam Date: Thu, 12 Sep 2013 18:31:41 -0700 Subject: [PATCH 11/19] Update test-kitchen gem and remove xfs cookbook --- Gemfile | 2 +- metadata.rb | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/Gemfile b/Gemfile index a2cc8be..8040081 100644 --- a/Gemfile +++ b/Gemfile @@ -3,5 +3,5 @@ source 'https://rubygems.org' gem 'berkshelf' gem 'thor-foodcritic' gem 'thor-scmversion' -gem 'test-kitchen', '~> 1.0.0.beta.2', :group => :integration +gem 'test-kitchen', '~> 1.0.0.beta.3', :group => :integration gem 'kitchen-vagrant', :group => :integration diff --git a/metadata.rb b/metadata.rb index 00acc33..8aebce8 100644 --- a/metadata.rb +++ b/metadata.rb @@ -6,5 +6,4 @@ long_description IO.read(File.join(File.dirname(__FILE__), 'README.md')) version IO.read(File.join(File.dirname(__FILE__), 'VERSION')) rescue '0.1.0' -depends 'xfs', '~> 1.1.0' depends 'lvm' From 9289d1330f8d7774ecd8339bdba4978062b26af9 Mon Sep 17 00:00:00 2001 From: Kannan Manickam Date: Thu, 12 Sep 2013 18:33:49 -0700 Subject: [PATCH 12/19] Update readme for the test cookbook --- test/cookbooks/ephemeral_lvm-test/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/cookbooks/ephemeral_lvm-test/README.md b/test/cookbooks/ephemeral_lvm-test/README.md index 26f0f7e..14fe064 100644 --- a/test/cookbooks/ephemeral_lvm-test/README.md +++ b/test/cookbooks/ephemeral_lvm-test/README.md @@ -7,7 +7,8 @@ Requires the `ephemeral_lvm` cookbook. This cookbook is only used to test the `ephemeral_lvm` cookbook. # Attributes -There are no attributes in this cookbook. + +`node['ephemeral_lvm-test']['devices']` - The ephemeral devices to be used for testing # Recipes From 7004868eac0c2d11e21333ff6d64f02f972bbba7 Mon Sep 17 00:00:00 2001 From: Kannan Manickam Date: Thu, 26 Sep 2013 17:10:42 -0700 Subject: [PATCH 13/19] code review changes and added unit tests --- Gemfile | 17 +++++++-- README.md | 12 +++++-- Strainerfile | 4 +++ attributes/default.rb | 5 +++ libraries/helper.rb | 23 +++++++++--- recipes/default.rb | 16 ++++----- spec/ephemeral_lvm_helper_spec.rb | 36 +++++++++++++++++++ test/cookbooks/ephemeral_lvm-test/README.md | 3 ++ .../ephemeral_lvm-test/libraries/helper.rb | 15 ++++---- .../ephemeral_lvm-test/recipes/gce.rb | 6 +++- 10 files changed, 111 insertions(+), 26 deletions(-) create mode 100644 Strainerfile create mode 100644 spec/ephemeral_lvm_helper_spec.rb diff --git a/Gemfile b/Gemfile index 8040081..542aa6a 100644 --- a/Gemfile +++ b/Gemfile @@ -1,7 +1,20 @@ source 'https://rubygems.org' +# Berkshelf had some issues with latest version of Celluloid +# which required latest version of ridley which was causing problems. +# So locking ridley to '~> 1.5.0' here makes things work +# +gem 'ridley', '~> 1.5.0' gem 'berkshelf' gem 'thor-foodcritic' gem 'thor-scmversion' -gem 'test-kitchen', '~> 1.0.0.beta.3', :group => :integration -gem 'kitchen-vagrant', :group => :integration + +group :integration do + gem 'test-kitchen', '~> 1.0.0.beta.3' + gem 'kitchen-vagrant' +end + +group :test do + gem 'chefspec', '~> 1.3' + gem 'strainer', '~> 3.0' +end diff --git a/README.md b/README.md index 067a0e9..7b041e1 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,15 @@ # ephemeral_lvm cookbook + Sets up the ephemeral device(s) on a cloud instance to be an LVM device, formats the device, and mounts it. # Requirements + * Chef 10 or higher * Ephemeral supported cloud * The [lvm](http://community.opscode.com/cookbooks/lvm) cookbook # Attributes + The following are the attributes used by the this cookbook. @@ -32,7 +35,7 @@ The following are the attributes used by the this cookbook. - + @@ -47,14 +50,17 @@ The following are the attributes used by the this cookbook.
node['ephemeral_lvm']['logical_volume_size'] The size to be used for the ephemeral LVM'100%VG' - This will use all avialable space in the volume group'100%VG' - This will use all available space in the volume group
node['ephemeral_lvm']['logical_volume_name']
# Usage + Once the required attributes are set, place the `ephemeral_lvm::default` in the runlist and the ephemeral devices will be setup. # Recipes + ## default + This recipe will identify the ephemeral devices available on the instance based on Ohai data. If no ephemeral devices -found, this recipe will gracefully exit with a log message. If ephemeral devices are found, they will be setup to use -LVM and a logical volume will be created, formatted, and mounted. If multiple ephemeral devices are found +are found, this recipe will gracefully exit with a log message. If ephemeral devices are found, they will be setup to +use LVM and a logical volume will be created, formatted, and mounted. If multiple ephemeral devices are found (e.g. m1.large on EC2 has 2 ephemeral devices with 420 GB each), they will be striped to create the LVM. # Author diff --git a/Strainerfile b/Strainerfile new file mode 100644 index 0000000..8d77cb6 --- /dev/null +++ b/Strainerfile @@ -0,0 +1,4 @@ +knife: bundle exec knife cookbook test $COOKBOOK +foodcritic: bundle exec foodcritic -f any $SANDBOX/$COOKBOOK +rspec: bundle exec rspec --color --format documentation +kitchen: bundle exec kitchen test diff --git a/attributes/default.rb b/attributes/default.rb index b624189..1d0f457 100644 --- a/attributes/default.rb +++ b/attributes/default.rb @@ -19,13 +19,18 @@ # The ephemeral file system default['ephemeral_lvm']['filesystem'] = "ext4" + # The ephemeral mount point default['ephemeral_lvm']['mount_point'] = "/mnt/ephemeral" + # The ephemeral volume group name default['ephemeral_lvm']['volume_group_name'] = "vg-data" + # The logical volume size of the ephemeral disk default['ephemeral_lvm']['logical_volume_size'] = "100%VG" + # The ephemeral logical volume name default['ephemeral_lvm']['logical_volume_name'] = "lvol0" + # The stripe size in kilobytes to be used if more than one ephemeral disk is found default['ephemeral_lvm']['stripe_size'] = 512 diff --git a/libraries/helper.rb b/libraries/helper.rb index 429cf4c..52dfc53 100644 --- a/libraries/helper.rb +++ b/libraries/helper.rb @@ -19,12 +19,27 @@ module EphemeralLvm module Helper + # Fixes the device mapping on Xen hypervisors. + # + # @param devices [Array] list of devices to fix the mapping + # @param node_block_devices [Array] list of block devices currently attached to the server + # + # @return [Array] list of devices with fixed mapping + # def self.fix_device_mapping(devices, node_block_devices) - fixed_devices = devices.map do |device| - fixed_device = device.sub("/sd", "/xvd") - fixed_device if node_block_devices.include?(fixed_device.match(/\/dev\/([a-z]+)$/)[1]) + devices.map! do |device| + if node_block_devices.include?(device.match(/\/dev\/([a-z]+)$/)[1]) + device + else + fixed_device = device.sub("/sd", "/xvd") + if node_block_devices.include?(fixed_device.match(/\/dev\/([a-z]+)$/)[1]) + fixed_device + else + Chef::Log.warn "could not find ephemeral device: #{device}" + end + end end - fixed_devices.compact + devices.compact end end end diff --git a/recipes/default.rb b/recipes/default.rb index ac92722..36e0162 100644 --- a/recipes/default.rb +++ b/recipes/default.rb @@ -43,42 +43,40 @@ # Servers running on Xen hypervisor require the block device to be in /dev/xvdX instead of /dev/sdX if node.attribute?('virtualization') && node['virtualization']['system'] == "xen" - Chef::Log.info "Mapping for devices: #{ephemeral_devices.inspect}" + log "Mapping for devices: #{ephemeral_devices.inspect}" ephemeral_devices = EphemeralLvm::Helper.fix_device_mapping( ephemeral_devices, node['block_device'].keys ) - log "Ephemeral disks found for cloud '#{cloud}': #{ephemeral_devices.inspect}" + log "Ephemeral disks found for cloud '#{cloud}': #{ephemeral_devices.inspect}" end else # Cloud specific ephemeral detection logic if the cloud doesn't support block_device_mapping # case cloud when 'gce' - # According the GCE documentation, the instances have links for ephemeral disks as - # /dev/disk/by-id/google-ephemeral-disk-*. Refer + # According to the GCE documentation, the instances have links for ephemeral disks as + # /dev/disk/by-id/google-ephemeral-disk-*. Refer to # https://developers.google.com/compute/docs/disks#scratchdisks for more information. # ephemeral_devices = node[cloud]['attached_disks']['disks'].collect do |disk| - if disk['type'] == "EPHEMERAL" && disk['deviceName'].match(/ephemeral-disk-\d+/) + if disk['type'] == "EPHEMERAL" && disk['deviceName'].match(/^ephemeral-disk-\d+$/) "/dev/disk/by-id/google-#{disk["deviceName"]}" end end # Removes nil elements from the ephemeral_devices array if any. ephemeral_devices.compact! else - log "Cloud '#{cloud}' doesn't have ephemeral disks or this cookbook doesn't support that cloud" + log "Cloud '#{cloud}' is not supported by this cookbook." end end - - if ephemeral_devices.empty? log "No ephemeral disks found. Skipping setup." else log "Ephemeral disks found for cloud '#{cloud}': #{ephemeral_devices.inspect}" - # Create the volume group and logical volume. If more than one ephemeral disks are found, + # Create the volume group and logical volume. If more than one ephemeral disk is found, # they are created with LVM stripes with the stripe size set in the attributes. # lvm_volume_group node['ephemeral_lvm']['volume_group_name'] do diff --git a/spec/ephemeral_lvm_helper_spec.rb b/spec/ephemeral_lvm_helper_spec.rb new file mode 100644 index 0000000..c417ab1 --- /dev/null +++ b/spec/ephemeral_lvm_helper_spec.rb @@ -0,0 +1,36 @@ +require_relative '../libraries/helper' + +describe EphemeralLvm::Helper do + describe "#fix_device_mapping" do + it "returns the devices as is when there is no need for mapping" do + expect( + EphemeralLvm::Helper.fix_device_mapping(["/dev/sda", "/dev/sdb"], ["sda", "sdb"]) + ).to eq(["/dev/sda", "/dev/sdb"]) + end + + it "maps the devices correctly" do + expect( + EphemeralLvm::Helper.fix_device_mapping(["/dev/sda", "/dev/sdb"], ["xvda", "xvdb"]) + ).to eq(["/dev/xvda", "/dev/xvdb"]) + end + + it "returns the original device unmapped if the device is found" do + expect( + EphemeralLvm::Helper.fix_device_mapping(["/dev/sda", "/dev/sdb"], ["xvda", "sdb"]) + ).to eq(["/dev/xvda", "/dev/sdb"]) + end + + it "skips the devices that cannot be mapped" do + # TODO: Mock this + class Chef + class Log + def self.warn(str); end + end + end + + expect( + EphemeralLvm::Helper.fix_device_mapping(["/dev/sda", "/dev/sdb"], ["xvda"]) + ).to eq(["/dev/xvda"]) + end + end +end diff --git a/test/cookbooks/ephemeral_lvm-test/README.md b/test/cookbooks/ephemeral_lvm-test/README.md index 14fe064..e4c1204 100644 --- a/test/cookbooks/ephemeral_lvm-test/README.md +++ b/test/cookbooks/ephemeral_lvm-test/README.md @@ -1,9 +1,11 @@ # ephemeral_lvm-test cookbook # Requirements + Requires the `ephemeral_lvm` cookbook. # Usage + This cookbook is only used to test the `ephemeral_lvm` cookbook. # Attributes @@ -13,6 +15,7 @@ This cookbook is only used to test the `ephemeral_lvm` cookbook. # Recipes ## prepare + This recipe prepares the server with some loop devices as ephemeral disks. # Author diff --git a/test/cookbooks/ephemeral_lvm-test/libraries/helper.rb b/test/cookbooks/ephemeral_lvm-test/libraries/helper.rb index 76856ab..8694c6f 100644 --- a/test/cookbooks/ephemeral_lvm-test/libraries/helper.rb +++ b/test/cookbooks/ephemeral_lvm-test/libraries/helper.rb @@ -17,20 +17,22 @@ # limitations under the License. # +require 'chef/mixin/shell_out' + module EphemeralLvmTest module Helper + extend Chef::Mixin::ShellOut + # Creates given loop devices # - # @param devices [Array, String] the devices to create + # @param devices [Array, String] the devices to create # # def self.create_loop_devices(devices) Array(devices).each do |device| num = device.slice(/\d+/) - mk_vfile_cmd = "dd if=/dev/zero of=/vfile#{num} bs=1024 count=65536" - Mixlib::ShellOut.new(mk_vfile_cmd).run_command.error! - mk_loop_dev_cmd = "losetup #{device} /vfile#{num}" - Mixlib::ShellOut.new(mk_loop_dev_cmd).run_command.error! + shell_out!("dd if=/dev/zero of=/vfile#{num} bs=1024 count=65536") + shell_out!("losetup #{device} /vfile#{num}") end end @@ -41,9 +43,8 @@ def self.create_loop_devices(devices) def self.remove_loop_devices(devices) require 'fileutils' Array(devices).each do |device| - Chef::Log.info "Removing loop device: #{device}" num = device.slice(/\d+/) - Mixlib::ShellOut.new("losetup -d #{device}").run_command.error! + shell_out!("losetup -d #{device}") FileUtils.rm_rf("/vfile#{num}") end end diff --git a/test/cookbooks/ephemeral_lvm-test/recipes/gce.rb b/test/cookbooks/ephemeral_lvm-test/recipes/gce.rb index 6059786..4f6f2db 100644 --- a/test/cookbooks/ephemeral_lvm-test/recipes/gce.rb +++ b/test/cookbooks/ephemeral_lvm-test/recipes/gce.rb @@ -26,7 +26,11 @@ # node['ephemeral_lvm-test']['devices'].each do |device| match = device.match(/\/dev\/loop(\d+)/) - match.nil? ? next : device_index = match[1] + if match.nil? + next + else + device_index = match[1] + end link "/dev/disk/by-id/google-ephemeral-disk-#{device_index}" do to device end From 342db3101b4651204a6ca2c64a5db264be50dfc2 Mon Sep 17 00:00:00 2001 From: Kannan Manickam Date: Thu, 26 Sep 2013 17:44:18 -0700 Subject: [PATCH 14/19] more changes from code review --- recipes/default.rb | 10 +++++----- test/cookbooks/ephemeral_lvm-test/README.md | 6 +++++- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/recipes/default.rb b/recipes/default.rb index 36e0162..8c0ecd7 100644 --- a/recipes/default.rb +++ b/recipes/default.rb @@ -31,10 +31,10 @@ # If the cloud plugin supports block device mapping on the node, obtain the # information from the node for setting up block device # - if node[cloud].keys.any? { |key| key.match(/block_device_mapping_ephemeral\d+/) } - ephemeral_devices = node[cloud].keys.collect do |key| - if key.match(/block_device_mapping_ephemeral\d+/) - node[cloud][key].match(/\/dev\//) ? node[cloud][key] : "/dev/#{node[cloud][key]}" + if node[cloud].keys.any? { |key| key.match(/^block_device_mapping_ephemeral\d+$/) } + ephemeral_devices = node[cloud].map do |key, device| + if key.match(/^block_device_mapping_ephemeral\d+$/) + device.match(/\/dev\//) ? device : "/dev/#{device}" end end @@ -59,7 +59,7 @@ # /dev/disk/by-id/google-ephemeral-disk-*. Refer to # https://developers.google.com/compute/docs/disks#scratchdisks for more information. # - ephemeral_devices = node[cloud]['attached_disks']['disks'].collect do |disk| + ephemeral_devices = node[cloud]['attached_disks']['disks'].map do |disk| if disk['type'] == "EPHEMERAL" && disk['deviceName'].match(/^ephemeral-disk-\d+$/) "/dev/disk/by-id/google-#{disk["deviceName"]}" end diff --git a/test/cookbooks/ephemeral_lvm-test/README.md b/test/cookbooks/ephemeral_lvm-test/README.md index e4c1204..6063de6 100644 --- a/test/cookbooks/ephemeral_lvm-test/README.md +++ b/test/cookbooks/ephemeral_lvm-test/README.md @@ -14,10 +14,14 @@ This cookbook is only used to test the `ephemeral_lvm` cookbook. # Recipes -## prepare +## default This recipe prepares the server with some loop devices as ephemeral disks. +## gce + +This recipe prepares the server to mimic the behavior of GCE cloud by setting up the links to ephemeral devices. + # Author Author:: RightScale, Inc. () From 429ce1fdf5169a31a7ac5e1910d2fee669b454cd Mon Sep 17 00:00:00 2001 From: Kannan Manickam Date: Mon, 30 Sep 2013 17:27:59 -0700 Subject: [PATCH 15/19] mock chef logger using Logger --- spec/ephemeral_lvm_helper_spec.rb | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/spec/ephemeral_lvm_helper_spec.rb b/spec/ephemeral_lvm_helper_spec.rb index c417ab1..ae14c57 100644 --- a/spec/ephemeral_lvm_helper_spec.rb +++ b/spec/ephemeral_lvm_helper_spec.rb @@ -1,4 +1,5 @@ require_relative '../libraries/helper' +require 'logger' describe EphemeralLvm::Helper do describe "#fix_device_mapping" do @@ -21,13 +22,8 @@ end it "skips the devices that cannot be mapped" do - # TODO: Mock this - class Chef - class Log - def self.warn(str); end - end - end - + stub_const("Chef::Log", Logger.new('/dev/null')) + Chef::Log.should_receive(:warn).with("could not find ephemeral device: /dev/sdb") expect( EphemeralLvm::Helper.fix_device_mapping(["/dev/sda", "/dev/sdb"], ["xvda"]) ).to eq(["/dev/xvda"]) From 2020abb34c1393ec6d0cc4eb092be3def7bb32b8 Mon Sep 17 00:00:00 2001 From: Kannan Manickam Date: Tue, 1 Oct 2013 14:34:32 -0700 Subject: [PATCH 16/19] Rename ephemeral_lvm-test to fake --- .kitchen.yml | 8 ++++---- Berksfile | 2 +- test/cookbooks/{ephemeral_lvm-test => fake}/README.md | 4 ++-- .../{ephemeral_lvm-test => fake}/attributes/default.rb | 4 ++-- .../{ephemeral_lvm-test => fake}/libraries/helper.rb | 2 +- test/cookbooks/{ephemeral_lvm-test => fake}/metadata.rb | 4 ++-- .../{ephemeral_lvm-test => fake}/recipes/default.rb | 4 ++-- .../cookbooks/{ephemeral_lvm-test => fake}/recipes/gce.rb | 8 ++++---- 8 files changed, 18 insertions(+), 18 deletions(-) rename test/cookbooks/{ephemeral_lvm-test => fake}/README.md (78%) rename test/cookbooks/{ephemeral_lvm-test => fake}/attributes/default.rb (86%) rename test/cookbooks/{ephemeral_lvm-test => fake}/libraries/helper.rb (97%) rename test/cookbooks/{ephemeral_lvm-test => fake}/metadata.rb (65%) rename test/cookbooks/{ephemeral_lvm-test => fake}/recipes/default.rb (86%) rename test/cookbooks/{ephemeral_lvm-test => fake}/recipes/gce.rb (81%) diff --git a/.kitchen.yml b/.kitchen.yml index ea71715..7862cf3 100644 --- a/.kitchen.yml +++ b/.kitchen.yml @@ -24,11 +24,11 @@ platforms: suites: # This test suite mimics the behavior of being in a cloud which supports block device mapping # The loopback devices given in block_device_mapping_ephemeral should be included in -# the test/cookbooks/ephemeral_lvm-test cookbook's attributes so they get created while running +# the test/cookbooks/fake cookbook's attributes so they get created while running # the test. EC2 and openstack clouds follow this format. # - name: default - run_list: ["recipe[ephemeral_lvm-test]", "recipe[ephemeral_lvm]"] + run_list: ["recipe[fake]", "recipe[ephemeral_lvm]"] attributes: cloud: provider: vagrant @@ -40,12 +40,12 @@ suites: # This test mimics the behavior of being in a google compute engine. The ephemeral disks # are mapped to /dev/disk/by-id/google-ephemeral-disk-. Loopback device matching the -# device index should be set in the test/cookbooks/ephemeral_lvm-test cookbook's attributes +# device index should be set in the test/cookbooks/fake cookbook's attributes # so they get created. For example, the following attributes will require the creation of # loopback devices "/dev/loop0" and "/dev/loop1" # - name: gce - run_list: ["recipe[ephemeral_lvm-test::gce]", "recipe[ephemeral_lvm]"] + run_list: ["recipe[fake::gce]", "recipe[ephemeral_lvm]"] attributes: cloud: provider: gce diff --git a/Berksfile b/Berksfile index 0577558..de8aac6 100644 --- a/Berksfile +++ b/Berksfile @@ -3,4 +3,4 @@ site :opscode metadata cookbook "lvm", github: "arangamani-cookbooks/lvm", tag: "0.8.13-rs" -cookbook "ephemeral_lvm-test", path: "./test/cookbooks/ephemeral_lvm-test", group: :integration +cookbook "fake", path: "./test/cookbooks/fake", group: :integration diff --git a/test/cookbooks/ephemeral_lvm-test/README.md b/test/cookbooks/fake/README.md similarity index 78% rename from test/cookbooks/ephemeral_lvm-test/README.md rename to test/cookbooks/fake/README.md index 6063de6..9ee3c8f 100644 --- a/test/cookbooks/ephemeral_lvm-test/README.md +++ b/test/cookbooks/fake/README.md @@ -1,4 +1,4 @@ -# ephemeral_lvm-test cookbook +# fake cookbook # Requirements @@ -10,7 +10,7 @@ This cookbook is only used to test the `ephemeral_lvm` cookbook. # Attributes -`node['ephemeral_lvm-test']['devices']` - The ephemeral devices to be used for testing +`node['fake']['devices']` - The ephemeral devices to be used for testing # Recipes diff --git a/test/cookbooks/ephemeral_lvm-test/attributes/default.rb b/test/cookbooks/fake/attributes/default.rb similarity index 86% rename from test/cookbooks/ephemeral_lvm-test/attributes/default.rb rename to test/cookbooks/fake/attributes/default.rb index a4d3655..ffdbf4a 100644 --- a/test/cookbooks/ephemeral_lvm-test/attributes/default.rb +++ b/test/cookbooks/fake/attributes/default.rb @@ -1,5 +1,5 @@ # -# Cookbook Name:: ephemeral_lvm-test +# Cookbook Name:: fake # Attributes:: default # # Copyright (C) 2013 RightScale, Inc. @@ -18,4 +18,4 @@ # # Ephemeral devices used for testing ephemeral_lvm cookbook -default['ephemeral_lvm-test']['devices'] = ["/dev/loop0", "/dev/loop1"] +default['fake']['devices'] = ["/dev/loop0", "/dev/loop1"] diff --git a/test/cookbooks/ephemeral_lvm-test/libraries/helper.rb b/test/cookbooks/fake/libraries/helper.rb similarity index 97% rename from test/cookbooks/ephemeral_lvm-test/libraries/helper.rb rename to test/cookbooks/fake/libraries/helper.rb index 8694c6f..463ed5b 100644 --- a/test/cookbooks/ephemeral_lvm-test/libraries/helper.rb +++ b/test/cookbooks/fake/libraries/helper.rb @@ -1,5 +1,5 @@ # -# Cookbook Name:: ephemeral_lvm-test +# Cookbook Name:: fake # Library:: helper # # Copyright (C) 2013 RightScale, Inc. diff --git a/test/cookbooks/ephemeral_lvm-test/metadata.rb b/test/cookbooks/fake/metadata.rb similarity index 65% rename from test/cookbooks/ephemeral_lvm-test/metadata.rb rename to test/cookbooks/fake/metadata.rb index 9d30b58..d5c4c0c 100644 --- a/test/cookbooks/ephemeral_lvm-test/metadata.rb +++ b/test/cookbooks/fake/metadata.rb @@ -1,8 +1,8 @@ -name 'ephemeral_lvm-test' +name 'fake' maintainer 'RightScale, Inc.' maintainer_email 'cookbooks@rightscale.com' license 'Apache 2.0' -description 'Installs/Configures ephemeral_lvm-test' +description 'A fake cookbook to prepare the test environment for ephemeral_lvm' long_description IO.read(File.join(File.dirname(__FILE__), 'README.md')) version '0.1.0' diff --git a/test/cookbooks/ephemeral_lvm-test/recipes/default.rb b/test/cookbooks/fake/recipes/default.rb similarity index 86% rename from test/cookbooks/ephemeral_lvm-test/recipes/default.rb rename to test/cookbooks/fake/recipes/default.rb index f773a01..37a28e0 100644 --- a/test/cookbooks/ephemeral_lvm-test/recipes/default.rb +++ b/test/cookbooks/fake/recipes/default.rb @@ -1,5 +1,5 @@ # -# Cookbook Name:: ephemeral_lvm-test +# Cookbook Name:: fake # Recipe:: default # # Copyright (C) 2013 RightScale, Inc. @@ -22,5 +22,5 @@ if !node.attribute?('cloud') || !node['cloud'].attribute?('provider') log "Not running on a known cloud, Skipping test setup." else - EphemeralLvmTest::Helper.create_loop_devices(node['ephemeral_lvm-test']['devices']) + EphemeralLvmTest::Helper.create_loop_devices(node['fake']['devices']) end diff --git a/test/cookbooks/ephemeral_lvm-test/recipes/gce.rb b/test/cookbooks/fake/recipes/gce.rb similarity index 81% rename from test/cookbooks/ephemeral_lvm-test/recipes/gce.rb rename to test/cookbooks/fake/recipes/gce.rb index 4f6f2db..c952b56 100644 --- a/test/cookbooks/ephemeral_lvm-test/recipes/gce.rb +++ b/test/cookbooks/fake/recipes/gce.rb @@ -1,5 +1,5 @@ # -# Cookbook Name:: ephemeral_lvm-test +# Cookbook Name:: fake # Recipe:: gce # # Copyright (C) 2013 RightScale, Inc. @@ -17,14 +17,14 @@ # limitations under the License. # -# Include the ephemeral_lvm-test::default recipe which sets up the loopback +# Include the fake::default recipe which sets up the loopback # devices used in the test. # -include_recipe "ephemeral_lvm-test" +include_recipe "fake" # Setup the links for ephemeral devices for google by id # -node['ephemeral_lvm-test']['devices'].each do |device| +node['fake']['devices'].each do |device| match = device.match(/\/dev\/loop(\d+)/) if match.nil? next From 734eb4936ea0bbdef00125d602f738ebf4695c56 Mon Sep 17 00:00:00 2001 From: Kannan Manickam Date: Mon, 7 Oct 2013 17:22:22 -0700 Subject: [PATCH 17/19] various changes for code review from @caryp --- Berksfile | 1 - README.md | 19 +++--- Strainerfile | 2 +- attributes/default.rb | 2 +- libraries/helper.rb | 61 ++++++++++++++++++- metadata.rb | 49 ++++++++++++++- recipes/default.rb | 51 ++-------------- .../default/bats/verify_ephemeral.bats | 8 +-- .../gce/bats/verify_ephemeral.bats | 8 +-- 9 files changed, 132 insertions(+), 69 deletions(-) diff --git a/Berksfile b/Berksfile index de8aac6..5820c8c 100644 --- a/Berksfile +++ b/Berksfile @@ -2,5 +2,4 @@ site :opscode metadata -cookbook "lvm", github: "arangamani-cookbooks/lvm", tag: "0.8.13-rs" cookbook "fake", path: "./test/cookbooks/fake", group: :integration diff --git a/README.md b/README.md index 7b041e1..195addc 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,14 @@ # ephemeral_lvm cookbook -Sets up the ephemeral device(s) on a cloud instance to be an LVM device, formats the device, and mounts it. +This cookbook will identify the ephemeral devices available on the instance based on Ohai data. If no ephemeral devices +are found, it will gracefully exit with a log message. If ephemeral devices are found, they will be setup to +use LVM and a logical volume will be created, formatted, and mounted. If multiple ephemeral devices are found +(e.g. m1.large on EC2 has 2 ephemeral devices with 420 GB each), they will be striped to create the LVM. # Requirements * Chef 10 or higher -* Ephemeral supported cloud +* A cloud that supports ephemeral devices. Currently supported clouds: EC2, Openstack, and Google. * The [lvm](http://community.opscode.com/cookbooks/lvm) cookbook # Attributes @@ -40,7 +43,7 @@ The following are the attributes used by the this cookbook. node['ephemeral_lvm']['logical_volume_name'] The name of the logical volume for ephemeral LVM - 'lvol0' + 'ephemeral0' node['ephemeral_lvm']['stripe_size'] @@ -51,20 +54,14 @@ The following are the attributes used by the this cookbook. # Usage -Once the required attributes are set, place the `ephemeral_lvm::default` in the runlist and the ephemeral devices will -be setup. +Place the `ephemeral_lvm::default` in the runlist and the ephemeral devices will be setup. # Recipes ## default -This recipe will identify the ephemeral devices available on the instance based on Ohai data. If no ephemeral devices -are found, this recipe will gracefully exit with a log message. If ephemeral devices are found, they will be setup to -use LVM and a logical volume will be created, formatted, and mounted. If multiple ephemeral devices are found -(e.g. m1.large on EC2 has 2 ephemeral devices with 420 GB each), they will be striped to create the LVM. +This recipe sets up available ephemeral devices to be an LVM device, formats it, and mounts it. # Author Author:: RightScale, Inc. () - -Maintained by the RightScale White Team diff --git a/Strainerfile b/Strainerfile index 8d77cb6..54b8e34 100644 --- a/Strainerfile +++ b/Strainerfile @@ -1,4 +1,4 @@ knife: bundle exec knife cookbook test $COOKBOOK -foodcritic: bundle exec foodcritic -f any $SANDBOX/$COOKBOOK +foodcritic: bundle exec foodcritic --epic-fail any $SANDBOX/$COOKBOOK rspec: bundle exec rspec --color --format documentation kitchen: bundle exec kitchen test diff --git a/attributes/default.rb b/attributes/default.rb index 1d0f457..979d322 100644 --- a/attributes/default.rb +++ b/attributes/default.rb @@ -30,7 +30,7 @@ default['ephemeral_lvm']['logical_volume_size'] = "100%VG" # The ephemeral logical volume name -default['ephemeral_lvm']['logical_volume_name'] = "lvol0" +default['ephemeral_lvm']['logical_volume_name'] = "ephemeral0" # The stripe size in kilobytes to be used if more than one ephemeral disk is found default['ephemeral_lvm']['stripe_size'] = 512 diff --git a/libraries/helper.rb b/libraries/helper.rb index 52dfc53..ee7b7d1 100644 --- a/libraries/helper.rb +++ b/libraries/helper.rb @@ -19,7 +19,66 @@ module EphemeralLvm module Helper - # Fixes the device mapping on Xen hypervisors. + # Identifies the ephemeral devices available on a cloud server based on cloud-specific Ohai data and returns + # them as an array. This method also does the mapping required for Xen hypervisors (/dev/sdX -> /dev/xvdX). + # + # @param cloud [String] the name of cloud + # @param node [Chef::Node] the Chef node + # + # @return [Array] list of ephemeral available ephemeral devices. + # + def self.get_ephemeral_devices(cloud, node) + ephemeral_devices = [] + # Detects the ephemeral disks available on the instance. + # + # If the cloud plugin supports block device mapping on the node, obtain the + # information from the node for setting up block device + # + if node[cloud].keys.any? { |key| key.match(/^block_device_mapping_ephemeral\d+$/) } + ephemeral_devices = node[cloud].map do |key, device| + if key.match(/^block_device_mapping_ephemeral\d+$/) + device.match(/\/dev\//) ? device : "/dev/#{device}" + end + end + + # Removes nil elements from the ephemeral_devices array if any. + ephemeral_devices.compact! + + # Servers running on Xen hypervisor require the block device to be in /dev/xvdX instead of /dev/sdX + if node.attribute?('virtualization') && node['virtualization']['system'] == "xen" + log "Mapping for devices: #{ephemeral_devices.inspect}" + ephemeral_devices = EphemeralLvm::Helper.fix_device_mapping( + ephemeral_devices, + node['block_device'].keys + ) + Chef::Log.info "Ephemeral disks found for cloud '#{cloud}': #{ephemeral_devices.inspect}" + end + else + # Cloud specific ephemeral detection logic if the cloud doesn't support block_device_mapping + # + case cloud + when 'gce' + # According to the GCE documentation, the instances have links for ephemeral disks as + # /dev/disk/by-id/google-ephemeral-disk-*. Refer to + # https://developers.google.com/compute/docs/disks#scratchdisks for more information. + # + ephemeral_devices = node[cloud]['attached_disks']['disks'].map do |disk| + if disk['type'] == "EPHEMERAL" && disk['deviceName'].match(/^ephemeral-disk-\d+$/) + "/dev/disk/by-id/google-#{disk["deviceName"]}" + end + end + # Removes nil elements from the ephemeral_devices array if any. + ephemeral_devices.compact! + else + Chef::Log.info "Cloud '#{cloud}' is not supported by this cookbook." + end + end + ephemeral_devices + end + + # Fixes the device mapping on Xen hypervisors. When using Xen hypervisors, the devices are mapped from /dev/sdX to + # /dev/xvdX. This method will identify if mapping is required (by checking the existence of unmapped device) and + # map the devices accordingly. # # @param devices [Array] list of devices to fix the mapping # @param node_block_devices [Array] list of block devices currently attached to the server diff --git a/metadata.rb b/metadata.rb index 8aebce8..f016b8c 100644 --- a/metadata.rb +++ b/metadata.rb @@ -6,4 +6,51 @@ long_description IO.read(File.join(File.dirname(__FILE__), 'README.md')) version IO.read(File.join(File.dirname(__FILE__), 'VERSION')) rescue '0.1.0' -depends 'lvm' +supports 'ubuntu' +supports 'centos' + +depends 'lvm', '~> 1.0.0' + +recipe "ephemeral_lvm::default", "Setps up ephemeral devices on a cloud instance" + +attribute "ephemeral_lvm/filesystem", + :display_name => "Ephemeral LVM Filesystem", + :description => "The filesystem to be used on the ephemeral volume", + :default => "ext4", + :recipes => ["ephemeral_lvm::default"], + :required => "recommended" + +attribute "ephemeral_lvm/mount_point", + :display_name => "Ephemeral LVM Mount Point", + :description => "The mount point for the ephemeral volume", + :default => "/mnt/ephemeral", + :recipes => ["ephemeral_lvm::default"], + :required => "recommended" + +attribute "ephemeral_lvm/volume_group_name", + :display_name => "Ephemeral LVM Volume Group Name", + :description => "The volume group name for the ephemeral LVM", + :default => "vg-data", + :recipes => ["ephemeral_lvm::default"], + :required => "optional" + +attribute "ephemeral_lvm/logical_volume_size", + :display_name => "Ephemeral LVM Logical Volume Size", + :description => "The size to be used for the ephemeral LVM", + :default => "100%VG", + :recipes => ["ephemeral_lvm::default"], + :required => "optional" + +attribute "ephemeral_lvm/logical_volume_name", + :display_name => "Ephemeral LVM Logical Volume Name", + :description => "The name of the logical volume for ephemeral LVM", + :default => "ephemeral0", + :recipes => ["ephemeral_lvm::default"], + :required => "optional" + +attribute "ephemeral_lvm/stripe_size", + :display_name => "Ephemeral LVM Stripe Size", + :description => "The stripe size to be used for the ephemeral logical volume", + :default => "512", + :recipes => ["ephemeral_lvm::default"], + :required => "optional" diff --git a/recipes/default.rb b/recipes/default.rb index 8c0ecd7..e5f4322 100644 --- a/recipes/default.rb +++ b/recipes/default.rb @@ -24,52 +24,13 @@ if !node.attribute?('cloud') || !node['cloud'].attribute?('provider') log "Not running on a known cloud, not setting up ephemeral LVM" else - ephemeral_devices = [] + # Obtain the current cloud cloud = node['cloud']['provider'] - # Detects the ephemeral disks available on the instance. - # - # If the cloud plugin supports block device mapping on the node, obtain the - # information from the node for setting up block device - # - if node[cloud].keys.any? { |key| key.match(/^block_device_mapping_ephemeral\d+$/) } - ephemeral_devices = node[cloud].map do |key, device| - if key.match(/^block_device_mapping_ephemeral\d+$/) - device.match(/\/dev\//) ? device : "/dev/#{device}" - end - end - # Removes nil elements from the ephemeral_devices array if any. - ephemeral_devices.compact! - - # Servers running on Xen hypervisor require the block device to be in /dev/xvdX instead of /dev/sdX - if node.attribute?('virtualization') && node['virtualization']['system'] == "xen" - log "Mapping for devices: #{ephemeral_devices.inspect}" - ephemeral_devices = EphemeralLvm::Helper.fix_device_mapping( - ephemeral_devices, - node['block_device'].keys - ) - log "Ephemeral disks found for cloud '#{cloud}': #{ephemeral_devices.inspect}" - end - else - # Cloud specific ephemeral detection logic if the cloud doesn't support block_device_mapping - # - case cloud - when 'gce' - # According to the GCE documentation, the instances have links for ephemeral disks as - # /dev/disk/by-id/google-ephemeral-disk-*. Refer to - # https://developers.google.com/compute/docs/disks#scratchdisks for more information. - # - ephemeral_devices = node[cloud]['attached_disks']['disks'].map do |disk| - if disk['type'] == "EPHEMERAL" && disk['deviceName'].match(/^ephemeral-disk-\d+$/) - "/dev/disk/by-id/google-#{disk["deviceName"]}" - end - end - # Removes nil elements from the ephemeral_devices array if any. - ephemeral_devices.compact! - else - log "Cloud '#{cloud}' is not supported by this cookbook." - end - end + # Obtain the available ephemeral devices. See "libraries/helper.rb" for the definition of + # "get_ephemeral_devices" method. + # + ephemeral_devices = EphemeralLvm::Helper.get_ephemeral_devices(cloud, node) if ephemeral_devices.empty? log "No ephemeral disks found. Skipping setup." @@ -88,7 +49,7 @@ mount_point node['ephemeral_lvm']['mount_point'] if ephemeral_devices.size > 1 stripes ephemeral_devices.size - stripe_size node['ephemeral_lvm']['stripe_size'] + stripe_size node['ephemeral_lvm']['stripe_size'].to_i end end end diff --git a/test/integration/default/bats/verify_ephemeral.bats b/test/integration/default/bats/verify_ephemeral.bats index 507b58b..40fef1c 100644 --- a/test/integration/default/bats/verify_ephemeral.bats +++ b/test/integration/default/bats/verify_ephemeral.bats @@ -14,7 +14,7 @@ export PATH=$PATH:/sbin:/usr/sbin } @test "logical volume is created for ephemeral devices on the correct volume group" { - lvs | grep vg-data | grep lvol0 + lvs | grep vg-data | grep ephemeral0 } # The `lvs --segments --separator :` command outputs in the following format @@ -22,11 +22,11 @@ export PATH=$PATH:/sbin:/usr/sbin # if the LVM is striped and 'linear' otherwise. # @test "logical volumes are striped" { - lvs --segments --separator : | grep -P "lvol0:vg-data.*:2:striped" + lvs --segments --separator : | grep -P "ephemeral0:vg-data.*:2:striped" } @test "ephemeral logical volume is mounted to /mnt/ephemeral" { mountpoint /mnt/ephemeral - mount | grep "/dev/mapper/vg--data-lvol0 on /mnt/ephemeral type ext3" - grep -P "/dev/mapper/vg--data-lvol0\s+/mnt/ephemeral\s+ext3" /etc/fstab + mount | grep "/dev/mapper/vg--data-ephemeral0 on /mnt/ephemeral type ext3" + grep -P "/dev/mapper/vg--data-ephemeral0\s+/mnt/ephemeral\s+ext3" /etc/fstab } diff --git a/test/integration/gce/bats/verify_ephemeral.bats b/test/integration/gce/bats/verify_ephemeral.bats index 6e6df42..6d5b693 100644 --- a/test/integration/gce/bats/verify_ephemeral.bats +++ b/test/integration/gce/bats/verify_ephemeral.bats @@ -19,7 +19,7 @@ export PATH=$PATH:/sbin:/usr/sbin } @test "logical volume is created for ephemeral devices on the correct volume group" { - lvs | grep vg-data | grep lvol0 + lvs | grep vg-data | grep ephemeral0 } @@ -28,11 +28,11 @@ export PATH=$PATH:/sbin:/usr/sbin # if the LVM is striped and 'linear' otherwise. # @test "logical volumes are striped" { - lvs --segments --separator : | grep -P "lvol0:vg-data.*:2:striped" + lvs --segments --separator : | grep -P "ephemeral0:vg-data.*:2:striped" } @test "ephemeral logical volume is mounted to /mnt/ephemeral" { mountpoint /mnt/ephemeral - mount | grep "/dev/mapper/vg--data-lvol0 on /mnt/ephemeral type ext3" - grep -P "/dev/mapper/vg--data-lvol0\s+/mnt/ephemeral\s+ext3" /etc/fstab + mount | grep "/dev/mapper/vg--data-ephemeral0 on /mnt/ephemeral type ext3" + grep -P "/dev/mapper/vg--data-ephemeral0\s+/mnt/ephemeral\s+ext3" /etc/fstab } From 78fad029915ab45a866cd1ca5d016a5621707475 Mon Sep 17 00:00:00 2001 From: Kannan Manickam Date: Tue, 22 Oct 2013 15:19:50 -0700 Subject: [PATCH 18/19] Made few other changes suggested by @caryp --- README.md | 2 +- libraries/helper.rb | 2 +- metadata.rb | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 195addc..c88bb9a 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ The following are the attributes used by the this cookbook. node['ephemeral_lvm']['filesystem'] The filesystem to be used on the ephemeral volume - 'ext3' + 'ext4' node['ephemeral_lvm']['mount_point'] diff --git a/libraries/helper.rb b/libraries/helper.rb index ee7b7d1..1522959 100644 --- a/libraries/helper.rb +++ b/libraries/helper.rb @@ -70,7 +70,7 @@ def self.get_ephemeral_devices(cloud, node) # Removes nil elements from the ephemeral_devices array if any. ephemeral_devices.compact! else - Chef::Log.info "Cloud '#{cloud}' is not supported by this cookbook." + Chef::Log.info "Cloud '#{cloud}' is not supported by 'ephemeral_lvm' cookbook." end end ephemeral_devices diff --git a/metadata.rb b/metadata.rb index f016b8c..1ae9d88 100644 --- a/metadata.rb +++ b/metadata.rb @@ -2,7 +2,7 @@ maintainer 'RightScale, Inc.' maintainer_email 'cookbooks@rightscale.com' license 'Apache 2.0' -description 'Installs/Configures ephemeral_lvm' +description 'Configures available ephemeral devices on a cloud server' long_description IO.read(File.join(File.dirname(__FILE__), 'README.md')) version IO.read(File.join(File.dirname(__FILE__), 'VERSION')) rescue '0.1.0' @@ -11,7 +11,7 @@ depends 'lvm', '~> 1.0.0' -recipe "ephemeral_lvm::default", "Setps up ephemeral devices on a cloud instance" +recipe "ephemeral_lvm::default", "Setps up ephemeral devices on a cloud server" attribute "ephemeral_lvm/filesystem", :display_name => "Ephemeral LVM Filesystem", From 683ede24b9476b2dcca7373d81bd70518f73540e Mon Sep 17 00:00:00 2001 From: Kannan Manickam Date: Tue, 22 Oct 2013 15:37:31 -0700 Subject: [PATCH 19/19] Fixed a minor typo --- metadata.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/metadata.rb b/metadata.rb index 1ae9d88..f6d0df3 100644 --- a/metadata.rb +++ b/metadata.rb @@ -11,7 +11,7 @@ depends 'lvm', '~> 1.0.0' -recipe "ephemeral_lvm::default", "Setps up ephemeral devices on a cloud server" +recipe "ephemeral_lvm::default", "Sets up ephemeral devices on a cloud server" attribute "ephemeral_lvm/filesystem", :display_name => "Ephemeral LVM Filesystem",