/* * Copyright 2014-2018 Markus Prasser, Tobias Weiss * * This file is part of Labcontrol. * * Labcontrol is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Labcontrol is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Labcontrol. If not, see . */ #include "client.h" #include "clientpinger.h" #include "settings.h" #include #include lc::Client::Client(const QString &argIP, const QString &argMAC, const QString &argName, const Settings *const argSettings, const unsigned short int argXPosition, const unsigned short int argYPosition, const QString &argPingCmd): ip{argIP}, mac{argMAC}, name{argName}, xPosition{argXPosition}, yPosition{argYPosition}, protectedCycles{0}, settings{argSettings} { if (!argPingCmd.isEmpty()) { pinger = new ClientPinger{ip, argPingCmd}; pinger->moveToThread(&pingerThread); connect(&pingerThread, &QThread::finished, pinger, &QObject::deleteLater); connect(this, &Client::PingWanted, pinger, &ClientPinger::doPing); connect(pinger, &ClientPinger::PingFinished, this, &Client::GotStatusChanged); pingerThread.start(); pingTimer = new QTimer{this}; connect(pingTimer, &QTimer::timeout, this, &Client::RequestAPing) ; pingTimer->start(3000); } qDebug() << "Created client" << name << "with MAC" << mac << "and IP" << ip << "at position" << QString{QString::number(xPosition) + "x" + QString::number(yPosition)}; } lc::Client::~Client() { if (pingTimer) { pingTimer->stop(); } delete pingTimer; pingerThread.quit(); pingerThread.wait(); } void lc::Client::BeamFile(const QString &argFileToBeam, const QString *const argPublickeyPathUser, const QString *const argUserNameOnClients) { if (state < EState::RESPONDING) { return; } const QStringList arguments{"-2", "-i", *argPublickeyPathUser, "-l", "32768", "-r", argFileToBeam, QString{*argUserNameOnClients + "@" + ip + ":media4ztree"}}; // Start the process QProcess beamFileProcess; beamFileProcess.setProcessEnvironment(QProcessEnvironment::systemEnvironment()); beamFileProcess.startDetached(settings->scpCmd, arguments); qDebug() << settings->scpCmd << arguments.join(" "); } void lc::Client::Boot() { const QStringList arguments{"-i", settings->netwBrdAddr, mac}; // Start the process QProcess wakeonlanProcess; wakeonlanProcess.setProcessEnvironment(QProcessEnvironment::systemEnvironment()); wakeonlanProcess.startDetached(settings->wakeonlanCmd, arguments); // Output message via the debug messages tab qDebug() << settings->wakeonlanCmd << arguments.join(" "); pingTimer->start(3000); protectedCycles = 7; GotStatusChanged(EState::BOOTING); } void lc::Client::GotStatusChanged(EState argState) { if ((protectedCycles > 0) && (state == EState::BOOTING) && (argState != EState::RESPONDING)) { return; } if ((protectedCycles > 0) && (state == EState::SHUTTING_DOWN) && argState != EState::NOT_RESPONDING) { return; } state = argState; qDebug() << name << "status changed to:" << static_cast(argState); } void lc::Client::KillZLeaf() { const QStringList arguments{"-i", settings->pkeyPathUser, QString{settings->userNameOnClients + "@" + ip}, settings->killallCmd, "-I", "-q", "zleaf.exe"}; // Start the process QProcess killZLeafProcess; killZLeafProcess.setProcessEnvironment(QProcessEnvironment::systemEnvironment()); killZLeafProcess.startDetached(settings->sshCmd, arguments); // Output message via the debug messages tab qDebug() << settings->sshCmd << arguments.join(" "); // Restart the ping_timer, because it is stopped when a zLeaf is started pingTimer->start(3000); } void lc::Client::OpenFilesystem(const QString *const argUserToBeUsed) { if (state < EState::RESPONDING) { return; } const QStringList arguments{QString{ "sftp://" + *argUserToBeUsed + "@" + ip }}; QProcess openFilesystemProcess; openFilesystemProcess.setProcessEnvironment(QProcessEnvironment::systemEnvironment()); openFilesystemProcess.startDetached(settings->fileMngr, arguments); qDebug() << settings->fileMngr << arguments.join(" "); } void lc::Client::OpenTerminal(const QString &argCommand, const bool argOpenAsRoot) { if (!settings->termEmulCmd.isEmpty()) { if (state < EState::RESPONDING) { return; } QStringList arguments; if (!argOpenAsRoot) { arguments << "-e" << QString{settings->sshCmd + " -i " + settings->pkeyPathUser + " " + settings->userNameOnClients + "@" + ip}; } else { arguments << "-e" << QString{settings->sshCmd + " -i " + settings->pkeyPathRoot + " " + "root@" + ip}; } if (!argCommand.isEmpty()) { arguments.last().append(" '" + argCommand + "'"); } QProcess openTerminalProcess; openTerminalProcess.setProcessEnvironment(QProcessEnvironment::systemEnvironment()); openTerminalProcess.startDetached(settings->termEmulCmd, arguments); qDebug() << settings->termEmulCmd << arguments.join(" "); } } void lc::Client::RequestAPing() { if (protectedCycles > 0) { --protectedCycles; } emit PingWanted(); } void lc::Client::SetStateToZLEAF_RUNNING(const QString &argClientIP) { if ( argClientIP != ip ) { return; } if (state != EState::ZLEAF_RUNNING) { pingTimer->stop(); // Inform the ClientPinger instance, that zLeaf is now running pinger->setStateToZLEAF_RUNNING(); this->GotStatusChanged(EState::ZLEAF_RUNNING); qDebug() << "Client" << name << "got 'ZLEAF_RUNNING' signal."; } } void lc::Client::ShowDesktopViewOnly() { QStringList arguments{ip}; QProcess showDesktopProcess; showDesktopProcess.setProcessEnvironment(QProcessEnvironment::systemEnvironment()); showDesktopProcess.startDetached( settings->vncViewer, QStringList{ip}); // Output message via the debug messages tab qDebug() << settings->vncViewer << arguments.join( " " ); } void lc::Client::ShowDesktopFullControl() { const QStringList arguments{QString{ip + ":5901"}}; QProcess showDesktopProcess; showDesktopProcess.setProcessEnvironment(QProcessEnvironment::systemEnvironment()); showDesktopProcess.startDetached(settings->vncViewer, arguments); // Output message via the debug messages tab qDebug() << settings->vncViewer << arguments.join(" "); } void lc::Client::Shutdown() { if (state == EState::NOT_RESPONDING || state == EState::BOOTING || state == EState::SHUTTING_DOWN) { return; } const QStringList arguments{"-i", settings->pkeyPathUser, QString{settings->userNameOnClients + "@" + ip}, "sudo shutdown -P now"}; // Start the process QProcess shutdownProcess; shutdownProcess.setProcessEnvironment(QProcessEnvironment::systemEnvironment()); shutdownProcess.startDetached(settings->sshCmd, arguments); // Output message via the debug messages tab qDebug() << settings->sshCmd << arguments.join(" "); // This additional 'ping_timer' start is needed for the case that the clients are shut down without prior closing of zLeaves pingTimer->start(3000); protectedCycles = 3; GotStatusChanged(EState::SHUTTING_DOWN); } void lc::Client::StartZLeaf(const QString *argFakeName, QString cmd) { if (state < EState::RESPONDING || zLeafVersion.isEmpty() || GetSessionPort() < 7000) { return; } // Create a QMessageBox for user interaction if there is already a zLeaf running std::unique_ptr messageBoxRunningZLeafFound; if (state == EState::ZLEAF_RUNNING) { messageBoxRunningZLeafFound.reset(new QMessageBox{QMessageBox::Warning, "Running zLeaf found", QString{"There is already a zLeaf running on " + name + "."}, QMessageBox::No | QMessageBox::Yes}); messageBoxRunningZLeafFound->setInformativeText("Do you want to start a zLeaf on client " + name + " nonetheless?"); messageBoxRunningZLeafFound->setDefaultButton(QMessageBox::No); messageBoxRunningZLeafFound->exec(); } if ((messageBoxRunningZLeafFound.get() != nullptr && messageBoxRunningZLeafFound->clickedButton() == messageBoxRunningZLeafFound->button(QMessageBox::Yes)) || state != EState::ZLEAF_RUNNING) { QStringList arguments; if (argFakeName == nullptr) { arguments << "-i" << settings->pkeyPathUser << QString{settings->userNameOnClients + "@" + ip} << cmd; } else { arguments << "-i" << settings->pkeyPathUser << QString{settings->userNameOnClients + "@" + ip} << cmd << "/name" << *argFakeName; } // Start the process QProcess startZLeafProcess; startZLeafProcess.setProcessEnvironment(QProcessEnvironment::systemEnvironment()); startZLeafProcess.startDetached(settings->sshCmd, arguments); // Output message via the debug messages tab qDebug() << settings->sshCmd << arguments.join(" "); } } void lc::Client::StartClientBrowser(const QString *const argURL, const bool *const argFullscreen) { //Declarations QStringList arguments; // Build arguments list for SSH command arguments << "-i" << settings->pkeyPathUser << QString{settings->userNameOnClients + "@" + ip} << "DISPLAY=:0.0" << settings->clientBrowserCmd << *argURL; // Add fullscreen toggle if checked if (*argFullscreen == true) { arguments << "& sleep 3 && DISPLAY=:0.0 xdotool key --clearmodifiers F11"; } // Start the process QProcess startClientBrowserProcess; startClientBrowserProcess.setProcessEnvironment(QProcessEnvironment::systemEnvironment()); startClientBrowserProcess.startDetached(settings->sshCmd, arguments); // Output message via the debug messages tab qDebug() << settings->sshCmd << arguments.join(" "); } void lc::Client::StopClientBrowser() { //Declarations QStringList arguments{"-i", settings->pkeyPathUser, QString{settings->userNameOnClients + "@" + ip}, "killall", settings->clientBrowserCmd, "& sleep 1 && rm -R /home/ewfuser/.mozilla/firefox/*"}; // Start the process QProcess startClientBrowserProcess; startClientBrowserProcess.setProcessEnvironment(QProcessEnvironment::systemEnvironment()); startClientBrowserProcess.startDetached(settings->sshCmd, arguments); // Output message via the debug messages tab qDebug() << settings->sshCmd << arguments.join(" "); }