예제 #1
0
    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()
예제 #2
0
    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
예제 #3
0
 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
예제 #4
0
 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
예제 #5
0
    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)
예제 #6
0
 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")
예제 #7
0
 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")
예제 #8
0
    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([], [])
예제 #9
0
        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")
예제 #10
0
    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()
예제 #11
0
    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)
예제 #12
0
        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))
예제 #13
0
    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")