Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


HVM capability enhancement: asynchronous upcalls to ROS userspace
[palacios.git] / linux_usr / gui / palacios / vm_threads.cpp
1 #include <QDebug>
2
3 #include "newpalacios.h"
4
5 class ProcVm {
6 public:
7         QString name;
8         QString devFile;
9 };
10
11 class DbVm {
12 public:
13         QString name;
14         QString config;
15         QString image;
16         int state;
17         QString dev;
18 };
19
20 int LoadVmsThread::getStatus() {
21         return status;
22 }
23
24 QList<VmInfo*> LoadVmsThread::getVmList() {
25         return list;
26 }
27
28 void LoadVmsThread::loadVms() {
29         bool doesProcExist = false;
30         bool isDbPresent = false;
31         
32         // Check if /proc file exists
33         QFileInfo procInfo("/proc/v3vee/v3-guests");
34         if (procInfo.exists()) {
35                 // Proc file exists
36                 doesProcExist = true;
37         } 
38        
39         // Read proc file
40         //QStringList procVms;
41         QList<ProcVm> procVms;
42         
43         if (doesProcExist) {
44                 QProcess* p = new QProcess();
45                 p->setProcessChannelMode(QProcess::MergedChannels);
46                 QStringList args;
47                 args << "-c" << "cat /proc/v3vee/v3-guests";
48                 p->start("sh", args);
49                 if (!p->waitForFinished()) {
50                         // Since we are unable to open the proc file
51                         // for whatever some reason, the only way
52                         // to identify this state would be to mark /proc
53                         // as not existing                        
54                         doesProcExist = false;
55                         
56                 } else {
57                         QByteArray procFile = p->readAllStandardOutput();
58                         if (!procFile.isNull()) {
59                             if (procFile.isEmpty()) {
60                                 doesProcExist = false;
61
62                             } else {
63                                 QList<QByteArray> procContents = procFile.split('\n');
64                                 
65                                 for (int i=0; i<procContents.size(); i++) {
66                                         QByteArray b = procContents.at(i);
67                                         QString procentry(b);
68                                         QStringList vals = procentry.split('\t');
69                                                                             
70                                         if (vals.size() == 2) {
71                                                 ProcVm procVm;
72                                                 QString val = vals.at(0);
73                                                 val.remove(QChar('\n'), Qt::CaseInsensitive);
74                                                 procVm.name = val;
75                                                 
76                                                 val = vals.at(1);
77                                                 val.remove(QChar('\n'), Qt::CaseInsensitive);
78                                                 procVm.devFile = val;
79                                                 procVms.append(procVm);
80                                         }
81                                 }
82                             }
83                         } 
84                 }
85                 
86                 // Delete proc process
87                 delete p;
88         }
89         
90         // Check if proc is empty
91         if (doesProcExist && procVms.size() == 0) {
92                 // There was nothing in the proc file
93                 doesProcExist = true;
94         }
95         
96         // Check if DB exists
97         QFileInfo dbFile("virtual_machines_list.txt");
98         if (dbFile.exists()) {
99                 isDbPresent = true;
100         }
101         
102         QFile file("virtual_machines_list.txt");
103         // Open DB file
104         if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
105                 // The DB file is missing
106                 isDbPresent = false;
107         }
108         
109         // Check if there is any source to load the VM
110         if (!doesProcExist && !isDbPresent) {
111                 // If proc file does not exist or is empty
112                 // and the DB does not exist then there are 
113                 // no VMs to load
114                 // return with STATUS_OK
115                 status = STATUS_OK;
116                 emit finished();
117                 return; 
118         }
119         
120         //QStringList dbVms;
121         QList<DbVm> dbVms;
122
123         if (isDbPresent) {
124                 // Read the DB file
125                 QTextStream in(&file);
126                 while (!in.atEnd()) {
127                         QString line = in.readLine();
128                         if (line.compare("\n") == 0) {
129                                 continue;
130                         }
131                 
132                         QStringList vmDet = line.split(",");
133                         DbVm dbVm;
134                         dbVm.name = vmDet.at(0);
135                         dbVm.config = vmDet.at(1);
136                         dbVm.dev = vmDet.at(2);
137                         dbVm.state = vmDet.at(3).toInt();
138                         dbVm.image = vmDet.at(4);
139                         
140                         dbVms.append(dbVm);
141                 }
142         }
143                         
144         if (!doesProcExist && isDbPresent) {
145                 // If /proc does not exist but DB does
146                 // then all VMs are inactive
147                 for (int i=0; i<dbVms.size(); i++) {
148                         VmInfo* vmDb = new VmInfo();
149                         vmDb->setVmName(dbVms[i].name);
150                         vmDb->setVmConfigFile(dbVms[i].config);
151                         vmDb->setVmDevFile(dbVms[i].dev);
152                         vmDb->setState(dbVms[i].state);
153                         vmDb->setImageFile(dbVms[i].image);
154                         vmDb->setCategory(VmInfo::INACTIVE_INVENTORY);
155                         // Add VM to loading list
156                         list.append(vmDb);
157                 }
158                                 
159         } else if (doesProcExist && !isDbPresent) {
160                 // If /proc exists but DB does not
161                 for (int i=0; i<procVms.size(); i++) {
162                         VmInfo* vmProc = new VmInfo();
163                         vmProc->setVmName(procVms[i].name);
164                         vmProc->setVmConfigFile("");
165                         vmProc->setVmDevFile(procVms[i].devFile);
166                         vmProc->setState(VmInfo::STOPPED);
167                         vmProc->setImageFile("");
168                         vmProc->setCategory(VmInfo::ACTIVE_NOT_INVENTORY);
169                         // Add VM to loading list
170                         list.append(vmProc);
171                 }
172                 
173         } else if (doesProcExist && isDbPresent) {
174                 // Both files exist
175                 // Compare entries in /proc and text file, mark non-matching entries in /proc as active not inventory
176                 QList<int> procIndices;
177                 QList<int> dbIndices;           
178                 
179                 int found = -1;
180
181                 for (int i=0; i<procVms.size(); i++) {
182                         for (int j=0; j<dbVms.size(); j++) {
183                                 if ((procVms[i].devFile.compare(dbVms[j].dev) == 0)
184                                         && (procVms[i].name.compare(dbVms[j].name) == 0)) {
185                                         found = j;
186                                         procIndices.append(i);
187                                         dbIndices.append(j);
188                                         break;
189                                 }               
190                         }
191                         
192                         if (found >= 0) {
193                                 VmInfo* vm = new VmInfo();
194                                 vm->setVmName(dbVms[found].name);
195                                 vm->setVmConfigFile(dbVms[found].config);
196                                 vm->setVmDevFile(dbVms[found].dev);
197                                 vm->setState(dbVms[found].state);
198                                 vm->setImageFile(dbVms[found].image);
199                                 
200                                 vm->setCategory(VmInfo::ACTIVE_INVENTORY);
201                                 // Add VM to loading list
202                                 list.append(vm);
203                                 found = -1;
204                         }
205                 }
206                 
207                 // Once we have compared /proc with the DB and marked matching indices
208                 // we mark the rest of the entries in /proc as active not inventory
209                 for (int j=0; j<procVms.size(); j++) {
210                         if (!procIndices.contains(j)) {
211                                 VmInfo* vmProcOnly = new VmInfo();
212                                 vmProcOnly->setVmName(procVms[j].name);
213                                 vmProcOnly->setVmConfigFile("");
214                                 vmProcOnly->setVmDevFile(procVms[j].devFile);
215                                 vmProcOnly->setState(VmInfo::STOPPED);
216                                 vmProcOnly->setImageFile("");
217                                 vmProcOnly->setCategory(VmInfo::ACTIVE_NOT_INVENTORY);
218                                 list.append(vmProcOnly);
219                         }
220                 }
221                 
222                 // Once we have compared /proc with the DB and marked matching indices
223                 // we mark the rest of the entries in dbVms as inactive
224                 for (int j=0; j<dbVms.size(); j++) {
225                         if (!dbIndices.contains(j)) {
226                                 VmInfo* vmDbOnly = new VmInfo();
227                                 vmDbOnly->setVmName(dbVms[j].name);
228                                 vmDbOnly->setVmConfigFile(dbVms[j].config);
229                                 vmDbOnly->setVmDevFile("");
230                                 vmDbOnly->setState(dbVms[j].state);
231                                 vmDbOnly->setImageFile(dbVms[j].image);
232                                 vmDbOnly->setCategory(VmInfo::INACTIVE_INVENTORY);
233                                 list.append(vmDbOnly);
234                         }
235                 }
236         }
237         
238         status = STATUS_OK;
239         file.close();
240
241         emit finished();
242 }
243
244 AddVmThread::AddVmThread(QString name, QString conf, QString img) {
245         this->status = STATUS_OK;
246         this->vmName = name;
247         this->vmConfigFile = conf;
248         this->vmImageFile = img;
249 }
250
251 int AddVmThread::getStatus() {
252         return status;
253 }
254
255 VmInfo* AddVmThread::getNewVm() {
256         return vm;
257 }
258
259 QString AddVmThread::getName() {
260         return vmName;
261 }
262
263 void AddVmThread::addVm() {
264         QFile file("virtual_machines_list.txt");
265         if (!file.open(QIODevice::Append | QIODevice::Text)) {
266                 status = ERROR_V3CREATE_DB;
267                 emit finished();
268                 return;
269         }
270         
271         // Add VM to the inventory (database). The VM still needs to be
272         // activated to run
273         // Create new VM instance
274         // The dev file for this VM will be set when it is activated
275         vm = new VmInfo();
276         vm->setVmName(vmName);
277         vm->setVmConfigFile(vmConfigFile);
278         vm->setImageFile(vmImageFile);
279         vm->setCategory(VmInfo::INACTIVE_INVENTORY);
280         
281         QTextStream out(&file);
282         
283         out << vmName;
284         out << ",";
285         out << vmConfigFile;
286         out << ",";
287         out << vmDevFile;
288         out << ",";
289         out << QString::number(VmInfo::STOPPED);
290         out << ",";
291         out << vmImageFile;
292         out << endl;
293         
294         out.flush();
295         file.close();
296         
297         status = STATUS_OK;
298
299         emit finished();
300 }
301
302 DeleteVmThread::DeleteVmThread(int category, QString name, QString devfile) {
303         this->vmCategory = category;
304         this->vmToDelete = name;
305         this->status = -2;
306         this->vmDevfile = devfile;
307 }
308
309 int DeleteVmThread::getStatus() {
310         return status;
311 }
312
313 /*void DeleteVmThread::processStarted() {
314         //qDebug() << "V3 Free process started";
315 }
316
317 void DeleteVmThread::processExit(int errorCode, QProcess::ExitStatus exitStatus) {
318         if (exitStatus == QProcess::CrashExit) {
319                 //qDebug() << "v3_free process crashed!!";
320         } else {
321                 //qDebug() << "v3_free process exited normally..";
322         }
323 }
324
325 void DeleteVmThread::processError(QProcess::ProcessError error) {
326         //qDebug() << "There was an error in the v3_free process execution...";
327         
328         switch (error) {
329         case QProcess::FailedToStart:
330                 //qDebug() << "Process failed to start...";
331                 break;
332         case QProcess::Crashed:
333                 //qDebug() << "Process crashed...";
334                 break;
335         case QProcess::Timedout:
336                 //qDebug() << "Process timed out...";
337                 break;
338         case QProcess::WriteError:
339                 //qDebug() << "Process had write error...";
340                 break;
341         case QProcess::ReadError:
342                 //qDebug() << "Process had read error...";
343                 break;
344         case QProcess::UnknownError:
345                 //qDebug() << "Process unknown error...";
346                 break;
347
348         }
349 }*/
350
351 void DeleteVmThread::deleteVm() {
352      
353      // Check for the category of VM being deleted
354      // If Active or Active not inventory then only
355      // invoke v3_free since we have an instance of the 
356      // VM in proc. If it is Inactive and we are deleting
357      // then we need to just remove it from the DB
358      
359      // Create variables
360      // C++ complains if we create variables inside switch statement
361      QProcess* v3Freeproc;
362      QStringList args;
363      QByteArray procOutput;
364      
365      switch (vmCategory) {
366      case VmInfo::ACTIVE_INVENTORY:
367      case VmInfo::ACTIVE_NOT_INVENTORY:
368         if (vmDevfile == NULL) {
369                 // Cannot delete VM without dev file
370                 status = ERROR_V3FREE_INVALID_ARGUMENT;
371                 emit finished();
372                 return;
373         }
374         
375         v3Freeproc = new QProcess();
376         v3Freeproc->setProcessChannelMode(QProcess::MergedChannels);
377         
378         // Connect debug slots
379         connect(v3Freeproc, SIGNAL(started()), this, SLOT(processStarted()));
380         connect(v3Freeproc, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(processExit(int, QProcess::ExitStatus)));
381         connect(v3Freeproc, SIGNAL(error(QProcess::ProcessError)), this, SLOT(processError(QProcess::ProcessError)));
382         
383         args << vmDevfile;
384         v3Freeproc->start("v3_free", args);
385         
386         if (!v3Freeproc->waitForFinished()) {
387                 // Reinsert data into database since v3_free was not successful
388                 status = ERROR_V3FREE_PATH;
389                 delete v3Freeproc;
390                 emit finished();
391                 return;
392         } else {
393                 procOutput = v3Freeproc->readAllStandardOutput();
394
395                 if (procOutput.contains("IOCTL error")) {
396                         status = ERROR_V3FREE_IOCTL;
397                         delete v3Freeproc;
398                         emit finished();
399                         return;
400                 }
401         }
402                                 
403         // V3_free success
404         if (v3Freeproc != NULL) {
405                 delete v3Freeproc;
406         }
407         
408         break;
409      case VmInfo::INACTIVE_INVENTORY:
410      default:
411         break;
412      }
413      
414      QFile file("virtual_machines_list.txt");
415      QFile tempFile("temp.txt");
416
417      bool oldFile = file.open(QIODevice::ReadOnly | QIODevice::Text);
418      bool newFile = tempFile.open(QIODevice::WriteOnly | QIODevice::Text);
419
420      if (!oldFile || !newFile) {
421         status = ERROR_V3FREE_DB;
422         emit finished();
423         return;
424      }
425
426      QTextStream in(&file);
427      QTextStream out(&tempFile);
428
429      while (!in.atEnd()) {
430         QString line = in.readLine();
431         QStringList vm = line.split(",");
432         if (vm.at(0).compare(vmToDelete) != 0) {
433                 out << line << endl;
434         }
435      }
436
437     out.flush();
438     file.remove("virtual_machines_list.txt");
439     tempFile.rename("virtual_machines_list.txt");
440       
441     file.close();
442     tempFile.close();
443     status = STATUS_OK;
444         
445     emit finished();
446 }