summaryrefslogtreecommitdiffstats
path: root/src/vsession.cpp
diff options
context:
space:
mode:
authorJan Darmochwal2010-10-02 18:50:09 +0200
committerJan Darmochwal2010-10-02 18:50:09 +0200
commit6117049617df720fb744a90773a3580b3450b005 (patch)
treec3b605ab7a7c2e9fd9d14572e8c0e69432d6ac76 /src/vsession.cpp
parentfixed bad copy & paste in CMakeLists.txt (diff)
downloadvmchooser-6117049617df720fb744a90773a3580b3450b005.tar.gz
vmchooser-6117049617df720fb744a90773a3580b3450b005.tar.xz
vmchooser-6117049617df720fb744a90773a3580b3450b005.zip
Qt port is almost complete (at least it compiles)
Major change: * struct DataEntry has become class Session with sub-classes XSession and VSession * functions from addInfo.cpp, addPrinters.cpp, addScanners.cpp, readLinSess.cpp, readXmlDir.cpp, runImage.cpp have been moved to XSession and VSession Several minor changes: * new files globals.h and globals.cpp for global variables (replaces constants.h and paths.h) * replaced (all) libxml2, (much) std:: and (most) boost:: stuff by Qt stuff Things left to do: * remove tons of debug printfs * show error messages on errors * tidy up anyoption stuff in main() * highlight session run previously * readGroupXml stuff * tree view (with "X Sessions" and "Virtual Sessions" sections) instead of list view for session selection
Diffstat (limited to 'src/vsession.cpp')
-rw-r--r--src/vsession.cpp295
1 files changed, 295 insertions, 0 deletions
diff --git a/src/vsession.cpp b/src/vsession.cpp
new file mode 100644
index 0000000..3fa385f
--- /dev/null
+++ b/src/vsession.cpp
@@ -0,0 +1,295 @@
+#include <QtXml>
+#include <QDir>
+#include <QApplication>
+#include <QProcess>
+#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) {
+ printf("VSession::init(xml, %s)\n", baseDirPath.toAscii().data());
+ //printf("xml = %s\n", xml.toAscii().data());
+ this->baseDirPath_ = baseDirPath;
+ return this->doc_.setContent(xml);
+}
+
+void VSession::addNodeWithAttribute(const QString& nodeName,
+ const QString& value,
+ const QString& attribute,
+ bool replace) {
+
+ printf("VSession:addNodeWithAttribute(%s, %s, %s, %d)\n",
+ nodeName.toUtf8().data(),
+ value.toUtf8().data(),
+ attribute.toUtf8().data(),
+ replace);
+
+ QDomElement node =
+ this->doc_.namedItem("eintrag").namedItem(nodeName).toElement();
+
+ if (replace == false || node.isNull()) {
+ printf(" creating new node\n");
+ // create a new node
+ node = this->doc_.createElement(nodeName);
+ this->doc_.namedItem("eintrag").appendChild(node);
+ }
+
+ printf(" setting attribute\n");
+ node.setAttribute(attribute, value);
+}
+
+QString VSession::toXml() const {
+ return this->doc_.toString();
+}
+
+QString VSession::getAttribute(const QString &nodeName,
+ const QString &attribute) const {
+ printf ("VSession::getAttribute(%s, %s)\n", nodeName.toAscii().data(), attribute.toAscii().data());
+ QDomDocument doc = this->doc_;
+ //printf (" doc xml:\n%s\n", doc.toString().toAscii().data());
+ QDomNode n = doc.namedItem("eintrag").namedItem(nodeName);
+ if (n.isNull()) {
+ printf(" failed to find node\n");
+ }
+
+ printf(" node name: %s\n", n.nodeName().toAscii().data());
+ printf(" node type: %d\n", n.nodeType());
+ printf(" node value: %s\n", n.nodeValue().toAscii().data());
+ printf(" attribute %s=%s\n", attribute.toUtf8().data(), this->doc_.namedItem("eintrag").namedItem(nodeName).toElement().attribute(attribute).toUtf8().data());
+ //printf (" --> %s\n", this->doc_.namedItem("eintrag").namedItem(nodeName).namedItem(attribute).toAttr().value());
+ 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 {
+ // default to true
+ return getAttribute("active").compare("false");
+}
+
+bool VSession::isLocked() const {
+ // default to false
+ return getAttribute("locked").compare("true") == 0;
+}
+
+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;
+ }
+
+ // TODO: check return values, exceptions, ...
+ 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() {
+ printf("VSession::addUserAndHostname()\n");
+ 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());
+}
+
+bool VSession::run() {
+
+ printf("VSession::run()\n");
+ QString command = getAttribute("command");
+ if (! command.isEmpty()) {
+ if (QProcess::startDetached(command)) {
+ // TODO: save session
+ return true;
+ }
+
+ return false;
+ }
+
+ VSession session = *this;
+
+ QString etcpath(VMCHOOSER_ETC_BASE_PATH);
+ // TODO: put script names in (global?) constants
+ session.addPrinters(etcpath + "printer.sh");
+ session.addScanners(etcpath + "scanner.sh");
+
+ session.addUserAndHostname();
+
+ // TODO: read the group configuration XML
+ //session.readGroupXml(&dat, env);
+
+ // 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);
+
+ // TODO: put script name in constant
+ QString runVmScript(QString(VMCHOOSER_BIN_PATH) + "run-virt.sh");
+ if (QProcess::startDetached(runVmScript, QStringList(tmpfile.fileName()))) {
+ // TODO: save session
+ return true;
+ }
+ return false;
+}
+
+QList<Session*> VSession::readXmlFile(const QString& filepath) {
+ printf("VSession::readXmlFile(%s)\n", filepath.toAscii().data());
+ QList<Session*> retval;
+
+ QDomDocument doc;
+ QFile file(filepath);
+ if (!file.open(QIODevice::ReadOnly)) {
+ // TODO: error message
+ printf("error: cannot open file\n");
+ return retval;
+ }
+ if (!doc.setContent(&file)) {
+ // TODO: error message
+ printf("error: cannot parse file\n");
+ file.close();
+ return retval;
+ }
+ file.close();
+
+ // TODO: iterate over all <settings> child nodes?
+ QString dirName(QFileInfo(filepath).dir().absolutePath());
+ QDomElement settingsNode = doc.firstChildElement("settings");
+ for (QDomElement el(settingsNode.firstChildElement("eintrag"));
+ !el.isNull();
+ el = el.nextSiblingElement("eintrag")) {
+ printf("reading %s node\n", el.tagName().toAscii().data());
+ QDomDocument dummy;
+ dummy.appendChild(dummy.importNode(el, true));
+ VSession* e = new VSession;
+ if (e->init(dummy.toString(), dirName)) {
+ printf("appending node\n");
+ 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) {
+ printf("VSession::readXmlDir(%s)\n", path.toAscii().data());
+ QList<Session*> retval;
+
+ QDir appDir(QApplication::applicationDirPath());
+ if (QFile::exists(appDir.filePath(filterscript))) {
+ // run filterscript
+ // treat every output line as a filename and read it
+ QProcess myFilterScript;
+ myFilterScript.start(appDir.filePath(filterscript), QStringList(path),
+ QIODevice::ReadOnly);
+ while (! myFilterScript.atEnd()) {
+ QString filename(myFilterScript.readLine());
+ if (QDir::isRelativePath(filename)) {
+ filename.prepend(path + "/");
+ }
+ retval.append(readXmlFile(filename));
+ }
+
+ myFilterScript.close();
+ } else {
+ // iterate over all .xml files in directory path and read them
+ foreach (QFileInfo fi, QDir(path).entryInfoList(QStringList("*.xml"))) {
+ retval.append(readXmlFile(fi.absoluteFilePath()));
+ }
+ }
+
+ printf("VSession::readXmlDir(%s), read %d entries\n", path.toAscii().data(), retval.size());
+ 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;
+}