fog-kubevirt 0.1.8 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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