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.
- checksums.yaml +4 -4
- data/lib/fog/kubevirt.rb +3 -2
- data/lib/fog/kubevirt/compute/compute.rb +5 -148
- data/lib/fog/kubevirt/compute/models/persistentvolume.rb +9 -9
- data/lib/fog/kubevirt/compute/models/persistentvolumes.rb +6 -1
- data/lib/fog/kubevirt/compute/models/pvcs.rb +3 -1
- data/lib/fog/kubevirt/compute/models/storageclass.rb +8 -2
- data/lib/fog/kubevirt/compute/models/template.rb +6 -0
- data/lib/fog/kubevirt/compute/models/vm.rb +1 -0
- data/lib/fog/kubevirt/compute/models/vminstances.rb +1 -1
- data/lib/fog/kubevirt/compute/models/vms.rb +12 -3
- data/lib/fog/kubevirt/compute/requests/create_networkattachmentdef.rb +0 -3
- data/lib/fog/kubevirt/compute/requests/create_persistentvolume.rb +0 -3
- data/lib/fog/kubevirt/compute/requests/create_pvc.rb +0 -3
- data/lib/fog/kubevirt/compute/requests/create_service.rb +0 -3
- data/lib/fog/kubevirt/compute/requests/create_storageclass.rb +0 -3
- data/lib/fog/kubevirt/compute/requests/create_vm.rb +0 -3
- data/lib/fog/kubevirt/compute/requests/create_vminstance.rb +0 -3
- data/lib/fog/kubevirt/compute/utils/exception_wrapper.rb +43 -0
- data/lib/fog/kubevirt/compute/utils/unit_converter.rb +115 -0
- data/lib/fog/kubevirt/version.rb +1 -1
- data/spec/integration/mac_vmi_spec.rb +135 -0
- data/spec/integration/net-attach-def_spec.rb +43 -0
- data/spec/integration/pvcs_spec.rb +3 -2
- data/spec/integration/shared_context.rb +11 -4
- data/spec/integration/volumes_spec.rb +45 -0
- data/spec/unit/create_vm_spec.rb +4 -3
- data/spec/unit/unit_converter_spec.rb +4 -2
- metadata +10 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b8646bec0df5d890b6c7aca5738a39596c982146
|
4
|
+
data.tar.gz: aa9d02efd6cd353248becb936f2365b25765ea03
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8bbe31efac532a38857e420fd847d878c0653eb64b75266506b03c7bd5b8fe918a908d99a71a391bf44e8b16d2ca3d5f157bc7a9787170fadb8bde99751eae3c
|
7
|
+
data.tar.gz: d72fa662e0dbf84869a8e66e7f30ea96062bc8365415733c4eef0fb7ea6c55851440b27cd94b27e1482cbea5f25a8b8b10fe4d0662f45ac0bd72c7445dcbdd69
|
data/lib/fog/kubevirt.rb
CHANGED
@@ -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
|
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
|
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
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
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,
|
18
|
-
attribute :config,
|
17
|
+
attribute :type, :aliases => 'spec_type'
|
18
|
+
attribute :config, :aliases => 'spec_config'
|
19
19
|
attribute :phase, :aliases => 'status_phase'
|
20
|
-
attribute :reason,
|
21
|
-
attribute :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
|
-
|
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]
|
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::
|
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
|
|
@@ -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 =>
|
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
|
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
|
|
@@ -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
|
data/lib/fog/kubevirt/version.rb
CHANGED
@@ -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 =>
|
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 =>
|
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(
|
16
|
-
:
|
17
|
-
:
|
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(
|
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
|
data/spec/unit/create_vm_spec.rb
CHANGED
@@ -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
|
-
|
3
|
+
require 'fog/kubevirt/compute/utils/unit_converter'
|
4
4
|
|
5
|
-
|
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.
|
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-
|
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
|