Category Archives: kubevirt

foreman_kubevirt plugin

Foreman  can be extended by installing plugins.

Recently I’ve been working on adding support for Kubevirt as a compute resource of Foreman: meaning Foreman users/admins can create and manage their hosts as Kubevirt’s virtual machines.

The Foreman-Kubevirt plugin is under development but no reason not to share info about it and get feedback about how to shape it and what to include in it. The following screenshots show the current state of the plugin and its supported dialog:

  • Adding Compute Resource:

compute_resource.png

  • Showing list of virtual machines:

list_vms.png

  • Showing a single offline virtual machine

show_offline_vm.png

  • Showing a single online virtual machine

show_online_vm.png

There are few gaps that need to be handled, i.e. support SSL communication with Kubevirt and Host actions.

In order to test the plugin on the env, users should use their self-built fog-kubevirt release on top of this fog-kubevirt patch.

Please report any issues to https://github.com/masayag/foreman_kubevirt/issues

fog-kubevirt

fog-kubevirt is a ruby client for Kubevirt. With kubevirt the administrator can manage virtual machines on Kubernetes cluster. fog-kubevirt uses kubeclient, a ruby client for Kubernetes.

Instructions for creating a running kubevirt instance can be found here.

In order to start working with fog-kubevirt, you’ll have to install it. Either by installing the latest release from rubygem.org by:

$ gem install fog-kubevirt

Or by picking a release from the releases page of the project.

In order to add fog-kubevirt to your ruby project, add the following line to project’s Gemfile:

gem 'fog-kubevirt'

followed by running:

$ bundle

Let’s start using fog-kubevirt:

Declare the library:

require 'fog/kubevirt'

Instantiate the kubevirt provider:

provider = Fog::Compute.new(:provider           => 'kubevirt',
                            :kubevirt_hostname  => hostname,
                            :kubevirt_port      => port,
                            :kubevirt_token     => token,
                            :kubevirt_namespace => 'default')

The required attributes are obtained as follow:

  • kubevirt_hostname – the hostname of the kubevirt server
  • kubevirt_port – the port of the kubevirt (8443/443 if relying on Openshift, else 6443)
  • kubevirt_token – the token can be achieved by extracting the token from the created my-account-tokex-xyz secret:
    • kubectl get secret my-account-token-vgtjm --template='{{index .data "token"}}' | base64 --decode
  • kubevirt_namespace – the cluster namespace to use

Another option is using the .fog file under the home directory. The .fog file contains the credentials and additional properties to be used by fog instead of specifying them within code. For kubevirt’s need, add the following properties to .fog with their actual value:

  :kubevirt_token:
  :kubevirt_hostname: node01
  :kubevirt_port: 8443
  :kubevirt_group: kubevirt.io
  :kubevirt_version: v1alpha2
  :kubevirt_namespace: default

Once kubevirt is instantiated, it can be used for listing virtual machines, virtual machine instances, templates and nodes and to perform management actions:

  # get all virtual machines
  vms = provider.vms

Creating a virtual machine is done by selecting a template and cloning it into a virtual machine.
Creating a template on kubevirt can be done by selecting a template and running:

kubectl create -f working-template.yml

More templates can be found here.
And creating the template by:

  # selecting a template named 'working'
  template = connection.template('working')

  # opts should contain keys to be replaced within the template
  opts = {name: 'vm-demo-1', memory: 1024, cpu_cores: 1}
  template.clone(opts)

Getting a specific virtual machine:

  # get vm by its name
  vm = provider.vms.get('vm-demo-1')

The returned object looks like:

"ovm-vm-demo-1", :"kubevirt.io/os"=>"fedora28"},
    owner_reference=nil,
    annotations=nil,
    cpu_cores=1,
    memory="1Gi",
    disks=[{:disk=>{:bus=>"virtio"}, :name=>"disk0", :volumeName=>"root"}, {:disk=>{:bus=>"virtio"}, :name=>"cloudinitdisk", :volumeName=>"cloudinitvolume"}],
    volumes=[{:name=>"root", :persistentVolumeClaim=>{:claimName=>"rhel75-pvc-15"}}, {:cloudInitNoCloud=>{:userData=>"#cloud-config\npassword: 'redhat'\nchpasswd: { expire: False }"}, :name=>"cloudinitvolume"}]

With the vm entity the user can start and stop the virtual machine:

  # start the virtual machine
  vm.start

The output of that action is a virt-launcher pod that will create the container in which the virtual machine will be running:
$ kubectl describe vmis vm-demo-1

And the output will be:

Name:           vm-demo-1
Namespace:      default
Labels:         kubevirt-ovm=ovm-vm-demo-1
                special=demo-key
Events:
  FirstSeen     LastSeen        Count   From                            SubObjectPath   Type            Reason                  Message
  ---------     --------        -----   ----                            -------------   --------        ------                  -------
  3s            3s              1       virtualmachine-controller                       Normal          SuccessfulCreate        Created virtual machine pod virt-launcher-vm-demo-1-2s6rg

Track the virtual machine instance status by:

  # get vm by its name
  vmi = provider.vminstances.get('vm-demo-1')
  vmi.status

In order to stop the virtual machine, simply:

  # stop the virtual machine and deletes the virtual machine instance
  vm.stop

In order to remove the virtual machine, use:

  # stop the virtual machine and deletes the virtual machine instance
  # 'default' is the namespace in which the virtual machine was created
  kube.delete_vm('vm-demo-1', 'default')

An attempt to get the virtual machine again will fail with 404:

  kube.vms.get('vm-demo-1')
Fog::Kubevirt::Errors::ClientError: HTTP status code 404, virtualmachines.kubevirt.io "vm-demo-1" not found

There is an option to track changes of virtual machines by receiving entities updates using notices.

  # last_known_version is the last version tracked by the client
  # all the updates later than last_known_version will be watched
  watcher = provider.watch_vms(:resource_version => last_known_version)
  watcher.each do |notice|
    # process notice data
  end

manageiq-providers-kubevirt is actively using fog-kubevirt as a client to interact with kubevirt. It also relies on the notices to dynamically update the virtual machines and templates on ManageIQ for Kubevirt provider.