fog-hyperv 0.0.3 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 800c08e48379e123d5b8803ea3bda44f4eddbaa8
4
- data.tar.gz: df40fef67b97eeed7469c51710b12bec6b455f39
3
+ metadata.gz: 7d1f016acb31e48e1b25113f74c059dcd1d76eb2
4
+ data.tar.gz: a9fa8894c68b1520b9e244c92dee0fc0e2e899cc
5
5
  SHA512:
6
- metadata.gz: 0401b571330dad19781f5c35bfbc0cce18de2fdb02266583ba4ca2255b9c4a16e3c38b93303cfde9fa655ed0e73c0abf217dea43495a243460f2328ba42cbdac
7
- data.tar.gz: 718b6a478f911d0070427d486951125a2ddb8407475cbc2540c962bb90f64a45a7af4cb982c9bfd0f9bc09afab2238d71a52dd0f622a7541d27b9afc65ebf2dc
6
+ metadata.gz: ed4973a3d9d1c34e0c5e5374f5048f7d6f9a9f41b16084e9799061cc25109458599a498b98b2e37e7070b2e9f496100bf052297c8c146dcbda361fd2ed0d14b5
7
+ data.tar.gz: 2ef22b03209489609a1ac1190e530c2b5dd9a88f8f7838617987a38fca2d1f365763ff3f9fa9443bc170ca6ce700f71d20cb0f33a88d3807834945da12298bc5
@@ -1,14 +1,22 @@
1
- ## v0.0.3 2017-09-30
1
+ ## v0.0.4 2017-11-14
2
2
 
3
- - Fix handling of BIOS/Firmware
4
- - Skip unnecessary Hyper-V calls when checking dirty status
5
- - Add some possible interface improvements when dealing with clusters
3
+ - Adds support for the Kerberos transport
4
+ - Implements a first prototype for multi-hop when not using Kerberos/CredSSP
5
+ - Fixes issues in the saving of a few models
6
+ - Fixes a major issue when a VM ends up in a state with a large numerical value
7
+ - An issue in the enum code made input validity checking unable to differentiate between hashes and arrays
6
8
 
7
- ## v0.0.2 2017-09-28
9
+ ## v0.0.3 2017-08-30
8
10
 
9
- - Reduced `fog-core` dependency to 1.42
10
- - Disabled `status` attribute for network adapters, due to Hyper-V 6.3 issues
11
+ - Fixes handling of BIOS/Firmware
12
+ - Skips unnecessary Hyper-V calls when checking dirty status
13
+ - Adds some possible interface improvements when dealing with clusters
11
14
 
12
- ## v0.0.1 2017-09-25
15
+ ## v0.0.2 2017-08-28
16
+
17
+ - Reduces `fog-core` dependency to 1.42
18
+ - Disables `status` attribute for network adapters, due to Hyper-V 6.3 issues
19
+
20
+ ## v0.0.1 2017-08-25
13
21
 
14
22
  - Initial release
@@ -15,13 +15,6 @@ module Fog
15
15
  requires.include? req
16
16
  end
17
17
 
18
- def search_attributes
19
- attributes.dup.merge(
20
- _return_fields: model.attributes - model.lazy_attributes,
21
- _json_depth: 1
22
- )
23
- end
24
-
25
18
  def all(filters = {})
26
19
  requires(*self.class.requires)
27
20
  data = service.send(method, search_attributes.merge(filters))
@@ -34,13 +27,13 @@ module Fog
34
27
  data = all(filters).first
35
28
  data if data
36
29
  rescue Fog::Hyperv::Errors::PSError => err
37
- raise Fog::Errors::NotFound, err if err.message =~ /Hyper-V was unable to find|^No .* is found|/
30
+ raise Fog::Errors::NotFound, err if err.message =~ /Hyper-V was unable to find|^No .* is found/
38
31
  raise err
39
32
  end
40
33
 
41
34
  def new(options = {})
42
35
  requires(*self.class.requires)
43
- super(search_attributes.merge(options))
36
+ super(creation_attributes.merge(options))
44
37
  end
45
38
 
46
39
  def create(attributes = {})
@@ -49,6 +42,19 @@ module Fog
49
42
  object
50
43
  end
51
44
 
45
+ protected
46
+
47
+ def search_attributes
48
+ attributes.dup.merge(
49
+ _return_fields: model.attributes - model.lazy_attributes,
50
+ _json_depth: 1
51
+ )
52
+ end
53
+
54
+ def creation_attributes
55
+ attributes.dup
56
+ end
57
+
52
58
  private
53
59
 
54
60
  def method
@@ -64,11 +70,20 @@ module Fog
64
70
  attr_accessor :cluster
65
71
  attr_accessor :computer
66
72
 
73
+ protected
74
+
75
+ def creation_attributes
76
+ to_add = {}
77
+ to_add[:cluster] = cluster if cluster
78
+ to_add[:computer] = computer if computer
79
+ super.merge(to_add)
80
+ end
81
+
67
82
  def search_attributes
68
83
  attrs = super
69
84
  attrs.delete :cluster
70
85
  attrs.delete :computer
71
- attrs[:computer_name] ||= cluster.hosts.map { |n| n.name } if cluster
86
+ attrs[:computer_name] ||= cluster.hosts.map(&:name) if cluster
72
87
  attrs[:computer_name] ||= computer.name if computer
73
88
  attrs
74
89
  end
@@ -85,22 +100,11 @@ module Fog
85
100
 
86
101
  attr_accessor :vm
87
102
 
88
- def search_attributes
89
- attrs = super
90
- attrs.delete :vm
91
- if vm
92
- attrs[:computer_name] ||= vm.computer_name
93
- attrs[match] = vm.send(match)
94
- end
95
- attrs
96
- end
97
-
98
- def create(attributes = {})
99
- object = new(attributes)
103
+ def new(attributes = {})
104
+ object = super
100
105
  # Ensure both ID and Name are populated, regardless of `match_on`
101
106
  object.vm_id ||= vm.id if vm && object.respond_to?(:vm_id)
102
107
  object.vm_name ||= vm.name if vm && object.respond_to?(:vm_name)
103
- object.save
104
108
  object
105
109
  end
106
110
 
@@ -109,12 +113,27 @@ module Fog
109
113
  to_s
110
114
  end
111
115
 
112
- private
116
+ protected
117
+
118
+ def creation_attributes
119
+ to_add = {}
120
+ to_add[:vm] = vm if vm
113
121
 
114
- def logger
115
- service.logger
122
+ super.merge to_add
116
123
  end
117
124
 
125
+ def search_attributes
126
+ attrs = super
127
+ attrs.delete :vm
128
+ if vm
129
+ attrs[:computer_name] ||= vm.computer_name
130
+ attrs[match] = vm.send(match)
131
+ end
132
+ attrs
133
+ end
134
+
135
+ private
136
+
118
137
  def match
119
138
  self.class.match_on || :vm_name
120
139
  end
@@ -24,10 +24,12 @@ module Fog
24
24
  # :ProtocolVersion # 32775
25
25
  ].freeze
26
26
 
27
- requires :hyperv_username, :hyperv_password
27
+ requires :hyperv_username
28
28
  recognizes :hyperv_endpoint, :hyperv_host,
29
- :hyperv_transport,
29
+ :hyperv_password,
30
+ :hyperv_transport, :hyperv_realm,
30
31
  :hyperv_debug
32
+
31
33
  secrets :hyperv_password, :connection
32
34
 
33
35
  model_path 'fog/hyperv/models/compute'
@@ -54,6 +56,7 @@ module Fog
54
56
  collection :vhds
55
57
 
56
58
  request_path 'fog/hyperv/requests/compute'
59
+ request :add_vm_dvd_drive
57
60
  request :add_vm_hard_disk_drive
58
61
  request :add_vm_network_adapter
59
62
  request :connect_vm_network_adapter
@@ -77,6 +80,7 @@ module Fog
77
80
  request :new_vm_switch
78
81
  request :remove_item
79
82
  request :remove_vm
83
+ request :remove_vm_dvd_drive
80
84
  request :remove_vm_hard_disk_drive
81
85
  request :remove_vm_network_adapter
82
86
  request :restart_vm
@@ -135,11 +139,15 @@ module Fog
135
139
  require 'fog/json'
136
140
  require 'logging'
137
141
 
142
+ @connections = {}
138
143
  @hyperv_endpoint = options[:hyperv_endpoint]
139
144
  @hyperv_endpoint = "http://#{options[:hyperv_host]}:5985/wsman" if !@hyperv_endpoint && options[:hyperv_host]
140
145
  @hyperv_username = options[:hyperv_username]
141
146
  @hyperv_password = options[:hyperv_password]
142
- @hyperv_transport = options[:hyperv_transport] || :negotiate
147
+ @hyperv_realm = options[:hyperv_realm]
148
+ @hyperv_transport = options[:hyperv_transport] || (@hyperv_realm ? :kerberos : :negotiate)
149
+
150
+ Logging.logger['WinRM::HTTP::HttpNegotiate'].level = :error
143
151
  @logger = Logging.logger['hyper-v']
144
152
  if options[:hyperv_debug]
145
153
  logger.level = :debug
@@ -159,10 +167,15 @@ module Fog
159
167
  else
160
168
  run_wql('SELECT Name FROM Msvm_ComputerSystem WHERE Caption = "Hosting Computer System"') && true
161
169
  end
162
- rescue Fog::Hyperv::Errors::ServiceError
170
+ rescue => e
171
+ logger.debug "Validation failed with #{e.class}; #{e.message}"
163
172
  false
164
173
  end
165
174
 
175
+ def supports_multihop?
176
+ return [ :kerberos ].include? @hyperv_transport.to_s.downcase.to_sym
177
+ end
178
+
166
179
  def version
167
180
  @version ||= run_wql('SELECT Version FROM Win32_OperatingSystem', _namespace: 'root/cimv2/*')[:xml_fragment].first[:version] rescue \
168
181
  run_shell("$VMMS = if ([environment]::Is64BitProcess) { \"$($env:SystemRoot)\\System32\\vmms.exe\" } else { \"$($env:SystemRoot)\\Sysnative\\vmms.exe\" }\n(Get-Item $VMMS).VersionInfo.ProductVersion", _skip_json: true).stdout.strip
@@ -206,6 +219,7 @@ module Fog
206
219
  end
207
220
 
208
221
  def run_shell(command, options = {})
222
+ orig_opts = options.dup
209
223
  return_fields = options.delete :_return_fields
210
224
  return_fields = "| select #{Fog::Hyperv.camelize([return_fields].flatten).join ','}" if return_fields
211
225
  suffix = options.delete :_suffix
@@ -213,8 +227,28 @@ module Fog
213
227
  skip_json = options.delete :_skip_json
214
228
  skip_camelize = options.delete :_skip_camelize
215
229
  skip_uncamelize = options.delete :_skip_uncamelize
230
+ computer = options.delete(:_target_computer) || '.'
231
+ computers = [options.delete(:computer_name)].flatten.compact
216
232
  options = Fog::Hyperv.camelize(options) unless skip_camelize
217
233
 
234
+ if supports_multihop?
235
+ options[:computer_name] = computers
236
+ computer = '.'
237
+ elsif computers.length > 1 || (computers.length == 1 && !['.','localhost'].include?(computers.first.downcase))
238
+ logger.debug "Executing multi-query for #{computers}"
239
+ ret = []
240
+ computers.each do |c|
241
+ out = run_shell(command, orig_opts.merge(computer_name: nil, _target_computer: c))
242
+ if out.is_a? Array
243
+ ret += out
244
+ else
245
+ ret << out
246
+ end
247
+ end
248
+ return ret.first if ret.length == 1
249
+ return ret
250
+ end
251
+
218
252
  # commandline = "$Args = #{hash_to_optmap options}\n$Ret = #{command} @Args#{"\n$Ret #{return_fields} | ConvertTo-Json -Compress #{"-Depth #{json_depth}" if json_depth}" unless skip_json}"
219
253
  # puts " > #{commandline.split("\n").join "\n > "}" if @hyperv_debug
220
254
  args = options.reject { |k, v| v.nil? || v.is_a?(FalseClass) || k.to_s.start_with?('_') || (v.is_a?(String) && v.empty?) }.map do |k, v|
@@ -244,7 +278,7 @@ module Fog
244
278
  out.exitcode = -1
245
279
  end
246
280
  else
247
- @connection.shell(:powershell) do |shell|
281
+ connection(computer).shell(:powershell) do |shell|
248
282
  out = shell.run(commandline)
249
283
  end
250
284
  end
@@ -265,18 +299,43 @@ module Fog
265
299
  end
266
300
  end
267
301
 
268
- def connect
269
- # return require 'open3' if local?
302
+ def connect(endpoint = nil)
303
+ endpoint = @hyperv_endpoint unless endpoint
304
+ fqdn = URI.parse(endpoint).host
270
305
 
271
306
  require 'winrm'
272
- @connection = WinRM::Connection.new(
273
- endpoint: @hyperv_endpoint,
307
+ opts = {
308
+ endpoint: endpoint,
309
+ transport: @hyperv_transport,
274
310
  user: @hyperv_username,
275
311
  password: @hyperv_password,
276
- transport: @hyperv_transport
277
- )
278
- Logging.logger['WinRM::HTTP::HttpNegotiate'].level = :error
279
- @connection.logger.level = :error
312
+ realm: @hyperv_realm
313
+ }
314
+
315
+ logger.debug "Creating WinRM connection with #{opts.merge password: '<REDACTED>'}"
316
+ connection = WinRM::Connection.new opts
317
+ connection.logger.level = :error
318
+ @connections[fqdn] = connection
319
+
320
+ if endpoint == @hyperv_endpoint
321
+ @connection = connection
322
+ @connections['.'] = connection
323
+ @connections['localhost'] = connection
324
+ end
325
+ connection
326
+ end
327
+
328
+ def connection(host)
329
+ c = @connections.find { |k,_v| k.downcase.start_with?(host.downcase) }
330
+ return c[1] if c
331
+
332
+ # TODO: Support non-standard endpoints for additional hosts
333
+ unless host.include? '.'
334
+ host = "#{host}.#{URI.parse(@hyperv_endpoint).host.split('.').drop(1).join('.')}"
335
+ end
336
+ endpoint = "http://#{host}:5985/wsman"
337
+
338
+ connect(endpoint)
280
339
  end
281
340
  end
282
341
 
@@ -8,17 +8,37 @@ module Fog
8
8
  super
9
9
  end
10
10
 
11
+ def ensure_value_getter
12
+ return if model.methods.include?("#{name}_values".to_sym)
13
+ model.class_eval <<-EOS, __FILE__, __LINE__
14
+ def #{name}_values
15
+ #{values}.freeze
16
+ end
17
+ EOS
18
+ end
19
+
11
20
  def create_setter
21
+ ensure_value_getter
12
22
  model.class_eval <<-EOS, __FILE__, __LINE__
13
23
  def #{name}=(new_#{name})
24
+ _values = #{name}_values
25
+ # FIXME: Prepare a key comparison array in advance
14
26
  if new_#{name}.is_a?(Fixnum)
15
- raise Fog::Hyperv::Errors::ServiceError, "\#{new_#{name}} is not in the range (0..#{values.length - 1})" unless new_#{name} >= 0 && new_#{name} < #{values.length}
16
- attributes[:#{name}] = #{values}[new_#{name}]
27
+ if _values.class.to_s == 'Array' # TODO: Better way to do class comparison in generated code
28
+ puts "\#{_values} (\#{_values.class}) Is array"
29
+ raise Fog::Hyperv::Errors::ServiceError, "\#{new_#{name}} is not in the range (0..\#{_values.length - 1})" unless new_#{name} >= 0 && new_#{name} < _values.length
30
+ else
31
+ puts "\#{_values} (\#{_values.class}) Is not array"
32
+ raise Fog::Hyperv::Errors::ServiceError, "\#{new_#{name}} is not one of \#{_values.is_a?(Hash) ? _values.keys : _values})" unless (_values.is_a?(Hash) ? _values.keys : _values).include? new_#{name}
33
+ end
34
+
35
+ attributes[:#{name}] = _values[new_#{name}]
17
36
  elsif new_#{name}.nil?
18
37
  attributes[:#{name}] = nil
19
38
  else
39
+ puts "Is string"
20
40
  new_#{name} = new_#{name}.to_s.to_sym unless new_#{name}.is_a? String
21
- raise Fog::Hyperv::Errors::ServiceError, "\#{new_#{name}} is not one of #{values.is_a?(Hash) ? values.values : values})" unless #{(values.is_a?(Hash) ? values.values : values)}.include? new_#{name}
41
+ raise Fog::Hyperv::Errors::ServiceError, "\#{new_#{name}} is not one of \#{_values.is_a?(Hash) ? _values.keys : _values})" unless (_values.is_a?(Hash) ? _values.keys : _values).include? new_#{name}
22
42
  attributes[:#{name}] = new_#{name}
23
43
  end
24
44
  end
@@ -26,23 +46,21 @@ module Fog
26
46
  end
27
47
 
28
48
  def create_getter
49
+ ensure_value_getter
29
50
  model.class_eval <<-EOS, __FILE__, __LINE__
30
51
  def #{name}_num
52
+ _values = #{name}_values
31
53
  return nil if self.#{name}.nil?
32
54
  if self.#{name}.is_a?(Fixnum)
33
55
  self.#{name}
34
56
  else
35
- if #{values}.is_a?(Hash)
36
- #{values}.key(self.#{name})
57
+ if _values.is_a?(Hash)
58
+ _values.key(self.#{name})
37
59
  else
38
- #{values}.index(self.#{name})
60
+ _values.index(self.#{name})
39
61
  end
40
62
  end
41
63
  end
42
-
43
- def #{name}_values
44
- #{values}.freeze
45
- end
46
64
  EOS
47
65
  super
48
66
  end
@@ -10,6 +10,14 @@ module Fog
10
10
  # TODO? Enum values; :CD, :IDE, :LegacyNetworkAdapter, :Floppy (, :VHD, :NetworkAdapter)
11
11
  attribute :startup_order, type: :array
12
12
  attribute :vm_name, type: :string
13
+
14
+ attr_reader :computer, :vm
15
+
16
+ def initialize(args = {})
17
+ super
18
+ @computer = args.delete :computer
19
+ @vm = args.delete :vm
20
+ end
13
21
 
14
22
  def save
15
23
  requires :computer_name, :vm_name
@@ -8,16 +8,19 @@ module Fog
8
8
  attribute :domain, type: :string
9
9
  attribute :name, type: :string
10
10
 
11
+ def initialize(attrs = {})
12
+ super
13
+
14
+ @collections = {}
15
+ self.class.ensure_collections!
16
+ end
17
+
11
18
  def nodes
12
19
  @nodes ||= [service.get_cluster_node(cluster: name, _return_fields: [:description, :name, :node_name])].flatten
13
20
  end
14
21
 
15
22
  def hosts
16
- @hosts ||= service.hosts computer_name: nodes.map { |n| n[:name] }
17
- end
18
-
19
- def servers
20
- @servers ||= service.servers cluster: self
23
+ @hosts ||= nodes.map { |n| service.hosts.get(n[:name]) }
21
24
  end
22
25
 
23
26
  def reload
@@ -33,6 +36,23 @@ module Fog
33
36
  merge_attributes(data.attributes)
34
37
  self
35
38
  end
39
+
40
+ def self.ensure_collections!
41
+ return if @collections
42
+ @collections = true
43
+
44
+ Fog::Compute::Hyperv.collections.each do |coll|
45
+ # Don't recurse on hosts
46
+ next if coll == :hosts
47
+ coll_name = coll.to_s.split('_').map(&:capitalize).join
48
+ klass = Fog::Compute::Hyperv.const_get(coll_name)
49
+ next if klass.requires?(:vm)
50
+
51
+ define_method coll do
52
+ @collections[coll] ||= service.send(coll, cluster: self)
53
+ end
54
+ end
55
+ end
36
56
  end
37
57
  end
38
58
  end
@@ -5,6 +5,10 @@ module Fog
5
5
  model Fog::Compute::Hyperv::Cluster
6
6
 
7
7
  get_method :get_cluster
8
+
9
+ def get(name, filters = {})
10
+ super(filters.merge(name: name))
11
+ end
8
12
  end
9
13
  end
10
14
  end
@@ -5,10 +5,10 @@ module Fog
5
5
  identity :id
6
6
 
7
7
  attribute :computer_name
8
- attribute :debugger_mode, type: :enum, values: [ :On, :Off ]
8
+ attribute :debugger_mode, type: :enum, values: %i[On Off]
9
9
  attribute :name
10
10
  attribute :path
11
-
11
+
12
12
  def save
13
13
  raise Fog::Errors::NotImplemented
14
14
  end
@@ -11,36 +11,65 @@ module Fog
11
11
  attribute :pool_name
12
12
  attribute :controller_location
13
13
  attribute :controller_number
14
- attribute :controller_type, type: :enum, values: [ :IDE, :SCSI ]
15
- attribute :dvd_media_type, type: :enum, values: [ :None, :ISO, :Passthrough ]
14
+ attribute :controller_type, type: :enum, values: %i[IDE SCSI]
15
+ attribute :dvd_media_type, type: :enum, values: %i[None ISO Passthrough]
16
16
  attribute :vm_id
17
17
  attribute :vm_name
18
18
  # TODO? VM Snapshots?
19
19
  #
20
- attr_accessor :to_controller_number, :to_controller_location
21
20
 
22
21
  def save
23
22
  requires :computer_name, :vm_name
24
23
 
25
- data = service.set_vm_dvd_drive(
26
- computer_name: computer_name,
27
- vm_name: vm_name,
28
- passthru: true,
24
+ data = \
25
+ if persisted?
26
+ service.set_vm_dvd_drive(
27
+ computer_name: old.computer_name,
28
+ vm_name: old.vm_name,
29
+ controller_number: old.controller_number,
30
+ controller_location: old.controller_location,
31
+ passthru: true,
29
32
 
30
- controller_number: controller_number,
31
- controller_location: controller_location,
32
- resource_pool_name: pool_name,
33
- path: path || '$null',
34
- to_controller_number: to_controller_number,
35
- to_controller_location: to_controller_location,
33
+ resource_pool_name: changed!(:pool_name),
34
+ path: changed?(:path) && (path || '$null'),
35
+ to_controller_number: changed!(:controller_number),
36
+ to_controller_location: changed!(:controller_location),
37
+
38
+ _return_fields: self.class.attributes,
39
+ _json_depth: 1
40
+ )
41
+ else
42
+ service.add_vm_dvd_drive(
43
+ computer_name: computer_name,
44
+ vm_name: vm_name,
45
+ passthru: true,
46
+
47
+ controller_number: controller_number,
48
+ controller_location: controller_location,
49
+ path: path,
50
+ resource_pool_name: pool_name,
51
+
52
+ _return_fields: self.class.attributes,
53
+ _json_depth: 1
54
+ )
55
+ end
36
56
 
37
- _return_fields: self.class.attributes,
38
- _json_depth: 1
39
- )
40
57
  merge_attributes(data)
58
+ @old = dup
41
59
  self
42
60
  end
43
61
 
62
+ def destroy
63
+ requires :computer_name, :vm_name, :controller_number, :controller_location
64
+
65
+ service.remove_vm_dvd_drive(
66
+ computer_name: computer_name,
67
+ vm_name: vm_name,
68
+ controller_number: controller_number,
69
+ controller_location: controller_location
70
+ )
71
+ end
72
+
44
73
  def reload
45
74
  requires :computer_name, :vm_name
46
75
 
@@ -54,6 +83,7 @@ module Fog
54
83
  _json_depth: 1
55
84
  )
56
85
  merge_attributes(data.attributes)
86
+ @old = data
57
87
  self
58
88
  end
59
89
  end
@@ -44,6 +44,7 @@ module Fog
44
44
  _return_fields: self.class.attributes
45
45
  )
46
46
  merge_attributes(data)
47
+ @old = data
47
48
  self
48
49
  end
49
50
  end
@@ -6,7 +6,7 @@ module Fog
6
6
 
7
7
  attribute :computer_name
8
8
  attribute :disk
9
- attribute :is_deleted
9
+ # attribute :is_deleted
10
10
  attribute :name
11
11
  attribute :path
12
12
  attribute :pool_name
@@ -16,21 +16,25 @@ module Fog
16
16
  #
17
17
 
18
18
  def save
19
+ raise Fog::Hyperv::Errors::ServiceError, "Can't create new floppy drives" unless persisted?
20
+
19
21
  requires :computer_name, :vm_name
20
22
 
21
- data = service.set_vm_floppy_disk_drive(
22
- computer_name: computer_name,
23
- vm_name: vm_name,
24
- passthru: true,
23
+ data = \
24
+ service.set_vm_floppy_disk_drive(
25
+ computer_name: old.computer_name,
26
+ vm_name: old.vm_name,
27
+ passthru: true,
25
28
 
26
- resource_pool_name: pool_name,
27
- path: path,
29
+ resource_pool_name: changed!(:pool_name),
30
+ path: changed?(:path) && (path || '$null'),
28
31
 
29
- _return_fields: self.class.attributes,
30
- _json_depth: 1
31
- )
32
+ _return_fields: self.class.attributes,
33
+ _json_depth: 1
34
+ )
32
35
 
33
36
  merge_attributes(data)
37
+ @old = dup
34
38
  self
35
39
  end
36
40
 
@@ -40,6 +44,7 @@ module Fog
40
44
  vm_name: vm_name
41
45
  )
42
46
  merge_attributes(data.attributes)
47
+ @old = data
43
48
  self
44
49
  end
45
50
  end
@@ -6,12 +6,12 @@ module Fog
6
6
 
7
7
  attribute :computer_name
8
8
  attribute :controller_location
9
- attribute :controller_number
10
- attribute :controller_type, type: :enum, values: [ :IDE, :SCSI ]
9
+ attribute :controller_number, type: :integer
10
+ attribute :controller_type, type: :enum, values: %i[IDE SCSI]
11
11
  attribute :disk
12
12
  # attribute :is_deleted
13
- attribute :maximum_iops
14
- attribute :minimum_iops
13
+ attribute :maximum_iops, type: :integer
14
+ attribute :minimum_iops, type: :integer
15
15
  attribute :name
16
16
  attribute :path
17
17
  attribute :pool_name
@@ -22,7 +22,7 @@ module Fog
22
22
 
23
23
  def vhd
24
24
  return nil unless path && computer_name
25
- @vhd ||= Fog::Compute::Hyperv::Vhd.new(service.get_vhd(computer_name: computer_name, path: path).merge(service: service))
25
+ @vhd ||= service.vhds.get(path, computer_name: computer_name)
26
26
  end
27
27
 
28
28
  def size_bytes
@@ -43,24 +43,24 @@ module Fog
43
43
  controller_location: old.controller_location,
44
44
  controller_number: old.controller_number,
45
45
  controller_type: old.controller_type,
46
+ passthru: true,
46
47
 
47
48
  disk_number: changed?(:disk) && disk && disk.number,
48
- maximum_iops: changed?(:maximum_iops) && maximum_iops,
49
- minimum_iops: changed?(:minimum_iops) && minimum_iops,
50
- path: changed?(:path) && path,
51
- resource_pool_name: changed?(:pool_name) && pool_name,
52
- support_persistent_reservations: changed?(:support_persistent_reservations) && support_persistent_reservations,
53
- to_controller_location: changed?(:controller_location) && controller_location,
54
- to_controller_number: changed?(:controller_number) && controller_number,
55
- to_controller_type: changed?(:controller_type) && controller_type,
49
+ maximum_iops: changed!(:maximum_iops),
50
+ minimum_iops: changed!(:minimum_iops),
51
+ path: changed!(:path),
52
+ resource_pool_name: changed!(:pool_name),
53
+ support_persistent_reservations: changed!(:support_persistent_reservations),
54
+ to_controller_location: changed!(:controller_location),
55
+ to_controller_number: changed!(:controller_number),
56
+ to_controller_type: changed!(:controller_type),
56
57
 
57
- passthru: true,
58
58
  _return_fields: self.class.attributes,
59
59
  _json_depth: 1
60
60
  )
61
61
  @vhd = nil if changed?(:path)
62
62
  else
63
- possible = %i(computer_name controller_location controller_number controller_type path vm_name).freeze
63
+ possible = %i[computer_name controller_location controller_number controller_type path vm_name].freeze
64
64
  data = service.add_vm_hard_disk_drive(
65
65
  attributes.select { |k, _v| possible.include? k }.merge(
66
66
  disk_number: disk && disk.number,
@@ -29,7 +29,7 @@ module Fog
29
29
  Fog::Compute::Hyperv.collections.each do |coll|
30
30
  coll_name = coll.to_s.split('_').map(&:capitalize).join
31
31
  klass = Fog::Compute::Hyperv.const_get(coll_name)
32
- next if klass.requires? :vm
32
+ next if klass.requires?(:vm)
33
33
 
34
34
  define_method coll do
35
35
  @collections[coll] ||= service.send(coll, computer: self)
@@ -83,7 +83,7 @@ module Fog
83
83
  passthru: true,
84
84
 
85
85
  dynamic_mac_address: changed?(:dynamic_mac_address_enabled) && dynamic_mac_address_enabled,
86
- static_mac_address: (changed?(:mac_address) || changed?(:dynamic_mac_address_enabled)) && !dynamic_mac_address_enabled && mac_address,
86
+ static_mac_address: changed!(:mac_address) || ((changed!(:dynamic_mac_address_enabled) == false) && mac_address),
87
87
 
88
88
  _return_fields: self.class.attributes,
89
89
  _json_depth: 1
@@ -134,6 +134,7 @@ module Fog
134
134
  vm_name: vm_name
135
135
  )
136
136
  merge_attributes(data.attributes)
137
+ @old = data
137
138
  self
138
139
  end
139
140
  end
@@ -45,6 +45,7 @@ module Fog
45
45
  attribute :com_port2
46
46
  attribute :dynamic_memory_enabled, type: :boolean, default: false
47
47
  attribute :generation, type: :integer, default: 1 # 1 => bios, 2 => uefi
48
+ attribute :is_clustered, type: :boolean, default: false
48
49
  attribute :state, type: :enum, values: VM_STATUS_ENUM_VALUES
49
50
  attribute :status, type: :string
50
51
  attribute :memory_assigned, type: :integer
@@ -59,6 +60,8 @@ module Fog
59
60
  :hard_drives,
60
61
  :floppy_drive
61
62
 
63
+ attr_accessor :cluster_name
64
+
62
65
  %i(network_adapters dvd_drives floppy_drives hard_drives vhds).each do |attr|
63
66
  define_method attr do
64
67
  if persisted?
@@ -75,6 +78,13 @@ module Fog
75
78
  end
76
79
  end
77
80
 
81
+ def initialize(attrs = {})
82
+ super
83
+
84
+ @cluster = attrs.delete :cluster
85
+ @computer = attrs.delete :computer
86
+ end
87
+
78
88
  def bios
79
89
  @bios ||= begin
80
90
  if generation == 1
@@ -11,36 +11,42 @@ module Fog
11
11
  attribute :name
12
12
  attribute :net_adapter_interface_description
13
13
  attribute :notes
14
- attribute :switch_type, type: :enum, values: [ :Private, :Internal, :External ]
14
+ attribute :switch_type, type: :enum, values: %i[Private Internal External]
15
15
 
16
16
  def save
17
17
  requires :name
18
18
 
19
- data = if persisted?
20
- service.set_vm_switch(
21
- computer_name: computer_name,
22
- default_flow_minimum_bandwidth_absolute: default_flow_minimum_bandwidth_absolute,
23
- default_flow_minimum_bandwidth_weight: default_flow_minimum_bandwidth_weight,
24
- name: name,
25
- net_adapter_interface_description: net_adapter_interface_description,
26
- notes: notes,
27
- switch_type: !net_adapter_interface_description && switch_type,
28
- passthru: true,
29
- _return_fields: self.class.attributes,
30
- _json_depth: 1
31
- )
32
- else
33
- service.new_vm_switch(
34
- computer_name: computer_name,
35
- name: name,
36
- net_adapter_interface_description: net_adapter_interface_description,
37
- notes: notes,
38
- switch_type: !net_adapter_interface_description && switch_type,
39
- _return_fields: self.class.attributes,
40
- _json_depth: 1
41
- )
42
- end
19
+ data = \
20
+ if persisted?
21
+ service.set_vm_switch(
22
+ computer_name: old.computer_name,
23
+ name: old.name,
24
+ net_adapter_interface_description: old.net_adapter_interface_description,
25
+ switch_type: !old.net_adapter_interface_description && old.switch_type,
26
+ passthru: true,
27
+
28
+ default_flow_minimum_bandwidth_absolute: changed!(default_flow_minimum_bandwidth_absolute),
29
+ default_flow_minimum_bandwidth_weight: changed!(default_flow_minimum_bandwidth_weight),
30
+ notes: changed!(notes),
31
+
32
+ _return_fields: self.class.attributes,
33
+ _json_depth: 1
34
+ )
35
+ else
36
+ service.new_vm_switch(
37
+ computer_name: computer_name,
38
+ name: name,
39
+ net_adapter_interface_description: net_adapter_interface_description,
40
+ notes: notes,
41
+ switch_type: !net_adapter_interface_description && switch_type,
42
+
43
+ _return_fields: self.class.attributes,
44
+ _json_depth: 1
45
+ )
46
+ end
47
+
43
48
  merge_attributes(data)
49
+ @old = dup
44
50
  self
45
51
  end
46
52
 
@@ -50,6 +56,7 @@ module Fog
50
56
  computer_name: computer_name
51
57
  )
52
58
  merge_attributes(data.attributes)
59
+ @old = data
53
60
  self
54
61
  end
55
62
  end
@@ -14,8 +14,8 @@ module Fog
14
14
  attribute :path, type: :string, default: 'New Disk'
15
15
  attribute :pool_name
16
16
  attribute :size, type: :integer, default: 343_597_383_68
17
- attribute :vhd_format, type: :enum, values: [ :Unknown, nil, :VHD, :VHDX, :VHDSet ]
18
- attribute :vhd_type, type: :enum, values: [ :Unknown, nil, :Fixed, :Dynamic, :Differencing ]
17
+ attribute :vhd_format, type: :enum, values: [:Unknown, nil, :VHD, :VHDX, :VHDSet]
18
+ attribute :vhd_type, type: :enum, values: [:Unknown, nil, :Fixed, :Dynamic, :Differencing]
19
19
  # TODO? VM Snapshots?
20
20
  #
21
21
 
@@ -35,7 +35,7 @@ module Fog
35
35
  end
36
36
 
37
37
  def unc_path
38
- "\\\\#{computer_name || '.'}\\#{real_path.gsub ':', '$'}"
38
+ "\\\\#{computer_name || '.'}\\#{real_path.tr ':', '$'}"
39
39
  end
40
40
 
41
41
  def host
@@ -84,6 +84,7 @@ module Fog
84
84
  disk_number: disk
85
85
  )
86
86
  merge_attributes(data.attributes)
87
+ @old = data
87
88
  self
88
89
  end
89
90
 
@@ -92,7 +93,7 @@ module Fog
92
93
 
93
94
  service.remove_item(
94
95
  path: unc_path
95
- ) if path
96
+ )
96
97
  end
97
98
  end
98
99
  end
@@ -0,0 +1,12 @@
1
+ module Fog
2
+ module Compute
3
+ class Hyperv
4
+ class Real
5
+ def add_vm_dvd_disk_drive(options = {})
6
+ requires options, :vm_name
7
+ run_shell('Add-VMDvdDrive', options)
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ module Fog
2
+ module Compute
3
+ class Hyperv
4
+ class Real
5
+ def remove_vm_dvd_drive(options = {})
6
+ requires options, :vm_name, :controller_number, :controller_location
7
+ run_shell('Remove-VMDvdDrive', options.merge(_skip_json: true)).exitcode.zero?
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
@@ -1,5 +1,5 @@
1
1
  module Fog
2
2
  module Hyperv
3
- VERSION = '0.0.3'.freeze
3
+ VERSION = '0.0.4'.freeze
4
4
  end
5
5
  end
@@ -19,6 +19,9 @@ module Fog
19
19
  end
20
20
 
21
21
  def parent
22
+ return @vm if @vm
23
+ return @computer if @computer
24
+ return @cluster if @cluster
22
25
  return nil unless collection
23
26
  return collection.vm if collection.attributes.include? :vm
24
27
  return collection.computer if collection.attributes.include? :computer
@@ -29,6 +32,24 @@ module Fog
29
32
  end
30
33
  end
31
34
 
35
+ def vm
36
+ if respond_to?(:vm_name) && vm_name
37
+ @vm ||= service.servers.get vm_name
38
+ end
39
+ end
40
+
41
+ def computer
42
+ if respond_to?(:computer_name) && computer_name
43
+ @computer ||= service.hosts.get computer_name
44
+ end
45
+ end
46
+
47
+ def cluster
48
+ if respond_to?(:cluster_name) && cluster_name
49
+ @cluster ||= service.clusters.get cluster_name
50
+ end
51
+ end
52
+
32
53
  private
33
54
 
34
55
  def logger
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fog-hyperv
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexander Olofsson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-08-30 00:00:00.000000000 Z
11
+ date: 2017-11-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: fog-core
@@ -120,6 +120,7 @@ files:
120
120
  - lib/fog/hyperv/models/compute/switches.rb
121
121
  - lib/fog/hyperv/models/compute/vhd.rb
122
122
  - lib/fog/hyperv/models/compute/vhds.rb
123
+ - lib/fog/hyperv/requests/compute/add_vm_dvd_drive.rb
123
124
  - lib/fog/hyperv/requests/compute/add_vm_hard_disk_drive.rb
124
125
  - lib/fog/hyperv/requests/compute/add_vm_network_adapter.rb
125
126
  - lib/fog/hyperv/requests/compute/connect_vm_network_adapter.rb
@@ -155,6 +156,7 @@ files:
155
156
  - lib/fog/hyperv/requests/compute/new_vm_switch.rb
156
157
  - lib/fog/hyperv/requests/compute/remove_item.rb
157
158
  - lib/fog/hyperv/requests/compute/remove_vm.rb
159
+ - lib/fog/hyperv/requests/compute/remove_vm_dvd_drive.rb
158
160
  - lib/fog/hyperv/requests/compute/remove_vm_hard_disk_drive.rb
159
161
  - lib/fog/hyperv/requests/compute/remove_vm_network_adapter.rb
160
162
  - lib/fog/hyperv/requests/compute/restart_vm.rb
@@ -191,7 +193,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
191
193
  version: '0'
192
194
  requirements: []
193
195
  rubyforge_project:
194
- rubygems_version: 2.6.12
196
+ rubygems_version: 2.6.14
195
197
  signing_key:
196
198
  specification_version: 4
197
199
  summary: Module for the `fog` gem to support Microsoft Hyper-V.