From 812ddda79e91bec6de0637ea890e9d6ab09df0ca Mon Sep 17 00:00:00 2001 From: Tim Smith Date: Thu, 29 Nov 2018 16:01:19 -0800 Subject: bsd virtualization: Detect amazonec2 hypervisor + kvm without dmidecode Refactor a chunk of code. There's no need to split the sysctl output since it's just a single line. There's also a ton of repetition in how we detect guests from sysctl kernel data. Add KVM and amazonec2 detection there. Signed-off-by: Tim Smith --- lib/ohai/plugins/bsd/virtualization.rb | 42 +++++---- spec/unit/plugins/bsd/virtualization_spec.rb | 125 +++++++++++++-------------- 2 files changed, 80 insertions(+), 87 deletions(-) diff --git a/lib/ohai/plugins/bsd/virtualization.rb b/lib/ohai/plugins/bsd/virtualization.rb index 5687f641..f6913340 100644 --- a/lib/ohai/plugins/bsd/virtualization.rb +++ b/lib/ohai/plugins/bsd/virtualization.rb @@ -1,7 +1,7 @@ # # Author:: Bryan McLellan (btm@loftninjas.org) # Copyright:: Copyright (c) 2009 Bryan McLellan -# Copyright:: Copyright (c) 2015-2016 Chef Software, Inc. +# Copyright:: Copyright (c) 2015-2018 Chef Software, Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -76,7 +76,7 @@ Ohai.plugin(:Virtualization) do # Detect KVM/QEMU paravirt guests from cpu, report as KVM # hw.model: QEMU Virtual CPU version 0.9.1 so = shell_out("sysctl -n hw.model") - if so.stdout.split($/)[0] =~ /QEMU Virtual CPU|Common KVM processor|Common 32-bit KVM processor/ + if so.stdout =~ /QEMU Virtual CPU|KVM processor/ virtualization[:system] = "kvm" virtualization[:role] = "guest" virtualization[:systems][:kvm] = "guest" @@ -87,27 +87,25 @@ Ohai.plugin(:Virtualization) do # there are a limited number of hypervisors detected here, BUT it doesn't # require dmidecode to be installed and dmidecode isn't in freebsd out of the box so = shell_out("sysctl -n kern.vm_guest") - case so.stdout - when /vmware/ - virtualization[:system] = "vmware" - virtualization[:role] = "guest" - virtualization[:systems][:vmware] = "guest" - logger.trace("Plugin Virtualization: Guest running on VMware detected") - when /hv/ - virtualization[:system] = "hyperv" - virtualization[:role] = "guest" - virtualization[:systems][:hyperv] = "guest" - logger.trace("Plugin Virtualization: Guest running on Hyper-V detected") - when /xen/ - virtualization[:system] = "xen" - virtualization[:role] = "guest" - virtualization[:systems][:xen] = "guest" - logger.trace("Plugin Virtualization: Guest running on Xen detected") - when /bhyve/ - virtualization[:system] = "bhyve" + hypervisor = case so.stdout + when /vmware/ + "vmware" + when /hv/ + "hyperv" + when /xen/ + "xen" + when /kvm/ + so = shell_out("sysctl -n kern.hostuuid") + so.stdout =~ /^ec2/ ? "amazonec2" : "kvm" + when /bhyve/ + "bhyve" + end + + if hypervisor + virtualization[:system] = hypervisor virtualization[:role] = "guest" - virtualization[:systems][:bhyve] = "guest" - logger.trace("Plugin Virtualization: Guest running on bhyve detected") + virtualization[:systems][hypervisor.to_sym] = "guest" + logger.trace("Plugin Virtualization: Guest running on #{hypervisor} detected") end # parse dmidecode to discover various virtualization guests diff --git a/spec/unit/plugins/bsd/virtualization_spec.rb b/spec/unit/plugins/bsd/virtualization_spec.rb index 1a28f601..584915e0 100644 --- a/spec/unit/plugins/bsd/virtualization_spec.rb +++ b/spec/unit/plugins/bsd/virtualization_spec.rb @@ -1,6 +1,6 @@ # # Author:: Bryan McLellan -# Copyright:: Copyright (c) 2012-2016 Chef Software, Inc. +# Copyright:: Copyright (c) 2012-2018 Chef Software, Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,54 +19,56 @@ require_relative "../../../spec_helper.rb" describe Ohai::System, "BSD virtualization plugin" do + let(:plugin) { get_plugin("bsd/virtualization") } + before(:each) do - @plugin = get_plugin("bsd/virtualization") - allow(@plugin).to receive(:collect_os).and_return(:freebsd) - allow(@plugin).to receive(:shell_out).with("sysctl -n security.jail.jailed").and_return(mock_shell_out(0, "0", "")) - allow(@plugin).to receive(:shell_out).with((Ohai.abs_path( "/sbin/kldstat" )).to_s).and_return(mock_shell_out(0, "", "")) - allow(@plugin).to receive(:shell_out).with("jls -nd").and_return(mock_shell_out(0, "", "")) - allow(@plugin).to receive(:shell_out).with("sysctl -n hw.model").and_return(mock_shell_out(0, "", "")) - allow(@plugin).to receive(:shell_out).with("sysctl -n kern.vm_guest").and_return(mock_shell_out(0, "", "")) + allow(plugin).to receive(:collect_os).and_return(:freebsd) + allow(plugin).to receive(:shell_out).with("sysctl -n security.jail.jailed").and_return(mock_shell_out(0, "0", "")) + allow(plugin).to receive(:shell_out).with((Ohai.abs_path( "/sbin/kldstat" )).to_s).and_return(mock_shell_out(0, "", "")) + allow(plugin).to receive(:shell_out).with("jls -nd").and_return(mock_shell_out(0, "", "")) + allow(plugin).to receive(:shell_out).with("sysctl -n hw.model").and_return(mock_shell_out(0, "", "")) + allow(plugin).to receive(:shell_out).with("sysctl -n kern.vm_guest").and_return(mock_shell_out(0, "", "")) + allow(plugin).to receive(:shell_out).with("sysctl -n kern.hostuuid").and_return(mock_shell_out(0, "", "")) allow(File).to receive(:exist?).and_return false end context "when on a bhyve host" do it "detects we are a host" do allow(File).to receive(:exist?).with("/dev/vmm").and_return true - @plugin.run - expect(@plugin[:virtualization][:system]).to eq("bhyve") - expect(@plugin[:virtualization][:role]).to eq("host") - expect(@plugin[:virtualization][:systems][:bhyve]).to eq("host") + plugin.run + expect(plugin[:virtualization][:system]).to eq("bhyve") + expect(plugin[:virtualization][:role]).to eq("host") + expect(plugin[:virtualization][:systems][:bhyve]).to eq("host") end end context "when on a bhyve guest" do it "detects we are a guest" do - allow(@plugin).to receive(:shell_out).with("sysctl -n kern.vm_guest").and_return(mock_shell_out(0, "bhyve", "")) - @plugin.run - expect(@plugin[:virtualization][:system]).to eq("bhyve") - expect(@plugin[:virtualization][:role]).to eq("guest") - expect(@plugin[:virtualization][:systems][:bhyve]).to eq("guest") + allow(plugin).to receive(:shell_out).with("sysctl -n kern.vm_guest").and_return(mock_shell_out(0, "bhyve", "")) + plugin.run + expect(plugin[:virtualization][:system]).to eq("bhyve") + expect(plugin[:virtualization][:role]).to eq("guest") + expect(plugin[:virtualization][:systems][:bhyve]).to eq("guest") end end context "jails" do it "detects we are in a jail" do - allow(@plugin).to receive(:shell_out).with("sysctl -n security.jail.jailed").and_return(mock_shell_out(0, "1", "")) - @plugin.run - expect(@plugin[:virtualization][:system]).to eq("jail") - expect(@plugin[:virtualization][:role]).to eq("guest") - expect(@plugin[:virtualization][:systems][:jail]).to eq("guest") + allow(plugin).to receive(:shell_out).with("sysctl -n security.jail.jailed").and_return(mock_shell_out(0, "1", "")) + plugin.run + expect(plugin[:virtualization][:system]).to eq("jail") + expect(plugin[:virtualization][:role]).to eq("guest") + expect(plugin[:virtualization][:systems][:jail]).to eq("guest") end it "detects we are hosting jails" do # from http://www.freebsd.org/doc/handbook/jails-application.html @jails = "JID IP Address Hostname Path\n 3 192.168.3.17 ns.example.org /home/j/ns\n 2 192.168.3.18 mail.example.org /home/j/mail\n 1 62.123.43.14 www.example.org /home/j/www" - allow(@plugin).to receive(:shell_out).with("jls -nd").and_return(mock_shell_out(0, @jails, "")) - @plugin.run - expect(@plugin[:virtualization][:system]).to eq("jail") - expect(@plugin[:virtualization][:role]).to eq("host") - expect(@plugin[:virtualization][:systems][:jail]).to eq("host") + allow(plugin).to receive(:shell_out).with("jls -nd").and_return(mock_shell_out(0, @jails, "")) + plugin.run + expect(plugin[:virtualization][:system]).to eq("jail") + expect(plugin[:virtualization][:role]).to eq("host") + expect(plugin[:virtualization][:systems][:jail]).to eq("host") end end @@ -77,14 +79,14 @@ describe Ohai::System, "BSD virtualization plugin" do 1 40 0xffffffff80100000 d20428 kernel 7 3 0xffffffff81055000 41e88 vboxguest.ko OUT - allow(@plugin).to receive(:shell_out).with((Ohai.abs_path("/sbin/kldstat")).to_s).and_return(mock_shell_out(0, @vbox_guest, "")) + allow(plugin).to receive(:shell_out).with((Ohai.abs_path("/sbin/kldstat")).to_s).and_return(mock_shell_out(0, @vbox_guest, "")) end it "detects we are a guest" do - @plugin.run - expect(@plugin[:virtualization][:system]).to eq("vbox") - expect(@plugin[:virtualization][:role]).to eq("guest") - expect(@plugin[:virtualization][:systems][:vbox]).to eq("guest") + plugin.run + expect(plugin[:virtualization][:system]).to eq("vbox") + expect(plugin[:virtualization][:role]).to eq("guest") + expect(plugin[:virtualization][:systems][:vbox]).to eq("guest") end end @@ -95,56 +97,49 @@ OUT 1 40 0xffffffff80100000 d20428 kernel 7 3 0xffffffff81055000 41e88 vboxdrv.ko OUT - allow(@plugin).to receive(:shell_out).with("/sbin/kldstat").and_return(mock_shell_out(0, @stdout, "")) + allow(plugin).to receive(:shell_out).with("/sbin/kldstat").and_return(mock_shell_out(0, @stdout, "")) end it "detects we are a host" do - @plugin.run - expect(@plugin[:virtualization][:system]).to eq("vbox") - expect(@plugin[:virtualization][:role]).to eq("host") - expect(@plugin[:virtualization][:systems][:vbox]).to eq("host") + plugin.run + expect(plugin[:virtualization][:system]).to eq("vbox") + expect(plugin[:virtualization][:role]).to eq("host") + expect(plugin[:virtualization][:systems][:vbox]).to eq("host") end end context "when on a QEMU guest" do it "detects we are a guest" do [ "Common KVM processor", 'QEMU Virtual CPU version (cpu64-rhel6) ("GenuineIntel" 686-class)', "Common 32-bit KVM processor"].each do |kvm_string| - allow(@plugin).to receive(:shell_out).with("sysctl -n hw.model").and_return(mock_shell_out(0, kvm_string, "")) - @plugin.run - expect(@plugin[:virtualization][:system]).to eq("kvm") - expect(@plugin[:virtualization][:role]).to eq("guest") - expect(@plugin[:virtualization][:systems][:kvm]).to eq("guest") + allow(plugin).to receive(:shell_out).with("sysctl -n hw.model").and_return(mock_shell_out(0, kvm_string, "")) + 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 end end - context "when on a xen guest" do - it "detects we are a guest" do - allow(@plugin).to receive(:shell_out).with("sysctl -n kern.vm_guest").and_return(mock_shell_out(0, "xen", "")) - @plugin.run - expect(@plugin[:virtualization][:system]).to eq("xen") - expect(@plugin[:virtualization][:role]).to eq("guest") - expect(@plugin[:virtualization][:systems][:xen]).to eq("guest") - end - end - - context "when on a vmware guest" do - it "detects we are a guest" do - allow(@plugin).to receive(:shell_out).with("sysctl -n kern.vm_guest").and_return(mock_shell_out(0, "vmware", "")) - @plugin.run - expect(@plugin[:virtualization][:system]).to eq("vmware") - expect(@plugin[:virtualization][:role]).to eq("guest") - expect(@plugin[:virtualization][:systems][:vmware]).to eq("guest") + { xen: "xen", vmware: "vmware", hyperv: "hv", kvm: "kvm", bhyve: "bhyve" }.each_pair do |hypervisor, val| + context "when on a #{hypervisor} guest" do + it "detects we are a guest" do + allow(plugin).to receive(:shell_out).with("sysctl -n kern.vm_guest").and_return(mock_shell_out(0, val, "")) + plugin.run + expect(plugin[:virtualization][:system]).to eq(hypervisor.to_s) + expect(plugin[:virtualization][:role]).to eq("guest") + expect(plugin[:virtualization][:systems][hypervisor]).to eq("guest") + end end end - context "when on a hyper-v guest" do + context "when on an amazonec2 guest" do it "detects we are a guest" do - allow(@plugin).to receive(:shell_out).with("sysctl -n kern.vm_guest").and_return(mock_shell_out(0, "hv", "")) - @plugin.run - expect(@plugin[:virtualization][:system]).to eq("hyperv") - expect(@plugin[:virtualization][:role]).to eq("guest") - expect(@plugin[:virtualization][:systems][:hyperv]).to eq("guest") + allow(plugin).to receive(:shell_out).with("sysctl -n kern.vm_guest").and_return(mock_shell_out(0, "kvm", "")) + allow(plugin).to receive(:shell_out).with("sysctl -n kern.hostuuid").and_return(mock_shell_out(0, "ec2fb75c-7a36-7938-4efa-8e40b4ac634b", "")) + plugin.run + expect(plugin[:virtualization][:system]).to eq("amazonec2") + expect(plugin[:virtualization][:role]).to eq("guest") + expect(plugin[:virtualization][:systems][:amazonec2]).to eq("guest") end end end -- cgit v1.2.1