NCL Composer  0.1.5
 All Classes Functions Variables Pages
RunRemoteGingaVM.cpp
1 /* Copyright (c) 2011-2012 Telemidia/PUC-Rio.
2  * All rights reserved. This program and the accompanying materials
3  * are made available under the terms of the Eclipse Public License v1.0
4  * which accompanies this distribution, and is available at
5  * http://www.eclipse.org/legal/epl-v10.html
6  *
7  * Contributors:
8  * Telemidia/PUC-Rio - initial API and implementation
9  */
10 #include "RunRemoteGingaVM.h"
11 
12 #include <QtXml>
13 #include <QDomDocument>
14 #include <QStack>
15 #include <QStringList>
16 #include <QFile>
17 #include <QDir>
18 #include <QFileInfo>
19 
20 #include <QMessageBox>
21 #include <QApplication>
22 #include <iostream>
23 
24 #include <core/util/ComposerSettings.h>
25 using namespace composer::core::util;
26 
27 void RunRemoteGingaVMAction::setCurrentProject(Project *project)
28 {
29  this->project = project;
30 }
31 
32 QStringList RunRemoteGingaVMAction::filesToSendToGingaVM(Project *project,
33  QString nclLocalPath)
34 {
35  QStringList filesToSend;
36  QFileInfo fileInfo(project->getLocation());
37  QString absoluteFilePath = fileInfo.path();
38 
39 // qDebug() << "############ ABSOLUTE PATH: " << absoluteFilePath << endl;
40  QDirIterator it(absoluteFilePath, QDirIterator::Subdirectories);
41  while (it.hasNext()) {
42  QString file = it.next();
43  if(!file.endsWith("."))
44  {
45  filesToSend << file;
46 // qDebug() << file;
47  }
48  }
49 
50  // Search the files for all required files.
51  /* QStack <Entity*> stack;
52  Entity *current = project;
53  stack.push(current);
54  while(stack.size())
55  {
56  current = stack.top();
57  stack.pop();
58 
59  QString path = "", fullpath = "";
60  if(current->hasAttribute("src"))
61  path = current->getAttribute("src");
62  if(current->hasAttribute("documentURI"))
63  path = current->getAttribute("documentURI");
64  if(current->hasAttribute("focusSrc"))
65  path = current->getAttribute("focusSrc");
66  if(current->hasAttribute("focusSelSrc"))
67  path = current->getAttribute("focusSelSrc");
68 
69  qDebug() << "path " << path;
70 
71  // Fix the fullpath if it is necessary
72  if(path != "")
73  {
74  fullpath = path;
75  QFileInfo fileInfo (fullpath);
76  if(fileInfo.exists())
77  {
78  fullpath = fileInfo.absoluteFilePath();
79  }
80  else
81  {
82  fileInfo.setFile(nclLocalPath);
83  QString tmp = fileInfo.absoluteDir().absolutePath();
84  tmp += QDir::separator();
85  tmp += fullpath;
86  fileInfo.setFile(tmp);
87 
88  if(fileInfo.exists())
89  fullpath = fileInfo.absoluteFilePath();
90  }
91 
92  if(fullpath != "")
93  filesToSend << fullpath;
94  }
95 
96  QVector <Entity*> children = current->getChildren();
97  for(int i = 0; i < children.size(); i++)
98  {
99  stack.push(children[i]);
100  }
101  }*/
102  return filesToSend;
103 }
104 
105 bool RunRemoteGingaVMAction::sendFilesToGingaVM(SimpleSSHClient &sshclient,
106  QString baseLocalPath,
107  QString baseRemotePath,
108  QStringList filesToSend)
109 {
110  int ret = 1;
111 
112  // \todo This search MUST BE RECURSIVE!!!
113  // \todo This also can be a function.
114 
115  if(!baseRemotePath.endsWith("/"))
116  baseRemotePath.append("/");
117 
118  // This will force the creation of the baseRemotePath if it does not exists
119  // filesToSend.prepend(baseRemotePath);
120  qDebug() << "Must send these files:" << filesToSend;
121 
122  emit taskDescription(tr("Sending files to remote machine..."));
123  emit taskMaximumValue(filesToSend.size());
124 
125  // Force the creation of remotePath (in case it does not exist)
126  QString mkdir = "mkdir -p ";
127  mkdir += baseRemotePath;
128 
129  qDebug() << "Running command = " << mkdir;
130  ret = !sshclient.exec_cmd(mkdir.toStdString().c_str());
131 
132  for(int i = 0; i < filesToSend.size(); i++)
133  {
134  if(mustStop) break;
135 
136  emit taskValue(i);
137 
138  int resp = 0;
139  QString fullpath = filesToSend.at(i);
140  if(fullpath.contains(baseLocalPath))
141  {
142  QString relativePath = fullpath.mid(baseLocalPath.size()+1);
143  QString relativePathDir = relativePath.mid(0, relativePath.lastIndexOf("/")+1);
144  QFileInfo fileInfo(fullpath);
145 
146  if(fileInfo.isFile())
147  {
148  qWarning() << "Sending file = " << fullpath <<
149  " to " << baseRemotePath + relativePathDir;
150 
151  resp = sshclient.sftp_copy_file( fullpath.toStdString().c_str(),
152  (baseRemotePath+relativePathDir).toStdString().c_str());
153  }
154  else
155  {
156  QString mkdir = "mkdir -p ";
157  mkdir += baseRemotePath + relativePath;
158 
159  qWarning() << "Running command = " << mkdir;
160  resp = sshclient.exec_cmd(mkdir.toStdString().c_str());
161  }
162  }
163 
164  ret = ret && !resp;
165  }
166 
167  return ret;
168 }
169 
170 bool RunRemoteGingaVMAction::fixSrcsFromNCLFile(const QString &nclLocalPath)
171 {
172  // Fix all the paths in the nclFile.
173  QFile tmpXmlFile(nclLocalPath);
174  QDomDocument document("doc");
175  document.setContent(&tmpXmlFile);
176  QStack <QDomElement> elements;
177  elements.push(document.documentElement());
178  while(elements.size())
179  {
180  QDomElement current = elements.top();
181  elements.pop();
182 
183  if(current.hasAttribute("uniqueEntityId"))
184  current.removeAttribute("uniqueEntityId");
185 
186  if(current.hasAttribute("src"))
187  {
188  QString src = current.attribute("src");
189  int start = src.lastIndexOf(QDir::separator());
190  src = src.mid(start+1);
191  current.setAttribute("src", src);
192  qDebug() << src;
193  }
194  if(current.hasAttribute("documentURI"))
195  {
196  QString src = current.attribute("documentURI");
197  int start = src.lastIndexOf(QDir::separator());
198  src = src.mid(start+1);
199  current.setAttribute("documentURI", src);
200  }
201  if(current.hasAttribute("focusSrc"))
202  {
203  QString src = current.attribute("focusSrc");
204  int start = src.lastIndexOf(QDir::separator());
205  src = src.mid(start+1);
206  current.setAttribute("focusSrc", src);
207  }
208  if(current.hasAttribute("focusSelSrc"))
209  {
210  QString src = current.attribute("focusSelSrc");
211  int start = src.lastIndexOf(QDir::separator());
212  src = src.mid(start+1);
213  current.setAttribute("focusSelSrc", src);
214  }
215 
216  QDomElement child = current.firstChildElement();
217  while(!child.isNull())
218  {
219  elements.push_back(child);
220  child = child.nextSiblingElement();
221  }
222  }
223  tmpXmlFile.close();
224 
225  // Replace the old XML file with the with the new source fixed!!!
226  if (tmpXmlFile.open( QIODevice::WriteOnly ))
227  {
228  QTextStream textStream(&tmpXmlFile);
229  textStream << document.toString() ;
230  tmpXmlFile.close();
231  }
232  else
233  qWarning() << "I couldn't fix the path in XML file, probably it will "
234  << "not run!!";
235 
236  return true;
237 }
238 
239 void RunRemoteGingaVMAction::runCurrentProject()
240 {
241  mustStop = false;
242 
243  emit startTask();
244 // emit taskMaximumValue(3);
245 
246  // Checks if there is a current NCL project.
247  QString location = project->getLocation();
248 
249  emit taskDescription(tr("Getting remote connection configuration"));
250  // Getting the settings user data.
251  GlobalSettings settings;
252  settings.beginGroup("runginga");
253  QString remoteIp = settings.value("remote_ip").toString();
254  QString remoteUser = settings.value("remote_user").toString();
255  QString remotePasswd = settings.value("remote_password").toString();
256  QString remotePath = settings.value("remote_path").toString();
257  QString remoteCmd = settings.value("remote_start_cmd").toString();
258  settings.endGroup();
259 
260  /*\todo Put the code to run the remote NCL */
261  SimpleSSHClient sshclient(remoteUser.toStdString().c_str(),
262  remotePasswd.toStdString().c_str(),
263  remoteIp.toStdString().c_str(),
264  remotePath.toStdString().c_str());
265 
266  // emit taskValue(1);
267  emit taskDescription(tr("Trying to connect to machine from IP: %1").
268  arg(remoteIp));
269 
270 
271  qWarning() << "Trying to connect to remote machine...";
272 
273  int connRet = sshclient.doConnect();
274 
275  if( connRet != 0 && !mustStop)
276  {
277  qWarning() << "Could not connect to remote machine...";
278  emit finished();
279  return;
280  }
281 
282  QFileInfo fileNCLInfo (location);
283  QString tmpNCLDir = fileNCLInfo.absoluteDir().absolutePath();
284  QString nclLocalPath = tmpNCLDir;
285  nclLocalPath += "/";
286  nclLocalPath += "tmp.ncl";
287 
288  emit taskDescription(tr("Computing files to transmit..."));
289 
290  /* First, get the list of files to send */
291  QStringList filesToSend = filesToSendToGingaVM(project, nclLocalPath);
292  /* and send them to Ginga VM*/
293 
294  if(!mustStop &&
295  sendFilesToGingaVM(sshclient, tmpNCLDir, remotePath, filesToSend))
296  {
297  emit copyFinished();
298  /* Now, fix all the paths from NCL, and send the NCL file*/
299  QFile file(nclLocalPath);
300  if(file.open(QFile::WriteOnly | QIODevice::Truncate))
301  {
302  /* Write FILE!! */
303  if(project->getChildren().size())
304  file.write(project->getChildren().at(0)->toString(0, false).toAscii());
305 
306  file.close();
307 
308 // if(fixSrcsFromNCLFile(nclLocalPath))
309 // {
310  /* RUNNING GINGA */
311  sshclient.sftp_copy_file(nclLocalPath.toStdString().c_str(),
312  remotePath.toStdString().c_str());
313  QString cmd = remoteCmd;
314  cmd += " ";
315  cmd += remotePath + "/tmp.ncl";
316  if(!mustStop)
317  sshclient.exec_cmd(cmd.toStdString().c_str());
318 // }
319  }
320  else
321  {
322  qWarning() << "Error trying to run NCL. Could not create : "
323  << nclLocalPath << " !";
324  }
325  }
326  else
327  {
328  qWarning() << "Error copying the dependency files";
329  }
330 
331  sshclient.doDisconnect();
332 
333  emit finished();
334 }
335 
336 void RunRemoteGingaVMAction::stopExecution()
337 {
338  qDebug() << "RunRemoteGingaVMAction::stopExecution";
339  mustStop = true;
340  emit taskDescription(tr("Cancelling..."));
341 
342  emit finished();
343 }
344 
345 void StopRemoteGingaVMAction::stopRunningApplication()
346 {
347  // Getting the settings user data.
348  GlobalSettings settings;
349  settings.beginGroup("runginga");
350  QString remoteIp = settings.value("remote_ip").toString();
351  QString remoteUser = settings.value("remote_user").toString();
352  QString remotePasswd = settings.value("remote_password").toString();
353  QString remotePath = settings.value("remote_path").toString();
354  QString remoteStopCmd = settings.value("remote_stop_cmd").toString();
355  settings.endGroup();
356 
357  /*\todo Put the code to run the remote NCL */
358  SimpleSSHClient sshclient(remoteUser.toStdString().c_str(),
359  remotePasswd.toStdString().c_str(),
360  remoteIp.toStdString().c_str(),
361  remotePath.toStdString().c_str());
362 
363  int connRet = sshclient.doConnect();
364  if( connRet != 0)
365  {
366  qWarning() << "Could not connect to remote machine...";
367  return;
368  }
369 
370  sshclient.exec_cmd(remoteStopCmd.toStdString().c_str());
371  sshclient.doDisconnect();
372 }