Skip to content
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
35 changes: 34 additions & 1 deletion lib/ohai/mixin/oci_metadata.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,39 @@ module OCIMetadata
OCI_METADATA_URL = "/opc/v2"
CHASSIS_ASSET_TAG_FILE = "/sys/devices/virtual/dmi/id/chassis_asset_tag"

# Get the chassis asset tag from DMI information
# On Linux: reads from sysfs
# On Windows: queries WMI Win32_SystemEnclosure
def chassis_asset_tag
if RUBY_PLATFORM =~ /mswin|mingw|windows/
get_chassis_asset_tag_windows
else
get_chassis_asset_tag_linux
end
end

# Read chassis asset tag from Linux sysfs
def get_chassis_asset_tag_linux
return unless ::File.exist?(CHASSIS_ASSET_TAG_FILE)

::File.read(CHASSIS_ASSET_TAG_FILE).strip
rescue => e
logger.debug("Mixin OciMetadata: Failed to read chassis asset tag from #{CHASSIS_ASSET_TAG_FILE}: #{e}")
nil
end

# Read chassis asset tag from Windows WMI
def get_chassis_asset_tag_windows
require "wmi-lite/wmi" unless defined?(WmiLite::Wmi)

wmi = WmiLite::Wmi.new
enclosure = wmi.first_of("Win32_SystemEnclosure")
enclosure&.[]("SMBIOSAssetTag")
rescue => e
logger.debug("Mixin OciMetadata: Failed to read chassis asset tag from WMI: #{e}")
nil
end

# fetch the meta content with a timeout and the required header
def http_get(uri)
conn = Net::HTTP.start(OCI_METADATA_ADDR)
Expand All @@ -51,7 +84,7 @@ def fetch_metadata(metadata = "instance")
end
json_data
else
logger.warn("Mixin OciMetadata: Received response code #{response.code} requesting metadata")
logger.debug("Mixin OciMetadata: Received response code #{response.code} requesting #{metadata}")
nil
end
end
Expand Down
30 changes: 15 additions & 15 deletions lib/ohai/plugins/oci.rb
Original file line number Diff line number Diff line change
Expand Up @@ -44,24 +44,22 @@
end

def oci_chassis_asset_tag?
has_oci_chassis_asset_tag = false
if file_exist?(Ohai::Mixin::OCIMetadata::CHASSIS_ASSET_TAG_FILE)
file_open(Ohai::Mixin::OCIMetadata::CHASSIS_ASSET_TAG_FILE).each do |line|
next unless /OracleCloud.com/.match?(line)

logger.trace("Plugin oci: Found OracleCloud.com chassis_asset_tag used by oci.")
has_oci_chassis_asset_tag = true
break
end
asset_tag = chassis_asset_tag
return false if asset_tag.nil? || asset_tag.empty?

if /OracleCloud.com/.match?(asset_tag)
logger.trace("Plugin oci: Found OracleCloud.com chassis_asset_tag used by oci.")
true
else
false
end
has_oci_chassis_asset_tag
end

def parse_metadata
return nil unless can_socket_connect?(Ohai::Mixin::OCIMetadata::OCI_METADATA_ADDR, 80)
return unless can_socket_connect?(Ohai::Mixin::OCIMetadata::OCI_METADATA_ADDR, 80)

instance_data = fetch_metadata("instance")
return nil if instance_data.nil?
return if instance_data.nil?

metadata = Mash.new
metadata["compute"] = Mash.new
Expand All @@ -80,12 +78,14 @@ def parse_metadata
end
end

volume_attachments_data = fetch_metadata("volumeAttachments")
volume_attachments_data = fetch_metadata("allVolumeAttachments")

unless volume_attachments_data.nil?
metadata["volumes"] = Mash.new
volume_attachments_data.each do |k, v|
metadata["volumes"][k] = v
volume_attachments_data.each do |v|
if v.is_a?(Hash) && v["id"]
metadata["volumes"][v["id"]] = v
end
end
end

Expand Down
86 changes: 85 additions & 1 deletion spec/unit/mixin/oci_metadata_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
http_mock = double("http", { code: "404" })
allow(mixin).to receive(:http_get).and_return(http_mock)

expect(mixin.logger).to receive(:warn)
expect(mixin.logger).to receive(:debug)
vals = mixin.fetch_metadata
expect(vals).to eq(nil)
end
Expand All @@ -63,4 +63,88 @@
expect(vals).to eq({ "foo" => "bar" })
end
end

describe "#chassis_asset_tag" do
context "on Windows platform" do
before do
stub_const("RUBY_PLATFORM", "mswin")
end

it "calls get_chassis_asset_tag_windows" do
expect(mixin).to receive(:get_chassis_asset_tag_windows).and_return("test-asset-tag")
expect(mixin.chassis_asset_tag).to eq("test-asset-tag")
end
end

context "on non-Windows platform" do
before do
stub_const("RUBY_PLATFORM", "linux")
end

it "calls get_chassis_asset_tag_linux" do
expect(mixin).to receive(:get_chassis_asset_tag_linux).and_return("test-asset-tag")
expect(mixin.chassis_asset_tag).to eq("test-asset-tag")
end
end
end

describe "#get_chassis_asset_tag_linux" do
let(:chassis_file) { Ohai::Mixin::OCIMetadata::CHASSIS_ASSET_TAG_FILE }

it "returns asset tag when file exists and is readable" do
allow(::File).to receive(:exist?).with(chassis_file).and_return(true)
allow(::File).to receive(:read).with(chassis_file).and_return(" OracleCloud.com \n")

expect(mixin.get_chassis_asset_tag_linux).to eq("OracleCloud.com")
end

it "returns nil when file does not exist" do
allow(::File).to receive(:exist?).with(chassis_file).and_return(false)

expect(mixin.get_chassis_asset_tag_linux).to be_nil
end

it "returns nil when file read fails" do
allow(::File).to receive(:exist?).with(chassis_file).and_return(true)
allow(::File).to receive(:read).with(chassis_file).and_raise(Errno::EACCES)

expect(mixin.logger).to receive(:debug).with(/Failed to read chassis asset tag/)
expect(mixin.get_chassis_asset_tag_linux).to be_nil
end
end

describe "#get_chassis_asset_tag_windows" do
let(:wmi_mock) { double("WmiLite::Wmi") }
let(:enclosure_mock) { { "SMBIOSAssetTag" => "OracleCloud.com" } }

before do
allow(mixin).to receive(:require)
stub_const("WmiLite::Wmi", double(new: wmi_mock))
end

it "returns asset tag from WMI when available" do
allow(wmi_mock).to receive(:first_of).with("Win32_SystemEnclosure").and_return(enclosure_mock)

expect(mixin.get_chassis_asset_tag_windows).to eq("OracleCloud.com")
end

it "returns nil when WMI query returns nil" do
allow(wmi_mock).to receive(:first_of).with("Win32_SystemEnclosure").and_return(nil)

expect(mixin.get_chassis_asset_tag_windows).to be_nil
end

it "returns nil when WMI query fails" do
allow(wmi_mock).to receive(:first_of).with("Win32_SystemEnclosure").and_raise(StandardError.new("WMI error"))

expect(mixin.logger).to receive(:debug).with(/Failed to read chassis asset tag from WMI/)
expect(mixin.get_chassis_asset_tag_windows).to be_nil
end

it "returns nil when SMBIOSAssetTag is not present" do
allow(wmi_mock).to receive(:first_of).with("Win32_SystemEnclosure").and_return({})

expect(mixin.get_chassis_asset_tag_windows).to be_nil
end
end
end
39 changes: 29 additions & 10 deletions spec/unit/plugins/oci_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -129,11 +129,7 @@
describe "without oci hint file not in OCI" do
before do
allow(plugin).to receive(:hint?).with("oci").and_return(false)
allow(plugin).to receive(:file_exist?).with(Ohai::Mixin::OCIMetadata::CHASSIS_ASSET_TAG_FILE).and_return(true)
@double_file = double(Ohai::Mixin::OCIMetadata::CHASSIS_ASSET_TAG_FILE)
allow(@double_file).to receive(:each)
.and_yield("")
allow(plugin).to receive(:file_open).with(Ohai::Mixin::OCIMetadata::CHASSIS_ASSET_TAG_FILE).and_return(@double_file)
allow(plugin).to receive(:chassis_asset_tag).and_return("")
end

it_behaves_like "!oci"
Expand All @@ -142,11 +138,7 @@
describe "without oci hint file in OCI" do
before do
allow(plugin).to receive(:hint?).with("oci").and_return(false)
allow(plugin).to receive(:file_exist?).with(Ohai::Mixin::OCIMetadata::CHASSIS_ASSET_TAG_FILE).and_return(true)
@double_file = double(Ohai::Mixin::OCIMetadata::CHASSIS_ASSET_TAG_FILE)
allow(@double_file).to receive(:each)
.and_yield("OracleCloud.com")
allow(plugin).to receive(:file_open).with(Ohai::Mixin::OCIMetadata::CHASSIS_ASSET_TAG_FILE).and_return(@double_file)
allow(plugin).to receive(:chassis_asset_tag).and_return("OracleCloud.com")
end

it_behaves_like "oci"
Expand Down Expand Up @@ -195,4 +187,31 @@
expect(plugin[:oci][:metadata][:network][:interface][0][:privateIp]).to eq("10.0.3.6")
end
end

describe "#oci_chassis_asset_tag?" do
it "returns true when chassis asset tag contains OracleCloud.com" do
allow(plugin).to receive(:chassis_asset_tag).and_return("OracleCloud.com")
expect(plugin.oci_chassis_asset_tag?).to be true
end

it "returns false when chassis asset tag is nil" do
allow(plugin).to receive(:chassis_asset_tag).and_return(nil)
expect(plugin.oci_chassis_asset_tag?).to be false
end

it "returns false when chassis asset tag is empty" do
allow(plugin).to receive(:chassis_asset_tag).and_return("")
expect(plugin.oci_chassis_asset_tag?).to be false
end

it "returns false when chassis asset tag does not contain OracleCloud.com" do
allow(plugin).to receive(:chassis_asset_tag).and_return("SomeOtherTag")
expect(plugin.oci_chassis_asset_tag?).to be false
end

it "returns true when chassis asset tag contains OracleCloud.com with extra content" do
allow(plugin).to receive(:chassis_asset_tag).and_return("prefix OracleCloud.com suffix")
expect(plugin.oci_chassis_asset_tag?).to be true
end
end
end