fog-kubevirt 0.2.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/lib/fog/compute/kubevirt.rb +24 -6
  3. data/lib/fog/compute/kubevirt/models/persistentvolume.rb +82 -0
  4. data/lib/fog/compute/kubevirt/models/persistentvolumes.rb +73 -0
  5. data/lib/fog/compute/kubevirt/models/storageclass.rb +33 -0
  6. data/lib/fog/compute/kubevirt/models/storageclasses.rb +61 -0
  7. data/lib/fog/compute/kubevirt/models/vm_base.rb +3 -2
  8. data/lib/fog/compute/kubevirt/models/vm_data.rb +11 -19
  9. data/lib/fog/compute/kubevirt/models/vminstance.rb +3 -2
  10. data/lib/fog/compute/kubevirt/models/vms.rb +49 -19
  11. data/lib/fog/compute/kubevirt/models/volume.rb +44 -69
  12. data/lib/fog/compute/kubevirt/models/volumes.rb +3 -58
  13. data/lib/fog/compute/kubevirt/requests/{create_volume.rb → create_persistentvolume.rb} +2 -2
  14. data/lib/fog/compute/kubevirt/requests/create_storageclass.rb +18 -0
  15. data/lib/fog/compute/kubevirt/requests/{delete_volume.rb → delete_persistentvolume.rb} +2 -2
  16. data/lib/fog/compute/kubevirt/requests/{get_volume.rb → delete_storageclass.rb} +3 -3
  17. data/lib/fog/compute/kubevirt/requests/delete_vm.rb +1 -1
  18. data/lib/fog/compute/kubevirt/requests/delete_vminstance.rb +3 -3
  19. data/lib/fog/compute/kubevirt/requests/get_persistentvolume.rb +16 -0
  20. data/lib/fog/compute/kubevirt/requests/get_storageclass.rb +16 -0
  21. data/lib/fog/compute/kubevirt/requests/list_persistentvolumes.rb +22 -0
  22. data/lib/fog/compute/kubevirt/requests/list_storageclasses.rb +22 -0
  23. data/lib/fog/compute/kubevirt/requests/list_volumes.rb +13 -5
  24. data/lib/fog/kubevirt/version.rb +1 -1
  25. data/spec/create_vm_spec.rb +101 -0
  26. data/spec/fixtures/kubevirt/{volume/volumes_crud.yml → persistentvolume/persistent_volumes_crud.yml} +0 -0
  27. data/spec/fixtures/kubevirt/pvc/pvcs_crud.yml +122 -76
  28. data/spec/fixtures/kubevirt/storageclass/storageclasses_crud.yml +400 -0
  29. data/spec/fixtures/kubevirt/vm/vm_create_multi.yml +459 -0
  30. data/spec/fixtures/kubevirt/vm/vm_create_single.yml +362 -0
  31. data/spec/{volumes_v1alpha2_spec.rb → persistent_volumes_v1alpha2_spec.rb} +11 -11
  32. data/spec/pvcs_v1alpha2_spec.rb +7 -0
  33. data/spec/storage_classes_v1_spec.rb +46 -0
  34. metadata +28 -9
@@ -28,6 +28,7 @@ module Fog
28
28
  status = object[:status]
29
29
  spec = object[:spec]
30
30
  domain = spec[:domain]
31
+ disks = parse_disks(domain[:devices][:disks])
31
32
  {
32
33
  :namespace => metadata[:namespace],
33
34
  :name => metadata[:name],
@@ -37,8 +38,8 @@ module Fog
37
38
  :owner_uid => metadata.dig(:ownerReferences, 0, :uid),
38
39
  :cpu_cores => domain.dig(:cpu, :cores),
39
40
  :memory => domain[:resources][:requests][:memory],
40
- :disks => parse_disks(domain[:devices][:disks]),
41
- :volumes => parse_volumes(spec[:volumes]),
41
+ :disks => disks,
42
+ :volumes => parse_volumes(spec[:volumes], disks),
42
43
  :interfaces => parse_interfaces(domain[:devices][:interfaces]),
43
44
  :networks => parse_networks(spec[:networks]),
44
45
  :ip_address => status.dig(:interfaces, 0, :ipAddress),
@@ -27,6 +27,10 @@ module Fog
27
27
  new service.get_vm(name)
28
28
  end
29
29
 
30
+ def delete(name)
31
+ service.delete_vm(name, service.namespace)
32
+ end
33
+
30
34
  # Creates a virtual machine using provided paramters:
31
35
  # :vm_name [String] - name of a vm
32
36
  # :cpus [String] - number of cpus
@@ -48,7 +52,9 @@ module Fog
48
52
  # :macAddress => '12:34:56:AB:CD:EF' }
49
53
  # ]
50
54
  #
51
- # One of :image or :pvc needs to be provided.
55
+ # @param [String] :image name of container disk.
56
+ #
57
+ # @param [Array] :volumes the volumes (Fog::Compute::Kubevirt::Volume) to be used by the VM
52
58
  #
53
59
  # @param [Hash] attributes containing details about vm about to be
54
60
  # created.
@@ -56,23 +62,16 @@ module Fog
56
62
  vm_name = args.fetch(:vm_name)
57
63
  cpus = args.fetch(:cpus, nil)
58
64
  memory_size = args.fetch(:memory_size)
59
- image = args.fetch(:image, nil)
60
- pvc = args.fetch(:pvc, nil)
61
65
  init = args.fetch(:cloudinit, {})
62
66
  networks = args.fetch(:networks, nil)
63
67
  interfaces = args.fetch(:interfaces, nil)
68
+ vm_volumes = args.fetch(:volumes, nil)
64
69
 
65
- if image.nil? && pvc.nil?
70
+ if vm_volumes.nil? || vm_volumes.empty?
66
71
  raise ::Fog::Kubevirt::Errors::ValidationError
67
72
  end
68
73
 
69
- volumes = []
70
- volume_name = vm_name.gsub(/[._]+/,'-') + "-disk-01"
71
- if !image.nil?
72
- volumes.push(:name => volume_name, :containerDisk => {:image => image})
73
- else
74
- volumes.push(:name => volume_name, :persistentVolumeClaim => {:claimName => pvc})
75
- end
74
+ volumes, disks = add_vm_storage(vm_name, vm_volumes)
76
75
 
77
76
  unless init.empty?
78
77
  volumes.push(:cloudInitNoCloud => init, :name => "cloudinitvolume")
@@ -99,13 +98,7 @@ module Fog
99
98
  :spec => {
100
99
  :domain => {
101
100
  :devices => {
102
- :disks => [
103
- {:disk => {
104
- :bus => "virtio"
105
- },
106
- :name => volume_name,
107
- }
108
- ]
101
+ :disks => disks
109
102
  },
110
103
  :machine => {
111
104
  :type => ""
@@ -167,9 +160,46 @@ module Fog
167
160
  }
168
161
  }
169
162
  ) unless interfaces.nil?
170
-
171
163
  service.create_vm(vm)
172
164
  end
165
+
166
+ def add_vm_storage(vm_name, vm_volumes)
167
+ normalized_vm_name = vm_name.gsub(/[._]+/,'-')
168
+ volumes, disks = [], []
169
+ vm_volumes.each_with_index do |v, idx|
170
+ volume_name = v.name || normalized_vm_name + "-disk-0" + idx.to_s
171
+ disk = {
172
+ :name => volume_name,
173
+ :disk => {}
174
+ }
175
+ disk[:bootOrder] = v.boot_order if v.boot_order
176
+
177
+ if v.type == 'containerDisk'
178
+ # set image
179
+ if v.config.nil?
180
+ volumes.push(:name => volume_name, :containerDisk => {:image => v.info})
181
+ else
182
+ volumes.push(:name => volume_name, v.type.to_sym => v.config)
183
+ end
184
+ disk[:disk][:bus] = v.bus || "virtio"
185
+ elsif v.type == 'persistentVolumeClaim'
186
+ # set claim
187
+ if v.config.nil?
188
+ volumes.push(:name => volume_name, :persistentVolumeClaim => {:claimName => v.info})
189
+ else
190
+ volumes.push(:name => volume_name, v.type.to_sym => v.config)
191
+ end
192
+ disk[:disk][:bus] = v.bus || "virtio"
193
+ else
194
+ # convert type into symbol and pass :config as volume content
195
+ volumes.push(:name => volume_name, v.type.to_sym => v.config)
196
+ disk[:disk][:bus] = v.bus if v.bus
197
+ end
198
+ disks.push(disk)
199
+ end
200
+
201
+ return volumes, disks
202
+ end
173
203
  end
174
204
  end
175
205
  end
@@ -1,80 +1,55 @@
1
+ require 'fog/compute/kubevirt/models/pvc'
2
+
1
3
  module Fog
2
4
  module Compute
3
5
  class Kubevirt
6
+ # Volumes represents volumes exist on kubevirt for vms:
7
+ # If volume is attached to a VM by disk, it will contain the attachment properties
8
+ # Disk Attachment properties are: boot_order and bus (when avaiable).
9
+ # If the volume isn't attached to any VM, it will contain name, type and info.
10
+ # When the volume type is persistentVolumeClaim, it will contain also the claim entity
11
+ # In order to create a new volume, user have to create a Claim when wishes to use PVC
12
+ # by using the pvcs collection.
4
13
  class Volume < Fog::Model
5
- identity :name
14
+ identity :name
6
15
 
7
- attribute :resource_version, :aliases => 'metadata_resource_version'
8
- attribute :uid, :aliases => 'metadata_uid'
9
- attribute :annotations, :aliases => 'metadata_annotations'
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'
15
- attribute :capacity, :aliases => 'spec_capacity'
16
- attribute :claim_ref, :aliases => 'spec_claim_ref'
17
- attribute :type, :aliases => 'spec_type'
18
- attribute :config, :aliases => 'spec_config'
19
- attribute :phase, :aliases => 'status_phase'
20
- attribute :reason, :aliases => 'status_reason'
21
- attribute :message, :aliases => 'status_message'
16
+ # values: containerDisk, persistentVolumeClaim, emptyDisk,
17
+ # ephemeral, cloudInitNoCloud, hostDisk, secret,
18
+ # dataVolume, serviceAccount, configMap
19
+ attribute :type
22
20
 
23
- def self.parse(object)
24
- metadata = object[:metadata]
25
- spec = object[:spec]
26
- status = object[:status]
27
- type = detect_type(spec)
21
+ # specific piece of information per volume type
22
+ # for containerDisk - contains the image
23
+ # for persistentVolumeClaim - contains the claim name
24
+ attribute :info
28
25
 
29
- {
30
- :name => metadata[:name],
31
- :resource_version => metadata[:resourceVersion],
32
- :uid => metadata[:uid],
33
- :annotations => metadata[:annotations],
34
- :labels => metadata[:labels],
35
- :access_modes => spec[:accessModes],
36
- :mount_options => spec[:mountOptions],
37
- :reclaim_policy => spec[:persistentVolumeReclaimPolicy],
38
- :storage_class => spec[:storageClassName],
39
- :capacity => spec.dig(:capacity, :storage),
40
- :claim_ref => spec[:claimRef],
41
- :type => type,
42
- :config => spec[type&.to_sym],
43
- :phase => status[:phase],
44
- :reason => status[:reason],
45
- :message => status[:message]
46
- }
47
- end
26
+ # holds the pvc entity if its type is persistentVolumeClaim
27
+ attribute :pvc
28
+
29
+ # Hash that holds volume type specific configurations, used for adding volume for a vm
30
+ # The set of config properties may change from type to type, see documentation for the supported
31
+ # keys of each volume type:
32
+ # https://kubevirt.io/user-guide/docs/latest/creating-virtual-machines/disks-and-volumes.html#volumes
33
+ attribute :config
34
+
35
+ # Disk attachment properties, relevant when volumes are fetched via the vm:
36
+
37
+ # the order (integer) of the device during boot sequence
38
+ attribute :boot_order
39
+
40
+ # detemines how the disk will be presented to the guest OS if available, supported values are:
41
+ # virtio, sata or scsi. See https://kubevirt.io/api-reference/master/definitions.html#_v1_disktarget
42
+ attribute :bus
43
+
44
+ def persisted?
45
+ !name.nil?
46
+ end
48
47
 
49
- def self.detect_type(spec)
50
- type = ''
51
- type = 'awsElasticBlockStore' if spec.keys.include?(:awsElasticBlockStore)
52
- type = 'azureDisk' if spec.keys.include?(:azureDisk)
53
- type = 'azureFile' if spec.keys.include?(:azureFile)
54
- type = 'cephfs' if spec.keys.include?(:cephfs)
55
- type = 'configMap' if spec.keys.include?(:configMap)
56
- type = 'csi' if spec.keys.include?(:csi)
57
- type = 'downwardAPI' if spec.keys.include?(:downwardAPI)
58
- type = 'emptyDir' if spec.keys.include?(:emptyDir)
59
- type = 'fc' if spec.keys.include?(:fc)
60
- type = 'flexVolume' if spec.keys.include?(:flexVolume)
61
- type = 'flocker' if spec.keys.include?(:flocker)
62
- type = 'gcePersistentDisk' if spec.keys.include?(:gcePersistentDisk)
63
- type = 'glusterfs' if spec.keys.include?(:glusterfs)
64
- type = 'hostPath' if spec.keys.include?(:hostPath)
65
- type = 'iscsi' if spec.keys.include?(:iscsi)
66
- type = 'local' if spec.keys.include?(:local)
67
- type = 'nfs' if spec.keys.include?(:nfs)
68
- type = 'persistentVolumeClaim' if spec.keys.include?(:persistentVolumeClaim)
69
- type = 'projected' if spec.keys.include?(:projected)
70
- type = 'portworxVolume' if spec.keys.include?(:portworxVolume)
71
- type = 'quobyte' if spec.keys.include?(:quobyte)
72
- type = 'rbd' if spec.keys.include?(:rbd)
73
- type = 'scaleIO' if spec.keys.include?(:scaleIO)
74
- type = 'secret' if spec.keys.include?(:secret)
75
- type = 'storageos' if spec.keys.include?(:storageos)
76
- type = 'vsphereVolume' if spec.keys.include?(:vsphereVolume)
77
- type
48
+ def self.parse(object, disk)
49
+ byebug
50
+ volume = parse_object(object)
51
+ volume[:boot_order] = object[:bootOrder]
52
+ volume
78
53
  end
79
54
  end
80
55
  end
@@ -5,67 +5,12 @@ module Fog
5
5
  module Compute
6
6
  class Kubevirt
7
7
  class Volumes < Fog::Collection
8
- attr_reader :kind, :resource_version
9
-
10
8
  model Fog::Compute::Kubevirt::Volume
11
9
 
12
- def all(filters = {})
13
- volumes = service.list_volumes(filters)
14
- @kind = volumes.kind
15
- @resource_version = volumes.resource_version
16
- load volumes
17
- end
18
-
19
- def get(name)
20
- new service.get_volume(name)
21
- end
22
-
23
- # Creates a volume using provided paramters:
24
- # :name [String] - name of a volume
25
- # :labels [Hash] - a hash of key,values representing the labels
26
- # :storage_class [String] - the storage class name of the volume
27
- # :capacity [String] - The capacity of the storage if applied
28
- # :accessModes [Arr] - the access modes for the volume, values are specified here:
29
- # https://kubernetes.io/docs/concepts/storage/persistent-volumes/#access-modes
30
- # :type [String] - the type of the storage
31
- # :config [Hash] - storage specific configuration to be applied for the volume
32
- # correlated to the args[:type]
33
- # @param [Hash] attributes containing details about volume to be created.
34
- def create(args = {})
35
- name = args[:name]
36
- labels = args[:labels]
37
-
38
- volume = {
39
- :apiVersion => "v1",
40
- :kind => "PersistentVolume",
41
- :metadata => {
42
- :name => name
43
- },
44
- :spec => {
45
- :storageClassName => args[:storage_class]
46
- }
47
- }
48
-
49
- volume[:metadata][:labels] = labels if labels
50
- volume[:spec][:capacity] = {
51
- :storage => args[:capacity]
52
- } if args[:capacity]
53
-
54
- volume[:spec][:accessModes] = args[:access_modes] if args[:access_modes]
55
- volume[:spec][args[:type].to_sym] = args[:config] if args[:type]
56
-
57
- service.create_volume(volume)
58
- end
59
-
60
- def delete(name)
61
- begin
62
- volume = get(name)
63
- rescue ::Fog::Kubevirt::Errors::ClientError
64
- # the volume doesn't exist
65
- volume = nil
66
- end
10
+ attr_accessor :vm
67
11
 
68
- service.delete_volume(name) unless volume.nil?
12
+ def all(vm_name = nil)
13
+ service.list_volumes(vm_name)
69
14
  end
70
15
  end
71
16
  end
@@ -2,7 +2,7 @@ module Fog
2
2
  module Compute
3
3
  class Kubevirt
4
4
  class Real
5
- def create_volume(volume)
5
+ def create_persistentvolume(volume)
6
6
  kube_client.create_persistent_volume(volume)
7
7
  rescue ::Fog::Kubevirt::Errors::ClientError => err
8
8
  log.warn(err)
@@ -11,7 +11,7 @@ module Fog
11
11
  end
12
12
 
13
13
  class Mock
14
- def create_volume(volume)
14
+ def create_persistentvolume(volume)
15
15
  end
16
16
  end
17
17
  end
@@ -0,0 +1,18 @@
1
+ module Fog
2
+ module Compute
3
+ class Kubevirt
4
+ class Real
5
+ def create_storageclass(storageclass)
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
+ end
11
+ end
12
+
13
+ class Mock
14
+ def create_storage_class(attrs); end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -2,13 +2,13 @@ module Fog
2
2
  module Compute
3
3
  class Kubevirt
4
4
  class Real
5
- def delete_volume(name)
5
+ def delete_persistentvolume(name)
6
6
  kube_client.delete_persistent_volume(name)
7
7
  end
8
8
  end
9
9
 
10
10
  class Mock
11
- def delete_volume(name)
11
+ def delete_persistentvolume(name)
12
12
  end
13
13
  end
14
14
  end
@@ -2,13 +2,13 @@ module Fog
2
2
  module Compute
3
3
  class Kubevirt
4
4
  class Real
5
- def get_volume(name)
6
- Volume.parse object_to_hash(kube_client.get_persistent_volume(name))
5
+ def delete_storageclass(name)
6
+ kube_storage_client.delete_storage_class(name)
7
7
  end
8
8
  end
9
9
 
10
10
  class Mock
11
- def get_volume(name)
11
+ def delete_storage_class(name)
12
12
  end
13
13
  end
14
14
  end
@@ -8,7 +8,7 @@ module Fog
8
8
  end
9
9
 
10
10
  class Mock
11
- def delete_vm(name)
11
+ def delete_vm(name, namespace)
12
12
  end
13
13
  end
14
14
  end
@@ -2,13 +2,13 @@ module Fog
2
2
  module Compute
3
3
  class Kubevirt
4
4
  class Real
5
- def delete_vminstance(name, namespace)
6
- kubevirt_client.delete_virtual_machine_instance(name, namespace)
5
+ def delete_vminstance(name)
6
+ kubevirt_client.delete_virtual_machine_instance(name, @namespace)
7
7
  end
8
8
  end
9
9
 
10
10
  class Mock
11
- def delete_virtual_machine_instance(name, namespace = nil)
11
+ def delete_virtual_machine_instance(name)
12
12
  end
13
13
  end
14
14
  end
@@ -0,0 +1,16 @@
1
+ module Fog
2
+ module Compute
3
+ class Kubevirt
4
+ class Real
5
+ def get_persistentvolume(name)
6
+ Persistentvolume.parse object_to_hash(kube_client.get_persistent_volume(name))
7
+ end
8
+ end
9
+
10
+ class Mock
11
+ def get_persistentvolume(name)
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ module Fog
2
+ module Compute
3
+ class Kubevirt
4
+ class Real
5
+ def get_storageclass(name)
6
+ Storageclass.parse object_to_hash(kube_storage_client.get_storage_class(name))
7
+ end
8
+ end
9
+
10
+ class Mock
11
+ def get_storage_class(name)
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end