pax_global_header00006660000000000000000000000064126340354300014512gustar00rootroot0000000000000052 comment=7a6cf0334b5d7fb4dffcd8f899a546dc4a5bdb32 fog-vsphere-0.4.0/000077500000000000000000000000001263403543000137405ustar00rootroot00000000000000fog-vsphere-0.4.0/.gitignore000066400000000000000000000003101263403543000157220ustar00rootroot00000000000000*.gem *.rbc .bundle .config .yardoc Gemfile.lock InstalledFiles _yardoc coverage doc/ lib/bundler/man pkg rdoc spec/reports test/tmp test/version_tmp tmp *.bundle *.so *.o *.a mkmf.log gemfiles/*.lockfog-vsphere-0.4.0/.travis.yml000066400000000000000000000011321263403543000160460ustar00rootroot00000000000000language: ruby sudo: false before_install: gem install bundler matrix: allow_failures: - rvm: jruby-head fast_finish: true include: - rvm: 1.9.3 gemfile: gemfiles/Gemfile.1.9.2+ - rvm: 2.0.0 gemfile: Gemfile - rvm: 2.1.0 gemfile: Gemfile - rvm: 2.1.1 gemfile: Gemfile - rvm: 2.2.0 gemfile: Gemfile - rvm: jruby-19mode gemfile: gemfiles/Gemfile.1.9.2+ - rvm: jruby-head gemfile: Gemfile notifications: email: false addons: code_climate: repo_token: 44bcd04b60228fc94f2be3a5e0346441b5ea156e94e89a17fc24c5d3de483721 fog-vsphere-0.4.0/CHANGELOG.md000066400000000000000000000010541263403543000155510ustar00rootroot00000000000000## v0.4.0 12/15/2015 * Fix cannot create vm on "Resources" resource pool * Fix Fog::Mock.reset * Implement support for DRS rules * Fix issues with boot options * Add boot retry support * Add support for annotation and extra_config ## v0.3.0 12/3/2015 * Fix update_vm_interface * Add add folder.destroy * Implement CD-ROM options * Implement storage pods * Fix nil error when snapshots is called on a VM without snapshots * No longer support Ruby 1.8 * Allow setting of boot order when using api > 5.0 * Select the most recent API version instead of 4.1 fog-vsphere-0.4.0/CONTRIBUTING.md000066400000000000000000000015421263403543000161730ustar00rootroot00000000000000## Getting Involved New contributors are always welcome, when it doubt please ask questions. We strive to be an open and welcoming community. Please be nice to one another. ### Coding * Pick a task: * Offer feedback on open [pull requests](https://github.com/fog/fog-vsphere/pulls). * Review open [issues](https://github.com/fog/fog-vsphere/issues) for things to help on. * [Create an issue](https://github.com/fog/fog-vsphere/issues/new) to start a discussion on additions or features. * Fork the project, add your changes and tests to cover them in a topic branch. * Commit your changes and rebase against `fog/fog-vsphere` to ensure everything is up to date. * [Submit a pull request](https://github.com/fog/fog-vsphere/compare/) ### Non-Coding * Offer feedback on open [issues](https://github.com/fog/fog-vsphere/issues). * Organize or volunteer at events. fog-vsphere-0.4.0/CONTRIBUTORS.md000066400000000000000000000047641263403543000162320ustar00rootroot00000000000000* Ahmed Elsabbahy * Alan Sebastian * Carl Caum * Carlos Sanchez * Chris Thompson * Chris Thompson * Christopher Oliver * Cyrus Team * Darren Foo * Dominic Cleal * Eric Stonfer * Ewoud Kohl van Wijngaarden * Francois Herbert * Francois Herbert * Francois Herbert * Ivan Nečas * Ivo Reznicek * J.R. Garcia * J.R. Garcia * James Herdman * Jeff McCune * Justin Clayton * Justin Pratt * Justin Pratt * Karan Misra * Kelsey Hightower * Kevin Menard * Kevin Menard * Lance Ivy * Lukas Zapletal * Marc Grimme * Marc Grimme * Martin Matuska * Matt Darby * Matthew Black * Matthew Black * Michael Moll * Mick Pollard * Ming Jin * Nick Huanca * Nick Huanca * Nick Huanuca * Ohad Levy * Ohad Levy * Oscar Elfving * Paul Thornthwaite * Paul Thornthwaite * Paulo Henrique Lopes Ribeiro * Rich Daley * Rich Lane * Samuel Keeley * Shlomi Zadok * Simon Josi * Tejas Ravindra Mandke * Timo Goebel * Timur Alperovich * Wesley Beary * Wesley Beary * Xavier Fontrodona * alan * endzyme * geemus * karmab * slivik * tipt0e fog-vsphere-0.4.0/Gemfile000066400000000000000000000001441263403543000152320ustar00rootroot00000000000000source 'https://rubygems.org' gem 'codeclimate-test-reporter', group: :test, require: nil gemspec fog-vsphere-0.4.0/LICENSE.md000066400000000000000000000021221263403543000153410ustar00rootroot00000000000000The MIT License (MIT) Copyright (c) 2014-2015 [CONTRIBUTORS.md](CONTRIBUTORS.md) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. fog-vsphere-0.4.0/README.md000066400000000000000000000023401263403543000152160ustar00rootroot00000000000000# Fog::Vsphere [![Gem Version](https://badge.fury.io/rb/fog-vsphere.svg)](http://badge.fury.io/rb/fog-vsphere) [![Build Status](https://travis-ci.org/fog/fog-vsphere.svg?branch=master)](https://travis-ci.org/fog/fog-vsphere) [![Dependency Status](https://gemnasium.com/fog/fog-vsphere.svg)](https://gemnasium.com/fog/fog-vsphere) [![Test Coverage](https://codeclimate.com/github/fog/fog-vsphere/badges/coverage.svg)](https://codeclimate.com/github/fog/fog-vsphere/coverage) [![Code Climate](https://codeclimate.com/github/fog/fog-vsphere.png)](https://codeclimate.com/github/fog/fog-vsphere) [![Stories in Ready](https://badge.waffle.io/fog/fog-vsphere.png?label=ready&title=Ready)](https://waffle.io/fog/fog-vsphere) TODO: Write a gem description ## Installation Add this line to your application's Gemfile: gem 'fog-vsphere' And then execute: $ bundle Or install it yourself as: $ gem install fog-vsphere ## Usage TODO: Write usage instructions here ## Contributing 1. Fork it ( https://github.com/fog/fog-vsphere/fork ) 2. Create your feature branch (`git checkout -b my-new-feature`) 3. Commit your changes (`git commit -am 'Add some feature'`) 4. Push to the branch (`git push origin my-new-feature`) 5. Create a new Pull Request fog-vsphere-0.4.0/Rakefile000066400000000000000000000002431263403543000154040ustar00rootroot00000000000000require 'bundler/gem_tasks' mock = ENV['FOG_MOCK'] || 'true' task :test do sh("export FOG_MOCK=#{mock} && bundle exec shindont") end task(:default => [:test]) fog-vsphere-0.4.0/fog-vsphere.gemspec000066400000000000000000000022411263403543000175310ustar00rootroot00000000000000# coding: utf-8 lib = File.expand_path('../lib', __FILE__) $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) require 'fog/vsphere/version' Gem::Specification.new do |spec| spec.name = 'fog-vsphere' spec.version = Fog::Vsphere::VERSION spec.authors = ['J.R. Garcia'] spec.email = ['jrg@vmware.com'] spec.summary = "Module for the 'fog' gem to support VMware vSphere." spec.description = 'This library can be used as a module for `fog` or as standalone provider to use vSphere in applications.' spec.homepage = 'https://github.com/fog/fog-vsphere' spec.license = 'MIT' spec.files = `git ls-files -z`.split("\x0") spec.test_files = spec.files.grep(%r{^tests\/}) spec.require_paths = ['lib'] spec.required_ruby_version = '>= 1.8.7' spec.add_runtime_dependency 'fog-core' spec.add_runtime_dependency 'rbvmomi', '~> 1.8' spec.add_development_dependency 'bundler', '~> 1.10' spec.add_development_dependency 'pry', '~> 0.10' spec.add_development_dependency 'rake', '~> 10.0' spec.add_development_dependency 'rubocop', '~> 0.34' spec.add_development_dependency 'shindo', '~> 0.3' end fog-vsphere-0.4.0/gemfiles/000077500000000000000000000000001263403543000155335ustar00rootroot00000000000000fog-vsphere-0.4.0/gemfiles/Gemfile.1.9.2+000066400000000000000000000002441263403543000175470ustar00rootroot00000000000000source 'https://rubygems.org' gem 'codeclimate-test-reporter', group: :test, require: nil gem 'net-ssh', '~> 2.9' gem 'rubocop', '~> 0.34' gemspec :path => '..' fog-vsphere-0.4.0/gemfiles/Gemfile.1.9.2-000066400000000000000000000003561263403543000175550ustar00rootroot00000000000000source 'https://rubygems.org' gem 'mime-types', '~> 1.25' gem 'net-ssh', '~> 2.9' gem 'nokogiri', '~> 1.5.11' gem 'rainbow', '~> 1.99' gem 'rest-client', '~> 1.6.8' gem 'rubocop', '~> 0.5.0' gem 'tins', '~> 1.6.0' gemspec :path => '..' fog-vsphere-0.4.0/lib/000077500000000000000000000000001263403543000145065ustar00rootroot00000000000000fog-vsphere-0.4.0/lib/fog/000077500000000000000000000000001263403543000152615ustar00rootroot00000000000000fog-vsphere-0.4.0/lib/fog/bin/000077500000000000000000000000001263403543000160315ustar00rootroot00000000000000fog-vsphere-0.4.0/lib/fog/bin/vsphere.rb000066400000000000000000000012171263403543000200330ustar00rootroot00000000000000class Vsphere < Fog::Bin class << self def class_for(key) case key when :compute Fog::Compute::Vsphere else raise ArgumentError, "Unrecognized service: #{key}" end end def [](service) @@connections ||= Hash.new do |hash, key| hash[key] = case key when :compute Fog::Compute.new(:provider => 'Vsphere') else raise ArgumentError, "Unrecognized service: #{key.inspect}" end end @@connections[service] end def services Fog::Vsphere.services end end end fog-vsphere-0.4.0/lib/fog/vsphere.rb000066400000000000000000000022371263403543000172660ustar00rootroot00000000000000require 'fog/core' module Fog module Compute autoload :Vsphere, File.expand_path('../vsphere/compute.rb', __FILE__) end module Vsphere extend Fog::Provider module Errors class ServiceError < Fog::Errors::Error; end class SecurityError < ServiceError; end class NotFound < ServiceError; end end service(:compute, 'Compute') # This helper was originally added as Fog.class_as_string and moved to core but only used here def self.class_from_string classname, defaultpath="" if classname and classname.is_a? String then chain = classname.split("::") klass = Kernel chain.each do |klass_string| klass = klass.const_get klass_string end if klass.is_a? Class then klass elsif defaultpath != nil then class_from_string((defaultpath.split("::")+chain).join("::"), nil) else nil end elsif classname and classname.is_a? Class then classname else nil end rescue NameError defaultpath != nil ? class_from_string((defaultpath.split("::")+chain).join("::"), nil) : nil end end end fog-vsphere-0.4.0/lib/fog/vsphere/000077500000000000000000000000001263403543000167355ustar00rootroot00000000000000fog-vsphere-0.4.0/lib/fog/vsphere/compute.rb000066400000000000000000000551671263403543000207540ustar00rootroot00000000000000require 'digest/sha2' module Fog module Compute class Vsphere < Fog::Service requires :vsphere_username, :vsphere_password, :vsphere_server recognizes :vsphere_port, :vsphere_path, :vsphere_ns recognizes :vsphere_rev, :vsphere_ssl, :vsphere_expected_pubkey_hash recognizes :vsphere_debug model_path 'fog/vsphere/models/compute' model :server collection :servers model :servertype collection :servertypes model :datacenter collection :datacenters model :interface collection :interfaces model :interfacetype collection :interfacetypes model :volume collection :volumes model :snapshot collection :snapshots model :template collection :templates model :cluster collection :clusters model :resource_pool collection :resource_pools model :network collection :networks model :datastore collection :datastores model :storage_pod collection :storage_pods model :folder collection :folders model :customvalue collection :customvalues model :customfield collection :customfields model :scsicontroller model :process model :cdrom collection :cdroms model :rule collection :rules request_path 'fog/vsphere/requests/compute' request :current_time request :cloudinit_to_customspec request :list_virtual_machines request :vm_power_off request :vm_power_on request :vm_reboot request :vm_clone request :vm_destroy request :vm_migrate request :vm_execute request :list_datacenters request :get_datacenter request :list_clusters request :get_cluster request :list_resource_pools request :get_resource_pool request :list_networks request :get_network request :list_datastores request :get_datastore request :list_storage_pods request :get_storage_pod request :list_compute_resources request :get_compute_resource request :list_templates request :get_template request :get_folder request :list_folders request :create_vm request :list_vm_interfaces request :modify_vm_interface request :modify_vm_volume request :modify_vm_cdrom request :list_vm_volumes request :list_vm_cdroms request :get_virtual_machine request :vm_reconfig_hardware request :vm_reconfig_memory request :vm_reconfig_cpus request :vm_reconfig_cdrom request :vm_config_vnc request :create_folder request :list_server_types request :get_server_type request :list_interface_types request :get_interface_type request :list_vm_customvalues request :list_customfields request :get_vm_first_scsi_controller request :set_vm_customvalue request :vm_take_snapshot request :list_vm_snapshots request :list_child_snapshots request :revert_to_snapshot request :list_processes request :upload_iso request :folder_destroy request :create_rule request :list_rules request :destroy_rule module Shared attr_reader :vsphere_is_vcenter attr_reader :vsphere_rev attr_reader :vsphere_server attr_reader :vsphere_username protected ATTR_TO_PROP = { :id => 'config.instanceUuid', :name => 'name', :uuid => 'config.uuid', :template => 'config.template', :parent => 'parent', :hostname => 'summary.guest.hostName', :operatingsystem => 'summary.guest.guestFullName', :ipaddress => 'guest.ipAddress', :power_state => 'runtime.powerState', :connection_state => 'runtime.connectionState', :hypervisor => 'runtime.host', :tools_state => 'guest.toolsStatus', :tools_version => 'guest.toolsVersionStatus', :memory_mb => 'config.hardware.memoryMB', :cpus => 'config.hardware.numCPU', :corespersocket => 'config.hardware.numCoresPerSocket', :overall_status => 'overallStatus', :guest_id => 'config.guestId', :hardware_version => 'config.version', :cpuHotAddEnabled => 'config.cpuHotAddEnabled', :memoryHotAddEnabled => 'config.memoryHotAddEnabled', :firmware => 'config.firmware', :annotation => 'config.annotation', } def convert_vm_view_to_attr_hash(vms) vms = @connection.serviceContent.propertyCollector.collectMultiple(vms,*ATTR_TO_PROP.values.uniq) vms.map { |vm| props_to_attr_hash(*vm) } end # Utility method to convert a VMware managed object into an attribute hash. # This should only really be necessary for the real class. # This method is expected to be called by the request methods # in order to massage VMware Managed Object References into Attribute Hashes. def convert_vm_mob_ref_to_attr_hash(vm_mob_ref) return nil unless vm_mob_ref props = vm_mob_ref.collect!(*ATTR_TO_PROP.values.uniq) props_to_attr_hash vm_mob_ref, props end def props_to_attr_hash vm_mob_ref, props # NOTE: Object.tap is in 1.8.7 and later. # Here we create the hash object that this method returns, but first we need # to add a few more attributes that require additional calls to the vSphere # API. The hypervisor name and mac_addresses attributes may not be available # so we need catch any exceptions thrown during lookup and set them to nil. # # The use of the "tap" method here is a convenience, it allows us to update the # hash object without explicitly returning the hash at the end of the method. Hash[ATTR_TO_PROP.map { |k,v| [k.to_s, props[v]] }].tap do |attrs| attrs['id'] ||= vm_mob_ref._ref attrs['mo_ref'] = vm_mob_ref._ref # The name method "magically" appears after a VM is ready and # finished cloning. if attrs['hypervisor'].kind_of?(RbVmomi::VIM::HostSystem) host = attrs['hypervisor'] attrs['datacenter'] = Proc.new { parent_attribute(host.path, :datacenter)[1] rescue nil } attrs['cluster'] = Proc.new { parent_attribute(host.path, :cluster)[1] rescue nil } attrs['hypervisor'] = Proc.new { host.name rescue nil } attrs['resource_pool'] = Proc.new {(vm_mob_ref.resourcePool || host.resourcePool).name rescue nil} end # This inline rescue catches any standard error. While a VM is # cloning, a call to the macs method will throw and NoMethodError attrs['mac_addresses'] = Proc.new {vm_mob_ref.macs rescue nil} # Rescue nil to catch testing while vm_mob_ref isn't reaL?? attrs['path'] = "/"+attrs['parent'].path.map(&:last).join('/') rescue nil end end # returns the parent object based on a type # provides both real RbVmomi object and its name. # e.g. #[Datacenter("datacenter-2"), "dc-name"] def parent_attribute path, type element = case type when :datacenter RbVmomi::VIM::Datacenter when :cluster RbVmomi::VIM::ClusterComputeResource when :host RbVmomi::VIM::HostSystem else raise "Unknown type" end path.select {|x| x[0].is_a? element}.flatten rescue nil end # returns vmware managed obj id string def managed_obj_id obj obj.to_s.match(/\("([^"]+)"\)/)[1] end def is_uuid?(id) !(id =~ /[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}/).nil? end end class Mock include Shared def self.data @data ||= Hash.new do |hash, key| hash[key] = { :servers => { "5032c8a5-9c5e-ba7a-3804-832a03e16381" => { "resource_pool" => "Resources", "memory_mb" => 2196, "mac_addresses" => { "Network adapter 1" => "00:50:56:a9:00:28" }, "power_state" => "poweredOn", "cpus" => 1, "hostname" => "dhcp75-197.virt.bos.redhat.com", "mo_ref" => "vm-562", "connection_state" => "connected", "overall_status" => "green", "datacenter" => "Solutions", "volumes" => [{ "id" => "6000C29c-a47d-4cd9-5249-c371de775f06", "datastore" => "Storage1", "mode" => "persistent", "size" => 8388608, "thin" => true, "name" => "Hard disk 1", "filename" => "[Storage1] rhel6-mfojtik/rhel6-mfojtik.vmdk", "size_gb" => 8 }], "interfaces" => [{"mac" => "00:50:56:a9:00:28", "network" => "VM Network", "name" => "Network adapter 1", "status" => "ok", "summary" => "VM Network", }], "cdroms" => [{ "name" => "CD-/DVD-Drive 1", "filename" => nil, "key" => 3000, "controller_key" => 200, "unit_number" => 0, "start_connected" => false, "allow_guest_control" => true, "connected" => false, }], "hypervisor" => "gunab.puppetlabs.lan", "guest_id" => "rhel6_64Guest", "tools_state" => "toolsOk", "cluster" => "Solutionscluster", "name" => "rhel64", "operatingsystem" => "Red Hat Enterprise Linux 6 (64-bit)", "path" => "/Datacenters/Solutions/vm", "uuid" => "4229f0e9-bfdc-d9a7-7bac-12070772e6dc", "instance_uuid" => "5032c8a5-9c5e-ba7a-3804-832a03e16381", "id" => "5032c8a5-9c5e-ba7a-3804-832a03e16381", "tools_version" => "guestToolsUnmanaged", "ipaddress" => "192.168.100.184", "template" => false }, "502916a3-b42e-17c7-43ce-b3206e9524dc" => { "resource_pool" => "Resources", "memory_mb" => 512, "power_state" => "poweredOn", "mac_addresses" => { "Network adapter 1" => "00:50:56:a9:00:00" }, "hostname" => nil, "cpus" => 1, "connection_state" => "connected", "mo_ref" => "vm-621", "overall_status" => "green", "datacenter" => "Solutions", "volumes" => [{"thin" => false, "size_gb" => 10, "datastore" => "datastore1", "filename" => "[datastore1] i-1342439683/i-1342439683.vmdk", "size" => 10485762, "name" => "Hard disk 1", "mode" => "persistent", "id" => "6000C29b-f364-d073-8316-8e98ac0a0eae" }], "interfaces" => [{ "summary" => "VM Network", "mac" => "00:50:56:a9:00:00", "status" => "ok", "network" => "VM Network", "name" => "Network adapter 1" }], "hypervisor" => "gunab.puppetlabs.lan", "guest_id" => nil, "cluster" => "Solutionscluster", "tools_state" => "toolsNotInstalled", "name" => "i-1342439683", "operatingsystem" => nil, "path" => "/", "tools_version" => "guestToolsNotInstalled", "uuid" => "4229e0de-30cb-ceb2-21f9-4d8d8beabb52", "instance_uuid" => "502916a3-b42e-17c7-43ce-b3206e9524dc", "id" => "502916a3-b42e-17c7-43ce-b3206e9524dc", "ipaddress" => nil, "template" => false }, "5029c440-85ee-c2a1-e9dd-b63e39364603" => { "resource_pool" => "Resources", "memory_mb" => 2196, "power_state" => "poweredOn", "mac_addresses" => { "Network adapter 1" => "00:50:56:b2:00:af" }, "hostname" => "centos56gm.localdomain", "cpus" => 1, "connection_state" => "connected", "mo_ref" => "vm-715", "overall_status" => "green", "datacenter" => "Solutions", "hypervisor" => "gunab.puppetlabs.lan", "guest_id" => "rhel6_64Guest", "cluster" => "Solutionscluster", "tools_state" => "toolsOk", "name" => "jefftest", "operatingsystem" => "Red Hat Enterprise Linux 6 (64-bit)", "path" => "/Solutions/wibble", "tools_version" => "guestToolsUnmanaged", "ipaddress" => "192.168.100.187", "uuid" => "42329da7-e8ab-29ec-1892-d6a4a964912a", "instance_uuid" => "5029c440-85ee-c2a1-e9dd-b63e39364603", "id" => "5029c440-85ee-c2a1-e9dd-b63e39364603", "template" => false } }, :datacenters => { "Solutions" => {:name => "Solutions", :status => "grey", :path => ['Solutions']} }, :folders => { 'wibble' => { 'name' => 'wibble', 'datacenter' => 'Solutions', 'path' => '/Solutions/wibble', 'type' => 'vm' }, 'empty' => { 'name' => 'empty', 'datacenter' => 'Solutions', 'path' => '/Solutions/empty', 'type' => 'vm' } }, :storage_pods => [{:id => "group-p123456", :name => "Datastore Cluster 1", :freespace => "4856891834368", :capacity => "7132061630464", :datacenter => "Solutions", }, ], :clusters => [{:id => "1d4d9a3f-e4e8-4c40-b7fc-263850068fa4", :name => "Solutionscluster", :num_host => "4", :num_cpu_cores => "16", :overall_status => "green", :datacenter => "Solutions", :klass => "RbVmomi::VIM::ComputeResource" }, {:id => "e4195973-102b-4096-bbd6-5429ff0b35c9", :name => "Problemscluster", :num_host => "4", :num_cpu_cores => "32", :overall_status => "green", :datacenter => "Solutions", :klass => "RbVmomi::VIM::ComputeResource" }, { :klass => "RbVmomi::VIM::Folder", :clusters => [{:id => "03616b8d-b707-41fd-b3b5-The first", :name => "Problemscluster", :num_host => "4", :num_cpu_cores => "32", :overall_status => "green", :datacenter => "Solutions", :klass => "RbVmomi::VIM::ComputeResource" }, {:id => "03616b8d-b707-41fd-b3b5-the Second", :name => "Lastcluster", :num_host => "8", :num_cpu_cores => "32", :overall_status => "green", :datacenter => "Solutions", :klass => "RbVmomi::VIM::ComputeResource"} ] } ], :rules => { 'anti-affinity-foo' => { :datacenter => 'Solutions', :cluster => 'Solutionscluster', :key => 4242, :name => 'anti-affinity-foo', :enabled => true, :type => RbVmomi::VIM::ClusterAntiAffinityRuleSpec, :vm_ids => ['5032c8a5-9c5e-ba7a-3804-832a03e16381', '502916a3-b42e-17c7-43ce-b3206e9524dc'] } } } end end def initialize(options={}) require 'rbvmomi' @vsphere_username = options[:vsphere_username] @vsphere_password = 'REDACTED' @vsphere_server = options[:vsphere_server] @vsphere_expected_pubkey_hash = options[:vsphere_expected_pubkey_hash] @vsphere_is_vcenter = true @vsphere_rev = '4.0' end def data self.class.data[@vsphere_username] end def reset_data self.class.data.delete(@vsphere_username) end end class Real include Shared def initialize(options={}) require 'rbvmomi' @vsphere_username = options[:vsphere_username] @vsphere_password = options[:vsphere_password] @vsphere_server = options[:vsphere_server] @vsphere_port = options[:vsphere_port] || 443 @vsphere_path = options[:vsphere_path] || '/sdk' @vsphere_ns = options[:vsphere_ns] || 'urn:vim25' @vsphere_rev = options[:vsphere_rev] || '4.0' @vsphere_ssl = options[:vsphere_ssl] || true @vsphere_debug = options[:vsphere_debug] || false @vsphere_expected_pubkey_hash = options[:vsphere_expected_pubkey_hash] @vsphere_must_reauthenticate = false @vsphere_is_vcenter = nil @connection = nil connect negotiate_revision(options[:vsphere_rev]) authenticate end def reload connect # Check if the negotiation was ever run if @vsphere_is_vcenter.nil? negotiate end authenticate end private def negotiate_revision(revision = nil) # Negotiate the API revision if not revision rev = @connection.serviceContent.about.apiVersion @connection.rev = [ rev, ENV['FOG_VSPHERE_REV'] || '4.1' ].max end @vsphere_is_vcenter = @connection.serviceContent.about.apiType == "VirtualCenter" @vsphere_rev = @connection.rev end def connect # This is a state variable to allow digest validation of the SSL cert bad_cert = false loop do begin @connection = RbVmomi::VIM.new :host => @vsphere_server, :port => @vsphere_port, :path => @vsphere_path, :ns => @vsphere_ns, :rev => @vsphere_rev, :ssl => @vsphere_ssl, :insecure => bad_cert, :debug => @vsphere_debug # Create a shadow class to change the behaviour of @connection.obj2xml # so that xsd:any types are converted to xsd:int (and not xsd:long). # # This is a known issue with RbVmomi. # # See https://communities.vmware.com/message/2505334 for discussion # and https://github.com/rlane/rbvmomi/pull/30 for an unmerged # pull request that fixes it in RbVmomi. # class <<@connection def obj2xml xml, name, type, is_array, o, attrs={} case o when Integer attrs['xsi:type'] = 'xsd:int' if type(type) == RbVmomi::BasicTypes::AnyType xml.tag! name, o.to_s, attrs xml else super xml, name, type, is_array, o, attrs end end end break rescue OpenSSL::SSL::SSLError raise if bad_cert bad_cert = true end end if bad_cert then validate_ssl_connection end end def authenticate begin @connection.serviceContent.sessionManager.Login :userName => @vsphere_username, :password => @vsphere_password rescue RbVmomi::VIM::InvalidLogin => e raise Fog::Vsphere::Errors::ServiceError, e.message end end # Verify a SSL certificate based on the hashed public key def validate_ssl_connection pubkey = @connection.http.peer_cert.public_key pubkey_hash = Digest::SHA2.hexdigest(pubkey.to_s) expected_pubkey_hash = @vsphere_expected_pubkey_hash if pubkey_hash != expected_pubkey_hash then raise Fog::Vsphere::Errors::SecurityError, "The remote system presented a public key with hash #{pubkey_hash} but we're expecting a hash of #{expected_pubkey_hash || ''}. If you are sure the remote system is authentic set vsphere_expected_pubkey_hash: in ~/.fog" end end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/models/000077500000000000000000000000001263403543000202205ustar00rootroot00000000000000fog-vsphere-0.4.0/lib/fog/vsphere/models/compute/000077500000000000000000000000001263403543000216745ustar00rootroot00000000000000fog-vsphere-0.4.0/lib/fog/vsphere/models/compute/cdrom.rb000066400000000000000000000036221263403543000233300ustar00rootroot00000000000000module Fog module Compute class Vsphere class Cdrom < Fog::Model identity :key attribute :filename attribute :name, :default => "CD-/DVD-ROM Drive" attribute :controller_key attribute :unit_number attribute :start_connected attribute :allow_guest_control attribute :connected has_one_identity :server, :servers, :aliases => :instance_uuid def to_s name end def destroy requires :instance_uuid, :key, :unit_number service.destroy_vm_cdrom(self) true end def save requires :instance_uuid if unit_number.nil? used_unit_numbers = server.cdroms.map { |cdrom| cdrom.unit_number } max_unit_number = used_unit_numbers.max if max_unit_number > server.cdroms.size # If the max ID exceeds the number of cdroms, there must be a hole in the range. Find a hole and use it. self.unit_number = max_unit_number.times.to_a.find { |i| used_unit_numbers.exclude?(i) } else self.unit_number = max_unit_number + 1 end else if server.cdroms.any? { |cdrom| cdrom.unit_number == self.unit_number && cdrom.id != self.id } raise "A cdrom already exists with that unit_number, so we can't save the new cdrom" end end data = service.add_vm_cdrom(self) if data['task_state'] == 'success' # We have to query vSphere to get the cdrom attributes since the task handle doesn't include that info. created = server.cdroms.get(unit_number) self.key = created.key self.filename = created.filename self.unit_number = created.unit_number true else false end end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/models/compute/cdroms.rb000066400000000000000000000006331263403543000235120ustar00rootroot00000000000000module Fog module Compute class Vsphere class Cdroms < Fog::Collection attribute :instance_uuid, :alias => :server_id model Fog::Compute::Vsphere::Cdrom def all(filters = {}) load service.list_vm_cdroms(instance_uuid) end def get(unit_number) all.find { |cdrom| cdrom.unit_number == unit_number } end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/models/compute/cluster.rb000066400000000000000000000020261263403543000237020ustar00rootroot00000000000000module Fog module Compute class Vsphere class Cluster < Fog::Model identity :id attribute :name attribute :datacenter attribute :num_host attribute :num_cpu_cores attribute :overall_status attribute :full_path def resource_pools(filters = { }) self.attributes[:resource_pools] ||= id.nil? ? [] : service.resource_pools({ :service => service, :cluster => name, :datacenter => datacenter }.merge(filters)) end def rules service.rules(:datacenter => datacenter, :cluster => name) end def to_s name end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/models/compute/clusters.rb000066400000000000000000000010201263403543000240560ustar00rootroot00000000000000module Fog module Compute class Vsphere class Clusters < Fog::Collection autoload :Cluster, File.expand_path('../cluster', __FILE__) model Fog::Compute::Vsphere::Cluster attr_accessor :datacenter def all(filters = {}) requires :datacenter load service.list_clusters(filters.merge(:datacenter => datacenter)) end def get(id) requires :datacenter new service.get_cluster(id, datacenter) end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/models/compute/customfield.rb000066400000000000000000000003431263403543000245370ustar00rootroot00000000000000module Fog module Compute class Vsphere class Customfield < Fog::Model identity :key attribute :name attribute :type def to_s name end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/models/compute/customfields.rb000066400000000000000000000010121263403543000247140ustar00rootroot00000000000000module Fog module Compute class Vsphere class Customfields < Fog::Collection autoload :Customfield, File.expand_path('../customfield', __FILE__) model Fog::Compute::Vsphere::Customfield attr_accessor :vm def all(filters = {}) load service.list_customfields() end def get(key) load(service.list_customfields()).find do | cv | cv.key == ((key.is_a? String) ? key.to_i : key) end end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/models/compute/customvalue.rb000066400000000000000000000003151263403543000245670ustar00rootroot00000000000000module Fog module Compute class Vsphere class Customvalue < Fog::Model attribute :value attribute :key def to_s value end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/models/compute/customvalues.rb000066400000000000000000000014641263403543000247600ustar00rootroot00000000000000module Fog module Compute class Vsphere class Customvalues < Fog::Collection autoload :Customvalue, File.expand_path('../customvalue', __FILE__) model Fog::Compute::Vsphere::Customvalue attr_accessor :vm def all(filters = {}) requires :vm case vm when Fog::Compute::Vsphere::Server load service.list_vm_customvalues(vm.id) else raise 'customvalues should have vm' end end def get(key) requires :vm case vm when Fog::Compute::Vsphere::Server load service.list_vm_customvalues(vm.id) else raise 'customvalues should have vm' end.find { | cv | cv.key == key } end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/models/compute/datacenter.rb000066400000000000000000000024011263403543000243300ustar00rootroot00000000000000module Fog module Compute class Vsphere class Datacenter < Fog::Model identity :id attribute :name attribute :path attribute :status def clusters filters = { } service.clusters({ :datacenter => path.join("/") }.merge(filters)) end def networks filters = { } service.networks({ :datacenter => path.join("/") }.merge(filters)) end def datastores filters = { } service.datastores({ :datacenter => path.join("/") }.merge(filters)) end def storage_pods filters = { } service.storage_pods({ :datacenter => path.join("/") }.merge(filters)) end def vm_folders filters = { } service.folders({ :datacenter => path.join("/"), :type => :vm }.merge(filters)) end def virtual_machines filters = {} service.servers({ :datacenter => path.join("/") }.merge(filters)) end def servertypes filters={} service.servertypes({:datacenter => name }.merge(filters)) end def customfields filters = {} service.customfields({ :datacenter => path.join("/")}.merge(filters)) end def to_s name end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/models/compute/datacenters.rb000066400000000000000000000006311263403543000245160ustar00rootroot00000000000000module Fog module Compute class Vsphere class Datacenters < Fog::Collection autoload :Datacenter, File.expand_path('../datacenter', __FILE__) model Fog::Compute::Vsphere::Datacenter def all(filters = {}) load service.list_datacenters(filters) end def get(name) new service.get_datacenter(name) end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/models/compute/datastore.rb000066400000000000000000000006331263403543000242110ustar00rootroot00000000000000module Fog module Compute class Vsphere class Datastore < Fog::Model identity :id attribute :name attribute :datacenter attribute :type attribute :freespace attribute :accessible # reachable by at least one hypervisor attribute :capacity attribute :uncommitted def to_s name end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/models/compute/datastores.rb000066400000000000000000000007751263403543000244030ustar00rootroot00000000000000module Fog module Compute class Vsphere class Datastores < Fog::Collection autoload :Datastore, File.expand_path('../datastore', __FILE__) model Fog::Compute::Vsphere::Datastore attr_accessor :datacenter def all(filters = {}) load service.list_datastores(filters.merge(:datacenter => datacenter)) end def get(id) requires :datacenter new service.get_datastore(id, datacenter) end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/models/compute/folder.rb000066400000000000000000000010251263403543000234720ustar00rootroot00000000000000module Fog module Compute class Vsphere class Folder < Fog::Model identity :id attribute :name attribute :parent attribute :datacenter attribute :path attribute :type def vms return [] if type.to_s != 'vm' service.servers(:folder => path, :datacenter => datacenter) end def to_s name end def destroy service.folder_destroy(path, datacenter) end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/models/compute/folders.rb000066400000000000000000000011261263403543000236570ustar00rootroot00000000000000module Fog module Compute class Vsphere class Folders < Fog::Collection autoload :Folder, File.expand_path('../folder', __FILE__) model Fog::Compute::Vsphere::Folder attr_accessor :datacenter, :type, :path def all(filters = { }) requires :datacenter requires :type load service.list_folders(filters.merge(:datacenter => datacenter, :type => type, :path => path)) end def get(id) requires :datacenter new service.get_folder(id, datacenter, type) end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/models/compute/interface.rb000066400000000000000000000053431263403543000241660ustar00rootroot00000000000000module Fog module Compute class Vsphere class Interface < Fog::Model SAVE_MUTEX = Mutex.new identity :mac alias_method :id, :mac attribute :network attribute :name attribute :status attribute :summary attribute :type attribute :key attribute :virtualswitch attribute :server_id def initialize(attributes = {}) # Assign server first to prevent race condition with persisted? self.server_id = attributes.delete(:server_id) if attributes.key? :type then if attributes[:type].is_a? String then attributes[:type] = Fog::Vsphere.class_from_string(attributes[:type], "RbVmomi::VIM") end else attributes[:type] = Fog::Vsphere.class_from_string("VirtualE1000", "RbVmomi::VIM") end super defaults.merge(attributes) end def to_s name end def server requires :server_id service.servers.get(server_id) end def destroy requires :server_id, :key, :type service.destroy_vm_interface(server_id, :key => key, :type => type) end def save raise Fog::Errors::Error.new('Resaving an existing object may create a duplicate') if persisted? requires :server_id, :type, :network # Our approach of finding the newly created interface is rough. We assume that the :key value always increments # and thus the highest :key value must correspond to the created interface. Since this has an inherent race # condition we need to gate the saves. SAVE_MUTEX.synchronize do data = service.add_vm_interface(server_id, attributes) if data['task_state'] == 'success' # We have to query vSphere to get the interface attributes since the task handle doesn't include that info. created = server.interfaces.all.sort_by(&:key).last self.mac = created.mac self.name = created.name self.status = created.status self.summary = created.summary self.key = created.key self.virtualswitch = created.virtualswitch true else false end end end private def defaults default_type=Fog.credentials[:default_nic_type] || RbVmomi::VIM::VirtualE1000 { :name=>"Network adapter", :network=>"VM Network", :summary=>"VM Network", :type=> Fog::Vsphere.class_from_string(default_type, "RbVmomi::VIM"), } end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/models/compute/interfaces.rb000066400000000000000000000033651263403543000243530ustar00rootroot00000000000000module Fog module Compute class Vsphere class Interfaces < Fog::Collection autoload :Interface, File.expand_path('../interface', __FILE__) model Fog::Compute::Vsphere::Interface attribute :server_id def all(filters = {}) requires :server_id case server when Fog::Compute::Vsphere::Server load service.list_vm_interfaces(server.id) when Fog::Compute::Vsphere::Template load service.list_template_interfaces(server.id) else raise 'interfaces should have vm or template' end self.each { |interface| interface.server_id = server.id } self end def get(id) requires :server_id case server when Fog::Compute::Vsphere::Server interface = service.get_vm_interface(server.id, :key => id, :mac=> id, :name => id) when Fog::Compute::Vsphere::Template interface = service.get_template_interfaces(server.id, :key => id, :mac=> id, :name => id) else raise 'interfaces should have vm or template' end if interface Fog::Compute::Vsphere::Interface.new(interface.merge(:server_id => server.id, :service => service)) else nil end end def new(attributes = {}) if server_id super({ :server_id => server_id }.merge(attributes)) else super end end def server return nil if server_id.nil? service.servers.get(server_id) end def server=(new_server) server_id = new_server.id end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/models/compute/interfacetype.rb000066400000000000000000000005611263403543000250650ustar00rootroot00000000000000module Fog module Compute class Vsphere class Interfacetype < Fog::Model identity :id # attribute :class attribute :name attribute :datacenter attribute :servertype def initialize(attributes={} ) super attributes end def to_s name end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/models/compute/interfacetypes.rb000066400000000000000000000020571263403543000252520ustar00rootroot00000000000000module Fog module Compute class Vsphere class Interfacetypes < Fog::Collection autoload :Interfacetype, File.expand_path('../interfacetype', __FILE__) model Fog::Compute::Vsphere::Interfacetype attr_accessor :datacenter attr_accessor :servertype def all(filters = { }) requires :servertype case servertype when Fog::Compute::Vsphere::Servertype load service.list_interface_types(filters.merge({ :datacenter => datacenter, :servertype => servertype.id })) else raise 'interfacetypes should have a servertype' end end def get(id) requires :servertype requires :datacenter new service.get_interface_type id, servertype, datacenter rescue Fog::Compute::Vsphere::NotFound nil end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/models/compute/network.rb000066400000000000000000000005121263403543000237100ustar00rootroot00000000000000module Fog module Compute class Vsphere class Network < Fog::Model identity :id attribute :name attribute :datacenter attribute :accessible # reachable by at least one hypervisor attribute :virtualswitch def to_s name end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/models/compute/networks.rb000066400000000000000000000010051263403543000240710ustar00rootroot00000000000000module Fog module Compute class Vsphere class Networks < Fog::Collection autoload :Network, File.expand_path('../network', __FILE__) model Fog::Compute::Vsphere::Network attr_accessor :datacenter def all(filters = {}) f = { :datacenter => datacenter }.merge(filters) load service.list_networks(f) end def get(id) requires :datacenter new service.get_network(id, datacenter) end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/models/compute/process.rb000066400000000000000000000005131263403543000236760ustar00rootroot00000000000000require 'fog/compute/models/server' module Fog module Compute class Vsphere class Process < Fog::Model attribute :cmd_line attribute :end_time attribute :exit_code attribute :name attribute :owner attribute :pid attribute :start_time end end end end fog-vsphere-0.4.0/lib/fog/vsphere/models/compute/resource_pool.rb000066400000000000000000000005161263403543000251030ustar00rootroot00000000000000module Fog module Compute class Vsphere class ResourcePool < Fog::Model identity :id attribute :name attribute :cluster attribute :datacenter attribute :configured_memory_mb attribute :overall_status def to_s name end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/models/compute/resource_pools.rb000066400000000000000000000011261263403543000252640ustar00rootroot00000000000000module Fog module Compute class Vsphere class ResourcePools < Fog::Collection autoload :ResourcePool, File.expand_path('../resource_pool', __FILE__) model Fog::Compute::Vsphere::ResourcePool attr_accessor :datacenter, :cluster def all(filters = {}) load service.list_resource_pools(filters.merge(:datacenter => datacenter, :cluster => cluster)) end def get(id) requires :datacenter requires :cluster new service.get_resource_pool(id, cluster, datacenter) end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/models/compute/rule.rb000066400000000000000000000021751263403543000231750ustar00rootroot00000000000000module Fog module Compute class Vsphere # ClusterRuleInfo class Rule < Fog::Model identity :key attribute :datacenter attribute :cluster attribute :name attribute :enabled # Type should be a class - either # - RbVmomi::VIM::ClusterAntiAffinityRuleSpec # - RbVmomi::VIM::ClusterAffinityRuleSpec attribute :type attribute :vm_ids def vms vm_ids.map {|id| service.servers.get(id, datacenter) } end def vms=(vms) self.vm_ids = vms.map(&:instance_uuid) end def save requires :datacenter, :cluster, :name, :enabled, :type, :vm_ids if vm_ids.length < 2 raise ArgumentError, "A rule must have at least 2 VMs" end if persisted? raise "Update is not supported yet" else self.key = service.create_rule(attributes) end reload end def destroy service.destroy_rule(attributes) end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/models/compute/rules.rb000066400000000000000000000015621263403543000233570ustar00rootroot00000000000000module Fog module Compute class Vsphere class Rules < Fog::Collection autoload :Rule, File.expand_path('../rule', __FILE__) model Fog::Compute::Vsphere::Rule attribute :datacenter attribute :cluster def all(filters = {}) requires :datacenter, :cluster load service.list_rules(:datacenter => datacenter, :cluster => cluster) end def get(key_or_name) all.find {|rule| [rule.key, rule.name].include? key_or_name } or raise Fog::Compute::Vsphere::NotFound, "no such rule #{key_or_name}" end # Pass datacenter/cluster to every new rule def new(attributes={}) requires :datacenter, :cluster super(attributes.merge(datacenter: datacenter, cluster: cluster)) end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/models/compute/scsicontroller.rb000066400000000000000000000005141263403543000252660ustar00rootroot00000000000000module Fog module Compute class Vsphere class SCSIController < Fog::Model attribute :shared_bus attribute :type attribute :unit_number attribute :key def to_s "#{type} ##{key}: shared: #{shared_bus}, unit_number: #{unit_number}" end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/models/compute/server.rb000066400000000000000000000253631263403543000235400ustar00rootroot00000000000000require 'fog/compute/models/server' module Fog module Compute class Vsphere class Server < Fog::Compute::Server extend Fog::Deprecation deprecate(:ipaddress, :public_ip_address) # This will be the instance uuid which is globally unique across # a vSphere deployment. identity :id # JJM REVISIT (Extend the model of a vmware server) # SEE: http://www.vmware.com/support/developer/vc-sdk/visdk41pubs/ApiReference/vim.VirtualMachine.html # (Take note of the See also section.) # In particular: # GuestInfo: information about the guest operating system # VirtualMachineConfigInfo: Access to the VMX file and configuration attribute :name # UUID may be the same from VM to VM if the user does not select (I copied it) attribute :uuid attribute :hostname attribute :operatingsystem attribute :public_ip_address, :aliases => 'ipaddress' attribute :power_state, :aliases => 'power' attribute :tools_state, :aliases => 'tools' attribute :tools_version attribute :mac_addresses, :aliases => 'macs' attribute :hypervisor, :aliases => 'host' attribute :connection_state attribute :mo_ref attribute :path attribute :memory_mb attribute :cpus attribute :corespersocket attribute :interfaces attribute :volumes attribute :customvalues attribute :overall_status, :aliases => 'status' attribute :cluster attribute :datacenter attribute :resource_pool attribute :instance_uuid # move this --> id attribute :guest_id attribute :hardware_version attribute :scsi_controller # this is the first scsi controller. Right now no more of them can be used. attribute :cpuHotAddEnabled attribute :memoryHotAddEnabled attribute :firmware attribute :annotation def initialize(attributes={} ) super defaults.merge(attributes) self.instance_uuid ||= id # TODO: remvoe instance_uuid as it can be replaced with simple id initialize_interfaces initialize_volumes initialize_customvalues initialize_scsi_controller end # Lazy Loaded Attributes [:datacenter, :cluster, :hypervisor, :resource_pool, :mac_addresses].each do |attr| define_method attr do attributes[attr] = attributes[attr].call if attributes[attr].is_a?(Proc) attributes[attr] end end # End Lazy Loaded Attributes def vm_reconfig_memory(options = {}) requires :instance_uuid, :memory service.vm_reconfig_memory('instance_uuid' => instance_uuid, 'memory' => memory_mb) end def vm_reconfig_cpus(options = {}) requires :instance_uuid, :cpus, :corespersocket service.vm_reconfig_cpus('instance_uuid' => instance_uuid, 'cpus' => cpus, 'corespersocket' => corespersocket) end def vm_reconfig_hardware(hardware_spec, options = {}) requires :instance_uuid service.vm_reconfig_hardware('instance_uuid' => instance_uuid, 'hardware_spec' => hardware_spec) end def start(options = {}) requires :instance_uuid service.vm_power_on('instance_uuid' => instance_uuid) end def stop(options = {}) options = { :force => !tools_installed? || !tools_running? }.merge(options) requires :instance_uuid service.vm_power_off('instance_uuid' => instance_uuid, 'force' => options[:force]) end def reboot(options = {}) options = { :force => false }.merge(options) requires :instance_uuid service.vm_reboot('instance_uuid' => instance_uuid, 'force' => options[:force]) end def destroy(options = {}) requires :instance_uuid if ready? # need to turn it off before destroying stop(options) wait_for { !ready? } end service.vm_destroy('instance_uuid' => instance_uuid) end def migrate(options = {}) options = { :priority => 'defaultPriority' }.merge(options) requires :instance_uuid service.vm_migrate('instance_uuid' => instance_uuid, 'priority' => options[:priority]) end # Clone from a server object # # ==== Parameters # *<~Hash>: # * 'name'<~String> - *REQUIRED* Name of the _new_ VirtualMachine # * See more options in vm_clone request/compute/vm_clone.rb # def clone(options = {}) requires :name, :datacenter, :path # Convert symbols to strings req_options = options.reduce({}) { |hsh, (k,v)| hsh[k.to_s] = v; hsh } # Give our path to the request req_options['template_path'] ="#{relative_path}/#{name}" req_options['datacenter'] = "#{datacenter}" # Perform the actual clone clone_results = service.vm_clone(req_options) # We need to assign the service, otherwise we can't reload the model # Create the new VM model. TODO This only works when "wait=true" new_vm = self.class.new(clone_results['new_vm'].merge(:service => self.service)) # We need to assign the collection otherwise we # cannot reload the model. new_vm.collection = self.collection # Return the new VM model. new_vm end def take_snapshot(options = {}) requires :instance_uuid service.vm_take_snapshot(options.merge('instance_uuid' => instance_uuid)) end def ready? power_state == "poweredOn" end def tools_installed? tools_state != "toolsNotInstalled" end def tools_running? ["toolsOk","toolsOld"].include? tools_state end # defines VNC attributes on the hypervisor def config_vnc(options = {}) requires :instance_uuid service.vm_config_vnc(options.merge('instance_uuid' => instance_uuid)) end # returns a hash of VNC attributes required for service def vnc requires :instance_uuid service.vm_get_vnc(instance_uuid) end def memory memory_mb * 1024 * 1024 end def sockets cpus / corespersocket end def mac interfaces.first.mac unless interfaces.empty? end def interfaces attributes[:interfaces] ||= id.nil? ? [] : service.interfaces( :server_id => self.id ) end def interface_ready? attrs (attrs.is_a? Hash and attrs[:blocking]) or attrs.is_a? Fog::Compute::Vsphere::Interface end def add_interface attrs Fog::Logger.deprecation(".add_interface is deprecated. Call .interfaces.create instead.") interfaces.create(attrs) end def update_interface attrs wait_for { not ready? } if interface_ready? attrs service.update_vm_interface(id, attrs) end def destroy_interface attrs Fog::Logger.deprecation(".destroy_vm_interface is deprecated. Call .interfaces.get(:key => ).destroy instead.") interfaces.get(attrs[:key] || attrs['key']).destroy end def volumes attributes[:volumes] ||= id.nil? ? [] : service.volumes(:server_id => self.id) end def snapshots(opts = {}) service.snapshots(:server_id => self.id).all(opts) end def find_snapshot(snapshot_ref) snapshots.get(snapshot_ref) end def revert_snapshot(snapshot) case snapshot when Snapshot service.revert_to_snapshot(snapshot) when String service.revert_to_snapshot(find_snapshot(snapshot)) else fail ArgumentError, "snapshot has to be kind of Snapshot or String class" end end def cdroms(opts = {}) service.cdroms(:instance_uuid => self.id).all(opts) end def cdrom(key) cdroms.get(key) end def guest_processes(opts = {}) fail 'VM tools must be running' unless tools_running? service.list_processes(self.id, opts) end def customvalues attributes[:customvalues] ||= id.nil? ? [] : service.customvalues( :vm => self ) end def scsi_controller self.attributes[:scsi_controller] ||= service.get_vm_first_scsi_controller(id) end def folder return nil unless datacenter and path attributes[:folder] ||= service.folders(:datacenter => datacenter, :type => :vm).get(path) end def save requires :name, :cluster, :datacenter if persisted? raise "update is not supported yet" # service.update_vm(attributes) else self.id = service.create_vm(attributes) end reload end def new? id.nil? end def reload # reload does not re-read assoiciated attributes, so we clear it manually [:interfaces, :volumes].each do |attr| self.attributes.delete(attr) end super end def relative_path requires :path, :datacenter (path.split('/').reject {|e| e.empty?} - ["Datacenters", datacenter, "vm"]).join("/") end private def defaults { :cpus => 1, # :corespersocket => 1, :memory_mb => 512, :guest_id => 'otherGuest', :path => '/' } end def initialize_interfaces if attributes[:interfaces] and attributes[:interfaces].is_a?(Array) self.attributes[:interfaces].map! { |nic| nic.is_a?(Hash) ? service.interfaces.new(nic) : nic } end end def initialize_volumes if attributes[:volumes] and attributes[:volumes].is_a?(Array) self.attributes[:volumes].map! { |vol| vol.is_a?(Hash) ? service.volumes.new(vol) : vol } end end def initialize_customvalues if attributes[:customvalues] and attributes[:customvalues].is_a?(Array) self.attributes[:customvalues].map { |cfield| cfield.is_a?(Hash) ? service.customvalue.new(cfield) : cfield} end end def initialize_scsi_controller if attributes[:scsi_controller] and attributes[:scsi_controller].is_a?(Hash) Fog::Compute::Vsphere::SCSIController.new(self.attributes[:scsi_controller]) end end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/models/compute/servers.rb000066400000000000000000000017631263403543000237210ustar00rootroot00000000000000module Fog module Compute class Vsphere class Servers < Fog::Collection autoload :Server, File.expand_path('../server', __FILE__) model Fog::Compute::Vsphere::Server attr_accessor :datacenter attr_accessor :network attr_accessor :cluster attr_accessor :resource_pool attr_accessor :folder # 'folder' => '/Datacenters/vm/Jeff/Templates' will be MUCH faster. # than simply listing everything. def all(filters = { }) f = { :datacenter => datacenter, :cluster => cluster, :network => network, :resource_pool => resource_pool, :folder => folder }.merge(filters) load service.list_virtual_machines(f) end def get(id, datacenter = nil) new service.get_virtual_machine id, datacenter rescue Fog::Compute::Vsphere::NotFound nil end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/models/compute/servertype.rb000066400000000000000000000013641263403543000244350ustar00rootroot00000000000000module Fog module Compute class Vsphere class Servertype < Fog::Model identity :id attribute :family attribute :fullname attribute :datacenter attribute :interfacetypes def initialize(attributes={} ) super defaults.merge(attributes) end def to_s id end def interfacetypes filters={} attributes[:interfacetypes] ||= service.interfacetypes({ :datacenter => datacenter, :servertype => self }.merge(filters)) end private def defaults { :id=>"otherGuest64", :family=>"otherGuestFamily", :interfacetypes => nil, } end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/models/compute/servertypes.rb000066400000000000000000000011251263403543000246130ustar00rootroot00000000000000module Fog module Compute class Vsphere class Servertypes < Fog::Collection autoload :Servertype, File.expand_path('../servertype', __FILE__) model Fog::Compute::Vsphere::Servertype attr_accessor :datacenter, :id, :fullname def all(filters = { }) load service.list_server_types(filters.merge({:datacenter => datacenter})) end def get(id) requires :datacenter new service.get_server_type(id, datacenter) rescue Fog::Compute::Vsphere::NotFound nil end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/models/compute/snapshot.rb000066400000000000000000000015401263403543000240600ustar00rootroot00000000000000require 'fog/compute/models/server' module Fog module Compute class Vsphere class Snapshot < Fog::Model identity :ref attribute :server_id attribute :name attribute :quiescedi, :default => false attribute :description, :default => '' attribute :create_time attribute :power_state, :default => 'none' attribute :ref attribute :mo_ref attribute :tree_node attribute :snapshot_name_chain attribute :ref_chain def child_snapshots(filters = {}) service.snapshots( { :server_id => server_id, :parent_snapshot => self }.update(filters) ) end def get_child(snapshot_ref) return self if ref == snapshot_ref child_snapshots().get(snapshot_ref) end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/models/compute/snapshots.rb000066400000000000000000000013011263403543000242360ustar00rootroot00000000000000require 'fog/core/collection' require 'fog/vsphere/models/compute/snapshot' module Fog module Compute class Vsphere class Snapshots < Fog::Collection attribute :server_id, :alias => :instance_uuid attribute :parent_snapshot model Fog::Compute::Vsphere::Snapshot def all(filters = {}) if parent_snapshot load service.list_child_snapshots(parent_snapshot, filters) else requires :server_id load service.list_vm_snapshots(server_id, filters) end end def get(snapshot_ref) all.find { |snapshot| snapshot.get_child(snapshot_ref) } end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/models/compute/storage_pod.rb000066400000000000000000000004701263403543000245300ustar00rootroot00000000000000module Fog module Compute class Vsphere class StoragePod < Fog::Model identity :id attribute :name attribute :datacenter attribute :type attribute :freespace attribute :capacity def to_s name end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/models/compute/storage_pods.rb000066400000000000000000000010031263403543000247040ustar00rootroot00000000000000require 'fog/core/collection' require 'fog/vsphere/models/compute/storage_pod' module Fog module Compute class Vsphere class StoragePods < Fog::Collection model Fog::Compute::Vsphere::StoragePod attribute :datacenter def all(filters = {}) load service.list_storage_pods(filters.merge(datacenter: datacenter)) end def get(id) requires :datacenter new service.get_storage_pod(id, datacenter) end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/models/compute/template.rb000066400000000000000000000002611263403543000240330ustar00rootroot00000000000000module Fog module Compute class Vsphere class Template < Fog::Model identity :id attribute :name attribute :uuid end end end end fog-vsphere-0.4.0/lib/fog/vsphere/models/compute/templates.rb000066400000000000000000000006111263403543000242150ustar00rootroot00000000000000module Fog module Compute class Vsphere class Templates < Fog::Collection autoload :Template, File.expand_path('../template', __FILE__) model Fog::Compute::Vsphere::Template def all(filters = {}) load service.list_templates(filters) end def get(id) new service.get_template(id) end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/models/compute/volume.rb000066400000000000000000000054501263403543000235340ustar00rootroot00000000000000module Fog module Compute class Vsphere class Volume < Fog::Model DISK_SIZE_TO_GB = 1048576 identity :id attribute :datastore attribute :storage_pod attribute :mode attribute :size attribute :thin attribute :eager_zero attribute :name attribute :filename attribute :size_gb attribute :key attribute :unit_number attribute :server_id def initialize(attributes={} ) # Assign server first to prevent race condition with persisted? self.server_id = attributes.delete(:server_id) super defaults.merge(attributes) end def size_gb attributes[:size_gb] ||= attributes[:size].to_i / DISK_SIZE_TO_GB if attributes[:size] end def size_gb= s attributes[:size] = s.to_i * DISK_SIZE_TO_GB if s end def to_s name end def destroy requires :server_id, :key, :unit_number service.destroy_vm_volume(self) true end def save raise Fog::Errors::Error.new('Resaving an existing object may create a duplicate') if persisted? requires :server_id, :size, :datastore if unit_number.nil? used_unit_numbers = server.volumes.map { |volume| volume.unit_number } max_unit_number = used_unit_numbers.max if max_unit_number > server.volumes.size # If the max ID exceeds the number of volumes, there must be a hole in the range. Find a hole and use it. self.unit_number = max_unit_number.times.to_a.find { |i| used_unit_numbers.exclude?(i) } else self.unit_number = max_unit_number + 1 end else if server.volumes.any? { |volume| volume.unit_number == self.unit_number && volume.id != self.id } raise "A volume already exists with that unit_number, so we can't save the new volume" end end data = service.add_vm_volume(self) if data['task_state'] == 'success' # We have to query vSphere to get the volume attributes since the task handle doesn't include that info. created = server.volumes.all.find { |volume| volume.unit_number == self.unit_number } self.id = created.id self.key = created.key self.filename = created.filename true else false end end def server requires :server_id service.servers.get(server_id) end private def defaults { :thin => true, :name => "Hard disk", :mode => "persistent" } end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/models/compute/volumes.rb000066400000000000000000000025331263403543000237160ustar00rootroot00000000000000module Fog module Compute class Vsphere class Volumes < Fog::Collection autoload :Volume, File.expand_path('../volume', __FILE__) attribute :server_id model Fog::Compute::Vsphere::Volume def all(filters = {}) requires :server_id case server when Fog::Compute::Vsphere::Server load service.list_vm_volumes(server.id) when Fog::Compute::Vsphere::Template load service.list_template_volumes(server.id) else raise 'volumes should have vm or template' end self.each { |volume| volume.server_id = server.id } self end def get(id) new service.get_volume(id) end def new(attributes = {}) if server_id # Default to the root volume datastore if one is not configured. datastore = ! attributes.key?(:datastore) && self.any? ? self.first.datastore : nil super({ :server_id => server_id, :datastore => datastore }.merge!(attributes)) else super end end def server return nil if server_id.nil? service.servers.get(server_id) end def server=(new_server) server_id = new_server.id end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/requests/000077500000000000000000000000001263403543000206105ustar00rootroot00000000000000fog-vsphere-0.4.0/lib/fog/vsphere/requests/compute/000077500000000000000000000000001263403543000222645ustar00rootroot00000000000000fog-vsphere-0.4.0/lib/fog/vsphere/requests/compute/cloudinit_to_customspec.rb000066400000000000000000000101451263403543000275530ustar00rootroot00000000000000module Fog module Compute class Vsphere class Real def cloudinit_to_customspec(user_data) raise ArgumentError, "user_data can't be nil" if user_data.nil? custom_spec = { 'customization_spec' => Hash.new } user_data = YAML.load(user_data) # https://pubs.vmware.com/vsphere-55/index.jsp#com.vmware.wssdk.apiref.doc/vim.vm.customization.Specification.html # encryptionKey expects an array # globalIPSettings expects a hash, REQUIRED # identity expects an hash, REQUIRED # nicSettingMap expects an array # options expects an hash custom_spec['encryptionKey'] = user_data['encryptionKey'] if user_data.key?('encryptionKey') custom_spec['globalIPSettings'] = user_data['globalIPSettings'] if user_data.key?('globalIPSettings') custom_spec['identity'] = user_data['identity'] if user_data.key?('identity') custom_spec['nicSettingMap'] = user_data['nicSettingMap'] if user_data.key?('nicSettingMap') custom_spec['options'] = user_data['options'] if user_data.key?('options') # for backwards compatability # hostname expects a string, REQUIRED # netmask expects a string # dns expects an array # gateway expects an array # domain expects a string, REQUIRED # domainsuffixlist expects an array, REQUIRED # timezone expects a string, for example Europe/Copenhagen, REQUIRED custom_spec['hostname'] = user_data['hostname'] if user_data.key?('hostname') custom_spec['ipsettings'] = { 'ip' => user_data['ip'] } if user_data.key?('ip') custom_spec['ipsettings']['subnetMask'] = user_data['netmask'] if user_data.key?('netmask') custom_spec['ipsettings']['dnsServerList'] = user_data['dns'] if user_data.key?('dns') custom_spec['ipsettings']['gateway'] = user_data['gateway'] if user_data.key?('gateway') custom_spec['domain'] = user_data['domain'] if user_data.key?('domain') custom_spec['dnsSuffixList'] = user_data['domainsuffixlist'] if user_data.key?('domainsuffixlist') custom_spec['time_zone'] = user_data['timezone'] if user_data.key?('timezone') custom_spec end end class Mock def cloudinit_to_customspec(user_data) raise ArgumentError, "user_data can't be nil" if user_data.nil? custom_spec = { 'customization_spec' => Hash.new } user_data = YAML.load(user_data) custom_spec['encryptionKey'] = user_data['encryptionKey'] if user_data.key?('encryptionKey') custom_spec['globalIPSettings'] = user_data['globalIPSettings'] if user_data.key?('globalIPSettings') custom_spec['identity'] = user_data['identity'] if user_data.key?('identity') custom_spec['nicSettingMap'] = user_data['nicSettingMap'] if user_data.key?('nicSettingMap') custom_spec['options'] = user_data['options'] if user_data.key?('options') custom_spec['hostname'] = user_data['hostname'] if user_data.key?('hostname') custom_spec['ipsettings'] = { 'ip' => user_data['ip'] } if user_data.key?('ip') custom_spec['ipsettings']['subnetMask'] = user_data['netmask'] if user_data.key?('netmask') custom_spec['ipsettings']['dnsServerList'] = user_data['dns'] if user_data.key?('dns') custom_spec['ipsettings']['gateway'] = user_data['gateway'] if user_data.key?('gateway') custom_spec['domain'] = user_data['domain'] if user_data.key?('domain') custom_spec['dnsSuffixList'] = user_data['domainsuffixlist'] if user_data.key?('domainsuffixlist') custom_spec['time_zone'] = user_data['timezone'] if user_data.key?('timezone') custom_spec end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/requests/compute/create_folder.rb000066400000000000000000000021001263403543000254000ustar00rootroot00000000000000module Fog module Compute class Vsphere class Real def create_folder(datacenter, path, name) #Path cannot be nil but it can be an empty string raise ArgumentError, "Path cannot be nil" if path.nil? parent_folder = get_raw_vmfolder(path, datacenter) begin new_folder = parent_folder.CreateFolder(:name => name) # output is cleaned up to return the new path # new path will be path/name, example: "Production/Pool1" new_folder.path.reject { |a| a.first.class == "Folder" }.map { |a| a.first.name }.join("/").sub(/^\/?Datacenters\/#{datacenter}\/vm\/?/, '') rescue => e raise e, "failed to create folder: #{e}" end end end class Mock def create_folder(datacenter, path, name) self.data[:folders][name] = { 'name' => name, 'datacenter' => datacenter, 'path' => "#{path}/#{name}", 'type' => 'vm' } end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/requests/compute/create_rule.rb000066400000000000000000000032661263403543000251120ustar00rootroot00000000000000module Fog module Compute class Vsphere class Real def create_rule(attributes={}) cluster = get_raw_cluster(attributes[:cluster], attributes[:datacenter]) # Check if it already exists and blow up if it does # (otherwise ESX just happily accepts it and then considers it a conflict) rule = cluster.configurationEx.rule.find {|n| n[:name] == attributes[:name]} if rule raise ArgumentError, "Rule #{attributes[:name]} already exists!" end # First, create the rulespec vms = attributes[:vm_ids].to_a.map {|id| get_vm_ref(id, attributes[:datacenter])} spec = attributes[:type].new( name: attributes[:name], enabled: attributes[:enabled], vm: vms ) # Now, attach it to the cluster cluster_spec = RbVmomi::VIM.ClusterConfigSpecEx(rulesSpec: [ RbVmomi::VIM.ClusterRuleSpec( operation: RbVmomi::VIM.ArrayUpdateOperation('add'), info: spec ) ]) ret = cluster.ReconfigureComputeResource_Task(spec: cluster_spec, modify: true).wait_for_completion rule = cluster.configurationEx.rule.find {|n| n[:name] == attributes[:name]} if rule return rule[:key] else raise Fog::Vsphere::Errors::ServiceError, "Unknown error creating rule #{attributes[:name]}" end end end class Mock def create_rule(attributes={}) attributes[:key] = rand(9999) self.data[:rules][attributes[:name]] = attributes attributes[:key] end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/requests/compute/create_vm.rb000066400000000000000000000326451263403543000245700ustar00rootroot00000000000000module Fog module Compute class Vsphere class Real def create_vm attributes = { } # build up vm configuration vm_cfg = { :name => attributes[:name], :annotation => attributes[:annotation], :guestId => attributes[:guest_id], :version => attributes[:hardware_version], :files => { :vmPathName => vm_path_name(attributes) }, :numCPUs => attributes[:cpus], :numCoresPerSocket => attributes[:corespersocket], :memoryMB => attributes[:memory_mb], :deviceChange => device_change(attributes), :extraConfig => extra_config(attributes), } vm_cfg[:cpuHotAddEnabled] = attributes[:cpuHotAddEnabled] if attributes.key?(:cpuHotAddEnabled) vm_cfg[:memoryHotAddEnabled] = attributes[:memoryHotAddEnabled] if attributes.key?(:memoryHotAddEnabled) vm_cfg[:firmware] = attributes[:firmware] if attributes.key?(:firmware) vm_cfg[:bootOptions] = boot_options(attributes) if attributes.key?(:boot_order) || attributes.key?(:boot_retry) resource_pool = if attributes[:resource_pool] && attributes[:resource_pool] != 'Resources' get_raw_resource_pool(attributes[:resource_pool], attributes[:cluster], attributes[:datacenter]) else get_raw_cluster(attributes[:cluster], attributes[:datacenter]).resourcePool end vmFolder = get_raw_vmfolder(attributes[:path], attributes[:datacenter]) # if any volume has a storage_pod set, we deploy the vm on a storage pod instead of the defined datastores pod = get_storage_pod(attributes) if pod vm = create_vm_on_storage_pod(pod, vm_cfg, vmFolder, resource_pool, attributes[:datacenter]) else vm = create_vm_on_datastore(vm_cfg, vmFolder, resource_pool) end vm.config.instanceUuid rescue => e raise e, "failed to create vm: #{e}" end private def create_vm_on_datastore(vm_cfg, vmFolder, resource_pool) vm = vmFolder.CreateVM_Task(:config => vm_cfg, :pool => resource_pool).wait_for_completion end def create_vm_on_storage_pod(storage_pod, vm_cfg, vmFolder, resource_pool, datacenter) pod_spec = RbVmomi::VIM::StorageDrsPodSelectionSpec.new( :storagePod => get_raw_storage_pod(storage_pod, datacenter), ) storage_spec = RbVmomi::VIM::StoragePlacementSpec.new( :type => 'create', :folder => vmFolder, :resourcePool => resource_pool, :podSelectionSpec => pod_spec, :configSpec => vm_cfg, ) srm = @connection.serviceContent.storageResourceManager result = srm.RecommendDatastores(:storageSpec => storage_spec) # if result array contains recommendation, we can apply it if key = result.recommendations.first.key result = srm.ApplyStorageDrsRecommendation_Task(:key => [key]).wait_for_completion vm = result.vm else raise "Could not create vm on storage pod, did not get a storage recommendation" end vm end # check if a storage pool is set on any of the volumes and return the first result found or nil # return early if vsphere revision is lower than 5 as this is not supported def get_storage_pod attributes return unless @vsphere_rev.to_f >= 5 volume = attributes[:volumes].detect {|volume| !( volume.storage_pod.nil? || volume.storage_pod.empty? ) } volume.storage_pod if volume end # this methods defines where the vm config files would be located, # by default we prefer to keep it at the same place the (first) vmdk is located # if we deploy the vm on a storage pool, we have to return an empty string def vm_path_name attributes return '' if get_storage_pod(attributes) datastore = attributes[:volumes].first.datastore unless attributes[:volumes].empty? datastore ||= 'datastore1' "[#{datastore}]" end def device_change attributes devices = [] if (nics = attributes[:interfaces]) devices << nics.map { |nic| create_interface(nic, nics.index(nic), :add, attributes) } end if (disks = attributes[:volumes]) devices << create_controller(attributes[:scsi_controller]||attributes["scsi_controller"]||{}) devices << disks.map { |disk| create_disk(disk, disks.index(disk), :add, 1000, get_storage_pod(attributes)) } end if (cdroms = attributes[:cdroms]) devices << cdroms.map { |cdrom| create_cdrom(cdrom, cdroms.index(cdrom)) } end devices.flatten end def boot_options attributes # NOTE: you must be using vsphere_rev 5.0 or greater to set boot_order # e.g. Fog::Compute.new(provider: "vsphere", vsphere_rev: "5.5", etc) options = {} if @vsphere_rev.to_f >= 5 and attributes[:boot_order] options[:bootOrder] = boot_order(attributes) end # Set attributes[:boot_retry] to a delay in miliseconds to enable boot retries if attributes[:boot_retry] options[:bootRetryEnabled] = true options[:bootRetryDelay] = attributes[:boot_retry] end options.empty? ? nil : RbVmomi::VIM::VirtualMachineBootOptions.new(options) end def boot_order attributes # attributes[:boot_order] may be an array like this ['network', 'disk'] # stating, that we want to prefer network boots over disk boots boot_order = [] attributes[:boot_order].each do |boot_device| case boot_device when 'network' if nics = attributes[:interfaces] # key is based on 4000 + the interface index # we allow booting from all network interfaces, the first interface has the highest priority nics.each do |nic| boot_order << RbVmomi::VIM::VirtualMachineBootOptionsBootableEthernetDevice.new( :deviceKey => 4000 + nics.index(nic), ) end end when 'disk' if disks = attributes[:volumes] disks.each do |disk| # we allow booting from all harddisks, the first disk has the highest priority boot_order << RbVmomi::VIM::VirtualMachineBootOptionsBootableDiskDevice.new( :deviceKey => disk.key || get_disk_device_key(disks.index(disk)), ) end end when 'cdrom' boot_order << RbVmomi::VIM::VirtualMachineBootOptionsBootableCdromDevice.new() when 'floppy' boot_order << RbVmomi::VIM::VirtualMachineBootOptionsBootableFloppyDevice.new() else raise "failed to create boot device because \"#{boot_device}\" is unknown" end end boot_order end def get_disk_device_key(index) # disk key is based on 2000 + the SCSI ID + the controller bus * 16 # the scsi host adapter appears as SCSI ID 7, so we have to skip that # host adapter key is based on 1000 + bus id # fog assumes that there is only a single scsi controller, see device_change() if (index > 6) then _index = index + 1 else _index = index end 2000 + _index end def create_nic_backing nic, attributes raw_network = get_raw_network(nic.network, attributes[:datacenter], if nic.virtualswitch then nic.virtualswitch end) if raw_network.kind_of? RbVmomi::VIM::DistributedVirtualPortgroup RbVmomi::VIM.VirtualEthernetCardDistributedVirtualPortBackingInfo( :port => RbVmomi::VIM.DistributedVirtualSwitchPortConnection( :portgroupKey => raw_network.key, :switchUuid => raw_network.config.distributedVirtualSwitch.uuid ) ) else RbVmomi::VIM.VirtualEthernetCardNetworkBackingInfo(:deviceName => nic.network) end end def create_interface nic, index = 0, operation = :add, attributes = {} { :operation => operation, :device => nic.type.new( :key => index, :deviceInfo => { :label => nic.name, :summary => nic.summary, }, :backing => create_nic_backing(nic, attributes), :addressType => 'generated') } end def create_controller options=nil options=if options controller_default_options.merge(Hash[options.map{|k,v| [k.to_sym,v] }]) else controller_default_options end controller_class=if options[:type].is_a? String then Fog::Vsphere.class_from_string options[:type], "RbVmomi::VIM" else options[:type] end { :operation => options[:operation], :device => controller_class.new({ :key => options[:key], :busNumber => options[:bus_id], :sharedBus => controller_get_shared_from_options(options), }) } end def controller_default_options {:operation => "add", :type => RbVmomi::VIM.VirtualLsiLogicController.class, :key => 1000, :bus_id => 0, :shared => false } end def controller_get_shared_from_options options if (options.key? :shared and options[:shared]==false) or not options.key? :shared then :noSharing elsif options[:shared]==true then :virtualSharing elsif options[:shared].is_a? String options[:shared] else :noSharing end end def create_disk disk, index = 0, operation = :add, controller_key = 1000, storage_pod = nil if (index > 6) then _index = index + 1 else _index = index end # If we deploy the vm on a storage pod, datastore has to be an empty string if storage_pod datastore '' else datastore = "[#{disk.datastore}]" end payload = { :operation => operation, :fileOperation => operation == :add ? :create : :destroy, :device => RbVmomi::VIM.VirtualDisk( :key => disk.key || _index, :backing => RbVmomi::VIM.VirtualDiskFlatVer2BackingInfo( :fileName => datastore, :diskMode => disk.mode.to_sym, :thinProvisioned => disk.thin ), :controllerKey => controller_key, :unitNumber => _index, :capacityInKB => disk.size ) } if operation == :add && disk.thin == 'false' && disk.eager_zero == 'true' payload[:device][:backing][:eagerlyScrub] = disk.eager_zero end payload end def create_cdrom cdrom, index = 0, operation = :add, controller_key = 200 { :operation => operation, :device => RbVmomi::VIM.VirtualCdrom( :key => cdrom.key || index, :backing => RbVmomi::VIM::VirtualCdromRemoteAtapiBackingInfo(deviceName: ''), :controllerKey => controller_key, connectable: RbVmomi::VIM::VirtualDeviceConnectInfo( startConnected: false, connected: false, allowGuestControl: true, ), ) } end def extra_config attributes extra_config = attributes[:extra_config] || {'bios.bootOrder' => 'ethernet0'} extra_config.map {|k,v| {:key => k, :value => v.to_s} } end end class Mock def create_vm attributes = { } id = SecureRandom.uuid vm = { 'id' => id, 'uuid' => id, 'instance_uuid' => id, 'mo_ref' => "vm-#{rand 99999}", 'datacenter' => attributes[:datacenter], 'name' => attributes[:name], 'interfaces' => attributes[:interfaces].map {{ 'mac' => 'f2:b5:46:b5:d8:d7' }} } self.data[:servers][id] = vm id end def create_cdrom cdrom, index = 0, operation = :add, controller_key = 200 { :operation => operation, :device => { :key => cdrom.key || index, :backing => { deviceName: '' }, :controllerKey => controller_key, connectable: { startConnected: false, connected: false, allowGuestControl: true, }, } } end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/requests/compute/current_time.rb000066400000000000000000000005341263403543000253130ustar00rootroot00000000000000module Fog module Compute class Vsphere class Real def current_time current_time = @connection.serviceInstance.CurrentTime { 'current_time' => current_time } end end class Mock def current_time { 'current_time' => Time.now.utc } end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/requests/compute/destroy_rule.rb000066400000000000000000000017611263403543000253360ustar00rootroot00000000000000module Fog module Compute class Vsphere class Real def destroy_rule(attributes = {}) cluster = get_raw_cluster(attributes[:cluster], attributes[:datacenter]) rule = cluster.configurationEx.rule.find {|rule| rule.key == attributes[:key]} raise Fog::Vsphere::Error::NotFound, "rule #{attributes[:key]} not found" unless rule delete_spec = RbVmomi::VIM.ClusterConfigSpecEx(rulesSpec: [ RbVmomi::VIM.ClusterRuleSpec( operation: RbVmomi::VIM.ArrayUpdateOperation('remove'), removeKey: rule.key ) ]) cluster.ReconfigureComputeResource_Task(spec: delete_spec, modify: true).wait_for_completion end end class Mock def destroy_rule(attributes = {}) rule = self.data[:rules][attributes[:name]] raise Fog::Vsphere::Error::NotFound unless rule self.data[:rules].delete(attributes[:name]) end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/requests/compute/folder_destroy.rb000066400000000000000000000015551263403543000256430ustar00rootroot00000000000000module Fog module Compute class Vsphere class Real def folder_destroy(path, datacenter_name) folder = get_raw_vmfolder(path, datacenter_name) raise Fog::Vsphere::Errors::NotFound, "No such folder #{path}" unless folder raise Fog::Vsphere::Errors::ServiceError, "Folder #{path} is not empty" if folder.childEntity.size > 0 task = folder.Destroy_Task task.wait_for_completion { 'task_state' => task.info.state } end end class Mock def folder_destroy(path, datacenter_name) vms = list_virtual_machines(folder: path, datacenter: datacenter_name) if vms.length > 0 raise Fog::Vsphere::Errors::ServiceError, "Folder #{path} is not empty" end { 'task_state' => 'success' } end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/requests/compute/get_cluster.rb000066400000000000000000000013441263403543000251330ustar00rootroot00000000000000module Fog module Compute class Vsphere class Real def get_cluster(name, datacenter_name) cluster = get_raw_cluster(name, datacenter_name) raise(Fog::Compute::Vsphere::NotFound) unless cluster cluster_attributes(cluster, datacenter_name) end protected def get_raw_cluster(name, datacenter_name) dc = find_raw_datacenter(datacenter_name) dc.find_compute_resource(name) end end class Mock def get_cluster(name, datacenter_name) self.data[:clusters].find {|c| c[:name] == name && c[:datacenter] == datacenter_name} or raise Fog::Compute::Vsphere::NotFound end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/requests/compute/get_compute_resource.rb000066400000000000000000000022421263403543000270330ustar00rootroot00000000000000module Fog module Compute class Vsphere class Real def get_compute_resource(name, datacenter_name) compute_resource = get_raw_compute_resource(name, datacenter_name) raise(Fog::Compute::Vsphere::NotFound) unless compute_resource compute_resource_attributes(compute_resource, datacenter_name) end protected def get_raw_compute_resource(name, datacenter_name) find_raw_datacenter(datacenter_name).find_compute_resource(name) end end class Mock def get_compute_resource(name, datacenter_name) { :id=>"domain-s7", :name=>"fake-host", :totalCpu=>33504, :totalMemory=>154604142592, :numCpuCores=>12, :numCpuThreads=>24, :effectiveCpu=>32247, :effectiveMemory=>135733, :numHosts=>1, :numEffectiveHosts=>1, :overallStatus=>"gray", :overallCpuUsage=>15682, :overallMemoryUsage=>132755, :effective=>true, :isSingleHost=>true } end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/requests/compute/get_datacenter.rb000066400000000000000000000014011263403543000255560ustar00rootroot00000000000000module Fog module Compute class Vsphere class Real def get_datacenter name dc = find_raw_datacenter(name) raise(Fog::Compute::Vsphere::NotFound) unless dc {:name => dc.name, :status => dc.overallStatus, :path => raw_getpathmo(dc) } end protected def find_raw_datacenter name raw_datacenters.find {|d| d.name == name} || get_raw_datacenter(name) end def get_raw_datacenter name @connection.serviceInstance.find_datacenter(name) end end class Mock def get_datacenter name dc = self.data[:datacenters][name] raise(Fog::Compute::Vsphere::NotFound) unless dc dc end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/requests/compute/get_datastore.rb000066400000000000000000000014551263403543000254430ustar00rootroot00000000000000module Fog module Compute class Vsphere class Real def get_datastore(name, datacenter_name) datastore = get_raw_datastore(name, datacenter_name) raise(Fog::Compute::Vsphere::NotFound) unless datastore datastore_attributes(datastore, datacenter_name) end protected def get_raw_datastore(name, datacenter_name) dc = find_raw_datacenter(datacenter_name) @connection.serviceContent.viewManager.CreateContainerView({ :container => dc.datastoreFolder, :type => ["Datastore"], :recursive => true }).view.select{|ds| ds.name == name}.first end end class Mock def get_datastore(name, datacenter_name) end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/requests/compute/get_folder.rb000066400000000000000000000056311263403543000247300ustar00rootroot00000000000000module Fog module Compute class Vsphere class Real def get_folder(path, datacenter_name, type = nil) type ||= 'vm' # Cycle through all types of folders. case type when 'vm', :vm # if you're a vm then grab the VM. folder = get_raw_vmfolder(path, datacenter_name) raise(Fog::Compute::Vsphere::NotFound) unless folder folder_attributes(folder, datacenter_name) when 'network', :network raise "not implemented" when 'datastore', :datastore raise "not implemented" else raise ArgumentError, "#{type} is unknown" end end protected def get_raw_vmfolder(path, datacenter_name) # The required path syntax - 'topfolder/subfolder # Clean up path to be relative since we're providing datacenter name dc = find_raw_datacenter(datacenter_name) dc_root_folder = dc.vmFolder # Filter the root path for this datacenter not to be used." dc_root_folder_path=dc_root_folder.path.map { | id, name | name }.join("/") paths = path.sub(/^\/?#{Regexp.quote(dc_root_folder_path)}\/?/, '').split('/') return dc_root_folder if paths.empty? # Walk the tree resetting the folder pointer as we go paths.reduce(dc_root_folder) do |last_returned_folder, sub_folder| # JJM VIM::Folder#find appears to be quite efficient as it uses the # searchIndex It certainly appears to be faster than # VIM::Folder#inventory since that returns _all_ managed objects of # a certain type _and_ their properties. sub = last_returned_folder.find(sub_folder, RbVmomi::VIM::Folder) raise Fog::Compute::Vsphere::NotFound, "Could not descend into #{sub_folder}. Please check your path. #{path}" unless sub sub end end def folder_attributes(folder, datacenter_name) { :id => managed_obj_id(folder), :name => folder.name, :parent => folder.parent.name, :datacenter => datacenter_name, :type => folder_type(folder), :path => "/"+folder.path.map(&:last).join('/'), } end def folder_type(folder) types = folder.childType return :vm if types.include?('VirtualMachine') return :network if types.include?('Network') return :datastore if types.include?('Datastore') end end class Mock def get_folder(path, datacenter_name, type = nil) self.data[:folders].values.find {|f| f['datacenter'] == datacenter_name and f['path'].end_with? path} or raise Fog::Compute::Vsphere::NotFound end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/requests/compute/get_interface_type.rb000066400000000000000000000006521263403543000264540ustar00rootroot00000000000000module Fog module Compute class Vsphere class Real def get_interface_type(id, servertype, datacenter, filter={}) interfacetype=list_interface_types(filters={:id => id, :datacenter => datacenter, :servertype => servertype.id }).first raise(Fog::Compute::Vsphere::NotFound) unless interfacetype interfacetype end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/requests/compute/get_network.rb000066400000000000000000000035461263403543000251510ustar00rootroot00000000000000module Fog module Compute class Vsphere class Real def get_network(name, datacenter_name) network = get_raw_network(name, datacenter_name) raise(Fog::Compute::Vsphere::NotFound) unless network network_attributes(network, datacenter_name) end protected def get_raw_network(name, datacenter_name, distributedswitch=nil) finder = choose_finder(name, distributedswitch) networks = get_all_raw_networks(datacenter_name) networks.find { |n| finder.call(n) } end end module Shared protected def get_all_raw_networks(datacenter_name) dc = find_raw_datacenter(datacenter_name) @connection.serviceContent.viewManager. CreateContainerView({ :container => dc.networkFolder, :type => ["Network"], :recursive => true }).view end def choose_finder(name, distributedswitch) case distributedswitch when String # only the one will do Proc.new { |n| (n.name == name) && (n.class.to_s == "DistributedVirtualPortgroup") && (n.config.distributedVirtualSwitch.name == distributedswitch) } when :dvs # the first distributed virtual switch will do - selected by network - gives control to vsphere Proc.new { |n| (n.name == name) && (n.class.to_s == "DistributedVirtualPortgroup") } else # the first matching network will do, seems like the non-distributed networks come first Proc.new { |n| (n.name == name) } end end end class Mock def get_network(id) end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/requests/compute/get_resource_pool.rb000066400000000000000000000014551263403543000263350ustar00rootroot00000000000000module Fog module Compute class Vsphere class Real def get_resource_pool(name, cluster_name, datacenter_name) resource_pool = get_raw_resource_pool(name, cluster_name, datacenter_name) raise(Fog::Compute::Vsphere::NotFound) unless resource_pool resource_pool_attributes(resource_pool, cluster_name, datacenter_name) end protected def get_raw_resource_pool(name, cluster_name, datacenter_name) dc = find_raw_datacenter(datacenter_name) cluster = dc.find_compute_resource(cluster_name) name.nil? ? cluster.resourcePool : cluster.resourcePool.traverse(name) end end class Mock def get_resource_pool(name, cluster_name, datacenter_name) end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/requests/compute/get_server_type.rb000066400000000000000000000017051263403543000260220ustar00rootroot00000000000000module Fog module Compute class Vsphere class Real def get_server_type(id, datacenter, filter={}) server_type=get_raw_server_type(id, datacenter) raise(Fog::Compute::Vsphere::NotFound) unless server_type server_type_attributes(server_type, datacenter) end protected def get_raw_server_type(id, datacenter, filter={}) types=raw_server_types(datacenter) raise(Fog::Compute::Vsphere::NotFound) unless types types=types.select{ | servertype | servertype.id == id }.first raise(Fog::Compute::Vsphere::NotFound) unless types types end end class Mock def get_server_type(id) {:id=>"rhel6Guest", :name=>"rhel6Guest", :family=>"linuxGuest", :fullname=>"Red Hat Enterprise Linux 6 (32-Bit)", :datacenter=>"Solutions"} end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/requests/compute/get_storage_pod.rb000066400000000000000000000016161263403543000257620ustar00rootroot00000000000000module Fog module Compute class Vsphere class Real def get_storage_pod(name, datacenter_name) storage_pod = get_raw_storage_pod(name, datacenter_name) raise(Fog::Compute::Vsphere::NotFound) unless storage_pod storage_pod_attributes(storage_pod, datacenter_name) end protected def get_raw_storage_pod(name, datacenter_name) dc = find_raw_datacenter(datacenter_name) @connection.serviceContent.viewManager.CreateContainerView({ :container => dc, :type => ["StoragePod"], :recursive => true }).view.select{|pod| pod.name == name}.first end end class Mock def get_storage_pod(name, datacenter_name) list_storage_pods({datacenter: datacenter_name}).select{|h| h[:name] == name }.first end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/requests/compute/get_template.rb000066400000000000000000000005021263403543000252600ustar00rootroot00000000000000module Fog module Compute class Vsphere class Real def get_template(id, datacenter_name = nil) convert_vm_mob_ref_to_attr_hash(get_vm_ref(id, datacenter_name)) end end class Mock def get_template(id, datacenter_name = nil) end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/requests/compute/get_virtual_machine.rb000066400000000000000000000040051263403543000266210ustar00rootroot00000000000000module Fog module Compute class Vsphere class Real def get_virtual_machine(id, datacenter_name = nil) # The larger the VM list the longer it will take if not searching based on UUID. convert_vm_mob_ref_to_attr_hash(get_vm_ref(id, datacenter_name)) end protected def get_vm_ref(id, dc = nil) raw_datacenter = find_raw_datacenter(dc) if dc vm = case is_uuid?(id) # UUID based when true params = {:uuid => id, :vmSearch => true, :instanceUuid => true} params[:datacenter] = raw_datacenter if dc @connection.searchIndex.FindByUuid(params) else # try to find based on VM name if dc get_vm_by_name(id, dc) else raw_datacenters.map { |d| get_vm_by_name(id, d["name"])}.compact.first end end vm ? vm : raise(Fog::Compute::Vsphere::NotFound, "#{id} was not found") end def get_vm_by_name(name, dc) vms = raw_list_all_virtual_machines(dc) if name.include?('/') folder = File.dirname(name) basename = File.basename(name) vms.keep_if { |v| v["name"] == basename && v.parent.pretty_path.include?(folder) }.first else vms.keep_if { |v| v["name"] == name }.first end end end class Mock def get_virtual_machine(id, datacenter_name = nil) if is_uuid?(id) vm = list_virtual_machines({ 'instance_uuid' => id, 'datacenter' => datacenter_name }).first else # try to find based on VM name. May need to handle the path of the VM vm = list_virtual_machines({ 'name' => id, 'datacenter' => datacenter_name }).first end vm ? vm : raise(Fog::Compute::Vsphere::NotFound, "#{id} was not found") end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/requests/compute/get_vm_first_scsi_controller.rb000066400000000000000000000013361263403543000305700ustar00rootroot00000000000000 module Fog module Compute class Vsphere class Real def get_vm_first_scsi_controller(vm_id) Fog::Compute::Vsphere::SCSIController.new(get_vm_first_scsi_controller_raw(vm_id)) end def get_vm_first_scsi_controller_raw(vm_id) ctrl=get_vm_ref(vm_id).config.hardware.device.grep(RbVmomi::VIM::VirtualSCSIController).select{ | ctrl | ctrl.key == 1000 }.first { :type => ctrl.class.to_s, :shared_bus => ctrl.sharedBus.to_s, :unit_number => ctrl.scsiCtlrUnitNumber, :key => ctrl.key, } end end class Mock def get_vm_first_scsi_controller(vm_id) end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/requests/compute/list_child_snapshots.rb000066400000000000000000000043151263403543000270340ustar00rootroot00000000000000module Fog module Compute class Vsphere class Real def list_child_snapshots(snapshot, opts = {}) normalized_snapshot = Hash === snapshot ? Snapshot.new(snapshot.update(:service => self)) : snapshot child_snapshots = normalized_snapshot.tree_node.childSnapshotList.map do |snap| item = child_snapshot_info(snap, normalized_snapshot) [ item, opts[:recursive] ? list_child_snapshots(item, opts) : nil ] end child_snapshots.flatten.compact end protected def child_snapshot_info(snap_tree, parent_snap) { :name => snap_tree.name, :quiesced => snap_tree.quiesced, :description => snap_tree.description, :create_time => snap_tree.createTime, :power_state => snap_tree.state, :ref => snap_tree.snapshot._ref, :mo_ref => snap_tree.snapshot, :tree_node => snap_tree, :snapshot_name_chain => "#{parent_snap.snapshot_name_chain}/#{snap_tree.name}", :ref_chain => "#{parent_snap.ref_chain}/#{snap_tree.snapshot._ref}" } end end class Mock def list_child_snapshots(snapshot, opts = {}) [ { :name => 'clean', :quiesced => false, :description => '', :create_time => Time.now.utc, :power_state => 'poweredOn', :ref => 'snapshot-0101', :mo_ref => nil, :tree_node => nil, :snapshot_name_chain => '123/clean', :ref_chain => '123/snap-0101' }, { :name => 'dirty', :quiesced => false, :description => '', :create_time => Time.now.utc, :power_state => 'poweredOn', :ref => 'snapshot-0102', :mo_ref => nil, :tree_node => nil, :snapshot_name_chain => '123/dirty', :ref_chain => '123/snap-0102' } ] end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/requests/compute/list_clusters.rb000066400000000000000000000043331263403543000255130ustar00rootroot00000000000000module Fog module Compute class Vsphere class Real def list_clusters(filters = { }) datacenter_name = filters[:datacenter] raw_clusters(datacenter_name).map do |cluster| cluster_attributes(cluster, datacenter_name) end end def raw_clusters(datacenter) folder ||= find_raw_datacenter(datacenter).hostFolder @raw_clusters = get_raw_clusters_from_folder(folder) end protected def get_raw_clusters_from_folder(folder) folder.childEntity.map do |child_entity| if child_entity.is_a? RbVmomi::VIM::ComputeResource child_entity elsif child_entity.is_a? RbVmomi::VIM::Folder get_raw_clusters_from_folder(child_entity) end end.flatten end def cluster_attributes cluster, datacenter_name { :id => managed_obj_id(cluster), :name => cluster.name, :full_path => cluster_path(cluster, datacenter_name), :num_host => cluster.summary.numHosts, :num_cpu_cores => cluster.summary.numCpuCores, :overall_status => cluster.summary.overallStatus, :datacenter => datacenter_name || parent_attribute(cluster.path, :datacenter)[1], } end def cluster_path(cluster, datacenter_name) datacenter = find_raw_datacenter(datacenter_name) cluster.pretty_path.gsub(/(#{datacenter_name}|#{datacenter.hostFolder.name})\//,'') end end class Mock def list_clusters(filters = { }) raw_clusters.map do |cluster| cluster end end def raw_clusters folder = self.data[:clusters] @raw_clusters = get_raw_clusters_from_folder(folder) end def get_raw_clusters_from_folder(folder) folder.map do |child| if child[:klass] == "RbVmomi::VIM::ComputeResource" child elsif child[:klass] == "RbVmomi::VIM::Folder" get_raw_clusters_from_folder(child[:clusters]) end end.flatten end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/requests/compute/list_compute_resources.rb000066400000000000000000000071341263403543000274170ustar00rootroot00000000000000module Fog module Compute class Vsphere class Real def list_compute_resources(filters = { }) datacenter_name = filters[:datacenter] # default to show all compute_resources only_active = filters[:effective] || false compute_resources = raw_compute_resources datacenter_name compute_resources.map do |compute_resource| summary = compute_resource.summary next if only_active and summary.numEffectiveHosts == 0 compute_resource_attributes(compute_resource, datacenter_name) end.compact end def raw_compute_resources(datacenter_name) find_raw_datacenter(datacenter_name).find_compute_resource('').children end protected def compute_resource_attributes compute_resource, datacenter overall_usage = compute_resource.host.inject({:overallCpuUsage=>0, :overallMemoryUsage=>0}) do |sum, host| { :overallCpuUsage => sum[:overallCpuUsage]+(host.summary.quickStats.overallCpuUsage || 0), :overallMemoryUsage=> sum[:overallMemoryUsage]+(host.summary.quickStats.overallMemoryUsage || 0) } end { :id => managed_obj_id(compute_resource), :name => compute_resource.name, :totalCpu => compute_resource.summary.totalCpu, :totalMemory => compute_resource.summary.totalMemory, :numCpuCores => compute_resource.summary.numCpuCores, :numCpuThreads => compute_resource.summary.numCpuThreads, :effectiveCpu => compute_resource.summary.effectiveCpu, :effectiveMemory => compute_resource.summary.effectiveMemory, :numHosts => compute_resource.summary.numHosts, :numEffectiveHosts => compute_resource.summary.numEffectiveHosts, :overallStatus => compute_resource.summary.overallStatus, :overallCpuUsage => overall_usage[:overallCpuUsage], :overallMemoryUsage => overall_usage[:overallMemoryUsage], :effective => compute_resource.summary.numEffectiveHosts > 0, :isSingleHost => compute_resource.summary.numHosts == 1 } end end class Mock def list_compute_resources(filters = { }) [ { :id=>"domain-s7", :name=>"fake-host", :totalCpu=>33504, :totalMemory=>154604142592, :numCpuCores=>12, :numCpuThreads=>24, :effectiveCpu=>32247, :effectiveMemory=>135733, :numHosts=>1, :numEffectiveHosts=>1, :overallStatus=>"gray", :overallCpuUsage=>15682, :overallMemoryUsage=>132755, :effective=>true, :isSingleHost=>true }, { :id=>"domain-s74", :name=>"fake-cluster", :totalCpu=>41484, :totalMemory=>51525996544, :numCpuCores=>12, :numCpuThreads=>24, :effectiveCpu=>37796, :effectiveMemory=>45115, :numHosts=>2, :numEffectiveHosts=>2, :overallStatus=>"gray", :overallCpuUsage=>584, :overallMemoryUsage=>26422, :effective=>true, :isSingleHost=>false } ] end end end end endfog-vsphere-0.4.0/lib/fog/vsphere/requests/compute/list_customfields.rb000066400000000000000000000007201263403543000263440ustar00rootroot00000000000000module Fog module Compute class Vsphere class Real def list_customfields() @connection.serviceContent.customFieldsManager.field.map do |customfield| { :key => customfield.key.to_i, :name => customfield.name, :type => customfield.type } end end end class Mock def list_vm_customfields() end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/requests/compute/list_datacenters.rb000066400000000000000000000025371263403543000261500ustar00rootroot00000000000000module Fog module Compute class Vsphere class Real def list_datacenters filters = {} raw_datacenters.map do |dc| { :id => managed_obj_id(dc), :name => dc.name, :path => raw_getpathmo(dc), :status => dc.overallStatus } end end protected def raw_getpathmo mo if mo.parent == nil or mo.parent.name == @connection.rootFolder.name then [ mo.name ] else [ raw_getpathmo(mo.parent), mo.name ].flatten end end def raw_datacenters folder=nil folder ||= @connection.rootFolder @raw_datacenters ||= get_raw_datacenters_from_folder folder end def get_raw_datacenters_from_folder folder=nil folder.childEntity.map do | childE | if childE.is_a? RbVmomi::VIM::Datacenter childE elsif childE.is_a? RbVmomi::VIM::Folder get_raw_datacenters_from_folder childE end end.flatten end def find_datacenters name=nil name ? [find_raw_datacenter(name)] : raw_datacenters end end class Mock def list_datacenters filters = {} self.data[:datacenters].values end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/requests/compute/list_datastores.rb000066400000000000000000000025511263403543000260200ustar00rootroot00000000000000module Fog module Compute class Vsphere class Real def list_datastores(filters = { }) datacenter_name = filters[:datacenter] # default to show all datastores only_active = filters[:accessible] || false raw_datastores(datacenter_name).map do |datastore| next if only_active and !datastore.summary.accessible datastore_attributes(datastore, datacenter_name) end.compact end def raw_datastores(datacenter_name) find_raw_datacenter(datacenter_name).datastore end protected def datastore_attributes datastore, datacenter { :id => managed_obj_id(datastore), :name => datastore.name, :accessible => datastore.summary.accessible, :type => datastore.summary.type, :freespace => datastore.summary.freeSpace, :capacity => datastore.summary.capacity, :uncommitted => datastore.summary.uncommitted, :datacenter => datacenter, } end end class Mock def list_datastores(datacenter_name) self.data[:datastores].values.select {|d| d['datacenter'] == datacenter_name[:datacenter]} or raise Fog::Compute::Vsphere::NotFound end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/requests/compute/list_folders.rb000066400000000000000000000030511263403543000253010ustar00rootroot00000000000000module Fog module Compute class Vsphere class Real # Grabs all sub folders within a given path folder. # # ==== Parameters # * filters<~Hash>: # * :datacenter<~String> - *REQUIRED* Your datacenter where you're # looking for folders. Example: 'my-datacenter-name' (passed if you # are using the models/collections) # eg: vspconn.datacenters.first.vm_folders('mypath') # * :path<~String> - Your path where you're looking for # more folders, if return = none you will get an error. If you don't # define it will look in the main datacenter folder for any folders # in that datacenter. # # Example Usage Testing Only: # vspconn = Fog::Compute[:vsphere] # mydc = vspconn.datacenters.first # folders = mydc.vm_folders # def list_folders(filters = { }) path = filters[:path] || filters['path'] || '' datacenter_name = filters[:datacenter] get_raw_vmfolders(path, datacenter_name).map do |folder| folder_attributes(folder, datacenter_name) end end protected def get_raw_vmfolders(path, datacenter_name) folder = get_raw_vmfolder(path, datacenter_name) child_folders(folder).flatten.compact end def child_folders folder [folder, folder.childEntity.grep(RbVmomi::VIM::Folder).map(&method(:child_folders)).flatten] end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/requests/compute/list_interface_types.rb000066400000000000000000000013611263403543000270310ustar00rootroot00000000000000module Fog module Compute class Vsphere class Real def list_interface_types(filters={}) datacenter_name = filters[:datacenter] servertype_name = filters[:servertype] get_raw_server_type(servertype_name, datacenter_name)[:supportedEthernetCard].map do | nictype | next if filters.key?(:id) and filters[:id] != nictype interface_type_attributes(nictype, servertype_name, datacenter_name) end.compact end def interface_type_attributes(nic, servertype, datacenter) { :id => nic, :name => nic, :datacenter => datacenter, :servertype => servertype } end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/requests/compute/list_networks.rb000066400000000000000000000023711263403543000255230ustar00rootroot00000000000000module Fog module Compute class Vsphere class Real def list_networks(filters = { }) datacenter_name = filters[:datacenter] # default to show all networks only_active = filters[:accessible] || false raw_networks(datacenter_name).map do |network| next if only_active and !network.summary.accessible network_attributes(network, datacenter_name) end.compact end def raw_networks(datacenter_name) find_raw_datacenter(datacenter_name).network end protected def network_attributes network, datacenter { :id => managed_obj_id(network), :name => network.name, :accessible => network.summary.accessible, :datacenter => datacenter, :virtualswitch => network.class.name == "DistributedVirtualPortgroup" ? network.config.distributedVirtualSwitch.name : nil } end end class Mock def list_networks(datacenter_name) self.data[:networks].values.select {|n| n['datacenter'] == datacenter_name[:datacenter]} or raise Fog::Compute::Vsphere::NotFound end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/requests/compute/list_processes.rb000066400000000000000000000020621263403543000256520ustar00rootroot00000000000000module Fog module Compute class Vsphere class Real def list_processes(vm_id, opts) vm = get_vm_ref(vm_id) auth = RbVmomi::VIM::NamePasswordAuthentication( :username => opts[:user], :password => opts[:password], :interactiveSession => false ) p_manager = @connection.serviceContent.guestOperationsManager.processManager processes = p_manager.ListProcessesInGuest(:vm => vm, :auth => auth) processes.map do |pi| Process.new( :cmd_line => pi.cmdLine, :end_time => pi.endTime, :exit_code => pi.exitCode, :name => pi.name, :owner => pi.owner, :pid => pi.pid, :start_time => pi.startTime ) end end end class Mock def list_processes(vm_id, opts = {}) [ Process.new(:name => 'winlogon'), Process.new(:name => 'init') ] end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/requests/compute/list_resource_pools.rb000066400000000000000000000023411263403543000267070ustar00rootroot00000000000000module Fog module Compute class Vsphere class Real def list_resource_pools(filters = { }) datacenter_name = filters[:datacenter] cluster_name = filters[:cluster] cluster = get_raw_cluster(cluster_name, datacenter_name) list_raw_resource_pools(cluster).map do |resource_pool| resource_pool_attributes(resource_pool, cluster_name, datacenter_name) end end protected # root ResourcePool + Children if they exists def list_raw_resource_pools(cluster) [cluster.resourcePool, cluster.resourcePool.resourcePool].flatten end def resource_pool_attributes resource_pool, cluster, datacenter { :id => managed_obj_id(resource_pool), :name => resource_pool.name, :configured_memory_mb => resource_pool.summary.configuredMemoryMB, :overall_status => resource_pool.overallStatus, :cluster => cluster, :datacenter => datacenter } end end class Mock def list_resource_pools(filters = { }) end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/requests/compute/list_rules.rb000066400000000000000000000016101263403543000247740ustar00rootroot00000000000000module Fog module Compute class Vsphere class Real def list_rules(filters = {}) cluster = get_raw_cluster(filters[:cluster], filters[:datacenter]) cluster.configurationEx.rule.map {|r| rule_attributes r, filters} end protected def rule_attributes(rule, filters) { datacenter: filters[:datacenter], cluster: filters[:cluster], key: rule[:key], name: rule[:name], enabled: rule[:enabled], type: rule.class, vm_ids: rule[:vm].map {|vm| vm.config.instanceUuid } } end end class Mock def list_rules(filters = {}) self.data[:rules].values.select {|r| r[:datacenter] == filters[:datacenter] && r[:cluster] == filters[:cluster]} end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/requests/compute/list_server_types.rb000066400000000000000000000033361263403543000264030ustar00rootroot00000000000000module Fog module Compute class Vsphere class Real def list_server_types(filters={}) datacenter_name = filters[:datacenter] servertypes=raw_server_types(datacenter_name) if servertypes servertypes.map do | servertype | server_type_attributes(servertype, datacenter_name) end.compact else nil end #select{ | guestdesc | guestdesc.select{ | k, v | filter.has_key?(k) and filter[k] == v }==filter } end def raw_server_types(datacenter_name, filter={}) datacenter=find_raw_datacenter(datacenter_name) environmentBrowser=datacenter.hostFolder.childEntity.grep(RbVmomi::VIM::ComputeResource).first.environmentBrowser if environmentBrowser environmentBrowser.QueryConfigOption[:guestOSDescriptor] end end protected def server_type_attributes(servertype, datacenter) { :id => servertype.id, :name => servertype.id, :family => servertype.family, :fullname => servertype.fullName, :datacenter => datacenter, } end end class Mock def list_server_types(datacenter_name) [{:id=>"rhel6Guest", :name=>"rhel6Guest", :family=>"linuxGuest", :fullname=>"Red Hat Enterprise Linux 6 (32-Bit)", :datacenter=>"Solutions"}, {:id=>"rhel5_64Guest", :name=>"rhel5_64Guest", :family=>"linuxGuest", :fullname=>"Red Hat Enterprise Linux 5 (64-Bit)", :datacenter=>"Solutions"}] end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/requests/compute/list_storage_pods.rb000066400000000000000000000024531263403543000263410ustar00rootroot00000000000000module Fog module Compute class Vsphere class Real def list_storage_pods(filters = { }) datacenter_name = filters[:datacenter] raw_storage_pods(datacenter_name).map do |storage_pod| storage_pod_attributes(storage_pod, datacenter_name) end.compact end private def raw_storage_pods(datacenter_name) dc = find_raw_datacenter(datacenter_name) @connection.serviceContent.viewManager.CreateContainerView({ :container => dc, :type => ["StoragePod"], :recursive => true }).view end protected def storage_pod_attributes storage_pod, datacenter { :id => managed_obj_id(storage_pod), :name => storage_pod.name, :freespace => storage_pod.summary.freeSpace, :capacity => storage_pod.summary.capacity, :datacenter => datacenter, } end end class Mock def list_storage_pods(filters = {}) if filters.key?(:datacenter) self.data[:storage_pods].select{|h| h[:datacenter] == filters[:datacenter] } else self.data[:storage_pods] end end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/requests/compute/list_templates.rb000066400000000000000000000027031263403543000256440ustar00rootroot00000000000000module Fog module Compute class Vsphere class Real def list_templates(options = { }) options[:folder] ||= options['folder'] if options[:folder] then list_all_templates_in_folder(options[:folder], options[:datacenter]) else list_all_templates(options) end end private def list_all_templates_in_folder(path, datacenter_name) folder = get_raw_vmfolder(path, datacenter_name) vms = folder.children.grep(RbVmomi::VIM::VirtualMachine) # remove all virtual machines that are not template vms.delete_if { |v| v.config.nil? or not v.config.template } vms.map(&method(:convert_vm_mob_ref_to_attr_hash)) end def list_all_templates(options = {}) datacenters = find_datacenters(options[:datacenter]) vms = datacenters.map do |dc| @connection.serviceContent.viewManager.CreateContainerView({ :container => dc.vmFolder, :type => ["VirtualMachine"], :recursive => true }).view end.flatten # remove all virtual machines that are not templates vms.delete_if { |v| v.config.nil? or not v.config.template } vms.map(&method(:convert_vm_mob_ref_to_attr_hash)) end end class Mock def list_templates(filters = { }) end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/requests/compute/list_virtual_machines.rb000066400000000000000000000066601263403543000272110ustar00rootroot00000000000000module Fog module Compute class Vsphere class Real def list_virtual_machines(options = { }) # Listing all VM's can be quite slow and expensive. Try and optimize # based on the available options we have. These conditions are in # ascending order of time to complete for large deployments. options[:folder] ||= options['folder'] if options['instance_uuid'] then [get_virtual_machine(options['instance_uuid'])] elsif options[:folder] && options[:datacenter] then list_all_virtual_machines_in_folder(options[:folder], options[:datacenter]) else list_all_virtual_machines(options) end end private def list_all_virtual_machines_in_folder(path, datacenter_name) folder = get_raw_vmfolder(path, datacenter_name) vms = folder.children.grep(RbVmomi::VIM::VirtualMachine) # remove all template based virtual machines vms.delete_if { |v| v.config.nil? or v.config.template } vms.map(&method(:convert_vm_mob_ref_to_attr_hash)) end def list_all_virtual_machines(options = { }) raw_vms = raw_list_all_virtual_machines(options[:datacenter]) vms = convert_vm_view_to_attr_hash(raw_vms) # remove all template based virtual machines vms.delete_if { |v| v['template'] } vms end def raw_list_all_virtual_machines(datacenter_name = nil) ## Moved this to its own function since trying to get a list of all virtual machines ## to parse for a find function took way too long. The raw list returned will make it ## much faster to interact for some functions. datacenters = find_datacenters(datacenter_name) datacenters.map do |dc| @connection.serviceContent.viewManager.CreateContainerView({ :container => dc.vmFolder, :type => ["VirtualMachine"], :recursive => true }).view end.flatten end def get_folder_path(folder, root = nil) if (not folder.methods.include?('parent')) or (folder == root) return end "#{get_folder_path(folder.parent)}/#{folder.name}" end end class Mock def get_folder_path(folder, root = nil) nil end def list_virtual_machines(options = { }) if options['instance_uuid'] server = self.data[:servers][options['instance_uuid']] server.nil? ? [] : [server] elsif options['mo_ref'] self.data[:servers].values.select{|vm| vm['mo_ref'] == options['mo_ref']} elsif options[:folder] and options[:datacenter] self.data[:servers].values.select {|vm| vm['path'] == options[:folder] && vm['datacenter'] == options[:datacenter]} else options.delete('datacenter') # real code iterates if this is missing options.reject! {|k,v| v.nil? } # ignore options with nil value self.data[:servers].values.select {|vm| options.all? {|k,v| vm[k.to_s] == v.to_s }} end end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/requests/compute/list_vm_cdroms.rb000066400000000000000000000021441263403543000256360ustar00rootroot00000000000000module Fog module Compute class Vsphere class Real def list_vm_cdroms(vm_id) get_vm_ref(vm_id).config.hardware.device.select { |hw| hw.class == RbVmomi::VIM::VirtualCdrom }.map do |cdrom| { :filename => (cdrom.backing.fileName rescue(nil)), :name => cdrom.deviceInfo.label, :key => cdrom.key, :controller_key => cdrom.controllerKey, :unit_number => cdrom.unitNumber, :start_connected => cdrom.connectable.startConnected, :allow_guest_control => cdrom.connectable.allowGuestControl, :connected => cdrom.connectable.connected, :instance_uuid => vm_id, } end end end class Mock def list_vm_cdroms(vm_id) raise Fog::Compute::Vsphere::NotFound, 'VM not Found' unless self.data[:servers].key?(vm_id) return [] unless self.data[:servers][vm_id].key?('cdroms') self.data[:servers][vm_id]['cdroms'].map {|h| h.merge({:instance_uuid => vm_id}) } end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/requests/compute/list_vm_customvalues.rb000066400000000000000000000006501263403543000271010ustar00rootroot00000000000000module Fog module Compute class Vsphere class Real def list_vm_customvalues(vm_id) get_vm_ref(vm_id).summary.customValue.map do |customvalue| { :key => customvalue.key.to_i, :value => customvalue.value, } end end end class Mock def list_vm_customfields(vm_id) end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/requests/compute/list_vm_interfaces.rb000066400000000000000000000047371263403543000265040ustar00rootroot00000000000000module Fog module Compute class Vsphere class Real # => VirtualE1000( #addressType: "assigned", #backing: VirtualEthernetCardNetworkBackingInfo( # deviceName: "VM Network", # dynamicProperty: [], # network: Network("network-163"), # useAutoDetect: false #), #connectable: VirtualDeviceConnectInfo( # allowGuestControl: true, # connected: true, # dynamicProperty: [], # startConnected: true, # status: "ok" #), #controllerKey: 100, #deviceInfo: Description( # dynamicProperty: [], # label: "Network adapter 1", # summary: "VM Network" #), #dynamicProperty: [], #key: 4000, #macAddress: "00:50:56:a9:00:28", #unitNumber: 7, # def list_vm_interfaces(vm_id, datacenter = nil) get_raw_interfaces(vm_id, datacenter).map {|nic| raw_to_hash nic} end def get_vm_interface(vm_id, options={}) raw = get_raw_interface(vm_id, options) if raw raw_to_hash(raw) else nil end end def get_raw_interfaces(vm_id, datacenter = nil) get_vm_ref(vm_id, datacenter).config.hardware.device.grep(RbVmomi::VIM::VirtualEthernetCard) end def get_raw_interface(vm_id, options={}) raise ArgumentError, "instance id is a required parameter" unless vm_id if options.is_a? Fog::Compute::Vsphere::Interface options else raise ArgumentError, "Either key or name is a required parameter. options: #{options}" unless options.key? :key or options.key? :mac or options.key? :name get_raw_interfaces(vm_id).find do |nic| (options.key? :key and nic.key==options[:key].to_i) or (options.key? :mac and nic.macAddress==options[:mac]) or (options.key? :name and nic.deviceInfo.label==options[:name]) end end end private def raw_to_hash(nic) { :name => nic.deviceInfo.label, :mac => nic.macAddress, :network => nic.backing.respond_to?("network") ? nic.backing.network.name : nic.backing.port.portgroupKey, :status => nic.connectable.status, :summary => nic.deviceInfo.summary, :type => nic.class, :key => nic.key, } end end class Mock def list_vm_interfaces(vm_id) end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/requests/compute/list_vm_snapshots.rb000066400000000000000000000041031263403543000263660ustar00rootroot00000000000000module Fog module Compute class Vsphere class Real def list_vm_snapshots(vm_id, opts = {}) vm_snapshot_info = get_vm_ref(vm_id).snapshot return [] unless vm_snapshot_info root_snapshots = vm_snapshot_info.rootSnapshotList.map do |snap| item = snapshot_info(snap, vm_id) [ item, opts[:recursive] ? list_child_snapshots(item, opts) : nil ] end root_snapshots.flatten.compact end protected def snapshot_info(snap_tree, vm_id) { :name => snap_tree.name, :quiesced => snap_tree.quiesced, :description => snap_tree.description, :create_time => snap_tree.createTime, :power_state => snap_tree.state, :ref => snap_tree.snapshot._ref, :mo_ref => snap_tree.snapshot, :tree_node => snap_tree, :ref_chain => "#{vm_id}/#{snap_tree.snapshot._ref}", :snapshot_name_chain => "#{vm_id}/#{snap_tree.name}" } end end class Mock def list_vm_snapshots(vm_id, opts = {}) [ { :name => 'clean', :quiesced => false, :description => '', :create_time => Time.now.utc, :power_state => 'poweredOn', :ref => 'snapshot-0101', :mo_ref => nil, :tree_node => nil, :snapshot_name_chain => '123/clean', :ref_chain => "#{vm_id}/snapshot-0101" }, { :name => 'dirty', :quiesced => false, :description => '', :create_time => Time.now.utc, :power_state => 'poweredOn', :ref => 'snapshot-0102', :mo_ref => nil, :tree_node => nil, :snapshot_name_chain => '123/dirty', :ref_chain => "#{vm_id}/snapshot-0102" } ] end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/requests/compute/list_vm_volumes.rb000066400000000000000000000026651263403543000260510ustar00rootroot00000000000000module Fog module Compute class Vsphere class Real # [VirtualDisk( # backing: VirtualDiskFlatVer2BackingInfo( # contentId: "a172d19487e878e17d6b16ff2505d7eb", # datastore: Datastore("datastore-162"), # diskMode: "persistent", # dynamicProperty: [], # fileName: "[Storage1] rhel6-mfojtik/rhel6-mfojtik.vmdk", # split: false, # thinProvisioned: true, # uuid: "6000C29c-a47d-4cd9-5249-c371de775f06", # writeThrough: false # ), # capacityInKB: 8388608, # controllerKey: 1000, # deviceInfo: Description( # dynamicProperty: [], # label: "Hard disk 1", # summary: "8,388,608 KB" # ), # dynamicProperty: [], # key: 2001, # shares: SharesInfo( dynamicProperty: [], level: "normal", shares: 1000 ), # unitNumber: 1 #)] def list_vm_volumes(vm_id) get_vm_ref(vm_id).disks.map do |vol| { :id => vol.backing.uuid, :thin => (vol.backing.thinProvisioned rescue(nil)), :mode => vol.backing.diskMode, :filename => vol.backing.fileName, :datastore => (vol.backing.datastore.name rescue(nil)), :size => vol.capacityInKB, :name => vol.deviceInfo.label, :key => vol.key, :unit_number => vol.unitNumber } end end end class Mock def list_vm_volumes(vm_id) end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/requests/compute/modify_vm_cdrom.rb000066400000000000000000000017031263403543000257670ustar00rootroot00000000000000module Fog module Compute class Vsphere class Real def add_vm_cdrom(cdrom) vm_reconfig_hardware('instance_uuid' => cdrom.server.instance_uuid, 'hardware_spec' => {'deviceChange'=>[create_cdrom(cdrom, cdrom.unit_number, :add)]}) end def destroy_vm_cdrom(cdrom) vm_reconfig_hardware('instance_uuid' => cdrom.server.instance_uuid, 'hardware_spec' => {'deviceChange'=>[create_cdrom(cdrom, cdrom.unit_number, :remove)]}) end end class Mock def add_vm_cdrom(cdrom) vm_reconfig_hardware('instance_uuid' => cdrom.server.instance_uuid, 'hardware_spec' => {'deviceChange'=>[create_cdrom(cdrom, cdrom.unit_number, :add)]}) end def destroy_vm_cdrom(cdrom) vm_reconfig_hardware('instance_uuid' => cdrom.server.instance_uuid, 'hardware_spec' => {'deviceChange'=>[create_cdrom(cdrom, cdrom.unit_number, :remove)]}) end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/requests/compute/modify_vm_interface.rb000066400000000000000000000055621263403543000266320ustar00rootroot00000000000000module Fog module Compute class Vsphere class Real def add_vm_interface(vmid, options = {}) raise ArgumentError, "instance id is a required parameter" unless vmid interface = get_interface_from_options(vmid, options.merge(:server_id => vmid)) vm_reconfig_hardware('instance_uuid' => vmid, 'hardware_spec' => {'deviceChange'=>[create_interface(interface, 0, :add, options)]}) end def destroy_vm_interface(vmid, options = {}) raise ArgumentError, "instance id is a required parameter" unless vmid interface = get_interface_from_options(vmid, options.merge(:server_id => vmid)) vm_reconfig_hardware('instance_uuid' => vmid, 'hardware_spec' => {'deviceChange'=>[create_interface(interface, interface.key, :remove)]}) end def update_vm_interface(vmid, options = {}) raise ArgumentError, "instance id is a required parameter" unless vmid interface = get_interface_from_options(vmid, options) raw_interface = get_raw_interface(vmid, key: interface.key) if options[:network] interface.network = options[:network] backing = create_nic_backing(interface, {}) raw_interface.backing = backing end spec = { operation: :edit, device: raw_interface } vm_reconfig_hardware('instance_uuid' => vmid, 'hardware_spec' => {'deviceChange'=>[spec]}) end private def get_interface_from_options(vmid, options) if options and options[:interface] options[:interface] elsif options[:key] and options[:key]>0 oldattributes = get_vm_interface(vmid, options) Fog::Compute::Vsphere::Interface.new(oldattributes.merge(options)) elsif options[:type] and options[:network] Fog::Compute::Vsphere::Interface.new options else raise ArgumentError, "interface is a required parameter or pass options with type and network" end end end class Mock def add_vm_interface(vmid, options = {}) raise ArgumentError, "instance id is a required parameter" unless vmid raise ArgumentError, "interface is a required parameter" unless options and options[:interface] true end def destroy_vm_interface(vmid, options = {}) raise ArgumentError, "instance id is a required parameter" unless vmid raise ArgumentError, "interface is a required parameter" unless options and options[:interface] true end def update_vm_interface(vmid, options = {}) return unless options[:interface] options[:interface].network = options[:network] options[:interface].type = options[:type] end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/requests/compute/modify_vm_volume.rb000066400000000000000000000014321263403543000261710ustar00rootroot00000000000000module Fog module Compute class Vsphere class Real def add_vm_volume(volume) vm_reconfig_hardware('instance_uuid' => volume.server_id, 'hardware_spec' => {'deviceChange'=>[create_disk(volume, volume.unit_number, :add)]}) end def destroy_vm_volume(volume) vm_reconfig_hardware('instance_uuid' => volume.server_id, 'hardware_spec' => {'deviceChange'=>[create_disk(volume, volume.unit_number, :remove)]}) end end class Mock def add_vm_volume(volume) vm_reconfig_hardware('instance_uuid' => volume.server_id, 'hardware_spec' => {'deviceChange'=>[create_cdrom(volume, volume.unit_number, :add)]}) end def destroy_vm_volume(volume) true end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/requests/compute/revert_to_snapshot.rb000066400000000000000000000012001263403543000265320ustar00rootroot00000000000000module Fog module Compute class Vsphere class Real def revert_to_snapshot(snapshot) unless Snapshot === snapshot fail ArgumentError, 'snapshot is a required parameter' end task = snapshot.mo_ref.RevertToSnapshot_Task task.wait_for_completion { 'state' => task.info.state } end end class Mock def revert_to_snapshot(snapshot) fail ArgumentError, 'snapshot is a required parameter' if snapshot.nil? { 'state' => 'success' } end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/requests/compute/set_vm_customvalue.rb000066400000000000000000000005431263403543000265370ustar00rootroot00000000000000module Fog module Compute class Vsphere class Real def set_vm_customvalue(vm_id, key, value) vm_ref = get_vm_ref(vm_id) vm_ref.setCustomValue(:key => key, :value => value) end end class Mock def set_vm_customvalue(vm_id, key, value) nil end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/requests/compute/upload_iso.rb000066400000000000000000000032051263403543000247470ustar00rootroot00000000000000module Fog module Compute class Vsphere class Real def upload_iso_check_options(options) default_options = { 'upload_directory' => 'isos', } options = default_options.merge(options) required_options = %w{ datacenter datastore local_path } required_options.each do |param| raise ArgumentError, "#{required_options.join(', ')} are required" unless options.key? param end raise Fog::Compute::Vsphere::NotFound, "Datacenter #{options["datacenter"]} Doesn't Exist!" unless get_datacenter(options["datacenter"]) raise Fog::Compute::Vsphere::NotFound, "Datastore #{options["datastore"]} Doesn't Exist!" unless get_raw_datastore(options['datastore'], options['datacenter']) options end def upload_iso(options = {}) options = upload_iso_check_options(options) datastore = get_raw_datastore(options['datastore'], options['datacenter']) datacenter = get_datacenter(options['datacenter']) filename = options['filename'] || File.basename(options['local_path']) unless datastore.exists? options['upload_directory']+'/' @connection.serviceContent.fileManager.MakeDirectory :name => "[#{options['datastore']}] #{options['directory']}", :datacenter => datacenter, :createParentDirectories => false end datastore.upload options['upload_directory']+'/'+filename, options['local_path'] end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/requests/compute/vm_clone.rb000066400000000000000000001510751263403543000244240ustar00rootroot00000000000000module Fog module Compute class Vsphere module Shared private def vm_clone_check_options(options) default_options = { 'force' => false, 'linked_clone' => false, 'nic_type' => 'VirtualE1000', } options = default_options.merge(options) options["storage_pod"] = nil if options["storage_pod"] == '' # Backwards compat for "path" option options["template_path"] ||= options["path"] options["path"] ||= options["template_path"] required_options = %w{ datacenter template_path name } required_options.each do |param| raise ArgumentError, "#{required_options.join(', ')} are required" unless options.key? param end raise Fog::Compute::Vsphere::NotFound, "Datacenter #{options["datacenter"]} Doesn't Exist!" unless get_datacenter(options["datacenter"]) raise Fog::Compute::Vsphere::NotFound, "Template #{options["template_path"]} Doesn't Exist!" unless get_virtual_machine(options["template_path"], options["datacenter"]) raise Fog::Compute::Vsphere::NotFound, "Storage Pod #{options["storage_pod"]} Doesn't Exist!" if options.key?('storage_pod') and ! get_storage_pod(options['storage_pod'], options['datacenter']) options end end class Real include Shared # Clones a VM from a template or existing machine on your vSphere # Server. # # ==== Parameters # * options<~Hash>: # * 'datacenter'<~String> - *REQUIRED* Datacenter name your cloning # in. Make sure this datacenter exists, should if you're using # the clone function in server.rb model. # * 'template_path'<~String> - *REQUIRED* The path to the machine you # want to clone FROM. Relative to Datacenter (Example: # "FolderNameHere/VMNameHere") # * 'name'<~String> - *REQUIRED* The VMName of the Destination # * 'dest_folder'<~String> - Destination Folder of where 'name' will # be placed on your cluster. Relative Path to Datacenter E.G. # "FolderPlaceHere/anotherSub Folder/onemore" # * 'power_on'<~Boolean> - Whether to power on machine after clone. # Defaults to true. # * 'wait'<~Boolean> - Whether the method should wait for the virtual # machine to finish cloning before returning information from # vSphere. Broken right now as you cannot return a model of a serer # that isn't finished cloning. Defaults to True # * 'resource_pool'<~Array> - The resource pool on your datacenter # cluster you want to use. Only works with clusters within same # same datacenter as where you're cloning from. Datacenter grabbed # from template_path option. # Example: ['cluster_name_here','resource_pool_name_here'] # * 'datastore'<~String> - The datastore you'd like to use. # (datacenterObj.datastoreFolder.find('name') in API) # * 'storage_pod'<~String> - The storage pod / datastore cluster you'd like to use. # * 'transform'<~String> - Not documented - see http://www.vmware.com/support/developer/vc-sdk/visdk41pubs/ApiReference/vim.vm.RelocateSpec.html # * 'numCPUs'<~Integer> - the number of Virtual CPUs of the Destination VM # * 'memoryMB'<~Integer> - the size of memory of the Destination VM in MB # * customization_spec<~Hash>: Options are marked as required if you # use this customization_spec. # As defined https://pubs.vmware.com/vsphere-55/index.jsp#com.vmware.wssdk.apiref.doc/vim.vm.customization.Specification.html # * encryptionKey <~array of bytes> Used to encrypt/decrypt password # * globalIPSettings expects a hash, REQUIRED # * identity expects a hash, REQUIRED - either LinuxPrep, Sysprep or SysprepText # * nicSettingMap expects an array # * options expects a hash # * All options can be parsed using a yaml template with cloudinit_to_customspec.rb # # OLD Values still supported: # This only support cloning and setting DHCP on the first interface # * 'domain'<~String> - *REQUIRED* This is put into # /etc/resolve.conf (we hope) # * 'hostname'<~String> - Hostname of the Guest Os - default is # options['name'] # * 'hw_utc_clock'<~Boolean> - *REQUIRED* Is hardware clock UTC? # Default true # * 'time_zone'<~String> - *REQUIRED* Only valid linux options # are valid - example: 'America/Denver' # * 'interfaces' <~Array> - interfaces object to apply to # the template when cloning: overrides the # network_label, network_adapter_device_key and nic_type attributes # * 'volumes' <~Array> - volumes object to apply to # the template when cloning: this allows to resize the # existing disks as well as add or remove them. The # resizing is applied only when the size is bigger then the # in size in the template def vm_clone(options = {}) # Option handling options = vm_clone_check_options(options) # Added for people still using options['path'] template_path = options['path'] || options['template_path'] # Options['template_path']<~String> # Added for people still using options['path'] template_path = options['path'] || options['template_path'] # Now find the template itself using the efficient find method vm_mob_ref = get_vm_ref(template_path, options['datacenter']) # Options['dest_folder']<~String> # Grab the destination folder object if it exists else use cloned mach dest_folder_path = options.fetch('dest_folder','/') # default to root path ({dc_name}/vm/) dest_folder = get_raw_vmfolder(dest_folder_path, options['datacenter']) # Options['resource_pool']<~Array> # Now find _a_ resource pool to use for the clone if one is not specified if ( options.key?('resource_pool') && options['resource_pool'].is_a?(Array) && options['resource_pool'].length == 2 && options['resource_pool'][1] != 'Resources') cluster_name = options['resource_pool'][0] pool_name = options['resource_pool'][1] resource_pool = get_raw_resource_pool(pool_name, cluster_name, options['datacenter']) elsif ( vm_mob_ref.resourcePool == nil ) # If the template is really a template then there is no associated resource pool, # so we need to find one using the template's parent host or cluster esx_host = vm_mob_ref.collect!('runtime.host')['runtime.host'] # The parent of the ESX host itself is a ComputeResource which has a resourcePool resource_pool = esx_host.parent.resourcePool end # If the vm given did return a valid resource pool, default to using it for the clone. # Even if specific pools aren't implemented in this environment, we will still get back # at least the cluster or host we can pass on to the clone task # This catches if resource_pool option is set but comes back nil and if resourcePool is # already set. resource_pool ||= vm_mob_ref.resourcePool.nil? ? esx_host.parent.resourcePool : vm_mob_ref.resourcePool # Options['datastore']<~String> # Grab the datastore object if option is set datastore_obj = get_raw_datastore(options['datastore'], options['datacenter']) if options.key?('datastore') # confirm nil if nil or option is not set datastore_obj ||= nil virtual_machine_config_spec = RbVmomi::VIM::VirtualMachineConfigSpec() device_change = [] # fully futured interfaces api: replace the current nics # with the new based on the specification if (options.key?('interfaces') ) if options.key?('network_label') raise ArgumentError, "interfaces option can't be specified together with network_label" end device_change.concat(modify_template_nics_specs(template_path, options['interfaces'], options['datacenter'])) elsif options.key?('network_label') device_change << modify_template_nics_simple_spec(options['network_label'], options['nic_type'], options['network_adapter_device_key'], options['datacenter']) end if disks = options['volumes'] device_change.concat(modify_template_volumes_specs(vm_mob_ref, options['volumes'])) end virtual_machine_config_spec.deviceChange = device_change if device_change.any? # Options['numCPUs'] or Options['memoryMB'] # Build up the specification for Hardware, for more details see ____________ # https://github.com/rlane/rbvmomi/blob/master/test/test_serialization.rb # http://www.vmware.com/support/developer/vc-sdk/visdk41pubs/ApiReference/vim.vm.ConfigSpec.html # FIXME: pad this out with the rest of the useful things in VirtualMachineConfigSpec virtual_machine_config_spec.numCPUs = options['numCPUs'] if ( options.key?('numCPUs') ) virtual_machine_config_spec.memoryMB = options['memoryMB'] if ( options.key?('memoryMB') ) virtual_machine_config_spec.cpuHotAddEnabled = options['cpuHotAddEnabled'] if ( options.key?('cpuHotAddEnabled') ) virtual_machine_config_spec.memoryHotAddEnabled = options['memoryHotAddEnabled'] if ( options.key?('memoryHotAddEnabled') ) virtual_machine_config_spec.firmware = options['firmware'] if ( options.key?('firmware') ) # Options['customization_spec'] # OLD Options still supported # * domain <~String> - *REQUIRED* - Sets the server's domain for customization # * dnsSuffixList <~Array> - Optional - Sets the dns search paths in resolv - Example: ["dev.example.com", "example.com"] # * time_zone <~String> - Required - Only valid linux options are valid - example: 'America/Denver' # * ipsettings <~Hash> - Optional - If not set defaults to dhcp # * ip <~String> - *REQUIRED* Sets the ip address of the VM - Example: 10.0.0.10 # * dnsServerList <~Array> - Optional - Sets the nameservers in resolv - Example: ["10.0.0.2", "10.0.0.3"] # * gateway <~Array> - Optional - Sets the gateway for the interface - Example: ["10.0.0.1"] # * subnetMask <~String> - *REQUIRED* - Set the netmask of the interface - Example: "255.255.255.0" # For other ip settings options see http://www.vmware.com/support/developer/vc-sdk/visdk41pubs/ApiReference/vim.vm.customization.IPSettings.html # # Implement complete customization spec as per https://pubs.vmware.com/vsphere-55/index.jsp#com.vmware.wssdk.apiref.doc/vim.vm.customization.Specification.html # * encryptionKey <~Array> - Optional, encryption key used to encypt any encrypted passwords # https://pubs.vmware.com/vsphere-51/index.jsp#com.vmware.wssdk.apiref.doc/vim.vm.customization.GlobalIPSettings.html # * globalIPSettings <~Hash> - REQUIRED # * dnsServerList <~Array> - Optional, list of dns servers - Example: ["10.0.0.2", "10.0.0.3"] # * dnsSuffixList <~Array> - Optional, List of name resolution suffixes - Example: ["dev.example.com", "example.com"] # * identity <~Hash> - REQUIRED, Network identity and settings, similar to Microsoft's Sysprep tool. This is a Sysprep, LinuxPrep, or SysprepText object # * Sysprep <~Hash> - Optional, representation of a Windows sysprep.inf answer file. # * guiRunOnce: <~Hash> -Optional, representation of the sysprep GuiRunOnce key # * commandList: <~Array> - REQUIRED, list of commands to run at first user logon, after guest customization. - Example: ["c:\sysprep\runaftersysprep.cmd", "c:\sysprep\installpuppet.ps1"] # * guiUnattended: <~Hash> - REQUIRED, representation of the sysprep GuiUnattended key # * autoLogin: boolean - REQUIRED, Flag to determine whether or not the machine automatically logs on as Administrator. # * autoLogonCount: int - REQUIRED, specifies the number of times the machine should automatically log on as Administrator # * password: <~Hash> - REQUIRED, new administrator password for the machine # * plainText: boolean - REQUIRED, specify whether or not the password is in plain text, rather than encrypted # * value: <~String> - REQUIRED, password string # * timeZone: <~int> - REQUIRED, (see here for values https://msdn.microsoft.com/en-us/library/ms912391(v=winembedded.11).aspx) # * identification: <~Hash> - REQUIRED, representation of the sysprep Identification key # * domainAdmin: <~String> - Optional, domain user account used for authentication if the virtual machine is joining a domain # * domainAdminPassword: <~Hash> - Optional, password for the domain user account used for authentication # * plainText: boolean - REQUIRED, specify whether or not the password is in plain text, rather than encrypted # * value: <~String> - REQUIRED, password string # * joinDomain: <~String> - Optional, The domain that the virtual machine should join. If this value is supplied, then domainAdmin and domainAdminPassword must also be supplied # * joinWorkgroup: <~String> - Optional, The workgroup that the virtual machine should join. # * licenseFilePrintData: <~Hash> - Optional, representation of the sysprep LicenseFilePrintData key # * autoMode: <~String> - REQUIRED, Server licensing mode. Two strings are supported: 'perSeat' or 'perServer' # * autoUsers: <~Int> - Optional, This key is valid only if AutoMode = PerServer. The integer value indicates the number of client licenses # * userData: <~Hash> - REQUIRED, representation of the sysprep UserData key # * computerName: <~String> - REQUIRED, The computer name of the (Windows) virtual machine. Will be truncates to 15 characters # * fullName: <~String> - REQUIRED, User's full name # * orgName: <~String> - REQUIRED, User's organization # * productId: <~String> - REQUIRED, serial number for os, ignored if using volume licensed instance # * LinuxPrep: <~Hash> - Optional, contains machine-wide settings (note the uppercase P) # * domain: <~String> - REQUIRED, The fully qualified domain name. # * hostName: <~String> - REQUIRED, the network host name # * hwClockUTC: <~Boolean> - Optional, Specifies whether the hardware clock is in UTC or local time # * timeZone: <~String> - Optional, Case sensistive timezone, valid values can be found at https://pubs.vmware.com/vsphere-51/topic/com.vmware.wssdk.apiref.doc/timezone.html # * SysprepText: <~Hash> - Optional, alternate way to specify the sysprep.inf answer file. # * value: <~String> - REQUIRED, Text for the sysprep.inf answer file. # * nicSettingMap: <~Array> - Optional, IP settings that are specific to a particular virtual network adapter # * Each item in array: # * adapter: <~Hash> - REQUIRED, IP settings for the associated virtual network adapter # * dnsDomain: <~String> - Optional, DNS domain suffix for adapter # * dnsServerList: <~Array> - Optional, list of dns server ip addresses - Example: ["10.0.0.2", "10.0.0.3"] # * gateway: <~Array> - Optional, list of gateways - Example: ["10.0.0.2", "10.0.0.3"] # * ip: <~String> - Optional, but required if static IP # * ipV6Spec: <~Hash> - Optional, IPv^ settings # * ipAddress: <~String> - Optional, but required if setting static IP # * gateway: <~Array> - Optional, list of ipv6 gateways # * netBIOS: <~String> - Optional, NetBIOS settings, if supplied must be one of: disableNetBIOS','enableNetBIOS','enableNetBIOSViaDhcp' # * primaryWINS: <~String> - Optional, IP address of primary WINS server # * secondaryWINS: <~String> - Optional, IP address of secondary WINS server # * subnetMask: <~String> - Optional, subnet mask for adapter # * macAddress: <~String> - Optional, MAC address of adapter being customized. This cannot be set by the client # * options: <~Hash> Optional operations, currently only win options have any value # * changeSID: <~Boolean> - REQUIRED, The customization process should modify the machine's security identifier # * deleteAccounts: <~Boolean> - REQUIRED, If deleteAccounts is true, then all user accounts are removed from the system # * reboot: <~String> - Optional, (defaults to reboot), Action to be taken after running sysprep, must be one of: 'noreboot', 'reboot', 'shutdown' # if ( options.key?('customization_spec') ) custom_spec = options['customization_spec'] # backwards compatablity if custom_spec.key?('domain') # doing this means the old options quash any new ones passed as well... might not be the best way to do it? # any 'old' options overwrite the following: # - custom_spec['identity']['LinuxPrep'] # - custom_spec['globalIPSettings['['dnsServerList'] # - custom_spec['globalIPSettings']['dnsSuffixList'] # - custom_spec['nicSettingMap'][0]['adapter']['ip'] # - custom_spec['nicSettingMap'][0]['adapter']['gateway'] # - custom_spec['nicSettingMap'][0]['adapter']['subnetMask'] # - custom_spec['nicSettingMap'][0]['adapter']['dnsDomain'] # - custom_spec['nicSettingMap'][0]['adapter']['dnsServerList'] # # we can assume old parameters being passed cust_hostname = custom_spec['hostname'] || options['name'] custom_spec['identity'] = Hash.new unless custom_spec.key?('identity') custom_spec['identity']['LinuxPrep'] = {"domain" => custom_spec['domain'], "hostName" => cust_hostname, "timeZone" => custom_spec['time_zone']} if custom_spec.key?('ipsettings') custom_spec['globalIPSettings']=Hash.new unless custom_spec.key?('globalIPSettings') custom_spec['globalIPSettings']['dnsServerList'] = custom_spec['ipsettings']['dnsServerList'] if custom_spec['ipsettings'].key?('dnsServerList') custom_spec['globalIPSettings']['dnsSuffixList'] = custom_spec['dnsSuffixList'] || [custom_spec['domain']] if ( custom_spec['dnsSuffixList'] || custom_spec['domain']) end if (custom_spec['ipsettings'].key?('ip') or custom_spec['ipsettings'].key?('gateway') or custom_spec['ipsettings'].key?('subnetMask') or custom_spec['ipsettings'].key?('domain') or custom_spec['ipsettings'].key?('dnsServerList')) if custom_spec['ipsettings'].key?('ip') raise ArgumentError, "subnetMask is required for static ip" unless custom_spec["ipsettings"].key?("subnetMask") end custom_spec['nicSettingMap']=Array.new unless custom_spec.key?('nicSettingMap') custom_spec['nicSettingMap'][0]=Hash.new unless custom_spec['nicSettingMap'].length > 0 custom_spec['nicSettingMap'][0]['adapter']=Hash.new unless custom_spec['nicSettingMap'][0].key?('adapter') custom_spec['nicSettingMap'][0]['adapter']['ip'] = custom_spec['ipsettings']['ip'] if custom_spec['ipsettings'].key?('ip') custom_spec['nicSettingMap'][0]['adapter']['gateway'] = custom_spec['ipsettings']['gateway'] if custom_spec['ipsettings'].key?('gateway') custom_spec['nicSettingMap'][0]['adapter']['subnetMask'] = custom_spec['ipsettings']['subnetMask'] if custom_spec['ipsettings'].key?('subnetMask') custom_spec['nicSettingMap'][0]['adapter']['dnsDomain'] = custom_spec['ipsettings']['domain'] if custom_spec['ipsettings'].key?('domain') custom_spec['nicSettingMap'][0]['adapter']['dnsServerList'] = custom_spec['ipsettings']['dnsServerList'] if custom_spec['ipsettings'].key?('dnsServerList') end end ### End of backwards compatability ## requirements check here ## raise ArgumentError, "globalIPSettings are required when using Customization Spec" unless custom_spec.key?('globalIPSettings') raise ArgumentError, "identity is required when using Customization Spec" unless custom_spec.key?('identity') # encryptionKey custom_encryptionKey = custom_spec['encryptionKey'] if custom_spec.key?('encryptionKey') custom_encryptionKey ||= nil # globalIPSettings # https://pubs.vmware.com/vsphere-55/index.jsp#com.vmware.wssdk.apiref.doc/vim.vm.customization.GlobalIPSettings.html custom_globalIPSettings = RbVmomi::VIM::CustomizationGlobalIPSettings.new() custom_globalIPSettings.dnsServerList = custom_spec['globalIPSettings']['dnsServerList'] if custom_spec['globalIPSettings'].key?("dnsServerList") custom_globalIPSettings.dnsSuffixList = custom_spec['globalIPSettings']['dnsSuffixList'] if custom_spec['globalIPSettings'].key?("dnsSuffixList") # identity # https://pubs.vmware.com/vsphere-55/index.jsp#com.vmware.wssdk.apiref.doc/vim.vm.customization.IdentitySettings.html # Accepts the 3 supported CustomizationIdentitySettings Types: # 1. CustomizationLinuxPrep (LinuxPrep) - note the uppercase P # 2. CustomizationSysprep (Sysprep) # 3. CustomizationSysprepText (SysprepText) # At least one of these is required # identity = custom_spec['identity'] if identity.key?("LinuxPrep") # https://pubs.vmware.com/vsphere-55/index.jsp#com.vmware.wssdk.apiref.doc/vim.vm.customization.LinuxPrep.html # Fields: # * domain: string **REQUIRED** # * hostName: string (CustomizationName) **REQUIRED** Will use options['name'] if not provided. # * hwClockUTC: boolean # * timeZone: string (https://pubs.vmware.com/vsphere-55/topic/com.vmware.wssdk.apiref.doc/timezone.html) raise ArgumentError, "domain is required when using LinuxPrep identity" unless identity['LinuxPrep'].key?('domain') custom_identity = RbVmomi::VIM::CustomizationLinuxPrep(:domain => identity['LinuxPrep']['domain']) cust_hostname = RbVmomi::VIM::CustomizationFixedName(:name => identity['LinuxPrep']['hostName']) if identity['LinuxPrep'].key?('hostName') cust_hostname ||= RbVmomi::VIM::CustomizationFixedName(:name => options['name']) custom_identity.hostName = cust_hostname custom_identity.hwClockUTC = identity['LinuxPrep']['hwClockUTC'] if identity['LinuxPrep'].key?('hwClockUTC') custom_identity.timeZone = identity['LinuxPrep']['timeZone'] if identity['LinuxPrep'].key?('timeZone') elsif identity.key?("Sysprep") # https://pubs.vmware.com/vsphere-55/index.jsp#com.vmware.wssdk.apiref.doc/vim.vm.customization.Sysprep.html # Fields: # * guiRunOnce: CustomizationGuiRunOnce # * guiUnattended: CustomizationGuiUnattended **REQUIRED** # * identification: CustomizationIdentification **REQUIRED** # * licenseFilePrintData: CustomizationLicenseFilePrintData # * userData: CustomizationUserData **REQUIRED** # raise ArgumentError, "guiUnattended is required when using Sysprep identity" unless identity['Sysprep'].key?('guiUnattended') raise ArgumentError, "identification is required when using Sysprep identity" unless identity['Sysprep'].key?('identification') raise ArgumentError, "userData is required when using Sysprep identity" unless identity['Sysprep'].key?('userData') if identity['Sysprep']['guiRunOnce'] # https://pubs.vmware.com/vsphere-55/index.jsp#com.vmware.wssdk.apiref.doc/vim.vm.customization.GuiRunOnce.html # Fields: # * commandList: array of string **REQUIRED*** # raise ArgumentError, "commandList is required when using Sysprep identity and guiRunOnce" unless identity['Sysprep']['guiRunOnce'].key?('commandList') cust_guirunonce = RbVmomi::VIM.CustomizationGuiRunOnce( :commandList => identity['Sysprep']['guiRunOnce']['commandList'] ) end # https://pubs.vmware.com/vsphere-55/index.jsp#com.vmware.wssdk.apiref.doc/vim.vm.customization.GuiUnattended.html # Fields: # * autoLogin: boolean **REQUIRED** # * autoLogonCount: int **REQUIRED** # * timeZone: int (see here for values https://msdn.microsoft.com/en-us/library/ms912391(v=winembedded.11).aspx) **REQUIRED** # * password: CustomizationPassword raise ArgumentError, "guiUnattended->autoLogon is required when using Sysprep identity" unless identity['Sysprep']['guiUnattended'].key?('autoLogon') raise ArgumentError, "guiUnattended->autoLogonCount is required when using Sysprep identity" unless identity['Sysprep']['guiUnattended'].key?('autoLogonCount') raise ArgumentError, "guiUnattended->timeZone is required when using Sysprep identity" unless identity['Sysprep']['guiUnattended'].key?('timeZone') custom_guiUnattended = RbVmomi::VIM.CustomizationGuiUnattended( :autoLogon => identity['Sysprep']['guiUnattended']['autoLogon'], :autoLogonCount => identity['Sysprep']['guiUnattended']['autoLogonCount'], :timeZone => identity['Sysprep']['guiUnattended']['timeZone'] ) if identity['Sysprep']['guiUnattended']['password'] # https://pubs.vmware.com/vsphere-55/index.jsp#com.vmware.wssdk.apiref.doc/vim.vm.customization.Password.html # Fields: # * plainText: boolean **REQUIRED** # * value: string **REQUIRED** raise ArgumentError, "guiUnattended->password->plainText is required when using Sysprep identity and guiUnattended -> password" unless identity['Sysprep']['guiUnattended']['password'].key?('plainText') raise ArgumentError, "guiUnattended->password->value is required when using Sysprep identity and guiUnattended -> password" unless identity['Sysprep']['guiUnattended']['password'].key?('value') custom_guiUnattended.password = RbVmomi::VIM.CustomizationPassword( :plainText => identity['Sysprep']['guiUnattended']['password']['plainText'], :value => identity['Sysprep']['guiUnattended']['password']['value'] ) end # https://pubs.vmware.com/vsphere-55/index.jsp#com.vmware.wssdk.apiref.doc/vim.vm.customization.Identification.html # Fields: # * domainAdmin: string # * domainAdminPassword: CustomizationPassword # * joinDomain: string *If supplied domainAdmin and domainAdminPassword must be set # * joinWorkgroup: string *If supplied, joinDomain, domainAdmin and domainAdminPassword will be ignored custom_identification = RbVmomi::VIM.CustomizationIdentification() if identity['Sysprep']['identification'].key?('joinWorkgroup') custom_identification.joinWorkgroup = identity['Sysprep']['identification']['joinWorkgroup'] elsif identity['Sysprep']['identification'].key?('joinDomain') raise ArgumentError, "identification->domainAdmin is required when using Sysprep identity and identification -> joinDomain" unless identity['Sysprep']['identification'].key?('domainAdmin') raise ArgumentError, "identification->domainAdminPassword is required when using Sysprep identity and identification -> joinDomain" unless identity['Sysprep']['identification'].key?('domainAdmin') raise ArgumentError, "identification->domainAdminPassword->plainText is required when using Sysprep identity and identification -> joinDomain" unless identity['Sysprep']['identification']['domainAdminPassword'].key?('plainText') raise ArgumentError, "identification->domainAdminPassword->value is required when using Sysprep identity and identification -> joinDomain" unless identity['Sysprep']['identification']['domainAdminPassword'].key?('value') custom_identification.joinDomain = identity['Sysprep']['identification']['joinDomain'] custom_identification.domainAdmin = identity['Sysprep']['identification']['domainAdmin'] # https://pubs.vmware.com/vsphere-55/index.jsp#com.vmware.wssdk.apiref.doc/vim.vm.customization.Password.html # Fields: # * plainText: boolean **REQUIRED** # * value: string **REQUIRED** custom_identification.domainAdminPassword = RbVmomi::VIM.CustomizationPassword( :plainText => identity['Sysprep']['identification']['domainAdminPassword']['plainText'], :value => identity['Sysprep']['identification']['domainAdminPassword']['value'] ) else raise ArgumentError, "No valid Indentification found, valid values are 'joinWorkgroup' and 'joinDomain'" end if identity['Sysprep'].key?('licenseFilePrintData') # https://pubs.vmware.com/vsphere-55/index.jsp#com.vmware.wssdk.apiref.doc/vim.vm.customization.LicenseFilePrintData.html # Fields: # * autoMode: string (CustomizationLicenseDataMode) ** REQUIRED **, valid strings are: 'perSeat' or 'perServer' # * autoUsers: int (valid only if AutoMode = PerServer) raise ArgumentError, "licenseFilePrintData->autoMode is required when using Sysprep identity and licenseFilePrintData" unless identity['Sysprep']['licenseFilePrintData'].key?('autoMode') raise ArgumentError, "Unsupported autoMode, supported modes are : 'perSeat' or 'perServer'" unless ['perSeat', 'perServer'].include? identity['Sysprep']['licenseFilePrintData']['autoMode'] custom_licenseFilePrintData = RbVmomi::VIM.CustomizationLicenseFilePrintData( :autoMode => RbVmomi::VIM.CustomizationLicenseDataMode(identity['Sysprep']['licenseFilePrintData']['autoMode']) ) if identity['Sysprep']['licenseFilePrintData'].key?('autoUsers') custom_licenseFilePrintData.autoUsers = identity['Sysprep']['licenseFilePrintData']['autoUsers'] if identity['Sysprep']['licenseFilePrintData']['autoMode'] == "PerServer" end end # https://pubs.vmware.com/vsphere-55/index.jsp#com.vmware.wssdk.apiref.doc/vim.vm.customization.UserData.html # Fields: # * computerName: string (CustomizationFixedName) **REQUIRED** # * fullName: string **REQUIRED** # * orgName: string **REQUIRED** # * productID: string **REQUIRED** raise ArgumentError, "userData->computerName is required when using Sysprep identity" unless identity['Sysprep']['userData'].key?('computerName') raise ArgumentError, "userData->fullName is required when using Sysprep identity" unless identity['Sysprep']['userData'].key?('fullName') raise ArgumentError, "userData->orgName is required when using Sysprep identity" unless identity['Sysprep']['userData'].key?('orgName') raise ArgumentError, "userData->productId is required when using Sysprep identity" unless identity['Sysprep']['userData'].key?('productId') custom_userData = RbVmomi::VIM.CustomizationUserData( :fullName => identity['Sysprep']['userData']['fullName'], :orgName => identity['Sysprep']['userData']['orgName'], :productId => identity['Sysprep']['userData']['productId'], :computerName => RbVmomi::VIM.CustomizationFixedName(:name => identity['Sysprep']['userData']['computerName']) ) custom_identity = RbVmomi::VIM::CustomizationSysprep( :guiUnattended => custom_guiUnattended, :identification => custom_identification, :userData => custom_userData ) custom_identity.guiRunOnce = cust_guirunonce if defined?(cust_guirunonce) custom_identity.licenseFilePrintData = custom_licenseFilePrintData if defined?(custom_licenseFilePrintData) elsif identity.key?("SysprepText") # https://pubs.vmware.com/vsphere-55/index.jsp#com.vmware.wssdk.apiref.doc/vim.vm.customization.SysprepText.html # Fields: # * value: string **REQUIRED** raise ArgumentError, "SysprepText -> value is required when using SysprepText identity" unless identity['SysprepText'].key?('value') custom_identity = RbVmomi::VIM::CustomizationSysprepText(:value => identity['SysprepText']['value']) else raise ArgumentError, "At least one of the following valid identities must be supplied: LinuxPrep, Sysprep, SysprepText" end if custom_spec.key?("nicSettingMap") # custom_spec['nicSettingMap'] is an array of adapater mappings: # custom_spec['nicSettingMap'][0]['macAddress'] # custom_spec['nicSettingMap'][0]['adapter']['ip'] #https://pubs.vmware.com/vsphere-55/index.jsp#com.vmware.wssdk.apiref.doc/vim.vm.customization.AdapterMapping.html # Fields: # * adapter: CustomizationIPSettings **REQUIRED** # * macAddress: string raise ArgumentError, "At least one nicSettingMap is required when using nicSettingMap" unless custom_spec['nicSettingMap'].length > 0 raise ArgumentError, "Adapter is required when using nicSettingMap" unless custom_spec['nicSettingMap'][0].key?('adapter') custom_nicSettingMap = [] # need to go through array here for each apapter custom_spec['nicSettingMap'].each do | nic | # https://pubs.vmware.com/vsphere-55/index.jsp?topic=%2Fcom.vmware.wssdk.apiref.doc%2Fvim.vm.customization.IPSettings.html # Fields: # * dnsDomain: string # * gateway: array of string # * ip: CustomizationIpGenerator (string) **REQUIRED IF Assigning Static IP*** # * ipV6Spec: CustomizationIPSettingsIpV6AddressSpec # * netBIOS: CustomizationNetBIOSMode (string) # * primaryWINS: string # * secondaryWINS: string # * subnetMask: string - Required if assigning static IP if nic['adapter'].key?('ip') raise ArgumentError, "SubnetMask is required when assigning static IP when using nicSettingMap -> Adapter" unless nic['adapter'].key?('subnetMask') custom_ip = RbVmomi::VIM.CustomizationFixedIp(:ipAddress => nic['adapter']['ip']) else custom_ip = RbVmomi::VIM::CustomizationDhcpIpGenerator.new() end custom_adapter = RbVmomi::VIM.CustomizationIPSettings(:ip => custom_ip) custom_adapter.dnsDomain = nic['adapter']['dnsDomain'] if nic['adapter'].key?('dnsDomain') custom_adapter.dnsServerList = nic['adapter']['dnsServerList'] if nic['adapter'].key?('dnsServerList') custom_adapter.gateway = nic['adapter']['gateway'] if nic['adapter'].key?('gateway') if nic['adapter'].key?('ipV6Spec') # https://pubs.vmware.com/vsphere-55/index.jsp#com.vmware.wssdk.apiref.doc/vim.vm.customization.IPSettings.IpV6AddressSpec.html # Fields: # * gateway: array of string # * ip: CustomizationIpV6Generator[] **Required if setting static IP ** if nic['adapter']['ipV6Spec'].key?('ipAddress') raise ArgumentError, "SubnetMask is required when assigning static IPv6 when using nicSettingMap -> Adapter -> ipV6Spec" unless nic['adapter']['ipV6Spec'].key?('subnetMask') # https://pubs.vmware.com/vsphere-55/index.jsp#com.vmware.wssdk.apiref.doc/vim.vm.customization.FixedIpV6.html # * ipAddress: string **REQUIRED** # * subnetMask: int **REQUIRED** custom_ipv6 = RbVmomi::VIM.CustomizationFixedIpV6( :ipAddress => nic['adapter']['ipV6Spec']['ipAddress'], :subnetMask => nic['adapter']['ipV6Spec']['subnetMask'] ) else custom_ipv6 = RbVmomi::VIM::CustomizationDhcpIpV6Generator.new() end custom_ipv6Spec = RbVmomi::VIM.CustomizationIPSettingsIpV6AddressSpec(:ip => custom_ipv6) custom_ipv6Spec.gateway = nic['adapter']['ipV6Spec']['gateway'] if nic['adapter']['ipV6Spec'].key?('gateway') custom_adapter.ipV6Spec = custom_ipv6Spec end if nic['adapter'].key?('netBIOS') # https://pubs.vmware.com/vsphere-55/index.jsp#com.vmware.wssdk.apiref.doc/vim.vm.customization.IPSettings.NetBIOSMode.html # Fields: # netBIOS: string matching: 'disableNetBIOS','enableNetBIOS' or 'enableNetBIOSViaDhcp' ** REQUIRED ** # raise ArgumentError, "Unsupported NetBIOSMode, supported modes are : 'disableNetBIOS','enableNetBIOS' or 'enableNetBIOSViaDhcp'" unless ['disableNetBIOS','enableNetBIOS','enableNetBIOSViaDhcp'].include? nic['adapter']['netBIOS'] custom_adapter.netBIOS = RbVmomi::VIM.CustomizationNetBIOSMode(nic['adapter']['netBIOS']) end custom_adapter.primaryWINS = nic['adapter']['primaryWINS'] if nic['adapter'].key?('primaryWINS') custom_adapter.secondaryWINS = nic['adapter']['secondaryWINS'] if nic['adapter'].key?('secondaryWINS') custom_adapter.subnetMask = nic['adapter']['subnetMask'] if nic['adapter'].key?('subnetMask') custom_adapter_mapping = RbVmomi::VIM::CustomizationAdapterMapping(:adapter => custom_adapter) custom_adapter_mapping.macAddress = nic['macAddress'] if nic.key?('macAddress') # build the adapters array, creates it if not already created, otherwise appends to it custom_nicSettingMap << custom_adapter_mapping end end custom_nicSettingMap = nil if custom_nicSettingMap.length < 1 if custom_spec.key?("options") # https://pubs.vmware.com/vsphere-55/index.jsp#com.vmware.wssdk.apiref.doc/vim.vm.customization.Options.html # this currently doesn't have any Linux options, just windows # Fields: # * changeSID: boolean **REQUIRED** # * deleteAccounts: boolean **REQUIRED** **note deleteAccounts is deprecated as of VI API 2.5 so can be ignored # * reboot: CustomizationSysprepRebootOption: (string) one of following 'noreboot', reboot' or 'shutdown' (defaults to reboot) raise ArgumentError, "changeSID id required when using Windows Options" unless custom_spec['options'].key?('changeSID') raise ArgumentError, "deleteAccounts id required when using Windows Options" unless custom_spec['options'].key?('deleteAccounts') custom_options = RbVmomi::VIM::CustomizationWinOptions( :changeSID => custom_spec['options']['changeSID'], :deleteAccounts => custom_spec['options']['deleteAccounts'] ) if custom_spec['options'].key?('reboot') raise ArgumentError, "Unsupported reboot option, supported options are : 'noreboot', 'reboot' or 'shutdown'" unless ['noreboot','reboot','shutdown'].include? custom_spec['options']['reboot'] custom_options.reboot = RBVmomi::VIM.CustomizationSysprepRebootOption(custom_spec['options']['reboot']) end end custom_options ||=nil # https://pubs.vmware.com/vsphere-55/index.jsp#com.vmware.wssdk.apiref.doc/vim.vm.customization.Specification.html customization_spec = RbVmomi::VIM::CustomizationSpec( :globalIPSettings => custom_globalIPSettings, :identity => custom_identity ) customization_spec.encryptionKey = custom_encryptionKey if defined?(custom_encryptionKey) customization_spec.nicSettingMap = custom_nicSettingMap if defined?(custom_nicSettingMap) customization_spec.options = custom_options if defined?(custom_options) end customization_spec ||= nil relocation_spec=nil if ( options['linked_clone'] ) # Storage DRS does not support vSphere linked clones. # http://www.vmware.com/files/pdf/techpaper/vsphere-storage-drs-interoperability.pdf raise ArgumentError, "linked clones are not supported on storage pods" unless options.key?('storage_pod') # cribbed heavily from the rbvmomi clone_vm.rb # this chunk of code reconfigures the disk of the clone source to be read only, # and then creates a delta disk on top of that, this is required by the API in order to create # linked clondes disks = vm_mob_ref.config.hardware.device.select do |vm_device| vm_device.class == RbVmomi::VIM::VirtualDisk end disks.select{|vm_device| vm_device.backing.parent == nil}.each do |disk| disk_spec = { :deviceChange => [ { :operation => :remove, :device => disk }, { :operation => :add, :fileOperation => :create, :device => disk.dup.tap{|disk_backing| disk_backing.backing = disk_backing.backing.dup; disk_backing.backing.fileName = "[#{disk.backing.datastore.name}]"; disk_backing.backing.parent = disk.backing } } ] } vm_mob_ref.ReconfigVM_Task(:spec => disk_spec).wait_for_completion end # Next, create a Relocation Spec instance relocation_spec = RbVmomi::VIM.VirtualMachineRelocateSpec(:datastore => datastore_obj, :pool => resource_pool, :diskMoveType => :moveChildMostDiskBacking) else relocation_spec = RbVmomi::VIM.VirtualMachineRelocateSpec(:pool => resource_pool, :transform => options['transform'] || 'sparse') unless options.key?('storage_pod') and datastore_obj.nil? relocation_spec[:datastore] = datastore_obj end end # And the clone specification clone_spec = RbVmomi::VIM.VirtualMachineCloneSpec(:location => relocation_spec, :config => virtual_machine_config_spec, :customization => customization_spec, :powerOn => options.key?('power_on') ? options['power_on'] : true, :template => false) # Perform the actual Clone Task # Clone VM on a storage pod if options.key?('storage_pod') raise ArgumentError, "need to use at least vsphere revision 5.0 or greater to use storage pods" unless @vsphere_rev.to_f >= 5 pod_spec = RbVmomi::VIM::StorageDrsPodSelectionSpec.new( :storagePod => get_raw_storage_pod(options['storage_pod'], options['datacenter']), ) storage_spec = RbVmomi::VIM::StoragePlacementSpec.new( :type => 'clone', :folder => dest_folder, :resourcePool => resource_pool, :podSelectionSpec => pod_spec, :cloneSpec => clone_spec, :cloneName => options['name'], :vm => vm_mob_ref, ) srm = @connection.serviceContent.storageResourceManager result = srm.RecommendDatastores(:storageSpec => storage_spec) # if result array contains recommendation, we can apply it if key = result.recommendations.first.key task = srm.ApplyStorageDrsRecommendation_Task(:key => [key]) if options.fetch('wait', true) then result = task.wait_for_completion new_vm = result.vm else new_vm = nil Fog.wait_for(150, 15) { begin new_vm = dest_folder.find(options['name'], RbVmomi::VIM::VirtualMachine) or raise Fog::Vsphere::Errors::NotFound rescue Fog::Vsphere::Errors::NotFound new_vm = nil end } raise Fog::Vsphere::Errors::NotFound unless new_vm end end else task = vm_mob_ref.CloneVM_Task(:folder => dest_folder, :name => options['name'], :spec => clone_spec) # Waiting for the VM to complete allows us to get the VirtulMachine # object of the new machine when it's done. It is HIGHLY recommended # to set 'wait' => true if your app wants to wait. Otherwise, you're # going to have to reload the server model over and over which # generates a lot of time consuming API calls to vmware. if options.fetch('wait', true) then # REVISIT: It would be awesome to call a block passed to this # request to notify the application how far along in the process we # are. I'm thinking of updating a progress bar, etc... new_vm = task.wait_for_completion else new_vm = nil Fog.wait_for(150, 15) { begin new_vm = dest_folder.find(options['name'], RbVmomi::VIM::VirtualMachine) or raise Fog::Vsphere::Errors::NotFound rescue Fog::Vsphere::Errors::NotFound new_vm = nil end } raise Fog::Vsphere::Errors::NotFound unless new_vm end end # Return hash { 'vm_ref' => new_vm ? new_vm._ref : nil, 'new_vm' => new_vm ? convert_vm_mob_ref_to_attr_hash(new_vm) : nil, 'task_ref' => task._ref } end # Build up the network config spec for simple case: # simple case: apply just the network_label, nic_type and network_adapter_device_key def modify_template_nics_simple_spec(network_label, nic_type, network_adapter_device_key, datacenter) config_spec_operation = RbVmomi::VIM::VirtualDeviceConfigSpecOperation('edit') # Get the portgroup and handle it from there. network = get_raw_network(network_label, datacenter) if ( network.kind_of? RbVmomi::VIM::DistributedVirtualPortgroup) # Create the NIC backing for the distributed virtual portgroup nic_backing_info = RbVmomi::VIM::VirtualEthernetCardDistributedVirtualPortBackingInfo( :port => RbVmomi::VIM::DistributedVirtualSwitchPortConnection( :portgroupKey => network.key, :switchUuid => network.config.distributedVirtualSwitch.uuid ) ) else # Otherwise it's a non distributed port group nic_backing_info = RbVmomi::VIM::VirtualEthernetCardNetworkBackingInfo(:deviceName => network_label) end connectable = RbVmomi::VIM::VirtualDeviceConnectInfo( :allowGuestControl => true, :connected => true, :startConnected => true) device = RbVmomi::VIM.public_send "#{nic_type}", :backing => nic_backing_info, :deviceInfo => RbVmomi::VIM::Description(:label => "Network adapter 1", :summary => network_label), :key => network_adapter_device_key, :connectable => connectable device_spec = RbVmomi::VIM::VirtualDeviceConfigSpec( :operation => config_spec_operation, :device => device) return device_spec end def modify_template_nics_specs(template_path, new_nics, datacenter) template_nics = list_vm_interfaces(template_path, datacenter).map do |old_attributes| Fog::Compute::Vsphere::Interface.new(old_attributes) end specs = [] template_nics.each do |interface| specs << create_interface(interface, interface.key, :remove, :datacenter => datacenter) end new_nics.each do |interface| specs << create_interface(interface, 0, :add, :datacenter => datacenter) end return specs end def modify_template_volumes_specs(vm_mob_ref, volumes) template_volumes = vm_mob_ref.config.hardware.device.grep(RbVmomi::VIM::VirtualDisk) modified_volumes = volumes.take(template_volumes.size) new_volumes = volumes.drop(template_volumes.size) specs = [] template_volumes.zip(modified_volumes).each do |template_volume, new_volume| if new_volume # updated the attribtues on the existing volume # it's not allowed to reduce the size of the volume when cloning if new_volume.size > template_volume.capacityInKB template_volume.capacityInKB = new_volume.size end template_volume.backing.diskMode = new_volume.mode template_volume.backing.thinProvisioned = new_volume.thin specs << { :operation => :edit, :device => template_volume } else specs << { :operation => :remove, :fileOperation => :destroy, :device => template_volume } end end specs.concat(new_volumes.map { |volume| create_disk(volume, volumes.index(volume)) }) return specs end end class Mock include Shared def vm_clone(options = {}) # Option handling TODO Needs better method of checking options = vm_clone_check_options(options) notfound = lambda { raise Fog::Compute::Vsphere::NotFound, "Could not find VM template" } template = list_virtual_machines.find(notfound) do |vm| vm['name'] == options['template_path'].split("/")[-1] end # generate a random id id = [8,4,4,4,12].map{|i| Fog::Mock.random_hex(i)}.join("-") new_vm = template.clone.merge({ "name" => options['name'], "id" => id, "instance_uuid" => id, "path" => "/Datacenters/#{options['datacenter']}/#{options['dest_folder'] ? options['dest_folder']+"/" : ""}#{options['name']}" }) self.data[:servers][id] = new_vm { 'vm_ref' => "vm-#{Fog::Mock.random_numbers(3)}", 'new_vm' => new_vm, 'task_ref' => "task-#{Fog::Mock.random_numbers(4)}", } end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/requests/compute/vm_config_vnc.rb000066400000000000000000000033171263403543000254320ustar00rootroot00000000000000module Fog module Compute class Vsphere class Real def vm_config_vnc(options = { }) raise ArgumentError, "instance_uuid is a required parameter" unless options.key? 'instance_uuid' search_filter = { :uuid => options['instance_uuid'], 'vmSearch' => true, 'instanceUuid' => true } vm_mob_ref = @connection.searchIndex.FindAllByUuid(search_filter).first task = vm_mob_ref.ReconfigVM_Task(:spec => { :extraConfig => [ { :key => 'RemoteDisplay.vnc.enabled', :value => options[:enabled] ? 'true' : 'false' }, { :key => 'RemoteDisplay.vnc.password', :value => options[:password].to_s }, { :key => 'RemoteDisplay.vnc.port', :value => options[:port].to_s || '5910' } ] }) task.wait_for_completion { 'task_state' => task.info.state } end # return a hash of VNC attributes required to view the console def vm_get_vnc uuid search_filter = { :uuid => uuid, 'vmSearch' => true, 'instanceUuid' => true } vm = @connection.searchIndex.FindAllByUuid(search_filter).first Hash[vm.config.extraConfig.map do |config| if config.key =~ /^RemoteDisplay\.vnc\.(\w+)$/ [$1.to_sym, config.value] end end.compact] end end class Mock def vm_config_vnc(options = { }) raise ArgumentError, "instance_uuid is a required parameter" unless options.key? 'instance_uuid' { 'task_state' => 'success' } end def vm_get_vnc uuid {:password => 'secret', :port => '5900', :enabled => 'true'} end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/requests/compute/vm_destroy.rb000066400000000000000000000012161263403543000250040ustar00rootroot00000000000000module Fog module Compute class Vsphere class Real def vm_destroy(options = {}) raise ArgumentError, "instance_uuid is a required parameter" unless options.key? 'instance_uuid' vm_mob_ref = get_vm_ref(options['instance_uuid']) task = vm_mob_ref.Destroy_Task task.wait_for_completion { 'task_state' => task.info.state } end end class Mock def vm_destroy(options = {}) raise ArgumentError, "instance_uuid is a required parameter" unless options.key? 'instance_uuid' { 'task_state' => 'success' } end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/requests/compute/vm_execute.rb000066400000000000000000000050141263403543000247550ustar00rootroot00000000000000module Fog module Compute class Vsphere class Real # NOTE: you must be using vsphere_rev 5.0 or greater to use this functionality # e.g. Fog::Compute.new(provider: "vsphere", vsphere_rev: "5.5", etc) # * options<~Hash>: # * 'instance_uuid'<~String> - *REQUIRED* the instance uuid you would like to operate on # * 'command'<~String> *REQUIRED* the command to execute # * 'args'<~String> arguments to pass the command # * 'working_dir'<~String> path to the working directory # * 'user'<~String> *REQUIRED* the ssh username you would like to login as # * 'password'<~String> *REQUIRED* the ssh password for the user you would like to log in as def vm_execute(options = {}) raise ArgumentError, "instance_uuid is a required parameter" unless options.key? 'instance_uuid' raise ArgumentError, "command is a required parameter" unless options.key? 'command' raise ArgumentError, "user is a required parameter" unless options.key? 'user' raise ArgumentError, "password is a required parameter" unless options.key? 'password' search_filter = { :uuid => options['instance_uuid'], 'vmSearch' => true, 'instanceUuid' => true } vm_mob_ref = @connection.searchIndex.FindAllByUuid(search_filter).first auth = RbVmomi::VIM::NamePasswordAuthentication(:interactiveSession => false, :username => options['user'], :password => options['password']) spec = RbVmomi::VIM::GuestProgramSpec(:programPath => options['command'], :arguments => options['args'], :workingDirectory => options['working_dir']) gom = @connection.serviceContent.guestOperationsManager gom.processManager.StartProgramInGuest(:vm => vm_mob_ref, :auth => auth, :spec => spec) end end class Mock def vm_execute(options = {}) raise ArgumentError, "instance_uuid is a required parameter" unless options.key? 'instance_uuid' raise ArgumentError, "command is a required parameter" unless options.key? 'command' raise ArgumentError, "user is a required parameter" unless options.key? 'user' raise ArgumentError, "password is a required parameter" unless options.key? 'password' return 12345 end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/requests/compute/vm_migrate.rb000066400000000000000000000026011263403543000247420ustar00rootroot00000000000000module Fog module Compute class Vsphere class Real def vm_migrate(options = {}) #priority is the only required option, and it has a sane default option. priority = options['priority'].nil? ? 'defaultPriority' : options["priority"] raise ArgumentError, "instance_uuid is a required parameter" unless options.key? 'instance_uuid' # Find the VM Object search_filter = { :uuid => options['instance_uuid'], 'vmSearch' => true, 'instanceUuid' => true } vm_mob_ref = @connection.searchIndex.FindAllByUuid(search_filter).first unless vm_mob_ref.kind_of? RbVmomi::VIM::VirtualMachine raise Fog::Vsphere::Errors::NotFound, "Could not find VirtualMachine with instance uuid #{options['instance_uuid']}" end task = vm_mob_ref.MigrateVM_Task(:pool => options['pool'], :host => options['host'], :priority => "#{priority}", :state => options['state'] ) task.wait_for_completion { 'task_state' => task.info.state } end end class Mock def vm_migrate(options = {}) priority = options['priority'].nil? ? 'defaultPriority' : options["priority"] raise ArgumentError, "instance_uuid is a required parameter" unless options.key? 'instance_uuid' { 'task_state' => 'success' } end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/requests/compute/vm_power_off.rb000066400000000000000000000024601263403543000253030ustar00rootroot00000000000000module Fog module Compute class Vsphere class Real def vm_power_off(options = {}) options = { 'force' => false }.merge(options) raise ArgumentError, "instance_uuid is a required parameter" unless options.key? 'instance_uuid' search_filter = { :uuid => options['instance_uuid'], 'vmSearch' => true, 'instanceUuid' => true } vm_mob_ref = @connection.searchIndex.FindAllByUuid(search_filter).first if options['force'] then task = vm_mob_ref.PowerOffVM_Task task.wait_for_completion { 'task_state' => task.info.result, 'power_off_type' => 'cut_power' } else vm_mob_ref.ShutdownGuest { 'task_state' => "running", 'power_off_type' => 'shutdown_guest', } end end end class Mock def vm_power_off(options = {}) raise ArgumentError, "instance_uuid is a required parameter" unless options.key? 'instance_uuid' vm = get_virtual_machine(options['instance_uuid']) vm["power_state"] = "poweredOff" { 'task_state' => "running", 'power_off_type' => options['force'] ? 'cut_power' : 'shutdown_guest', } end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/requests/compute/vm_power_on.rb000066400000000000000000000015111263403543000251410ustar00rootroot00000000000000module Fog module Compute class Vsphere class Real def vm_power_on(options = {}) raise ArgumentError, "instance_uuid is a required parameter" unless options.key? 'instance_uuid' search_filter = { :uuid => options['instance_uuid'], 'vmSearch' => true, 'instanceUuid' => true } vm_mob_ref = @connection.searchIndex.FindAllByUuid(search_filter).first task = vm_mob_ref.PowerOnVM_Task task.wait_for_completion # 'success', 'running', 'queued', 'error' { 'task_state' => task.info.state } end end class Mock def vm_power_on(options = {}) raise ArgumentError, "instance_uuid is a required parameter" unless options.key? 'instance_uuid' { 'task_state' => 'success' } end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/requests/compute/vm_reboot.rb000066400000000000000000000021441263403543000246060ustar00rootroot00000000000000module Fog module Compute class Vsphere class Real def vm_reboot(options = {}) options = { 'force' => false }.merge(options) raise ArgumentError, "instance_uuid is a required parameter" unless options.key? 'instance_uuid' search_filter = { :uuid => options['instance_uuid'], 'vmSearch' => true, 'instanceUuid' => true } vm_mob_ref = @connection.searchIndex.FindAllByUuid(search_filter).first if options['force'] then task = vm_mob_ref.ResetVM_Task task.wait_for_completion { 'task_state' => task.info.result, 'reboot_type' => 'reset_power' } else vm_mob_ref.RebootGuest { 'task_state' => "running", 'reboot_type' => 'reboot_guest' } end end end class Mock def vm_reboot(options = {}) raise ArgumentError, "instance_uuid is a required parameter" unless options.key? 'instance_uuid' { 'task_state' => "running", 'reboot_type' => options['force'] ? 'reset_power' : 'reboot_guest' } end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/requests/compute/vm_reconfig_cdrom.rb000066400000000000000000000053041263403543000262750ustar00rootroot00000000000000module Fog module Compute class Vsphere class Real def vm_reconfig_cdrom(options = {}) raise ArgumentError, "instance_uuid is a required parameter" unless options.key? 'instance_uuid' # Attach iso / disattach if options.has_key?('iso') raise ArgumentError, "datastore is a required parameter" unless options.key? 'datastore' backing = RbVmomi::VIM::VirtualCdromIsoBackingInfo( fileName: "[#{options['datastore']}] #{options['iso']}" ) else backing = RbVmomi::VIM::VirtualCdromRemoteAtapiBackingInfo(deviceName: '') end cdrom_obj = get_vm_ref(options['instance_uuid']).config.hardware.device.grep(RbVmomi::VIM::VirtualCdrom).first hardware_spec = { deviceChange: [{ operation: :edit, device: RbVmomi::VIM::VirtualCdrom( backing: backing, key: cdrom_obj.key, controllerKey: cdrom_obj.controllerKey, connectable: RbVmomi::VIM::VirtualDeviceConnectInfo( startConnected: options['start_connected'] || false, connected: options['connected'] || false, allowGuestControl: options['allow_guest_control'] || true, ) ) }] } vm_reconfig_hardware('instance_uuid' => options['instance_uuid'], 'hardware_spec' => hardware_spec ) end end class Mock def vm_reconfig_cdrom(options = {}) raise ArgumentError, "instance_uuid is a required parameter" unless options.key? 'instance_uuid' if options.has_key?('iso') raise ArgumentError, "datastore is a required parameter" unless options.key? 'datastore' backing = { fileName: "[#{options['datastore']}] #{options['iso']}" } else backing = {deviceName: ''} end cdrom_obj = list_vm_cdroms(options['instance_uuid']).first hardware_spec = { deviceChange: [{ operation: :edit, device: { backing: backing, key: cdrom_obj['key'], controllerKey: cdrom_obj['controllerKey'], connectable: { startConnected: options['start_connected'] || false, connected: options['connected'] || false, allowGuestControl: options['allow_guest_control'] || true, } } }] } vm_reconfig_hardware('instance_uuid' => options['instance_uuid'], 'hardware_spec' => hardware_spec ) end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/requests/compute/vm_reconfig_cpus.rb000066400000000000000000000020351263403543000261410ustar00rootroot00000000000000module Fog module Compute class Vsphere class Real def vm_reconfig_cpus(options = {}) raise ArgumentError, "cpus is a required parameter" unless options.key? 'cpus' raise ArgumentError, "instance_uuid is a required parameter" unless options.key? 'instance_uuid' hardware_spec={'numCPUs' => options['cpus'], 'numCoresPerSocket' => options['corespersocket']} vm_reconfig_hardware('instance_uuid' => options['instance_uuid'], 'hardware_spec' => hardware_spec ) end end class Mock def vm_reconfig_cpus(options = {}) raise ArgumentError, "cpus is a required parameter" unless options.key? 'cpus' raise ArgumentError, "instance_uuid is a required parameter" unless options.key? 'instance_uuid' hardware_spec={'numCPUs' => options['cpus'], 'numCoresPerSocket' => options['corespersocket']} vm_reconfig_hardware('instance_uuid' => options['instance_uuid'], 'hardware_spec' => hardware_spec ) end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/requests/compute/vm_reconfig_hardware.rb000066400000000000000000000017051263403543000267670ustar00rootroot00000000000000module Fog module Compute class Vsphere class Real def vm_reconfig_hardware(options = {}) raise ArgumentError, "hardware_spec is a required parameter" unless options.key? 'hardware_spec' raise ArgumentError, "instance_uuid is a required parameter" unless options.key? 'instance_uuid' vm_mob_ref = get_vm_ref(options['instance_uuid']) task = vm_mob_ref.ReconfigVM_Task(:spec => RbVmomi::VIM.VirtualMachineConfigSpec(options['hardware_spec'])) task.wait_for_completion { 'task_state' => task.info.state } end end class Mock def vm_reconfig_hardware(options = {}) raise ArgumentError, "hardware_spec is a required parameter" unless options.key? 'hardware_spec' raise ArgumentError, "instance_uuid is a required parameter" unless options.key? 'instance_uuid' { 'task_state' => 'success' } end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/requests/compute/vm_reconfig_memory.rb000066400000000000000000000017131263403543000265010ustar00rootroot00000000000000module Fog module Compute class Vsphere class Real def vm_reconfig_memory(options = {}) raise ArgumentError, "memory is a required parameter" unless options.key? 'memory' raise ArgumentError, "instance_uuid is a required parameter" unless options.key? 'instance_uuid' hardware_spec={'memoryMB' => options['memory']} vm_reconfig_hardware('instance_uuid' => options['instance_uuid'], 'hardware_spec' => hardware_spec ) end end class Mock def vm_reconfig_memory(options = {}) raise ArgumentError, "memory is a required parameter" unless options.key? 'memory' raise ArgumentError, "instance_uuid is a required parameter" unless options.key? 'instance_uuid' hardware_spec={'memoryMB' => options['memory']} vm_reconfig_hardware('instance_uuid' => options['instance_uuid'], 'hardware_spec' => hardware_spec ) end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/requests/compute/vm_take_snapshot.rb000066400000000000000000000022351263403543000261600ustar00rootroot00000000000000module Fog module Compute class Vsphere class Real def vm_take_snapshot(options = {}) raise ArgumentError, "instance_uuid is a required parameter" unless options.key? 'instance_uuid' raise ArgumentError, "name is a required parameter" unless options.key? 'name' vm = get_vm_ref(options['instance_uuid']) task = vm.CreateSnapshot_Task( :name => options['name'], :description => options['description'] || '', :memory => options['memory'] || true, :quiesce => options['quiesce'] || false ) task.wait_for_completion { 'task_state' => task.info.state, 'was_cancelled' => task.info.cancelled } end end class Mock def vm_take_snapshot(options = {}) raise ArgumentError, "instance_uuid is a required parameter" unless options.key? 'instance_uuid' raise ArgumentError, "name is a required parameter" unless options.key? 'name' { 'task_state' => 'success', 'was_cancelled' => false } end end end end end fog-vsphere-0.4.0/lib/fog/vsphere/version.rb000066400000000000000000000000741263403543000207500ustar00rootroot00000000000000module Fog module Vsphere VERSION = '0.4.0' end end fog-vsphere-0.4.0/tests/000077500000000000000000000000001263403543000151025ustar00rootroot00000000000000fog-vsphere-0.4.0/tests/compute_tests.rb000066400000000000000000000031641263403543000203310ustar00rootroot00000000000000Shindo.tests('Fog::Compute[:vsphere]', ['vsphere']) do compute = Fog::Compute[:vsphere] tests("| convert_vm_mob_ref_to_attr_hash") do # Mock the RbVmomi::VIM::ManagedObject class class MockManagedObject attr_reader :parent, :_ref def initialize @parent = @_ref = 'vm-123' end def collect! *pathSet { '_ref' => 'vm-123', 'name' => 'fakevm' } end end fake_vm_mob_ref = MockManagedObject.new tests("When converting an incomplete vm object") do test("it should return a Hash") do compute.send(:convert_vm_mob_ref_to_attr_hash, fake_vm_mob_ref).kind_of? Hash end tests("The converted Hash should") do attr_hash = compute.send(:convert_vm_mob_ref_to_attr_hash, fake_vm_mob_ref) test("have a name") { attr_hash['name'] == 'fakevm' } test("have a mo_ref") {attr_hash['mo_ref'] == 'vm-123' } test("have an id") { attr_hash['id'] == 'vm-123' } test("not have a instance_uuid") { attr_hash['instance_uuid'].nil? } end end tests("When passed a nil object") do attr_hash = compute.send :convert_vm_mob_ref_to_attr_hash, nil test("it should return a nil object") do attr_hash.nil? end end end tests("Compute attributes") do %w{ vsphere_is_vcenter vsphere_rev vsphere_username vsphere_server }.each do |attr| test("it should respond to #{attr}") { compute.respond_to? attr } end end tests("Compute collections") do %w{ servers }.each do |collection| test("it should respond to #{collection}") { compute.respond_to? collection } end end end fog-vsphere-0.4.0/tests/helper.rb000066400000000000000000000003401263403543000167030ustar00rootroot00000000000000begin require 'codeclimate-test-reporter' CodeClimate::TestReporter.start rescue LoadError => e $stderr.puts "not recording test coverage: #{e.inspect}" end require File.expand_path('../../lib/fog/vsphere', __FILE__) fog-vsphere-0.4.0/tests/helpers/000077500000000000000000000000001263403543000165445ustar00rootroot00000000000000fog-vsphere-0.4.0/tests/helpers/mock_helper.rb000066400000000000000000000003751263403543000213660ustar00rootroot00000000000000Fog.mock! if ENV['FOG_MOCK'] == 'true' if Fog.mock? Fog.credentials = { :vsphere_server => 'fake_vsphere_server', :vsphere_username => 'fake_vsphere_username', :vsphere_password => 'fake_vsphere_password' }.merge(Fog.credentials) end fog-vsphere-0.4.0/tests/helpers/succeeds_helper.rb000066400000000000000000000002061263403543000222240ustar00rootroot00000000000000module Shindo class Tests def succeeds test('succeeds') do !!instance_eval(&Proc.new) end end end end fog-vsphere-0.4.0/tests/models/000077500000000000000000000000001263403543000163655ustar00rootroot00000000000000fog-vsphere-0.4.0/tests/models/compute/000077500000000000000000000000001263403543000200415ustar00rootroot00000000000000fog-vsphere-0.4.0/tests/models/compute/rules_tests.rb000066400000000000000000000023421263403543000227430ustar00rootroot00000000000000Shindo.tests('Fog::Compute[:vsphere] | rules collection', ['vsphere']) do compute = Fog::Compute[:vsphere] cluster = compute.datacenters.first.clusters.get('Solutionscluster') servers = compute.servers rules = cluster.rules tests('The rules collection') do test('should not be empty') { not rules.empty? } test('should be a kind of Fog::Compute::Vsphere::Rules') { rules.kind_of? Fog::Compute::Vsphere::Rules } test('should get rules') { rules.get('anti-affinity-foo').key == 4242 } test('should destroy rules') { rules.first.destroy; rules.reload; rules.empty? } test('should create rules') do r = rules.new({ name: 'affinity-foo', enabled: true, type: RbVmomi::VIM::ClusterAffinityRuleSpec }) r.vms = [servers.get('5032c8a5-9c5e-ba7a-3804-832a03e16381'), servers.get('502916a3-b42e-17c7-43ce-b3206e9524dc')] r.save rules.reload rules.get('affinity-foo').key > 0 end raises(ArgumentError, 'should not create rules with <2 vms') do rules.create({ name: 'affinity-foo', enabled: true, type: RbVmomi::VIM::ClusterAffinityRuleSpec, vm_ids: ['5032c8a5-9c5e-ba7a-3804-832a03e16381'] }) end end end fog-vsphere-0.4.0/tests/models/compute/server_tests.rb000066400000000000000000000050241263403543000231170ustar00rootroot00000000000000Shindo.tests('Fog::Compute[:vsphere] | server model', ['vsphere']) do servers = Fog::Compute[:vsphere].servers server = servers.last tests('The server model should') do tests('have the action') do test('reload') { server.respond_to? 'reload' } %w{ stop start destroy reboot }.each do |action| test(action) { server.respond_to? action } test("#{action} returns successfully") { server.send(action.to_sym) ? true : false } end test('guest_processes') { server.respond_to? 'guest_processes' } test('take_snapshot') do test('responds') { server.respond_to? 'take_snapshot'} test('returns successfully') { server.take_snapshot('name' => 'foobar').kind_of? Hash } end test('snapshots') do test('responds') { server.respond_to? 'snapshots'} test('returns successfully') { server.snapshots.kind_of? Fog::Compute::Vsphere::Snapshots } end test('find_snapshot') do test('responds') { server.respond_to? 'find_snapshot'} test('returns successfully') do server.find_snapshot('snapshot-0101').kind_of? Fog::Compute::Vsphere::Snapshot end test('returns correct snapshot') do server.find_snapshot('snapshot-0101').ref == 'snapshot-0101' end end tests('revert_snapshot') do test('responds') { server.respond_to? 'revert_snapshot'} tests('returns correctly') do test('when correct input given') { server.revert_snapshot('snapshot-0101').kind_of? Hash } test('when incorrect input given') do raises(ArgumentError) { server.revert_snapshot(1) } end end end end tests('have attributes') do model_attribute_hash = server.attributes attributes = [ :id, :instance_uuid, :uuid, :power_state, :tools_state, :mo_ref, :tools_version, :hostname, :mac_addresses, :operatingsystem, :connection_state, :hypervisor, :name, :public_ip_address] tests("The server model should respond to") do attributes.each do |attribute| test("#{attribute}") { server.respond_to? attribute } end end tests("The attributes hash should have key") do attributes.each do |attribute| test("#{attribute}") { model_attribute_hash.key? attribute } end end end test('be a kind of Fog::Compute::Vsphere::Server') { server.kind_of? Fog::Compute::Vsphere::Server } end end fog-vsphere-0.4.0/tests/models/compute/servers_tests.rb000066400000000000000000000012011263403543000232730ustar00rootroot00000000000000Shindo.tests('Fog::Compute[:vsphere] | servers collection', ['vsphere']) do servers = Fog::Compute[:vsphere].servers tests('The servers collection') do test('should not be empty') { not servers.empty? } test('should be a kind of Fog::Compute::Vsphere::Servers') { servers.kind_of? Fog::Compute::Vsphere::Servers } tests('should be able to reload itself').succeeds { servers.reload } tests('should be able to get a model') do tests('by managed object reference').succeeds { servers.get 'jefftest' } tests('by instance uuid').succeeds { servers.get '5032c8a5-9c5e-ba7a-3804-832a03e16381' } end end end fog-vsphere-0.4.0/tests/requests/000077500000000000000000000000001263403543000167555ustar00rootroot00000000000000fog-vsphere-0.4.0/tests/requests/compute/000077500000000000000000000000001263403543000204315ustar00rootroot00000000000000fog-vsphere-0.4.0/tests/requests/compute/current_time_tests.rb000066400000000000000000000006431263403543000247030ustar00rootroot00000000000000Shindo.tests('Fog::Compute[:vsphere] | current_time request', ['vsphere']) do compute = Fog::Compute[:vsphere] tests('The response should') do response = compute.current_time test('be a kind of Hash') { response.kind_of? Hash } test('have a current_time key') { response.key? 'current_time' } test('have a current_time key with a Time value') { response['current_time'].kind_of? Time } end end fog-vsphere-0.4.0/tests/requests/compute/folder_destroy_tests.rb000066400000000000000000000012011263403543000252160ustar00rootroot00000000000000Shindo.tests('Fog::Compute[:vsphere] | folder_destroy request', ['vsphere']) do compute = Fog::Compute[:vsphere] empty_folder = "/Solutions/empty" full_folder = "/Solutions/wibble" datacenter = "Solutions" tests('The response should') do response = compute.folder_destroy(empty_folder, datacenter) test('be a kind of Hash') { response.kind_of? Hash } test('should have a task_state key') { response.key? 'task_state' } end tests('When folder is not empty') do raises(Fog::Vsphere::Errors::ServiceError, 'raises ServiceError') do compute.folder_destroy(full_folder, datacenter) end end end fog-vsphere-0.4.0/tests/requests/compute/get_network_tests.rb000066400000000000000000000035641263403543000245400ustar00rootroot00000000000000require 'ostruct' Shindo.tests('Fog::Compute[:vsphere] | get_network request', ['vsphere']) do compute = Fog::Compute[:vsphere] class DistributedVirtualPortgroup attr_accessor :name, :dvs_name def initialize attrs @name = attrs.fetch(:name) @dvs_name = attrs.fetch(:dvs_name) end def config OpenStruct.new( :distributedVirtualSwitch => OpenStruct.new(:name => dvs_name)) end end fake_networks = [OpenStruct.new(:name => 'non-dvs'), DistributedVirtualPortgroup.new( :name => 'web1', :dvs_name => 'dvs5'), DistributedVirtualPortgroup.new( :name => 'web1', :dvs_name => 'dvs11'), DistributedVirtualPortgroup.new( :name => 'other', :dvs_name => 'other'), ] tests('#choose_finder should') do test('choose the network based on network name and dvs name'){ finder = compute.send(:choose_finder, 'web1', 'dvs11') found_network = fake_networks.find{ |n| finder.call(n) } found_network.name == 'web1' && found_network.dvs_name == 'dvs11' } test('choose the network based on network name and any dvs'){ finder = compute.send(:choose_finder, 'web1', :dvs) found_network = fake_networks.find{ |n| finder.call(n) } found_network.name == 'web1' && found_network.dvs_name == 'dvs5' } test('choose the network based on network name only'){ finder = compute.send(:choose_finder, 'other', nil) found_network = fake_networks.find{ |n| finder.call(n) } found_network.name == 'other' && found_network.dvs_name == 'other' } test('choose the network based on network name only for non-dvs'){ finder = compute.send(:choose_finder, 'non-dvs', nil) found_network = fake_networks.find{ |n| finder.call(n) } found_network.name == 'non-dvs' && found_network.class.name.to_s == 'OpenStruct' } end end fog-vsphere-0.4.0/tests/requests/compute/list_child_snapshots_tests.rb000066400000000000000000000005521263403543000264220ustar00rootroot00000000000000Shindo.tests('Fog::Compute[:vsphere] | list_child_snapshots request', ['vsphere']) do compute = Fog::Compute[:vsphere] tests('The response should') do response = compute.list_child_snapshots('snapshot-0101') test('be a kind of Array') { response.kind_of? Array } test('it should contains Hashes') { response.all? { |i| Hash === i } } end end fog-vsphere-0.4.0/tests/requests/compute/list_clusters_tests.rb000066400000000000000000000005561263403543000251050ustar00rootroot00000000000000Shindo.tests('Fog::Compute[:vsphere] | list_clusters request', ['vsphere']) do tests("When listing all clusters") do response = Fog::Compute[:vsphere].list_clusters test("Clusters extracted from folders... ") {response.length == 4} tests("The response data format ...") do test("be a kind of Hash") { response.kind_of? Array } end end endfog-vsphere-0.4.0/tests/requests/compute/list_storage_pods_test.rb000066400000000000000000000004641263403543000255450ustar00rootroot00000000000000Shindo.tests('Fog::Compute[:vsphere] | list_storage_pods request', ['vsphere']) do tests("When listing all storage pods") do response = Fog::Compute[:vsphere].list_storage_pods tests("The response data format ...") do test("be a kind of Hash") { response.kind_of? Array } end end end fog-vsphere-0.4.0/tests/requests/compute/list_virtual_machines_tests.rb000066400000000000000000000022551263403543000265740ustar00rootroot00000000000000Shindo.tests('Fog::Compute[:vsphere] | list_virtual_machines request', ['vsphere']) do tests("When listing all machines") do response = Fog::Compute[:vsphere].list_virtual_machines tests("The response data format ...") do test("be a kind of Hash") { response.kind_of? Array } end end tests("When providing an instance_uuid") do # pending unless Fog.mock? tests("that does exist") do uuid = "5029c440-85ee-c2a1-e9dd-b63e39364603" response = Fog::Compute[:vsphere].list_virtual_machines({'instance_uuid' => uuid}) tests("The response should") do test("contain one vm") { response.length == 1 } test("contain that is an attribute hash") { response[0].kind_of? Hash } test("find jefftest") { response.first['name'] == 'jefftest' } end end tests("that does not exist or is a template") do %w{ does-not-exist-and-is-not-a-uuid 50323f93-6835-1178-8b8f-9e2109890e1a }.each do |uuid| response = Fog::Compute[:vsphere].list_virtual_machines({'instance_uuid' => uuid}) tests("The response should") do test("be empty") { response.empty? } end end end end end fog-vsphere-0.4.0/tests/requests/compute/list_vm_cdroms_tests.rb000066400000000000000000000005651263403543000252320ustar00rootroot00000000000000Shindo.tests('Fog::Compute[:vsphere] | list_vm_cdroms request', ['vsphere']) do compute = Fog::Compute[:vsphere] tests('The response should') do response = compute.list_vm_cdroms('5032c8a5-9c5e-ba7a-3804-832a03e16381') test('be a kind of Array') { response.kind_of? Array } test('it should contains Hashes') { response.all? { |i| Hash === i } } end end fog-vsphere-0.4.0/tests/requests/compute/list_vm_snapshots_tests.rb000066400000000000000000000005731263403543000257640ustar00rootroot00000000000000Shindo.tests('Fog::Compute[:vsphere] | list_vm_snapshots request', ['vsphere']) do compute = Fog::Compute[:vsphere] tests('The response should') do response = compute.list_vm_snapshots('5032c8a5-9c5e-ba7a-3804-832a03e16381') test('be a kind of Array') { response.kind_of? Array } test('it should contains Hashes') { response.all? { |i| Hash === i } } end end fog-vsphere-0.4.0/tests/requests/compute/modify_vm_cdrom_tests.rb000066400000000000000000000013461263403543000253610ustar00rootroot00000000000000Shindo.tests('Fog::Compute[:vsphere] | modify_vm_cdrom request', ['vsphere']) do compute = Fog::Compute[:vsphere] modify_target = '5032c8a5-9c5e-ba7a-3804-832a03e16381' modify_cdrom = compute.cdroms.new( instance_uuid: modify_target, ) tests('When adding a cdrom the response should') do response = compute.add_vm_cdrom(modify_cdrom) test('be a kind of Hash') { response.kind_of? Hash } test('should have a task_state key') { response.key? 'task_state' } end tests('When destroying a cdrom the response should') do response = compute.destroy_vm_cdrom(modify_cdrom) test('be a kind of Hash') { response.kind_of? Hash } test('should have a task_state key') { response.key? 'task_state' } end end fog-vsphere-0.4.0/tests/requests/compute/revert_to_snapshot_tests.rb000066400000000000000000000010341263403543000261260ustar00rootroot00000000000000Shindo.tests('Fog::Compute[:vsphere] | revert_to_snapshot request', ['vsphere']) do compute = Fog::Compute[:vsphere] tests('The response should') do response = compute.revert_to_snapshot(Fog::Compute::Vsphere::Snapshot.new(:service => 1)) test('be a kind of Hash') { response.kind_of? Hash } test('should have a task_state key') { response.key? 'state' } end tests('The expected options') do raises(ArgumentError, 'raises ArgumentError when input param is missing') { compute.revert_to_snapshot(nil) } end end fog-vsphere-0.4.0/tests/requests/compute/set_vm_customvalue_tests.rb000066400000000000000000000014621263403543000261270ustar00rootroot00000000000000Shindo.tests('Fog::Compute[:vsphere] | set_vm_customvalue request', ['vsphere']) do compute = Fog::Compute[:vsphere] instance_uuid = '50137835-88a1-436e-768e-9b2677076e67' custom_key = nil custom_value = nil tests('The response should') do response = compute.set_vm_customvalue(instance_uuid, custom_key, custom_value) test('be nil') { response.nil? } end tests('The expected options') do raises(ArgumentError, 'raises ArgumentError when instance_uuid option is missing') { compute.set_vm_customvalue } raises(ArgumentError, 'raises ArgumentError when custom_key option is missing') { compute.set_vm_customvalue(instance_uuid) } raises(ArgumentError, 'raises ArgumentError when custom_value option is missing') { compute.set_vm_customvalue(instance_uuid, custom_key) } end end fog-vsphere-0.4.0/tests/requests/compute/vm_clone_tests.rb000066400000000000000000000046651263403543000240150ustar00rootroot00000000000000Shindo.tests("Fog::Compute[:vsphere] | vm_clone request", 'vsphere') do # require 'guid' compute = Fog::Compute[:vsphere] response = nil response_linked = nil template = "rhel64" datacenter = "Solutions" tests("Standard Clone | The return value should") do servers_size = compute.servers.size response = compute.vm_clone('datacenter' => datacenter, 'template_path' => template, 'name' => 'cloning_vm', 'wait' => true) test("be a kind of Hash") { response.kind_of? Hash } %w{ vm_ref new_vm task_ref }.each do |key| test("have a #{key} key") { response.key? key } end test("creates a new server") { compute.servers.size == servers_size+1 } test("new server name is set") { compute.get_virtual_machine(response['new_vm']['id'])['name'] == 'cloning_vm' } end tests("Standard Clone setting ram and cpu | The return value should") do servers_size = compute.servers.size response = compute.vm_clone('datacenter' => datacenter, 'template_path' => template, 'name' => 'cloning_vm', 'memoryMB' => '8192', 'numCPUs' => '8', 'wait' => true) test("be a kind of Hash") { response.kind_of? Hash } %w{ vm_ref new_vm task_ref }.each do |key| test("have a #{key} key") { response.key? key } end test("creates a new server") { compute.servers.size == servers_size+1 } test("new server name is set") { compute.get_virtual_machine(response['new_vm']['id'])['name'] == 'cloning_vm' } end tests("Linked Clone | The return value should") do servers_size = compute.servers.size response = compute.vm_clone('datacenter' => datacenter, 'template_path' => template, 'name' => 'cloning_vm_linked', 'wait' => 1, 'linked_clone' => true) test("be a kind of Hash") { response.kind_of? Hash } %w{ vm_ref new_vm task_ref }.each do |key| test("have a #{key} key") { response.key? key } end test("creates a new server") { compute.servers.size == servers_size+1 } test("new server name is set") { compute.get_virtual_machine(response['new_vm']['id'])['name'] == 'cloning_vm_linked' } end tests("When invalid input is presented") do raises(ArgumentError, 'it should raise ArgumentError') { compute.vm_clone(:foo => 1) } raises(Fog::Compute::Vsphere::NotFound, 'it should raise Fog::Compute::Vsphere::NotFound when the UUID is not a string') do pending # require 'guid' compute.vm_clone('instance_uuid' => Guid.from_s(template), 'name' => 'jefftestfoo') end end end fog-vsphere-0.4.0/tests/requests/compute/vm_config_vnc_tests.rb000066400000000000000000000013251263403543000250160ustar00rootroot00000000000000Shindo.tests('Fog::Compute[:vsphere] | vm_config_vnc request', ['vsphere']) do compute = Fog::Compute[:vsphere] reconfig_target = '50137835-88a1-436e-768e-9b2677076e67' vnc_spec = {:port => '5900', :password => 'ssaaa', :enabled => 'true'} tests('The response should') do response = compute.vm_config_vnc('instance_uuid' => reconfig_target).merge(vnc_spec) test('be a kind of Hash') { response.kind_of? Hash } test('should have a task_state key') { response.key? 'task_state' } end tests('VNC attrs response should') do response = compute.vm_get_vnc(reconfig_target) test('be a kind of Hash') { response.kind_of? Hash } test('should have a port key') { response.key? :port } end end fog-vsphere-0.4.0/tests/requests/compute/vm_destroy_tests.rb000066400000000000000000000010551263403543000243740ustar00rootroot00000000000000Shindo.tests('Fog::Compute[:vsphere] | vm_destroy request', ['vsphere']) do compute = Fog::Compute[:vsphere] booted_vm = '5032c8a5-9c5e-ba7a-3804-832a03e16381' tests('The response should') do response = compute.vm_destroy('instance_uuid' => booted_vm) test('be a kind of Hash') { response.kind_of? Hash } test('should have a task_state key') { response.key? 'task_state' } end tests('The expected options') do raises(ArgumentError, 'raises ArgumentError when instance_uuid option is missing') { compute.vm_destroy } end end fog-vsphere-0.4.0/tests/requests/compute/vm_migrate_tests.rb000066400000000000000000000010641263403543000243330ustar00rootroot00000000000000Shindo.tests('Fog::Compute[:vsphere] | vm_migrate request', ['vsphere']) do compute = Fog::Compute[:vsphere] powered_on_vm = '50137835-88a1-436e-768e-9b2677076e67' tests('The response should') do response = compute.vm_migrate('instance_uuid' => powered_on_vm) test('be a kind of Hash') { response.kind_of? Hash } test('should have a task_state key') { response.key? 'task_state' } end tests('The expected options') do raises(ArgumentError, 'raises ArgumentError when instance_uuid option is missing') { compute.vm_migrate } end end fog-vsphere-0.4.0/tests/requests/compute/vm_power_off_tests.rb000066400000000000000000000020111263403543000246620ustar00rootroot00000000000000Shindo.tests('Fog::Compute[:vsphere] | vm_power_off request', ['vsphere']) do compute = Fog::Compute[:vsphere] powered_on_vm = '5032c8a5-9c5e-ba7a-3804-832a03e16381' tests('The response should') do response = compute.vm_power_off('instance_uuid' => powered_on_vm) test('be a kind of Hash') { response.kind_of? Hash } test('should have a task_state key') { response.key? 'task_state' } test('should have a power_off_type key') { response.key? 'power_off_type' } end # When forcing the shutdown, we expect the result to be { true => 'cut_power', false => 'shutdown_guest'}.each do |force, expected| tests("When 'force' => #{force}") do response = compute.vm_power_off('instance_uuid' => powered_on_vm, 'force' => force) test('should retur power_off_type of #{expected}') { response['power_off_type'] == expected } end end tests('The expected options') do raises(ArgumentError, 'raises ArgumentError when instance_uuid option is missing') { compute.vm_power_off } end end fog-vsphere-0.4.0/tests/requests/compute/vm_power_on_tests.rb000066400000000000000000000010271263403543000245320ustar00rootroot00000000000000Shindo.tests('Fog::Compute[:vsphere] | vm_power_on request', ['vsphere']) do compute = Fog::Compute[:vsphere] powered_off_vm = nil tests('The response should') do response = compute.vm_power_on('instance_uuid' => powered_off_vm) test('be a kind of Hash') { response.kind_of? Hash } test('should have a task_state key') { response.key? 'task_state' } end tests('The expected options') do raises(ArgumentError, 'raises ArgumentError when instance_uuid option is missing') { compute.vm_power_on } end end fog-vsphere-0.4.0/tests/requests/compute/vm_reboot_tests.rb000066400000000000000000000017601263403543000242000ustar00rootroot00000000000000Shindo.tests('Fog::Compute[:vsphere] | vm_reboot request', ['vsphere']) do compute = Fog::Compute[:vsphere] powered_on_vm = '5032c8a5-9c5e-ba7a-3804-832a03e16381' tests('The response should') do response = compute.vm_reboot('instance_uuid' => powered_on_vm) test('be a kind of Hash') { response.kind_of? Hash } test('should have a task_state key') { response.key? 'task_state' } test('should have a reboot_type key') { response.key? 'reboot_type' } end # When forcing the shutdown, we expect the result to be { true => 'reset_power', false => 'reboot_guest'}.each do |force, expected| tests("When force => #{force}") do response = compute.vm_reboot('instance_uuid' => powered_on_vm, 'force' => force) test("should return reboot_type of #{expected}") { response['reboot_type'] == expected } end end tests('The expected options') do raises(ArgumentError, 'raises ArgumentError when instance_uuid option is missing') { compute.vm_reboot } end end fog-vsphere-0.4.0/tests/requests/compute/vm_reconfig_cdrom_tests.rb000066400000000000000000000010101263403543000256520ustar00rootroot00000000000000Shindo.tests('Fog::Compute[:vsphere] | vm_reconfig_cdrom request', ['vsphere']) do compute = Fog::Compute[:vsphere] reconfig_target = '5032c8a5-9c5e-ba7a-3804-832a03e16381' reconfig_spec = { 'start_connected' => false, } tests('the response should') do response = compute.vm_reconfig_cdrom('instance_uuid' => reconfig_target, 'hardware_spec' => reconfig_spec) test('be a kind of Hash') { response.kind_of? Hash } test('should have a task_state key') { response.key? 'task_state' } end end fog-vsphere-0.4.0/tests/requests/compute/vm_reconfig_cpus_tests.rb000066400000000000000000000014401263403543000255270ustar00rootroot00000000000000Shindo.tests('Fog::Compute[:vsphere] | vm_reconfig_cpus request', ['vsphere']) do compute = Fog::Compute[:vsphere] reconfig_target = '50137835-88a1-436e-768e-9b2677076e67' reconfig_spec = 2 tests('The response should') do response = compute.vm_reconfig_cpus('instance_uuid' => reconfig_target, 'cpus' => reconfig_spec) test('be a kind of Hash') { response.kind_of? Hash } test('should have a task_state key') { response.key? 'task_state' } end tests('The expected options') do raises(ArgumentError, 'raises ArgumentError when instance_uuid option is missing') { compute.vm_reconfig_cpus('cpus' => reconfig_spec) } raises(ArgumentError, 'raises ArgumentError when cpus option is missing') { compute.vm_reconfig_cpus('instance_uuid' => reconfig_target) } end end fog-vsphere-0.4.0/tests/requests/compute/vm_reconfig_hardware_tests.rb000066400000000000000000000015501263403543000263540ustar00rootroot00000000000000Shindo.tests('Fog::Compute[:vsphere] | vm_reconfig_hardware request', ['vsphere']) do compute = Fog::Compute[:vsphere] reconfig_target = '50137835-88a1-436e-768e-9b2677076e67' reconfig_spec = {'guestId' => 'rhel5_64Guest'} tests('The response should') do response = compute.vm_reconfig_hardware('instance_uuid' => reconfig_target, 'hardware_spec' => reconfig_spec) test('be a kind of Hash') { response.kind_of? Hash } test('should have a task_state key') { response.key? 'task_state' } end tests('The expected options') do raises(ArgumentError, 'raises ArgumentError when instance_uuid option is missing') { compute.vm_reconfig_hardware('hardware_spec' => reconfig_spec) } raises(ArgumentError, 'raises ArgumentError when hardware_spec option is missing') { compute.vm_reconfig_hardware('instance_uuid' => reconfig_target) } end end fog-vsphere-0.4.0/tests/requests/compute/vm_reconfig_memory_tests.rb000066400000000000000000000014611263403543000260700ustar00rootroot00000000000000Shindo.tests('Fog::Compute[:vsphere] | vm_reconfig_memory request', ['vsphere']) do compute = Fog::Compute[:vsphere] reconfig_target = '50137835-88a1-436e-768e-9b2677076e67' reconfig_spec = 4096 tests('The response should') do response = compute.vm_reconfig_memory('instance_uuid' => reconfig_target, 'memory' => reconfig_spec) test('be a kind of Hash') { response.kind_of? Hash } test('should have a task_state key') { response.key? 'task_state' } end tests('The expected options') do raises(ArgumentError, 'raises ArgumentError when instance_uuid option is missing') { compute.vm_reconfig_memory('memory' => reconfig_spec) } raises(ArgumentError, 'raises ArgumentError when memory option is missing') { compute.vm_reconfig_memory('instance_uuid' => reconfig_target) } end end fog-vsphere-0.4.0/tests/requests/compute/vm_take_snapshot_tests.rb000066400000000000000000000014521263403543000255470ustar00rootroot00000000000000Shindo.tests('Fog::Compute[:vsphere] | vm_take_snapshot request', ['vsphere']) do compute = Fog::Compute[:vsphere] powered_off_vm = nil tests('The response should') do response = compute.vm_take_snapshot('instance_uuid' => powered_off_vm, 'name' => 'foobar') test('be a kind of Hash') { response.kind_of? Hash } test('should have a task_state key') { response.key? 'task_state' } test('should have a was_cancelled key') { response.key? 'was_cancelled' } end tests('The expected options') do raises(ArgumentError, 'raises ArgumentError when instance_uuid option is missing') { compute.vm_take_snapshot('name' => 'foobar') } raises(ArgumentError, 'raises ArgumentError when name option is missing') { compute.vm_take_snapshot('instance_uuid' => powered_off_vm) } end end