cloudkeeper-one 1.0.0
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.
- checksums.yaml +7 -0
- data/.gitignore +11 -0
- data/.gitmodules +3 -0
- data/.rspec +2 -0
- data/.rubocop.yml +48 -0
- data/.travis.yml +22 -0
- data/CODE_OF_CONDUCT.md +49 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +17 -0
- data/README.md +98 -0
- data/Rakefile +17 -0
- data/bin/cloudkeeper-one +5 -0
- data/cloudkeeper-one.gemspec +44 -0
- data/config/cloudkeeper-one.yml +23 -0
- data/config/templates/image.erb +20 -0
- data/config/templates/template.erb +19 -0
- data/lib/cloudkeeper/one/appliance_actions/list.rb +68 -0
- data/lib/cloudkeeper/one/appliance_actions/registration.rb +73 -0
- data/lib/cloudkeeper/one/appliance_actions/removal.rb +57 -0
- data/lib/cloudkeeper/one/appliance_actions/update.rb +34 -0
- data/lib/cloudkeeper/one/appliance_actions/utils/image_download.rb +43 -0
- data/lib/cloudkeeper/one/appliance_actions/utils/template_preparation.rb +36 -0
- data/lib/cloudkeeper/one/appliance_actions/utils/templates/attributes.erb +23 -0
- data/lib/cloudkeeper/one/appliance_actions/utils.rb +10 -0
- data/lib/cloudkeeper/one/appliance_actions.rb +11 -0
- data/lib/cloudkeeper/one/cli.rb +185 -0
- data/lib/cloudkeeper/one/core_connector.rb +106 -0
- data/lib/cloudkeeper/one/errors/actions/action_error.rb +9 -0
- data/lib/cloudkeeper/one/errors/actions/listing_error.rb +9 -0
- data/lib/cloudkeeper/one/errors/actions/registration_error.rb +9 -0
- data/lib/cloudkeeper/one/errors/actions/update_error.rb +9 -0
- data/lib/cloudkeeper/one/errors/actions.rb +12 -0
- data/lib/cloudkeeper/one/errors/argument_error.rb +7 -0
- data/lib/cloudkeeper/one/errors/invalid_configuration_error.rb +7 -0
- data/lib/cloudkeeper/one/errors/multi_error.rb +25 -0
- data/lib/cloudkeeper/one/errors/network_connection_error.rb +7 -0
- data/lib/cloudkeeper/one/errors/opennebula/api_call_timeout_error.rb +9 -0
- data/lib/cloudkeeper/one/errors/opennebula/authentication_error.rb +9 -0
- data/lib/cloudkeeper/one/errors/opennebula/missing_pool_error.rb +9 -0
- data/lib/cloudkeeper/one/errors/opennebula/opennebula_error.rb +9 -0
- data/lib/cloudkeeper/one/errors/opennebula/resource_not_found_error.rb +9 -0
- data/lib/cloudkeeper/one/errors/opennebula/resource_retrieval_error.rb +9 -0
- data/lib/cloudkeeper/one/errors/opennebula/resource_state_error.rb +9 -0
- data/lib/cloudkeeper/one/errors/opennebula/stub_error.rb +9 -0
- data/lib/cloudkeeper/one/errors/opennebula/user_not_authorized_error.rb +9 -0
- data/lib/cloudkeeper/one/errors/opennebula.rb +17 -0
- data/lib/cloudkeeper/one/errors/standard_error.rb +7 -0
- data/lib/cloudkeeper/one/errors.rb +14 -0
- data/lib/cloudkeeper/one/opennebula/appliance_handler.rb +91 -0
- data/lib/cloudkeeper/one/opennebula/datastore_handler.rb +16 -0
- data/lib/cloudkeeper/one/opennebula/group_handler.rb +12 -0
- data/lib/cloudkeeper/one/opennebula/handler.rb +59 -0
- data/lib/cloudkeeper/one/opennebula/helper.rb +27 -0
- data/lib/cloudkeeper/one/opennebula/image_handler.rb +133 -0
- data/lib/cloudkeeper/one/opennebula/tags.rb +34 -0
- data/lib/cloudkeeper/one/opennebula/template_handler.rb +24 -0
- data/lib/cloudkeeper/one/opennebula.rb +14 -0
- data/lib/cloudkeeper/one/settings.rb +21 -0
- data/lib/cloudkeeper/one/version.rb +5 -0
- data/lib/cloudkeeper/one.rb +19 -0
- data/lib/cloudkeeper_grpc.rb +5 -0
- metadata +385 -0
| @@ -0,0 +1,14 @@ | |
| 1 | 
            +
            module Cloudkeeper
         | 
| 2 | 
            +
              module One
         | 
| 3 | 
            +
                module Errors
         | 
| 4 | 
            +
                  autoload :StandardError, 'cloudkeeper/one/errors/standard_error'
         | 
| 5 | 
            +
                  autoload :ArgumentError, 'cloudkeeper/one/errors/argument_error'
         | 
| 6 | 
            +
                  autoload :NetworkConnectionError, 'cloudkeeper/one/errors/network_connection_error'
         | 
| 7 | 
            +
                  autoload :MultiError, 'cloudkeeper/one/errors/multi_error'
         | 
| 8 | 
            +
                  autoload :InvalidConfigurationError, 'cloudkeeper/one/errors/invalid_configuration_error'
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                  autoload :Opennebula, 'cloudkeeper/one/errors/opennebula'
         | 
| 11 | 
            +
                  autoload :Actions, 'cloudkeeper/one/errors/actions'
         | 
| 12 | 
            +
                end
         | 
| 13 | 
            +
              end
         | 
| 14 | 
            +
            end
         | 
| @@ -0,0 +1,91 @@ | |
| 1 | 
            +
            require 'timeout'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Cloudkeeper
         | 
| 4 | 
            +
              module One
         | 
| 5 | 
            +
                module Opennebula
         | 
| 6 | 
            +
                  class ApplianceHandler < Handler
         | 
| 7 | 
            +
                    attr_reader :identifier
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                    LEAVE_ID_AS_IS = -1
         | 
| 10 | 
            +
                    ONEADMIN_ID = 0
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                    def initialize
         | 
| 13 | 
            +
                      super
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                      @identifier = Cloudkeeper::One::Settings[:identifier]
         | 
| 16 | 
            +
                    end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                    def find_by_appliance_id(appliance_id)
         | 
| 19 | 
            +
                      find_all_by "TEMPLATE/#{Tags::APPLIANCE_ID}" => appliance_id
         | 
| 20 | 
            +
                    end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                    def find_by_image_list_id(image_list_id)
         | 
| 23 | 
            +
                      find_all_by "TEMPLATE/#{Tags::APPLIANCE_IMAGE_LIST_ID}" => image_list_id
         | 
| 24 | 
            +
                    end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                    def delete(element)
         | 
| 27 | 
            +
                      raise Cloudkeeper::One::Errors::ArgumentError, 'element cannot be nil' unless element
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                      id = element.id
         | 
| 30 | 
            +
                      handle_opennebula_error { element.delete }
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                      timeout { sleep(Cloudkeeper::One::Opennebula::Handler::API_POLLING_WAIT) while exist? id }
         | 
| 33 | 
            +
                    end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                    def chmod(element, permissions)
         | 
| 36 | 
            +
                      raise Cloudkeeper::One::Errors::ArgumentError, 'element cannot be nil' unless element
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                      handle_opennebula_error do
         | 
| 39 | 
            +
                        element.chmod_octet permissions
         | 
| 40 | 
            +
                        element.info!
         | 
| 41 | 
            +
                      end
         | 
| 42 | 
            +
                    end
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                    def update(element, template)
         | 
| 45 | 
            +
                      raise Cloudkeeper::One::Errors::ArgumentError, 'element cannot be nil' unless element
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                      handle_opennebula_error do
         | 
| 48 | 
            +
                        element.update template, true
         | 
| 49 | 
            +
                        element.info!
         | 
| 50 | 
            +
                      end
         | 
| 51 | 
            +
                    end
         | 
| 52 | 
            +
             | 
| 53 | 
            +
                    def chgrp(element, group)
         | 
| 54 | 
            +
                      raise Cloudkeeper::One::Errors::ArgumentError, 'element cannot be nil' unless element
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                      handle_opennebula_error { element.info! }
         | 
| 57 | 
            +
                      return if group.id == element.gid
         | 
| 58 | 
            +
             | 
| 59 | 
            +
                      handle_opennebula_error do
         | 
| 60 | 
            +
                        element.chown(LEAVE_ID_AS_IS, group.id)
         | 
| 61 | 
            +
                        element.info!
         | 
| 62 | 
            +
                      end
         | 
| 63 | 
            +
                    end
         | 
| 64 | 
            +
             | 
| 65 | 
            +
                    private
         | 
| 66 | 
            +
             | 
| 67 | 
            +
                    def find_all_by(attributes)
         | 
| 68 | 
            +
                      xpaths = attributes.clone
         | 
| 69 | 
            +
                      xpaths['UNAME'] = Cloudkeeper::One::Settings[:'opennebula-users'] \
         | 
| 70 | 
            +
                        if Cloudkeeper::One::Settings[:'opennebula-users'] && !Cloudkeeper::One::Settings[:'opennebula-users'].empty?
         | 
| 71 | 
            +
             | 
| 72 | 
            +
                      find_all xpaths
         | 
| 73 | 
            +
                    end
         | 
| 74 | 
            +
             | 
| 75 | 
            +
                    def timeout
         | 
| 76 | 
            +
                      raise Cloudkeeper::One::Errors::ArgumentError, 'Timeout called without a block!' unless block_given?
         | 
| 77 | 
            +
             | 
| 78 | 
            +
                      Timeout.timeout(Cloudkeeper::One::Settings[:'opennebula-api-call-timeout']) { yield }
         | 
| 79 | 
            +
                    rescue Timeout::Error
         | 
| 80 | 
            +
                      raise Cloudkeeper::One::Errors::Opennebula::ApiCallTimeoutError, 'Operation was not successful within the timeout'
         | 
| 81 | 
            +
                    end
         | 
| 82 | 
            +
             | 
| 83 | 
            +
                    def find(method, xpaths = {})
         | 
| 84 | 
            +
                      reload!
         | 
| 85 | 
            +
             | 
| 86 | 
            +
                      pool.send(method) { |element| element["TEMPLATE/#{Tags::ID}"] == identifier && evaluate_xpaths(element, xpaths) }
         | 
| 87 | 
            +
                    end
         | 
| 88 | 
            +
                  end
         | 
| 89 | 
            +
                end
         | 
| 90 | 
            +
              end
         | 
| 91 | 
            +
            end
         | 
| @@ -0,0 +1,16 @@ | |
| 1 | 
            +
            module Cloudkeeper
         | 
| 2 | 
            +
              module One
         | 
| 3 | 
            +
                module Opennebula
         | 
| 4 | 
            +
                  class DatastoreHandler < Handler
         | 
| 5 | 
            +
                    def initialize
         | 
| 6 | 
            +
                      super
         | 
| 7 | 
            +
                      @pool = OpenNebula::DatastorePool.new client
         | 
| 8 | 
            +
                    end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                    def find_by_names(names)
         | 
| 11 | 
            +
                      names.map { |name| find_by_name name }.compact
         | 
| 12 | 
            +
                    end
         | 
| 13 | 
            +
                  end
         | 
| 14 | 
            +
                end
         | 
| 15 | 
            +
              end
         | 
| 16 | 
            +
            end
         | 
| @@ -0,0 +1,59 @@ | |
| 1 | 
            +
            module Cloudkeeper
         | 
| 2 | 
            +
              module One
         | 
| 3 | 
            +
                module Opennebula
         | 
| 4 | 
            +
                  class Handler
         | 
| 5 | 
            +
                    include Helper
         | 
| 6 | 
            +
                    attr_reader :client
         | 
| 7 | 
            +
                    attr_accessor :pool
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                    API_POLLING_WAIT = 5
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                    def initialize
         | 
| 12 | 
            +
                      @client = OpenNebula::Client.new Cloudkeeper::One::Settings[:'opennebula-secret'],
         | 
| 13 | 
            +
                                                       Cloudkeeper::One::Settings[:'opennebula-endpoint']
         | 
| 14 | 
            +
                    end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                    def find_one(xpaths = {})
         | 
| 17 | 
            +
                      find(:find, xpaths)
         | 
| 18 | 
            +
                    end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                    def find_all(xpaths = {})
         | 
| 21 | 
            +
                      find(:find_all, xpaths)
         | 
| 22 | 
            +
                    end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                    def find_by_name(name)
         | 
| 25 | 
            +
                      find_one('NAME' => name)
         | 
| 26 | 
            +
                    end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                    def find_by_id(id)
         | 
| 29 | 
            +
                      find_one('ID' => id.to_s)
         | 
| 30 | 
            +
                    end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                    def exist?(id)
         | 
| 33 | 
            +
                      find_by_id id
         | 
| 34 | 
            +
                    end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                    private
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                    def find(method, xpaths = {})
         | 
| 39 | 
            +
                      reload!
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                      pool.send(method) { |element| evaluate_xpaths(element, xpaths) }
         | 
| 42 | 
            +
                    end
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                    def evaluate_xpaths(element, xpaths)
         | 
| 45 | 
            +
                      xpaths.inject(true) do |red, elem|
         | 
| 46 | 
            +
                        red && (elem.last.is_a?(Array) ? elem.last.include?(element[elem.first]) : element[elem.first] == elem.last)
         | 
| 47 | 
            +
                      end
         | 
| 48 | 
            +
                    end
         | 
| 49 | 
            +
             | 
| 50 | 
            +
                    def reload!
         | 
| 51 | 
            +
                      raise Cloudkeeper::One::Errors::Opennebula::MissingPoolError, 'Handler is missing an OpenNebula pool' unless pool
         | 
| 52 | 
            +
             | 
| 53 | 
            +
                      method = pool.respond_to?('info_all!') ? 'info_all!' : 'info!'
         | 
| 54 | 
            +
                      handle_opennebula_error { pool.send(method.to_sym) }
         | 
| 55 | 
            +
                    end
         | 
| 56 | 
            +
                  end
         | 
| 57 | 
            +
                end
         | 
| 58 | 
            +
              end
         | 
| 59 | 
            +
            end
         | 
| @@ -0,0 +1,27 @@ | |
| 1 | 
            +
            module Cloudkeeper
         | 
| 2 | 
            +
              module One
         | 
| 3 | 
            +
                module Opennebula
         | 
| 4 | 
            +
                  module Helper
         | 
| 5 | 
            +
                    ERRORS = Hash.new(Cloudkeeper::One::Errors::Opennebula::ResourceRetrievalError)
         | 
| 6 | 
            +
                                 .update(::OpenNebula::Error::EAUTHENTICATION => Cloudkeeper::One::Errors::Opennebula::AuthenticationError,
         | 
| 7 | 
            +
                                         ::OpenNebula::Error::EAUTHORIZATION => Cloudkeeper::One::Errors::Opennebula::UserNotAuthorizedError,
         | 
| 8 | 
            +
                                         ::OpenNebula::Error::ENO_EXISTS => Cloudkeeper::One::Errors::Opennebula::ResourceNotFoundError,
         | 
| 9 | 
            +
                                         ::OpenNebula::Error::EACTION => Cloudkeeper::One::Errors::Opennebula::ResourceStateError).freeze
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                    def handle_opennebula_error
         | 
| 12 | 
            +
                      raise Cloudkeeper::One::Errors::ArgumentError, 'OpenNebula service-wrapper was called without a block!' \
         | 
| 13 | 
            +
                        unless block_given?
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                      return_value = yield
         | 
| 16 | 
            +
                      return return_value unless OpenNebula.is_error?(return_value)
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                      raise decode_error(return_value.errno), return_value.message
         | 
| 19 | 
            +
                    end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                    def decode_error(errno)
         | 
| 22 | 
            +
                      ERRORS[errno]
         | 
| 23 | 
            +
                    end
         | 
| 24 | 
            +
                  end
         | 
| 25 | 
            +
                end
         | 
| 26 | 
            +
              end
         | 
| 27 | 
            +
            end
         | 
| @@ -0,0 +1,133 @@ | |
| 1 | 
            +
            module Cloudkeeper
         | 
| 2 | 
            +
              module One
         | 
| 3 | 
            +
                module Opennebula
         | 
| 4 | 
            +
                  class ImageHandler < ApplianceHandler
         | 
| 5 | 
            +
                    IMAGE_STATES = {
         | 
| 6 | 
            +
                      ready: 'READY',
         | 
| 7 | 
            +
                      used: 'USED',
         | 
| 8 | 
            +
                      disabled: 'DISABLED',
         | 
| 9 | 
            +
                      error: 'ERROR'
         | 
| 10 | 
            +
                    }.freeze
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                    EXPIRED_PERMISSIONS = '600'.freeze
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                    def initialize
         | 
| 15 | 
            +
                      super
         | 
| 16 | 
            +
                      @pool = OpenNebula::ImagePool.new client
         | 
| 17 | 
            +
                    end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                    def expired
         | 
| 20 | 
            +
                      xpaths = { "TEMPLATE/#{Tags::EXPIRED}" => 'yes' }
         | 
| 21 | 
            +
                      xpaths['UNAME'] = Cloudkeeper::One::Settings[:'opennebula-users'] \
         | 
| 22 | 
            +
                        if Cloudkeeper::One::Settings[:'opennebula-users'] && !Cloudkeeper::One::Settings[:'opennebula-users'].empty?
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                      find_all xpaths
         | 
| 25 | 
            +
                    end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                    def delete(image)
         | 
| 28 | 
            +
                      raise Cloudkeeper::One::Errors::ArgumentError, 'image cannot be nil' unless image
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                      id = image.id
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                      if used? image
         | 
| 33 | 
            +
                        logger.warn "Image with id #{id.inspect} cannot be removed, still in use"
         | 
| 34 | 
            +
                        return
         | 
| 35 | 
            +
                      end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                      super image
         | 
| 38 | 
            +
                    end
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                    def disable(image)
         | 
| 41 | 
            +
                      raise Cloudkeeper::One::Errors::ArgumentError, 'image cannot be nil' unless image
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                      id = image.id
         | 
| 44 | 
            +
             | 
| 45 | 
            +
                      if disabled? image
         | 
| 46 | 
            +
                        logger.info "Image with id #{id.inspect} is already disabled, skipping"
         | 
| 47 | 
            +
                        return
         | 
| 48 | 
            +
                      end
         | 
| 49 | 
            +
             | 
| 50 | 
            +
                      unless free? image
         | 
| 51 | 
            +
                        logger.warn "Image with id #{id.inspect} cannot be disabled"
         | 
| 52 | 
            +
                        return
         | 
| 53 | 
            +
                      end
         | 
| 54 | 
            +
             | 
| 55 | 
            +
                      handle_opennebula_error { image.disable }
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                      timeout { sleep(Cloudkeeper::One::Opennebula::Handler::API_POLLING_WAIT) until disabled? image }
         | 
| 58 | 
            +
                    end
         | 
| 59 | 
            +
             | 
| 60 | 
            +
                    def expire(image)
         | 
| 61 | 
            +
                      raise Cloudkeeper::One::Errors::ArgumentError, 'image cannot be nil' unless image
         | 
| 62 | 
            +
             | 
| 63 | 
            +
                      id = image.id
         | 
| 64 | 
            +
             | 
| 65 | 
            +
                      if expired? image
         | 
| 66 | 
            +
                        logger.debug("Image with id #{id.inspect} is already expired, skipping")
         | 
| 67 | 
            +
                        return
         | 
| 68 | 
            +
                      end
         | 
| 69 | 
            +
             | 
| 70 | 
            +
                      chmod image, EXPIRED_PERMISSIONS
         | 
| 71 | 
            +
                      disable image
         | 
| 72 | 
            +
             | 
| 73 | 
            +
                      expiration_attribute = "#{Tags::EXPIRED} = \"yes\""
         | 
| 74 | 
            +
             | 
| 75 | 
            +
                      handle_opennebula_error { image.rename("EXPIRED_#{Time.now.to_i}_#{image.name}") }
         | 
| 76 | 
            +
                      handle_opennebula_error { image.update(expiration_attribute, true) }
         | 
| 77 | 
            +
                    end
         | 
| 78 | 
            +
             | 
| 79 | 
            +
                    def register(image_template, datastore, group)
         | 
| 80 | 
            +
                      image_alloc = OpenNebula::Image.build_xml
         | 
| 81 | 
            +
                      image = OpenNebula::Image.new(image_alloc, client)
         | 
| 82 | 
            +
             | 
| 83 | 
            +
                      handle_opennebula_error { image.allocate(image_template, datastore.id) }
         | 
| 84 | 
            +
             | 
| 85 | 
            +
                      timeout do
         | 
| 86 | 
            +
                        until ready? image
         | 
| 87 | 
            +
                          raise Cloudkeeper::One::Errors::Opennebula::ResourceStateError, image['TEMPLATE/ERROR'] if error? image
         | 
| 88 | 
            +
                          sleep(Cloudkeeper::One::Opennebula::Handler::API_POLLING_WAIT)
         | 
| 89 | 
            +
                        end
         | 
| 90 | 
            +
                      end
         | 
| 91 | 
            +
             | 
| 92 | 
            +
                      chmod image, Cloudkeeper::One::Settings[:'appliances-permissions']
         | 
| 93 | 
            +
                      chgrp image, group
         | 
| 94 | 
            +
             | 
| 95 | 
            +
                      image
         | 
| 96 | 
            +
                    end
         | 
| 97 | 
            +
             | 
| 98 | 
            +
                    def expired?(image)
         | 
| 99 | 
            +
                      is?(image) { image["TEMPLATE/#{Tags::EXPIRED}"] == 'yes' }
         | 
| 100 | 
            +
                    end
         | 
| 101 | 
            +
             | 
| 102 | 
            +
                    def disabled?(image)
         | 
| 103 | 
            +
                      is?(image) { image.state_str == IMAGE_STATES[:disabled] }
         | 
| 104 | 
            +
                    end
         | 
| 105 | 
            +
             | 
| 106 | 
            +
                    def ready?(image)
         | 
| 107 | 
            +
                      is?(image) { image.state_str == IMAGE_STATES[:ready] }
         | 
| 108 | 
            +
                    end
         | 
| 109 | 
            +
             | 
| 110 | 
            +
                    def used?(image)
         | 
| 111 | 
            +
                      is?(image) { image.state_str == IMAGE_STATES[:used] }
         | 
| 112 | 
            +
                    end
         | 
| 113 | 
            +
             | 
| 114 | 
            +
                    def free?(image)
         | 
| 115 | 
            +
                      is?(image) { image.state_str == IMAGE_STATES[:ready] || image.state_str == IMAGE_STATES[:error] }
         | 
| 116 | 
            +
                    end
         | 
| 117 | 
            +
             | 
| 118 | 
            +
                    def error?(image)
         | 
| 119 | 
            +
                      is?(image) { image.state_str == IMAGE_STATES[:error] }
         | 
| 120 | 
            +
                    end
         | 
| 121 | 
            +
             | 
| 122 | 
            +
                    private
         | 
| 123 | 
            +
             | 
| 124 | 
            +
                    def is?(image)
         | 
| 125 | 
            +
                      raise Cloudkeeper::One::Errors::ArgumentError, 'image cannot be nil' unless image
         | 
| 126 | 
            +
             | 
| 127 | 
            +
                      handle_opennebula_error { image.info! }
         | 
| 128 | 
            +
                      yield
         | 
| 129 | 
            +
                    end
         | 
| 130 | 
            +
                  end
         | 
| 131 | 
            +
                end
         | 
| 132 | 
            +
              end
         | 
| 133 | 
            +
            end
         | 
| @@ -0,0 +1,34 @@ | |
| 1 | 
            +
            module Cloudkeeper
         | 
| 2 | 
            +
              module One
         | 
| 3 | 
            +
                module Opennebula
         | 
| 4 | 
            +
                  module Tags
         | 
| 5 | 
            +
                    BASE = 'CLOUDKEEPER'.freeze
         | 
| 6 | 
            +
                    APPLIANCE = "#{BASE}_APPLIANCE".freeze
         | 
| 7 | 
            +
                    IMAGE = "#{BASE}_IMAGE".freeze
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                    ID = "#{BASE}_ID".freeze
         | 
| 10 | 
            +
                    EXPIRED = "#{BASE}_EXPIRED".freeze
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                    APPLIANCE_ID = "#{APPLIANCE}_ID".freeze
         | 
| 13 | 
            +
                    APPLIANCE_TITLE = "#{APPLIANCE}_TITLE".freeze
         | 
| 14 | 
            +
                    APPLIANCE_DESCRIPTION = "#{APPLIANCE}_DESCRIPTION".freeze
         | 
| 15 | 
            +
                    APPLIANCE_MPURI = "#{APPLIANCE}_MPURI".freeze
         | 
| 16 | 
            +
                    APPLIANCE_GROUP = "#{APPLIANCE}_GROUP".freeze
         | 
| 17 | 
            +
                    APPLIANCE_RAM = "#{APPLIANCE}_RAM".freeze
         | 
| 18 | 
            +
                    APPLIANCE_CORE = "#{APPLIANCE}_CORE".freeze
         | 
| 19 | 
            +
                    APPLIANCE_VERSION = "#{APPLIANCE}_VERSION".freeze
         | 
| 20 | 
            +
                    APPLIANCE_ARCHITECTURE = "#{APPLIANCE}_ARCHITECTURE".freeze
         | 
| 21 | 
            +
                    APPLIANCE_OPERATING_SYSTEM = "#{APPLIANCE}_OPERATING_SYSTEM".freeze
         | 
| 22 | 
            +
                    APPLIANCE_VO = "#{APPLIANCE}_VO".freeze
         | 
| 23 | 
            +
                    APPLIANCE_EXPIRATION_DATE = "#{APPLIANCE}_EXPIRATION_DATE".freeze
         | 
| 24 | 
            +
                    APPLIANCE_IMAGE_LIST_ID = "#{APPLIANCE}_IMAGE_LIST_ID".freeze
         | 
| 25 | 
            +
                    APPLIANCE_ATTRIBUTES = "#{APPLIANCE}_ATTRIBUTES".freeze
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                    IMAGE_URI = "#{IMAGE}_URI".freeze
         | 
| 28 | 
            +
                    IMAGE_CHECKSUM = "#{IMAGE}_CHECKSUM".freeze
         | 
| 29 | 
            +
                    IMAGE_SIZE = "#{IMAGE}_SIZE".freeze
         | 
| 30 | 
            +
                    IMAGE_FORMAT = "#{IMAGE}_FORMAT".freeze
         | 
| 31 | 
            +
                  end
         | 
| 32 | 
            +
                end
         | 
| 33 | 
            +
              end
         | 
| 34 | 
            +
            end
         | 
| @@ -0,0 +1,24 @@ | |
| 1 | 
            +
            module Cloudkeeper
         | 
| 2 | 
            +
              module One
         | 
| 3 | 
            +
                module Opennebula
         | 
| 4 | 
            +
                  class TemplateHandler < ApplianceHandler
         | 
| 5 | 
            +
                    def initialize
         | 
| 6 | 
            +
                      super
         | 
| 7 | 
            +
                      @pool = OpenNebula::TemplatePool.new client
         | 
| 8 | 
            +
                    end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                    def register(template_template, group)
         | 
| 11 | 
            +
                      template_alloc = OpenNebula::Template.build_xml
         | 
| 12 | 
            +
                      template = OpenNebula::Template.new(template_alloc, client)
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                      handle_opennebula_error { template.allocate template_template }
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                      chmod template, Cloudkeeper::One::Settings[:'appliances-permissions']
         | 
| 17 | 
            +
                      chgrp template, group
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                      template
         | 
| 20 | 
            +
                    end
         | 
| 21 | 
            +
                  end
         | 
| 22 | 
            +
                end
         | 
| 23 | 
            +
              end
         | 
| 24 | 
            +
            end
         | 
| @@ -0,0 +1,14 @@ | |
| 1 | 
            +
            module Cloudkeeper
         | 
| 2 | 
            +
              module One
         | 
| 3 | 
            +
                module Opennebula
         | 
| 4 | 
            +
                  autoload :Helper, 'cloudkeeper/one/opennebula/helper'
         | 
| 5 | 
            +
                  autoload :Tags, 'cloudkeeper/one/opennebula/tags'
         | 
| 6 | 
            +
                  autoload :Handler, 'cloudkeeper/one/opennebula/handler'
         | 
| 7 | 
            +
                  autoload :DatastoreHandler, 'cloudkeeper/one/opennebula/datastore_handler'
         | 
| 8 | 
            +
                  autoload :GroupHandler, 'cloudkeeper/one/opennebula/group_handler'
         | 
| 9 | 
            +
                  autoload :ApplianceHandler, 'cloudkeeper/one/opennebula/appliance_handler'
         | 
| 10 | 
            +
                  autoload :ImageHandler, 'cloudkeeper/one/opennebula/image_handler'
         | 
| 11 | 
            +
                  autoload :TemplateHandler, 'cloudkeeper/one/opennebula/template_handler'
         | 
| 12 | 
            +
                end
         | 
| 13 | 
            +
              end
         | 
| 14 | 
            +
            end
         | 
| @@ -0,0 +1,21 @@ | |
| 1 | 
            +
            require 'settingslogic'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Cloudkeeper
         | 
| 4 | 
            +
              module One
         | 
| 5 | 
            +
                class Settings < Settingslogic
         | 
| 6 | 
            +
                  CONFIGURATION = 'cloudkeeper-one.yml'.freeze
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                  # three possible configuration file locations in order by preference
         | 
| 9 | 
            +
                  # if configuration file is found rest of the locations are ignored
         | 
| 10 | 
            +
                  source "#{ENV['HOME']}/.cloudkeeper-one/#{CONFIGURATION}"\
         | 
| 11 | 
            +
                  if File.exist?("#{ENV['HOME']}/.cloudkeeper-one/#{CONFIGURATION}")
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                  source "/etc/cloudkeeper-one/#{CONFIGURATION}"\
         | 
| 14 | 
            +
                  if File.exist?("/etc/cloudkeeper-one/#{CONFIGURATION}")
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                  source "#{File.dirname(__FILE__)}/../../../config/#{CONFIGURATION}"
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                  namespace 'cloudkeeper-one'
         | 
| 19 | 
            +
                end
         | 
| 20 | 
            +
              end
         | 
| 21 | 
            +
            end
         | 
| @@ -0,0 +1,19 @@ | |
| 1 | 
            +
            require 'active_support/all'
         | 
| 2 | 
            +
            require 'opennebula'
         | 
| 3 | 
            +
            require 'json'
         | 
| 4 | 
            +
            require 'base64'
         | 
| 5 | 
            +
            require 'tempfile'
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            module Cloudkeeper
         | 
| 8 | 
            +
              module One
         | 
| 9 | 
            +
                autoload :Errors, 'cloudkeeper/one/errors'
         | 
| 10 | 
            +
                autoload :Opennebula, 'cloudkeeper/one/opennebula'
         | 
| 11 | 
            +
                autoload :ApplianceActions, 'cloudkeeper/one/appliance_actions'
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                autoload :CLI, 'cloudkeeper/one/cli'
         | 
| 14 | 
            +
                autoload :Settings, 'cloudkeeper/one/settings'
         | 
| 15 | 
            +
                autoload :CoreConnector, 'cloudkeeper/one/core_connector'
         | 
| 16 | 
            +
              end
         | 
| 17 | 
            +
            end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
            require 'cloudkeeper/one/version'
         |