/src/vmManager.cpp

https://github.com/deltaforge/nebu-app-framework-cpp · C++ · 209 lines · 175 code · 31 blank · 3 comment · 22 complexity · 115352f336dee86c1dd443b1bb313f11 MD5 · raw file

  1. #include "nebu-app-framework/vmManager.h"
  2. #include "nebu/util/exceptions.h"
  3. #include "log4cxx/logger.h"
  4. #include <set>
  5. // Using declarations - standard library
  6. using std::list;
  7. using std::make_shared;
  8. using std::set;
  9. using std::shared_ptr;
  10. using std::string;
  11. using std::unordered_map;
  12. using std::vector;
  13. // Using declarations - nebu-common
  14. using nebu::common::NebuServerException;
  15. using nebu::common::VirtualMachine;
  16. using nebu::common::VMStatus;
  17. static log4cxx::LoggerPtr logger(log4cxx::Logger::getLogger("nebu.app.framework.VMManager"));
  18. #define FOREACH_EVENTHANDLER(itName) \
  19. for (list<shared_ptr<VMEventHandler>>::iterator itName = this->vmEventHandlers.begin(); \
  20. itName != this->vmEventHandlers.end(); \
  21. itName++)
  22. namespace nebu
  23. {
  24. namespace app
  25. {
  26. namespace framework
  27. {
  28. bool VMManager::refreshVMList()
  29. {
  30. vector<string> vmIDs;
  31. try {
  32. vmIDs = this->appVirtRequest->getVirtualMachineIDs();
  33. } catch (NebuServerException &ex) {
  34. LOG4CXX_WARN(logger, "Could not refresh VM list\n" + ex.what());
  35. return false;
  36. }
  37. vector<string> vmIDsFiltered(vmIDs);
  38. bool succes = true;
  39. succes &= this->addNewVMs(vmIDsFiltered);
  40. succes &= this->updateVMs(vmIDsFiltered);
  41. this->removeVMs(vmIDs);
  42. return succes;
  43. }
  44. bool VMManager::addNewVMs(vector<string> &retrievedVMIds)
  45. {
  46. bool succes = true;
  47. for (vector<string>::iterator it = retrievedVMIds.begin();
  48. it != retrievedVMIds.end();
  49. )
  50. {
  51. if (this->vmList.find(*it) == this->vmList.end()) {
  52. try {
  53. shared_ptr<VirtualMachine> newVM = make_shared<VirtualMachine>(
  54. this->appVirtRequest->getVirtualMachine(*it));
  55. LOG4CXX_INFO(logger, "Detected new VM with hostname '" + newVM->getHostname() +
  56. "' (id: " + newVM->getUUID() + ")");
  57. LOG4CXX_DEBUG(logger, "\tHost: " << newVM->getPhysicalHostID() <<
  58. ", store: " << newVM->getPhysicalStoreID() << ", status: " <<
  59. static_cast<unsigned int>(newVM->getStatus()));
  60. this->addVM(newVM);
  61. } catch (NebuServerException &ex) {
  62. LOG4CXX_WARN(logger, "Missing information on a new vm\n" + ex.what());
  63. succes = false;
  64. }
  65. retrievedVMIds.erase(it);
  66. } else {
  67. it++;
  68. }
  69. }
  70. return succes;
  71. }
  72. bool VMManager::updateVMs(vector<string> &filteredVMIds)
  73. {
  74. bool succes = true;
  75. for (vector<string>::iterator it = filteredVMIds.begin();
  76. it != filteredVMIds.end();
  77. it++)
  78. {
  79. shared_ptr<VirtualMachine> vm = this->vmList[*it];
  80. try {
  81. VirtualMachine updatedVM = this->appVirtRequest->getVirtualMachine(*it);
  82. if (vm->getStatus() != updatedVM.getStatus()) {
  83. LOG4CXX_INFO(logger, "Detected change in VM with hostname '" << vm->getHostname() <<
  84. "' (id: " << vm->getUUID() << ")");
  85. LOG4CXX_DEBUG(logger, "\tStatus from " << static_cast<unsigned int>(vm->getStatus()) <<
  86. " to " << static_cast<unsigned int>(updatedVM.getStatus()));
  87. this->updateVM(vm, updatedVM);
  88. }
  89. } catch (NebuServerException &ex) {
  90. // TODO: Decide: should the VM status be set to UNKNOWN?
  91. LOG4CXX_WARN(logger, "Missing information for a VM update\n" + ex.what());
  92. succes = false;
  93. }
  94. }
  95. return succes;
  96. }
  97. void VMManager::removeVMs(vector<string> &retrievedVMIds)
  98. {
  99. vector<shared_ptr<VirtualMachine>> knownVMs = this->getVMs();
  100. set<string> vmIDSet(retrievedVMIds.begin(), retrievedVMIds.end());
  101. for (vector<shared_ptr<VirtualMachine>>::iterator it = knownVMs.begin();
  102. it != knownVMs.end();
  103. it++)
  104. {
  105. if (vmIDSet.find((*it)->getUUID()) == vmIDSet.end()) {
  106. this->removeVM(*it);
  107. }
  108. }
  109. }
  110. vector<shared_ptr<VirtualMachine>> VMManager::getVMs() const
  111. {
  112. vector<shared_ptr<VirtualMachine>> res;
  113. for (unordered_map<string, shared_ptr<VirtualMachine>>::const_iterator it = this->vmList.begin();
  114. it != this->vmList.end();
  115. it++)
  116. {
  117. res.push_back(it->second);
  118. }
  119. return res;
  120. }
  121. shared_ptr<VirtualMachine> VMManager::getVM(const string &uuid) const
  122. {
  123. if (this->hasVM(uuid)) {
  124. return this->vmList.at(uuid);
  125. } else {
  126. return shared_ptr<VirtualMachine>();
  127. }
  128. }
  129. void VMManager::addVM(shared_ptr<VirtualMachine> vm)
  130. {
  131. this->vmList[vm->getUUID()] = vm;
  132. FOREACH_EVENTHANDLER(ev)
  133. {
  134. ev->get()->newVMAdded(vm);
  135. }
  136. }
  137. void VMManager::updateVM(shared_ptr<VirtualMachine> vm, const VirtualMachine &updated)
  138. {
  139. if (vm->getStatus() != updated.getStatus()) {
  140. vm->setStatus(updated.getStatus());
  141. VMEvent event;
  142. switch (vm->getStatus())
  143. {
  144. case VMStatus::ON:
  145. event = VMEvent::POWERED_ON;
  146. break;
  147. case VMStatus::OFF:
  148. event = VMEvent::POWERED_OFF;
  149. break;
  150. case VMStatus::UNKNOWN:
  151. event = VMEvent::UNKNOWN;
  152. break;
  153. }
  154. FOREACH_EVENTHANDLER(ev)
  155. {
  156. ev->get()->existingVMChanged(vm, event);
  157. }
  158. }
  159. }
  160. void VMManager::removeVM(shared_ptr<VirtualMachine> vm)
  161. {
  162. this->vmList.erase(vm->getUUID());
  163. FOREACH_EVENTHANDLER(ev)
  164. {
  165. ev->get()->oldVMRemoved(*vm);
  166. }
  167. }
  168. bool VMManager::hasVM(const string &uuid) const
  169. {
  170. return (this->vmList.count(uuid) > 0);
  171. }
  172. void VMManager::registerVMEventHandler(shared_ptr<VMEventHandler> eventHandler)
  173. {
  174. this->vmEventHandlers.push_back(eventHandler);
  175. }
  176. }
  177. }
  178. }