diff --git a/include/VMGroup.h b/include/VMGroup.h index 4452f0cd0c..489008ed70 100644 --- a/include/VMGroup.h +++ b/include/VMGroup.h @@ -70,6 +70,33 @@ public: return new Template(*obj_template); }; + // ------------------------------------------------------------------------- + // Role Management + // ------------------------------------------------------------------------- + /** + * Adds a VM to a role + * @param role_name + * @param vmid + * + * @return 0 if VM was successfully added, -1 otherwise + */ + int add_vm(const std::string& role_name, int vmid) + { + return roles.add_vm(role_name, vmid); + } + + /** + * Deletes a VM from a role + * @param role_name + * @param vmid + * + * @return 0 if VM was successfully added, -1 otherwise + */ + int del_vm(const std::string& role_name, int vmid) + { + return roles.del_vm(role_name, vmid); + } + private: // ------------------------------------------------------------------------- // Friends @@ -96,30 +123,6 @@ private: */ int check_affinity(const std::string& aname, std::string& error_str); - /** - * Adds a VM to a role - * @param role_name - * @param vmid - * - * @return 0 if VM was successfully added, -1 otherwise - */ - int add_vm(const std::string& role_name, int vmid) - { - return roles.add_vm(role_name, vmid); - } - - /** - * Deletes a VM from a role - * @param role_name - * @param vmid - * - * @return 0 if VM was successfully added, -1 otherwise - */ - int del_vm(const std::string& role_name, int vmid) - { - return roles.del_vm(role_name, vmid); - } - // ------------------------------------------------------------------------- // DataBase implementation // ------------------------------------------------------------------------- diff --git a/include/VMGroupRole.h b/include/VMGroupRole.h index 1c0c7f8086..72de052760 100644 --- a/include/VMGroupRole.h +++ b/include/VMGroupRole.h @@ -136,6 +136,11 @@ public: */ int del_vm(const std::string& role_name, int vmid); + /** + * @return the total number of VMs in the group + */ + int vm_size(); + private: /** * A role map indexed by different key types @@ -230,12 +235,75 @@ private: return true; } - private: + /** + * Iterators for the map + */ typedef typename std::map::iterator roles_it; + roles_it begin() + { + return roles.begin(); + } + + roles_it end() + { + return roles.end(); + } + + private: std::map roles; }; + class RoleIterator + { + public: + RoleIterator& operator=(const RoleIterator& rhs) + { + role_it = rhs.role_it; + return *this; + } + + RoleIterator& operator++() + { + ++role_it; + return *this; + } + + bool operator!=(const RoleIterator& rhs) + { + return role_it != rhs.role_it; + } + + VMGroupRole * operator*() const + { + return role_it->second; + } + + RoleIterator(){}; + RoleIterator(const RoleIterator& rit):role_it(rit.role_it){}; + RoleIterator(const std::map::iterator& _role_it) + :role_it(_role_it){}; + + virtual ~RoleIterator(){}; + + private: + std::map::iterator role_it; + }; + + RoleIterator begin() + { + RoleIterator it(by_id.begin()); + return it; + } + + RoleIterator end() + { + RoleIterator it(by_id.end()); + return it; + } + + typedef class RoleIterator role_iterator; + /** * The role template to store the VMGroupRole */ diff --git a/include/VirtualMachine.h b/include/VirtualMachine.h index 3fa26008f7..aeb9f21b58 100644 --- a/include/VirtualMachine.h +++ b/include/VirtualMachine.h @@ -1085,6 +1085,14 @@ public: */ void remove_security_group(int sgid); + // ------------------------------------------------------------------------ + // Virtual Machine Groups + // ------------------------------------------------------------------------ + /** + * Remove this VM from its role and VM group if any + */ + void release_vmgroup(); + // ------------------------------------------------------------------------ // Imported VM interface // ------------------------------------------------------------------------ @@ -1999,7 +2007,7 @@ private: int parse_context_variables(VectorAttribute ** context, string& error_str); // ------------------------------------------------------------------------- - // NIC & DISK Management Helpers + // Management helpers: NIC, DISK and VMGROUP // ------------------------------------------------------------------------- /** * Get all network leases for this Virtual Machine @@ -2014,6 +2022,13 @@ private: */ int get_disk_images(string &error_str); + /** + * Adds the VM to the VM group if needed + * @param error_str Returns the error reason, if any + * @return 0 if success + */ + int get_vmgroup(string& error); + // ------------------------------------------------------------------------ // Public cloud templates related functions // ------------------------------------------------------------------------ diff --git a/src/dm/DispatchManagerActions.cc b/src/dm/DispatchManagerActions.cc index 05ff168b84..c5e4b588bf 100644 --- a/src/dm/DispatchManagerActions.cc +++ b/src/dm/DispatchManagerActions.cc @@ -223,6 +223,7 @@ void DispatchManager::free_vm_resources(VirtualMachine * vm) int vmid; vm->release_network_leases(); + vm->release_vmgroup(); vm->release_disk_images(ds_quotas); vm->set_exit_time(time(0)); diff --git a/src/dm/DispatchManagerStates.cc b/src/dm/DispatchManagerStates.cc index 276b6fcf9b..cb48a9f1a9 100644 --- a/src/dm/DispatchManagerStates.cc +++ b/src/dm/DispatchManagerStates.cc @@ -230,6 +230,8 @@ void DispatchManager::done_action(int vid) { vm->release_network_leases(); + vm->release_vmgroup(); + vm->release_disk_images(ds_quotas); vm->set_state(VirtualMachine::DONE); diff --git a/src/vm/VirtualMachine.cc b/src/vm/VirtualMachine.cc index 22caf2a6f3..c697190062 100644 --- a/src/vm/VirtualMachine.cc +++ b/src/vm/VirtualMachine.cc @@ -741,12 +741,8 @@ int VirtualMachine::insert(SqlDB * db, string& error_str) // ------------------------------------------------------------------------ // Set a name if the VM has not got one and VM_ID // ------------------------------------------------------------------------ - - oss << oid; - value = oss.str(); - user_obj_template->erase("VMID"); - obj_template->add("VMID", value); + obj_template->add("VMID", oid); user_obj_template->get("TEMPLATE_ID", value); user_obj_template->erase("TEMPLATE_ID"); @@ -1019,6 +1015,14 @@ int VirtualMachine::insert(SqlDB * db, string& error_str) } } + // ------------------------------------------------------------------------ + // Associate to VM Group + // ------------------------------------------------------------------------ + if ( get_vmgroup(error_str) == -1 ) + { + goto error_rollback; + } + // ------------------------------------------------------------------------ parse_well_known_attributes(); @@ -2883,6 +2887,145 @@ int VirtualMachine::set_detach_nic(int nic_id) return 0; } +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ +/* VirtualMachine VMGroup interface */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ +int VirtualMachine::get_vmgroup(string& error) +{ + vector vmgroups; + vector::iterator it; + + bool found; + VectorAttribute * thegroup = 0; + + user_obj_template->remove("VMGROUP", vmgroups); + + for (it = vmgroups.begin(), found = false; it != vmgroups.end(); ) + { + if ( (*it)->type() != Attribute::VECTOR || found ) + { + delete *it; + it = vmgroups.erase(it); + } + else + { + thegroup = dynamic_cast(*it); + found = true; + + ++it; + } + } + + if ( thegroup == 0 ) + { + return 0; + } + + /* ------------------ Get the VMGroup by_name or by_id ------------------ */ + VMGroupPool * vmgrouppool = Nebula::instance().get_vmgrouppool(); + VMGroup * vmgroup; + + string vmg_role = thegroup->vector_value("ROLE"); + string vmg_name = thegroup->vector_value("VMGROUP"); + int vmg_id; + + if ( vmg_role.empty() ) + { + error = "Missing role name in VM Group definition"; + delete thegroup; + + return -1; + } + + if ( !vmg_name.empty() ) + { + int vmg_uid; + + if ( thegroup->vector_value("VMGROUP_UID", vmg_uid) == -1 ) + { + vmg_uid = get_uid(); + } + + vmgroup = vmgrouppool->get(gname, vmg_uid, true); + } + else if ( thegroup->vector_value("VMGROUP_ID", vmg_id) == 0 ) + { + vmgroup = vmgrouppool->get(vmg_id, true); + } + + if ( vmgroup == 0 ) + { + error = "Cannot find VM Group to associate the VM to"; + delete thegroup; + + return -1; + } + + /* ------------------ Add VM to the role in the vm group ---------------- */ + + thegroup->replace("VMGROUP_ID", vmgroup->get_oid()); + + int rc = vmgroup->add_vm(vmg_role, get_oid()); + + + if ( rc != 0 ) + { + error = "Role does not exist in VM Group"; + delete thegroup; + } + else + { + vmgrouppool->update(vmgroup); + + obj_template->set(thegroup); + } + + vmgroup->unlock(); + + return rc; +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +void VirtualMachine::release_vmgroup() +{ + VectorAttribute * thegroup = obj_template->get("VMGROUP"); + + if ( thegroup == 0 ) + { + return; + } + + int vmg_id; + + if ( thegroup->vector_value("VMGROUP_ID", vmg_id) == -1 ) + { + return; + } + + string vmg_role = thegroup->vector_value("ROLE"); + + if ( vmg_role.empty() ) + { + return; + } + + VMGroupPool * vmgrouppool = Nebula::instance().get_vmgrouppool(); + VMGroup * vmgroup = vmgrouppool->get(vmg_id, true); + + if ( vmgroup == 0 ) + { + return; + } + + vmgroup->del_vm(vmg_role, get_oid()); + + vmgrouppool->update(vmgroup); + + vmgroup->unlock(); +} + diff --git a/src/vm_group/VMGroup.cc b/src/vm_group/VMGroup.cc index 890740a44b..21c01460d7 100644 --- a/src/vm_group/VMGroup.cc +++ b/src/vm_group/VMGroup.cc @@ -202,6 +202,18 @@ int VMGroupRoles::del_vm(const std::string& role_name, int vmid) return 0; } +int VMGroupRoles::vm_size() +{ + int total = 0; + + for ( role_iterator it = begin(); it != end() ; ++it ) + { + total += (*it)->get_vms().size(); + } + + return total; +} + /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ /* VMGroup */ @@ -497,6 +509,18 @@ int VMGroup::insert(SqlDB *db, string& error_str) int VMGroup::post_update_template(string& error) { + int vms = roles.vm_size(); + + if ( vms > 0 ) + { + ostringstream oss; + + oss << "VM Group has " << vms << " VMs"; + error = oss.str(); + + return -1; + } + if ( check_affinity("AFFINED", error) == -1 ) { return -1;