Skip to content

Commit

Permalink
Comp schedule tests and fixes (#111)
Browse files Browse the repository at this point in the history
* Bump tsq & EL

* Working tests of the computer schedule
  • Loading branch information
mj-xmr committed Aug 18, 2022
1 parent 2012238 commit cd8b94a
Show file tree
Hide file tree
Showing 4 changed files with 163 additions and 29 deletions.
2 changes: 1 addition & 1 deletion externals/tsqsim
56 changes: 40 additions & 16 deletions src/opti-lib/src/OptiEnProfitResults.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
using namespace std;
using namespace EnjoLib;

const int OptiEnProfitResults::SSH_TIMEOUT = 60;

/// TODO: UTest & refactor
void OptimizerEnProfit::PrintSolution(const EnjoLib::Matrix & bestMat) const
{
Expand Down Expand Up @@ -45,7 +47,10 @@ void OptimizerEnProfit::PrintSolution(const EnjoLib::Matrix & bestMat) const
{
const Computer & comp = m_dataModel.GetComputers().at(i);
const VecD & best = bestMat.at(i);
LOG << OptiEnProfitResults().PrintScheduleComp(comp, best, currHour);
LOG << OptiEnProfitResults().PrintScheduleComp(comp, best);
const OptiEnProfitResults::CommandsInfos & cmdInfo = OptiEnProfitResults().PrintCommandsComp(comp, best, currHour);
LOG << cmdInfo.infos;
oss << cmdInfo.commands;
}

LOG << "Commands:\n\n";
Expand All @@ -61,16 +66,24 @@ void OptimizerEnProfit::PrintSolution(const EnjoLib::Matrix & bestMat) const
OptiEnProfitResults:: OptiEnProfitResults() {}
OptiEnProfitResults::~OptiEnProfitResults() {}

EnjoLib::Str OptiEnProfitResults::PrintScheduleComp(const Computer & comp, const VecD & best, int currHour) const
EnjoLib::Str OptiEnProfitResults::PrintScheduleComp(const Computer & comp, const VecD & best) const
{
Osstream oss;
oss << comp.name << Nl;
const double maxx = 1;
oss << AsciiPlot::Build()(AsciiPlot::Pars::MAXIMUM, maxx).Finalize().Plot(best) << Nl;
return oss.str();
}

OptiEnProfitResults::CommandsInfos OptiEnProfitResults::PrintCommandsComp(const Computer & comp, const VecD & best, int currHour, int maxDayCmdsLimit) const
{
CommandsInfos ret;
Osstream ossCmd, ossInfo;
const CharManipulations cman;
//oss << cman.Replace(best.Print(), " ", "") << Nl;

const Str cmdsSSHbare = "ssh -o ConnectTimeout=35 -n " + comp.hostname + " ";
const Str cmdsSSH = cmdsSSHbare + " 'hostname; echo \"";
const Str cmdsSSHbare = "ssh -o ConnectTimeout=" + cman.ToStr(SSH_TIMEOUT) + " -n " + comp.hostname + " ";
const Str cmdsSSH = cmdsSSHbare + "'hostname; echo \"";
const Str cmdWOL = "wakeonlan " + comp.macAddr;
//const Str cmdSuspendAt = "systemctl suspend\" | at ";
const Str cmdSuspendAt = "systemctl suspend\" | at ";
Expand All @@ -89,7 +102,7 @@ EnjoLib::Str OptiEnProfitResults::PrintScheduleComp(const Computer & comp, const
const int dayPrev = GMat().round((ihour-1) / static_cast<double>(OptimizerEnProfit::HOURS_IN_DAY));
if (day != dayPrev)
{
//oss << Nl;
//ossInfo << Nl;
}

const bool onPrev = best.at(i-1);
Expand All @@ -99,45 +112,56 @@ EnjoLib::Str OptiEnProfitResults::PrintScheduleComp(const Computer & comp, const
lastHourOn = hour;
lastDayOn = day;
}
const bool isInDayLimit = maxDayCmdsLimit < 0 || lastDayOn <= maxDayCmdsLimit;
const int hourPrev = (ihour - 1) % OptimizerEnProfit::HOURS_IN_DAY;
if (lastHourOn > 0)
{
if (not onCurr) // Switch off
{
oss << "day " << lastDayOn << ", hour " << lastHourOn << "-" << hourPrev << Nl;
if (lastDayOn == 1)
ossInfo << "day " << lastDayOn << ", hour " << lastHourOn << "-" << hourPrev << Nl;
if (isInDayLimit)
{
// Wake up
oss << "echo \"" << cmdWOL << "\" | at " << lastHourOn << cmdMinuteSuffix << Nl;
ossCmd << "echo \"" << cmdWOL << "\" | at " << lastHourOn << cmdMinuteSuffix << Nl;
// Put to sleep
oss << cmdsSSH << cmdSuspendAt << hourPrev << cmdMinuteSuffix << "'" << Nl;
/// TODO: This is a logic error. It should SSH AT the end hour to sleep, not SSH now to sleep at hour. The rig is sleeping until the start hour!
ossCmd << cmdsSSH << cmdSuspendAt << hourPrev << cmdMinuteSuffix << "'" << Nl;
}

lastHourOn = -1;
}
else if (i == horizonHours - 1)
{
oss << "day " << lastDayOn << ", hour " << lastHourOn << "-.." << Nl;
ossInfo << "day " << lastDayOn << ", hour " << lastHourOn << "-.." << Nl;
if (isInDayLimit)
{
// Wake up
ossCmd << "echo \"" << cmdWOL << "\" | at " << lastHourOn << cmdMinuteSuffix << Nl;
}
}
}
if (onCurr && i == 1)
{
// Wake up now, right at the beginning! The battery is probably already overloaded.
oss << cmdWOL << Nl;
ossCmd << cmdWOL << Nl;
onAtFirstHour = true;
}
else
if (onPrev && not onCurr && day == 1)
if (onPrev && not onCurr && isInDayLimit)
{
if (onAtFirstHour) // Was started at the beginning already. Be sure to suspend later on.
{
oss << "day 1, hour !-" << hourPrev << Nl;
oss << cmdsSSH << cmdSuspendAt << hourPrev << cmdMinuteSuffix << "'" << Nl;
ossInfo << "day 0, hour !-" << hourPrev << Nl;
ossCmd << cmdsSSH << cmdSuspendAt << hourPrev << cmdMinuteSuffix << "'" << Nl;
}
}
}
oss << Nl;
ossCmd << Nl;
ossInfo << Nl;

return oss.str();
ret.commands = ossCmd.str();
ret.infos = ossInfo.str();

return ret;
}

11 changes: 10 additions & 1 deletion src/opti-lib/src/OptiEnProfitResults.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,17 @@ class OptiEnProfitResults
public:
OptiEnProfitResults();
virtual ~OptiEnProfitResults();

struct CommandsInfos
{
EnjoLib::Str commands;
EnjoLib::Str infos;
};

EnjoLib::Str PrintScheduleComp(const Computer & comp, const EnjoLib::VecD & best, int currHour) const;
EnjoLib::Str PrintScheduleComp(const Computer & comp, const EnjoLib::VecD & best) const;
CommandsInfos PrintCommandsComp(const Computer & comp, const EnjoLib::VecD & best, int currHour, int maxDayCmdsLimit = 1) const;

static const int SSH_TIMEOUT;

protected:

Expand Down
123 changes: 112 additions & 11 deletions tests/opti-test/src/CompScheduleTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,14 @@

using namespace EnjoLib;

static int SCHEDULE_CURR_HOUR = 0;
static Str compSched_macAddr = "DE:AD:BE:EF:AA:BB";
static Str compSched_hostname = "Miner_2049er";
static Computer GetCompTestSched()
{
Computer compTest;
compTest.macAddr = compSched_macAddr;
compTest.hostname = compSched_hostname;

return compTest;
}
Expand All @@ -36,8 +41,8 @@ static Str GetSched2ExpPlot(const VecD & schedule)
static Str GetStartHourToSchedule(int startHour, int endHour = -1)
{
Osstream oss;

oss << "day 0, hour " << startHour << "-";
const CharManipulations cman;
oss << "day 0, hour " << (startHour > 0 ? cman.ToStr(startHour) : "!") << "-";
if (endHour >= 0)
{
oss << endHour;
Expand All @@ -49,14 +54,41 @@ static Str GetStartHourToSchedule(int startHour, int endHour = -1)
return oss.str();
}

static Str GetStartHourToWakeup(int startHour, const Computer & comp)
{
Osstream oss;
if (startHour > SCHEDULE_CURR_HOUR)
{
oss << "echo \"";
}
oss << "wakeonlan " << compSched_macAddr;
if (startHour > SCHEDULE_CURR_HOUR)
{
/// TODO: All "at"s should also include the day when to start, not just today, unless we assume starting once only every day, which makes sense as well, but make it a parameter or sth.
oss << "\" | at " << startHour << ":00";
}
return oss.str();
}

static Str GetStartHourToSleep(const Computer & comp, int endHour)
{
/// TODO: This is a logic error. It should SSH AT the end hour to sleep, not SSH now to sleep at hour. The rig is sleeping until the start hour!
Osstream oss;
oss << "ssh -o ConnectTimeout=" << OptiEnProfitResults::SSH_TIMEOUT << " -n " << compSched_hostname
<< " 'hostname; echo \"systemctl suspend\" | at " << endHour << ":00'";
return oss.str();
}

//ssh -o ConnectTimeout=35 -n Miner_2049er 'hostname; echo "systemctl suspend" | at 7:00

TEST(CompSched_open_ended)
{
const CharManipulations cman;
const OptiEnProfitResults proRes;
const Computer & comp0 = GetCompTestSched();
const VecD schedule = {0, 0, 0, 1, 1, 1, 1, 1, 1};
const int currHour = 0;
const int currHour = SCHEDULE_CURR_HOUR;
const int startHour = 3;
const Str & schedStr = OptiEnProfitResults().PrintScheduleComp(comp0, schedule, currHour);
const Str & schedStr = proRes.PrintScheduleComp(comp0, schedule);
CHECK(schedStr.size());
const Tokenizer tok;
const VecStr & toks = tok.Tokenize(schedStr, '\n');
Expand All @@ -66,23 +98,92 @@ TEST(CompSched_open_ended)
const Str & exp = GetSched2ExpPlot(schedule);
CHECK_EQUAL(exp, toks.at(1));

const Str & expText = GetStartHourToSchedule(startHour);
CHECK_EQUAL(expText, toks.at(2));
{
ELO
const OptiEnProfitResults::CommandsInfos & cmdInfo = proRes.PrintCommandsComp(comp0, schedule, currHour);
LOG << "Info: " << cmdInfo.infos;
LOG << "Cmds: " << cmdInfo.commands;
const VecStr & toksInfo = tok.Tokenize(cmdInfo.infos, '\n');
const Str & expTextInfo = GetStartHourToSchedule(startHour);
CHECK(toksInfo.size());
CHECK_EQUAL(expTextInfo, toksInfo.at(0));

const VecStr & toksCmds = tok.Tokenize(cmdInfo.commands, '\n');
const Str & expTextCmdWakeUp = GetStartHourToWakeup(startHour, comp0);
CHECK(toksCmds.size() >= 1);
CHECK_EQUAL(expTextCmdWakeUp, toksCmds.at(0));

} //echo "wakeonlan DE:AD:BE:EF:AA:BB" | at 3:00
}

TEST(CompSched_finalized)
{
const OptiEnProfitResults proRes;
const Computer & comp0 = GetCompTestSched();
const VecD schedule = {0, 0, 0, 1, 1, 1, 1, 1, 0};
const int currHour = 0;
const int currHour = SCHEDULE_CURR_HOUR;
const int startHour = 3;
const int endHour = 7;
const Str & schedStr = OptiEnProfitResults().PrintScheduleComp(comp0, schedule, currHour);
const Str & schedStr = proRes.PrintScheduleComp(comp0, schedule);
const OptiEnProfitResults::CommandsInfos & cmdInfo = proRes.PrintCommandsComp(comp0, schedule, currHour);
const Tokenizer tok;
const VecStr & toks = tok.Tokenize(schedStr, '\n');
LOGL << schedStr << Nl;
const Str & exp = GetSched2ExpPlot(schedule);
CHECK_EQUAL(exp, toks.at(1));
const Str & expText = GetStartHourToSchedule(startHour, endHour);
CHECK_EQUAL(expText, toks.at(2));

{
ELO
const OptiEnProfitResults::CommandsInfos & cmdInfo = proRes.PrintCommandsComp(comp0, schedule, currHour);
LOG << "Info: " << cmdInfo.infos;
LOG << "Cmds: " << cmdInfo.commands;
const VecStr & toksInfo = tok.Tokenize(cmdInfo.infos, '\n');
const Str & expTextInfo = GetStartHourToSchedule(startHour, endHour);
CHECK_EQUAL(expTextInfo, toksInfo.at(0));

const VecStr & toksCmds = tok.Tokenize(cmdInfo.commands, '\n');
const Str & expTextCmdWakeUp = GetStartHourToWakeup(startHour, comp0);
const Str & expTextCmdSleep = GetStartHourToSleep(comp0, endHour);
CHECK(toksCmds.size() >= 2);
CHECK_EQUAL(expTextCmdWakeUp, toksCmds.at(0));
LOG << "Was & exp:\n" << toksCmds.at(1) << Nl << expTextCmdSleep << Nl;
CHECK_EQUAL(expTextCmdSleep, toksCmds.at(1));
}
}


TEST(CompSched_start_immediately)
{
const OptiEnProfitResults proRes;
const Computer & comp0 = GetCompTestSched();
const VecD schedule = {1, 1, 1, 1, 1, 1, 1, 1, 0}; // TODO: {1, 1, 1, 1, 1, 1, 1, 1, 1}; (aka - start and never finish)
const int currHour = SCHEDULE_CURR_HOUR;
const int startHour = 0;
const int endHour = 7;
const Str & schedStr = proRes.PrintScheduleComp(comp0, schedule);
const OptiEnProfitResults::CommandsInfos & cmdInfo = proRes.PrintCommandsComp(comp0, schedule, currHour);
const Tokenizer tok;
const VecStr & toks = tok.Tokenize(schedStr, '\n');
LOGL << schedStr << Nl;
const Str & exp = GetSched2ExpPlot(schedule);
CHECK_EQUAL(exp, toks.at(1));

{
ELO
const OptiEnProfitResults::CommandsInfos & cmdInfo = proRes.PrintCommandsComp(comp0, schedule, currHour);
LOG << "Info: " << cmdInfo.infos;
LOG << "Cmds: " << cmdInfo.commands;
const VecStr & toksInfo = tok.Tokenize(cmdInfo.infos, '\n');
const Str & expTextInfo = GetStartHourToSchedule(startHour, endHour);
CHECK_EQUAL(expTextInfo, toksInfo.at(0));

const VecStr & toksCmds = tok.Tokenize(cmdInfo.commands, '\n');
const Str & expTextCmdWakeUp = GetStartHourToWakeup(startHour, comp0);
const Str & expTextCmdSleep = GetStartHourToSleep(comp0, endHour);
CHECK(toksCmds.size() >= 2);
CHECK_EQUAL(expTextCmdWakeUp, toksCmds.at(0));
LOG << "Was & exp:\n" << toksCmds.at(1) << Nl << expTextCmdSleep << Nl;
CHECK_EQUAL(expTextCmdSleep, toksCmds.at(1));
}
}

0 comments on commit cd8b94a

Please sign in to comment.