From 030d91e628a2ecd5634376c9c4d903a1fa0fb423 Mon Sep 17 00:00:00 2001 From: Nils Schwabe Date: Mon, 3 Mar 2014 15:14:20 +0100 Subject: added files from vmchooser1 --- src/vsession.cpp | 405 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 405 insertions(+) create mode 100644 src/vsession.cpp (limited to 'src/vsession.cpp') 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 +#include +#include +#include +#include +#include +#if 0 +#include // available since Qt 4.7 +#endif +#include // for HOST_NAME_MAX +#include // for gethostname(), getuid() +#include // for getuid, getpwuid +#include // 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 + // 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 + // 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 VSession::readXmlFile(const QString& filepath) { + QList 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 VSession::readXmlDir(const QString& path) { + QList 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 (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 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; +} -- cgit v1.2.3-55-g7522