Skip to content
This repository was archived by the owner on Apr 16, 2026. It is now read-only.

Commit 3605def

Browse files
committed
Restores runtime behavior after refactoring (WIP)
1 parent 50527ff commit 3605def

16 files changed

Lines changed: 390 additions & 254 deletions

File tree

include/cloysterhpc/services/files.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ class KeyFile {
6666
[[nodiscard]] std::vector<std::string> getGroups() const;
6767
[[nodiscard]] std::string getString(
6868
const std::string& group, const std::string& key) const;
69+
[[nodiscard]] std::string getString(
70+
const std::string& group, const std::string& key, std::string&& defaultValue) const;
6971
[[nodiscard]] bool getBoolean(
7072
const std::string& group, const std::string& key) const;
7173
[[nodiscard]] std::optional<std::string> getStringOpt(

include/cloysterhpc/services/options.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ struct Options final {
2828
std::string dumpAnswerfile;
2929
std::set<std::string> skipSteps;
3030
std::set<std::string> forceSteps;
31+
std::set<std::string> enabledRepos;
3132
std::set<std::string> ohpcPackages;
3233

3334
#ifndef NDEBUG

src/connection.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
Connection::Connection(Network* network)
3131
: m_network(network)
3232
{
33-
33+
LOG_DEBUG("Initializing network")
3434
if (network->getType() == Network::Type::Infiniband)
3535
setMTU(2044);
3636
}
@@ -40,7 +40,7 @@ Connection::Connection(Network* network,
4040
std::optional<std::string_view> mac, const std::string& ip)
4141
: m_network(network)
4242
{
43-
43+
LOG_DEBUG("Initializing network {}", ip)
4444
if (interface.has_value())
4545
setInterface(interface.value());
4646

@@ -75,7 +75,6 @@ std::optional<std::string_view> Connection::getInterface() const
7575
void Connection::setInterface(std::string_view interface)
7676
{
7777
LOG_DEBUG("Checking if interface {} exists", interface)
78-
7978
if (interface == "lo")
8079
throw std::runtime_error("Cannot use the loopback interface");
8180

@@ -186,6 +185,7 @@ void Connection::setAddress(const address& ip)
186185

187186
void Connection::setAddress(const std::string& ip)
188187
{
188+
LOG_DEBUG("Initializing network address {}", ip)
189189
try {
190190
setAddress(boost::asio::ip::make_address(ip));
191191
} catch (boost::system::system_error& e) {

src/functions.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,9 +111,7 @@ void removeFile(std::string_view filename)
111111
return;
112112
}
113113

114-
LOG_DEBUG("Checking if file {} already exists on filesystem", filename)
115114
if (std::filesystem::exists(filename)) {
116-
LOG_DEBUG("Already exists")
117115
std::filesystem::remove(filename);
118116
LOG_DEBUG("File {} deleted", filename)
119117
} else {

src/main.cpp

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,6 @@ void initializeSingletonsModel(auto&& cluster)
7070
auto clusterPtr = cloyster::Singleton<Cluster>::get();
7171
const auto& osinfo = clusterPtr->getHeadnode().getOS();
7272
auto repoManager = std::make_unique<RepoManager>();
73-
repoManager->initializeDefaultRepositories();
7473
return repoManager;
7574
});
7675

@@ -92,8 +91,11 @@ int runTestCommand(const std::string& testCommand,
9291
fmt::join(testCommandArgs, ","));
9392
auto cluster = cloyster::Singleton<cloyster::models::Cluster>::get();
9493
auto runner = cloyster::Singleton<cloyster::IRunner>::get();
94+
auto repoManager = cloyster::Singleton<repos::RepoManager>::get();
9595
if (testCommand == "execute-command") {
9696
runner->checkCommand(testCommandArgs[0]);
97+
} else if (testCommand == "initialize-repos") {
98+
repoManager->initializeDefaultRepositories();
9799
} else if (testCommand == "create-http-repo") {
98100
assert(testCommandArgs.size() > 0);
99101
cloyster::createHTTPRepo(testCommandArgs[0]);
@@ -127,16 +129,11 @@ int runTestCommand(const std::string& testCommand,
127129
*/
128130
int main(int argc, const char** argv)
129131
{
130-
auto options = Options::factory(argc, argv);
131-
initializeSingletonsOptions(std::move(options));
132-
auto opts = Singleton<Options>::get();
133-
134-
constexpr std::size_t logLevels
135-
= cloyster::utils::enums::count<Log::Level>();
136-
const std::vector<std::string> logLevelVector
137-
= cloyster::utils::enums::toStrings<Log::Level>();
132+
initializeSingletonsOptions(Options::factory(argc, argv));
138133

134+
auto opts = Singleton<Options>::get();
139135
Log::init(opts->logLevelInput);
136+
140137
if (opts->showVersion) {
141138
fmt::print("{}: Version {}\n", productName, productVersion);
142139
return EXIT_SUCCESS;
@@ -191,11 +188,11 @@ int main(int argc, const char** argv)
191188

192189
LOG_INFO("Initializing the model");
193190
auto model = std::make_unique<cloyster::models::Cluster>();
191+
LOG_INFO("Model initialized");
194192
if (!opts->answerfile.empty()) {
195193
LOG_INFO("Loading the answerfile: {}", opts->answerfile)
196194
model->fillData(opts->answerfile);
197195
}
198-
LOG_INFO("Model initialized");
199196

200197
opts->enableTUI = opts->answerfile.empty() && opts->testCommand.empty();
201198

src/models/answerfile.cpp

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -339,17 +339,16 @@ void AnswerFile::loadNetwork(
339339
network.con_interface = m_keyfile.getString(networkSection, "interface");
340340
convertNetworkAddressAndValidate(
341341
networkSection, "ip_address", network.con_ip_addr);
342-
network.con_mac_addr = m_keyfile.getString(networkSection, "mac_address");
342+
network.con_mac_addr = m_keyfile.getString(networkSection, "mac_address", "");
343343
convertNetworkAddressAndValidate(
344344
networkSection, "subnet_mask", network.subnet_mask);
345-
network.domain_name = m_keyfile.getString(networkSection, "domain_name");
345+
network.domain_name = m_keyfile.getString(networkSection, "domain_name", "");
346346
convertNetworkAddressAndValidate(
347347
networkSection, "gateway", network.gateway);
348348

349-
if (m_keyfile.getStringOpt(networkSection, "nameservers")) {
349+
if (auto opt = m_keyfile.getStringOpt(networkSection, "nameservers")) {
350350
std::vector<std::string> nameservers;
351-
boost::split(nameservers,
352-
m_keyfile.getString(networkSection, "nameservers"),
351+
boost::split(nameservers, opt.value(),
353352
boost::is_any_of(", "), boost::token_compress_on);
354353

355354
network.nameservers = nameservers;
@@ -431,6 +430,7 @@ void AnswerFile::loadSystemSettings()
431430
AFNode AnswerFile::loadNode(const std::string& section)
432431
{
433432
AFNode node;
433+
LOG_DEBUG("Loading node {}", section);
434434

435435
if (section == "node") {
436436
node.prefix = m_keyfile.getString(section, "prefix");
@@ -451,16 +451,19 @@ AFNode AnswerFile::loadNode(const std::string& section)
451451
}
452452
}
453453

454-
node.hostname = m_keyfile.getString(section, "hostname");
455-
node.root_password = m_keyfile.getString(section, "node_root_password");
456-
node.sockets = m_keyfile.getString(section, "sockets");
457-
node.cores_per_socket = m_keyfile.getString(section, "cores_per_socket");
458-
node.threads_per_core = m_keyfile.getString(section, "threads_per_core");
459-
node.bmc_address = m_keyfile.getString(section, "bmc_address");
460-
node.bmc_username = m_keyfile.getString(section, "bmc_username");
461-
node.bmc_password = m_keyfile.getString(section, "bmc_password");
462-
node.bmc_serialport = m_keyfile.getString(section, "bmc_serialport");
463-
node.bmc_serialspeed = m_keyfile.getString(section, "bmc_serialspeed");
454+
// Initialize with empty strings if the values are not found, the remaining
455+
// of the code is assuming that
456+
node.hostname = m_keyfile.getString(section, "hostname", "");
457+
node.root_password = m_keyfile.getString(section, "node_root_password", "");
458+
node.sockets = m_keyfile.getString(section, "sockets", "");
459+
node.cores_per_socket = m_keyfile.getString(section, "cores_per_socket", "");
460+
node.threads_per_core = m_keyfile.getString(section, "threads_per_core", "");
461+
node.bmc_address = m_keyfile.getString(section, "bmc_address", "");
462+
node.bmc_username = m_keyfile.getString(section, "bmc_username", "");
463+
node.bmc_password = m_keyfile.getString(section, "bmc_password", "");
464+
node.bmc_serialport = m_keyfile.getString(section, "bmc_serialport", "");
465+
node.bmc_serialspeed = m_keyfile.getString(section, "bmc_serialspeed", "");
466+
LOG_DEBUG("Node loaded {}", section);
464467

465468
return node;
466469
}
@@ -503,10 +506,10 @@ void AnswerFile::loadNodes()
503506
nodelist | std::views::filter(is_node_number)) {
504507
auto nodeCounter = node_counter(nodeSection);
505508

506-
LOG_TRACE("Configure {}", nodeSection)
507509
AFNode newNode = loadNode(nodeSection);
508510

509511
if (newNode.hostname->empty()) {
512+
LOG_DEBUG("Node configured {}", newNode.hostname.value());
510513
if (generic.prefix->empty()) {
511514
throw std::invalid_argument(
512515
fmt::format("Section node.{} must have a 'hostname' key or "

src/models/cluster.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -592,11 +592,12 @@ void Cluster::fillData(const std::filesystem::path& answerfilePath)
592592
if (answerfil.ofed.enabled) {
593593
// Install the cofigured OFED variant
594594
LOG_DEBUG("Loading OFED {}", answerfil.ofed.kind);
595-
auto kind = utils::enums::ofStringOpt<OFED::Kind>(answerfil.ofed.kind);
595+
auto kind = utils::enums::ofStringOpt<OFED::Kind>(answerfil.ofed.kind,
596+
utils::enums::Case::Insensitive);
596597
if (!kind) {
597598
throw std::runtime_error(fmt::format(
598599
"Invalid OFED kind, expected one of {}, found {}. Edit the "
599-
"anwerfile {} [ofed] sectino and try again.",
600+
"anwerfile {} [ofed] section and try again.",
600601
opts->answerfile,
601602
fmt::join(
602603
cloyster::utils::enums::toStrings<OFED::Kind>(), ", "),
@@ -613,14 +614,17 @@ void Cluster::fillData(const std::filesystem::path& answerfilePath)
613614

614615
addNetwork(std::move(managementNetwork));
615616

616-
LOG_TRACE("Configure Management Connection")
617+
LOG_DEBUG("Configure Management Connection")
617618
auto managementConnection
618619
= Connection(&getNetwork(Network::Profile::Management));
620+
LOG_DEBUG("Configure Management Connection interface")
619621
managementConnection.setInterface(
620622
answerfil.management.con_interface.value());
621623

624+
LOG_DEBUG("Configure Management Connection IP")
622625
managementConnection.setAddress(answerfil.management.con_ip_addr.value());
623626

627+
LOG_DEBUG("Configure Management Connection MAC")
624628
if (!answerfil.management.con_mac_addr->empty()) {
625629
managementConnection.setMAC(answerfil.management.con_mac_addr.value());
626630
}

src/models/os.cpp

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@ OS::OS()
2828
{
2929
struct utsname system {};
3030
auto opts = cloyster::Singleton<cloyster::services::Options>::get();
31+
// @FIXME: Unfortunately this runs during the initialization of the
32+
// cluster instance. Which prevents us of running this during testing
33+
// in a machine that does not have /etc/os-release file.
34+
// The isTest flag below is used to fill up default values during tests
35+
// to make it possible to run outside of target machines
3136
const bool isTest = !opts->testCommand.empty();
3237
uname(&system);
3338

@@ -124,23 +129,22 @@ OS::Platform OS::getPlatform() const
124129
return std::get<OS::Platform>(m_platform);
125130
}
126131

127-
void OS::setPlatform(OS::Platform platform) { m_platform = platform; }
132+
void OS::setPlatform(OS::Platform platform) {
133+
134+
LOG_DEBUG("Found platform ........ (PLATFORM_ID=)");
135+
m_platform = platform; }
128136

129137
void OS::setPlatform(std::string_view platform)
130138
{
131-
std::string lowercasePlatform(platform);
132-
std::transform(lowercasePlatform.begin(), lowercasePlatform.end(),
133-
lowercasePlatform.begin(), ::tolower);
134-
135-
for (const auto& enumValue :
136-
cloyster::utils::enums::toStrings<Platform>()) {
137-
if (lowercasePlatform == enumValue) {
138-
setPlatform(enumValue);
139-
return;
140-
}
139+
using namespace cloyster::utils;
140+
auto enumValue = enums::ofStringOpt<Platform>(
141+
platform,
142+
enums::Case::Insensitive);
143+
if (!enumValue) {
144+
throw std::runtime_error(fmt::format("Unsupported Platform: {}", platform));
145+
} else {
146+
setPlatform(enumValue.value());
141147
}
142-
143-
throw std::runtime_error(fmt::format("Unsupported Platform: {}", platform));
144148
}
145149

146150
OS::Distro OS::getDistro() const

src/ofed.cpp

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -65,13 +65,20 @@ bool OFED::installed() const
6565
void OFED::install() const
6666
{
6767
const auto opts = cloyster::Singleton<cloyster::services::Options>::get();
68+
69+
if (opts->dryRun) {
70+
LOG_WARN("Dry-Run: Skiping OFED installation");
71+
return;
72+
}
73+
6874
// Idempotency check
6975
if (installed()) {
7076
LOG_WARN("Inifiniband already installed, skipping, use `--force "
7177
"infiniband-install` to force");
7278
return;
7379
}
7480

81+
7582
switch (m_kind) {
7683
case OFED::Kind::Inbox:
7784
cloyster::Singleton<cloyster::services::IOSService>::get()
@@ -135,13 +142,15 @@ void OFED::install() const
135142
}
136143

137144
// Get the last rpm in /tmp/DOCA*/ folder
138-
auto rpm = runner->checkOutput(
139-
"bash -c \"find /tmp/DOCA*/ -name '*.rpm' -printf '%T@ %p\n' | "
140-
"sort -nk1 | tail -1 | awk '{print $2}'\"");
141-
assert(rpm.size() > 0); // at last one line
142-
143-
// Install the (last) generated rpm
144-
runner->executeCommand(fmt::format("dnf install -y {}", rpm[0]));
145+
// On dry-run the below command will not run so we
146+
// cannot get the output of it
147+
auto rpm = runner->checkOutput(
148+
"bash -c \"find /tmp/DOCA*/ -name '*.rpm' -printf '%T@ %p\n' | "
149+
"sort -nk1 | tail -1 | awk '{print $2}'\"");
150+
assert(rpm.size() > 0); // at last one line
151+
152+
// Install the (last) generated rpm
153+
runner->executeCommand(fmt::format("dnf install -y {}", rpm[0]));
145154

146155
runner->checkCommand(R"(dnf makecache --repo=doca*)");
147156
runner->checkCommand("dnf install -y doca-ofed mlnx-fw-updater");

src/options.cpp

Lines changed: 26 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,18 @@
99
namespace cloyster::services {
1010
using std::ifstream;
1111

12-
Options::Options()
13-
: helpAndExit{false}
14-
, showVersion{false}
15-
, runAsRoot{false}
16-
, dryRun{false}
17-
, enableTUI{false}
18-
, enableCLI{false}
19-
, runAsDaemon{false}
20-
, airGap{false} // Explicitly set to false
21-
, unattended{false} // Default log level
22-
, logLevelInput{3} // Added from main.cpp
23-
{};
12+
Options::Options()
13+
: helpAndExit { false }
14+
, showVersion { false }
15+
, runAsRoot { false }
16+
, dryRun { false }
17+
, enableTUI { false }
18+
, enableCLI { false }
19+
, runAsDaemon { false }
20+
, airGap { false } // Explicitly set to false
21+
, unattended { false } // Default log level
22+
, logLevelInput { 3 } // Added from main.cpp
23+
{ };
2424

2525
std::unique_ptr<Options> Options::factory(int argc, const char** argv)
2626
{
@@ -84,15 +84,21 @@ std::unique_ptr<Options> Options::factory(int argc, const char** argv)
8484
po::value<std::vector<std::string>>()->multitoken()->composing(),
8585
"Skip specific steps during installation")("force",
8686
po::value<std::vector<std::string>>()->multitoken()->composing(),
87-
"Force specific steps during installation")("ohpc-packages",
88-
po::value<std::vector<std::string>>()->multitoken()->composing(),
89-
"Select OHPC packages")("unattended,u",
87+
"Force specific steps during installation")
88+
("ohpc-packages",
89+
po::value<std::vector<std::string>>()->multitoken()->composing(),
90+
"Select OHPC packages")
91+
("repos",
92+
po::value<std::vector<std::string>>()->multitoken()->composing(),
93+
"Enabled repostiories")
94+
("unattended,u",
9095
po::bool_switch(&opt.unattended),
9196
"Perform an unattended installation") // Added from main.cpp
9297
("dump-answerfile", po::value<std::string>(&opt.dumpAnswerfile),
9398
"Create an answerfile based on input and save to specified path") // Added from main.cpp
9499
("config", po::value<std::string>(&opt.config),
95-
"Config file to pass options for the command line from a configuration file") // Added from main.cpp
100+
"Config file to pass options for the command line from a "
101+
"configuration file") // Added from main.cpp
96102
#ifndef NDEBUG
97103
("test", po::value<std::string>(&opt.testCommand),
98104
"Run a command for testing purposes") // Added from main.cpp
@@ -144,17 +150,17 @@ std::unique_ptr<Options> Options::factory(int argc, const char** argv)
144150
"spack-ohpc", "valgrind-ohpc" };
145151
initializeSetOption(
146152
"ohpc-packages", opt.ohpcPackages, vmap, ohpcPackagesDefault);
153+
const auto reposEnabledDefault = { "beegfs", "elrepo", "epel", "openhpc",
154+
"openhpc-updates", "rpmfusion-free-updates" };
155+
initializeSetOption(
156+
"repos", opt.enabledRepos, vmap, reposEnabledDefault);
147157

148158
// Validate log-level input using std::from_chars (set to default "3" if
149159
// invalid)
150160
int levelNum = 0;
151161
constexpr int levelMax = 6;
152162
constexpr int levelMin = 1;
153163

154-
if (vmap.contains("test")) {
155-
opt.dryRun = true;
156-
}
157-
158164
return std::make_unique<Options>(std::move(opt));
159165
}
160166

0 commit comments

Comments
 (0)