fog-vsphere 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (123) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +23 -0
  3. data/.travis.yml +32 -0
  4. data/CONTRIBUTING.md +18 -0
  5. data/CONTRIBUTORS.md +59 -0
  6. data/Gemfile +5 -0
  7. data/LICENSE.md +20 -0
  8. data/README.md +31 -0
  9. data/Rakefile +8 -0
  10. data/fog-vsphere.gemspec +32 -0
  11. data/gemfiles/Gemfile.1.9.2+ +8 -0
  12. data/gemfiles/Gemfile.1.9.2- +11 -0
  13. data/lib/fog/vsphere.rb +41 -0
  14. data/lib/fog/vsphere/compute.rb +473 -0
  15. data/lib/fog/vsphere/models/compute/cluster.rb +28 -0
  16. data/lib/fog/vsphere/models/compute/clusters.rb +22 -0
  17. data/lib/fog/vsphere/models/compute/customfield.rb +16 -0
  18. data/lib/fog/vsphere/models/compute/customfields.rb +23 -0
  19. data/lib/fog/vsphere/models/compute/customvalue.rb +14 -0
  20. data/lib/fog/vsphere/models/compute/customvalues.rb +33 -0
  21. data/lib/fog/vsphere/models/compute/datacenter.rb +44 -0
  22. data/lib/fog/vsphere/models/compute/datacenters.rb +19 -0
  23. data/lib/fog/vsphere/models/compute/datastore.rb +21 -0
  24. data/lib/fog/vsphere/models/compute/datastores.rb +21 -0
  25. data/lib/fog/vsphere/models/compute/folder.rb +24 -0
  26. data/lib/fog/vsphere/models/compute/folders.rb +23 -0
  27. data/lib/fog/vsphere/models/compute/interface.rb +91 -0
  28. data/lib/fog/vsphere/models/compute/interfaces.rb +66 -0
  29. data/lib/fog/vsphere/models/compute/interfacetype.rb +22 -0
  30. data/lib/fog/vsphere/models/compute/interfacetypes.rb +34 -0
  31. data/lib/fog/vsphere/models/compute/network.rb +18 -0
  32. data/lib/fog/vsphere/models/compute/networks.rb +22 -0
  33. data/lib/fog/vsphere/models/compute/process.rb +17 -0
  34. data/lib/fog/vsphere/models/compute/resource_pool.rb +19 -0
  35. data/lib/fog/vsphere/models/compute/resource_pools.rb +22 -0
  36. data/lib/fog/vsphere/models/compute/scsicontroller.rb +16 -0
  37. data/lib/fog/vsphere/models/compute/server.rb +325 -0
  38. data/lib/fog/vsphere/models/compute/servers.rb +36 -0
  39. data/lib/fog/vsphere/models/compute/servertype.rb +36 -0
  40. data/lib/fog/vsphere/models/compute/servertypes.rb +23 -0
  41. data/lib/fog/vsphere/models/compute/snapshot.rb +35 -0
  42. data/lib/fog/vsphere/models/compute/snapshots.rb +27 -0
  43. data/lib/fog/vsphere/models/compute/template.rb +11 -0
  44. data/lib/fog/vsphere/models/compute/templates.rb +19 -0
  45. data/lib/fog/vsphere/models/compute/volume.rb +99 -0
  46. data/lib/fog/vsphere/models/compute/volumes.rb +53 -0
  47. data/lib/fog/vsphere/requests/compute/cloudinit_to_customspec.rb +65 -0
  48. data/lib/fog/vsphere/requests/compute/create_folder.rb +22 -0
  49. data/lib/fog/vsphere/requests/compute/create_vm.rb +169 -0
  50. data/lib/fog/vsphere/requests/compute/current_time.rb +18 -0
  51. data/lib/fog/vsphere/requests/compute/get_cluster.rb +25 -0
  52. data/lib/fog/vsphere/requests/compute/get_compute_resource.rb +41 -0
  53. data/lib/fog/vsphere/requests/compute/get_datacenter.rb +31 -0
  54. data/lib/fog/vsphere/requests/compute/get_datastore.rb +30 -0
  55. data/lib/fog/vsphere/requests/compute/get_folder.rb +74 -0
  56. data/lib/fog/vsphere/requests/compute/get_interface_type.rb +15 -0
  57. data/lib/fog/vsphere/requests/compute/get_network.rb +59 -0
  58. data/lib/fog/vsphere/requests/compute/get_resource_pool.rb +26 -0
  59. data/lib/fog/vsphere/requests/compute/get_server_type.rb +32 -0
  60. data/lib/fog/vsphere/requests/compute/get_template.rb +16 -0
  61. data/lib/fog/vsphere/requests/compute/get_virtual_machine.rb +57 -0
  62. data/lib/fog/vsphere/requests/compute/get_vm_first_scsi_controller.rb +26 -0
  63. data/lib/fog/vsphere/requests/compute/list_child_snapshots.rb +71 -0
  64. data/lib/fog/vsphere/requests/compute/list_clusters.rb +72 -0
  65. data/lib/fog/vsphere/requests/compute/list_compute_resources.rb +92 -0
  66. data/lib/fog/vsphere/requests/compute/list_customfields.rb +21 -0
  67. data/lib/fog/vsphere/requests/compute/list_datacenters.rb +53 -0
  68. data/lib/fog/vsphere/requests/compute/list_datastores.rb +40 -0
  69. data/lib/fog/vsphere/requests/compute/list_folders.rb +44 -0
  70. data/lib/fog/vsphere/requests/compute/list_interface_types.rb +25 -0
  71. data/lib/fog/vsphere/requests/compute/list_networks.rb +38 -0
  72. data/lib/fog/vsphere/requests/compute/list_processes.rb +40 -0
  73. data/lib/fog/vsphere/requests/compute/list_resource_pools.rb +38 -0
  74. data/lib/fog/vsphere/requests/compute/list_server_types.rb +54 -0
  75. data/lib/fog/vsphere/requests/compute/list_templates.rb +48 -0
  76. data/lib/fog/vsphere/requests/compute/list_virtual_machines.rb +80 -0
  77. data/lib/fog/vsphere/requests/compute/list_vm_customvalues.rb +20 -0
  78. data/lib/fog/vsphere/requests/compute/list_vm_interfaces.rb +63 -0
  79. data/lib/fog/vsphere/requests/compute/list_vm_snapshots.rb +66 -0
  80. data/lib/fog/vsphere/requests/compute/list_vm_volumes.rb +52 -0
  81. data/lib/fog/vsphere/requests/compute/modify_vm_interface.rb +59 -0
  82. data/lib/fog/vsphere/requests/compute/modify_vm_volume.rb +25 -0
  83. data/lib/fog/vsphere/requests/compute/revert_to_snapshot.rb +30 -0
  84. data/lib/fog/vsphere/requests/compute/set_vm_customvalue.rb +17 -0
  85. data/lib/fog/vsphere/requests/compute/vm_clone.rb +727 -0
  86. data/lib/fog/vsphere/requests/compute/vm_config_vnc.rb +45 -0
  87. data/lib/fog/vsphere/requests/compute/vm_destroy.rb +23 -0
  88. data/lib/fog/vsphere/requests/compute/vm_execute.rb +47 -0
  89. data/lib/fog/vsphere/requests/compute/vm_migrate.rb +33 -0
  90. data/lib/fog/vsphere/requests/compute/vm_power_off.rb +39 -0
  91. data/lib/fog/vsphere/requests/compute/vm_power_on.rb +26 -0
  92. data/lib/fog/vsphere/requests/compute/vm_reboot.rb +31 -0
  93. data/lib/fog/vsphere/requests/compute/vm_reconfig_cpus.rb +23 -0
  94. data/lib/fog/vsphere/requests/compute/vm_reconfig_hardware.rb +24 -0
  95. data/lib/fog/vsphere/requests/compute/vm_reconfig_memory.rb +23 -0
  96. data/lib/fog/vsphere/requests/compute/vm_take_snapshot.rb +37 -0
  97. data/lib/fog/vsphere/version.rb +5 -0
  98. data/tests/compute_tests.rb +53 -0
  99. data/tests/helper.rb +8 -0
  100. data/tests/helpers/mock_helper.rb +9 -0
  101. data/tests/helpers/succeeds_helper.rb +9 -0
  102. data/tests/models/compute/server_tests.rb +70 -0
  103. data/tests/models/compute/servers_tests.rb +15 -0
  104. data/tests/requests/compute/current_time_tests.rb +12 -0
  105. data/tests/requests/compute/get_network_tests.rb +50 -0
  106. data/tests/requests/compute/list_child_snapshots_tests.rb +10 -0
  107. data/tests/requests/compute/list_clusters_tests.rb +11 -0
  108. data/tests/requests/compute/list_virtual_machines_tests.rb +38 -0
  109. data/tests/requests/compute/list_vm_snapshots_tests.rb +10 -0
  110. data/tests/requests/compute/revert_to_snapshot_tests.rb +15 -0
  111. data/tests/requests/compute/set_vm_customvalue_tests.rb +20 -0
  112. data/tests/requests/compute/vm_clone_tests.rb +50 -0
  113. data/tests/requests/compute/vm_config_vnc_tests.rb +19 -0
  114. data/tests/requests/compute/vm_destroy_tests.rb +17 -0
  115. data/tests/requests/compute/vm_migrate_tests.rb +16 -0
  116. data/tests/requests/compute/vm_power_off_tests.rb +26 -0
  117. data/tests/requests/compute/vm_power_on_tests.rb +17 -0
  118. data/tests/requests/compute/vm_reboot_tests.rb +26 -0
  119. data/tests/requests/compute/vm_reconfig_cpus_tests.rb +19 -0
  120. data/tests/requests/compute/vm_reconfig_hardware_tests.rb +19 -0
  121. data/tests/requests/compute/vm_reconfig_memory_tests.rb +19 -0
  122. data/tests/requests/compute/vm_take_snapshot_tests.rb +19 -0
  123. metadata +289 -0
@@ -0,0 +1,36 @@
1
+ module Fog
2
+ module Compute
3
+ class Vsphere
4
+ class Servers < Fog::Collection
5
+ autoload :Server, File.expand_path('../server', __FILE__)
6
+
7
+ model Fog::Compute::Vsphere::Server
8
+ attr_accessor :datacenter
9
+ attr_accessor :network
10
+ attr_accessor :cluster
11
+ attr_accessor :resource_pool
12
+ attr_accessor :folder
13
+
14
+ # 'folder' => '/Datacenters/vm/Jeff/Templates' will be MUCH faster.
15
+ # than simply listing everything.
16
+ def all(filters = { })
17
+ f = {
18
+ :datacenter => datacenter,
19
+ :cluster => cluster,
20
+ :network => network,
21
+ :resource_pool => resource_pool,
22
+ :folder => folder
23
+ }.merge(filters)
24
+
25
+ load service.list_virtual_machines(f)
26
+ end
27
+
28
+ def get(id, datacenter = nil)
29
+ new service.get_virtual_machine id, datacenter
30
+ rescue Fog::Compute::Vsphere::NotFound
31
+ nil
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,36 @@
1
+ module Fog
2
+ module Compute
3
+ class Vsphere
4
+ class Servertype < Fog::Model
5
+ identity :id
6
+
7
+ attribute :family
8
+ attribute :fullname
9
+ attribute :datacenter
10
+ attribute :interfacetypes
11
+
12
+ def initialize(attributes={} )
13
+ super defaults.merge(attributes)
14
+ end
15
+
16
+ def to_s
17
+ id
18
+ end
19
+
20
+ def interfacetypes filters={}
21
+ attributes[:interfacetypes] ||= service.interfacetypes({ :datacenter => datacenter, :servertype => self }.merge(filters))
22
+ end
23
+
24
+ private
25
+
26
+ def defaults
27
+ {
28
+ :id=>"otherGuest64",
29
+ :family=>"otherGuestFamily",
30
+ :interfacetypes => nil,
31
+ }
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,23 @@
1
+ module Fog
2
+ module Compute
3
+ class Vsphere
4
+ class Servertypes < Fog::Collection
5
+ autoload :Servertype, File.expand_path('../servertype', __FILE__)
6
+
7
+ model Fog::Compute::Vsphere::Servertype
8
+ attr_accessor :datacenter, :id, :fullname
9
+
10
+ def all(filters = { })
11
+ load service.list_server_types(filters.merge({:datacenter => datacenter}))
12
+ end
13
+
14
+ def get(id)
15
+ requires :datacenter
16
+ new service.get_server_type(id, datacenter)
17
+ rescue Fog::Compute::Vsphere::NotFound
18
+ nil
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,35 @@
1
+ require 'fog/compute/models/server'
2
+
3
+ module Fog
4
+ module Compute
5
+ class Vsphere
6
+ class Snapshot < Fog::Model
7
+
8
+ identity :ref
9
+ attribute :server_id
10
+
11
+ attribute :name
12
+ attribute :quiescedi, :default => false
13
+ attribute :description, :default => ''
14
+ attribute :create_time
15
+ attribute :power_state, :default => 'none'
16
+ attribute :ref
17
+ attribute :mo_ref
18
+ attribute :tree_node
19
+ attribute :snapshot_name_chain
20
+ attribute :ref_chain
21
+
22
+ def child_snapshots(filters = {})
23
+ service.snapshots(
24
+ { :server_id => server_id, :parent_snapshot => self }.update(filters)
25
+ )
26
+ end
27
+
28
+ def get_child(snapshot_ref)
29
+ return self if ref == snapshot_ref
30
+ child_snapshots().get(snapshot_ref)
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,27 @@
1
+ require 'fog/core/collection'
2
+ require 'fog/vsphere/models/compute/snapshot'
3
+
4
+ module Fog
5
+ module Compute
6
+ class Vsphere
7
+ class Snapshots < Fog::Collection
8
+ attribute :server_id, :alias => :instance_uuid
9
+ attribute :parent_snapshot
10
+ model Fog::Compute::Vsphere::Snapshot
11
+
12
+ def all(filters = {})
13
+ if parent_snapshot
14
+ load service.list_child_snapshots(parent_snapshot, filters)
15
+ else
16
+ requires :server_id
17
+ load service.list_vm_snapshots(server_id, filters)
18
+ end
19
+ end
20
+
21
+ def get(snapshot_ref)
22
+ all.find { |snapshot| snapshot.get_child(snapshot_ref) }
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,11 @@
1
+ module Fog
2
+ module Compute
3
+ class Vsphere
4
+ class Template < Fog::Model
5
+ identity :id
6
+ attribute :name
7
+ attribute :uuid
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,19 @@
1
+ module Fog
2
+ module Compute
3
+ class Vsphere
4
+ class Templates < Fog::Collection
5
+ autoload :Template, File.expand_path('../template', __FILE__)
6
+
7
+ model Fog::Compute::Vsphere::Template
8
+
9
+ def all(filters = {})
10
+ load service.list_templates(filters)
11
+ end
12
+
13
+ def get(id)
14
+ new service.get_template(id)
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,99 @@
1
+ module Fog
2
+ module Compute
3
+ class Vsphere
4
+ class Volume < Fog::Model
5
+ DISK_SIZE_TO_GB = 1048576
6
+ identity :id
7
+
8
+ attribute :datastore
9
+ attribute :mode
10
+ attribute :size
11
+ attribute :thin
12
+ attribute :eager_zero
13
+ attribute :name
14
+ attribute :filename
15
+ attribute :size_gb
16
+ attribute :key
17
+ attribute :unit_number
18
+ attribute :server_id
19
+
20
+ def initialize(attributes={} )
21
+ # Assign server first to prevent race condition with persisted?
22
+ self.server_id = attributes.delete(:server_id)
23
+
24
+ super defaults.merge(attributes)
25
+ end
26
+
27
+ def size_gb
28
+ attributes[:size_gb] ||= attributes[:size].to_i / DISK_SIZE_TO_GB if attributes[:size]
29
+ end
30
+
31
+ def size_gb= s
32
+ attributes[:size] = s.to_i * DISK_SIZE_TO_GB if s
33
+ end
34
+
35
+ def to_s
36
+ name
37
+ end
38
+
39
+ def destroy
40
+ requires :server_id, :key, :unit_number
41
+
42
+ service.destroy_vm_volume(self)
43
+ true
44
+ end
45
+
46
+ def save
47
+ raise Fog::Errors::Error.new('Resaving an existing object may create a duplicate') if persisted?
48
+ requires :server_id, :size, :datastore
49
+
50
+ if unit_number.nil?
51
+ used_unit_numbers = server.volumes.map { |volume| volume.unit_number }
52
+ max_unit_number = used_unit_numbers.max
53
+
54
+ if max_unit_number > server.volumes.size
55
+ # If the max ID exceeds the number of volumes, there must be a hole in the range. Find a hole and use it.
56
+ self.unit_number = max_unit_number.times.to_a.find { |i| used_unit_numbers.exclude?(i) }
57
+ else
58
+ self.unit_number = max_unit_number + 1
59
+ end
60
+ else
61
+ if server.volumes.any? { |volume| volume.unit_number == self.unit_number && volume.id != self.id }
62
+ raise "A volume already exists with that unit_number, so we can't save the new volume"
63
+ end
64
+ end
65
+
66
+ data = service.add_vm_volume(self)
67
+
68
+ if data['task_state'] == 'success'
69
+ # We have to query vSphere to get the volume attributes since the task handle doesn't include that info.
70
+ created = server.volumes.all.find { |volume| volume.unit_number == self.unit_number }
71
+
72
+ self.id = created.id
73
+ self.key = created.key
74
+ self.filename = created.filename
75
+
76
+ true
77
+ else
78
+ false
79
+ end
80
+ end
81
+
82
+ def server
83
+ requires :server_id
84
+ service.servers.get(server_id)
85
+ end
86
+
87
+ private
88
+
89
+ def defaults
90
+ {
91
+ :thin => true,
92
+ :name => "Hard disk",
93
+ :mode => "persistent"
94
+ }
95
+ end
96
+ end
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,53 @@
1
+ module Fog
2
+ module Compute
3
+ class Vsphere
4
+ class Volumes < Fog::Collection
5
+ autoload :Volume, File.expand_path('../volume', __FILE__)
6
+
7
+ attribute :server_id
8
+
9
+ model Fog::Compute::Vsphere::Volume
10
+
11
+ def all(filters = {})
12
+ requires :server_id
13
+
14
+ case server
15
+ when Fog::Compute::Vsphere::Server
16
+ load service.list_vm_volumes(server.id)
17
+ when Fog::Compute::Vsphere::Template
18
+ load service.list_template_volumes(server.id)
19
+ else
20
+ raise 'volumes should have vm or template'
21
+ end
22
+
23
+ self.each { |volume| volume.server_id = server.id }
24
+ self
25
+ end
26
+
27
+ def get(id)
28
+ new service.get_volume(id)
29
+ end
30
+
31
+ def new(attributes = {})
32
+ if server_id
33
+ # Default to the root volume datastore if one is not configured.
34
+ datastore = ! attributes.key?(:datastore) && self.any? ? self.first.datastore : nil
35
+
36
+ super({ :server_id => server_id, :datastore => datastore }.merge!(attributes))
37
+ else
38
+ super
39
+ end
40
+ end
41
+
42
+ def server
43
+ return nil if server_id.nil?
44
+ service.servers.get(server_id)
45
+ end
46
+
47
+ def server=(new_server)
48
+ server_id = new_server.id
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,65 @@
1
+ module Fog
2
+ module Compute
3
+ class Vsphere
4
+ class Real
5
+ def cloudinit_to_customspec(user_data)
6
+ raise ArgumentError, "user_data can't be nil" if user_data.nil?
7
+ custom_spec = { 'customization_spec' => Hash.new }
8
+ user_data = YAML.load(user_data)
9
+ # https://pubs.vmware.com/vsphere-55/index.jsp#com.vmware.wssdk.apiref.doc/vim.vm.customization.Specification.html
10
+ # encryptionKey expects an array
11
+ # globalIPSettings expects a hash, REQUIRED
12
+ # identity expects an hash, REQUIRED
13
+ # nicSettingMap expects an array
14
+ # options expects an hash
15
+
16
+ custom_spec['encryptionKey'] = user_data['encryptionKey'] if user_data.key?('encryptionKey')
17
+ custom_spec['globalIPSettings'] = user_data['globalIPSettings'] if user_data.key?('globalIPSettings')
18
+ custom_spec['identity'] = user_data['identity'] if user_data.key?('identity')
19
+ custom_spec['nicSettingMap'] = user_data['nicSettingMap'] if user_data.key?('nicSettingMap')
20
+ custom_spec['options'] = user_data['options'] if user_data.key?('options')
21
+
22
+ # for backwards compatability
23
+ # hostname expects a string, REQUIRED
24
+ # netmask expects a string
25
+ # dns expects an array
26
+ # gateway expects an array
27
+ # domain expects a string, REQUIRED
28
+ # domainsuffixlist expects an array, REQUIRED
29
+ # timezone expects a string, for example Europe/Copenhagen, REQUIRED
30
+ custom_spec['hostname'] = user_data['hostname'] if user_data.key?('hostname')
31
+ custom_spec['ipsettings'] = { 'ip' => user_data['ip'] } if user_data.key?('ip')
32
+ custom_spec['ipsettings']['subnetMask'] = user_data['netmask'] if user_data.key?('netmask')
33
+ custom_spec['ipsettings']['dnsServerList'] = user_data['dns'] if user_data.key?('dns')
34
+ custom_spec['ipsettings']['gateway'] = user_data['gateway'] if user_data.key?('gateway')
35
+ custom_spec['domain'] = user_data['domain'] if user_data.key?('domain')
36
+ custom_spec['dnsSuffixList'] = user_data['domainsuffixlist'] if user_data.key?('domainsuffixlist')
37
+ custom_spec['time_zone'] = user_data['timezone'] if user_data.key?('timezone')
38
+ custom_spec
39
+ end
40
+ end
41
+
42
+ class Mock
43
+ def cloudinit_to_customspec(user_data)
44
+ raise ArgumentError, "user_data can't be nil" if user_data.nil?
45
+ custom_spec = { 'customization_spec' => Hash.new }
46
+ user_data = YAML.load(user_data)
47
+ custom_spec['encryptionKey'] = user_data['encryptionKey'] if user_data.key?('encryptionKey')
48
+ custom_spec['globalIPSettings'] = user_data['globalIPSettings'] if user_data.key?('globalIPSettings')
49
+ custom_spec['identity'] = user_data['identity'] if user_data.key?('identity')
50
+ custom_spec['nicSettingMap'] = user_data['nicSettingMap'] if user_data.key?('nicSettingMap')
51
+ custom_spec['options'] = user_data['options'] if user_data.key?('options')
52
+ custom_spec['hostname'] = user_data['hostname'] if user_data.key?('hostname')
53
+ custom_spec['ipsettings'] = { 'ip' => user_data['ip'] } if user_data.key?('ip')
54
+ custom_spec['ipsettings']['subnetMask'] = user_data['netmask'] if user_data.key?('netmask')
55
+ custom_spec['ipsettings']['dnsServerList'] = user_data['dns'] if user_data.key?('dns')
56
+ custom_spec['ipsettings']['gateway'] = user_data['gateway'] if user_data.key?('gateway')
57
+ custom_spec['domain'] = user_data['domain'] if user_data.key?('domain')
58
+ custom_spec['dnsSuffixList'] = user_data['domainsuffixlist'] if user_data.key?('domainsuffixlist')
59
+ custom_spec['time_zone'] = user_data['timezone'] if user_data.key?('timezone')
60
+ custom_spec
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,22 @@
1
+ module Fog
2
+ module Compute
3
+ class Vsphere
4
+ class Real
5
+ def create_folder(datacenter, path, name)
6
+ #Path cannot be nil but it can be an empty string
7
+ raise ArgumentError, "Path cannot be nil" if path.nil?
8
+
9
+ parent_folder = get_raw_vmfolder(path, datacenter)
10
+ begin
11
+ new_folder = parent_folder.CreateFolder(:name => name)
12
+ # output is cleaned up to return the new path
13
+ # new path will be path/name, example: "Production/Pool1"
14
+ new_folder.path.reject { |a| a.first.class == "Folder" }.map { |a| a.first.name }.join("/").sub(/^\/?Datacenters\/#{datacenter}\/vm\/?/, '')
15
+ rescue => e
16
+ raise e, "failed to create folder: #{e}"
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,169 @@
1
+ module Fog
2
+ module Compute
3
+ class Vsphere
4
+ class Real
5
+ def create_vm attributes = { }
6
+ # build up vm configuration
7
+
8
+ vm_cfg = {
9
+ :name => attributes[:name],
10
+ :guestId => attributes[:guest_id],
11
+ :version => attributes[:hardware_version],
12
+ :files => { :vmPathName => vm_path_name(attributes) },
13
+ :numCPUs => attributes[:cpus],
14
+ :numCoresPerSocket => attributes[:corespersocket],
15
+ :memoryMB => attributes[:memory_mb],
16
+ :deviceChange => device_change(attributes),
17
+ :extraConfig => extra_config(attributes),
18
+ }
19
+ vm_cfg[:cpuHotAddEnabled] = attributes[:cpuHotAddEnabled] if attributes.key?(:cpuHotAddEnabled)
20
+ vm_cfg[:memoryHotAddEnabled] = attributes[:memoryHotAddEnabled] if attributes.key?(:memoryHotAddEnabled)
21
+ vm_cfg[:firmware] = attributes[:firmware] if attributes.key?(:firmware)
22
+ resource_pool = if attributes[:resource_pool]
23
+ get_raw_resource_pool(attributes[:resource_pool], attributes[:cluster], attributes[:datacenter])
24
+ else
25
+ get_raw_cluster(attributes[:cluster], attributes[:datacenter]).resourcePool
26
+ end
27
+ vmFolder = get_raw_vmfolder(attributes[:path], attributes[:datacenter])
28
+ vm = vmFolder.CreateVM_Task(:config => vm_cfg, :pool => resource_pool).wait_for_completion
29
+ vm.config.instanceUuid
30
+ rescue => e
31
+ raise e, "failed to create vm: #{e}"
32
+ end
33
+
34
+ private
35
+
36
+ # this methods defines where the vm config files would be located,
37
+ # by default we prefer to keep it at the same place the (first) vmdk is located
38
+ def vm_path_name attributes
39
+ datastore = attributes[:volumes].first.datastore unless attributes[:volumes].empty?
40
+ datastore ||= 'datastore1'
41
+ "[#{datastore}]"
42
+ end
43
+
44
+ def device_change attributes
45
+ devices = []
46
+ if (nics = attributes[:interfaces])
47
+ devices << nics.map { |nic| create_interface(nic, nics.index(nic), :add, attributes) }
48
+ end
49
+
50
+ if (disks = attributes[:volumes])
51
+ devices << create_controller(attributes[:scsi_controller]||attributes["scsi_controller"]||{})
52
+ devices << disks.map { |disk| create_disk(disk, disks.index(disk)) }
53
+ end
54
+ devices.flatten
55
+ end
56
+
57
+ def create_nic_backing nic, attributes
58
+ raw_network = get_raw_network(nic.network, attributes[:datacenter], if nic.virtualswitch then nic.virtualswitch end)
59
+
60
+ if raw_network.kind_of? RbVmomi::VIM::DistributedVirtualPortgroup
61
+ RbVmomi::VIM.VirtualEthernetCardDistributedVirtualPortBackingInfo(
62
+ :port => RbVmomi::VIM.DistributedVirtualSwitchPortConnection(
63
+ :portgroupKey => raw_network.key,
64
+ :switchUuid => raw_network.config.distributedVirtualSwitch.uuid
65
+ )
66
+ )
67
+ else
68
+ RbVmomi::VIM.VirtualEthernetCardNetworkBackingInfo(:deviceName => nic.network)
69
+ end
70
+ end
71
+
72
+ def create_interface nic, index = 0, operation = :add, attributes = {}
73
+ {
74
+ :operation => operation,
75
+ :device => nic.type.new(
76
+ :key => index,
77
+ :deviceInfo =>
78
+ {
79
+ :label => nic.name,
80
+ :summary => nic.summary,
81
+ },
82
+ :backing => create_nic_backing(nic, attributes),
83
+ :addressType => 'generated')
84
+ }
85
+ end
86
+
87
+ def create_controller options=nil
88
+ options=if options
89
+ controller_default_options.merge(Hash[options.map{|k,v| [k.to_sym,v] }])
90
+ else
91
+ controller_default_options
92
+ end
93
+ controller_class=if options[:type].is_a? String then
94
+ Fog::Vsphere.class_from_string options[:type], "RbVmomi::VIM"
95
+ else
96
+ options[:type]
97
+ end
98
+ {
99
+ :operation => options[:operation],
100
+ :device => controller_class.new({
101
+ :key => options[:key],
102
+ :busNumber => options[:bus_id],
103
+ :sharedBus => controller_get_shared_from_options(options),
104
+ })
105
+ }
106
+ end
107
+
108
+ def controller_default_options
109
+ {:operation => "add", :type => RbVmomi::VIM.VirtualLsiLogicController.class, :key => 1000, :bus_id => 0, :shared => false }
110
+ end
111
+
112
+ def controller_get_shared_from_options options
113
+ if (options.key? :shared and options[:shared]==false) or not options.key? :shared then
114
+ :noSharing
115
+ elsif options[:shared]==true then
116
+ :virtualSharing
117
+ elsif options[:shared].is_a? String
118
+ options[:shared]
119
+ else
120
+ :noSharing
121
+ end
122
+ end
123
+
124
+ def create_disk disk, index = 0, operation = :add, controller_key = 1000
125
+ if (index > 6) then
126
+ _index = index + 1
127
+ else
128
+ _index = index
129
+ end
130
+ payload = {
131
+ :operation => operation,
132
+ :fileOperation => operation == :add ? :create : :destroy,
133
+ :device => RbVmomi::VIM.VirtualDisk(
134
+ :key => disk.key || _index,
135
+ :backing => RbVmomi::VIM.VirtualDiskFlatVer2BackingInfo(
136
+ :fileName => "[#{disk.datastore}]",
137
+ :diskMode => disk.mode.to_sym,
138
+ :thinProvisioned => disk.thin
139
+ ),
140
+ :controllerKey => controller_key,
141
+ :unitNumber => _index,
142
+ :capacityInKB => disk.size
143
+ )
144
+ }
145
+
146
+ if operation == :add && disk.thin == 'false' && disk.eager_zero == 'true'
147
+ payload[:device][:backing][:eagerlyScrub] = disk.eager_zero
148
+ end
149
+
150
+ payload
151
+ end
152
+
153
+ def extra_config attributes
154
+ [
155
+ {
156
+ :key => 'bios.bootOrder',
157
+ :value => 'ethernet0'
158
+ }
159
+ ]
160
+ end
161
+ end
162
+
163
+ class Mock
164
+ def create_vm attributes = { }
165
+ end
166
+ end
167
+ end
168
+ end
169
+ end