ec2-snapshot 0.1

Sign up to get free protection for your applications and to get access to all the features.
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