foreman_kubevirt 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +619 -0
- data/README.md +156 -0
- data/Rakefile +44 -0
- data/app/assets/javascripts/foreman_kubevirt/kubevirt.js +31 -0
- data/app/assets/javascripts/foreman_kubevirt/nic_info.js +9 -0
- data/app/controllers/foreman_kubevirt/concerns/api/compute_resources_controller_extensions.rb +26 -0
- data/app/models/concerns/fog_extensions/kubevirt/network.rb +11 -0
- data/app/models/concerns/fog_extensions/kubevirt/server.rb +55 -0
- data/app/models/concerns/fog_extensions/kubevirt/vmnic.rb +12 -0
- data/app/models/concerns/fog_extensions/kubevirt/volume.rb +26 -0
- data/app/models/foreman_kubevirt/kubevirt.rb +370 -0
- data/app/views/api/v2/compute_resources/kubevirt.json.rabl +1 -0
- data/app/views/compute_resources/form/_kubevirt.html.erb +14 -0
- data/app/views/compute_resources/show/_kubevirt.html.erb +14 -0
- data/app/views/compute_resources_vms/form/kubevirt/_base.html.erb +27 -0
- data/app/views/compute_resources_vms/form/kubevirt/_network.html.erb +15 -0
- data/app/views/compute_resources_vms/form/kubevirt/_volume.html.erb +21 -0
- data/app/views/compute_resources_vms/index/_kubevirt.html.erb +29 -0
- data/app/views/compute_resources_vms/show/_kubevirt.html.erb +55 -0
- data/app/views/images/form/_kubevirt.html.erb +4 -0
- data/config/routes.rb +2 -0
- data/lib/foreman_kubevirt/engine.rb +75 -0
- data/lib/foreman_kubevirt/version.rb +3 -0
- data/lib/foreman_kubevirt.rb +4 -0
- data/lib/tasks/foreman_kubevirt_tasks.rake +47 -0
- data/locale/Makefile +60 -0
- data/locale/en/foreman_kubevirt.po +19 -0
- data/locale/foreman_kubevirt.pot +19 -0
- data/locale/gemspec.rb +2 -0
- data/test/factories/compute_resource_factories.rb +10 -0
- data/test/factories/host_factories.rb +49 -0
- data/test/factories/nic_factories.rb +31 -0
- data/test/models/compute_resources/kubevirt_test.rb +69 -0
- data/test/test_plugin_helper.rb +7 -0
- data/test/unit/foreman_kubevirt_test.rb +45 -0
- metadata +127 -0
data/README.md
ADDED
@@ -0,0 +1,156 @@
|
|
1
|
+
|
2
|
+
# Foreman Kubevirt Plugin
|
3
|
+
|
4
|
+
The ```foreman_kubevirt ``` plugin enables managing of [KubeVirt](https://kubevirt.io) as a Compute Resource in Foreman.
|
5
|
+
|
6
|
+
* Website: [TheForeman.org](http://theforeman.org)
|
7
|
+
* Wiki: [Foreman wiki](http://projects.theforeman.org/projects/foreman/wiki/About)
|
8
|
+
* Community and support: #theforeman for general support, #theforeman-dev for development chat in [Freenode](irc.freenode.net)
|
9
|
+
* Mailing lists:
|
10
|
+
* [foreman-users](https://groups.google.com/forum/?fromgroups#!forum/foreman-users)
|
11
|
+
* [foreman-dev](https://groups.google.com/forum/?fromgroups#!forum/foreman-dev)
|
12
|
+
|
13
|
+
|
14
|
+
## Installation
|
15
|
+
|
16
|
+
Please see the Foreman manual for appropriate instructions:
|
17
|
+
|
18
|
+
* [Foreman: How to Install a Plugin](https://theforeman.org/plugins/#2.Installation)
|
19
|
+
|
20
|
+
|
21
|
+
### Building the plugin from source
|
22
|
+
# git clone https://github.com/masayag/foreman_kubevirt.git
|
23
|
+
# cd foreman_kubevirt
|
24
|
+
# gem build foreman_kubevirt.gemspec # the output will be gem named foreman_kubevirt-x.y.z.gem, where x.y.z should be replaced with the actual version
|
25
|
+
|
26
|
+
### Installing the plugin
|
27
|
+
|
28
|
+
#### Installing on Red Hat, CentOS, Fedora, Scientific Linux (rpm)
|
29
|
+
# sudo -i
|
30
|
+
# scl enable tfm bash
|
31
|
+
# yum -y install gcc-c++ redhat-rpm-config gcc rubygems rh-ruby25-ruby-devel-2.5 # or a matching version according to the installed ruby
|
32
|
+
# gem install foreman_kubevirt-x.y.z.gem # replace x.y.z with the actual version
|
33
|
+
|
34
|
+
### Bundle (gem)
|
35
|
+
|
36
|
+
Add the following to bundler.d/Gemfile.local.rb in your Foreman installation directory (/usr/share/foreman by default)
|
37
|
+
|
38
|
+
$ gem 'foreman_kubevirt'
|
39
|
+
|
40
|
+
Or simply:
|
41
|
+
|
42
|
+
$ echo "gem 'foreman_kubevirt'" > /usr/share/foreman/bundler.d/Gemfile.local.rb
|
43
|
+
|
44
|
+
Then run `bundle install` from the same directory
|
45
|
+
|
46
|
+
#### Developing the plugin
|
47
|
+
Add the following to bundler.d/Gemfile.local.rb in your Foreman development directory
|
48
|
+
|
49
|
+
$ gem 'foreman_kubevirt', :path => 'path to foreman_kubevirt directory'
|
50
|
+
|
51
|
+
Then run `bundle install` from the same directory
|
52
|
+
|
53
|
+
-------------------
|
54
|
+
To verify that the installation was successful, go to Foreman, top bar **Administer > About** and check *foreman_kubevirt* shows up in the **System Status** menu under the **Plugins** tab.
|
55
|
+
|
56
|
+
## Compatibility
|
57
|
+
|
58
|
+
| Foreman Version | Plugin Version |
|
59
|
+
| --------------- | --------------:|
|
60
|
+
| >= 1.21.x | ~> 0.1.x |
|
61
|
+
|
62
|
+
## Usage
|
63
|
+
Go to **Infrastructure > Compute Resources** and click on **New Compute Resource**.
|
64
|
+
Choose the **KubeVirt provider**, and fill in all the fields.
|
65
|
+
|
66
|
+
Here is a short description of some of the fields:
|
67
|
+
* *Namespace* - the virtual cluster on kubernetes to which the user has permissions as cluster-admin.
|
68
|
+
* *Token* - a bearer token authentication for HTTP(s) calls.
|
69
|
+
* *X509 Certification Authorities* - enables client certificate authentication for API server calls.
|
70
|
+
|
71
|
+
### How to get values of *Token* and *X509 CA* ?
|
72
|
+
|
73
|
+
#### Kubernetes
|
74
|
+
##### *Token*:
|
75
|
+
|
76
|
+
Either list the secrets and pick the one that contains the relevant token, or select a service account:
|
77
|
+
|
78
|
+
List of secrets that contain the tokens and set secret name instead of *YOUR_SECRET*:
|
79
|
+
```
|
80
|
+
# kubectl get secrets
|
81
|
+
# kubectl get secrets YOUR_SECRET -o jsonpath='{.data.token}' | base64 -d | xargs
|
82
|
+
```
|
83
|
+
|
84
|
+
Or obtain token for a service account named 'foreman-account':
|
85
|
+
```
|
86
|
+
# KUBE_SECRET=`kubectl get sa foreman-account -o jsonpath='{.secrets[0].name}'`
|
87
|
+
# kubectl get secrets $KUBE_SECRET -o jsonpath='{.data.token}' | base64 -d | xargs
|
88
|
+
```
|
89
|
+
|
90
|
+
##### *X509 CA*:
|
91
|
+
|
92
|
+
Taken from kubernetes admin config file:
|
93
|
+
```
|
94
|
+
# cat /etc/kubernetes/admin.conf | grep certificate-authority-data: | cut -d: -f2 | tr -d " " | base64 -d
|
95
|
+
```
|
96
|
+
|
97
|
+
Or by retrieving from the secret, via the service account (in this example assuming its name is *foreman-account*):
|
98
|
+
```
|
99
|
+
# KUBE_SECRET=`kubectl get sa foreman-account -o jsonpath='{.secrets[0].name}'`
|
100
|
+
# kubectl get secret $KUBE_SECRET -o jsonpath='{.data.ca\.crt}' | base64 -d
|
101
|
+
```
|
102
|
+
|
103
|
+
#### OpenShift
|
104
|
+
##### *Token*:
|
105
|
+
|
106
|
+
Create a privileged account named *my-account*:
|
107
|
+
```
|
108
|
+
# oc create -f https://raw.githubusercontent.com/ManageIQ/manageiq-providers-kubevirt/master/manifests/account-openshift.yml
|
109
|
+
```
|
110
|
+
Use *oc* tool for reading the token of the *my-account* service account under *default* namespace:
|
111
|
+
`# oc sa get-token my-account -n default`
|
112
|
+
|
113
|
+
##### *X509 CA*:
|
114
|
+
|
115
|
+
Taken from OpenShift admin config file:
|
116
|
+
```
|
117
|
+
# cat /etc/origin/master/openshift-master.kubeconfig | grep certificate-authority-data: | cut -d: -f2 | tr -d " " | base64 -d
|
118
|
+
```
|
119
|
+
|
120
|
+
Or by retrieving from the secret of service account *my-account* under the *default* namespace:
|
121
|
+
```
|
122
|
+
# KUBE_SECRET=`oc get sa my-account -n default -o jsonpath='{.secrets[0].name}'`
|
123
|
+
# kubectl get secret $KUBE_SECRET -n default -o jsonpath='{.data.ca\.crt}' | base64 -d
|
124
|
+
```
|
125
|
+
|
126
|
+
## Tests
|
127
|
+
|
128
|
+
Tests should be invoked from the *foreman* directory by:
|
129
|
+
```
|
130
|
+
# bundle exec rake test:foreman_kubevirt
|
131
|
+
```
|
132
|
+
|
133
|
+
## TODO
|
134
|
+
|
135
|
+
* Implement VM Console
|
136
|
+
|
137
|
+
## Contributing
|
138
|
+
|
139
|
+
Fork and send a Pull Request. Thanks!
|
140
|
+
|
141
|
+
## Copyright
|
142
|
+
|
143
|
+
Copyright (c) 2018 Red Hat, Inc.
|
144
|
+
|
145
|
+
This program is free software: you can redistribute it and/or modify
|
146
|
+
it under the terms of the GNU General Public License as published by
|
147
|
+
the Free Software Foundation, either version 3 of the License, or
|
148
|
+
(at your option) any later version.
|
149
|
+
|
150
|
+
This program is distributed in the hope that it will be useful,
|
151
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
152
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
153
|
+
GNU General Public License for more details.
|
154
|
+
|
155
|
+
You should have received a copy of the GNU General Public License
|
156
|
+
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
data/Rakefile
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
begin
|
3
|
+
require 'bundler/setup'
|
4
|
+
rescue LoadError
|
5
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
6
|
+
end
|
7
|
+
begin
|
8
|
+
require 'rdoc/task'
|
9
|
+
rescue LoadError
|
10
|
+
require 'rdoc/rdoc'
|
11
|
+
require 'rake/rdoctask'
|
12
|
+
RDoc::Task = Rake::RDocTask
|
13
|
+
end
|
14
|
+
|
15
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
16
|
+
rdoc.rdoc_dir = 'rdoc'
|
17
|
+
rdoc.title = 'ForemanKubevirt'
|
18
|
+
rdoc.options << '--line-numbers'
|
19
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
20
|
+
end
|
21
|
+
|
22
|
+
APP_RAKEFILE = File.expand_path('test/dummy/Rakefile', __dir__)
|
23
|
+
|
24
|
+
Bundler::GemHelper.install_tasks
|
25
|
+
|
26
|
+
require 'rake/testtask'
|
27
|
+
|
28
|
+
Rake::TestTask.new(:test) do |t|
|
29
|
+
t.libs << 'lib'
|
30
|
+
t.libs << 'test'
|
31
|
+
t.pattern = 'test/**/*_test.rb'
|
32
|
+
t.verbose = false
|
33
|
+
end
|
34
|
+
|
35
|
+
begin
|
36
|
+
require 'rubocop/rake_task'
|
37
|
+
RuboCop::RakeTask.new
|
38
|
+
rescue StandardError => _
|
39
|
+
puts 'Rubocop not loaded.'
|
40
|
+
end
|
41
|
+
|
42
|
+
task :default do
|
43
|
+
Rake::Task['rubocop'].execute
|
44
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
bootableRadio = function (item) {
|
2
|
+
const disabled = $('[id$=_bootable_true]:disabled:checked:visible');
|
3
|
+
|
4
|
+
$('[id$=_bootable_true]').prop('checked', false);
|
5
|
+
if (disabled.length > 0) {
|
6
|
+
disabled.prop('checked', true);
|
7
|
+
} else {
|
8
|
+
$(item).prop('checked', true);
|
9
|
+
}
|
10
|
+
}
|
11
|
+
|
12
|
+
cniProviderSelected = function (item) {
|
13
|
+
const selected = $(item).val().toLowerCase();
|
14
|
+
podSelected = selected == "pod";
|
15
|
+
changeNetworkElementVisibility(!podSelected);
|
16
|
+
}
|
17
|
+
|
18
|
+
function changeNetworkElementVisibility(toggle) {
|
19
|
+
if (toggle) {
|
20
|
+
$('.kubevirt-network').parents('.form-group').css('display', '');
|
21
|
+
} else {
|
22
|
+
$('.kubevirt-network').parents('.form-group').css('display', 'none');
|
23
|
+
}
|
24
|
+
}
|
25
|
+
|
26
|
+
function changeNetworkElementVisibilityOnLoad() {
|
27
|
+
selected = $('select.kubevirt-cni-provider').val().toLowerCase();
|
28
|
+
changeNetworkElementVisibility(selected != "pod");
|
29
|
+
}
|
30
|
+
|
31
|
+
$(document).ready(changeNetworkElementVisibilityOnLoad);
|
@@ -0,0 +1,9 @@
|
|
1
|
+
providerSpecificNICInfo = function(form) {
|
2
|
+
cni_provider = form.find('select.kubevirt-cni-provider :selected').text();
|
3
|
+
if (cni_provider === 'pod') {
|
4
|
+
network = '';
|
5
|
+
} else {
|
6
|
+
network = form.find('select.kubevirt-network').val();
|
7
|
+
}
|
8
|
+
return network + ' @ ' + cni_provider;
|
9
|
+
}
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module ForemanKubevirt
|
2
|
+
module Concerns
|
3
|
+
module Api
|
4
|
+
module ComputeResourcesControllerExtensions
|
5
|
+
module ApiPieExtensions
|
6
|
+
extend ::Apipie::DSL::Concern
|
7
|
+
update_api(:create, :update) do
|
8
|
+
param :compute_resource, Hash do
|
9
|
+
param :token, String, :desc => N_("Token for KubeVirt only")
|
10
|
+
param :hostname, String, :desc => N_("Host name for KubeVirt only")
|
11
|
+
param :namespace, String, :desc => N_("Namespace for KubeVirt only")
|
12
|
+
param :ca_crt, String, :desc => N_("CA crt for KubeVirt only")
|
13
|
+
param :api_port, String, :desc => N_("API port for KubeVirt only")
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
extend ActiveSupport::Concern
|
20
|
+
|
21
|
+
included do
|
22
|
+
include ApiPieExtensions
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module FogExtensions
|
2
|
+
module Kubevirt
|
3
|
+
module Server
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
include ActionView::Helpers::NumberHelper
|
7
|
+
|
8
|
+
attr_accessor :image_id
|
9
|
+
|
10
|
+
def to_s
|
11
|
+
name
|
12
|
+
end
|
13
|
+
|
14
|
+
def state
|
15
|
+
status
|
16
|
+
end
|
17
|
+
|
18
|
+
def interfaces_attributes=(attrs)
|
19
|
+
end
|
20
|
+
|
21
|
+
def volumes_attributes=(attrs)
|
22
|
+
end
|
23
|
+
|
24
|
+
def uuid
|
25
|
+
name
|
26
|
+
end
|
27
|
+
|
28
|
+
def mac
|
29
|
+
interfaces.map(&:mac_address).compact.min
|
30
|
+
end
|
31
|
+
|
32
|
+
# TODO: Update once new API for reporting IP_ADRESSSES is set
|
33
|
+
def ip_addresses
|
34
|
+
[interfaces&.first&.ip_address]
|
35
|
+
end
|
36
|
+
|
37
|
+
def poweroff
|
38
|
+
stop
|
39
|
+
end
|
40
|
+
|
41
|
+
def reset
|
42
|
+
stop
|
43
|
+
start
|
44
|
+
end
|
45
|
+
|
46
|
+
def vm_description
|
47
|
+
_("%{cpu_cores} Cores and %{memory} memory") % { :cpu_cores => cpu_cores, :memory => number_to_human_size(memory.to_i) }
|
48
|
+
end
|
49
|
+
|
50
|
+
def select_nic(fog_nics, _nic)
|
51
|
+
fog_nics.select { |iface| !iface.mac.nil? }[0]
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module FogExtensions
|
2
|
+
module Kubevirt
|
3
|
+
module Volume
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
attr_writer :storage_class
|
7
|
+
attr_writer :capacity
|
8
|
+
|
9
|
+
def capacity
|
10
|
+
pvc.requests[:storage] unless pvc.nil?
|
11
|
+
end
|
12
|
+
|
13
|
+
def storage_class
|
14
|
+
pvc&.storage_class
|
15
|
+
end
|
16
|
+
|
17
|
+
def bootable
|
18
|
+
boot_order == 1
|
19
|
+
end
|
20
|
+
|
21
|
+
def id
|
22
|
+
name
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|