Class: ForemanKubevirt::Kubevirt
- Inherits:
-
ComputeResource
- Object
- ComputeResource
- ForemanKubevirt::Kubevirt
- Defined in:
- app/models/foreman_kubevirt/kubevirt.rb
Class Method Summary collapse
Instance Method Summary collapse
- #api_port ⇒ Object
- #api_port=(key) ⇒ Object
- #associated_host(vm) ⇒ Object
- #available_images ⇒ Object
- #ca_cert ⇒ Object
- #ca_cert=(key) ⇒ Object
- #caching_enabled ⇒ Object
- #capabilities ⇒ Object
- #cni_providers ⇒ Object
- #connection_properties_valid? ⇒ Boolean
- #console(uuid) ⇒ Object
-
#convert_memory_to_bytes(memory) ⇒ Object
Converts a given memory to bytes.
-
#create_vm(args = {}) ⇒ Object
volumes_attributes - the attributes for the persistent volume claims: { “1554394214729” => { “storage_class” => “local-storage”, “name” => “alvin-hinojosa1”, “capacity” => “3”, “bootable”=>“true” }, “1554394230987” => { “storage_class” => “local-storage”, “name” => “alvin-hinojosa”, “capacity”=>“2” } }.
- #destroy_vm(vm_uuid) ⇒ Object
- #find_vm_by_uuid(uuid) ⇒ Object
- #host_compute_attrs(host) ⇒ Object
-
#host_interfaces_attrs(host) ⇒ Object
Overrding base class implementation since ‘mac’ is required for the created interface.
-
#max_cpu_count ⇒ Object
TODO: max supported values should be fetched according to namespace capabilities: kubectl get limits namespace_name.
- #max_memory ⇒ Object
- #max_socket_count ⇒ Object
- #networks ⇒ Object
- #new_interface(attr = {}) ⇒ Object
- #new_vm(attr = {}) ⇒ Object
- #new_volume(attrs = {}) ⇒ Object
- #new_volume_errors ⇒ Object
- #plain_kubevirt_protocol ⇒ Object
- #provided_attributes ⇒ Object
-
#set_vm_volumes_attributes(vm, vm_attrs) ⇒ Object
Overrding base class implementation since ‘pvc’ is required.
- #storage_classes ⇒ Object
- #storage_classes_for_select ⇒ Object
- #test_connection(options = {}) ⇒ Object
- #to_label ⇒ Object
- #token_protocol(token) ⇒ Object
- #user_data_supported? ⇒ Boolean
- #validate_connectivity(options = {}) ⇒ Object
- #vm_compute_attributes(vm) ⇒ Object
-
#vm_instance_defaults ⇒ Object
Since ‘name’ is the identity/UUID of server/vm, we need to override default values that assign also value for ‘name’ so vm_exists? will return ‘false’.
- #volumes ⇒ Object
Class Method Details
.model_name ⇒ Object
51 52 53 |
# File 'app/models/foreman_kubevirt/kubevirt.rb', line 51 def self.model_name ComputeResource.model_name end |
.provider_friendly_name ⇒ Object
43 44 45 |
# File 'app/models/foreman_kubevirt/kubevirt.rb', line 43 def self.provider_friendly_name 'KubeVirt' end |
Instance Method Details
#api_port ⇒ Object
19 20 21 |
# File 'app/models/foreman_kubevirt/kubevirt.rb', line 19 def api_port attrs[:api_port] end |
#api_port=(key) ⇒ Object
23 24 25 |
# File 'app/models/foreman_kubevirt/kubevirt.rb', line 23 def api_port=(key) attrs[:api_port] = key end |
#associated_host(vm) ⇒ Object
268 269 270 |
# File 'app/models/foreman_kubevirt/kubevirt.rb', line 268 def associated_host(vm) associate_by("mac", vm.mac) end |
#available_images ⇒ Object
39 40 41 |
# File 'app/models/foreman_kubevirt/kubevirt.rb', line 39 def available_images [] end |
#ca_cert ⇒ Object
11 12 13 |
# File 'app/models/foreman_kubevirt/kubevirt.rb', line 11 def ca_cert attrs[:ca_cert] end |
#ca_cert=(key) ⇒ Object
15 16 17 |
# File 'app/models/foreman_kubevirt/kubevirt.rb', line 15 def ca_cert=(key) attrs[:ca_cert] = key end |
#caching_enabled ⇒ Object
60 61 62 |
# File 'app/models/foreman_kubevirt/kubevirt.rb', line 60 def caching_enabled false end |
#capabilities ⇒ Object
27 28 29 |
# File 'app/models/foreman_kubevirt/kubevirt.rb', line 27 def capabilities %i[build image new_volume] end |
#cni_providers ⇒ Object
122 123 124 |
# File 'app/models/foreman_kubevirt/kubevirt.rb', line 122 def cni_providers [[_("multus"), :multus], [_("genie"), :genie], [_("pod"), :pod]] end |
#connection_properties_valid? ⇒ Boolean
76 77 78 |
# File 'app/models/foreman_kubevirt/kubevirt.rb', line 76 def connection_properties_valid? errors[:hostname].empty? && errors[:token].empty? && errors[:namespace].empty? && errors[:api_port].empty? end |
#console(uuid) ⇒ Object
302 303 304 305 306 307 308 309 310 311 312 313 314 315 |
# File 'app/models/foreman_kubevirt/kubevirt.rb', line 302 def console(uuid) vm = find_vm_by_uuid(uuid) vnc_details = client.vminstances.get_vnc_console_details(vm.name, namespace) token = Base64.encode64(vnc_details[:token]).delete!("\n").delete("==") { :host => vnc_details[:host], :port => vnc_details[:port], :path => vnc_details[:path], :token_protocol => token_protocol(token), :plain_protocol => plain_kubevirt_protocol, :type => 'vnc', :encrypt => true } end |
#convert_memory_to_bytes(memory) ⇒ Object
Converts a given memory to bytes
290 291 292 |
# File 'app/models/foreman_kubevirt/kubevirt.rb', line 290 def convert_memory_to_bytes(memory) convert_memory(memory, :b) end |
#create_vm(args = {}) ⇒ Object
volumes_attributes - the attributes for the persistent volume claims:
{
"1554394214729" => {
"storage_class" => "local-storage",
"name" => "alvin-hinojosa1",
"capacity" => "3",
"bootable"=>"true"
},
"1554394230987" => {
"storage_class" => "local-storage",
"name" => "alvin-hinojosa",
"capacity"=>"2"
}
}
158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 |
# File 'app/models/foreman_kubevirt/kubevirt.rb', line 158 def create_vm(args = {}) = vm_instance_defaults.merge(args.to_hash.deep_symbolize_keys) logger.debug("creating VM with the following options: #{.inspect}") # Add clound init user data user_data = { "userData" => [:user_data] } if [:user_data].present? begin volumes = create_volumes_for_vm() interfaces, networks = create_network_devices_for_vm(, volumes) client.vms.create(:vm_name => [:name], :cpus => [:cpu_cores].to_i, :memory_size => convert_memory([:memory] + "b", :mi).to_s, :memory_unit => "Mi", :volumes => volumes, :cloudinit => user_data, :networks => networks, :interfaces => interfaces) client.servers.get([:name]) rescue Exception => e delete_pvcs(volumes) if volumes raise e end end |
#destroy_vm(vm_uuid) ⇒ Object
183 184 185 186 187 188 189 |
# File 'app/models/foreman_kubevirt/kubevirt.rb', line 183 def destroy_vm(vm_uuid) vm = find_vm_by_uuid(vm_uuid) delete_pvcs(vm.volumes) vm.destroy rescue ActiveRecord::RecordNotFound true end |
#find_vm_by_uuid(uuid) ⇒ Object
88 89 90 91 92 93 |
# File 'app/models/foreman_kubevirt/kubevirt.rb', line 88 def find_vm_by_uuid(uuid) super rescue Fog::Kubevirt::Errors::ClientError => e Foreman::Logging.exception("Failed retrieving KubeVirt vm by uuid #{uuid}", e) raise ActiveRecord::RecordNotFound end |
#host_compute_attrs(host) ⇒ Object
191 192 193 194 195 |
# File 'app/models/foreman_kubevirt/kubevirt.rb', line 191 def host_compute_attrs(host) attrs = super attrs[:interfaces_attributes].each_value { |nic| nic["network"] = nil if nic["cni_provider"] == "pod" } attrs end |
#host_interfaces_attrs(host) ⇒ Object
Overrding base class implementation since ‘mac’ is required for the created interface
215 216 217 218 219 |
# File 'app/models/foreman_kubevirt/kubevirt.rb', line 215 def host_interfaces_attrs(host) host.interfaces.select(&:physical?).each.with_index.reduce({}) do |hash, (nic, index)| hash.merge(index.to_s => nic.compute_attributes.merge(ip: nic.ip, mac: nic.mac, provision: nic.provision)) end end |
#max_cpu_count ⇒ Object
TODO: max supported values should be fetched according to namespace
capabilities: kubectl get limits namespace_name
274 275 276 |
# File 'app/models/foreman_kubevirt/kubevirt.rb', line 274 def max_cpu_count 16 end |
#max_memory ⇒ Object
282 283 284 |
# File 'app/models/foreman_kubevirt/kubevirt.rb', line 282 def max_memory 64.gigabytes end |
#max_socket_count ⇒ Object
278 279 280 |
# File 'app/models/foreman_kubevirt/kubevirt.rb', line 278 def max_socket_count 16 end |
#networks ⇒ Object
80 81 82 83 84 85 86 |
# File 'app/models/foreman_kubevirt/kubevirt.rb', line 80 def networks client..all rescue StandardError => e logger.warn("Failed to retrieve network attachments definition from KubeVirt, make sure KubeVirt has CNI provider and NetworkAttachmentDefinition CRD deployed: #{e.}") [] end |
#new_interface(attr = {}) ⇒ Object
208 209 210 |
# File 'app/models/foreman_kubevirt/kubevirt.rb', line 208 def new_interface(attr = {}) Fog::Kubevirt::Compute::VmNic.new attr end |
#new_vm(attr = {}) ⇒ Object
259 260 261 262 263 264 265 266 |
# File 'app/models/foreman_kubevirt/kubevirt.rb', line 259 def new_vm(attr = {}) vm = super interfaces = nested_attributes_for :interfaces, attr[:interfaces_attributes] interfaces.map { |i| vm.interfaces << new_interface(i) } volumes = nested_attributes_for :volumes, attr[:volumes_attributes] volumes.map { |v| vm.volumes << new_volume(v) } vm end |
#new_volume(attrs = {}) ⇒ Object
107 108 109 110 111 112 113 114 |
# File 'app/models/foreman_kubevirt/kubevirt.rb', line 107 def new_volume(attrs = {}) return unless new_volume_errors.empty? capacity = attrs.delete(:capacity) args = {capacity: capacity}.merge(attrs) vol = Fog::Kubevirt::Compute::Volume.new(args) vol.boot_order = 1 if args[:bootable] == "on" || args[:bootable] == "true" vol end |
#new_volume_errors ⇒ Object
116 117 118 119 120 |
# File 'app/models/foreman_kubevirt/kubevirt.rb', line 116 def new_volume_errors errors = [] errors.push _('no Storage Classes available on provider') if storage_classes.empty? errors end |
#plain_kubevirt_protocol ⇒ Object
294 295 296 |
# File 'app/models/foreman_kubevirt/kubevirt.rb', line 294 def plain_kubevirt_protocol "plain.kubevirt.io".freeze end |
#provided_attributes ⇒ Object
35 36 37 |
# File 'app/models/foreman_kubevirt/kubevirt.rb', line 35 def provided_attributes { :uuid => :name, :mac => :mac } end |
#set_vm_volumes_attributes(vm, vm_attrs) ⇒ Object
Overrding base class implementation since ‘pvc’ is required
224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 |
# File 'app/models/foreman_kubevirt/kubevirt.rb', line 224 def set_vm_volumes_attributes(vm, vm_attrs) volumes = vm.volumes.collect do |vol| next unless vol.type == 'persistentVolumeClaim' begin vol.pvc = client.pvcs.get(vol.info) vol rescue StandardError => e # An import of a VM where one of its PVC doesn't exist Foreman::Logging.exception("Import VM fail: The PVC #{vol.info} does not exist for VM #{vm.name}", e) nil end end.compact vm_attrs[:volumes_attributes] = Hash[volumes.each_with_index.map { |volume, idx| [idx.to_s, volume.attributes] }] vm_attrs end |
#storage_classes ⇒ Object
99 100 101 |
# File 'app/models/foreman_kubevirt/kubevirt.rb', line 99 def storage_classes client.storageclasses.all end |
#storage_classes_for_select ⇒ Object
103 104 105 |
# File 'app/models/foreman_kubevirt/kubevirt.rb', line 103 def storage_classes_for_select storage_classes.map { |sc| OpenStruct.new(id: sc.name, description: "#{sc.name} (#{sc.provisioner})") } end |
#test_connection(options = {}) ⇒ Object
55 56 57 58 |
# File 'app/models/foreman_kubevirt/kubevirt.rb', line 55 def test_connection( = {}) super validate_connectivity() end |
#to_label ⇒ Object
47 48 49 |
# File 'app/models/foreman_kubevirt/kubevirt.rb', line 47 def to_label "#{name} (#{provider_friendly_name})" end |
#token_protocol(token) ⇒ Object
298 299 300 |
# File 'app/models/foreman_kubevirt/kubevirt.rb', line 298 def token_protocol(token) "base64url.bearer.authorization.k8s.io.#{token}" end |
#user_data_supported? ⇒ Boolean
31 32 33 |
# File 'app/models/foreman_kubevirt/kubevirt.rb', line 31 def user_data_supported? true end |
#validate_connectivity(options = {}) ⇒ Object
64 65 66 67 68 69 70 71 72 73 74 |
# File 'app/models/foreman_kubevirt/kubevirt.rb', line 64 def validate_connectivity( = {}) return unless connection_properties_valid? return false if errors.any? client&.valid? && client&.virt_supported? rescue StandardError => e if /401/.match?(e.) errors[:base] << _('The compute resource could not be authenticated') else errors[:base] << e. end end |
#vm_compute_attributes(vm) ⇒ Object
242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 |
# File 'app/models/foreman_kubevirt/kubevirt.rb', line 242 def vm_compute_attributes(vm) vm_attrs = super interfaces = vm.interfaces || [] vm_attrs[:interfaces_attributes] = interfaces.each_with_index.each_with_object({}) do |(interface, index), hsh| interface_attrs = { mac: interface.mac, compute_attributes: { network: interface.network, cni_provider: interface.cni_provider } } hsh[index.to_s] = interface_attrs end vm_attrs end |
#vm_instance_defaults ⇒ Object
Since ‘name’ is the identity/UUID of server/vm, we need to override default values that assign also value for ‘name’ so vm_exists? will return ‘false’
201 202 203 204 205 206 |
# File 'app/models/foreman_kubevirt/kubevirt.rb', line 201 def vm_instance_defaults { :memory => 1024.megabytes.to_s, :cpu_cores => '1' } end |
#volumes ⇒ Object
95 96 97 |
# File 'app/models/foreman_kubevirt/kubevirt.rb', line 95 def volumes client.volumes.all end |