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
2 changes: 2 additions & 0 deletions lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ include_directories(inc ${Boost_INCLUDE_DIRS} ${LEATHERMAN_INCLUDE_DIRS})

set(PROJECT_SOURCES
"src/${PROJECT_NAME}.cc"
"src/detectors/metadata.cc"
"src/detectors/result.cc"
"src/detectors/virtualbox_detector.cc"
"src/sources/cpuid_source.cc"
"src/sources/dmi_source.cc")
Expand Down
63 changes: 63 additions & 0 deletions lib/inc/internal/detectors/metadata.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#pragma once

#include <unordered_map>
#include <boost/variant.hpp>

namespace whereami { namespace detectors {

/**
* Metadata values can be string or boolean
*/
using metadata_value = boost::variant<std::string, bool>;

/**
* Metadata container
*/
class metadata
{
public:
/**
* Set a key with a string value using a string
* @param key The key
* @param value The value
*/
void set(std::string const& key, std::string const& value);

/**
* Set a key with a string value using a string literal
* @param key The key
* @param value The value
*/
void set(std::string const& key, const char *value);

/**
* Set a key with a boolean value
* @param key The key
* @param value The value
*/
void set(std::string const& key, bool value);

/**
* Retrieve a metadata value by key
* @tparam T The expected type of the value
* @param key The key
* @return
*/
template<typename T>
T get(std::string const& key) const throw(boost::bad_get)
{
auto it = data_.find(key);
if (it == data_.end()) {
return {};
}
return boost::get<T>((*it).second);
}

protected:
/**
* Metadata key/value map
*/
std::unordered_map <std::string, metadata_value> data_;
};

}} // namespace whereami::detectors
75 changes: 75 additions & 0 deletions lib/inc/internal/detectors/result.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#pragma once

#include <internal/detectors/metadata.hpp>

namespace whereami { namespace detectors {

/**
* Represents the result of a hypervisor detector
*/
class result
{
public:
/**
* Constructs a result given a hypervisor name
* @param name The name of the hypervisor this result represents
*/
result(std::string const& name): name_(name) {}

/**
* Retrieves the name of the hypervisor
* @return Returns name of the hypervisor
*/
std::string name() const;

/**
* Reports whether the hypervisor was detected
* @return Returns true if the hypervisor was detected
*/
bool valid() const;

/**
* Marks the result as having successfully detected the hypervisor
*/
void validate();

/**
* Sets a metadata key and value
* @tparam T The type of the value
* @param key The key
* @param value The value
*/
template<typename T>
void set(std::string const& key, T&& value)
{
metadata_.set(key, std::forward<T>(value));
}

/**
* Retrieves a metadata value by key
* @tparam T The expected type of the value
* @param key The key
* @return Returns the value
*/
template<typename T>
T get(std::string const& key) const throw(boost::bad_get)
{
return metadata_.get<T>(key);
}

protected:
/**
* The name of the hypervisor this result respresents
*/
std::string name_;
/**
* Whether this hypervisor has been detected
*/
bool valid_ = false;
/**
* Metadata about the hypervisor
*/
metadata metadata_;
};

}}; // namespace whereami::detectors
5 changes: 3 additions & 2 deletions lib/inc/internal/detectors/virtualbox_detector.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#pragma once

#include <internal/detectors/result.hpp>
#include <internal/sources/dmi_source.hpp>
#include <internal/sources/cpuid_source.hpp>

Expand All @@ -11,7 +12,7 @@ namespace whereami { namespace detectors {
* @param dmi_source An instance of a DMI data source
* @return Whether this machine is a VirtualBox guest
*/
bool virtualbox(const sources::cpuid_base& cpuid_source,
const sources::dmi_base& dmi_source);
result virtualbox(const sources::cpuid_base& cpuid_source,
const sources::dmi_base& dmi_source);

}} // namespace whereami::detectors
11 changes: 11 additions & 0 deletions lib/inc/internal/sources/dmi_source.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include <memory>
#include <string>
#include <vector>

namespace whereami { namespace sources {

Expand Down Expand Up @@ -35,6 +36,11 @@ namespace whereami { namespace sources {
* via /sys/class/dmi/id/product_name or dmidecode section 1 product name
*/
std::string product_name;
/**
* OEM strings
* Only available via dmidecode section 11 (requires root)
*/
std::vector<std::string> oem_strings;
};

/**
Expand Down Expand Up @@ -70,6 +76,11 @@ namespace whereami { namespace sources {
* @return The product name
*/
std::string product_name() const;
/**
* Retrieve any OEM strings
* @return A vector of OEM strings
*/
std::vector<std::string> oem_strings() const;
protected:
/**
* Collected data for this machine based on DMI information
Expand Down
4 changes: 2 additions & 2 deletions lib/inc/whereami/whereami.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#pragma once

#include <string>
#include <internal/detectors/result.hpp>
#include <vector>
#include "export.h"

Expand All @@ -16,6 +16,6 @@ namespace whereami {
* Try to detect whether this machine is a guest on any hypervisors
* @return A vector of detected hypervisor names
*/
std::vector<std::string> LIBWHEREAMI_EXPORT hypervisors();
std::vector<detectors::result> LIBWHEREAMI_EXPORT hypervisors();

} // namespace whereami
22 changes: 22 additions & 0 deletions lib/src/detectors/metadata.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#include <internal/detectors/metadata.hpp>

using namespace std;

namespace whereami { namespace detectors {

void metadata::set(string const& key, bool value)
{
data_.emplace(key, value);
}

void metadata::set(string const& key, const char* value)
{
data_.emplace(key, string {value});
}

void metadata::set(string const& key, string const& value)
{
data_.emplace(key, value);
}

}} // namespace whereami::detectors
21 changes: 21 additions & 0 deletions lib/src/detectors/result.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#include <internal/detectors/result.hpp>

using namespace std;

namespace whereami { namespace detectors {

bool result::valid() const
{
return valid_;
}

void result::validate()
{
valid_ = true;
}

std::string result::name() const
{
return name_;
}
}} // namespace whereami::detectors
29 changes: 24 additions & 5 deletions lib/src/detectors/virtualbox_detector.cc
Original file line number Diff line number Diff line change
@@ -1,18 +1,37 @@
#include <internal/detectors/virtualbox_detector.hpp>
#include <leatherman/util/regex.hpp>
#include <internal/vm.hpp>
#include <boost/algorithm/string.hpp>

using namespace std;
using namespace whereami;
using namespace leatherman::util;

namespace whereami { namespace detectors {

bool virtualbox(const sources::cpuid_base& cpuid_source,
const sources::dmi_base& dmi_source) {
static const boost::regex re_virtualbox{"[Vv]irtual[Bb]ox"};
result virtualbox(const sources::cpuid_base& cpuid_source,
const sources::dmi_base& dmi_source) {
result res {vm::virtualbox};

return cpuid_source.vendor() == "VBoxVBoxVBox" ||
re_search(dmi_source.product_name(), re_virtualbox);
if (cpuid_source.vendor() == "VBoxVBoxVBox" ||
dmi_source.product_name() == "VirtualBox") {
res.validate();

// Look for VirtualBox version and revision in DMI OEM strings
auto oem_strings = dmi_source.oem_strings();

for (auto const& oem_string : dmi_source.oem_strings()) {
if (boost::istarts_with(oem_string, "vboxVer_")) {
auto version = oem_string.substr(8, string::npos);
res.set("version", version);
} else if (boost::istarts_with(oem_string, "vboxRev_")) {
auto revision = oem_string.substr(8, string::npos);
res.set("revision", revision);
}
}
}

return res;
}

}} // namespace whereami::detectors
Loading