4 #include <QtAlgorithms>
6 #include "newpalacios.h"
9 NewPalacios::NewPalacios(QWidget *parent) :
12 // Call UI setup methods
14 createCentralWidget();
20 readExistingVmsFile();
22 setWindowTitle(tr(TITLE_MAIN_WINDOW));
24 mExitAppFromMenu = false;
27 NewPalacios::~NewPalacios() {
46 delete mVmCtrlToolBar;
48 /*if (mLoadVmsThread != NULL)
49 delete mLoadVmsThread;
50 if (mAddVmThread != NULL)
52 if (mDeleteVmThread != NULL)
53 delete mDeleteVmThread;*/
56 delete mVmTelemetryView;
60 // Delete the central widget at the end
61 delete mVmControlPanel;
64 void NewPalacios::createCentralWidget() {
65 // The VM View will be the central widget
66 // of this window. The List of VMs will
67 // be docked in the left corner
68 mVmControlPanel = new QTabWidget();
69 mVmControlPanel->setTabsClosable(true);
70 connect(mVmControlPanel, SIGNAL(tabCloseRequested(int)),
71 this, SLOT(vmTabClosed(int)));
73 mVmInfoWidget = new VmInfoWidget(mVmControlPanel);
75 // Set the widget to the window
76 this->setCentralWidget(mVmControlPanel);
79 void NewPalacios::createActions() {
80 mVmNew = new QAction(QIcon(":/images/images/new_vm.png"),
81 tr(FILE_MENU_NEW_VM), this);
82 connect(mVmNew, SIGNAL(triggered()), this, SLOT(createVmInstance()));
84 mExitApp = new QAction(QIcon(":/images/images/exit.png"),
85 tr(FILE_MENU_EXIT), this);
86 connect(mExitApp, SIGNAL(triggered()), this, SLOT(exitApplication()));
88 mVmStart = new QAction(QIcon(":/images/images/start_vm.png"),
89 tr(VM_MENU_START), this);
90 connect(mVmStart, SIGNAL(triggered()), this, SLOT(selectVmMode()));
92 mVmStop = new QAction(QIcon(":/images/images/stop_vm.png"),
93 tr(VM_MENU_STOP), this);
94 connect(mVmStop, SIGNAL(triggered()), this, SLOT(stopVm()));
96 mVmPause = new QAction(QIcon(":/images/images/pause_vm.png"),
97 tr(VM_MENU_PAUSE), this);
98 connect(mVmPause, SIGNAL(triggered()), this, SLOT(pauseVm()));
100 mVmActivate = new QAction(QIcon(":/images/images/activate_vm.png"),
101 tr(VM_MENU_ACTIVATE), this);
102 connect(mVmActivate, SIGNAL(triggered()), this, SLOT(activateVm()));
104 mAboutApp = new QAction(tr(HELP_MENU_ABOUT), this);
105 connect(mAboutApp, SIGNAL(triggered()), this, SLOT(aboutPalacios()));
107 mReloadVms = new QAction(QIcon(":/images/images/reload_vm.png"), tr(VM_MENU_RELOAD), this);
108 connect(mReloadVms, SIGNAL(triggered()), this, SLOT(reloadVms()));
110 connect(mVmWizard, SIGNAL(accepted()), this, SLOT(addNewVm()));
113 void NewPalacios::createMenus() {
114 mFileMenu = menuBar()->addMenu(tr(MENU_FILE));
115 mFileMenu->addAction(mVmNew);
116 mFileMenu->addSeparator();
117 mFileMenu->addAction(mExitApp);
119 mViewMenu = menuBar()->addMenu(tr(MENU_VIEW));
121 mVmMenu = menuBar()->addMenu(tr(MENU_VM));
122 mVmMenu->addAction(mVmStart);
123 mVmMenu->addAction(mVmStop);
124 mVmMenu->addAction(mVmPause);
125 mVmMenu->addAction(mVmActivate);
126 mVmMenu->addAction(mReloadVms);
128 mHelpMenu = menuBar()->addMenu(tr(MENU_HELP));
129 mHelpMenu->addAction(mAboutApp);
132 void NewPalacios::createToolBars() {
133 mVmToolBar = addToolBar(tr(MENU_FILE));
134 mVmToolBar->addAction(mVmNew);
136 mVmCtrlToolBar = addToolBar(tr(MENU_VM));
137 mVmCtrlToolBar->addAction(mVmStart);
138 mVmCtrlToolBar->addAction(mVmStop);
139 mVmCtrlToolBar->addAction(mVmPause);
140 mVmCtrlToolBar->addAction(mVmActivate);
141 mVmCtrlToolBar->addAction(mReloadVms);
144 void NewPalacios::createStatusBar() {
145 statusBar()->showMessage(tr(STATUS_BAR_MSG_READY));
148 void NewPalacios::createDockWindows() {
149 QDockWidget* dockVmList = new QDockWidget(tr(TITLE_DOCK_VM_LIST), this);
151 // Setup VM instance tree view
152 mVmTreeView = new QTreeWidget(dockVmList);
153 mVmTreeView->setColumnCount(1);
154 mVmTreeView->headerItem()->setHidden(true);
155 // Header for active VMs
156 QTreeWidgetItem* activeVms = new QTreeWidgetItem(mVmTreeView);
157 activeVms->setText(0, tr(LABEL_ACTIVE_INVENTORY));
158 mVmTreeView->addTopLevelItem(activeVms);
160 // Header for inactive VMs in the inventory
161 QTreeWidgetItem* inactiveVms = new QTreeWidgetItem(mVmTreeView);
162 inactiveVms->setText(0, tr(LABEL_INACTIVE_INVENTORY));
163 mVmTreeView->addTopLevelItem(inactiveVms);
165 // Header for active VMs not in inventory
166 QTreeWidgetItem* activeNotInventoryVms = new QTreeWidgetItem(mVmTreeView);
167 activeNotInventoryVms->setText(0, tr(LABEL_ACTIVE_NOT_INVENTORY));
168 mVmTreeView->addTopLevelItem(activeNotInventoryVms);
170 mVmTreeView->setContextMenuPolicy(Qt::CustomContextMenu);
171 connect(mVmTreeView, SIGNAL(customContextMenuRequested(const QPoint &)),
172 this, SLOT(vmContextMenu(const QPoint &)));
173 connect(mVmTreeView, SIGNAL(itemClicked(QTreeWidgetItem*, int)), this,
174 SLOT(vmItemClickListener(QTreeWidgetItem*, int)));
176 dockVmList->setAllowedAreas(Qt::LeftDockWidgetArea);
177 dockVmList->setFeatures(QDockWidget::DockWidgetClosable);
178 dockVmList->setWidget(mVmTreeView);
179 addDockWidget(Qt::LeftDockWidgetArea, dockVmList);
180 mViewMenu->addAction(dockVmList->toggleViewAction());
183 QDockWidget* dockTelemetry = new QDockWidget(tr(TITLE_DOCK_TELEMETRY), this);
184 mVmTelemetryView = new QTextEdit(dockTelemetry);
185 mVmTelemetryView->setReadOnly(true);
186 dockTelemetry->setAllowedAreas(Qt::BottomDockWidgetArea);
187 dockTelemetry->setFeatures(QDockWidget::NoDockWidgetFeatures);
188 dockTelemetry->setWidget(mVmTelemetryView);
189 addDockWidget(Qt::BottomDockWidgetArea, dockTelemetry);
190 connect(dockTelemetry, SIGNAL(visibilityChanged(bool)), this, SLOT(updateTelemetry(bool)));
193 void NewPalacios::updateTelemetry(bool visible) {
195 mTelemProc = new QProcess();
196 mTelemProc->setProcessChannelMode(QProcess::MergedChannels);
198 args << "-c" << "tail -f /var/log/messages";
200 // Slots used for debugging
201 //connect(mTelemProc, SIGNAL(started()), this, SLOT(processStarted()));
202 //connect(mTelemProc, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(processExit(int, QProcess::ExitStatus)));
203 //connect(mTelemProc, SIGNAL(error(QProcess::ProcessError)), this, SLOT(processError(QProcess::ProcessError)));
205 // Connect output of dmesg to text widget
206 connect(mTelemProc, SIGNAL(readyReadStandardOutput()), this, SLOT(updateTelemetryView()));
208 mTelemProc->start("sh", args);
209 if (!mTelemProc->waitForStarted()) {
210 if (mVmTelemetryView != NULL) {
211 mVmTelemetryView->setText(tr(ERROR_TELEMETRY));
215 /*if (mTelemProc != NULL) {
217 mTelemProc->terminate();
223 void NewPalacios::updateTelemetryView() {
224 if (mVmTelemetryView != NULL && mTelemProc != NULL) {
225 mVmTelemetryView->setText(mTelemProc->readAllStandardOutput());
229 void NewPalacios::createWizard() {
230 mVmWizard = new NewVmWizard();
233 // Listener for VM item clicks
234 void NewPalacios::vmItemClickListener(QTreeWidgetItem* item, int col) {
235 if (item->text(0).compare(LABEL_ACTIVE_INVENTORY) == 0
236 || item->text(0).compare(LABEL_INACTIVE_INVENTORY) == 0
237 || item->text(0).compare(LABEL_ACTIVE_NOT_INVENTORY) == 0) {
238 // If user clicks on the main headers
240 isHeaderClicked = true;
244 isHeaderClicked = false;
246 QString vmName = item->text(col);
249 // Locate the VM clicked in the list. This is inefficient because each time we need
250 // to search the list. If a better way is found. replace here
252 for (int i = 0; i < mVmList.size(); i++) {
253 if (vmName.compare(mVmList[i]->getVmName()) == 0) {
259 // Load the details of the seleted VM
261 mVmInfoWidget->updateInfoView(vm);
265 void NewPalacios::vmContextMenu(const QPoint &pos) {
266 //QPoint globalPos = mVmListView->mapToGlobal(pos);
267 QPoint globalPos = mVmTreeView->mapToGlobal(pos);
269 QTreeWidgetItem* item = mVmTreeView->itemAt(pos);
270 if (item->text(0).compare(LABEL_ACTIVE_INVENTORY) == 0
271 || item->text(0).compare(LABEL_INACTIVE_INVENTORY) == 0
272 || item->text(0).compare(LABEL_ACTIVE_NOT_INVENTORY) == 0) {
273 // Clicked on the headers
275 isHeaderClicked = true;
279 isHeaderClicked = false;
281 // Update VM pos, the global index locator for VMs
282 QString vmName = item->text(0);
283 // Update global VM name
285 for (int i=0; i<mVmList.size(); i++) {
286 if (vmName.compare(mVmList[i]->getVmName()) == 0) {
292 QMenu *menu = new QMenu();
293 if (mVmList[mVmPos]->getCategory() == VmInfo::INACTIVE_INVENTORY
294 || mVmList[mVmPos]->getCategory() == VmInfo::ACTIVE_NOT_INVENTORY) {
296 menu->addAction(new QAction(tr(VM_MENU_ACTIVATE), this));
298 if (mVmList[mVmPos]->getState() == VmInfo::RUNNING) {
299 menu->addAction(new QAction(tr(VM_MENU_PAUSE), this));
301 } else if (mVmList[mVmPos]->getState() == VmInfo::PAUSED) {
302 menu->addAction(new QAction(tr(VM_MENU_RESTART), this));
304 } else if (mVmList[mVmPos]->getState() == VmInfo::STOPPED) {
305 menu->addAction(new QAction(tr(VM_MENU_START), this));
309 menu->addAction(new QAction(tr(VM_MENU_STOP), this));
312 menu->addAction(new QAction(tr(VM_MENU_REMOVE), this));
314 QAction* selectedAction = menu->exec(globalPos);
315 if (selectedAction == NULL) {
316 // User did not select any option
320 QString actionItem = selectedAction->text();
321 if (actionItem.compare(tr(VM_MENU_START)) == 0
322 || actionItem.compare(tr(VM_MENU_RESTART)) == 0) {
323 // If VM was stopped or paused
326 } else if (actionItem.compare(tr(VM_MENU_PAUSE)) == 0) {
330 } else if (actionItem.compare(tr(VM_MENU_RESTART)) == 0) {
334 } else if (actionItem.compare(tr(VM_MENU_STOP)) == 0) {
335 // Stop the VM if possible
338 } else if (actionItem.compare(tr(VM_MENU_REMOVE)) == 0) {
339 bool isVmRunning = false;
340 for (int i=0; i < mRunningVms.size(); i++) {
341 if (mVmName.compare(mRunningVms[i]->getVmName()) == 0) {
347 QMessageBox vmDeleteWarningBox;
350 vmDeleteWarningBox.setText(DELETE_RUNNING_VM_ERROR);
351 vmDeleteWarningBox.setIcon(QMessageBox::Critical);
353 vmDeleteWarningBox.setText(VM_DELETE_WARNING_MESSAGE);
354 vmDeleteWarningBox.setIcon(QMessageBox::Warning);
357 vmDeleteWarningBox.setStandardButtons(
358 QMessageBox::Ok | QMessageBox::Cancel);
359 vmDeleteWarningBox.setDefaultButton(QMessageBox::Cancel);
360 int retVal = vmDeleteWarningBox.exec();
363 case QMessageBox::Ok:
368 case QMessageBox::Cancel:
372 } else if (actionItem.compare(tr(VM_MENU_ACTIVATE)) == 0) {
379 void NewPalacios::aboutPalacios() {
380 QMessageBox::about(this, tr(HELP_MENU_ABOUT), tr(ABOUT_PALACIOS));
383 // This function checks for the necessary setup
384 // required by palacios to run. The setup for palacios
386 // 1. Check for v3vee.ko module
387 // 2. Check if palacios has been allocated memory
388 void NewPalacios::checkPalacios() {
390 QMessageBox setupError;
391 setupError.setStandardButtons(QMessageBox::Ok);
392 setupError.setIcon(QMessageBox::Critical);
395 QProcess* v3 = new QProcess();
396 v3->setProcessChannelMode(QProcess::MergedChannels);
398 v3->waitForFinished();
399 QByteArray reply = v3->readAllStandardOutput();
401 if (reply.isEmpty() || !reply.contains("v3vee")) {
402 setupError.setText(tr(ERROR_SETUP_MODULE_INSTALL));
406 QFile file("/proc/v3vee/v3-mem");
407 if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
408 setupError.setText(tr(ERROR_SETUP_MODULE_INSTALL_FAILED));
412 QTextStream in(&file);
415 QString line = in.readLine();
416 if (line.contains("null")) {
417 setupError.setText(tr(ERROR_SETUP_MEMORY));
424 int ret = setupError.exec();
426 if (ret == QMessageBox::Ok) {
427 // Palacios not setup correctly, exit
433 void NewPalacios::closeEvent(QCloseEvent* event) {
434 if (mExitAppFromMenu == true) {
441 for (int i=0; i<mVmList.size(); i++) {
442 if (mVmList[i]->getState() == VmInfo::RUNNING) {
449 if (mTelemProc != NULL) {
451 mTelemProc->terminate();
457 QMessageBox appCloseWarning;
458 appCloseWarning.setText(tr("There are still running VMs. It is suggested to close the running VMs tab before exiting. Click cancel to go back"));
459 appCloseWarning.setIcon(QMessageBox::Warning);
460 appCloseWarning.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
462 int ret = appCloseWarning.exec();
464 case QMessageBox::Ok:
467 case QMessageBox::Cancel:
474 void NewPalacios::exitApplication() {
475 QMessageBox appCloseWarning;
476 appCloseWarning.setText(tr("There are still running VMs. It is suggested to close the running VMs tab before exiting. Click cancel to go back"));
477 appCloseWarning.setIcon(QMessageBox::Warning);
478 appCloseWarning.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
482 // Check if there are running VMs
483 for (int i=0; i<mVmList.size(); i++) {
484 if (mVmList[i]->getState() == VmInfo::RUNNING) {
490 // If there are no running VMs
493 if (mTelemProc != NULL) {
495 mTelemProc->terminate();
498 mExitAppFromMenu = true;
501 // Inform user about running VMs and ask for consent
502 // before closing application
503 int ret = appCloseWarning.exec();
505 case QMessageBox::Ok:
506 mExitAppFromMenu = true;
509 case QMessageBox::Cancel:
510 mExitAppFromMenu = false;
516 // Convenience method for showing messages
517 void NewPalacios::showMessage(QString msg, bool err, bool warning) {
521 msgBox.setIcon(QMessageBox::Critical);
522 } else if (warning == true) {
523 msgBox.setIcon(QMessageBox::Warning);
526 msgBox.setStandardButtons(QMessageBox::Ok);
530 /*void NewPalacios::processStarted() {
531 //qDebug() << "Process started...";
534 void NewPalacios::processExit(int errorCode, QProcess::ExitStatus exitStatus) {
535 if (exitStatus == QProcess::CrashExit) {
536 //qDebug() << "The process crashed!!";
538 //qDebug() << "The process exited normally..";
542 void NewPalacios::processError(QProcess::ProcessError error) {
543 //qDebug() << "There was an error in the process execution...";
546 case QProcess::FailedToStart:
547 //qDebug() << "Process failed to start...";
549 case QProcess::Crashed:
550 //qDebug() << "Process crashed...";
552 case QProcess::Timedout:
553 //qDebug() << "Process timed out...";
555 case QProcess::WriteError:
556 //qDebug() << "Process had write error...";
558 case QProcess::ReadError:
559 //qDebug() << "Process had read error...";
561 case QProcess::UnknownError:
562 //qDebug() << "Process unknown error...";
568 void NewPalacios::createVmInstance() {
569 if (mVmWizard != NULL) {
570 mVmWizard->restart();
575 void NewPalacios::selectVmMode() {
576 if (isHeaderClicked) {
580 if (mVmList[mVmPos]->getCategory() != VmInfo::ACTIVE_INVENTORY) {
582 showMessage(tr("VM is not active!"), true);
587 if (mVmList[mVmPos]->getState() == VmInfo::PAUSED) {
588 // If machine is paused, we just restart using the previous selected mode
591 // Machine is started fresh
592 mVmModeDialog = new VmModeDialog(this);
593 connect(mVmModeDialog, SIGNAL(setMode(int, QString)),
594 this, SLOT(getVmMode(int, QString)));
595 mVmModeDialog->show();
599 void NewPalacios::getVmMode(int mode, QString streamName) {
601 mStreamName = streamName;
606 void NewPalacios::startVm() {
607 if (mVmList.isEmpty()) {
608 // There is no VM in the list
612 // Check if we are trying to start an inactive VM
613 if (mVmList[mVmPos]->getCategory() == VmInfo::INACTIVE_INVENTORY) {
614 showMessage(tr(ERROR_RUN_INACTIVE_INVENTORY), true);
618 // Check if we are trying to start a VM not in the inventory
619 if (mVmList[mVmPos]->getCategory() == VmInfo::ACTIVE_NOT_INVENTORY) {
620 showMessage(tr(ERROR_RUN_ACTIVE_NOT_INVENTORY), true);
625 // Check if the VM is already running
626 for (int i=0; i < mRunningVms.size(); i++) {
627 if (mVmName.compare(mRunningVms[i]->getVmName()) == 0
628 && mVmMode != VmConsoleWidget::STREAM) {
629 // If we are running the VM in stream mode then we
630 // can have multiple streams open simultaneously
631 // For the other modes, only one instance can be running
632 showMessage(tr(ERROR_VM_RUNNING), true);
637 QString v3_devfile = mVmList[mVmPos]->getVmDevFile();
638 if (v3_devfile == NULL) {
639 showMessage(tr(ERROR_NO_DEVFILE_FOR_LAUNCH), true);
643 int vm_status = mVmList[mVmPos]->getState();
645 QProcess* v3LaunchProc = NULL;
651 case VmInfo::STOPPED:
652 // If VM is stopped, launch it <v3_launch>
653 v3LaunchProc = new QProcess();
654 v3LaunchProc->setProcessChannelMode(QProcess::MergedChannels);
656 // Connect debug slots
657 //connect(v3LaunchProc, SIGNAL(started()), this, SLOT(processStarted()));
658 //connect(v3LaunchProc, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(processExit(int, QProcess::ExitStatus)));
659 //connect(v3LaunchProc, SIGNAL(error(QProcess::ProcessError)), this, SLOT(processError(QProcess::ProcessError)));
662 v3LaunchProc->start("v3_launch", args);
664 flag = v3LaunchProc->waitForFinished();
665 message = v3LaunchProc->readAllStandardOutput();
668 showMessage(tr(ERROR_VM_LAUNCH), true);
672 } else if (message.contains("Error opening V3Vee VM device")) {
673 showMessage(tr(ERROR_LAUNCH_VM_DEVICE_NOT_FOUND), true);
680 /*case VmInfo::PAUSED:
681 // If VM is paused, call <v3_continue>
684 case VmInfo::RUNNING:
685 // If VM is running, do nothing
686 // We will be just calling v3_cons_sc/v3_stream/vnc to
691 QString name = mVmList[mVmPos]->getVmName();
692 // Create a new console instance and set the launch file
693 VmXConsoleParent* consoleParent = new VmXConsoleParent(name);
695 // Add it to list of running VMs
696 mRunningVms.append(consoleParent);
697 pos = mRunningVms.indexOf(consoleParent);
700 // Disable updates in widgets to reduce screen flicker
701 // due to layouting in widgets
702 consoleParent->setUpdatesEnabled(false);
703 mVmControlPanel->setUpdatesEnabled(false);
704 if (mVmMode != VmConsoleWidget::STREAM) {
705 // If not in stream mode, header will be VM name
706 mVmControlPanel->insertTab(mVmControlPanel->count(), consoleParent, name);
708 // If stream mode, header will be stream name
709 mVmControlPanel->insertTab(mVmControlPanel->count(), consoleParent, mStreamName);
711 mVmControlPanel->setCurrentWidget(consoleParent);
714 consoleParent->showWidget(mVmMode, v3_devfile, mStreamName);
715 // Re-enable updates to widgets
716 mVmControlPanel->setUpdatesEnabled(true);
717 consoleParent->setUpdatesEnabled(true);
719 // Signal to tell the background xterm process to quit when console widget is closed
720 connect(mRunningVms[pos], SIGNAL(windowClosingWithId(QString)), this,
721 SLOT(consoleWindowClosed(QString)));
723 updateVmState(VmInfo::RUNNING);
725 for (int i=0; i<mVmTreeView->topLevelItem(VmInfo::ACTIVE_INVENTORY)->childCount(); i++) {
726 QTreeWidgetItem* child = mVmTreeView->topLevelItem(VmInfo::ACTIVE_INVENTORY)->child(i);
727 if (mVmName.compare(child->text(0)) == 0) {
728 child->setIcon(0, QIcon(":/images/images/start_vm.png"));
734 void NewPalacios::updateVmState(int mode) {
735 // TODO: Move this to a background thread
736 QString vm_name = mVmList[mVmPos]->getVmName();
738 QFile file("virtual_machines_list.txt");
739 if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
740 showMessage(tr(ERROR_UPDATE_VM_STATE), true);
745 QFile temp("temp.txt");
746 if (!temp.open(QIODevice::WriteOnly | QIODevice::Text)) {
747 showMessage(tr(ERROR_UPDATE_VM_STATE), true);
752 QTextStream in(&file);
753 QTextStream out(&temp);
755 while (!in.atEnd()) {
756 QString line = in.readLine();
757 if (line.compare("\n") == 0) {
761 QStringList vmDet = line.split(",");
762 QString nameStr = vmDet.at(0);
764 if (nameStr.compare(vm_name) == 0) {
765 QString configStr = vmDet.at(1);
766 QString devfileStr = vmDet.at(2);
767 QString stateStr = vmDet.at(3);
768 QString imageStr = vmDet.at(4);
770 out << nameStr << "," << configStr << "," << devfileStr << "," << QString::number(mode) <<"," << imageStr << endl;
777 file.remove("virtual_machines_list.txt");
778 temp.rename("virtual_machines_list.txt");
784 mVmList[mVmPos]->setState(mode);
787 void NewPalacios::stopVm() {
788 if (mVmList.isEmpty()
789 || mVmList[mVmPos]->getState() == VmInfo::STOPPED) {
790 // If the VM list is empty or the VM is already stopped
791 // or if the VM is passive
793 showMessage(tr(ERROR_STOP_VM), false, true);
797 if (mVmList[mVmPos]->getCategory() == VmInfo::INACTIVE_INVENTORY
798 || mVmList[mVmPos]->getCategory() == VmInfo::ACTIVE_NOT_INVENTORY) {
799 // If the VM is inactive or active not inventory
800 showMessage(tr(ERROR_VM_NOT_INVENTORY), true);
805 QMessageBox vmStopWarningBox;
806 vmStopWarningBox.setText(VM_STOP_WARNING_MESSAGE);
807 vmStopWarningBox.setIcon(QMessageBox::Warning);
808 vmStopWarningBox.setStandardButtons(
809 QMessageBox::Cancel | QMessageBox::Ok);
810 vmStopWarningBox.setDefaultButton(QMessageBox::Cancel);
811 int ret = vmStopWarningBox.exec();
812 int posInTabWidget = -1;
814 QProcess* v3StopProc = NULL;
817 case QMessageBox::Ok:
819 v3StopProc = new QProcess();
820 v3StopProc->setProcessChannelMode(QProcess::MergedChannels);
821 args << mVmList[mVmPos]->getVmDevFile();
822 v3StopProc->start("v3_stop", args);
823 if (!v3StopProc->waitForFinished()) {
824 showMessage(tr(ERROR_STOP_VM_PATH), true);
828 } else if (v3StopProc->readAllStandardOutput().contains("Error opening V3Vee VM device")) {
829 showMessage(tr(ERROR_STOP_VM_DEVICE_NOT_FOUND), true);
834 name = mVmList[mVmPos]->getVmName();
835 for (int i=0; i<mRunningVms.length(); i++) {
836 if (name.compare(mRunningVms[i]->getVmName()) == 0) {
837 // Remove widget from tab if placed there
838 posInTabWidget = mVmControlPanel->indexOf(mRunningVms[i]);
839 if (posInTabWidget != -1) {
840 // Console is present in tab
841 mVmControlPanel->removeTab(posInTabWidget);
844 mRunningVms[i]->close();
845 // Remove it from list of running console windows
846 mRunningVms.removeAt(i);
852 updateVmState(VmInfo::STOPPED);
855 for (int i=0; i<mVmTreeView->topLevelItem(VmInfo::ACTIVE_INVENTORY)->childCount(); i++) {
856 QTreeWidgetItem* child = mVmTreeView->topLevelItem(VmInfo::ACTIVE_INVENTORY)->child(i);
857 if (mVmName.compare(child->text(0)) == 0) {
858 child->setIcon(0, QIcon(":/images/images/stop_vm.png"));
864 case QMessageBox::Cancel:
869 void NewPalacios::pauseVm() {
870 if (mVmList.isEmpty()) {
874 if (mVmList[mVmPos]->getCategory() == VmInfo::INACTIVE_INVENTORY
875 || mVmList[mVmPos]->getCategory() == VmInfo::ACTIVE_NOT_INVENTORY) {
876 showMessage(tr(ERROR_VM_NOT_INVENTORY), false, true);
880 QString v3_devfile = mVmList[mVmPos]->getVmDevFile();
881 if (v3_devfile == NULL) {
882 showMessage(tr("Device file not found"), true);
886 QProcess* v3Pauseproc = new QProcess();
887 v3Pauseproc->setProcessChannelMode(QProcess::MergedChannels);
890 v3Pauseproc->start("v3_pause", args);
891 if (!v3Pauseproc->waitForFinished()) {
892 showMessage(v3Pauseproc->errorString(), true);
893 } else if (v3Pauseproc->readAllStandardOutput().contains("Error opening V3Vee VM device")) {
894 showMessage(tr(ERROR_PAUSE_VM_DEVICE_NOT_FOUND), true);
898 updateVmState(VmInfo::PAUSED);
901 for (int i=0; i<mVmTreeView->topLevelItem(VmInfo::ACTIVE_INVENTORY)->childCount(); i++) {
902 QTreeWidgetItem* child = mVmTreeView->topLevelItem(VmInfo::ACTIVE_INVENTORY)->child(i);
903 if (mVmName.compare(child->text(0)) == 0) {
904 child->setIcon(0, QIcon(":/images/images/pause_vm.png"));
912 void NewPalacios::restartVm() {
913 if (mVmList.isEmpty()) {
917 if (mVmList[mVmPos]->getCategory() == VmInfo::INACTIVE_INVENTORY
918 || mVmList[mVmPos]->getCategory() == VmInfo::ACTIVE_NOT_INVENTORY) {
919 showMessage(tr(ERROR_VM_NOT_INVENTORY), false, true);
923 QString v3_devfile = mVmList[mVmPos]->getVmDevFile();
924 if (v3_devfile == NULL) {
925 showMessage(tr("Device file not found"), true);
929 QProcess* v3Continueproc = new QProcess();
930 v3Continueproc->setProcessChannelMode(QProcess::MergedChannels);
933 v3Continueproc->start("v3_continue", args);
935 if (!v3Continueproc->waitForFinished()) {
936 showMessage(v3Continueproc->errorString(), true);
937 } else if (v3Continueproc->readAllStandardOutput().contains("Error opening V3Vee VM device")) {
938 showMessage(tr(ERROR_RESTART_VM_IOCTL), true);
942 for (int i=0; i<mVmTreeView->topLevelItem(VmInfo::ACTIVE_INVENTORY)->childCount(); i++) {
943 QTreeWidgetItem* child = mVmTreeView->topLevelItem(VmInfo::ACTIVE_INVENTORY)->child(i);
944 if (mVmName.compare(child->text(0)) == 0) {
945 child->setIcon(0, QIcon(":/images/images/start_vm.png"));
950 delete v3Continueproc;
953 // Method to create a VM from inactive list
954 int NewPalacios::createInactiveVm() {
955 QString vmImageFile = mVmList[mVmPos]->getImageFile();
956 QString vmName = mVmList[mVmPos]->getVmName();
958 // Create the VM instance
959 QProcess* v3CreateProc = new QProcess();
962 args << vmImageFile << vmName;
963 v3CreateProc->start("v3_create", args);
965 if (v3CreateProc->waitForFinished()) {
966 if (v3CreateProc->readAllStandardOutput().contains("Error (-1)")) {
967 // v3_create has failed with IOCTL error
968 showMessage(tr(ERROR_VM_CREATE_IOCTL), true);
973 showMessage(tr(ERROR_VM_CREATE_PATH), true);
981 // Check the last line of /proc/v3vee/v3-guests
982 // to see the /dev/v3-vm# of the new VM
983 bool isCreated = false;
984 QProcess* proc = new QProcess();
985 proc->setProcessChannelMode(QProcess::MergedChannels);
986 proc->start("cat /proc/v3vee/v3-guests");
988 if (!proc->waitForFinished()) {
989 showMessage(tr(ERROR_VM_CREATE_PROC), true);
994 //QByteArray temp = vmName.toAscii();
995 //const char* vmEntry = temp.data();
997 // Read standard output of process
998 QByteArray val = proc->readAllStandardOutput();
1000 // The created VM can be defined anywhere in the /proc file
1001 // we need to go over all entries till we find it
1002 QList<QByteArray> procs = val.split('\n');
1003 for (int i=0; i<procs.size(); i++) {
1004 QList<QByteArray> temp = procs[i].split('\t');
1005 QByteArray a = temp.at(0);
1006 QString vmProcName(a);
1007 if (vmName.compare(vmProcName) == 0) {
1008 // We have found the VM, get dev file name
1009 QByteArray b = temp.at(1);
1010 QString vmDevFile(b);
1011 vmDevFile.remove(QChar('\n'), Qt::CaseInsensitive);
1012 mVmList[mVmPos]->setVmDevFile(vmDevFile);
1013 // Make VM instance active
1014 mVmList[mVmPos]->setCategory(VmInfo::ACTIVE_INVENTORY);
1022 // We did not find an entry in
1023 // /proc file so there must have
1024 // been an error in creation
1025 showMessage(tr(ERROR_VM_CREATE_FAILED), true);
1036 int NewPalacios::updateDb(int cat) {
1037 QString vm_name = mVmList[mVmPos]->getVmName();
1039 QFile file("virtual_machines_list.txt");
1040 if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
1041 showMessage("Error opening DB! Please restart application", true);
1045 QFile temp("temp.txt");
1046 if (!temp.open(QIODevice::WriteOnly | QIODevice::Text)) {
1047 showMessage("Error opening DB! Please restart application", true);
1051 QTextStream in(&file);
1052 QTextStream out(&temp);
1055 if (cat == VmInfo::INACTIVE_INVENTORY) {
1056 // If we are updating an inactive entry
1057 // search the file and update
1058 while (!in.atEnd()) {
1059 QString line = in.readLine();
1060 if (line.compare("\n") == 0) {
1063 QStringList vmDet = line.split(",");
1064 QString nameStr = vmDet.at(0);
1066 if (vm_name.compare(nameStr) != 0) {
1067 // If the name does not match, then copy to new place
1068 out << line << endl;
1071 VmInfo* v = mVmList[mVmPos];
1072 QString updateLine = v->getVmName()
1073 + "," + v->getVmConfigFile()
1074 + "," + v->getVmDevFile()
1075 + "," + QString::number(VmInfo::STOPPED)
1076 + "," + v->getImageFile();
1077 out << updateLine << endl;
1080 } else if (cat == VmInfo::ACTIVE_NOT_INVENTORY) {
1082 while (!in.atEnd()) {
1083 QString line = in.readLine();
1084 if (line.compare("\n") == 0) {
1088 // Copy all the contents into new file
1089 out << line << endl;
1092 // Copy the new VM info
1093 VmInfo* vv = mVmList[mVmPos];
1094 QString updateLine = vv->getVmName()
1095 + "," + vv->getVmConfigFile()
1096 + "," + vv->getVmDevFile()
1097 + "," + QString::number(VmInfo::STOPPED)
1098 + "," + vv->getImageFile();
1099 out << updateLine << endl;
1103 file.remove("virtual_machines_list.txt");
1104 temp.rename("virtual_machines_list.txt");
1112 void NewPalacios::activateVm() {
1113 // 1. Check VM category
1114 // 1a. If VM is active but not in inventory, upgrade category
1115 // 1b. If VM is inactive, create VM and upgrade category
1116 QTreeWidgetItem* item = NULL;
1118 // Remove VM from inactive list
1119 // The list could be from either the inactive inventory or
1120 // active not inventory
1121 int category = mVmList[mVmPos]->getCategory();
1123 if (category == VmInfo::ACTIVE_NOT_INVENTORY) {
1124 // The VM exists in the /proc file and
1125 // is already created. We will only update
1128 // Ask user for Config file and Image file
1129 QString configFile = QFileDialog::getOpenFileName(this, tr("Select config file"), ".",
1130 "XML file (*.xml)");
1131 if (configFile == NULL) {
1132 // User pressed cancel
1135 QString imageFile = QFileDialog::getOpenFileName(this, tr("Select image file"), ".",
1136 "Image file (*.img *.bZ)");
1137 if (imageFile == NULL) {
1138 // User pressed cancel
1142 mVmList[mVmPos]->setVmConfigFile(configFile);
1143 mVmList[mVmPos]->setImageFile(imageFile);
1145 // Remove from active not inventory list
1146 for (int i=0; i<mVmTreeView->topLevelItem(VmInfo::ACTIVE_NOT_INVENTORY)->childCount(); i++) {
1147 item = mVmTreeView->topLevelItem(VmInfo::ACTIVE_NOT_INVENTORY)->child(i);
1148 if (item->text(0).compare(mVmList[mVmPos]->getVmName()) == 0) {
1149 item = mVmTreeView->topLevelItem(VmInfo::ACTIVE_NOT_INVENTORY)->takeChild(i);
1154 // Add it to active list
1155 QTreeWidgetItem* subParent = mVmTreeView->topLevelItem(VmInfo::ACTIVE_INVENTORY);
1156 subParent->addChild(item);
1159 mVmList[mVmPos]->setCategory(VmInfo::ACTIVE_INVENTORY);
1161 // Update DB with newly created entry
1162 updateDb(VmInfo::ACTIVE_NOT_INVENTORY);
1165 } else if (category == VmInfo::INACTIVE_INVENTORY) {
1166 // The VM is in the inventory but inactive.
1167 // This means that we need to create it.
1168 int ret = createInactiveVm();
1171 // VM was not created due to some problem
1172 // TODO: Decide if you want to delete the reference
1173 // from the text file or keep it there for a while and
1178 // Once VM is created, we need to first remove it from the
1179 // inactive list and add it to active list
1180 for (int i=0; i<mVmTreeView->topLevelItem(VmInfo::INACTIVE_INVENTORY)->childCount(); i++) {
1181 item = mVmTreeView->topLevelItem(VmInfo::INACTIVE_INVENTORY)->child(i);
1182 if (item->text(0).compare(mVmList[mVmPos]->getVmName()) == 0) {
1183 item = mVmTreeView->topLevelItem(VmInfo::INACTIVE_INVENTORY)->takeChild(i);
1188 // Add it to active list
1189 QTreeWidgetItem* subParent = mVmTreeView->topLevelItem(VmInfo::ACTIVE_INVENTORY);
1190 subParent->addChild(item);
1192 // Update DB with newly created entry
1193 updateDb(VmInfo::INACTIVE_INVENTORY);
1197 void NewPalacios::reloadVms() {
1198 // Clear all previous entries
1199 for (int i=0; i<mVmTreeView->topLevelItemCount(); i++) {
1200 qDeleteAll(mVmTreeView->topLevelItem(i)->takeChildren());
1203 // Call load VM thread
1204 readExistingVmsFile();
1207 // This handler is used in serial mode when user clicks
1208 // the close button of the floating window
1209 void NewPalacios::consoleWindowClosed(QString name) {
1210 // Remove the console from the list of
1212 for (int i=0; i < mRunningVms.length(); i++) {
1213 if (name.compare(mRunningVms[i]->getVmName()) == 0) {
1214 mRunningVms.removeAt(i);
1220 // This handler is used in v3_cons_sc mode when the user clicks
1221 // the close button on the tab widget
1222 void NewPalacios::vmTabClosed(int index) {
1224 // As of now do not remove the info tab
1228 // Get the name of the VM tab which we need to close
1229 // Need to cast the return value of TabWidget->widget as it returns an object
1230 // of the base class. static_cast is used because the conversion is from base
1231 // class object to derived class object
1232 VmXConsoleParent* widget = static_cast<VmXConsoleParent*>(mVmControlPanel->widget(index));
1233 QString name = widget->getVmName();
1234 for (int i=0; i<mRunningVms.length(); i++) {
1235 if (name.compare(mRunningVms[i]->getVmName()) == 0) {
1237 mVmControlPanel->removeTab(index);
1238 // Remove the console from running vm instances
1239 mRunningVms.removeAt(i);
1240 // Send close event to widget
1247 /* This function reads from the vm list file */
1248 void NewPalacios::readExistingVmsFile() {
1249 mThread = new QThread();
1250 mLoadVmsThread = new LoadVmsThread();
1251 mLoadVmsThread->moveToThread(mThread);
1252 connect(mThread, SIGNAL(started()), mLoadVmsThread, SLOT(loadVms()));
1253 connect(mLoadVmsThread, SIGNAL(finished()), mThread, SLOT(quit()));
1254 // Action which listens to completion of initial VM loading
1255 connect(mLoadVmsThread, SIGNAL(finished()), this,
1256 SLOT(finishLoadingVmsFromFile()));
1260 // Update UI with VMs loaded from file
1261 void NewPalacios::finishLoadingVmsFromFile() {
1262 if (mLoadVmsThread->getStatus() == LoadVmsThread::STATUS_OK) {
1268 // Load VMs into memory
1269 mVmList.append(mLoadVmsThread->getVmList());
1271 QTreeWidgetItem* item = NULL;
1272 for (int i = 0; i < mVmList.size(); i++) {
1273 if (mVmList[i]->getCategory() == VmInfo::ACTIVE_INVENTORY) {
1274 item = new QTreeWidgetItem();
1275 item->setText(0, mVmList[i]->getVmName());
1277 category = mVmList[i]->getState();
1279 case VmInfo::STOPPED:
1280 item->setIcon(0, QIcon(":/images/images/stop_vm.png"));
1282 case VmInfo::PAUSED:
1283 item->setIcon(0, QIcon(":/images/images/pause_vm.png"));
1285 case VmInfo::RUNNING:
1286 item->setIcon(0, QIcon(":/images/images/start_vm.png"));
1290 mVmTreeView->topLevelItem(VmInfo::ACTIVE_INVENTORY)->addChild(item);
1292 } else if (mVmList[i]->getCategory() == VmInfo::INACTIVE_INVENTORY) {
1293 item = new QTreeWidgetItem();
1294 item->setText(0, mVmList[i]->getVmName());
1295 mVmTreeView->topLevelItem(VmInfo::INACTIVE_INVENTORY)->addChild(item);
1297 } else if (mVmList[i]->getCategory() == VmInfo::ACTIVE_NOT_INVENTORY) {
1298 item = new QTreeWidgetItem();
1299 item->setText(0, mVmList[i]->getVmName());
1300 mVmTreeView->topLevelItem(VmInfo::ACTIVE_NOT_INVENTORY)->addChild(item);
1304 mVmControlPanel->insertTab(0, mVmInfoWidget, tr(VM_TAB_TITLE));
1306 if (mThread != NULL)
1312 /* This method is called after completion of the VM wizard
1313 * It updates the backend vm file with new vm */
1314 void NewPalacios::addNewVm() {
1315 QString name = mVmWizard->field("guestName").toString();
1316 QString file = mVmWizard->field("configLoc").toString();
1317 QFileInfo f(mVmWizard->field("imageLoc").toString());
1318 QString img = f.fileName();
1320 mThread = new QThread();
1321 mAddVmThread = new AddVmThread(name, file, img);
1322 mAddVmThread->moveToThread(mThread);
1323 connect(mThread, SIGNAL(started()), mAddVmThread, SLOT(addVm()));
1324 connect(mAddVmThread, SIGNAL(finished()), mThread, SLOT(quit()));
1325 // Call method on window to update the vm list
1326 connect(mAddVmThread, SIGNAL(finished()), this, SLOT(updateVmList()));
1330 /* Update UI with new VM added to list */
1331 void NewPalacios::updateVmList() {
1332 if(mAddVmThread != NULL && mAddVmThread->getStatus()
1333 == AddVmThread::ERROR_V3CREATE_DB) {
1334 showMessage(tr(ERROR_VM_CREATE_DB), true);
1336 } else if (mAddVmThread != NULL &&
1337 mAddVmThread->getStatus() == AddVmThread::STATUS_OK) {
1338 // Newly created VM is inactive but in inventory
1339 showMessage(tr(SUCCESS_VM_ADDED), false);
1340 mVmList.append(mAddVmThread->getNewVm());
1341 QTreeWidgetItem* item = new QTreeWidgetItem();
1342 item->setText(0, mAddVmThread->getName());
1344 QTreeWidgetItem* subParent = mVmTreeView->topLevelItem(VmInfo::INACTIVE_INVENTORY);
1345 subParent->addChild(item);
1348 if (mThread != NULL)
1352 /* Handler to delete VM instance from list and backend file */
1353 void NewPalacios::deleteVm(QString item) {
1357 for (int i = 0; i < mVmList.size(); i++) {
1358 if (item.compare(mVmList[i]->getVmName()) == 0) {
1359 category = mVmList[i]->getCategory();
1360 devfile = mVmList[i]->getVmDevFile();
1365 mThread = new QThread();
1366 mDeleteVmThread = new DeleteVmThread(category, item, devfile);
1367 mDeleteVmThread->moveToThread(mThread);
1368 connect(mThread, SIGNAL(started()), mDeleteVmThread, SLOT(deleteVm()));
1369 connect(mDeleteVmThread, SIGNAL(finished()), mThread, SLOT(quit()));
1370 connect(mDeleteVmThread, SIGNAL(finished()), this, SLOT(handleVmDeletion()));
1374 void NewPalacios::handleVmDeletion() {
1375 if (mDeleteVmThread->getStatus()
1376 == DeleteVmThread::ERROR_V3FREE_PATH) {
1377 showMessage(tr(ERROR_VM_DELETE_PATH), true);
1379 } else if (mDeleteVmThread->getStatus()
1380 == DeleteVmThread::ERROR_V3FREE_IOCTL) {
1381 showMessage(tr(ERROR_VM_DELETE_IOCTL), true);
1383 } else if (mDeleteVmThread->getStatus()
1384 == DeleteVmThread::ERROR_V3FREE_DB) {
1385 showMessage(tr(ERROR_VM_DELETE_DB), true);
1387 } else if (mDeleteVmThread->getStatus()
1388 == DeleteVmThread::ERROR_V3FREE_INVALID_ARGUMENT) {
1389 showMessage(tr(ERROR_VM_DELETE_INVALID_ARGUMENT), true);
1391 } else if (mDeleteVmThread->getStatus()
1392 == DeleteVmThread::STATUS_OK) {
1393 // Delete VM from list
1394 for (int i = 0; i < mVmList.size(); i++) {
1395 if (mVmName.compare(mVmList[i]->getVmName()) == 0) {
1396 // Deletion is a little tricky
1397 // 1. Find the VM to be deleted and get its name
1398 // 2. Remove VM from list
1399 // 3. Determine the category
1400 // 4. Search the appropriate category for the VM
1401 // 5. Remove from UI widget and delete
1402 int cat = mVmList[i]->getCategory();
1403 mVmList.removeAt(i);
1405 if (cat == VmInfo::ACTIVE_INVENTORY) {
1406 QTreeWidgetItem* activeItems = mVmTreeView->topLevelItem(VmInfo::ACTIVE_INVENTORY);
1407 for (int j=0; j<activeItems->childCount(); j++) {
1408 QString n = activeItems->child(j)->text(0);
1409 if (mVmName.compare(n) == 0) {
1410 QTreeWidgetItem* achild = activeItems->takeChild(j);
1416 } else if (cat == VmInfo::INACTIVE_INVENTORY) {
1417 QTreeWidgetItem* inactiveItems = mVmTreeView->topLevelItem(VmInfo::INACTIVE_INVENTORY);
1418 for (int j=0; j<inactiveItems->childCount(); j++) {
1419 QString in = inactiveItems->child(j)->text(0);
1420 if (mVmName.compare(in) == 0) {
1421 QTreeWidgetItem* ichild = inactiveItems->takeChild(j);
1426 } else if (cat == VmInfo::ACTIVE_NOT_INVENTORY) {
1427 QTreeWidgetItem* activeNotInvItems = mVmTreeView->topLevelItem(VmInfo::ACTIVE_NOT_INVENTORY);
1428 for (int j=0; j<activeNotInvItems->childCount(); j++) {
1429 QString an = activeNotInvItems->child(j)->text(0);
1430 if (mVmName.compare(an) == 0) {
1431 QTreeWidgetItem* aichild = activeNotInvItems->takeChild(j);
1439 // Clear VM from Info widget view
1440 mVmInfoWidget->deleteVm();
1445 showMessage(tr(SUCCESS_VM_DELETE), false);
1448 if (mThread != NULL)