Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Detect Openstack hosts #751

Merged
merged 7 commits into from
Mar 9, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 28 additions & 16 deletions lib/ohai/plugins/linux/virtualization.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,14 @@ def docker_exists?
which("docker")
end

def nova_exists?
which("nova")
end

collect_data(:linux) do
virtualization Mash.new unless virtualization
virtualization[:systems] = Mash.new unless virtualization[:systems]

# if it is possible to detect paravirt vs hardware virt, it should be put in
# virtualization[:mechanism]

## Xen
# /proc/xen is an empty dir for EL6 + Linode Guests + Paravirt EC2 instances
if File.exist?("/proc/xen")
Expand All @@ -60,18 +61,13 @@ def docker_exists?
# Xen Notes:
# - cpuid of guests, if we could get it, would also be a clue
# - may be able to determine if under paravirt from /dev/xen/evtchn (See OHAI-253)
# - EL6 guests carry a 'hypervisor' cpu flag
# - Additional edge cases likely should not change the above assumptions
# but rather be additive - btm

# Detect from kernel module
# Detect Virtualbox from kernel module
if File.exist?("/proc/modules")
modules = File.read("/proc/modules")
if modules =~ /^kvm/
virtualization[:system] = "kvm"
virtualization[:role] = "host"
virtualization[:systems][:kvm] = "host"
elsif modules =~ /^vboxdrv/
if modules =~ /^vboxdrv/
virtualization[:system] = "vbox"
virtualization[:role] = "host"
virtualization[:systems][:vbox] = "host"
Expand All @@ -82,11 +78,14 @@ def docker_exists?
end
end

# Detect KVM/QEMU from cpuinfo, report as KVM
# We could pick KVM from 'Booting paravirtualized kernel on KVM' in dmesg
# 2.6.27-9-server (intrepid) has this / 2.6.18-6-amd64 (etch) does not
# It would be great if we could read pv_info in the kernel
# Wait for reply to: http://article.gmane.org/gmane.comp.emulators.kvm.devel/27885
# if nova binary is present we're on an openstack host
if nova_exists?
virtualization[:system] = "openstack"
virtualization[:role] = "host"
virtualization[:systems][:openstack] = "host"
end

# Detect paravirt KVM/QEMU from cpuinfo, report as KVM
if File.exist?("/proc/cpuinfo")
if File.read("/proc/cpuinfo") =~ /QEMU Virtual CPU|Common KVM processor|Common 32-bit KVM processor/
virtualization[:system] = "kvm"
Expand All @@ -95,6 +94,19 @@ def docker_exists?
end
end

# Detect KVM systems via /sys
# guests will have the hypervisor cpu feature that hosts don't have
if File.exist?("/sys/devices/virtual/misc/kvm")
virtualization[:system] = "kvm"
if File.read("/proc/cpuinfo") =~ /hypervisor/
virtualization[:role] = "guest"
virtualization[:systems][:kvm] = "guest"
else
virtualization[:role] = "host"
virtualization[:systems][:kvm] = "host"
end
end

# Detect OpenVZ / Virtuozzo.
# http://wiki.openvz.org/BC_proc_entries
if File.exist?("/proc/bc/0")
Expand Down Expand Up @@ -163,7 +175,7 @@ def docker_exists?
if File.exist?("/proc/self/cgroup")
cgroup_content = File.read("/proc/self/cgroup")
if cgroup_content =~ %r{^\d+:[^:]+:/(lxc|docker)/.+$} ||
cgroup_content =~ %r{^\d+:[^:]+:/[^/]+/(lxc|docker)-.+$}
cgroup_content =~ %r{^\d+:[^:]+:/[^/]+/(lxc|docker)-.+$}
virtualization[:system] = $1
virtualization[:role] = "guest"
virtualization[:systems][$1.to_sym] = "guest"
Expand Down
6 changes: 5 additions & 1 deletion lib/ohai/util/file_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,12 @@ def which(cmd)
paths = ENV["PATH"].split(File::PATH_SEPARATOR) + [ "/bin", "/usr/bin", "/sbin", "/usr/sbin" ]
paths.each do |path|
filename = File.join(path, cmd)
return filename if File.executable?(filename)
if File.executable?(filename)
Ohai::Log.debug("#{self.name} plugin: found #{cmd} at #{filename}")
return filename
end
end
Ohai::Log.debug("#{self.name} plugin: did not find #{cmd}")
false
end
end
Expand Down
31 changes: 28 additions & 3 deletions spec/unit/plugins/linux/virtualization_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@
allow(File).to receive(:exist?).with("/.dockerenv").and_return(false)
allow(File).to receive(:exist?).with("/.dockerinit").and_return(false)
allow(File).to receive(:exist?).with("/proc/bus/pci/devices").and_return(false)
allow(File).to receive(:exist?).with("/sys/devices/virtual/misc/kvm").and_return(false)

# default the which wrappers to nil
allow(plugin).to receive(:lxc_version_exists?).and_return(false)
allow(plugin).to receive(:docker_exists?).and_return(false)
allow(plugin).to receive(:nova_exists?).and_return(false)
end

describe "when we are checking for xen" do
Expand Down Expand Up @@ -76,10 +82,29 @@
end
end

describe "when we are checking for openstack" do
it "sets openstack host if nova binary exists" do
allow(plugin).to receive(:nova_exists?).and_return("/usr/bin/nova")
plugin.run
expect(plugin[:virtualization][:system]).to eq("openstack")
expect(plugin[:virtualization][:role]).to eq("host")
expect(plugin[:virtualization][:systems][:openstack]).to eq("host")
end
end

describe "when we are checking for kvm" do
it "sets kvm host if /proc/modules contains kvm" do
expect(File).to receive(:exist?).with("/proc/modules").and_return(true)
allow(File).to receive(:read).with("/proc/modules").and_return("kvm 165872 1 kvm_intel")
it "sets kvm guest if /sys/devices/virtual/misc/kvm exists & hypervisor cpu feature is present" do
allow(File).to receive(:exist?).with("/sys/devices/virtual/misc/kvm").and_return(true)
allow(File).to receive(:read).with("/proc/cpuinfo").and_return("fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss syscall nx rdtscp lm constant_tsc arch_perfmon rep_good nopl pni vmx ssse3 cx16 sse4_1 sse4_2 x2apic popcnt hypervisor lahf_lm vnmi ept tsc_adjust")
plugin.run
expect(plugin[:virtualization][:system]).to eq("kvm")
expect(plugin[:virtualization][:role]).to eq("guest")
expect(plugin[:virtualization][:systems][:kvm]).to eq("guest")
end

it "sets kvm host if /sys/devices/virtual/misc/kvm exists & hypervisor cpu feature is not present" do
allow(File).to receive(:exist?).with("/sys/devices/virtual/misc/kvm").and_return(true)
allow(File).to receive(:read).with("/proc/cpuinfo").and_return("fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf pni dtes64 monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr pdcm dca sse4_1 sse4_2 popcnt lahf_lm ida dtherm tpr_shadow vnmi flexpriority ept vpid")
plugin.run
expect(plugin[:virtualization][:system]).to eq("kvm")
expect(plugin[:virtualization][:role]).to eq("host")
Expand Down
1 change: 1 addition & 0 deletions spec/unit/util/file_helper_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class FileHelperMock
let(:file_helper) { FileHelperMock.new }

before(:each) do
allow(file_helper).to receive(:name).and_return("Fakeclass")
allow(File).to receive(:executable?).and_return(false)
end

Expand Down