summaryrefslogtreecommitdiffstats
path: root/src/VSession.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/VSession.cpp')
-rw-r--r--src/VSession.cpp356
1 files changed, 356 insertions, 0 deletions
diff --git a/src/VSession.cpp b/src/VSession.cpp
new file mode 100644
index 0000000..76e13b0
--- /dev/null
+++ b/src/VSession.cpp
@@ -0,0 +1,356 @@
+/*
+ * Copyright (c) 2010,2011 - RZ Uni Freiburg
+ * Copyright (c) 2010,2011 - OpenSLX Project
+ *
+ * This program/file is free software distributed under the GPL version 2.
+ * See http://gpl.openslx.org/
+ *
+ * If you have any feedback please consult http://feedback.openslx.org/ and
+ * send your feedback to feedback@openslx.org
+ *
+ * General information about OpenSLX - libChooser can be found under
+ * http://openslx.org
+ *
+ */
+
+#include <QtXml>
+#include <QDir>
+#include <QApplication>
+#include <QProcess>
+#include <QDate>
+#include <QStringList>
+#include <QTextStream>
+#if 0
+#include <QHostInfo> // available since Qt 4.7
+#endif
+#include <limits> // for HOST_NAME_MAX
+#include <unistd.h> // for gethostname(), getuid()
+#include <sys/types.h> // for getuid, getpwuid
+#include <pwd.h> // for getpwuid
+//#include "globals.h"
+
+#include "VSession.h"
+#include "VSessionHandler.h"
+
+bool VSession::debugMode = false;
+
+VSession::VSession(VSessionHandler *parent) {
+ sessionHandler = parent;
+}
+
+bool VSession::init(const QString& xml, const QString& baseDirPath) {
+ this->baseDirPath_ = baseDirPath;
+ _process = new QProcess();
+ return this->doc_.setContent(xml);
+}
+
+void VSession::addNodeWithAttribute(const QString& nodeName,
+ const QString& value,
+ const QString& attribute,
+ bool replace) {
+ QDomElement node =
+ this->doc_.namedItem("eintrag").namedItem(nodeName).toElement();
+
+ if (replace == false || node.isNull()) {
+ // create a new node
+ node = this->doc_.createElement(nodeName);
+ this->doc_.namedItem("eintrag").appendChild(node);
+ }
+
+ node.setAttribute(attribute, value);
+}
+
+QString VSession::icon() const {
+ QString icon(getAttribute("icon"));
+ if (icon.isEmpty()) {
+ if (imgtype() == VMWARE) icon = "vmware";
+ else if (imgtype() == VBOX) icon = "virtualbox";
+ else icon = "unknown";
+ } else if (icon.contains(".") && QDir::isRelativePath(icon)) {
+ // non-built-in icon with relative path
+ icon.prepend(baseDirPath_ + "/");
+ }
+ return icon;
+ }
+
+QString VSession::screenshot() const {
+ QString ret;
+ ret = getAttribute("screenshot");
+// qDebug() << ret;
+ if (ret.size() > 0) {
+ ret.prepend(baseDirPath_ + "/");
+ ret.prepend("file://");
+ return ret;
+ }
+ return QString("qrc:/img/noscreenshot");
+};
+
+
+QString VSession::toXml() const {
+ QDomDocument doc;
+ doc.appendChild(doc.createElement("settings"));
+
+ doc.firstChild().appendChild(doc.importNode(doc_.documentElement(), true));
+
+ QDomNode xmlNode = doc.createProcessingInstruction(
+ "xml", "version=\"1.0\" encoding=\"UTF-8\"");
+ doc.insertBefore(xmlNode, doc.firstChild());
+
+ return doc.toString();
+}
+
+QString VSession::getAttribute(const QString &nodeName,
+ const QString &attribute) const {
+ QDomDocument doc = this->doc_;
+ QDomNode n = doc.namedItem("eintrag").namedItem(nodeName);
+ return this->doc_.namedItem("eintrag").namedItem(nodeName).toElement()
+ .attribute(attribute);
+}
+
+QString VSession::getNodeText(const QString& nodeName) const {
+ QString str;
+ QTextStream stream(&str);
+ QDomNode node = this->doc_.namedItem("eintrag").namedItem(nodeName).toElement();
+ node.save(stream, 4);
+
+// return this->doc_.namedItem("eintrag").namedItem(nodeName).toElement().text();
+ return str;
+}
+
+ImgType VSession::imgtype() const {
+ QString s(getAttribute("virtualmachine"));
+
+ if (s.compare("vmware") == 0) {
+ return VMWARE;
+ } else if (s.compare("virtualbox") == 0 || s.compare("vbox") == 0) {
+ return VBOX;
+ } else {
+ return OTHER;
+ }
+}
+
+bool VSession::isActive() const {
+ QString value(getAttribute("active"));
+
+ if (value.compare("false") == 0) {
+ return false;
+ } else if (value.count("/") == 1) {
+ // try to interpret value as date range
+ // [YYYY-MM-DD]/[YYYY-MM-DD]
+ // eg. "1970-01-01/1971-01-01" from Jan 1st 1970 till Jan 1st 1971
+ // "/1971-01-01" till Jan 1st 1971
+ // "1970-01-01/" from Jan 1st 1970
+ // "/" allways
+ // note: invalid dates are treated as empty dates
+
+ QStringList list(value.split("/"));
+ QString from(list.value(0));
+ QString till(list.value(1));
+ QDate fromDate(QDate::fromString(from, Qt::ISODate));
+ QDate tillDate(QDate::fromString(till, Qt::ISODate));
+
+ QDate today(QDate::currentDate());
+
+ if (fromDate.isValid() && fromDate > today) {
+ // fromDate is in the future
+ if (debugMode) qDebug() << "Not active. Reason: fromDate is in the future";
+ return false;
+ }
+
+ if (tillDate.isValid() && tillDate < today) {
+ // tillDate is in the past
+ if (debugMode) qDebug() << "Not active. Reason: tillDate is in the past";
+ return false;
+ }
+ }
+
+ if (sessionHandler->hasEnv()) {
+ QStringList pools = getAttribute("pools").split("\\s*,\\s*");
+ if (!pools.isEmpty() && !pools.contains(sessionHandler->getEnv())) {
+ // pools does not contain pool
+ if (debugMode) qDebug() << "Not active. Reason: vsession is not part of active env";
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool VSession::isLocked() const {
+ // default to false
+ return getAttribute("locked").compare("true") == 0;
+}
+
+bool VSession::isValid() const {
+ // default to false
+ return QFile::exists(QString(this->baseDirPath_).append("/").append(getAttribute("image_name")));
+}
+
+int VSession::priority() const {
+ return getAttribute("priority").toInt();
+}
+
+
+void VSession::addPrinters(const QString& script, const QString& type) {
+ QDomElement printersNode =
+ this->doc_.namedItem("eintrag").namedItem(type + "s").toElement();
+
+ if (printersNode.isNull()) {
+ // create new printers node
+ printersNode = this->doc_.createElement(type + "s");
+ this->doc_.namedItem("eintrag").appendChild(printersNode);
+ }
+
+ QProcess addPrintersScript;
+ addPrintersScript.start(script, QIODevice::ReadOnly);
+ while (!addPrintersScript.atEnd()) {
+ QString line(addPrintersScript.readLine());
+ QStringList tokens(line.split("\t"));
+
+ if (tokens.size() < 2 or tokens.size() > 3) {
+ // TODO error message
+ // invalid output of printerScript
+ // printserver\tprinter\tprinter description
+ continue;
+ }
+
+ QDomElement printerNode(doc_.createElement(type));
+ printerNode.setAttribute("name", tokens.at(1));
+ printerNode.setAttribute("path",
+ "\\\\" + tokens.at(0) + "\\" + tokens.at(1));
+ if (tokens.size() == 3) {
+ QDomText printerDescriptionNode(doc_.createTextNode(tokens.at(3)));
+ printerNode.appendChild(printerDescriptionNode);
+ }
+ printersNode.appendChild(printerNode);
+ }
+
+ addPrintersScript.close();
+
+ return;
+}
+
+void VSession::addScanners(const QString& script) {
+ addPrinters(script, "scanner");
+}
+
+void VSession::addUserAndHostname() {
+ QString username(getpwuid(geteuid())->pw_name);
+ this->addNodeWithAttribute("username", username);
+
+ // Qt >= 4.7 has <QHostInfo>
+ // QString hostname(QHostInfo::localHostName());
+ char hname[255];
+ gethostname(hname, sizeof(hname));
+ QString hostname(hname);
+ this->addNodeWithAttribute("hostname", hostname);
+
+ QString image(this->getAttribute("image_name"));
+ if (QFileInfo(image).isRelative()) {
+ // make path to image absolute
+ this->addNodeWithAttribute("image_name",
+ this->baseDirPath_ + "/" + image);
+ }
+
+ // insert computername as the first child of <eintrag>
+ // bootpgm needs computername within the first 500 bytes
+ QDomElement computername(doc_.createElement("computername"));
+ computername.setAttribute("param", hostname);
+ this->doc_.namedItem("eintrag").insertBefore(computername, QDomNode());
+}
+
+void VSession::mergePoolXml() {
+ QDomDocument doc;
+
+ QString poolXmlFile = sessionHandler->getConfPath() + "/vmchooser-" + sessionHandler->getEnv() + ".xml";
+
+ QFile file(poolXmlFile);
+ if (!file.open(QIODevice::ReadOnly)) {
+ return;
+ }
+ if (!doc.setContent(&file)) {
+ file.close();
+ return;
+ }
+ file.close();
+
+ for (QDomElement envNode(doc.firstChildElement("environment"));
+ !envNode.isNull();
+ envNode = envNode.nextSiblingElement()) {
+ if (envNode.attribute("param") != sessionHandler->getEnv()) continue;
+
+ for (QDomElement typeNode(envNode.firstChildElement());
+ !typeNode.isNull();
+ typeNode = typeNode.nextSiblingElement()) {
+ QString type = typeNode.nodeName();
+ if (type != "shared_folders" &&
+ type != "printers" &&
+ type != "scanners") continue;
+
+ QDomElement destinationNode =
+ this->doc_.namedItem("eintrag").namedItem(type).toElement();
+
+ if (destinationNode.isNull()) {
+ // create new node
+ destinationNode = this->doc_.createElement(type);
+ this->doc_.namedItem("eintrag").appendChild(destinationNode);
+ }
+
+ for (QDomElement el(typeNode.firstChildElement());
+ !el.isNull();
+ el = el.nextSiblingElement()) {
+ destinationNode.appendChild(this->doc_.importNode(el, true));
+ }
+ }
+ }
+}
+
+bool VSession::run() const {
+ QString command = getAttribute("command");
+ if (!command.isEmpty()) {
+ return QProcess::startDetached(command);
+ }
+
+ VSession session = *this;
+
+ session.addPrinters(sessionHandler->getPrinterScript());
+ session.addScanners(sessionHandler->getScannerScript());
+
+ session.addUserAndHostname();
+
+ session.mergePoolXml();
+
+ // write xml to temporary file
+ QTemporaryFile tmpfile(QDir::tempPath() + "/vmchooser-XXXXXX.xml");
+ if (!tmpfile.open() ||
+ tmpfile.write(session.toXml().toUtf8()) == -1) {
+ return false;
+ }
+ tmpfile.close();
+ tmpfile.setAutoRemove(false);
+
+ _process->start(sessionHandler->getRunVmScript(), QStringList(tmpfile.fileName()));
+ qDebug() << sessionHandler->getRunVmScript();
+ QObject::connect(_process, SIGNAL(finished(int, QProcess::ExitStatus)), QApplication::instance(), SLOT(quit()));
+ if (_process->state() == QProcess::Starting || QProcess::Running)
+ return true;
+ else
+ return false;
+}
+
+int VSession::type() const {
+ return Session::VSESSION;
+}
+
+bool VSession::operator<(const Session& other) const {
+ int p0 = this->priority();
+ int p1 = other.priority();
+
+ if (p0 < p1) return true;
+ if (p0 == p1) {
+ QString d0 = this->shortDescription();
+ QString d1 = other.shortDescription();
+ return d0.localeAwareCompare(d1) < 0;
+ }
+ return false;
+}