summaryrefslogtreecommitdiffstats
path: root/src/vsession.cpp
diff options
context:
space:
mode:
authorNils Schwabe2014-03-03 15:14:20 +0100
committerNils Schwabe2014-03-03 15:14:20 +0100
commit030d91e628a2ecd5634376c9c4d903a1fa0fb423 (patch)
tree227029e3b48deb1d4d01ce497d9ec3b8d47f7a61 /src/vsession.cpp
parentInitial commit (diff)
downloadvmchooser2-030d91e628a2ecd5634376c9c4d903a1fa0fb423.tar.gz
vmchooser2-030d91e628a2ecd5634376c9c4d903a1fa0fb423.tar.xz
vmchooser2-030d91e628a2ecd5634376c9c4d903a1fa0fb423.zip
added files from vmchooser1
Diffstat (limited to 'src/vsession.cpp')
-rw-r--r--src/vsession.cpp405
1 files changed, 405 insertions, 0 deletions
diff --git a/src/vsession.cpp b/src/vsession.cpp
new file mode 100644
index 0000000..e9059f2
--- /dev/null
+++ b/src/vsession.cpp
@@ -0,0 +1,405 @@
+#include <QtXml>
+#include <QDir>
+#include <QApplication>
+#include <QProcess>
+#include <QDate>
+#include <QStringList>
+#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"
+
+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::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 {
+ return this->doc_.namedItem(nodeName).toText().data();
+}
+
+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 (!pool.isEmpty()) {
+ QStringList pools = getAttribute("pools").split("\\s*,\\s*");
+ if (!pools.isEmpty() && !pools.contains(pool)) {
+ // 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[HOST_NAME_MAX + 1];
+ gethostname(hname, HOST_NAME_MAX);
+ 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 = etcPath + "/vmchooser-" + pool + ".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") != pool) 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(printerScript);
+ session.addScanners(scannerScript);
+
+ 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(runVmScript, QStringList(tmpfile.fileName()));
+ 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;
+}
+
+QList<Session*> VSession::readXmlFile(const QString& filepath) {
+ QList<Session*> retval;
+
+ QDomDocument doc;
+ QFile file(filepath);
+ if (!file.open(QIODevice::ReadOnly)) {
+ // TODO: error message
+ return retval;
+ }
+ if (!doc.setContent(&file)) {
+ // TODO: error message
+ file.close();
+ return retval;
+ }
+ file.close();
+
+ QString dirName(QFileInfo(filepath).dir().absolutePath());
+ QDomElement settingsNode = doc.firstChildElement("settings");
+ for (QDomElement el(settingsNode.firstChildElement("eintrag"));
+ !el.isNull();
+ el = el.nextSiblingElement("eintrag")) {
+ QDomDocument dummy;
+ dummy.appendChild(dummy.importNode(el, true));
+ VSession* e = new VSession;
+ if (e->init(dummy.toString(), dirName)) {
+ retval.append(e);
+ }
+ }
+ return retval;
+}
+
+/**
+ * - calls xmlfilter.sh to glob a folder for xmls
+ * -> if no xmlfilter.sh is available, it globs for available xmls
+ * - reads all xml files and creates for each its own VSession-struct
+ */
+QList<Session*> VSession::readXmlDir(const QString& path) {
+ QList<Session*> retval;
+
+ if (QFile::exists(filterScript)) {
+ // run filterScript
+ // treat every output line as a filename and read it
+ QProcess myFilterScript;
+ myFilterScript.start(filterScript, QStringList(path),
+ QIODevice::ReadOnly);
+ myFilterScript.waitForFinished();
+ while (!myFilterScript.atEnd()) {
+ QString filename(myFilterScript.readLine());
+ filename = filename.trimmed();
+ if (QDir::isRelativePath(filename)) {
+ filename.prepend(path + "/");
+ }
+ retval.append(readXmlFile(filename));
+ }
+
+ myFilterScript.close();
+ } else {
+ // iterate over all .xml files in directory <path> (and sub-directories)
+ // and read them
+ QDirIterator di(path,
+ QDirIterator::Subdirectories |
+ QDirIterator::FollowSymlinks);
+ while (di.hasNext()) {
+ if (!di.next().endsWith(".xml")) continue;
+
+ if (!di.fileInfo().isReadable()) {
+ if (debugMode) qDebug() << "skip" << di.fileInfo().absoluteFilePath() << ": xml not readable, incorrect file permissions";
+ continue;
+ }
+
+ QList<Session*> vsessionTmp = readXmlFile(di.fileInfo().absoluteFilePath());
+
+ if (vsessionTmp.isEmpty()) {
+ if (debugMode) qDebug() << "skip" << di.fileInfo().absoluteFilePath() << ": reading xml failed for some reason";
+ continue;
+ }
+
+ if (!vsessionTmp.first()->isValid()) {
+ if (debugMode) qDebug() << "skip" << vsessionTmp.first()->shortDescription() << ": vdi/vmdk missing";
+ continue;
+ }
+
+ if (!vsessionTmp.first()->isActive()) {
+ if (debugMode) qDebug() << "skip" << vsessionTmp.first()->shortDescription() << ": not active";
+ continue;
+ }
+
+ retval.append(vsessionTmp);
+ }
+ }
+ return retval;
+}
+
+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;
+}