From deb2ca830e4a6c6ae33e1d2a2bacacc006d18c6d Mon Sep 17 00:00:00 2001 From: Paul Thornthwaite Date: Tue, 14 Aug 2012 17:08:39 +0100 Subject: [PATCH 1/3] [brightbox|compute] Implemented reboot using available API commands --- lib/fog/brightbox/models/compute/server.rb | 46 +++++++++++++++++++++- 1 file changed, 44 insertions(+), 2 deletions(-) diff --git a/lib/fog/brightbox/models/compute/server.rb b/lib/fog/brightbox/models/compute/server.rb index 9ddb9d80a..87e5d3080 100644 --- a/lib/fog/brightbox/models/compute/server.rb +++ b/lib/fog/brightbox/models/compute/server.rb @@ -71,8 +71,26 @@ module Fog connection.snapshot_server(identity) end - def reboot - false + # Directly requesting a server reboot is not supported in the API + # so needs to attempt a shutdown/stop, wait and start again. + # + # Default behaviour is a hard reboot because it is more reliable + # because the state of the server's OS is irrelevant. + # + # @param [Boolean] use_hard_reboot + # @return [Boolean] + def reboot(use_hard_reboot = true) + requires :identity + if ready? + unless use_hard_reboot + soft_reboot + else + hard_reboot + end + else + # Not able to reboot if not ready in the first place + false + end end def start @@ -152,7 +170,31 @@ module Fog merge_attributes(data) true end + + private + # Hard reboots are fast, avoiding the OS by doing a "power off" + def hard_reboot + stop + wait_for { ! ready? } + start + end + + # Soft reboots often timeout if the OS missed the request so we do more + # error checking trying to detect the timeout + # + # @fixme - Using side effect of wait_for's (evaluated block) to detect timeouts + def soft_reboot + shutdown + if wait_for(20) { ! ready? } + # Server is now down, start it up again + start + else + # We timed out + false + end + end end + end end end From 977f6e3b8b6b7097e50f199d21fcc68aa74a30bb Mon Sep 17 00:00:00 2001 From: Paul Thornthwaite Date: Wed, 15 Aug 2012 12:01:56 +0100 Subject: [PATCH 2/3] [brightbox|compute] Updates to Test helper for select image * Extracted Image API lookup * Removed inline rescue --- tests/brightbox/requests/compute/helper.rb | 22 ++++++++++++++++++---- tests/compute/helper.rb | 2 +- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/tests/brightbox/requests/compute/helper.rb b/tests/brightbox/requests/compute/helper.rb index 63f5ce7bc..c23949eac 100644 --- a/tests/brightbox/requests/compute/helper.rb +++ b/tests/brightbox/requests/compute/helper.rb @@ -42,13 +42,20 @@ class Brightbox module TestSupport # Find a suitable image for testing with # For speed of server building we're using an empty image + # + # Unless the tester has credentials this will fail so we rescue + # any errors and return nil. + # + # This is used in the shared file +tests/compute/helper.rb+ so unfortunately + # makes all tests reliant on hardcoded values and each other + # + # @return [String,NilClass] the most suitable test image's identifier or nil def self.image_id return @image_id unless @image_id.nil? - images = Fog::Compute[:brightbox].list_images - raise "No available images!" if images.empty? - image = images.select {|img| img.size == 0 }.first - image = images.first if image.nil? + image = select_testing_image_from_api @image_id = image["id"] + rescue + @image_id = nil end # Prepare a test server, wait for it to be usable but raise if it fails @@ -62,6 +69,13 @@ class Brightbox server end + private + def self.select_testing_image_from_api + images = Fog::Compute[:brightbox].list_images + raise "No available images!" if images.empty? + images.select {|img| img.size == 0 }.first || images.first + end + end module Formats module Struct diff --git a/tests/compute/helper.rb b/tests/compute/helper.rb index ff812e36d..eec88af33 100644 --- a/tests/compute/helper.rb +++ b/tests/compute/helper.rb @@ -15,7 +15,7 @@ def compute_providers }, :brightbox => { :server_attributes => { - :image_id => (Brightbox::Compute::TestSupport.image_id rescue 'img-wwgbb') # Ubuntu Lucid 10.04 server (i686) + :image_id => Brightbox::Compute::TestSupport.image_id }, :mocked => false }, From b221b97ba62622ea60f623af6d41c6db9d9798ec Mon Sep 17 00:00:00 2001 From: Paul Thornthwaite Date: Wed, 15 Aug 2012 12:27:09 +0100 Subject: [PATCH 3/3] [brightbox|compute] Helper to get default image from API * First will look for a configuration value brightbox_default_image * Second will query the API for latest Ubuntu (ideally LTS) --- lib/fog/brightbox/compute.rb | 51 ++++++++++++++++++++++ lib/fog/brightbox/models/compute/server.rb | 2 +- tests/brightbox/compute_tests.rb | 9 ++++ 3 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 tests/brightbox/compute_tests.rb diff --git a/lib/fog/brightbox/compute.rb b/lib/fog/brightbox/compute.rb index c7d445b3d..b299c0b5f 100644 --- a/lib/fog/brightbox/compute.rb +++ b/lib/fog/brightbox/compute.rb @@ -101,7 +101,24 @@ module Fog request :update_server_group request :update_user + module Shared + # Returns an identifier for the default image for use + # + # Currently tries to find the latest version Ubuntu LTS (i686) widening + # up to the latest, official version of Ubuntu available. + # + # Highly recommended that you actually select the image you want to run + # on your servers yourself! + # + # @return [String, nil] + def default_image + return @default_image_id unless @default_image_id.nil? + @default_image_id = Fog.credentials[:brightbox_default_image] || select_default_image + end + end + class Mock + include Shared def initialize(options) @brightbox_client_id = options[:brightbox_client_id] || Fog.credentials[:brightbox_client_id] @@ -111,9 +128,15 @@ module Fog def request(options) raise "Not implemented" end + + private + def select_default_image + "img-mockd" + end end class Real + include Shared def initialize(options) # Currently authentication and api endpoints are the same but may change @@ -180,6 +203,34 @@ module Fog options[:headers] = headers @connection.request(options) end + + # Queries the API and tries to select the most suitable official Image + # to use if the user chooses not to select their own. + def select_default_image + return @default_image_id unless @default_image_id.nil? + + all_images = Fog::Compute[:brightbox].list_images + official_images = all_images.select {|img| img["official"] == true} + ubuntu_lts_images = official_images.select {|img| img["name"] =~ /Ubuntu.*LTS/} + ubuntu_lts_i686_images = ubuntu_lts_images.select {|img| img["arch"] == "i686"} + + if ubuntu_lts_i686_images.empty? + # Accept other architectures + if ubuntu_lts_images.empty? + # Accept non-LTS versions of Ubuntu + unsorted_images = official_images.select {|img| img["name"] =~ /Ubuntu/} + else + unsorted_images = ubuntu_lts_images + end + else + unsorted_images = ubuntu_lts_i686_images + end + + # Get the latest and use it's ID for the default image + @default_image_id = unsorted_images.sort {|a,b| a["created_at"] <=> b["created_at"]}.first["id"] + rescue + nil + end end end diff --git a/lib/fog/brightbox/models/compute/server.rb b/lib/fog/brightbox/models/compute/server.rb index 87e5d3080..c1e2e9549 100644 --- a/lib/fog/brightbox/models/compute/server.rb +++ b/lib/fog/brightbox/models/compute/server.rb @@ -38,7 +38,7 @@ module Fog attribute :server_type def initialize(attributes={}) - self.image_id ||= 'img-wwgbb' # Ubuntu Lucid 10.04 server (i686) + self.image_id ||= Fog::Compute[:brightbox].default_image super end diff --git a/tests/brightbox/compute_tests.rb b/tests/brightbox/compute_tests.rb new file mode 100644 index 000000000..06501b68e --- /dev/null +++ b/tests/brightbox/compute_tests.rb @@ -0,0 +1,9 @@ +Shindo.tests('Fog::Compute::Brightbox::Real', ['brightbox']) do + + @bb = Fog::Compute::Brightbox::Real.new({}) + + tests("#respond_to? :default_image").returns(true) do + @bb.respond_to?(:default_image) + end + +end \ No newline at end of file