diff --git a/zerg/lib/zerg/cli.rb b/zerg/lib/zerg/cli.rb index aee1e28..1a38fa4 100644 --- a/zerg/lib/zerg/cli.rb +++ b/zerg/lib/zerg/cli.rb @@ -59,7 +59,8 @@ def remove(file) class CLI < Thor class_option :force, :type => :boolean, :banner => "force overwrite of files" - class_option :debug, :type => :boolean, :banner => "add debug option to driver" + class_option :debug, :type => :boolean, :banner => "add debug option to driver" + class_option :base, :type => :string, :banner => "base name for the snapshot" def self.exit_on_failure? true @@ -84,6 +85,11 @@ def clean(task) def halt(task) puts Zerg::Runner.halt(task, options[:debug]) end + + desc "snapshot [TASK]", "takes a snapshot of currently running vms" + def snapshot(task) + puts Zerg::Runner.snapshot(task, options[:base]) + end register(HiveCLI, 'hive', 'hive [COMMAND]', 'Manage hive - a collection of task descriptions.') end diff --git a/zerg/lib/zerg/runner.rb b/zerg/lib/zerg/runner.rb index ba0e190..6c9c888 100644 --- a/zerg/lib/zerg/runner.rb +++ b/zerg/lib/zerg/runner.rb @@ -82,5 +82,23 @@ def self.clean(task, debug) end puts("SUCCESS!") end + + def self.snapshot(task, base) + # load the hive first + Zerg::Hive.instance.load + + puts "Loaded hive. Looking for task #{task}..." + abort("ERROR: Task #{task} not found in current hive!") unless Zerg::Hive.instance.hive.has_key?(task) + + begin + pmgr = ZergGemPlugin::Manager.instance + pmgr.load + driver = pmgr.create("/driver/#{Zerg::Hive.instance.hive[task]["vm"]["driver"]["drivertype"]}") + driver.snapshot Zerg::Hive.instance.load_path, task, Zerg::Hive.instance.hive[task], base + rescue ZergGemPlugin::PluginNotLoaded + abort("ERROR: driver #{Zerg::Hive.instance.hive[task]["vm"]["driver"]["drivertype"]} not found. Did you install the plugin gem?") + end + puts("SUCCESS!") + end end end \ No newline at end of file diff --git a/zerg/lib/zerg/version.rb b/zerg/lib/zerg/version.rb index d713cb0..63591ca 100644 --- a/zerg/lib/zerg/version.rb +++ b/zerg/lib/zerg/version.rb @@ -22,5 +22,5 @@ #++ module Zerg - VERSION = "0.0.21" + VERSION = "0.0.22" end diff --git a/zerg/zerg.gemspec b/zerg/zerg.gemspec index d5e9e01..f1ffed5 100644 --- a/zerg/zerg.gemspec +++ b/zerg/zerg.gemspec @@ -26,8 +26,8 @@ Gem::Specification.new do |s| s.add_dependency "json-schema" s.add_dependency "thor" s.add_dependency "highline" - s.add_dependency "zergrush_vagrant", ">= 0.0.4" - s.add_dependency "zergrush_cf", ">= 0.0.14" + s.add_dependency "zergrush_vagrant", ">= 0.0.5" + s.add_dependency "zergrush_cf", ">= 0.0.15" s.files = `git ls-files`.split("\n") s.executables = `git ls-files`.split("\n").map{|f| f =~ /^bin\/(.*)/ ? $1 : nil}.compact diff --git a/zerg_plugins/zergrush_cf/lib/zergrush_cf/init.rb b/zerg_plugins/zergrush_cf/lib/zergrush_cf/init.rb index 20b8515..f9c35e8 100644 --- a/zerg_plugins/zergrush_cf/lib/zergrush_cf/init.rb +++ b/zerg_plugins/zergrush_cf/lib/zergrush_cf/init.rb @@ -274,6 +274,81 @@ def clean hive_location, task_name, task_hash, debug abort ("ERROR: AWS error: #{fog_cf_error.ai}") end + def snapshot hive_location, task_name, task_hash, base + aws_key_id = task_hash["vm"]["driver"]["driveroptions"][0]["access_key_id"] + aws_secret = task_hash["vm"]["driver"]["driveroptions"][0]["secret_access_key"] + + # eval possible environment variables + if aws_key_id =~ /^ENV\['.+'\]$/ + aws_key_id = eval(aws_key_id) + end + + if aws_secret =~ /^ENV\['.+'\]$/ + aws_secret = eval(aws_secret) + end + + abort("AWS key id is not specified in task") unless aws_key_id != nil + abort("AWS secret is not specified in task") unless aws_secret != nil + + base_name = (base.nil?) ? "#{task_name}" : base + + puts("creating AMI Snapshots of all EC2 instances. Will use base name of #{base_name}") + + cf = Fog::AWS::CloudFormation.new( + :aws_access_key_id => aws_key_id, + :aws_secret_access_key => aws_secret + ) + + fogCompute = Fog::Compute.new( + :provider => 'AWS', + :aws_access_key_id => aws_key_id, + :aws_secret_access_key => aws_secret + ) + + rabbit_objects = initRabbitConnection(task_hash["vm"]["driver"]["driveroptions"][0]["rabbit"]) + + # create the cloudformation stack + stack_name = "#{task_name}" + processStack(stack_name, base_name, cf, fogCompute) + return 0 + + rescue Fog::Errors::Error => fog_cf_error + abort ("ERROR: AWS error: #{fog_cf_error.message}") + end + + def processStack stack_name, base_name, fogCF, fogCompute + fogCF.describe_stack_resources({ 'StackName' => stack_name })[:body]['StackResources'].each { |stack_resource| + if stack_resource['ResourceType'] == 'AWS::EC2::Instance' + saveAmi(stack_resource, base_name, fogCompute) + elsif stack_resource['ResourceType'] == 'AWS::CloudFormation::Stack' + processStack(stack_resource['PhysicalResourceId'].split('/')[1], base_name, fogCF, fogCompute) + end + } + end + + def saveAmi ec2res, base_name, fogCompute + liveInstance = fogCompute.describe_instances({ 'instance-id' => ec2res['PhysicalResourceId'] })[:body] + nameTag = liveInstance['reservationSet'][0]['instancesSet'][0]['tagSet']['Name'].split(':')[1].downcase + + ap "Creating AMI #{base_name}-#{nameTag}. Stack resource:" + ap ec2res + + ap 'Checking if image already exists...' + imageSet = fogCompute.describe_images( { 'name' => "#{base_name}-#{nameTag}" } )[:body] + if imageSet['imagesSet'].length > 0 + imageId = imageSet[0]['imageId'] + ap "Deregistering old image #{imageId}..." + response = fogCompute.deregister_image(imageId) + abort("ERROR: deregistering #{imageId} failed!") unless response[:body]['return'] == true + end + + ap 'Saving new image...' + newId = fogCompute.create_image(ec2res['PhysicalResourceId'], "#{base_name}-#{nameTag}", "#{base_name}-#{nameTag} snapshot")[:body]['imageId'] + ap "Created new AMI #{newId}" + ap "Tagging #{newId} with #{base_name}" + fogCompute.create_tags(newId, { base_name => base_name }) + end + def logEvents events events.each do |event| puts "Timestamp: #{Time.parse(event['Timestamp'].to_s).iso8601}" diff --git a/zerg_plugins/zergrush_cf/lib/zergrush_cf/version.rb b/zerg_plugins/zergrush_cf/lib/zergrush_cf/version.rb index fa3b83b..1b6d9de 100644 --- a/zerg_plugins/zergrush_cf/lib/zergrush_cf/version.rb +++ b/zerg_plugins/zergrush_cf/lib/zergrush_cf/version.rb @@ -22,5 +22,5 @@ #++ module ZergrushCF - VERSION = "0.0.14" + VERSION = "0.0.15" end diff --git a/zerg_plugins/zergrush_cf/zergrush_cf.gemspec b/zerg_plugins/zergrush_cf/zergrush_cf.gemspec index 38fdd32..399411e 100644 --- a/zerg_plugins/zergrush_cf/zergrush_cf.gemspec +++ b/zerg_plugins/zergrush_cf/zergrush_cf.gemspec @@ -17,7 +17,7 @@ Gem::Specification.new do |s| s.add_development_dependency "bundler", ">= 1.0.0" s.add_development_dependency "rake" - s.add_development_dependency "zergrush", ">= 0.0.21" + s.add_development_dependency "zergrush", ">= 0.0.22" s.add_dependency "fog", ">=1.20.0" s.add_dependency "bunny", ">=1.2.1" diff --git a/zerg_plugins/zergrush_vagrant/lib/zergrush_vagrant/init.rb b/zerg_plugins/zergrush_vagrant/lib/zergrush_vagrant/init.rb index 2fdc494..bf0ab82 100644 --- a/zerg_plugins/zergrush_vagrant/lib/zergrush_vagrant/init.rb +++ b/zerg_plugins/zergrush_vagrant/lib/zergrush_vagrant/init.rb @@ -211,6 +211,10 @@ def halt hive_location, task_name, task_hash, debug end end + def snapshot hive_location, task_name, task_hash, base + abort("ERROR: Not implemented!") + end + def task_schema return File.open(File.join("#{File.dirname(__FILE__)}", "..", "..", "resources", "tasks_schema.template"), 'r').read end diff --git a/zerg_plugins/zergrush_vagrant/lib/zergrush_vagrant/version.rb b/zerg_plugins/zergrush_vagrant/lib/zergrush_vagrant/version.rb index 8a79984..1fa8fb7 100644 --- a/zerg_plugins/zergrush_vagrant/lib/zergrush_vagrant/version.rb +++ b/zerg_plugins/zergrush_vagrant/lib/zergrush_vagrant/version.rb @@ -22,5 +22,5 @@ #++ module ZergrushVagrant - VERSION = "0.0.4" + VERSION = "0.0.5" end diff --git a/zerg_plugins/zergrush_vagrant/zergrush_vagrant.gemspec b/zerg_plugins/zergrush_vagrant/zergrush_vagrant.gemspec index 647fa49..1ff747d 100644 --- a/zerg_plugins/zergrush_vagrant/zergrush_vagrant.gemspec +++ b/zerg_plugins/zergrush_vagrant/zergrush_vagrant.gemspec @@ -17,7 +17,7 @@ Gem::Specification.new do |s| s.add_development_dependency "bundler", ">= 1.0.0" s.add_development_dependency "rake" - s.add_development_dependency "zergrush", ">= 0.0.7" + s.add_development_dependency "zergrush", ">= 0.0.22" s.add_dependency "ipaddress"