Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Re-implements the xendomains fact in Facter 3.
- Loading branch information
Michael Smith
committed
Jun 26, 2015
1 parent
9b1ef72
commit f735036
Showing
12 changed files
with
362 additions
and
1 deletion.
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
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
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,24 @@ | ||
/** | ||
* @file | ||
* Declares the Xen fact resolver on POSIX systems. | ||
*/ | ||
#pragma once | ||
|
||
#include <internal/facts/resolvers/xen_resolver.hpp> | ||
|
||
namespace facter { namespace facts { namespace posix { | ||
|
||
/** | ||
* Responsible for resolving Xen facts. | ||
*/ | ||
struct xen_resolver : resolver | ||
{ | ||
protected: | ||
/** | ||
* Gets the Xen management command. | ||
* @return Returns the Xen management command. | ||
*/ | ||
virtual std::string xen_command(); | ||
}; | ||
|
||
}}} // namespace facter::facts::posix |
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,55 @@ | ||
/** | ||
* @file | ||
* Declares the Xen fact resolver. | ||
*/ | ||
#pragma once | ||
|
||
#include <facter/facts/resolver.hpp> | ||
#include <string> | ||
#include <vector> | ||
|
||
namespace facter { namespace facts { namespace resolvers { | ||
|
||
/** | ||
* Responsible for resolving Xen facts. | ||
*/ | ||
struct xen_resolver : resolver | ||
{ | ||
/** | ||
* Constructs the xen_resolver. | ||
*/ | ||
xen_resolver(); | ||
|
||
/** | ||
* Called to resolve all facts the resolver is responsible for. | ||
* @param facts The fact collection that is resolving facts. | ||
*/ | ||
virtual void resolve(collection& facts) override; | ||
|
||
protected: | ||
/** | ||
* Gets the Xen management command. | ||
* @return Returns the Xen management command. | ||
*/ | ||
virtual std::string xen_command() = 0; | ||
|
||
/** | ||
* Represents the resolver's data. | ||
*/ | ||
struct data | ||
{ | ||
/** | ||
* Stores the Xen domains. | ||
*/ | ||
std::vector<std::string> domains; | ||
}; | ||
|
||
/** | ||
* Collects the resolver data. | ||
* @param facts The fact collection that is resolving facts. | ||
* @return Returns the resolver data. | ||
*/ | ||
virtual data collect_data(collection& facts); | ||
}; | ||
|
||
}}} // namespace facter::facts::resolvers |
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
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
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,45 @@ | ||
#include <internal/facts/posix/xen_resolver.hpp> | ||
#include <facter/execution/execution.hpp> | ||
#include <leatherman/logging/logging.hpp> | ||
#include <boost/filesystem.hpp> | ||
|
||
using namespace std; | ||
using namespace facter::facts; | ||
using namespace facter::execution; | ||
using namespace boost::filesystem; | ||
namespace bs = boost::system; | ||
|
||
namespace facter { namespace facts { namespace posix { | ||
|
||
string xen_resolver::xen_command() | ||
{ | ||
constexpr char const* xen_toolstack = "/usr/lib/xen-common/bin/xen-toolstack"; | ||
|
||
bs::error_code ec; | ||
if (exists(xen_toolstack, ec) && !ec) { | ||
bool success; | ||
string output, error; | ||
tie(success, output, error) = execute(xen_toolstack); | ||
if (success) { | ||
return output; | ||
} else { | ||
LOG_DEBUG("failure executing %1%: %2%", xen_toolstack, error); | ||
return {}; | ||
} | ||
} else { | ||
LOG_TRACE("xen toolstack command not found: %1%", ec.message()); | ||
|
||
static vector<string> xen_commands{"/usr/sbin/xl", "/usr/sbin/xm"}; | ||
for (auto const& cmd : xen_commands) { | ||
auto cmd_path = execution::which(cmd); | ||
if (!cmd_path.empty()) { | ||
return cmd_path; | ||
} | ||
} | ||
|
||
LOG_TRACE("no xen commands found"); | ||
return {}; | ||
} | ||
} | ||
|
||
}}} // namespace facter::facts::posix |
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,81 @@ | ||
#include <internal/facts/resolvers/xen_resolver.hpp> | ||
#include <internal/util/regex.hpp> | ||
#include <leatherman/logging/logging.hpp> | ||
#include <facter/facts/collection.hpp> | ||
#include <facter/facts/fact.hpp> | ||
#include <facter/facts/vm.hpp> | ||
#include <facter/facts/scalar_value.hpp> | ||
#include <facter/facts/array_value.hpp> | ||
#include <facter/facts/map_value.hpp> | ||
#include <facter/execution/execution.hpp> | ||
#include <boost/algorithm/string.hpp> | ||
|
||
using namespace std; | ||
using namespace facter::facts; | ||
|
||
namespace facter { namespace facts { namespace resolvers { | ||
|
||
xen_resolver::xen_resolver() : | ||
resolver( | ||
"Xen", | ||
{ | ||
fact::xen, | ||
fact::xendomains | ||
}) | ||
{ | ||
} | ||
|
||
void xen_resolver::resolve(collection& facts) | ||
{ | ||
// Confine to fact virtual == xen0 | ||
auto virt = facts.get<string_value>(fact::virtualization); | ||
if (!virt || virt->value() != vm::xen_privileged) { | ||
return; | ||
} | ||
|
||
auto data = collect_data(facts); | ||
|
||
if (!data.domains.empty()) { | ||
auto xendomains = boost::algorithm::join(data.domains, ","); | ||
facts.add(fact::xendomains, make_value<string_value>(move(xendomains), true)); | ||
} | ||
|
||
auto domains = make_value<array_value>(); | ||
for (auto& domain : data.domains) { | ||
domains->add(make_value<string_value>(move(domain))); | ||
} | ||
|
||
auto xen = make_value<map_value>(); | ||
if (!domains->empty()) { | ||
xen->add("domains", move(domains)); | ||
} | ||
|
||
if (!xen->empty()) { | ||
facts.add(fact::xen, move(xen)); | ||
} | ||
} | ||
|
||
xen_resolver::data xen_resolver::collect_data(collection& facts) | ||
{ | ||
data result; | ||
|
||
auto command = xen_command(); | ||
if (!command.empty()) { | ||
static boost::regex domain_header("^(Name|Domain-0)"); | ||
static boost::regex domain_entry("^([^\\s]*)\\s"); | ||
execution::each_line(command, {"list"}, [&](string& line) { | ||
string domain; | ||
if (!boost::regex_match(line, domain_header) && util::re_search(line, domain_entry, &domain)) { | ||
result.domains.emplace_back(move(domain)); | ||
} | ||
return true; | ||
}, [&](string& line) { | ||
LOG_DEBUG("output on stderr running %1% list: %2%", command, line); | ||
return true; | ||
}); | ||
} | ||
|
||
return result; | ||
} | ||
|
||
}}} // namespace facter::facts::resolvers |
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
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
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,100 @@ | ||
#include <catch.hpp> | ||
#include <internal/facts/resolvers/xen_resolver.hpp> | ||
#include <facter/facts/collection.hpp> | ||
#include <facter/facts/fact.hpp> | ||
#include <facter/facts/vm.hpp> | ||
#include <facter/facts/scalar_value.hpp> | ||
#include <facter/facts/map_value.hpp> | ||
#include <facter/facts/array_value.hpp> | ||
#include "../../collection_fixture.hpp" | ||
|
||
using namespace std; | ||
using namespace facter::facts; | ||
using namespace facter::facts::resolvers; | ||
using namespace facter::testing; | ||
|
||
struct empty_xen_resolver : xen_resolver | ||
{ | ||
protected: | ||
virtual string xen_command() | ||
{ | ||
return ""; | ||
} | ||
|
||
virtual data collect_data(collection& facts) override | ||
{ | ||
data result; | ||
return result; | ||
} | ||
}; | ||
|
||
struct test_xen_resolver : xen_resolver | ||
{ | ||
protected: | ||
virtual string xen_command() | ||
{ | ||
return ""; | ||
} | ||
|
||
virtual data collect_data(collection& facts) override | ||
{ | ||
data result; | ||
result.domains = { "domain1", "domain2" }; | ||
return result; | ||
} | ||
}; | ||
|
||
// CATCH doesn't behave well with constexpr, so create memory for | ||
// the string here before using it in the test. | ||
static string xen_privileged = vm::xen_privileged; | ||
|
||
SCENARIO("using the Xen resolver on a privileged VM") { | ||
collection_fixture facts; | ||
facts.add(fact::virtualization, make_value<string_value>(xen_privileged)); | ||
WHEN("data is not present") { | ||
facts.add(make_shared<empty_xen_resolver>()); | ||
THEN("facts should not be added") { | ||
REQUIRE(facts.size() == 1u); | ||
} | ||
} | ||
WHEN("data is present") { | ||
facts.add(make_shared<test_xen_resolver>()); | ||
THEN("flat facts are added") { | ||
REQUIRE(facts.size() == 3u); | ||
auto value = facts.get<string_value>(fact::xendomains); | ||
REQUIRE(value); | ||
REQUIRE(value->value() == "domain1,domain2"); | ||
} | ||
|
||
THEN("structured facts are added") { | ||
REQUIRE(facts.size() == 3u); | ||
auto xen = facts.get<map_value>(fact::xen); | ||
REQUIRE(xen); | ||
REQUIRE(xen->size() == 1u); | ||
auto domains = xen->get<array_value>("domains"); | ||
REQUIRE(domains); | ||
REQUIRE(domains->size() == 2u); | ||
for (size_t i = 0; i < 2; ++i) { | ||
auto domain = domains->get<string_value>(i); | ||
REQUIRE(domain); | ||
REQUIRE(domain->value() == "domain" + to_string(i+1)); | ||
} | ||
} | ||
} | ||
} | ||
|
||
SCENARIO("using the Xen resolver on an unprivileged machine") { | ||
collection_fixture facts; | ||
WHEN("data is not present") { | ||
facts.add(make_shared<empty_xen_resolver>()); | ||
THEN("facts should not be added") { | ||
REQUIRE(facts.size() == 0u); | ||
} | ||
} | ||
WHEN("data is present") { | ||
facts.add(make_shared<test_xen_resolver>()); | ||
THEN("facts should not be added") { | ||
REQUIRE(facts.size() == 0u); | ||
} | ||
} | ||
} |
Oops, something went wrong.