This repository has been archived by the owner on Dec 7, 2022. It is now read-only.
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
362 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
What? | ||
===== | ||
|
||
Basic management of Libvirt Hypervisors and domains | ||
|
||
Usage? | ||
====== | ||
|
||
There isn't a bundled application, it works fine through the normal RPC client: | ||
|
||
Hypervisor Information: | ||
----------------------- | ||
<pre> | ||
% mco rpc libvirt hvinfo | ||
|
||
kvm1.xx.net | ||
Inactive Domains: [] | ||
Type: QEMU | ||
Sockets: 1 | ||
Max VCPUs: 16 | ||
Cores: 2 | ||
Model: x86_64 | ||
URI: qemu:///system | ||
Version: 12001 | ||
Memory: 8063656 | ||
Numa Nodes: 1 | ||
Free Memory: 2292154368 | ||
CPUs: 2 | ||
Active Domains: ["dev2_devco", "dev4_devco", "dev5_devco", "dev3_devco"] | ||
MHz: 1297 | ||
Threads: 1 | ||
|
||
Finished processing 1 / 1 hosts in 103.90 ms | ||
</pre> | ||
|
||
Domain Information: | ||
------------------- | ||
|
||
<pre> | ||
% mco rpc libvirt domaininfo domain=dev2_devco | ||
|
||
kvm1.xx.net | ||
State: 1 | ||
State: Running | ||
UUID: fd402bc2-9207-fb2a-d650-a3ba85214578 | ||
Autostart: true | ||
Memory: 524288 | ||
VCPUs: 1 | ||
Max Memory: 524288 | ||
CPU Time: 29540000000 | ||
|
||
Finished processing 1 / 1 hosts in 92.90 ms | ||
</pre> | ||
|
||
Manage a Domain: | ||
---------------- | ||
|
||
<pre> | ||
% mco rpc libvirt destroy domain=dev4_devco | ||
|
||
kvm1.xx.net | ||
State: 5 | ||
State: Shut off | ||
|
||
Finished processing 1 / 1 hosts in 320.48 ms | ||
</pre> | ||
|
||
Other available actions are: | ||
|
||
* create / start | ||
* destroy | ||
* resume | ||
* shutdown | ||
* suspend | ||
|
||
Todo? | ||
==== | ||
|
||
* Make the hypervisor URL configurable, atm only QEMU and only unauthenticated | ||
* Expose more hypervisor information like device lists, network lists, storage lists etc | ||
* Allow for creation using provided XML | ||
* More stats so that full feature auto provisioning can be built | ||
|
||
Contact? | ||
======== | ||
|
||
R.I.Pienaar / rip@devco.net / http://devco.net / @ripienaar |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,154 @@ | ||
metadata :name => "libvirt", | ||
:description => "SimpleRPC Libvirt Agent", | ||
:author => "R.I.Pienaar <rip@devco.net>", | ||
:license => "ASL2.0", | ||
:version => "0.1", | ||
:url => "http://devco.net/", | ||
:timeout => 10 | ||
|
||
action "hvinfo", :description => "Hypervisor Information" do | ||
display :always | ||
|
||
output :model, | ||
:description => "Hypervisor Model", | ||
:display_as => "Model" | ||
|
||
output :memory, | ||
:description => "Hypervisor Total Memory", | ||
:display_as => "Memory" | ||
|
||
output :cpus, | ||
:description => "Number of CPUs", | ||
:display_as => "CPUs" | ||
|
||
output :mhz, | ||
:description => "CPU Clock Frequency", | ||
:display_as => "MHz" | ||
|
||
output :nodes, | ||
:description => "Number of NUMA Nodes", | ||
:display_as => "Numa Nodes" | ||
|
||
output :sockets, | ||
:description => "CPU Sockets", | ||
:display_as => "Sockets" | ||
|
||
output :cores, | ||
:description => "CPU Cores", | ||
:display_as => "Cores" | ||
|
||
output :threads, | ||
:description => "CPU Threads", | ||
:display_as => "Threads" | ||
|
||
output :type, | ||
:description => "Hypervisor Type", | ||
:display_as => "Type" | ||
|
||
output :version, | ||
:description => "Hypervisor Version", | ||
:display_as => "Version" | ||
|
||
output :uri, | ||
:description => "Hypervisor URI", | ||
:display_as => "URI" | ||
|
||
output :node_free_memory, | ||
:description => "Total Free Memory", | ||
:display_as => "Free Memory" | ||
|
||
output :active_domains, | ||
:description => "Active Domains", | ||
:display_as => "Active Domains" | ||
|
||
output :inactive_domains, | ||
:description => "Inactive Domains", | ||
:display_as => "Inactive Domains" | ||
|
||
output :max_vcpus, | ||
:description => "Maximum virtual CPUs", | ||
:display_as => "Max VCPUs" | ||
end | ||
|
||
action "domaininfo", :description => "Domain Information" do | ||
display :always | ||
|
||
input :domain, | ||
:prompt => "Domain Name", | ||
:description => "Name of a defined domain", | ||
:type => :string, | ||
:validation => '^.+$', | ||
:optional => false, | ||
:maxlength => 50 | ||
|
||
output :autostart, | ||
:description => "Will the domain auto start", | ||
:display_as => "Autostart" | ||
|
||
output :vcpus, | ||
:description => "Number of Virtual CPUs", | ||
:display_as => "VCPUs" | ||
|
||
output :memory, | ||
:description => "Current Memory", | ||
:display_as => "Memory" | ||
|
||
output :max_memory, | ||
:description => "Maximum Memory", | ||
:display_as => "Max Memory" | ||
|
||
output :cputime, | ||
:description => "CPU Time", | ||
:display_as => "CPU Time" | ||
|
||
output :state, | ||
:description => "Domain State", | ||
:display_as => "State" | ||
|
||
output :state_description, | ||
:description => "Domain State", | ||
:display_as => "State" | ||
|
||
output :uuid, | ||
:description => "Domain UUID", | ||
:display_as => "UUID" | ||
end | ||
|
||
action "domainxml", :description => "Retrieve the full libvirt XML description for a domain" do | ||
display :always | ||
|
||
input :domain, | ||
:prompt => "Domain Name", | ||
:description => "Name of a defined domain", | ||
:type => :string, | ||
:validation => '^.+$', | ||
:optional => false, | ||
:maxlength => 50 | ||
|
||
output :xml, | ||
:description => "Domain XML", | ||
:display_as => "XML" | ||
end | ||
|
||
[:destroy, :shutdown, :suspend, :resume, :create, :start].each do |act| | ||
action act.to_s, :description => "#{act.to_s.capitalize} a domain" do | ||
display :always | ||
|
||
input :domain, | ||
:prompt => "Domain Name", | ||
:description => "Name of a defined domain", | ||
:type => :string, | ||
:validation => '^.+$', | ||
:optional => false, | ||
:maxlength => 50 | ||
|
||
output :state, | ||
:description => "Domain State", | ||
:display_as => "State" | ||
|
||
output :state_description, | ||
:description => "Domain State", | ||
:display_as => "State" | ||
|
||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
module MCollective | ||
module Agent | ||
class Libvirt<RPC::Agent | ||
require 'libvirt' | ||
|
||
metadata :name => "libvirt", | ||
:description => "SimpleRPC Libvirt Agent", | ||
:author => "R.I.Pienaar <rip@devco.net>", | ||
:license => "ASL2.0", | ||
:version => "0.1", | ||
:url => "http://devco.net/", | ||
:timeout => 10 | ||
|
||
action "hvinfo" do | ||
conn = connect | ||
|
||
nodeinfo = conn.node_get_info | ||
|
||
[:model, :memory, :cpus, :mhz, :nodes, :sockets, :cores, :threads].each do |i| | ||
reply[i] = nodeinfo.send(i) | ||
end | ||
|
||
[:type, :version, :uri, :node_free_memory, :max_vcpus].each do |i| | ||
reply[i] = conn.send(i) | ||
end | ||
|
||
reply[:active_domains] = [] | ||
conn.list_domains.each do |domain| | ||
reply[:active_domains] << conn.lookup_domain_by_id(domain).name | ||
end | ||
reply[:active_domains].sort! | ||
|
||
reply[:inactive_domains] = conn.list_defined_domains.sort | ||
|
||
conn.close | ||
end | ||
|
||
action "domaininfo" do | ||
validate :domain, String | ||
|
||
conn = connect | ||
|
||
begin | ||
domain = conn.lookup_domain_by_name(request[:domain]) | ||
info = domain.info | ||
|
||
reply[:autostart] = domain.autostart? | ||
reply[:vcpus] = info.nr_virt_cpu | ||
reply[:memory] = info.memory | ||
reply[:max_memory] = info.max_mem | ||
reply[:cputime] = info.cpu_time | ||
reply[:state] = info.state | ||
reply[:state_description] = virtstates[info.state] | ||
reply[:uuid] = domain.uuid | ||
rescue Exception => e | ||
reply.fail! "Could not load domain %s: %s" % [request[:domain], e] | ||
end | ||
|
||
conn.close | ||
end | ||
|
||
action "domainxml" do | ||
validate :domain, String | ||
|
||
conn = connect | ||
|
||
begin | ||
domain = conn.lookup_domain_by_name(request[:domain]) | ||
reply[:xml] = domain.xml_desc | ||
rescue Exception => e | ||
reply.fail! "Could not load domain %s: %s" % [request[:domain], e] | ||
end | ||
|
||
conn.close | ||
end | ||
|
||
[:destroy, :shutdown, :suspend, :resume, :create].each do |act| | ||
action act do | ||
validate :domain, String | ||
|
||
reply[:state] = domain_action(request[:domain], act) | ||
reply[:state_description] = virtstates[reply[:state]] | ||
end | ||
end | ||
|
||
alias :start_action :create_action | ||
|
||
private | ||
def connect | ||
conn = ::Libvirt::open('qemu:///system') | ||
|
||
raise "Could not connect to hypervisor" if conn.closed? | ||
|
||
conn | ||
end | ||
|
||
def virtstates | ||
{0 => "No state", | ||
1 => "Running", | ||
2 => "Blocked on resource", | ||
3 => "Paused", | ||
4 => "Shutting down", | ||
5 => "Shut off", | ||
6 => "Crashed"} | ||
end | ||
|
||
def domain_action(name, action) | ||
conn = connect | ||
|
||
begin | ||
domain = conn.lookup_domain_by_name(name) | ||
domain.send(action.to_sym) | ||
|
||
return domain.info.state | ||
rescue Exception => e | ||
reply.fail! "Could not #{action} domain %s : %s" % [request[:domain], e] | ||
end | ||
end | ||
end | ||
end | ||
end |