gosddc/vagrant-vcloudair

View on GitHub
lib/vagrant-vcloudair/driver/meta.rb

Summary

Maintainability
B
6 hrs
Test Coverage
#
#  Copyright 2012 Stefano Tortarolo
#  Copyright 2013 Fabio Rapposelli and Timo Sugliani
#
#  Licensed under the Apache License, Version 2.0 (the "License");
#  you may not use this file except in compliance with the License.
#  You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
#  Unless required by applicable law or agreed to in writing, software
#  distributed under the License is distributed on an "AS IS" BASIS,
#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#  See the License for the specific language governing permissions and
#   limitations under the License.
#

require 'forwardable'
require 'log4r'
require 'nokogiri'
require 'httpclient'

require File.expand_path('../base', __FILE__)

module VagrantPlugins
  module VCloudAir
    module Driver
      class Meta < Base
        # We use forwardable to do all our driver forwarding
        extend Forwardable
        attr_reader :driver

        def initialize(cloud_id, username, password, vdc_name)
          # Setup the base
          super()

          @username = username
          @password = password

          @logger = Log4r::Logger.new('vagrant::provider::vcloudair::meta')

          # Logging into vCloud Air
          params = {
            'method'  => :post,
            'command' => '/vchs/sessions'
          }

          _response, headers = send_vcloudair_request(params)

          unless headers.key?('x-vchs-authorization')
            fail Errors::InvalidRequestError,
                 :message => 'Failed to authenticate: ' \
                             'missing x-vchs-authorization header'
          end

          @vcloudair_auth_key = headers['x-vchs-authorization']

          # Get Services available
          params = {
            'method'  => :get,
            'command' => '/vchs/services'
          }

          response, _headers = send_vcloudair_request(params)
          services = response.css('Services Service')

          service_id = cloud_id || vdc_name
          services.each do |service|
            if service['serviceId'] == service_id
              @compute_id = URI(service['href']).path.gsub('/api', '')
            end
          end

          fail Errors::ServiceNotFound if @compute_id.nil?

          # Get Service Link to vCloud Director
          params = {
            'method'  => :get,
            'command' => @compute_id
          }

          response, _headers = send_vcloudair_request(params)

          vdcs = response.css('Compute VdcRef')

          vdcs.each do |vdc|
            if vdc['name'] == vdc_name
              @vdc_id = URI(vdc['href']).path.gsub('/api', '')
            end
          end

          fail Errors::VdcNotFound, :message => vdc_name if @vdc_id.nil?

          # Authenticate to vCloud Director
          params = {
            'method'  => :post,
            'command' => "#{@vdc_id}/vcloudsession"
          }

          response, _headers = send_vcloudair_request(params)

          vdclinks = response.css('VCloudSession VdcLink')

          vdclinks.each do |vdclink|
            if vdclink['name'] == service_id
              uri = URI(vdclink['href'])
              @api_url = "#{uri.scheme}://#{uri.host}:#{uri.port}/api"
              @host_url = "#{uri.scheme}://#{uri.host}:#{uri.port}"
              @auth_key = vdclink['authorizationToken']
            end
          end

          fail Errors::ObjectNotFound,
               :message => 'Cannot find link to backend \
               vCloud Director Instance' if @api_url.nil?

          @org_name = vdc_name

          # Read and assign the version of vCloud Air we know which
          # specific driver to instantiate.
          @logger.debug("Asking API Version with host_url: #{@host_url}")
          @version = get_api_version(@host_url) || ''

          # Instantiate the proper version driver for vCloud Air
          @logger.debug("Finding driver for vCloud Air version: #{@version}")
          driver_map   = {
            '5.1'  => Version_5_1,
            '5.5'  => Version_5_1,
            '5.6'  => Version_5_1,
            '5.7'  => Version_5_1,
            '11.0' => Version_5_1
          }

          if @version.start_with?('0.9') ||
             @version.start_with?('1.0') ||
             @version.start_with?('1.5')
            # We only support vCloud Air 5.1 or higher.
            fail Errors::VCloudAirOldVersion, :version => @version
          end

          driver_klass = nil
          driver_map.each do |key, klass|
            if @version.start_with?(key)
              driver_klass = klass
              break
            end
          end

          unless driver_klass
            supported_versions = driver_map.keys.sort.join(', ')
            fail Errors::VCloudAirInvalidVersion,
                 :supported_versions => supported_versions
          end

          @logger.info("Using vCloud Air driver: #{driver_klass}")
          @driver = driver_klass.new(@api_url, @host_url, @auth_key, @org_name)
        end

        def_delegators  :@driver,
                        :login,
                        :logout,
                        :get_organizations,
                        :get_organization_id_by_name,
                        :get_organization_by_name,
                        :get_organization,
                        :get_catalog,
                        :get_catalog_id_by_name,
                        :get_catalog_by_name,
                        :get_vdc,
                        :get_vdc_id_by_name,
                        :get_vdc_by_name,
                        :get_catalog_item,
                        :get_catalog_item_by_name,
                        :get_vapp,
                        :delete_vapp,
                        :poweroff_vapp,
                        :suspend_vapp,
                        :reboot_vapp,
                        :reset_vapp,
                        :poweron_vapp,
                        :create_vapp_from_template,
                        :compose_vapp_from_vm,
                        :get_vapp_template,
                        :set_vapp_port_forwarding_rules,
                        :get_vapp_port_forwarding_rules,
                        :get_vapp_edge_public_ip,
                        :upload_ovf,
                        :get_task,
                        :wait_task_completion,
                        :set_vapp_network_config,
                        :set_vm_network_config,
                        :set_vm_guest_customization,
                        :get_vm,
                        :send_request,
                        :upload_file,
                        :convert_vapp_status

        protected

      end
    end
  end
end