ec2-snapshot 0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2011 Voormedia B.V.
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,122 @@
1
+ EC2-snapshot - create snapshots from all mounted EBS volumes
2
+ ============================================================
3
+
4
+ EC2-snapshot is gem that allows you to easily create snapshots for mounted EBS volumes on
5
+ an EC2 instance.
6
+
7
+ The idea originated from the wish of automating snapshot creation for EC2 instances and making
8
+ it easy to integrate it into Chef.
9
+
10
+ EC2-snapshot was written with the idea of it running only on the EC2 instance for which snapshots
11
+ need to be created. Because we wanted to use it with Chef, we needed to keep configuration to a minimum.
12
+ There is no need to provide an instance id or volume ids, as that will already be retrieved on the
13
+ instance itself. The only necessities are the AWS credentials, region and an option to set which types
14
+ of volumes need to be snapshotted.
15
+
16
+ Therefore, the current implementation doesn't support the case of using a snapshotting server that creates snapshots
17
+ for all volumes. It is meant to run on all servers that require snapshots to be created of its volumes.
18
+
19
+
20
+ Features
21
+ --------
22
+
23
+ * No need to specify instance id and volume ids while using the gem
24
+ * Recognizes XFS filesystems, and looks up mount points automatically
25
+ * Freezes XFS filesystems while creating the snapshot, resulting in a consistent snapshot
26
+ * Easy integration within Chef, requiring a very simple recipe that only requires (globally defined) AWS credentials and a region
27
+ * Easy integration within your own scripts with either the executable or by instantiating the `Ec2Snapshot::Instance` class yourself
28
+ * Custom actions that need to be executed before and/or after the snapshot is created can be easily configured
29
+
30
+
31
+ Requirements
32
+ ------------
33
+
34
+ There are some requirements for using this gem:
35
+
36
+ * The gem only works on Linux, as it has dependencies on files such as `/etc/hostname` and `/proc/mounts`
37
+ * `wget` needs to be installed. This is required to automatically retrieve the current instance id
38
+ * `xfs_freeze` (included in xfsprogs package) needs to be installed in order to be able to freeze a XFS filesystem to get a consistent snapshot
39
+
40
+
41
+ Getting started
42
+ ---------------
43
+
44
+ Installing the Gem is pretty straightforward:
45
+
46
+ gem install ec2-snapshot
47
+
48
+ Note that `/etc/hostname` is used to get the name of the current instance.
49
+ Also `/proc/mounts` is used to retrieve information on the filesystems to be snapshotted.
50
+
51
+
52
+ Using the executable
53
+ --------------------
54
+
55
+ An executable has been provided to easily use the gem within your own scripts.
56
+
57
+ The executable requires a few mandatory details to be able to use your AWS account. These are:
58
+
59
+ * `AWS Access Key`: The access key defaults to `ENV["AWS_ACCESS_KEY_ID"]`.
60
+ If the environment variable is not set the value should be provided as an option while using the executable,
61
+ ie. `--aws-access-key KEY`
62
+ * `AWS Secret Access Key`: The secret access key defaults to `ENV["AWS_SECRET_ACCESS_KEY"]`.
63
+ If the environment variable is not set the value should be provided as an option while using the executable,
64
+ ie. `--aws-secret-access-key KEY`
65
+ * `AWS Region`: The region on which the volumes have been created. Needs to be provided as an option,
66
+ ie. `--aws-region eu-west-1`
67
+
68
+ The gem makes a distinction between root volumes and data volumes. The root volume is the volume on which the OS
69
+ is installed, while the data volumes are other volumes mounted on the same instance that could for example be used to store
70
+ application specific data.
71
+
72
+ By default, EC2-snapshot will attempt to create snapshots of all volumes mounted on the
73
+ current instance. In case you only need snapshots of the data volumes, which could be a valid case when using Chef,
74
+ you can easily specify that by using the `--volume-type` option:
75
+
76
+ ec2-snapshot --aws-access-key ACCESS_KEY --aws-secret-access-key KEY --aws-region us-west-1 --volume-type data
77
+
78
+ For a complete list of supported options, please execute
79
+
80
+ ec2-snapshot -h
81
+
82
+ Take note that `xfs_freeze` requires the process to run with root privileges (sudo), otherwise the XFS filesystem
83
+ cannot be frozen.
84
+
85
+
86
+ Security
87
+ --------
88
+
89
+ The most secure way of using EC2-snapshot is to create a new user with AWS IAM and allow that user to only execute a
90
+ specific set of actions.
91
+
92
+ The following actions are required:
93
+
94
+ * ec2:CreateSnapshot
95
+ * ec2:CreateTags
96
+ * ec2:DeleteSnapshot
97
+ * ec2:DescribeInstances
98
+ * ec2:DescribeSnapshots
99
+
100
+ By restricting the user to only these actions, you can make sure that the access keys required for EC2-instance cannot
101
+ be misused to manipulate the instances themselves.
102
+
103
+
104
+ Inspiration
105
+ -----------
106
+
107
+ EC2-snapshot was inspired by [ec2-consistent-snapshot](https://launchpad.net/ec2-consistent-snapshot) and
108
+ its Ruby port [ec2-consistent-snapshot-rb](http://rubygems.org/gems/ec2-consistent-snapshot-rb).
109
+
110
+
111
+ About EC2-snapshot
112
+ ------------------
113
+
114
+ EC2-snapshot was created by Mattijs van Druenen (m.vandruenen *at* voormedia.com)
115
+
116
+ Copyright 2011 Voormedia - [www.voormedia.com](http://www.voormedia.com/)
117
+
118
+
119
+ License
120
+ -------
121
+
122
+ EC2-snapshot is released under the MIT license.
data/Rakefile ADDED
@@ -0,0 +1,4 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+ Rake::TestTask.new
4
+ task :default => :test
data/bin/ec2-snapshot ADDED
@@ -0,0 +1,64 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "ec2_snapshot"
4
+ require "optparse"
5
+ require "date"
6
+
7
+ options = Hash.new
8
+
9
+ optparse = OptionParser.new do |opts|
10
+ opts.banner = "Usage: ec2-snapshot [options]"
11
+
12
+ options[:volume_type] = :all
13
+ opts.on("--volume-type TYPE", [:all, :root, :data], "Volume types that need to be snapshotted (all/root/data). Defaults to all.") do |volume_type|
14
+ options[:volume_type] = volume_type
15
+ end
16
+
17
+ options[:aws_access_key] = ENV["AWS_ACCESS_KEY_ID"]
18
+ opts.on("--aws-access-key KEY", "AWS Access Key.Either set ENV[\"AWS_ACCESS_KEY_ID\"] or provide it as an option.") do |access_key|
19
+ options[:aws_access_key] = access_key
20
+ end
21
+
22
+ options[:aws_secret_access_key] = ENV["AWS_SECRET_ACCESS_KEY"]
23
+ opts.on("--aws-secret-access-key KEY", "AWS Secret Access Key. Either set ENV[\"AWS_SECRET_ACCESS_KEY\"] or provide it as an option.") do |secret_access_key|
24
+ options[:aws_secret_access_key] = secret_access_key
25
+ end
26
+
27
+ opts.on("--aws-region REGION", "AWS Region. Mandatory. Example regions are eu-west-1 and us-west-1") do |region|
28
+ options[:aws_region] = region
29
+ end
30
+
31
+ opts.on("--before BEFORE", "Shell command to run before volume is snapshotted. Optional.") do |before|
32
+ options[:before] = before
33
+ end
34
+
35
+ opts.on("--after AFTER", "Shell command to run after volume is snapshotted. Optional.") do |after|
36
+ options[:after] = after
37
+ end
38
+
39
+ opts.on("--delete-older-than MONTHS", "Delete snapshots for this instance that are older than # months. Optional.") do |months|
40
+ options[:delete_older_than] = months.to_i
41
+ end
42
+
43
+ options[:verbose] = false
44
+ opts.on("-v", "--verbose", "Display progress output.") do |verbose|
45
+ options[:verbose] = verbose
46
+ end
47
+
48
+ opts.on("-h", "--help", "Display this screen.") do
49
+ puts opts
50
+ exit
51
+ end
52
+ end
53
+
54
+ optparse.parse!
55
+
56
+ if options[:aws_access_key].nil? or options[:aws_secret_access_key].nil? or options[:aws_region].nil?
57
+ Kernel.abort("Not all mandatory options have been provided. Exiting.")
58
+ end
59
+
60
+ instance = Ec2Snapshot::Instance.new(options)
61
+ instance.enable_rootvol_snapshot if [:all, :root].include?(options[:volume_type])
62
+ instance.enable_datavol_snapshot if [:all, :data].include?(options[:volume_type])
63
+ instance.create_snapshots
64
+ instance.delete_snapshots(Date.today << options[:delete_older_than]) if options.include?(:delete_older_than)
@@ -0,0 +1,21 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path("../lib/ec2_snapshot/version", __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.name = "ec2-snapshot"
6
+ gem.authors = ["mattijsvandruenen"]
7
+ gem.email = ["m.vandruenen@voormedia.com"]
8
+ gem.description = %q{EC2 EBS Volume Snapshotting}
9
+ gem.summary = %q{Create consistent snapshots of EBS volumes on Amazon EC2 instances.}
10
+ gem.homepage = "https://github.com/voormedia/ec2-snapshot"
11
+
12
+ gem.add_runtime_dependency "right_aws"
13
+ gem.add_development_dependency "minitest", "~> 2.8.0"
14
+ gem.add_development_dependency "mocha"
15
+
16
+ gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
17
+ gem.files = `git ls-files`.split("\n")
18
+ gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ gem.require_paths = ["lib"]
20
+ gem.version = Ec2Snapshot::VERSION
21
+ end
@@ -0,0 +1 @@
1
+ require 'ec2_snapshot'
@@ -0,0 +1,2 @@
1
+ require 'ec2_snapshot/instance'
2
+ require 'ec2_snapshot/volume'
@@ -0,0 +1,88 @@
1
+ require "date"
2
+ require "right_aws"
3
+
4
+ module Ec2Snapshot
5
+ class Instance
6
+ attr_accessor :ec2, :ec2_info, :create_rootvol_snapshot, :create_datavol_snapshot, :before, :after, :verbose
7
+
8
+ def initialize(options = {})
9
+ @ec2 = RightAws::Ec2.new(options[:aws_access_key], options[:aws_secret_access_key], :region => options[:aws_region], :logger => Logger.new('/dev/null'))
10
+ @ec2_info = @ec2.describe_instances(instance_id).first
11
+ @create_rootvol_snapshot = false
12
+ @create_datavol_snapshot = false
13
+ @before = options[:before]
14
+ @after = options[:after]
15
+ @verbose = options[:verbose] ? options[:verbose] : false
16
+ end
17
+
18
+ def enable_rootvol_snapshot
19
+ @create_rootvol_snapshot = true
20
+ end
21
+
22
+ def enable_datavol_snapshot
23
+ @create_datavol_snapshot = true
24
+ end
25
+
26
+ def create_snapshots
27
+ volumes.each do |volume|
28
+ next if not volume.requires_snapshot
29
+
30
+ puts "preparing snapshot for volume #{volume.volume_id} (#{volume.device_name})" if @verbose
31
+ custom_actions do
32
+ volume.freeze_filesystem do
33
+ volume.create_snapshot
34
+ end
35
+ end
36
+ end
37
+ end
38
+
39
+ def delete_snapshots(cut_off_date = Date.today << 3)
40
+ # This function requires a tag called Hostname to be set for each snapshot of the current instance
41
+ @ec2.describe_snapshots(:filters => {'tag:Hostname' => hostname}).each do |snapshot|
42
+ if Date.parse(snapshot[:aws_started_at]) <= cut_off_date
43
+ puts "deleting snapshot #{snapshot[:aws_id]}" if @verbose
44
+ @ec2.delete_snapshot(snapshot[:aws_id])
45
+ end
46
+ end
47
+ end
48
+
49
+ def custom_actions(&block)
50
+ if @before
51
+ puts "executing before command" if @verbose
52
+ Kernel.system(@before)
53
+ end
54
+ begin
55
+ yield
56
+ rescue Exception => ex
57
+ puts "exception thrown during snapshot creation: #{ex}" if @verbose
58
+ ensure
59
+ if @after
60
+ puts "executing after command" if @verbose
61
+ Kernel.system(@after)
62
+ end
63
+ end
64
+ end
65
+
66
+ def instance_id
67
+ # See http://docs.amazonwebservices.com/AWSEC2/latest/UserGuide/index.html?AESDG-chapter-instancedata.html
68
+ output = %x[wget -T 5 -t 1 -q -O - http://169.254.169.254/latest/meta-data/instance-id]
69
+ raise if output.empty?
70
+ output
71
+ rescue
72
+ # catch both empty output and missing wget
73
+ raise "Failed to retrieve the current instance id"
74
+ end
75
+
76
+ def hostname
77
+ %x[cat /etc/hostname].chomp
78
+ end
79
+
80
+ def root_device_name
81
+ @ec2_info[:root_device_name]
82
+ end
83
+
84
+ def volumes
85
+ @ec2_info[:block_device_mappings].collect{ |v| Ec2Snapshot::Volume.new(self, v[:ebs_volume_id], v[:device_name]) }
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,3 @@
1
+ module Ec2Snapshot
2
+ VERSION = "0.1"
3
+ end
@@ -0,0 +1,63 @@
1
+ module Ec2Snapshot
2
+ class Volume
3
+ attr_accessor :instance, :volume_id, :device_name, :mount_point, :file_system
4
+
5
+ def initialize(instance, volume_id, device_name)
6
+ @instance = instance
7
+ @volume_id = volume_id
8
+ @device_name = device_name
9
+ init_mount_info
10
+ end
11
+
12
+ def requires_snapshot
13
+ root_device = @instance.root_device_name
14
+ raise Exception, "No root device could be found" unless root_device
15
+ (root_device == @device_name and @instance.create_rootvol_snapshot) or (root_device != @device_name and @instance.create_datavol_snapshot)
16
+ end
17
+
18
+ def freeze_filesystem(&block)
19
+ if @mount_point and @file_system == "xfs"
20
+ puts "freezing XFS filesystem" if @instance.verbose
21
+ Kernel.system("xfs_freeze -f #{@mount_point}")
22
+ end
23
+
24
+ begin
25
+ yield
26
+ rescue Exception => ex
27
+ puts "exception thrown during snapshot creation: #{ex}" if @verbose
28
+ ensure
29
+ if @mount_point and @file_system == "xfs"
30
+ puts "unfreezing XFS filesystem" if @instance.verbose
31
+ Kernel.system("xfs_freeze -u #{@mount_point}")
32
+ end
33
+ end
34
+ end
35
+
36
+ def create_snapshot
37
+ puts "creating and tagging snapshot" if @instance.verbose
38
+ snapshot = @instance.ec2.create_snapshot(@volume_id, "#{@instance.hostname}: automated snapshot #{@device_name} (#{@volume_id})")
39
+ # The only way to set the name of a snapshot is by creating a name tag for the snapshot
40
+ @instance.ec2.create_tags(snapshot[:aws_id], { "Name" => "#{@instance.hostname} (#{@device_name})", "Hostname" => @instance.hostname })
41
+ end
42
+
43
+ def xfs_device_name
44
+ # Required for Ubuntu Natty Narwhal and up, which uses xvdX, while Amazon uses sdX
45
+ @device_name.gsub("/sd", "/xvd")
46
+ end
47
+
48
+ private
49
+
50
+ def init_mount_info
51
+ mounts = %x[cat /proc/mounts].split("\n")
52
+ mounts.each do |mount|
53
+ parts = mount.split(" ")
54
+ # Make sure that both Amazons volume naming and Ubuntu naming is matched
55
+ if [@device_name, xfs_device_name].include?(parts.first)
56
+ @mount_point = parts[1]
57
+ @file_system = parts[2]
58
+ break
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
data/test/helper.rb ADDED
@@ -0,0 +1,3 @@
1
+ require "minitest/mock"
2
+ require "minitest/autorun"
3
+ require "mocha"
@@ -0,0 +1,118 @@
1
+ require 'ec2_snapshot/instance'
2
+ require 'ec2_snapshot/volume'
3
+ require File.expand_path("../helper", __FILE__)
4
+
5
+ class InstanceTest < MiniTest::Unit::TestCase
6
+ def setup
7
+ # Mock system calls
8
+ Ec2Snapshot::Instance.any_instance.stubs(:`).returns("output")
9
+ Ec2Snapshot::Volume.any_instance.stubs(:`).returns("/dev/xvdf /srv xfs rw,noatime,attr2,delaylog,noquota 0 0")
10
+ # Mock right_aws init, return mock object and mock methods on that object
11
+ m = MiniTest::Mock.new
12
+ RightAws::Ec2.stubs(:new).returns(m)
13
+ m.stubs(:describe_instances).returns([{:root_device_type=>"ebs", :root_device_name=>"/dev/sda1", :block_device_mappings=>[{:device_name=>"/dev/sda1", :ebs_volume_id=>"vol-id1", :ebs_status=>"attached", :ebs_attach_time=>"2011-12-06T14:48:27.000Z", :ebs_delete_on_termination=>true}, {:device_name=>"/dev/sdf", :ebs_volume_id=>"vol-id2", :ebs_status=>"attached", :ebs_attach_time=>"2011-12-06T14:48:27.000Z", :ebs_delete_on_termination=>false}]}])
14
+
15
+ # Init Ec2Snapshot::Instance to work with
16
+ @instance = Ec2Snapshot::Instance.new({ :access_key => "accesskey", :secret_access_key => "secretkey", :region => "region" })
17
+ end
18
+
19
+ # new
20
+ def test_create_new_instance_should_fail_if_required_ec2_credentials_are_unavailable
21
+ assert_raises NoMethodError do
22
+ Ec2Snapshot::Instance.new(nil)
23
+ end
24
+ end
25
+
26
+ def test_create_new_instance_should_not_fail_if_required_ec2_credentials_are_available
27
+ assert_instance_of Ec2Snapshot::Instance, @instance
28
+ end
29
+
30
+ # custom_actions
31
+ def test_custom_actions_should_execute_before_action_if_set
32
+ Kernel.expects(:system).with("test")
33
+ @instance.before = "test"
34
+ @instance.custom_actions do
35
+ true
36
+ end
37
+ end
38
+
39
+ def test_custom_actions_should_execute_after_action_if_set
40
+ Kernel.expects(:system).with("test")
41
+ @instance.after = "test"
42
+ @instance.custom_actions do
43
+ true
44
+ end
45
+ end
46
+
47
+ def test_custom_actions_should_execute_after_action_even_if_block_throws_an_exception
48
+ Kernel.expects(:system).with("test")
49
+ @instance.after = "test"
50
+ @instance.custom_actions do
51
+ raise Exception
52
+ end
53
+ end
54
+
55
+ # enable_rootvol_snapshot
56
+ def test_enable_rootvol_snapshot_should_return_true
57
+ assert @instance.enable_rootvol_snapshot
58
+ end
59
+
60
+ def test_enable_rootvol_snapshot_should_set_instance_variable
61
+ assert !@instance.create_rootvol_snapshot
62
+ @instance.enable_rootvol_snapshot
63
+ assert @instance.create_rootvol_snapshot
64
+ end
65
+
66
+ # enable_datavol_snapshot
67
+ def test_enable_datavol_snapshot_should_return_true
68
+ assert @instance.enable_datavol_snapshot
69
+ end
70
+
71
+ def test_enable_datavol_snapshot_should_set_instance_variable
72
+ assert !@instance.create_datavol_snapshot
73
+ @instance.enable_datavol_snapshot
74
+ assert @instance.create_datavol_snapshot
75
+ end
76
+
77
+ # instance_id
78
+ def test_instance_id_should_return_a_string
79
+ assert_instance_of String, @instance.instance_id
80
+ end
81
+
82
+ def test_instance_id_should_return_output_of_wget_call
83
+ assert_equal "output", @instance.instance_id
84
+ end
85
+
86
+ # hostname
87
+ def test_hostname_should_return_a_string
88
+ assert_instance_of String, @instance.hostname
89
+ end
90
+
91
+ def test_hostname_should_return_hostname
92
+ assert_equal "output", @instance.instance_id
93
+ end
94
+
95
+ # root_device_name
96
+ def test_root_device_name_should_return_a_string_if_device_name_is_found
97
+ assert_instance_of String, @instance.root_device_name
98
+ end
99
+
100
+ def test_root_device_name_should_return_correct_metadata
101
+ assert_equal "/dev/sda1", @instance.root_device_name
102
+ end
103
+
104
+ # volumes
105
+ def test_volumes_should_return_an_array
106
+ assert_instance_of Array, @instance.volumes
107
+ end
108
+
109
+ def test_volumes_should_return_volume_objects
110
+ @instance.volumes.each do |vol|
111
+ assert_instance_of Ec2Snapshot::Volume, vol
112
+ end
113
+ end
114
+
115
+ def test_volumes_should_return_correct_number_of_volumes
116
+ assert_equal 2, @instance.volumes.count
117
+ end
118
+ end
@@ -0,0 +1,76 @@
1
+ require 'ec2_snapshot/volume'
2
+ require File.expand_path("../helper", __FILE__)
3
+
4
+ class VolumeTest < MiniTest::Unit::TestCase
5
+ def setup
6
+ # Mock system calls
7
+ Ec2Snapshot::Instance.any_instance.stubs(:`).returns("output")
8
+ Ec2Snapshot::Volume.any_instance.stubs(:`).returns("/dev/xvdf /srv xfs rw,noatime,attr2,delaylog,noquota 0 0")
9
+ # Mock right_aws init, return mock object and mock methods on that object
10
+ m = MiniTest::Mock.new
11
+ RightAws::Ec2.stubs(:new).returns(m)
12
+ m.stubs(:describe_instances).returns([{:root_device_type=>"ebs", :root_device_name=>"/dev/sda1", :block_device_mappings=>[{:device_name=>"/dev/sda1", :ebs_volume_id=>"vol-id1", :ebs_status=>"attached", :ebs_attach_time=>"2011-12-06T14:48:27.000Z", :ebs_delete_on_termination=>true}, {:device_name=>"/dev/sdf", :ebs_volume_id=>"vol-id2", :ebs_status=>"attached", :ebs_attach_time=>"2011-12-06T14:48:27.000Z", :ebs_delete_on_termination=>false}]}])
13
+ # Init Ec2Snapshot::Instance to work with
14
+ @instance = Ec2Snapshot::Instance.new({ :access_key => "accesskey", :secret_access_key => "secretkey", :region => "region" })
15
+ end
16
+
17
+ # freeze_filesystem
18
+ def test_freeze_filesystem_should_freeze_and_unfreeze_filesystem_if_filesystem_is_xfs
19
+ vol = Ec2Snapshot::Volume.new(@instance, "volume-id", "/dev/sdf")
20
+ vol.file_system = "xfs"
21
+ Kernel.expects(:system).with("xfs_freeze -f /srv")
22
+ Kernel.expects(:system).with("xfs_freeze -u /srv")
23
+ vol.freeze_filesystem
24
+ end
25
+
26
+ def test_freeze_filesystem_shouldnt_freeze_and_unfreeze_filesystem_if_filesystem_is_not_xfs
27
+ vol = Ec2Snapshot::Volume.new(@instance, "volume-id", "/dev/sdf")
28
+ vol.file_system = "fat32"
29
+ Kernel.expects(:system).never
30
+ vol.freeze_filesystem
31
+ end
32
+
33
+ def test_freeze_filesystem_should_freeze_and_unfreeze_filesystem_if_filesystem_is_xfs_and_block_throws_an_exception
34
+ vol = Ec2Snapshot::Volume.new(@instance, "volume-id", "/dev/sdf")
35
+ vol.file_system = "xfs"
36
+ Kernel.expects(:system).with("xfs_freeze -f /srv")
37
+ Kernel.expects(:system).with("xfs_freeze -u /srv")
38
+ vol.freeze_filesystem do
39
+ raise Exception
40
+ end
41
+ end
42
+
43
+ # xfs_device_name
44
+ def test_xfs_device_name_should_return_a_string
45
+ vol = Ec2Snapshot::Volume.new(@instance, "volume-id", "/dev/sdf")
46
+ assert_instance_of String, vol.xfs_device_name
47
+ end
48
+
49
+ def test_xfs_device_name_should_replace_device_name
50
+ vol = Ec2Snapshot::Volume.new(@instance, "volume-id", "/dev/sdf")
51
+ assert_equal "/dev/xvdf", vol.xfs_device_name
52
+ end
53
+
54
+ # requires_snapshot
55
+ def test_requires_snapshot_should_return_true_if_volume_is_rootvol_and_rootvol_should_be_snapshotted
56
+ vol = Ec2Snapshot::Volume.new(@instance, "volume-id", "/dev/sda1")
57
+ @instance.enable_rootvol_snapshot
58
+ assert vol.requires_snapshot
59
+ end
60
+
61
+ def test_requires_snapshot_should_return_false_if_volume_is_rootvol_and_rootvol_shouldnt_be_snapshotted
62
+ vol = Ec2Snapshot::Volume.new(@instance, "volume-id", "/dev/sda1")
63
+ assert !vol.requires_snapshot
64
+ end
65
+
66
+ def test_requires_snapshot_should_return_true_if_volume_is_datavol_and_datavol_should_be_snapshotted
67
+ vol = Ec2Snapshot::Volume.new(@instance, "volume-id", "/dev/sdf")
68
+ @instance.enable_datavol_snapshot
69
+ assert vol.requires_snapshot
70
+ end
71
+
72
+ def test_requires_snapshot_should_return_false_if_volume_is_datavol_and_datavol_shouldnt_be_snapshotted
73
+ vol = Ec2Snapshot::Volume.new(@instance, "volume-id", "/dev/sdf")
74
+ assert !vol.requires_snapshot
75
+ end
76
+ end
metadata ADDED
@@ -0,0 +1,103 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ec2-snapshot
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: "0.1"
6
+ platform: ruby
7
+ authors:
8
+ - mattijsvandruenen
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2011-12-22 00:00:00 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: right_aws
17
+ prerelease: false
18
+ requirement: &id001 !ruby/object:Gem::Requirement
19
+ none: false
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ type: :runtime
25
+ version_requirements: *id001
26
+ - !ruby/object:Gem::Dependency
27
+ name: minitest
28
+ prerelease: false
29
+ requirement: &id002 !ruby/object:Gem::Requirement
30
+ none: false
31
+ requirements:
32
+ - - ~>
33
+ - !ruby/object:Gem::Version
34
+ version: 2.8.0
35
+ type: :development
36
+ version_requirements: *id002
37
+ - !ruby/object:Gem::Dependency
38
+ name: mocha
39
+ prerelease: false
40
+ requirement: &id003 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ version: "0"
46
+ type: :development
47
+ version_requirements: *id003
48
+ description: EC2 EBS Volume Snapshotting
49
+ email:
50
+ - m.vandruenen@voormedia.com
51
+ executables:
52
+ - ec2-snapshot
53
+ extensions: []
54
+
55
+ extra_rdoc_files: []
56
+
57
+ files:
58
+ - .gitignore
59
+ - Gemfile
60
+ - LICENSE
61
+ - README.md
62
+ - Rakefile
63
+ - bin/ec2-snapshot
64
+ - ec2-snapshot.gemspec
65
+ - lib/ec2-snapshot.rb
66
+ - lib/ec2_snapshot.rb
67
+ - lib/ec2_snapshot/instance.rb
68
+ - lib/ec2_snapshot/version.rb
69
+ - lib/ec2_snapshot/volume.rb
70
+ - test/helper.rb
71
+ - test/test_instance.rb
72
+ - test/test_volume.rb
73
+ homepage: https://github.com/voormedia/ec2-snapshot
74
+ licenses: []
75
+
76
+ post_install_message:
77
+ rdoc_options: []
78
+
79
+ require_paths:
80
+ - lib
81
+ required_ruby_version: !ruby/object:Gem::Requirement
82
+ none: false
83
+ requirements:
84
+ - - ">="
85
+ - !ruby/object:Gem::Version
86
+ version: "0"
87
+ required_rubygems_version: !ruby/object:Gem::Requirement
88
+ none: false
89
+ requirements:
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ version: "0"
93
+ requirements: []
94
+
95
+ rubyforge_project:
96
+ rubygems_version: 1.8.8
97
+ signing_key:
98
+ specification_version: 3
99
+ summary: Create consistent snapshots of EBS volumes on Amazon EC2 instances.
100
+ test_files:
101
+ - test/helper.rb
102
+ - test/test_instance.rb
103
+ - test/test_volume.rb