fog-kubevirt 0.1.8 → 0.2.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 (37) hide show
  1. checksums.yaml +4 -4
  2. data/lib/fog/compute/kubevirt.rb +64 -20
  3. data/lib/fog/compute/kubevirt/models/networkattachmentdef.rb +25 -0
  4. data/lib/fog/compute/kubevirt/models/networkattachmentdefs.rb +59 -0
  5. data/lib/fog/compute/kubevirt/models/pvc.rb +59 -0
  6. data/lib/fog/compute/kubevirt/models/pvcs.rb +76 -0
  7. data/lib/fog/compute/kubevirt/models/server.rb +3 -1
  8. data/lib/fog/compute/kubevirt/models/vm_data.rb +5 -4
  9. data/lib/fog/compute/kubevirt/models/vms.rb +44 -7
  10. data/lib/fog/compute/kubevirt/models/volume.rb +73 -0
  11. data/lib/fog/compute/kubevirt/models/volumes.rb +61 -0
  12. data/lib/fog/compute/kubevirt/requests/create_networkattachmentdef.rb +37 -0
  13. data/lib/fog/compute/kubevirt/requests/create_vm.rb +1 -0
  14. data/lib/fog/compute/kubevirt/requests/create_volume.rb +19 -0
  15. data/lib/fog/compute/kubevirt/requests/delete_networkattachmentdef.rb +16 -0
  16. data/lib/fog/compute/kubevirt/requests/delete_pvc.rb +16 -0
  17. data/lib/fog/compute/kubevirt/requests/delete_volume.rb +16 -0
  18. data/lib/fog/compute/kubevirt/requests/get_networkattachmentdef.rb +19 -0
  19. data/lib/fog/compute/kubevirt/requests/get_pvc.rb +16 -0
  20. data/lib/fog/compute/kubevirt/requests/get_vminstance.rb +4 -4
  21. data/lib/fog/compute/kubevirt/requests/get_volume.rb +16 -0
  22. data/lib/fog/compute/kubevirt/requests/list_networkattachmentdefs.rb +21 -0
  23. data/lib/fog/compute/kubevirt/requests/list_pvcs.rb +22 -0
  24. data/lib/fog/compute/kubevirt/requests/list_vms.rb +4 -4
  25. data/lib/fog/compute/kubevirt/requests/list_volumes.rb +22 -0
  26. data/lib/fog/kubevirt/version.rb +1 -1
  27. data/spec/compute_v1alpha2_spec.rb +1 -1
  28. data/spec/fixtures/kubevirt/networkattachmentdefinition/networkattachmentdefinitions_crud.yml +320 -0
  29. data/spec/fixtures/kubevirt/pvc/pvcs_crud.yml +316 -0
  30. data/spec/fixtures/kubevirt/service/services_crud.yml +316 -0
  31. data/spec/fixtures/kubevirt/volume/volumes_crud.yml +316 -0
  32. data/spec/network_attachment_definition_v1alpha2_spec.rb +28 -0
  33. data/spec/pvcs_v1alpha2_spec.rb +52 -0
  34. data/spec/shared_context.rb +2 -2
  35. data/spec/volumes_v1alpha2_spec.rb +45 -0
  36. metadata +33 -20
  37. data/spec/fixtures/kubevirt/service/v1alpha2/services_crud.yml +0 -172
@@ -31,9 +31,22 @@ module Fog
31
31
  # :vm_name [String] - name of a vm
32
32
  # :cpus [String] - number of cpus
33
33
  # :memory_size [String] - amount of memory
34
- # :image [String] - name of a registry disk
34
+ # :image [String] - name of a container disk
35
35
  # :pvc [String] - name of a persistent volume claim
36
36
  # :cloudinit [Hash] - number of items needed to configure cloud-init
37
+ # :networks[Array] - networks to which the vm should be connected, i.e:
38
+ # [ { :name => 'default', :pod => {} } ,
39
+ # { :name => 'ovs-red', :multus => { :networkName => 'red'} }
40
+ # ]
41
+ #
42
+ # :interfaces[Array] - network interfaces for the vm, correlated to
43
+ # :networks section by network's name, i.e.:
44
+ # [ { :name => 'default', :bridge => {} },
45
+ # { :name => 'red', # correlated to networks[networkName]
46
+ # :bridge => {},
47
+ # :bootOrder => 1, # 1 to boot from network interface
48
+ # :macAddress => '12:34:56:AB:CD:EF' }
49
+ # ]
37
50
  #
38
51
  # One of :image or :pvc needs to be provided.
39
52
  #
@@ -46,17 +59,19 @@ module Fog
46
59
  image = args.fetch(:image, nil)
47
60
  pvc = args.fetch(:pvc, nil)
48
61
  init = args.fetch(:cloudinit, {})
62
+ networks = args.fetch(:networks)
63
+ interfaces = args.fetch(:interfaces)
49
64
 
50
65
  if image.nil? && pvc.nil?
51
66
  raise ::Fog::Kubevirt::Errors::ValidationError
52
67
  end
53
-
54
- volumes = []
55
68
 
69
+ volumes = []
70
+ volume_name = vm_name.gsub(/[._]+/,'-') + "-disk-01"
56
71
  if !image.nil?
57
- volumes.push(:name => vm_name, :registryDisk => {:image => image})
72
+ volumes.push(:name => volume_name, :containerDisk => {:image => image})
58
73
  else
59
- volumes.push(:name => vm_name, :persistentVolumeClaim => {:claimName => pvc})
74
+ volumes.push(:name => volume_name, :persistentVolumeClaim => {:claimName => pvc})
60
75
  end
61
76
 
62
77
  unless init.empty?
@@ -64,7 +79,6 @@ module Fog
64
79
  end
65
80
 
66
81
  vm = {
67
- :apiVersion => service.class::KUBEVIRT_VERSION_LABEL,
68
82
  :kind => "VirtualMachine",
69
83
  :metadata => {
70
84
  :labels => {
@@ -90,7 +104,6 @@ module Fog
90
104
  :bus => "virtio"
91
105
  },
92
106
  :name => vm_name,
93
- :volumeName => vm_name
94
107
  }
95
108
  ]
96
109
  },
@@ -132,6 +145,30 @@ module Fog
132
145
  :volumeName => "cloudinitvolume"
133
146
  ) unless init.empty?
134
147
 
148
+ vm = deep_merge!(vm,
149
+ :spec => {
150
+ :template => {
151
+ :spec => {
152
+ :networks => networks
153
+ }
154
+ }
155
+ }
156
+ ) unless networks.nil?
157
+
158
+ vm = deep_merge!(vm,
159
+ :spec => {
160
+ :template => {
161
+ :spec => {
162
+ :domain => {
163
+ :devices => {
164
+ :interfaces => interfaces
165
+ }
166
+ }
167
+ }
168
+ }
169
+ }
170
+ ) unless interfaces.nil?
171
+
135
172
  service.create_vm(vm)
136
173
  end
137
174
  end
@@ -2,7 +2,80 @@ module Fog
2
2
  module Compute
3
3
  class Kubevirt
4
4
  class Volume < Fog::Model
5
+ identity :name
5
6
 
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'
22
+
23
+ def self.parse(object)
24
+ metadata = object[:metadata]
25
+ spec = object[:spec]
26
+ status = object[:status]
27
+ type = detect_type(spec)
28
+
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
48
+
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
78
+ end
6
79
  end
7
80
  end
8
81
  end
@@ -5,7 +5,68 @@ module Fog
5
5
  module Compute
6
6
  class Kubevirt
7
7
  class Volumes < Fog::Collection
8
+ attr_reader :kind, :resource_version
9
+
8
10
  model Fog::Compute::Kubevirt::Volume
11
+
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
67
+
68
+ service.delete_volume(name) unless volume.nil?
69
+ end
9
70
  end
10
71
  end
11
72
  end
@@ -0,0 +1,37 @@
1
+ module Fog
2
+ module Compute
3
+ class Kubevirt
4
+ class Real
5
+ include Shared
6
+
7
+ # creates netwrork attachment definition object
8
+ # @param net_att[Hash] contains the following elements:
9
+ # metadata[Hash]: the net-attachment-def metadata:
10
+ # name[String]: the netwrork attachment definition definition
11
+ # spec[Hash]: the specification of the attachment, contains:config
12
+ # config[string]: the configuration of the attachment, i.e.
13
+ # '{ :cniVersion => "0.3.1", :type => "ovs", :bridge => "red" }'
14
+ # Example of net_att:
15
+ # metadata: {
16
+ # name: "ovs-red"},
17
+ # spec: {
18
+ # config: '{ cni_version: "0.3.1", type: "ovs", bridge: "red" }'
19
+ # }
20
+ def create_networkattachmentdef(net_att)
21
+ if net_att.dig(:metadata, :namespace).nil?
22
+ net_att = deep_merge!(net_att, metadata: { namespace: @namespace })
23
+ end
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
+ end
29
+ end
30
+
31
+ class Mock
32
+ def create_networkattachmentdef(_net_att_def)
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -3,6 +3,7 @@ module Fog
3
3
  class Kubevirt
4
4
  class Real
5
5
  def create_vm(vm)
6
+ vm[:apiVersion] = kubevirt_client.version
6
7
  kubevirt_client.create_virtual_machine(vm)
7
8
  rescue ::Fog::Kubevirt::Errors::ClientError => err
8
9
  log.warn(err)
@@ -0,0 +1,19 @@
1
+ module Fog
2
+ module Compute
3
+ class Kubevirt
4
+ class Real
5
+ def create_volume(volume)
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
+ end
11
+ end
12
+
13
+ class Mock
14
+ def create_volume(volume)
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,16 @@
1
+ module Fog
2
+ module Compute
3
+ class Kubevirt
4
+ class Real
5
+ def delete_networkattachmentdef(name, namespace)
6
+ kube_net_client.delete_network_attachment_definition(name, namespace)
7
+ end
8
+ end
9
+
10
+ class Mock
11
+ def delete_networkattachmentdef(_name, _namespace)
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 delete_pvc(name)
6
+ kube_client.delete_persistent_volume_claim(name, namespace)
7
+ end
8
+ end
9
+
10
+ class Mock
11
+ def delete_pvc(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 delete_volume(name)
6
+ kube_client.delete_persistent_volume(name)
7
+ end
8
+ end
9
+
10
+ class Mock
11
+ def delete_volume(name)
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,19 @@
1
+ require 'recursive_open_struct'
2
+
3
+ module Fog
4
+ module Compute
5
+ class Kubevirt
6
+ class Real
7
+ def get_networkattachmentdef(name)
8
+ net_attach_def = kube_net_client.get_network_attachment_definition(name, @namespace)
9
+ Networkattachmentdef.parse object_to_hash(net_attach_def)
10
+ end
11
+ end
12
+
13
+ class Mock
14
+ def get_networkattachmentdef(name)
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,16 @@
1
+ module Fog
2
+ module Compute
3
+ class Kubevirt
4
+ class Real
5
+ def get_pvc(name)
6
+ Pvc.parse object_to_hash(kube_client.get_persistent_volume_claim(name, @namespace))
7
+ end
8
+ end
9
+
10
+ class Mock
11
+ def get_pvc(name)
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -30,8 +30,8 @@ module Fog
30
30
  },
31
31
  :spec => { :domain => { :cpu => { :cores => "4" },
32
32
  :devices => { :disks => [{ :disk => { :dev => "vda" },
33
- :name => "registrydisk",
34
- :volumeName => "registryvolume"
33
+ :name => "containerDisk",
34
+ :volumeName => "containervolume"
35
35
  },
36
36
  { :disk => { :dev => "vdb" },
37
37
  :name => "cloudinitdisk",
@@ -42,8 +42,8 @@ module Fog
42
42
  :machine => { :type => "q35" },
43
43
  :resources => { :requests => { :memory => "512Mi" }}
44
44
  },
45
- :volumes => [ { :name => "registryvolume",
46
- :registryDisk => { :image => "kubevirt/fedora-cloud-registry-disk-demo:latest" }
45
+ :volumes => [ { :name => "containervolume",
46
+ :containerDisk => { :image => "kubevirt/fedora-cloud-registry-disk-demo:latest" }
47
47
  },
48
48
  { :cloudInitNoCloud => { :userDataBase64 => "I2Nsb3VkLWNvbmZpZwpwYXNzd29yZDogYXRvbWljCnNzaF9wd2F1dGg6IFRydWUKY2hwYXNzd2Q6IHsgZXhwaXJlOiBGYWxzZSB9Cg==" },
49
49
  :name => "cloudinitvolume"
@@ -0,0 +1,16 @@
1
+ module Fog
2
+ module Compute
3
+ class Kubevirt
4
+ class Real
5
+ def get_volume(name)
6
+ Volume.parse object_to_hash(kube_client.get_persistent_volume(name))
7
+ end
8
+ end
9
+
10
+ class Mock
11
+ def get_volume(name)
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,21 @@
1
+ module Fog
2
+ module Compute
3
+ class Kubevirt
4
+ class Real
5
+ def list_networkattachmentdefs(_filters = {})
6
+ netdefs = kube_net_client.get_network_attachment_definitions
7
+ entities = netdefs.map do |kubevirt_obj|
8
+ Networkattachmentdef.parse object_to_hash(kubevirt_obj)
9
+ end
10
+ EntityCollection.new(netdefs.kind, netdefs.resourceVersion, entities)
11
+ end
12
+ end
13
+
14
+ class Mock
15
+ # TODO provide implementation
16
+ def list_networkattachmentdefs(_filters = {})
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end