fog-kubevirt 1.0.2 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/lib/fog/kubevirt/compute/compute.rb +28 -6
  3. data/lib/fog/kubevirt/compute/models/persistentvolume.rb +82 -0
  4. data/lib/fog/kubevirt/compute/models/persistentvolumes.rb +73 -0
  5. data/lib/fog/kubevirt/compute/models/storageclass.rb +33 -0
  6. data/lib/fog/kubevirt/compute/models/storageclasses.rb +61 -0
  7. data/lib/fog/kubevirt/compute/models/vm_base.rb +13 -2
  8. data/lib/fog/kubevirt/compute/models/vm_data.rb +11 -13
  9. data/lib/fog/kubevirt/compute/models/vminstance.rb +11 -2
  10. data/lib/fog/kubevirt/compute/models/vms.rb +48 -19
  11. data/lib/fog/kubevirt/compute/models/volume.rb +44 -69
  12. data/lib/fog/kubevirt/compute/models/volumes.rb +3 -58
  13. data/lib/fog/kubevirt/compute/requests/{create_volume.rb → create_persistentvolume.rb} +2 -2
  14. data/lib/fog/kubevirt/compute/requests/create_storageclass.rb +18 -0
  15. data/lib/fog/kubevirt/compute/requests/{delete_volume.rb → delete_persistentvolume.rb} +2 -2
  16. data/lib/fog/kubevirt/compute/requests/{get_volume.rb → delete_storageclass.rb} +3 -3
  17. data/lib/fog/kubevirt/compute/requests/delete_vm.rb +1 -1
  18. data/lib/fog/kubevirt/compute/requests/delete_vminstance.rb +3 -3
  19. data/lib/fog/kubevirt/compute/requests/get_persistentvolume.rb +16 -0
  20. data/lib/fog/kubevirt/compute/requests/get_storageclass.rb +16 -0
  21. data/lib/fog/kubevirt/compute/requests/list_persistentvolumes.rb +22 -0
  22. data/lib/fog/kubevirt/compute/requests/list_storageclasses.rb +22 -0
  23. data/lib/fog/kubevirt/compute/requests/list_volumes.rb +14 -6
  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
@@ -1,7 +1,11 @@
1
+ require 'fog/kubevirt/compute/models/vm_data'
2
+
1
3
  module Fog
2
4
  module Kubevirt
3
5
  class Compute
4
6
  class Vminstance < Fog::Model
7
+ extend VmData
8
+
5
9
  identity :name
6
10
 
7
11
  attribute :namespace, :aliases => 'metadata_namespace'
@@ -14,6 +18,8 @@ module Fog
14
18
  attribute :disks, :aliases => 'spec_disks'
15
19
  attribute :volumes, :aliases => 'spec_volumes'
16
20
  attribute :ip_address, :aliases => 'status_interfaces_ip'
21
+ attribute :interfaces, :aliases => 'spec_interfaces'
22
+ attribute :networks, :aliases => 'spec_networks'
17
23
  attribute :node_name, :aliases => 'status_node_name'
18
24
  attribute :status, :aliases => 'status_phase'
19
25
 
@@ -22,6 +28,7 @@ module Fog
22
28
  status = object[:status]
23
29
  spec = object[:spec]
24
30
  domain = spec[:domain]
31
+ disks = parse_disks(domain[:devices][:disks])
25
32
  {
26
33
  :namespace => metadata[:namespace],
27
34
  :name => metadata[:name],
@@ -31,8 +38,10 @@ module Fog
31
38
  :owner_uid => metadata.dig(:ownerReferences, 0, :uid),
32
39
  :cpu_cores => domain.dig(:cpu, :cores),
33
40
  :memory => domain[:resources][:requests][:memory],
34
- :disks => domain[:devices][:disks],
35
- :volumes => spec[:volumes],
41
+ :disks => disks,
42
+ :volumes => parse_volumes(spec[:volumes], disks),
43
+ :interfaces => parse_interfaces(domain[:devices][:interfaces]),
44
+ :networks => parse_networks(spec[:networks]),
36
45
  :ip_address => status.dig(:interfaces, 0, :ipAddress),
37
46
  :node_name => status[:nodeName],
38
47
  :status => status[:phase]
@@ -27,6 +27,9 @@ 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
30
33
 
31
34
  # Creates a virtual machine using provided paramters:
32
35
  # :vm_name [String] - name of a vm
@@ -49,7 +52,9 @@ module Fog
49
52
  # :macAddress => '12:34:56:AB:CD:EF' }
50
53
  # ]
51
54
  #
52
- # 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::Kubevirt::Compute::Volume) to be used by the VM
53
58
  #
54
59
  # @param [Hash] attributes containing details about vm about to be
55
60
  # created.
@@ -57,23 +62,16 @@ module Fog
57
62
  vm_name = args.fetch(:vm_name)
58
63
  cpus = args.fetch(:cpus, nil)
59
64
  memory_size = args.fetch(:memory_size)
60
- image = args.fetch(:image, nil)
61
- pvc = args.fetch(:pvc, nil)
62
65
  init = args.fetch(:cloudinit, {})
63
66
  networks = args.fetch(:networks, nil)
64
67
  interfaces = args.fetch(:interfaces, nil)
68
+ vm_volumes = args.fetch(:volumes, nil)
65
69
 
66
- if image.nil? && pvc.nil?
70
+ if vm_volumes.nil? || vm_volumes.empty?
67
71
  raise ::Fog::Kubevirt::Errors::ValidationError
68
72
  end
69
73
 
70
- volumes = []
71
- volume_name = vm_name.gsub(/[._]+/,'-') + "-disk-01"
72
- if !image.nil?
73
- volumes.push(:name => volume_name, :containerDisk => {:image => image})
74
- else
75
- volumes.push(:name => volume_name, :persistentVolumeClaim => {:claimName => pvc})
76
- end
74
+ volumes, disks = add_vm_storage(vm_name, vm_volumes)
77
75
 
78
76
  unless init.empty?
79
77
  volumes.push(:cloudInitNoCloud => init, :name => "cloudinitvolume")
@@ -100,13 +98,7 @@ module Fog
100
98
  :spec => {
101
99
  :domain => {
102
100
  :devices => {
103
- :disks => [
104
- {:disk => {
105
- :bus => "virtio"
106
- },
107
- :name => volume_name,
108
- }
109
- ]
101
+ :disks => disks
110
102
  },
111
103
  :machine => {
112
104
  :type => ""
@@ -168,9 +160,46 @@ module Fog
168
160
  }
169
161
  }
170
162
  ) unless interfaces.nil?
171
-
172
163
  service.create_vm(vm)
173
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
174
203
  end
175
204
  end
176
205
  end
@@ -1,80 +1,55 @@
1
+ require 'fog/kubevirt/compute/models/pvc'
2
+
1
3
  module Fog
2
4
  module Kubevirt
3
5
  class Compute
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 Kubevirt
6
6
  class Compute
7
7
  class Volumes < Fog::Collection
8
- attr_reader :kind, :resource_version
9
-
10
8
  model Fog::Kubevirt::Compute::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 Kubevirt
3
3
  class Compute
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 Kubevirt
3
+ class Compute
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 Kubevirt
3
3
  class Compute
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 Kubevirt
3
3
  class Compute
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 Kubevirt
3
3
  class Compute
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