fog-kubevirt 1.2.5 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (29) hide show
  1. checksums.yaml +4 -4
  2. data/lib/fog/kubevirt.rb +3 -2
  3. data/lib/fog/kubevirt/compute/compute.rb +5 -148
  4. data/lib/fog/kubevirt/compute/models/persistentvolume.rb +9 -9
  5. data/lib/fog/kubevirt/compute/models/persistentvolumes.rb +6 -1
  6. data/lib/fog/kubevirt/compute/models/pvcs.rb +3 -1
  7. data/lib/fog/kubevirt/compute/models/storageclass.rb +8 -2
  8. data/lib/fog/kubevirt/compute/models/template.rb +6 -0
  9. data/lib/fog/kubevirt/compute/models/vm.rb +1 -0
  10. data/lib/fog/kubevirt/compute/models/vminstances.rb +1 -1
  11. data/lib/fog/kubevirt/compute/models/vms.rb +12 -3
  12. data/lib/fog/kubevirt/compute/requests/create_networkattachmentdef.rb +0 -3
  13. data/lib/fog/kubevirt/compute/requests/create_persistentvolume.rb +0 -3
  14. data/lib/fog/kubevirt/compute/requests/create_pvc.rb +0 -3
  15. data/lib/fog/kubevirt/compute/requests/create_service.rb +0 -3
  16. data/lib/fog/kubevirt/compute/requests/create_storageclass.rb +0 -3
  17. data/lib/fog/kubevirt/compute/requests/create_vm.rb +0 -3
  18. data/lib/fog/kubevirt/compute/requests/create_vminstance.rb +0 -3
  19. data/lib/fog/kubevirt/compute/utils/exception_wrapper.rb +43 -0
  20. data/lib/fog/kubevirt/compute/utils/unit_converter.rb +115 -0
  21. data/lib/fog/kubevirt/version.rb +1 -1
  22. data/spec/integration/mac_vmi_spec.rb +135 -0
  23. data/spec/integration/net-attach-def_spec.rb +43 -0
  24. data/spec/integration/pvcs_spec.rb +3 -2
  25. data/spec/integration/shared_context.rb +11 -4
  26. data/spec/integration/volumes_spec.rb +45 -0
  27. data/spec/unit/create_vm_spec.rb +4 -3
  28. data/spec/unit/unit_converter_spec.rb +4 -2
  29. metadata +10 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a757bb97341858b22dcbce97ae84899d67851f64
4
- data.tar.gz: 2d92ed31781d8c7331a76dbb6111875222baf5ce
3
+ metadata.gz: b8646bec0df5d890b6c7aca5738a39596c982146
4
+ data.tar.gz: aa9d02efd6cd353248becb936f2365b25765ea03
5
5
  SHA512:
6
- metadata.gz: dc6973eb073d9abfa2bb8016820d7e62a51ed5a08725b9238dcd86fd847ddc0873196c05536433133581c732cfdd63df2414dc034c30c48e0313d4bbf907ba05
7
- data.tar.gz: 2262f37fe3e69f0c66856c17722dbd4ff88160ee32c11d736eddb29ebd29b53948fc71312e473e28c3c3be6d01ca32db2f4c95da2a016c9c73ce9cbf4fc3be1d
6
+ metadata.gz: 8bbe31efac532a38857e420fd847d878c0653eb64b75266506b03c7bd5b8fe918a908d99a71a391bf44e8b16d2ca3d5f157bc7a9787170fadb8bde99751eae3c
7
+ data.tar.gz: d72fa662e0dbf84869a8e66e7f30ea96062bc8365415733c4eef0fb7ea6c55851440b27cd94b27e1482cbea5f25a8b8b10fe4d0662f45ac0bd72c7445dcbdd69
@@ -7,9 +7,10 @@ module Fog
7
7
 
8
8
  module Errors
9
9
  class ServiceError < Fog::Errors::Error; end
10
- class AlreadyExistsError < Fog::Errors::Error; end
11
10
  class ClientError < Fog::Errors::Error; end
12
- class ValidationError < Fog::Errors::Error; end
11
+ class AlreadyExistsError < ClientError; end
12
+ class NotFoundError < ClientError; end
13
+ class ValidationError < ClientError; end
13
14
  end
14
15
 
15
16
  service(:compute, 'Compute')
@@ -2,7 +2,8 @@ require 'delegate'
2
2
  require 'json'
3
3
  require 'rest-client'
4
4
 
5
- require "fog/core"
5
+ require 'fog/core'
6
+ require 'fog/kubevirt/compute/utils/exception_wrapper'
6
7
 
7
8
  module Fog
8
9
  module Kubevirt
@@ -84,150 +85,6 @@ module Fog
84
85
  end
85
86
  end
86
87
 
87
- class ExceptionWrapper
88
- def initialize(client, version)
89
- @client = client
90
- @version = version
91
- end
92
-
93
- def method_missing(symbol, *args)
94
- super unless @client.respond_to?(symbol)
95
-
96
- if block_given?
97
- @client.__send__(symbol, *args) do |*block_args|
98
- yield(*block_args)
99
- end
100
- else
101
- @client.__send__(symbol, *args)
102
- end
103
- rescue KubeException => e
104
- raise ::Fog::Kubevirt::Errors::ClientError, e
105
- end
106
-
107
- def respond_to_missing?(method_name, include_private = false)
108
- @client.respond_to?(symbol, include_all) || super
109
- end
110
-
111
- def version
112
- @version
113
- end
114
- end
115
-
116
- #
117
- # This class contains functions performing unit calculations.
118
- # Originally implemented for manageiq-providers-kubevirt project
119
- #
120
- class UnitConverter
121
- #
122
- # Converts a value containing an optional unit to another unit. For example, if the value is
123
- # `2 MiB` and the unit is `KiB` the result will be 2048.
124
- #
125
- # @param value [String] The value to convert, with an optional unit suffix.
126
- # @param to [Symbol] (:b) The name of the unit to convert to, for example `:gib`.
127
- # @return [BigDecimal] The converted value.
128
- #
129
- def self.convert(value, to)
130
- # Return nil if no value is given:
131
- return nil unless value
132
-
133
- match = validate(value)
134
- value = match[:value]
135
- from = match[:suffix]
136
-
137
- # Convert the value from string to big decimal to make sure that we don't loose precission:
138
- value = BigDecimal(value)
139
-
140
- # Do the conversion:
141
- from_factor = scale_factor(from)
142
- to_factor = scale_factor(to)
143
- value * from_factor / to_factor
144
- end
145
-
146
- #
147
- # Validates and extracts the numeric value and the unit
148
- #
149
- # @param value [String] The value to validate with optional unit suffix.
150
- # @return [MatchData] describing the match, or ValidationError is raised if no match.
151
- #
152
- def self.validate(value)
153
- match = VALUE_RE.match(value)
154
- raise ::Fog::Kubevirt::Errors::ValidationError, "The value '#{value}' isn't a valid unit" unless match
155
-
156
- match
157
- end
158
-
159
- #
160
- # Regular expression used to match values and to separate them into the numeric value and the
161
- # optional unit suffix.
162
- #
163
- VALUE_RE = /^\s*(?<value>[[:digit:]]+)\s*(?<suffix>[[:alpha:]]+)?\s*$/i
164
- private_constant :VALUE_RE
165
-
166
- #
167
- # Scale factors associated to the different unit suffixes.
168
- #
169
- SCALE_FACTORS = {
170
- :b => 1,
171
-
172
- :k => 10**3,
173
- :m => 10**6,
174
- :g => 10**9,
175
- :t => 10**12,
176
- :p => 10**15,
177
- :e => 10**18,
178
- :z => 10**21,
179
- :y => 10**24,
180
-
181
- :kb => 10**3,
182
- :mb => 10**6,
183
- :gb => 10**9,
184
- :tb => 10**12,
185
- :pb => 10**15,
186
- :eb => 10**18,
187
- :zb => 10**21,
188
- :yb => 10**24,
189
-
190
- :ki => 2**10,
191
- :mi => 2**20,
192
- :gi => 2**30,
193
- :ti => 2**40,
194
- :pi => 2**50,
195
- :ei => 2**60,
196
- :zi => 2**70,
197
- :yi => 2**80,
198
-
199
- :kib => 2**10,
200
- :mib => 2**20,
201
- :gib => 2**30,
202
- :tib => 2**40,
203
- :pib => 2**50,
204
- :eib => 2**60,
205
- :zib => 2**70,
206
- :yib => 2**80
207
- }.freeze
208
- private_constant :SCALE_FACTORS
209
-
210
- #
211
- # Finds the scale factor that matches the given unit suffix.
212
- #
213
- # @param sufix [Symbol, String] The unit suffix, as symbol or string. For example `MiB` or `:mib`.
214
- # @return [Integer] The scale factor corresponding to that unit.
215
- #
216
- def self.scale_factor(suffix)
217
- suffix = suffix.downcase.to_sym if suffix.kind_of?(String)
218
- factor = SCALE_FACTORS[suffix]
219
- raise ::Fog::Kubevirt::Errors::ValidationError, "The value '#{suffix}' isn't a valid unit suffix" unless factor
220
- factor
221
- end
222
- private_class_method :scale_factor
223
- end
224
-
225
- #
226
- # Label name which identifies operation system information
227
- #
228
- OS_LABEL = 'kubevirt.io/os'.freeze
229
- OS_LABEL_SYMBOL = :'kubevirt.io/os'
230
-
231
88
  # converts kubeclient objects into hash for fog to consume
232
89
  def object_to_hash(object)
233
90
  result = object
@@ -382,7 +239,7 @@ module Fog
382
239
  #
383
240
  def watch_vms(opts = {})
384
241
  mapper = Proc.new do |notice|
385
- vm = OpenStruct.new(Vm.parse(notice.object)) if notice.object.kind == 'VirtualMachine'
242
+ vm = OpenStruct.new(Vm.parse(object_to_hash(notice.object))) if notice.object.kind == 'VirtualMachine'
386
243
  vm ||= OpenStruct.new
387
244
 
388
245
  populate_notice_attributes(vm, notice)
@@ -401,7 +258,7 @@ module Fog
401
258
  #
402
259
  def watch_vminstances(opts = {})
403
260
  mapper = Proc.new do |notice|
404
- vminstance = OpenStruct.new(Vminstance.parse(notice.object)) if notice.object.kind == 'VirtualMachineInstance'
261
+ vminstance = OpenStruct.new(Vminstance.parse(object_to_hash(notice.object))) if notice.object.kind == 'VirtualMachineInstance'
405
262
  vminstance ||= OpenStruct.new
406
263
 
407
264
  populate_notice_attributes(vminstance, notice)
@@ -538,7 +395,7 @@ module Fog
538
395
  end
539
396
 
540
397
  def wrap_client(client, version, key)
541
- wrapped_client = ExceptionWrapper.new(client, version)
398
+ wrapped_client = ::Fog::Kubevirt::Utils::ExceptionWrapper.new(client, version, @log)
542
399
  @clients[key] = wrapped_client
543
400
 
544
401
  wrapped_client
@@ -8,17 +8,17 @@ module Fog
8
8
  attribute :uid, :aliases => 'metadata_uid'
9
9
  attribute :annotations, :aliases => 'metadata_annotations'
10
10
  attribute :labels, :aliases => 'metadata_labels'
11
- attribute :access_modes, :aliases => 'spec_access_modes'
12
- attribute :mount_options, :aliases => 'spec_mount_options'
13
- attribute :reclaim_policy, :aliases => 'spec_reclaim_policy'
14
- attribute :storage_class, :aliases => 'spec_storage_class'
11
+ attribute :access_modes, :aliases => 'spec_access_modes'
12
+ attribute :mount_options, :aliases => 'spec_mount_options'
13
+ attribute :reclaim_policy, :aliases => 'spec_reclaim_policy'
14
+ attribute :storage_class, :aliases => 'spec_storage_class'
15
15
  attribute :capacity, :aliases => 'spec_capacity'
16
16
  attribute :claim_ref, :aliases => 'spec_claim_ref'
17
- attribute :type, :aliases => 'spec_type'
18
- attribute :config, :aliases => 'spec_config'
17
+ attribute :type, :aliases => 'spec_type'
18
+ attribute :config, :aliases => 'spec_config'
19
19
  attribute :phase, :aliases => 'status_phase'
20
- attribute :reason, :aliases => 'status_reason'
21
- attribute :message, :aliases => 'status_message'
20
+ attribute :reason, :aliases => 'status_reason'
21
+ attribute :message, :aliases => 'status_message'
22
22
 
23
23
  def self.parse(object)
24
24
  metadata = object[:metadata]
@@ -35,7 +35,7 @@ module Fog
35
35
  :access_modes => spec[:accessModes],
36
36
  :mount_options => spec[:mountOptions],
37
37
  :reclaim_policy => spec[:persistentVolumeReclaimPolicy],
38
- :storage_class => spec[:storageClassName],
38
+ :storage_class => spec[:storageClassName],
39
39
  :capacity => spec.dig(:capacity, :storage),
40
40
  :claim_ref => spec[:claimRef],
41
41
  :type => type,
@@ -35,6 +35,11 @@ module Fog
35
35
  name = args[:name]
36
36
  labels = args[:labels]
37
37
 
38
+ # type is required
39
+ if args[:type].nil? || args[:type].empty?
40
+ raise ::Fog::Kubevirt::Errors::ValidationError "Type of storage can not be empty"
41
+ end
42
+
38
43
  volume = {
39
44
  :apiVersion => "v1",
40
45
  :kind => "PersistentVolume",
@@ -52,7 +57,7 @@ module Fog
52
57
  } if args[:capacity]
53
58
 
54
59
  volume[:spec][:accessModes] = args[:access_modes] if args[:access_modes]
55
- volume[:spec][args[:type].to_sym] = args[:config] if args[:type]
60
+ volume[:spec][args[:type].to_sym] = args[:config]
56
61
 
57
62
  service.create_persistentvolume(volume)
58
63
  end
@@ -1,10 +1,12 @@
1
1
  require 'fog/core/collection'
2
2
  require 'fog/kubevirt/compute/models/pvc'
3
+ require 'fog/kubevirt/compute/utils/unit_converter'
3
4
 
4
5
  module Fog
5
6
  module Kubevirt
6
7
  class Compute
7
8
  class Pvcs < Fog::Collection
9
+
8
10
  attr_reader :kind, :resource_version
9
11
 
10
12
  model Fog::Kubevirt::Compute::Pvc
@@ -82,7 +84,7 @@ module Fog
82
84
  private
83
85
 
84
86
  def check_size(value)
85
- ::Fog::Kubevirt::Compute::Shared::UnitConverter.validate(value[:storage])
87
+ ::Fog::Kubevirt::Utils::UnitConverter.validate(value[:storage])
86
88
  end
87
89
  end
88
90
  end
@@ -2,10 +2,13 @@ module Fog
2
2
  module Kubevirt
3
3
  class Compute
4
4
  class Storageclass < Fog::Model
5
+ IS_DEFAULT = 'storageclass.kubernetes.io/is-default-class'.freeze
6
+
5
7
  # Metadata
6
8
  identity :name
7
9
  attribute :resource_version, :aliases => 'metadata_resource_version'
8
10
  attribute :uid, :aliases => 'metadata_uid'
11
+ attribute :default
9
12
 
10
13
  attribute :mount_options
11
14
  attribute :parameters
@@ -15,17 +18,20 @@ module Fog
15
18
 
16
19
  def self.parse(object)
17
20
  metadata = object[:metadata]
18
- {
21
+ annotations = metadata[:annotations]
22
+ sc = {
19
23
  :name => metadata[:name],
20
24
  :resource_version => metadata[:resourceVersion],
21
25
  :uid => metadata[:uid],
22
-
23
26
  :parameters => object[:parameters],
24
27
  :mount_options => object[:mountOptions],
25
28
  :provisioner => object[:provisioner],
26
29
  :reclaim_policy => object[:reclaimPolicy],
27
30
  :volume_binding_mode => object[:volumeBindingMode]
28
31
  }
32
+
33
+ sc[:default] = annotations[IS_DEFAULT.to_sym] unless annotations.nil?
34
+ sc
29
35
  end
30
36
  end
31
37
  end
@@ -15,6 +15,12 @@ module Fog
15
15
  attribute :objects
16
16
  attribute :parameters
17
17
 
18
+ #
19
+ # Label name which identifies operation system information
20
+ #
21
+ OS_LABEL = 'kubevirt.io/os'.freeze
22
+ OS_LABEL_SYMBOL = :'kubevirt.io/os'
23
+
18
24
  def clone(options = {})
19
25
  params = values(options)
20
26
 
@@ -6,6 +6,7 @@ module Fog
6
6
  class Compute
7
7
  class Vm < Fog::Model
8
8
  include VmAction
9
+ include Shared
9
10
  extend VmBase
10
11
  define_properties
11
12
 
@@ -37,7 +37,7 @@ module Fog
37
37
  service.delete_vm(name, namespace)
38
38
 
39
39
  # delete vm instance
40
- service.delete_vminstance(name, namespace) unless vm_instance.nil?
40
+ service.delete_vminstance(name) unless vm_instance.nil?
41
41
  end
42
42
  end
43
43
  end
@@ -44,6 +44,7 @@ module Fog
44
44
  # :vm_name [String] - name of a vm
45
45
  # :cpus [String] - number of cpus
46
46
  # :memory_size [String] - amount of memory
47
+ # :memory_unit [String] - memory unit to use, default to 'M'
47
48
  # :image [String] - name of a container disk
48
49
  # :pvc [String] - name of a persistent volume claim
49
50
  # :cloudinit [Hash] - number of items needed to configure cloud-init
@@ -71,6 +72,7 @@ module Fog
71
72
  vm_name = args.fetch(:vm_name)
72
73
  cpus = args.fetch(:cpus, nil)
73
74
  memory_size = args.fetch(:memory_size)
75
+ memory_unit = args.fetch(:memory_unit, "M")
74
76
  init = args.fetch(:cloudinit, {})
75
77
  networks = args.fetch(:networks, nil)
76
78
  interfaces = args.fetch(:interfaces, nil)
@@ -80,6 +82,8 @@ module Fog
80
82
  raise ::Fog::Kubevirt::Errors::ValidationError
81
83
  end
82
84
 
85
+ memory = "#{memory_size}#{memory_unit}"
86
+ ::Fog::Kubevirt::Utils::UnitConverter.validate(memory)
83
87
  volumes, disks = add_vm_storage(vm_name, vm_volumes)
84
88
 
85
89
  unless init.empty?
@@ -114,7 +118,7 @@ module Fog
114
118
  },
115
119
  :resources => {
116
120
  :requests => {
117
- :memory => "#{memory_size}M"
121
+ :memory => memory
118
122
  }
119
123
  }
120
124
  },
@@ -173,10 +177,9 @@ module Fog
173
177
  end
174
178
 
175
179
  def add_vm_storage(vm_name, vm_volumes)
176
- normalized_vm_name = vm_name.gsub(/[._]+/,'-')
177
180
  volumes, disks = [], []
178
181
  vm_volumes.each_with_index do |v, idx|
179
- volume_name = v.name || normalized_vm_name + "-disk-0" + idx.to_s
182
+ volume_name = v.name.nil? ? normalized_name(vm_name) + "-disk-0" + idx.to_s : normalized_name(v.name)
180
183
  disk = {
181
184
  :name => volume_name,
182
185
  :disk => {}
@@ -209,6 +212,12 @@ module Fog
209
212
 
210
213
  return volumes, disks
211
214
  end
215
+
216
+ private
217
+
218
+ def normalized_name(name)
219
+ name.gsub(/[._]+/,'-')
220
+ end
212
221
  end
213
222
  end
214
223
  end
@@ -22,9 +22,6 @@ module Fog
22
22
  net_att = deep_merge!(net_att, metadata: { namespace: @namespace })
23
23
  end
24
24
  kube_net_client.create_network_attachment_definition(net_att)
25
- rescue ::Fog::Kubevirt::Errors::ClientError => err
26
- log.warn(err)
27
- raise ::Fog::Kubevirt::Errors::AlreadyExistsError
28
25
  end
29
26
  end
30
27
 
@@ -4,9 +4,6 @@ module Fog
4
4
  class Real
5
5
  def create_persistentvolume(volume)
6
6
  kube_client.create_persistent_volume(volume)
7
- rescue ::Fog::Kubevirt::Errors::ClientError => err
8
- log.warn(err)
9
- raise ::Fog::Kubevirt::Errors::AlreadyExistsError
10
7
  end
11
8
  end
12
9
 
@@ -4,9 +4,6 @@ module Fog
4
4
  class Real
5
5
  def create_pvc(pvc)
6
6
  kube_client.create_persistent_volume_claim(pvc)
7
- rescue ::Fog::Kubevirt::Errors::ClientError => err
8
- log.warn(err)
9
- raise ::Fog::Kubevirt::Errors::AlreadyExistsError
10
7
  end
11
8
  end
12
9
 
@@ -4,9 +4,6 @@ module Fog
4
4
  class Real
5
5
  def create_service(srv)
6
6
  kube_client.create_service(srv)
7
- rescue ::Fog::Kubevirt::Errors::ClientError => err
8
- log.warn(err)
9
- raise ::Fog::Kubevirt::Errors::AlreadyExistsError
10
7
  end
11
8
  end
12
9
 
@@ -4,9 +4,6 @@ module Fog
4
4
  class Real
5
5
  def create_storageclass(storageclass)
6
6
  kube_storage_client.create_storage_class(storageclass)
7
- rescue ::Fog::Kubevirt::Errors::ClientError => err
8
- log.warn(err)
9
- raise ::Fog::Kubevirt::Errors::AlreadyExistsError
10
7
  end
11
8
  end
12
9
 
@@ -6,9 +6,6 @@ module Fog
6
6
  vm[:apiVersion] = kubevirt_client.version
7
7
 
8
8
  kubevirt_client.create_virtual_machine(vm)
9
- rescue ::Fog::Kubevirt::Errors::ClientError => err
10
- log.warn(err)
11
- raise ::Fog::Kubevirt::Errors::AlreadyExistsError
12
9
  end
13
10
  end
14
11
 
@@ -5,9 +5,6 @@ module Fog
5
5
 
6
6
  def create_vminstance(vm)
7
7
  kubevirt_client.create_virtual_machine_instance(vm)
8
- rescue ::Fog::Kubevirt::Errors::ClientError => err
9
- log.warn(err)
10
- raise ::Fog::Kubevirt::Errors::AlreadyExistsError
11
8
  end
12
9
  end
13
10
 
@@ -0,0 +1,43 @@
1
+ module Fog
2
+ module Kubevirt
3
+ module Utils
4
+ class ExceptionWrapper
5
+ def initialize(client, version, log)
6
+ @client = client
7
+ @version = version
8
+ @log = log
9
+ end
10
+
11
+ def method_missing(symbol, *args)
12
+ super unless @client.respond_to?(symbol)
13
+
14
+ if block_given?
15
+ @client.__send__(symbol, *args) do |*block_args|
16
+ yield(*block_args)
17
+ end
18
+ else
19
+ @client.__send__(symbol, *args)
20
+ end
21
+ rescue KubeException => e
22
+ if e.error_code == 409
23
+ @log.warn(e)
24
+ raise ::Fog::Kubevirt::Errors::AlreadyExistsError, e
25
+ elsif e.error_code == 404
26
+ raise ::Fog::Kubevirt::Errors::NotFoundError, e
27
+ else
28
+ @log.warn(e)
29
+ raise ::Fog::Kubevirt::Errors::ClientError, e
30
+ end
31
+ end
32
+
33
+ def respond_to_missing?(method_name, include_private = false)
34
+ @client.respond_to?(method_name, include_private) || super
35
+ end
36
+
37
+ def version
38
+ @version
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,115 @@
1
+ module Fog
2
+ module Kubevirt
3
+ module Utils
4
+ #
5
+ # This class contains functions performing unit calculations.
6
+ # Originally implemented for manageiq-providers-kubevirt project
7
+ #
8
+ class UnitConverter
9
+
10
+ #
11
+ # Converts a value containing an optional unit to another unit. For example, if the value is
12
+ # `2 MiB` and the unit is `KiB` the result will be 2048.
13
+ #
14
+ # @param value [String] The value to convert, with an optional unit suffix.
15
+ # @param to [Symbol] (:b) The name of the unit to convert to, for example `:gib`.
16
+ # @return [BigDecimal] The converted value.
17
+ #
18
+ def self.convert(value, to)
19
+ # Return nil if no value is given:
20
+ return nil unless value
21
+
22
+ match = validate(value)
23
+ value = match[:value]
24
+ from = match[:suffix]
25
+
26
+ # Convert the value from string to big decimal to make sure that we don't loose precission:
27
+ value = BigDecimal(value)
28
+
29
+ # Do the conversion:
30
+ from_factor = scale_factor(from)
31
+ to_factor = scale_factor(to)
32
+ value * from_factor / to_factor
33
+ end
34
+
35
+ #
36
+ # Validates and extracts the numeric value and the unit
37
+ #
38
+ # @param value [String] The value to validate with optional unit suffix.
39
+ # @return [MatchData] describing the match, or ValidationError is raised if no match.
40
+ #
41
+ def self.validate(value)
42
+ match = VALUE_RE.match(value)
43
+ raise ::Fog::Kubevirt::Errors::ValidationError, "The value '#{value}' isn't a valid unit" unless match
44
+
45
+ match
46
+ end
47
+
48
+ #
49
+ # Regular expression used to match values and to separate them into the numeric value and the
50
+ # optional unit suffix.
51
+ #
52
+ VALUE_RE = /^\s*(?<value>[[:digit:]]+)\s*(?<suffix>[[:alpha:]]+)?\s*$/i
53
+ private_constant :VALUE_RE
54
+
55
+ #
56
+ # Scale factors associated to the different unit suffixes.
57
+ #
58
+ SCALE_FACTORS = {
59
+ :b => 1,
60
+
61
+ :k => 10**3,
62
+ :m => 10**6,
63
+ :g => 10**9,
64
+ :t => 10**12,
65
+ :p => 10**15,
66
+ :e => 10**18,
67
+ :z => 10**21,
68
+ :y => 10**24,
69
+
70
+ :kb => 10**3,
71
+ :mb => 10**6,
72
+ :gb => 10**9,
73
+ :tb => 10**12,
74
+ :pb => 10**15,
75
+ :eb => 10**18,
76
+ :zb => 10**21,
77
+ :yb => 10**24,
78
+
79
+ :ki => 2**10,
80
+ :mi => 2**20,
81
+ :gi => 2**30,
82
+ :ti => 2**40,
83
+ :pi => 2**50,
84
+ :ei => 2**60,
85
+ :zi => 2**70,
86
+ :yi => 2**80,
87
+
88
+ :kib => 2**10,
89
+ :mib => 2**20,
90
+ :gib => 2**30,
91
+ :tib => 2**40,
92
+ :pib => 2**50,
93
+ :eib => 2**60,
94
+ :zib => 2**70,
95
+ :yib => 2**80
96
+ }.freeze
97
+ private_constant :SCALE_FACTORS
98
+
99
+ #
100
+ # Finds the scale factor that matches the given unit suffix.
101
+ #
102
+ # @param sufix [Symbol, String] The unit suffix, as symbol or string. For example `MiB` or `:mib`.
103
+ # @return [Integer] The scale factor corresponding to that unit.
104
+ #
105
+ def self.scale_factor(suffix)
106
+ suffix = suffix.downcase.to_sym if suffix.kind_of?(String)
107
+ factor = SCALE_FACTORS[suffix]
108
+ raise ::Fog::Kubevirt::Errors::ValidationError, "The value '#{suffix}' isn't a valid unit suffix" unless factor
109
+ factor
110
+ end
111
+ private_class_method :scale_factor
112
+ end
113
+ end
114
+ end
115
+ end
@@ -1,5 +1,5 @@
1
1
  module Fog
2
2
  module Kubevirt
3
- VERSION = '1.2.5'
3
+ VERSION = '1.3.0'
4
4
  end
5
5
  end
@@ -0,0 +1,135 @@
1
+ require_relative './shared_context'
2
+
3
+ describe Fog::Kubevirt::Compute do
4
+ before :all do
5
+ conn = KubevirtConnection.new()
6
+ @client = conn.client
7
+ @watch = nil
8
+ end
9
+
10
+ it 'creates VMI and checks MAC' do
11
+ vm_name = 'test'
12
+ cpus = 1
13
+ memory_size = 64
14
+
15
+ volume = Fog::Kubevirt::Compute::Volume.new
16
+ volume.type = 'containerDisk'
17
+ volume.name = 'test-disk-01'
18
+ volume.info = 'registry:5000/kubevirt/cirros-container-disk-demo:devel'
19
+
20
+ @client.vms.create(vm_name: vm_name, cpus: cpus, memory_size: memory_size, volumes: [volume])
21
+
22
+ vm = @client.vms.get(vm_name)
23
+ assert_equal(vm.cpu_cores, cpus)
24
+ assert_equal(vm.memory, "#{memory_size}M")
25
+
26
+ vm.start()
27
+
28
+ # check whether vmi to be created if not it will raise ClientError
29
+ @client.vminstances.get(vm_name)
30
+
31
+ vmis = @client.vminstances.all()
32
+ @watch = @client.watch_vminstances(:resource_version => vmis.resource_version)
33
+
34
+ thread = Thread.new do
35
+ @watch.each do |notice|
36
+ break if notice.type == 'MODIFIED' && notice.status == 'Running'
37
+ end
38
+ end
39
+
40
+ if thread.join(60).nil?
41
+ fail('VMI did not start')
42
+ end
43
+ @watch.finish
44
+ @watch = nil
45
+
46
+ vmi = @client.vminstances.get(vm_name)
47
+
48
+ assert_equal(vm.cpu_cores, cpus)
49
+ assert_equal(vm.memory, "#{memory_size}M")
50
+
51
+ vmi.interfaces do |iface|
52
+ assert !iface.mac_address.nil?
53
+ end
54
+
55
+ vmis = @client.vminstances.all()
56
+ @watch = @client.watch_vminstances(:resource_version => vmis.resource_version)
57
+
58
+ @client.vminstances.destroy(vm_name, @client.namespace)
59
+
60
+ thread = Thread.new do
61
+ @watch.each do |notice|
62
+ break if notice.type == 'DELETED'
63
+ end
64
+ end
65
+
66
+ if thread.join(60).nil?
67
+ fail('VMI was not removed')
68
+ end
69
+ @watch.finish
70
+ @watch = nil
71
+ end
72
+
73
+ it 'creates VMI and checks MAC using server' do
74
+ vm_name = 'test-server'
75
+ cpus = 1
76
+ memory_size = 64
77
+
78
+ volume = Fog::Kubevirt::Compute::Volume.new
79
+ volume.type = 'containerDisk'
80
+ volume.name = 'test.disk.01'
81
+ volume.info = 'registry:5000/kubevirt/cirros-container-disk-demo:devel'
82
+
83
+ @client.vms.create(vm_name: vm_name, cpus: cpus, memory_size: memory_size, volumes: [volume])
84
+
85
+ server_vm = @client.servers.get(vm_name)
86
+ assert_equal(server_vm.cpu_cores, cpus)
87
+ assert_equal(server_vm.memory, "#{memory_size}M")
88
+
89
+ server_vm.start()
90
+
91
+ # check whether vmi to be created if not it will raise ClientError
92
+ @client.servers.get(vm_name)
93
+
94
+ vmis = @client.vminstances.all()
95
+ @watch = @client.watch_vminstances(:resource_version => vmis.resource_version)
96
+
97
+ thread = Thread.new do
98
+ @watch.each do |notice|
99
+ break if notice.type == 'MODIFIED' && notice.status == 'Running'
100
+ end
101
+ end
102
+
103
+ if thread.join(60).nil?
104
+ fail('Server did not start')
105
+ end
106
+ @watch.finish
107
+ @watch = nil
108
+
109
+ server = @client.servers.get(vm_name)
110
+
111
+ assert_equal(server.cpu_cores, cpus)
112
+ assert_equal(server.memory, "#{memory_size}M")
113
+
114
+ server.interfaces do |iface|
115
+ assert !iface.mac_address.nil?
116
+ end
117
+
118
+ vmis = @client.vminstances.all()
119
+ @watch = @client.watch_vminstances(:resource_version => vmis.resource_version)
120
+
121
+ server.destroy
122
+
123
+ thread = Thread.new do
124
+ @watch.each do |notice|
125
+ break if notice.type == 'DELETED'
126
+ end
127
+ end
128
+
129
+ if thread.join(60).nil?
130
+ fail('Server was not removed')
131
+ end
132
+ @watch.finish
133
+ @watch = nil
134
+ end
135
+ end
@@ -0,0 +1,43 @@
1
+ require_relative './shared_context'
2
+
3
+ describe Fog::Kubevirt::Compute do
4
+ before :all do
5
+ conn = KubevirtConnection.new()
6
+ @client = conn.client.networkattachmentdefs
7
+ end
8
+
9
+ it 'CRD network attachements' do
10
+ name = 'ovs-red'
11
+ config = '{ cni_version: "0.3.1", type: "ovs", bridge: "red" }'
12
+
13
+ @client.create(name: name, config: config)
14
+
15
+ net_att_def = @client.get(name)
16
+ assert_equal(net_att_def.config, config)
17
+
18
+ @client.delete(name)
19
+
20
+ begin
21
+ @client.get(name)
22
+ fail "net_attach_def should not exist"
23
+ rescue ::Fog::Kubevirt::Errors::ClientError
24
+ # expected
25
+ end
26
+ end
27
+
28
+ it 'creates empty config' do
29
+ begin
30
+ @client.create(name: 'aaa')
31
+ fail "empty config can not be nil"
32
+ rescue ::Fog::Kubevirt::Errors::ClientError
33
+ # expected
34
+ end
35
+
36
+ begin
37
+ @client.create(name: 'aaa', config: '{}')
38
+ fail "empty config can not be nil"
39
+ rescue ::Fog::Kubevirt::Errors::ClientError
40
+ # expected
41
+ end
42
+ end
43
+ end
@@ -3,13 +3,14 @@ require_relative './shared_context'
3
3
  describe Fog::Kubevirt::Compute do
4
4
  before :all do
5
5
  conn = KubevirtConnection.new()
6
+ @namespace = conn.client.namespace
6
7
  @client = conn.client.pvcs
7
8
  end
8
9
 
9
10
  it 'CRD pvc' do
10
11
  pvc = {
11
12
  :name => 'test-pvc',
12
- :namespace => 'default',
13
+ :namespace => @namespace,
13
14
  :storage_class => '',
14
15
  :access_modes => ['ReadWriteOnce'],
15
16
  :requests => { storage: "1Gi" }
@@ -42,7 +43,7 @@ describe Fog::Kubevirt::Compute do
42
43
  it 'fails with wrong size format' do
43
44
  pvc = {
44
45
  :name => 'test-pvc',
45
- :namespace => 'default',
46
+ :namespace => @namespace,
46
47
  :storage_class => '',
47
48
  :access_modes => ['ReadWriteOnce'],
48
49
  :requests => { storage: "X" }
@@ -8,15 +8,22 @@ class KubevirtConnection
8
8
  @host = ENV.key?('KUBE_HOST') ? ENV['KUBE_HOST'] : options[:host]
9
9
  @port = ENV.key?('KUBE_PORT') ? ENV['KUBE_PORT'] : options[:port]
10
10
  @token = ENV.key?('KUBE_TOKEN') ? ENV['KUBE_TOKEN'] : options[:token]
11
+ @namespace = ENV.key?('KUBE_NAMESPACE') ? ENV['KUBE_NAMESPACE'] : options[:namespace]
11
12
  end
12
13
 
13
14
  def client
14
15
  if !ENV.key?('KUBECONFIG')
15
- return Fog::Kubevirt::Compute.new(:kubevirt_hostname => @host,
16
- :kubevirt_port => @port,
17
- :kubevirt_token => @token)
16
+ return Fog::Kubevirt::Compute.new(
17
+ :kubevirt_hostname => @host,
18
+ :kubevirt_port => @port,
19
+ :kubevirt_token => @token,
20
+ :kubevirt_namespace => @namespace
21
+ )
18
22
  else
19
- return Fog::Kubevirt::Compute.new(:kubevirt_token => nil)
23
+ return Fog::Kubevirt::Compute.new(
24
+ :kubevirt_token => nil,
25
+ :kubevirt_namespace => @namespace
26
+ )
20
27
  end
21
28
  end
22
29
  end
@@ -0,0 +1,45 @@
1
+ require_relative './shared_context'
2
+
3
+ require 'fileutils'
4
+
5
+ describe Fog::Kubevirt::Compute do
6
+ before :all do
7
+ conn = KubevirtConnection.new()
8
+ @client = conn.client
9
+ end
10
+
11
+ it 'creates volumes' do
12
+ scs = @client.storageclasses.all()
13
+ default_sc = scs.find { | sc | sc.default }
14
+
15
+ dir = Dir.mktmpdir
16
+
17
+ name = 'my-local-storage'
18
+ access_modes = [ 'ReadWriteOnce' ]
19
+ capacity = '1Gi'
20
+ type = 'hostPath'
21
+ config = { path: dir, type: "Directory" }
22
+
23
+ @client.persistentvolumes.create(name: name,
24
+ access_modes: access_modes,
25
+ capacity: capacity,
26
+ storage_class: default_sc.name,
27
+ type: type,
28
+ config: config)
29
+
30
+ pv = @client.persistentvolumes.get(name)
31
+ assert_equal(pv.storage_class, default_sc.name)
32
+ assert_equal(pv.capacity, capacity)
33
+ assert_equal(pv.access_modes, access_modes)
34
+
35
+ @client.persistentvolumes.delete(name)
36
+ FileUtils.remove_entry dir
37
+
38
+ begin
39
+ @client.persistentvolumes.get(name)
40
+ fail "pv should not exist"
41
+ rescue ::Fog::Kubevirt::Errors::ClientError
42
+ # expected
43
+ end
44
+ end
45
+ end
@@ -18,7 +18,7 @@ describe Fog::Compute do
18
18
  begin
19
19
  vm_name = 'test'
20
20
  cpus = 1
21
- memory_size = 64
21
+ memory_size = '64'
22
22
  pvc1 = 'mypvc1'
23
23
  pvc2 = 'mypvc2'
24
24
 
@@ -104,12 +104,13 @@ describe Fog::Compute do
104
104
  begin
105
105
  vm_name = 'test2'
106
106
  cpus = 1
107
- memory_size = 64
107
+ memory_size = '64'
108
+ memory_unit = 'M'
108
109
 
109
110
  volume = Fog::Kubevirt::Compute::Volume.new
110
111
  volume.type = 'persistentVolumeClaim'
111
112
  volume.info = 'mypvc3'
112
- @service.vms.create(vm_name: vm_name, cpus: cpus, memory_size: memory_size, volumes: [volume])
113
+ @service.vms.create(vm_name: vm_name, cpus: cpus, memory_size: memory_size, memory_unit: memory_unit, volumes: [volume])
113
114
 
114
115
  vm = @service.vms.get(vm_name)
115
116
 
@@ -1,8 +1,10 @@
1
1
  require_relative './spec_helper'
2
2
 
3
- describe Fog::Kubevirt::Compute::Shared::UnitConverter do
3
+ require 'fog/kubevirt/compute/utils/unit_converter'
4
4
 
5
- described_class = Fog::Kubevirt::Compute::Shared::UnitConverter
5
+ describe Fog::Kubevirt::Utils::UnitConverter do
6
+
7
+ described_class = Fog::Kubevirt::Utils::UnitConverter
6
8
 
7
9
  describe '.convert' do
8
10
  it 'converts correctly units that correspond to powers of 10' do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fog-kubevirt
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.5
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Piotr Kliczewski
@@ -14,7 +14,7 @@ authors:
14
14
  autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
- date: 2019-04-24 00:00:00.000000000 Z
17
+ date: 2019-05-14 00:00:00.000000000 Z
18
18
  dependencies:
19
19
  - !ruby/object:Gem::Dependency
20
20
  name: minitest
@@ -209,6 +209,8 @@ files:
209
209
  - lib/fog/kubevirt/compute/requests/list_vms.rb
210
210
  - lib/fog/kubevirt/compute/requests/list_volumes.rb
211
211
  - lib/fog/kubevirt/compute/requests/update_vm.rb
212
+ - lib/fog/kubevirt/compute/utils/exception_wrapper.rb
213
+ - lib/fog/kubevirt/compute/utils/unit_converter.rb
212
214
  - lib/fog/kubevirt/version.rb
213
215
  - spec/fixtures/kubevirt/networkattachmentdefinition/networkattachmentdefinitions_crud.yml
214
216
  - spec/fixtures/kubevirt/persistentvolume/persistent_volumes_crud.yml
@@ -219,8 +221,11 @@ files:
219
221
  - spec/fixtures/kubevirt/storageclass/storageclasses_crud.yml
220
222
  - spec/fixtures/kubevirt/vm/vm_create_multi.yml
221
223
  - spec/fixtures/kubevirt/vm/vm_create_single.yml
224
+ - spec/integration/mac_vmi_spec.rb
225
+ - spec/integration/net-attach-def_spec.rb
222
226
  - spec/integration/pvcs_spec.rb
223
227
  - spec/integration/shared_context.rb
228
+ - spec/integration/volumes_spec.rb
224
229
  - spec/unit/compute_v1alpha2_spec.rb
225
230
  - spec/unit/create_vm_spec.rb
226
231
  - spec/unit/network_attachment_definition_v1alpha2_spec.rb
@@ -266,8 +271,11 @@ test_files:
266
271
  - spec/fixtures/kubevirt/storageclass/storageclasses_crud.yml
267
272
  - spec/fixtures/kubevirt/vm/vm_create_multi.yml
268
273
  - spec/fixtures/kubevirt/vm/vm_create_single.yml
274
+ - spec/integration/mac_vmi_spec.rb
275
+ - spec/integration/net-attach-def_spec.rb
269
276
  - spec/integration/pvcs_spec.rb
270
277
  - spec/integration/shared_context.rb
278
+ - spec/integration/volumes_spec.rb
271
279
  - spec/unit/compute_v1alpha2_spec.rb
272
280
  - spec/unit/create_vm_spec.rb
273
281
  - spec/unit/network_attachment_definition_v1alpha2_spec.rb