def handle_central_keepalive_event(self, event): """ Called when the central agents announce themselves. @type event: xmpp.Node @param event: the pubsub event node """ items = event.getTag("event").getTag("items").getTags("item") for item in items: central_announcement_event = item.getTag("event") event_type = central_announcement_event.getAttr("type") if event_type == "keepalive": keepalive_jid = xmpp.JID( central_announcement_event.getAttr("jid")) if self.is_central_agent and keepalive_jid != self.jid: # detect another central agent self.log.warning( "CENTRALAGENT: another central agent detected, performing election" ) keepalive_salt = float( central_announcement_event.getAttr("salt")) if keepalive_salt > self.salt: self.log.debug("CENTRALAGENT: stepping down") self.change_presence("away", "Standby") self.is_central_agent = False else: self.log.debug("CENTRALAGENT: election won") return self.central_agent_jid_val = keepalive_jid self.last_keepalive_heard = datetime.datetime.now()
def unregister_vms(self, entries): """ Unregister a list of vms from central db. @type entries: List @param entries: list of vms """ # first, we extract jid so that the hypervisor can unregister them uuids = [] for entry in entries: uuids.append(entry["uuid"]) where_statement = "uuid = '" where_statement += "' or uuid='".join(uuids) where_statement += "'" # list of vms which have been found in central db, including uuid and jid cleaned_entries = self.read_vms("uuid,domain", where_statement) for i in range(len(cleaned_entries)): domain_xml = cleaned_entries[i]["domain"] if domain_xml != "None": domain = xmpp.simplexml.NodeBuilder( data=cleaned_entries[i]["domain"]).getDom() cleaned_entries[i]["jid"] = xmpp.JID( domain.getTag("description").getData().split("::::")[0]) del (cleaned_entries[i]["domain"]) self.db_commit("delete from vms where uuid=:uuid", cleaned_entries) return cleaned_entries
def iq_users_change_password(self, iq): """ Change password for users. @type iq: xmpp.Protocol.Iq @param iq: the received IQ @rtype: xmpp.Protocol.Iq @return: a ready to send IQ containing the result of the action """ try: reply = iq.buildReply("result") users = map(lambda x: {"jid": xmpp.JID(x.getAttr("jid")), "password": x.getAttr("password")}, iq.getTag("query").getTag("archipel").getTags("user")) self.users_change_password(users) except Exception as ex: reply = build_error_iq(self, ex, iq, ARCHIPEL_ERROR_CODE_XMPPSERVER_USERS_CHANGEPASSWORD) return reply
def iq_users_unregister(self, iq): """ Unregister somes users. @type iq: xmpp.Protocol.Iq @param iq: the received IQ @rtype: xmpp.Protocol.Iq @return: a ready to send IQ containing the result of the action """ try: reply = iq.buildReply("result") users = map(lambda x: xmpp.JID(x.getAttr("jid")), iq.getTag("query").getTag("archipel").getTags("user")) self.users_unregister(users) except Exception as ex: reply = build_error_iq(self, ex, iq, ARCHIPEL_ERROR_CODE_XMPPSERVER_USERS_UNREGISTER) return reply
def handle_central_keepalive_event(self, event): """ Called when the central agent sends a keepalive. @type event: xmpp.Node @param event: the pubsub event node """ items = event.getTag("event").getTag("items").getTags("item") for item in items: central_announcement_event = item.getTag("event") event_type = central_announcement_event.getAttr("type") if event_type == "keepalive": old_central_agent_jid = self.central_agent_jid() self.entity.log.debug("CENTRALDB: Keepalive heard : %s " % str(item)) keepalive_jid = xmpp.JID( central_announcement_event.getAttr("jid")) if central_announcement_event.getAttr("keepalive_interval"): self.keepalive_interval = int( central_announcement_event.getAttr( "keepalive_interval")) if central_announcement_event.getAttr( "hypervisor_timeout_threshold"): self.hypervisor_timeout_threshold = int( central_announcement_event.getAttr( "hypervisor_timeout_threshold")) self.central_agent_jid_val = keepalive_jid self.last_keepalive_heard = datetime.datetime.now() self.delayed_tasks.add( (self.hypervisor_timeout_threshold - self.keepalive_interval) * 2 / 3, self.push_statistics_to_centraldb, {'central_announcement_event': central_announcement_event}) if not old_central_agent_jid: self.delayed_tasks.add(self.keepalive_interval, self.handle_first_keepalive, {'keepalive_jid': keepalive_jid}) elif central_announcement_event.getAttr( "force_update" ) == "true" or keepalive_jid != old_central_agent_jid: self.delayed_tasks.add(self.keepalive_interval, self.push_vms_in_central_db)
def group_delete_users(self, ID, users): """ Delete users from a group @type ID: string @param ID: the ID of the group @type users: list @param users: list of users to remove """ server = self.entity.jid.getDomain() for user in users: userJID = xmpp.JID(user) answer = self._send_xmlrpc_call("srg_user_del", {"user": userJID.getNode(), "host": userJID.getDomain(), "group": ID, "grouphost": server}) if not answer['res'] == 0: raise Exception("Cannot remove user from shared roster group. %s" % str(answer)) self.entity.log.info("XMPPSERVER: Removing user %s from shared group %s" % (userJID, ID)) self.entity.push_change("xmppserver:groups", "usersdeleted")
def group_add_users(self, ID, users): """ Add users into a group @type ID: string @param ID: the ID of the group @type users: list @param users: list of the users to add in the group """ server = self.entity.jid.getDomain() members = self._send_xmlrpc_call("srg_get_members", {"host": server, "group": ID}) for user in users: userJID = xmpp.JID(user) if [True for member in members['members'] if member['member'] == userJID]: continue answer = self._send_xmlrpc_call("srg_user_add", {"user": userJID.getNode(), "host": userJID.getDomain(), "group": ID, "grouphost": server}) if not answer['res'] == 0: raise Exception("Cannot add user to shared roster group. %s" % str(answer)) self.entity.log.info("XMPPSERVER: Adding user %s into shared group %s" % (userJID, ID)) self.entity.push_change("xmppserver:groups", "usersadded")
def handle_first_keepalive(self, keepalive_jid): """ this is the first keepalive. We query hypervisors that have started somewhere else then we trigger method manage_persistence to start the vms. """ vms_from_local_db = self.entity.get_vms_from_local_db() if len(vms_from_local_db) > 0: dbCommand = xmpp.Node(tag="event", attrs={"jid": self.entity.jid}) for vm in vms_from_local_db: entryTag = xmpp.Node(tag="entry") uuid = xmpp.JID(vm["string_jid"]).getNode() entryTag.addChild("item", attrs={"key": "uuid", "value": uuid}) dbCommand.addChild(node=entryTag) iq = xmpp.Iq(typ="set", queryNS=ARCHIPEL_NS_CENTRALAGENT, to=keepalive_jid) iq.getTag("query").addChild( name="archipel", attrs={"action": "read_vms_started_elsewhere"}) iq.getTag("query").getTag("archipel").addChild(node=dbCommand) xmpp.dispatcher.ID += 1 iq.setID("%s-%d" % (self.entity.jid.getNode(), xmpp.dispatcher.ID)) def _read_vms_started_elsewhere_callback(conn, packed_vms): vms_started_elsewhere = self.unpack_entries(packed_vms) self.entity.manage_persistence(vms_from_local_db, vms_started_elsewhere) self.entity.xmppclient.SendAndCallForResponse( iq, _read_vms_started_elsewhere_callback) else: # update status to Online(0) self.entity.manage_persistence([], [])
def _unregister_vms_callback(unregistered_vms): self.entity.log.debug("VMPARKING: unregistered_vms: %s" % unregistered_vms) # Then perfom cleanup operations jids = [] for vm in unregistered_vms: vmfolder = "%s/%s" % (self.configuration.get( "VIRTUALMACHINE", "vm_base_path"), vm["uuid"]) if os.path.exists(vmfolder): shutil.rmtree(vmfolder) jids.append(xmpp.JID(vm["jid"])) # And remove the XMPP account self.entity.get_plugin("xmppserver").users_unregister(jids) self.entity.log.info( "VMPARKING: successfully deleted %s from parking" % str(unregistered_vms)) self.entity.push_change("vmparking", "deleted")
def handle_first_keepalive(self, keepalive_jid): """ this is the first keepalive. We query hypervisors that have vm entities somewhere else then we trigger method manage_persistence to instantiate vm entities. """ vms_from_local_db = self.entity.get_vms_from_local_db() if len(vms_from_local_db) > 0: dbCommand = xmpp.Node(tag="event", attrs={"jid": self.entity.jid}) for vm in vms_from_local_db: entryTag = xmpp.Node(tag="entry") uuid = xmpp.JID(vm["string_jid"]).getNode() entryTag.addChild("item", attrs={"key": "uuid", "value": uuid}) dbCommand.addChild(node=entryTag) iq = xmpp.Iq(typ="set", queryNS=ARCHIPEL_NS_CENTRALAGENT, to=keepalive_jid) iq.getTag("query").addChild( name="archipel", attrs={"action": "get_existing_vms_instances"}) iq.getTag("query").getTag("archipel").addChild(node=dbCommand) def _get_existing_vms_instances_callback(conn, packed_vms): existing_vms_entities = self.unpack_entries(packed_vms) self.entity.manage_persistence(vms_from_local_db, existing_vms_entities) self.entity.xmppclient.SendAndCallForResponse( iq, _get_existing_vms_instances_callback) else: # update status to Online(0) self.entity.manage_persistence()
def handle_central_keepalive_event(self, event): """ Called when the central agent sends a keepalive. @type event: xmpp.Node @param event: the pubsub event node """ items = event.getTag("event").getTag("items").getTags("item") for item in items: central_announcement_event = item.getTag("event") event_type = central_announcement_event.getAttr("type") if event_type == "keepalive": old_central_agent_jid = self.central_agent_jid() self.entity.log.debug("CENTRALDB: Keepalive heard : %s " % str(item)) keepalive_jid = xmpp.JID( central_announcement_event.getAttr("jid")) # we use central agent time in case of drift between hypervisors central_agent_time = central_announcement_event.getAttr( "central_agent_time") self.central_agent_jid_val = keepalive_jid self.last_keepalive_heard = datetime.datetime.now() self.push_statistics_to_centraldb(central_agent_time) if old_central_agent_jid == None: self.handle_first_keepalive(keepalive_jid) if central_announcement_event.getAttr( "force_update" ) == "true" or keepalive_jid != old_central_agent_jid: self.push_vms_in_central_db(central_announcement_event)
def _unpark_callback(vm_items): vm_information_by_uuid = {} for vm_info in vm_information: vm_information_by_uuid[vm_info["uuid"]] = vm_info for vm_item in vm_items: vm_info = vm_information_by_uuid[vm_item["uuid"]] domain = vm_item["domain"] ret = str(domain).replace( 'xmlns=\"archipel:hypervisor:vmparking\"', '') domain = xmpp.simplexml.NodeBuilder(data=ret).getDom() vmjid = domain.getTag("description").getData().split("::::")[0] vmpass = domain.getTag("description").getData().split( "::::")[1] vmname = domain.getTag("name").getData() self.entity.log.debug("VMPARKING: about to create vm thread") vm_thread = self.entity.soft_alloc( xmpp.JID(vmjid), vmname, vmpass, start=False, organization_info=self.entity.vcard_infos) vm = vm_thread.get_instance() vm.register_hook("HOOK_ARCHIPELENTITY_XMPP_AUTHENTICATED", method=vm.define_hook, user_info=domain, oneshot=True) if vm_info["start"]: vm.register_hook("HOOK_ARCHIPELENTITY_XMPP_AUTHENTICATED", method=vm.control_create_hook, oneshot=True) vm_thread.start() self.entity.push_change("vmparking", "unparked") self.entity.log.info("VMPARKING: successfully unparked %s" % str(vmjid))
def park(self, vm_informations): """ Park a virtual machine. @type vm_informations: list @param vm_informations: list of dict like {"uuid": x, "parker": z)} """ vm_informations_cleaned = [] for vm_info in vm_informations: vm = self.entity.get_vm_by_uuid(vm_info["uuid"]) if not vm: self.entity.log.warning( "VMPARKING: No virtual machine with UUID %s" % vm_info["uuid"]) continue if not vm.domain: self.entity.log.warning( "VMPARKING: VM with UUID %s cannot be parked because it is not defined" % vm_info["uuid"]) continue vm_informations_cleaned.append(vm_info) # Now, perform operations new_vm_info = [] for vm_info in vm_informations_cleaned: vm = self.entity.get_vm_by_uuid(vm_info["uuid"]) if not vm.info()["state"] == 5: vm.destroy() domain = vm.xmldesc(mask_description=False) vm_jid = xmpp.JID( domain.getTag("description").getData().split("::::")[0]) vm_info["hypervisor"] = None vm_info['name'] = domain.getTag("name").getData() new_vm_info.append(vm_info) self.entity.soft_free(vm_jid) if len(new_vm_info) > 0: self.entity.get_plugin("centraldb").update_vms(vm_informations) self.entity.push_change("vmparking", "parked")