class Fog::Kubevirt::Compute::Real
Constants
- CORE_GROUP
The API group of the Kubernetes core:
- KUBEVIRT_GROUP
The API group of KubeVirt:
- NETWORK_GROUP
The API group of the Kubernetes network extention:
- STORAGE_GROUP
The API group of the Kubernetes network extention:
Public Class Methods
# File lib/fog/kubevirt/compute/compute.rb, line 151 def initialize(options={}) require 'kubeclient' @kubevirt_token = options[:kubevirt_token] @host = options[:kubevirt_hostname] @port = options[:kubevirt_port] @kubevirt_version = options[:kubevirt_version] @log = options[:kubevirt_log] @log ||= ::Logger.new(STDOUT) @namespace = options[:kubevirt_namespace] || 'default' @opts = { :ssl_options => obtain_ssl_options(options), :auth_options => { :bearer_token => @kubevirt_token } } # Kubeclient needs different client objects for different API groups. We will keep in this hash the # client objects, indexed by API path/version. @clients = {} end
Public Instance Methods
creates netwrork attachment definition object @param net_att contains the following elements: metadata: the net-attachment-def metadata:
name[String]: the netwrork attachment definition definition spec[Hash]: the specification of the attachment, contains:config config[string]: the configuration of the attachment, i.e. '{ :cniVersion => "0.3.1", :type => "ovs", :bridge => "red" }'
Example of net_att: metadata: {
name: "ovs-red"}, spec: { config: '{ cni_version: "0.3.1", type: "ovs", bridge: "red" }' }
# File lib/fog/kubevirt/compute/requests/create_networkattachmentdef.rb, line 20 def create_networkattachmentdef(net_att) if net_att.dig(:metadata, :namespace).nil? net_att = deep_merge!(net_att, metadata: { namespace: @namespace }) end kube_net_client.create_network_attachment_definition(net_att) end
# File lib/fog/kubevirt/compute/requests/create_persistentvolume.rb, line 5 def create_persistentvolume(volume) kube_client.create_persistent_volume(volume) end
# File lib/fog/kubevirt/compute/requests/create_pvc.rb, line 5 def create_pvc(pvc) kube_client.create_persistent_volume_claim(pvc) end
# File lib/fog/kubevirt/compute/requests/create_service.rb, line 5 def create_service(srv) kube_client.create_service(srv) end
# File lib/fog/kubevirt/compute/requests/create_storageclass.rb, line 5 def create_storageclass(storageclass) kube_storage_client.create_storage_class(storageclass) end
# File lib/fog/kubevirt/compute/requests/create_vm.rb, line 5 def create_vm(vm) vm[:apiVersion] = kubevirt_client.version kubevirt_client.create_virtual_machine(vm) end
# File lib/fog/kubevirt/compute/requests/create_vminstance.rb, line 6 def create_vminstance(vm) kubevirt_client.create_virtual_machine_instance(vm) end
# File lib/fog/kubevirt/compute/requests/delete_networkattachmentdef.rb, line 5 def delete_networkattachmentdef(name, namespace) kube_net_client.delete_network_attachment_definition(name, namespace) end
# File lib/fog/kubevirt/compute/requests/delete_persistentvolume.rb, line 5 def delete_persistentvolume(name) kube_client.delete_persistent_volume(name) end
# File lib/fog/kubevirt/compute/requests/delete_pvc.rb, line 5 def delete_pvc(name) kube_client.delete_persistent_volume_claim(name, namespace) end
# File lib/fog/kubevirt/compute/requests/delete_service.rb, line 5 def delete_service(name, namespace) kube_client.delete_service(name, namespace) end
# File lib/fog/kubevirt/compute/requests/delete_storageclass.rb, line 5 def delete_storageclass(name) kube_storage_client.delete_storage_class(name) end
# File lib/fog/kubevirt/compute/requests/delete_vm.rb, line 5 def delete_vm(name, namespace) kubevirt_client.delete_virtual_machine(name, namespace) end
# File lib/fog/kubevirt/compute/requests/delete_vminstance.rb, line 5 def delete_vminstance(name) kubevirt_client.delete_virtual_machine_instance(name, @namespace) end
# File lib/fog/kubevirt/compute/requests/get_networkattachmentdef.rb, line 7 def get_networkattachmentdef(name) net_attach_def = kube_net_client.get_network_attachment_definition(name, @namespace) Networkattachmentdef.parse object_to_hash(net_attach_def) end
# File lib/fog/kubevirt/compute/requests/get_node.rb, line 7 def get_node(name) Node.parse object_to_hash( kube_client.get_node(name) ) end
# File lib/fog/kubevirt/compute/requests/get_persistentvolume.rb, line 5 def get_persistentvolume(name) Persistentvolume.parse object_to_hash(kube_client.get_persistent_volume(name)) end
# File lib/fog/kubevirt/compute/requests/get_pvc.rb, line 5 def get_pvc(name) Pvc.parse object_to_hash(kube_client.get_persistent_volume_claim(name, @namespace)) end
# File lib/fog/kubevirt/compute/requests/get_vm.rb, line 33 def get_raw_vm(name) object_to_hash(kubevirt_client.get_virtual_machine(name, @namespace)) end
# File lib/fog/kubevirt/compute/requests/get_server.rb, line 5 def get_server(name) vm = get_raw_vm(name) vmi = runtime_vm(vm) populate_runtime_info(vm, vmi) server = Server.parse vm populate_pvcs_for_vm(server) populate_runtime_nets(server, vmi) server end
# File lib/fog/kubevirt/compute/requests/get_service.rb, line 5 def get_service(name) Service.parse object_to_hash(kube_client.get_service(name, @namespace)) end
# File lib/fog/kubevirt/compute/requests/get_storageclass.rb, line 5 def get_storageclass(name) Storageclass.parse object_to_hash(kube_storage_client.get_storage_class(name)) end
# File lib/fog/kubevirt/compute/requests/get_template.rb, line 5 def get_template(name) Template.parse object_to_hash( openshift_client.get_template(name, @namespace) ) end
# File lib/fog/kubevirt/compute/requests/get_vm.rb, line 5 def get_vm(name) vm = Vm.parse get_raw_vm(name) populate_pvcs_for_vm(vm) vm end
# File lib/fog/kubevirt/compute/requests/get_vminstance.rb, line 7 def get_vminstance(name) # namespace is defined on the Real object Vminstance.parse object_to_hash( kubevirt_client.get_virtual_machine_instance(name, @namespace) ) end
# File lib/fog/kubevirt/compute/requests/get_vnc_console_details.rb, line 5 def get_vnc_console_details(name, namespace) url = URI::Generic.build( :scheme => 'https', :host => @host, :port => @port, :path => "/apis/kubevirt.io" ) version = detect_version(url.to_s, @opts[:ssl_options]) { :host => @host, :port => @port, :path => "/apis/subresources.kubevirt.io/#{version}/namespaces/#{namespace}/virtualmachineinstances/#{name}/vnc", :token => @opts[:auth_options][:bearer_token] } end
# File lib/fog/kubevirt/compute/requests/list_networkattachmentdefs.rb, line 5 def list_networkattachmentdefs(_filters = {}) netdefs = kube_net_client.get_network_attachment_definitions entities = netdefs.map do |kubevirt_obj| Networkattachmentdef.parse object_to_hash(kubevirt_obj) end EntityCollection.new(netdefs.kind, netdefs.resourceVersion, entities) end
# File lib/fog/kubevirt/compute/requests/list_nodes.rb, line 5 def list_nodes(_filters = {}) nodes = kube_client.get_nodes entities = nodes.map { |kubevirt_obj| Node.parse object_to_hash(kubevirt_obj) } EntityCollection.new(nodes.kind, nodes.resourceVersion, entities) end
# File lib/fog/kubevirt/compute/requests/list_persistentvolumes.rb, line 7 def list_persistentvolumes(_filters = {}) volumes = kube_client.get_persistent_volumes() entities = volumes.map do |kubevirt_obj| Persistentvolume.parse object_to_hash(kubevirt_obj) end EntityCollection.new(volumes.kind, volumes.resourceVersion, entities) end
# File lib/fog/kubevirt/compute/requests/list_pvcs.rb, line 7 def list_pvcs(_filters = {}) pvcs = kube_client.get_persistent_volume_claims(namespace: @namespace) entities = pvcs.map do |kubevirt_obj| Pvc.parse object_to_hash(kubevirt_obj) end EntityCollection.new(pvcs.kind, pvcs.resourceVersion, entities) end
filters - if contains ':pvcs' set to true will popoulate pvcs for vms
# File lib/fog/kubevirt/compute/requests/list_servers.rb, line 9 def list_servers(filters = {}) vms = kubevirt_client.get_virtual_machines(namespace: @namespace) entities = vms.map do |kubevirt_obj| vm_obj = object_to_hash(kubevirt_obj) vmi = runtime_vm(vm_obj) populate_runtime_info(vm_obj, vmi) server = Server.parse vm_obj populate_runtime_nets(server, vmi) if filters[:pvcs] populate_pvcs_for_vm(server) end server end EntityCollection.new(vms.kind, vms.resourceVersion, entities) end
# File lib/fog/kubevirt/compute/requests/list_services.rb, line 7 def list_services(_filters = {}) services = kube_client.get_services(namespace: @namespace) entities = services.map do |kubevirt_obj| Service.parse object_to_hash(kubevirt_obj) end EntityCollection.new(services.kind, services.resourceVersion, entities) end
# File lib/fog/kubevirt/compute/requests/list_storageclasses.rb, line 7 def list_storageclasses(_filters = {}) storageclasses = kube_storage_client.get_storage_classes entities = storageclasses.map do |kubevirt_obj| Storageclass.parse object_to_hash(kubevirt_obj) end EntityCollection.new(storageclasses.kind, storageclasses.resourceVersion, entities) end
# File lib/fog/kubevirt/compute/requests/list_templates.rb, line 7 def list_templates(_filters = {}) temps = openshift_client.get_templates(namespace: @namespace) entities = temps.map do |kubevirt_obj| Template.parse object_to_hash(kubevirt_obj) end EntityCollection.new(temps.kind, temps.resourceVersion, entities) end
# File lib/fog/kubevirt/compute/requests/list_vminstances.rb, line 5 def list_vminstances(_filters = {}) vminstances = kubevirt_client.get_virtual_machine_instances(namespace: @namespace) entities = vminstances.map do |kubevirt_obj| Vminstance.parse object_to_hash(kubevirt_obj) end EntityCollection.new(vminstances.kind, vminstances.resourceVersion, entities) end
filters - if contains ':pvcs' set to true will popoulate pvcs for vms
# File lib/fog/kubevirt/compute/requests/list_vms.rb, line 8 def list_vms(filters = {}) vms = kubevirt_client.get_virtual_machines(namespace: @namespace) entities = vms.map do |kubevirt_obj| vm = Vm.parse object_to_hash(kubevirt_obj) if filters[:pvcs] populate_pvcs_for_vm(vm) end vm end EntityCollection.new(vms.kind, vms.resourceVersion, entities) end
# File lib/fog/kubevirt/compute/requests/list_volumes.rb, line 7 def list_volumes(vm_name = nil) if vm_name.nil? entities = pvcs.all.map do |pvc| volume = Volume.new volume.name = pvc.name volume.type = 'persistentVolumeClaim' set_volume_pvc_attributes(volume, pvc) volume end EntityCollection.new('Volume', pvcs.resource_version, entities) else vm = vms.get(vm_name) EntityCollection.new('Volume', vm.resource_version, vm.volumes) end end
# File lib/fog/kubevirt/compute/compute.rb, line 310 def namespace @namespace end
# File lib/fog/kubevirt/compute/requests/get_vm.rb, line 11 def populate_pvcs_for_vm(vm) vm[:volumes].each do |vol| set_volume_pvc_attributes(vol) end end
Updates a given VM raw entity with vm instance info if exists
@param vm [Hash] A hash with vm raw data. @param vmi VMInstance object
# File lib/fog/kubevirt/compute/requests/get_server.rb, line 20 def populate_runtime_info(vm, vmi) return if vmi.nil? vm[:ip_address] = vmi[:ip_address] vm[:node_name] = vmi[:node_name] vm[:phase] = vmi[:status] vm end
Updates a given Server entity with vm instance networking details if exists
@param server Server object @param vmi VMInstance object
# File lib/fog/kubevirt/compute/requests/get_server.rb, line 33 def populate_runtime_nets(server, vmi) return if vmi.nil? server[:networks] = vmi[:networks] server[:interfaces] = vmi[:interfaces] end
# File lib/fog/kubevirt/compute/requests/get_vm.rb, line 17 def set_volume_pvc_attributes(volume, pvc = nil) return unless volume.type == 'persistentVolumeClaim' if pvc.nil? begin pvc = pvcs.get(volume.info) rescue # there is an option that the PVC does not exist return end end volume.pvc = pvc volume.capacity = pvc&.requests[:storage] volume.storage_class = pvc.storage_class end
Calculates the URL of the SPICE proxy server.
@return [String] The URL of the spice proxy server.
# File lib/fog/kubevirt/compute/compute.rb, line 298 def spice_proxy_url service = kube_client.get_service('spice-proxy', @namespace) host = service.spec.externalIPs.first port = service.spec.ports.first.port url = URI::Generic.build( :scheme => 'http', :host => host, :port => port, ) url.to_s end
# File lib/fog/kubevirt/compute/requests/update_vm.rb, line 5 def update_vm(update) kubevirt_client.update_virtual_machine(update) end
# File lib/fog/kubevirt/compute/compute.rb, line 188 def valid? kube_client.api_valid? begin kube_client.get_namespace(namespace) rescue => err @log.warn("The namespace [#{namespace}] does not exist on the kubernetes cluster: #{err.message}") raise "The namespace '#{namespace}' does not exist on the kubernetes cluster" end end
# File lib/fog/kubevirt/compute/compute.rb, line 175 def virt_supported? virt_enabled = false begin virt_enabled = kubevirt_client.api["versions"].any? { |ver| ver["groupVersion"]&.start_with?(KUBEVIRT_GROUP) } rescue => err # we failed to communicate or to evaluate the version format @log.warn("Failed to detect kubevirt on provider with error: #{err.message}") end virt_enabled end
Returns a watcher for nodes.
@param opts [Hash] A hash with options for the watcher. @return [WatchWrapper] The watcher.
# File lib/fog/kubevirt/compute/compute.rb, line 223 def watch_nodes(opts = {}) mapper = Proc.new do |notice| node = OpenStruct.new(Node.parse(notice.object)) if notice.object.kind == 'Node' node ||= OpenStruct.new populate_notice_attributes(node, notice) node end watch = kube_client.watch_nodes(opts) WatchWrapper.new(watch, mapper) end
Returns a watcher for templates.
@param opts [Hash] A hash with options for the watcher. @return [WatchWrapper] The watcher.
# File lib/fog/kubevirt/compute/compute.rb, line 280 def watch_templates(opts = {}) mapper = Proc.new do |notice| template = OpenStruct.new(Template.parse(notice.object)) if notice.object.kind == 'Template' template ||= OpenStruct.new populate_notice_attributes(template, notice) template end watch = openshift_client.watch_templates(opts) WatchWrapper.new(watch, mapper) end
Returns a watcher for virtual machine instances.
@param opts [Hash] A hash with options for the watcher. @return [WatchWrapper] The watcher.
# File lib/fog/kubevirt/compute/compute.rb, line 261 def watch_vminstances(opts = {}) mapper = Proc.new do |notice| vminstance = OpenStruct.new(Vminstance.parse(object_to_hash(notice.object))) if notice.object.kind == 'VirtualMachineInstance' vminstance ||= OpenStruct.new populate_notice_attributes(vminstance, notice) vminstance end watch = kubevirt_client.watch_virtual_machine_instances(opts) WatchWrapper.new(watch, mapper) end
Returns a watcher for virtual machines.
@param opts [Hash] A hash with options for the watcher. @return [WatchWrapper] The watcher.
# File lib/fog/kubevirt/compute/compute.rb, line 242 def watch_vms(opts = {}) mapper = Proc.new do |notice| vm = OpenStruct.new(Vm.parse(object_to_hash(notice.object))) if notice.object.kind == 'VirtualMachine' vm ||= OpenStruct.new populate_notice_attributes(vm, notice) vm end watch = kubevirt_client.watch_virtual_machines(opts) WatchWrapper.new(watch, mapper) end
Private Instance Methods
# File lib/fog/kubevirt/compute/compute.rb, line 395 def check_client(key) @clients[key] end
Lazily creates the a client for the given Kubernetes API path.
@param path [String] The Kubernetes API path. @return [Kubeclient::Client] The client for the given path.
# File lib/fog/kubevirt/compute/compute.rb, line 334 def create_client(path) url = URI::Generic.build( :scheme => 'https', :host => @host, :port => @port, :path => path ) if @kubevirt_token.to_s.empty? create_client_from_config(path) else create_client_from_token(url) end end
# File lib/fog/kubevirt/compute/compute.rb, line 375 def create_client_from_config(path) config = Kubeclient::Config.read(ENV['KUBECONFIG'] || ENV['HOME']+'/.kube/config') context = config.context url = context.api_endpoint version = detect_version(url + path, context.ssl_options) key = path + '/' + version client = check_client(key) return client if client client = Kubeclient::Client.new( url + path, version, ssl_options: context.ssl_options, auth_options: context.auth_options ) wrap_client(client, version, key) end
# File lib/fog/kubevirt/compute/compute.rb, line 349 def create_client_from_token(url) # Prepare the TLS and authentication options that will be used for the standard Kubernetes API # and also for the KubeVirt extension: @opts = { :ssl_options => { :verify_ssl => OpenSSL::SSL::VERIFY_NONE, }, :auth_options => { :bearer_token => @kubevirt_token } } version = detect_version(url.to_s, @opts[:ssl_options]) key = url.path + '/' + version client = check_client(key) return client if client client = Kubeclient::Client.new( url.to_s, version, @opts ) wrap_client(client, version, key) end
# File lib/fog/kubevirt/compute/compute.rb, line 406 def detect_version(url, ssl_options) options = { ssl_ca_file: ssl_options[:ca_file], ssl_cert_store: ssl_options[:cert_store], verify_ssl: ssl_options[:verify_ssl], ssl_client_cert: ssl_options[:client_cert], ssl_client_key: ssl_options[:client_key], headers: { Authorization: "Bearer #{@opts[:auth_options][:bearer_token]}"} } begin response = ::JSON.parse(RestClient::Resource.new(url, options).get) rescue => e raise ::Fog::Kubevirt::Errors::ClientError, e end # version detected based on # https://github.com/kubernetes-incubator/apiserver-builder/blob/master/docs/concepts/aggregation.md#viewing-discovery-information preferredVersion = response["preferredVersion"] if url.include? KUBEVIRT_GROUP version = @kubevirt_version || preferredVersion["version"] else version = preferredVersion["version"] if preferredVersion version = version || response["versions"][0] end version end
# File lib/fog/kubevirt/compute/compute.rb, line 438 def kube_client create_client('/api') end
# File lib/fog/kubevirt/compute/compute.rb, line 446 def kube_net_client create_client('/apis/' + NETWORK_GROUP) end
# File lib/fog/kubevirt/compute/compute.rb, line 450 def kube_storage_client create_client('/apis/' + STORAGE_GROUP) end
# File lib/fog/kubevirt/compute/compute.rb, line 442 def kubevirt_client create_client('/apis/' + KUBEVIRT_GROUP) end
# File lib/fog/kubevirt/compute/compute.rb, line 454 def log @log end
Prepare the TLS and authentication options that will be used for the standard Kubernetes API and also for the KubeVirt extension
@param options [Hash] a hash with connection options
# File lib/fog/kubevirt/compute/compute.rb, line 464 def obtain_ssl_options(options) verify_ssl = options[:kubevirt_verify_ssl] if verify_ssl == true ca = options[:kubevirt_ca_cert] || "" ca = IO.read(ca) if File.file?(ca) certs = ca.split(/(?=-----BEGIN)/).reject(&:empty?).collect do |pem| OpenSSL::X509::Certificate.new(pem) end cert_store = OpenSSL::X509::Store.new certs.each do |cert| cert_store.add_cert(cert) end ssl_options = { :verify_ssl => OpenSSL::SSL::VERIFY_PEER, :cert_store => cert_store } elsif verify_ssl == false || verify_ssl.to_s.empty? ssl_options = { :verify_ssl => OpenSSL::SSL::VERIFY_NONE } else ssl_options = { :verify_ssl => verify_ssl } end end
# File lib/fog/kubevirt/compute/compute.rb, line 434 def openshift_client create_client('/oapi') end
Populates required notice attributes
@param object entity to populate @param notice the source of the data to populate from
# File lib/fog/kubevirt/compute/compute.rb, line 321 def populate_notice_attributes(object, notice) object.metadata = notice.object.metadata object.type = notice.type object.code = notice.object.code object.kind = notice.object.kind end
# File lib/fog/kubevirt/compute/requests/get_server.rb, line 42 def runtime_vm(vm) get_vminstance(vm[:metadata][:name]) rescue # do nothing if vmi doesn't exist end
# File lib/fog/kubevirt/compute/compute.rb, line 399 def wrap_client(client, version, key) wrapped_client = ::Fog::Kubevirt::Utils::ExceptionWrapper.new(client, version, @log) @clients[key] = wrapped_client wrapped_client end