def _on_centralagent_reply(results): try: error = False result_msg = "" for result in results: result_msg += "uuid : %s, error : %s, msg : %s" % ( result["uuid"], result["error"], result["result"]) if result["error"] == "True": error = True if not error: reply = iq.buildReply("result") self.entity.push_change("vmparking", "updated") else: reply = build_error_iq( self, result_msg, iq, ARCHIPEL_ERROR_CODE_VMPARK_UPDATEXML) except Exception as ex: reply = build_error_iq(self, ex, iq, ARCHIPEL_ERROR_CODE_VMPARK_UPDATEXML) self.entity.xmppclient.send(reply) raise xmpp.protocol.NodeProcessed
def iq_display(self, iq): """ Get the VNC display used in the virtual machine. @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 """ reply = iq.buildReply("result") try: if not self.entity.domain: return iq.buildReply('ignore') ports = self.display() if not ports: payload = xmpp.Node("display", attrs={}) else: payload = xmpp.Node("display", attrs={ "port": str(ports["direct"]), "proxy": str(ports["proxy"]), "host": self.entity.ipaddr, "onlyssl": str(ports["onlyssl"]), "supportssl": str(ports["supportssl"]) }) reply.setQueryPayload([payload]) except libvirt.libvirtError as ex: reply = build_error_iq(self, ex, iq, ex.get_error_code(), ns=archipel.archipelLibvirtEntity. ARCHIPEL_NS_LIBVIRT_GENERIC_ERROR) except Exception as ex: reply = build_error_iq(self, ex, iq, ARCHIPEL_ERROR_CODE_VM_VNC) return reply
def iq_alloc(self, iq): """ This method creates a threaded L{TNArchipelVirtualMachine} with UUID given as payload in IQ and register the hypervisor and the iq sender in the VM's roster. @type iq: xmpp.Protocol.Iq @param iq: the sender request IQ @rtype: xmpp.Protocol.Iq @return: a ready-to-send IQ containing the results """ try: try: requested_name = iq.getTag("query").getTag("archipel").getAttr("name") except: requested_name = None vm = self.alloc(iq.getFrom(), requested_name=requested_name) reply = iq.buildReply("result") payload = xmpp.Node("virtualmachine", attrs={"jid": str(vm.jid.getStripped())}) reply.setQueryPayload([payload]) self.shout("virtualmachine", "A new Archipel Virtual Machine has been created by %s with uuid %s" % (iq.getFrom(), vm.uuid)) except libvirt.libvirtError as ex: reply = build_error_iq(self, ex, iq, ex.get_error_code(), ns=ARCHIPEL_NS_LIBVIRT_GENERIC_ERROR) except Exception as ex: reply = build_error_iq(self, ex, iq, ARCHIPEL_ERROR_CODE_HYPERVISOR_ALLOC) return reply
def iq_free(self, iq): """ This method destroy a threaded L{TNArchipelVirtualMachine} with UUID given as payload in IQ and remove it from the hypervisor roster. @type iq: xmpp.Protocol.Iq @param iq: the sender request IQ @rtype: xmpp.Protocol.Iq @return: a ready-to-send IQ containing the results """ reply = iq.buildReply("result") try: vm_jid = xmpp.JID( jid=iq.getTag("query").getTag("archipel").getAttr("jid")) domain_uuid = vm_jid.getNode() self.free(vm_jid) reply.setQueryPayload( [xmpp.Node(tag="virtualmachine", attrs={"jid": vm_jid})]) self.shout( "virtualmachine", "The Archipel Virtual Machine %s has been destroyed by %s" % (domain_uuid, iq.getFrom())) except libvirt.libvirtError as ex: reply = build_error_iq(self, ex, iq, ex.get_error_code(), ns=ARCHIPEL_NS_LIBVIRT_GENERIC_ERROR) except Exception as ex: reply = build_error_iq(self, ex, iq, ARCHIPEL_ERROR_CODE_HYPERVISOR_FREE) return reply
def iq_get_names(self, iq): """ List all virtual network names. @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") active_networks_nodes = [] actives_networks_names = self.get(inactive=False)["active"] for network_name in actives_networks_names: network = xmpp.Node(tag="network", attrs={"name": network_name}) active_networks_nodes.append(network) reply.setQueryPayload(active_networks_nodes) except libvirt.libvirtError as ex: reply = build_error_iq(self, ex, iq, ex.get_error_code(), ns=ARCHIPEL_NS_LIBVIRT_GENERIC_ERROR) except Exception as ex: reply = build_error_iq(self, ex, iq, ARCHIPEL_ERROR_CODE_NETWORKS_GETNAMES) return reply
def iq_revert(self, iq): """ return current snapshot @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") # xmlDesc = iq.getTag('query').getTag('uuid') would be better but not in API at this time. name = iq.getTag('query').getTag("archipel").getAttr('name') old_show = self.entity.xmppstatusshow old_status = self.entity.xmppstatus self.entity.log.info("restoring snapshot with name %s" % name) self.entity.change_presence(presence_show="dnd", presence_status="Restoring snapshot...") snapshotObject = self.entity.domain.snapshotLookupByName(name, 0) self.entity.domain.revertToSnapshot(snapshotObject, 0) self.entity.change_presence(presence_show=old_show, presence_status=old_status) self.entity.log.info("reverted to snapshot with name %s " % name) self.entity.push_change("snapshoting", "restored") self.entity.shout("Snapshot", "I've been reverted to the snapshot named %s as asked by %s" % (name, iq.getFrom())) except libvirt.libvirtError as ex: self.entity.change_presence(presence_show=old_show, presence_status="Error while reverting") reply = build_error_iq(self, ex, iq, ex.get_error_code(), ns=ARCHIPEL_NS_LIBVIRT_GENERIC_ERROR) except Exception as ex: self.entity.change_presence(presence_show=old_show, presence_status="Error while reverting") reply = build_error_iq(self, ex, iq, ARCHIPEL_ERROR_CODE_SNAPSHOT_REVERT) return reply
def iq_define(self, iq): """ Define a virtual network in the libvirt according to the XML data network passed in argument. @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") network_node = iq.getTag("query").getTag("archipel").getTag( "network") self.define(network_node) if iq.getTag("query").getTag("archipel").getAttr( "autostart") == "1": self.setAutostart(network_node.getTag("uuid").getData(), True) except libvirt.libvirtError as ex: reply = build_error_iq(self, ex, iq, ex.get_error_code(), ns=ARCHIPEL_NS_LIBVIRT_GENERIC_ERROR) except Exception as ex: reply = build_error_iq(self, ex, iq, ARCHIPEL_ERROR_CODE_NETWORKS_DEFINE) return reply
def iq_destroy(self, iq): """ Destroy a network using libvirt connection. @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: network_uuid = iq.getTag("query").getTag("archipel").getAttr( "uuid") self.destroy(network_uuid) reply = iq.buildReply("result") self.entity.shout( "network", "Network %s has been shutdowned by %s." % (network_uuid, iq.getFrom())) except libvirt.libvirtError as ex: reply = build_error_iq(self, ex, iq, ex.get_error_code(), ns=ARCHIPEL_NS_LIBVIRT_GENERIC_ERROR) except Exception as ex: reply = build_error_iq(self, ex, iq, ARCHIPEL_ERROR_CODE_NETWORKS_DESTROY) return reply
def iq_get(self, iq): """ List all snapshots. @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") nodes = [] if self.entity.domain.hasCurrentSnapshot(0): snapshot_names = self.entity.domain.snapshotListNames(0) for snapshot_name in snapshot_names: snapshotObject = self.entity.domain.snapshotLookupByName( snapshot_name, 0) desc = snapshotObject.getXMLDesc(0) n = xmpp.simplexml.NodeBuilder(data=desc).getDom() nodes.append(n) reply.setQueryPayload(nodes) except libvirt.libvirtError as ex: reply = build_error_iq(self, ex, iq, ex.get_error_code(), ns=ARCHIPEL_NS_LIBVIRT_GENERIC_ERROR) except Exception as ex: reply = build_error_iq(self, ex, iq, ARCHIPEL_ERROR_CODE_SNAPSHOT_GET) return reply
def iq_getcurrent(self, iq): """ Return current snapshot. @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") if self.entity.domain.hasCurrentSnapshot(0): snapshotObject = self.entity.domain.snapshotCurrent(0) desc = snapshotObject.getXMLDesc(0) n = xmpp.simplexml.NodeBuilder(data=desc).getDom() reply.setQueryPayload([n]) except libvirt.libvirtError as ex: if ex.get_error_code() == libvirt.VIR_ERR_NO_DOMAIN_SNAPSHOT: reply = iq.buildReply("result") else: reply = build_error_iq(self, ex, iq, ex.get_error_code(), ns=ARCHIPEL_NS_LIBVIRT_GENERIC_ERROR) except Exception as ex: reply = build_error_iq(self, ex, iq, ARCHIPEL_ERROR_CODE_SNAPSHOT_CURRENT) return reply
def iq_get(self, iq): """ List all virtual networks. @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") active_networks_nodes = [] inactive_networks_nodes = [] networks = self.get() for network_name in networks["active"]: network = self.entity.libvirt_connection.networkLookupByName(network_name) desc = network.XMLDesc(0) n = xmpp.simplexml.NodeBuilder(data=desc).getDom() n.setAttr("autostart", self.getAutostart(network_name)) active_networks_nodes.append(n) for network_name in networks["inactive"]: network = self.entity.libvirt_connection.networkLookupByName(network_name) desc = network.XMLDesc(0) n = xmpp.simplexml.NodeBuilder(data=desc).getDom() n.setAttr("autostart", self.getAutostart(network_name)) inactive_networks_nodes.append(n) active_networks_root_node = xmpp.Node(tag="activedNetworks", payload=active_networks_nodes) inactive_networks_root_node = xmpp.Node(tag="unactivedNetworks", payload=inactive_networks_nodes) reply.setQueryPayload([active_networks_root_node, inactive_networks_root_node]) except libvirt.libvirtError as ex: reply = build_error_iq(self, ex, iq, ex.get_error_code(), ns=ARCHIPEL_NS_LIBVIRT_GENERIC_ERROR) except Exception as ex: reply = build_error_iq(self, ex, iq, ARCHIPEL_ERROR_CODE_NETWORKS_GET) return reply
def iq_display(self, iq): """ Get the VNC display used in the virtual machine. @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 """ reply = iq.buildReply("result") try: if not self.entity.domain: return iq.buildReply("ignore") ports = self.display() if not ports: payload = xmpp.Node("display", attrs={}) else: payload = xmpp.Node( "display", attrs={ "port": str(ports["direct"]), "proxy": str(ports["proxy"]), "host": self.entity.ipaddr, "onlyssl": str(ports["onlyssl"]), "supportssl": str(ports["supportssl"]), }, ) reply.setQueryPayload([payload]) except libvirt.libvirtError as ex: reply = build_error_iq( self, ex, iq, ex.get_error_code(), ns=archipel.archipelLibvirtEntity.ARCHIPEL_NS_LIBVIRT_GENERIC_ERROR ) except Exception as ex: reply = build_error_iq(self, ex, iq, ARCHIPEL_ERROR_CODE_VM_VNC) return reply
def iq_health_info(self, iq): """ Send information about the hypervisor health info. @type iq: xmpp.Protocol.Iq @param iq: the sender request IQ @rtype: xmpp.Protocol.Iq @return: a ready-to-send IQ containing the results """ try: reply = iq.buildReply("result") nodes = [] stats = self.collector.get_collected_stats(1) if not stats: reply = build_error_iq(self, "Unable to get stats. See hypervisor log.", iq) else: try: mem_free_node = xmpp.Node("memory", attrs=stats["memory"][0]) nodes.append(mem_free_node) except Exception as ex: raise Exception("Unable to append memory stats node.", ex) try: cpu_node = xmpp.Node("cpu", attrs=stats["cpu"][0]) nodes.append(cpu_node) except Exception as ex: raise Exception("Unable to append cpu stats node.", ex) try: disk_free_node = xmpp.Node("disk", attrs=stats["totaldisk"]) for s in stats["disk"]: disk_free_node.addChild("partition", attrs=s) nodes.append(disk_free_node) except Exception as ex: raise Exception("Unable to append disk stats node.", ex) try: network_node = xmpp.Node("networks") for nic, delta in json.loads(stats["network"][0]["records"]).items(): network_node.addChild("network", attrs={"name": nic, "delta": delta}) nodes.append(network_node) except Exception as ex: raise Exception("Unable to append network stats node.", ex) try: load_node = xmpp.Node("load", attrs=stats["load"][0]) nodes.append(load_node) except Exception as ex: raise Exception("Unable to append load avergae stats node.", ex) try: uptime_node = xmpp.Node("uptime", attrs=stats["uptime"]) nodes.append(uptime_node) except Exception as ex: raise Exception("Unable to append uptime stats node:", ex) try: uname_node = xmpp.Node("uname", attrs=stats["uname"]) nodes.append(uname_node) except Exception as ex: raise Exception("Unable to append uname node.", ex) reply.setQueryPayload(nodes) except Exception as ex: reply = build_error_iq(self, ex, iq, ARCHIPEL_ERROR_CODE_HEALTH_INFO) return reply
def iq_set_permission(self, iq, onlyown): """ set a list of permission @type iq: xmpp.Node @param iq: the original request IQ @type onlyown: Boolean @param onlyown: if True, will raise an exception if user trying to set permission for other user """ try: reply = iq.buildReply("result") errors = [] perms = iq.getTag("query").getTag("archipel").getTags(name="permission") if onlyown: for perm in perms: if not perm.getAttr("permission_target") == iq.getFrom().getStripped(): raise Exception("You cannot set permissions of other users") perm_targets = [] for perm in perms: perm_type = perm.getAttr("permission_type") perm_target = perm.getAttr("permission_target") perm_name = perm.getAttr("permission_name") perm_value = perm.getAttr("permission_value") if perm_type == "role": if perm_value.upper() in ("1", "TRUE", "YES", "Y"): if not self.permission_center.grant_permission_to_role(perm_name, perm_target): errors.append("cannot grant permission %s on role %s" % (perm_name, perm_target)) else: if not self.permission_center.revoke_permission_to_role(perm_name, perm_target): errors.append("cannot revoke permission %s on role %s" % (perm_name, perm_target)) elif perm_type == "user": if perm_value.upper() in ("1", "TRUE", "YES", "Y", "OUI", "O"): self.log.info("granting permission %s to user %s" % (perm_name, perm_target)) if not self.permission_center.grant_permission_to_user(perm_name, perm_target): errors.append("cannot grant permission %s on user %s" % (perm_name, perm_target)) else: self.log.info("revoking permission %s to user %s" % (perm_name, perm_target)) if not self.permission_center.revoke_permission_to_user(perm_name, perm_target): errors.append("cannot revoke permission %s on user %s" % (perm_name, perm_target)) if perm_name == "presence": if self.permission_center.check_permission(perm_target, "presence"): self.authorize(xmpp.JID(perm_target)) else: self.unauthorize(xmpp.JID(perm_target)) if not perm_target in perm_targets: perm_targets.append(perm_target) if len(errors) > 0: reply = build_error_iq(self, str(errors), iq, ARCHIPEL_NS_PERMISSION_ERROR) for target in perm_targets: self.push_change("permissions", target) except Exception as ex: reply = build_error_iq(self, ex, iq, ARCHIPEL_ERROR_CODE_SET_PERMISSIONS) return reply
def iq_bridges(self, iq): """ List all bridge names. @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") bridges_list = commands.getoutput( "brctl show 2>/dev/null | grep -v -E '^[[:space:]]|bridge name' | cut -f 1" ).split("\n") bridges_list += commands.getoutput( "ovs-vsctl list-br 2>/dev/null").split("\n") bridges_list = sorted(set(bridges_list)) bridges_names = [] for bridge_name in bridges_list: if bridge_name: bridge_node = xmpp.Node(tag="bridge", attrs={"name": bridge_name}) bridges_names.append(bridge_node) reply.setQueryPayload(bridges_names) except Exception as ex: reply = build_error_iq(self, ex, iq, ARCHIPEL_ERROR_CODE_NETWORKS_BRIDGES) return reply
def iq_register(self, iq): """ Register to a new VMCast. @type iq: xmpp.Protocol.Iq @param iq: the sender request IQ @rtype: xmpp.Protocol.Iq @return: a ready-to-send IQ containing the results """ reply = iq.buildReply("result") url = iq.getTag("query").getTag("archipel").getAttr("url") try: if not url or url == "": raise Exception("IncorrectStanza", "Stanza must have url: %s" % str(iq)) try: urllib.urlcleanup() f = urllib.urlopen(url) except: raise Exception("The given url doesn't exist. Can't register.") try: self.getFeed(f.read()) except: raise Exception("The given url doesn't contains a valid VMCast feed. Can't register.") self.cursor.execute("INSERT INTO vmcastsources (url) VALUES ('%s')" % url) self.database_connection.commit() self.parseRSS() self.entity.push_change("vmcasting", "register") self.entity.shout("vmcast", "I'm now registred to vmcast %s as asked by %s" % (url, iq.getFrom())) except Exception as ex: reply = build_error_iq(self, ex, iq, ARCHIPEL_ERROR_CODE_VMCASTS_REGISTER) return reply
def iq_group_list(self, iq): """ List shared groups. @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") groups = self.group_list() groupsNode = [] for group in groups: members = group["members"] del group["members"] displayed_groups = group["displayed_groups"] del group["displayed_groups"] newNode = xmpp.Node("group", attrs=group) for member in members: newNode.addChild("user", attrs={"jid": member}) for displayed_group in displayed_groups: if(displayed_group != ''): newNode.addChild("displayed_group", attrs={"id": displayed_group}) groupsNode.append(newNode) newNode = xmpp.Node("displayed_groups") reply.setQueryPayload(groupsNode) except Exception as ex: reply = build_error_iq(self, ex, iq, ARCHIPEL_ERROR_CODE_XMPPSERVER_GROUP_LIST) return reply
def iq_getiso(self, iq): """ Get the virtual cdrom ISO of the virtual machine @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: nodes = [] isos = subprocess.Popen(["ls", self.entity.folder], stdout=subprocess.PIPE).communicate()[0].split() for iso in isos: if subprocess.Popen(["file", "%s/%s" % (self.shared_isos_folder, iso)], stdout=subprocess.PIPE).communicate()[0].lower().find("iso 9660") > -1: node = xmpp.Node(tag="iso", attrs={"name": iso, "path": self.entity.folder + "/" + iso}) nodes.append(node) sharedisos = subprocess.Popen(["ls", self.shared_isos_folder], stdout=subprocess.PIPE).communicate()[0].split() for iso in sharedisos: if subprocess.Popen(["file", "%s/%s" % (self.shared_isos_folder, iso)], stdout=subprocess.PIPE).communicate()[0].lower().find("iso 9660") > -1: node = xmpp.Node(tag="iso", attrs={"name": iso, "path": self.shared_isos_folder + "/" + iso}) nodes.append(node) reply = iq.buildReply("result") reply.setQueryPayload(nodes) self.entity.log.info("info about iso sent") except Exception as ex: reply = build_error_iq(self, ex, iq, ARCHIPEL_ERROR_CODE_DRIVES_GETISO) return reply
def iq_create_parked(self, iq): """ Create a VM in directly into the parking @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: items = iq.getTag("query").getTag("archipel").getTags("item") vms_info = [] for item in items: vm_uuid = item.getAttr("uuid") if not vm_uuid: self.entity.log.error("VMPARKING: Unable to park vm: missing 'uuid' element.") raise Exception("You must must set the UUID of the vms you want to park") vm_domain = item.getTag("domain") vms_info.append({"uuid": vm_uuid, "domain": vm_domain, "parker": str(iq.getFrom()), "creation_date": datetime.datetime.now(), "status": ARCHIPEL_PARKING_STATUS_PARKED}) self.create_parked(vms_info) reply = iq.buildReply("result") except Exception as ex: reply = build_error_iq(self, ex, iq, ARCHIPEL_ERROR_CODE_VMPARK_CREATE_PARKED) return reply
def iq_health_info_history(self, iq): """ Get a range of old stat history according to the limit parameters in iq node. @type iq: xmpp.Protocol.Iq @param iq: the sender request IQ @rtype: xmpp.Protocol.Iq @return: a ready-to-send IQ containing the results """ try: reply = iq.buildReply("result") self.entity.log.debug("Converting stats into XML node.") limit = int(iq.getTag("query").getTag("archipel").getAttr("limit")) nodes = [] stats = self.collector.get_collected_stats(limit) number_of_rows = limit if number_of_rows > len(stats["memory"]): number_of_rows = len(stats["memory"]) for i in range(number_of_rows): statNode = xmpp.Node("stat") statNode.addChild("memory", attrs=stats["memory"][i]) statNode.addChild("cpu", attrs=stats["cpu"][i]) statNode.addChild("disk") statNode.addChild("load", attrs=stats["load"][i]) network_node = statNode.addChild("networks") for nic, delta in json.loads(stats["network"][i]["records"]).items(): network_node.addChild("network", attrs={"name": nic, "delta": delta}) nodes.append(statNode) reply.setQueryPayload(nodes) except Exception as ex: reply = build_error_iq(self, ex, iq, ARCHIPEL_ERROR_CODE_HEALTH_HISTORY) return reply
def iq_get_logs(self, iq): """ Read the hypervisor's log file. @type iq: xmpp.Protocol.Iq @param iq: the sender request IQ @rtype: xmpp.Protocol.Iq @return: a ready-to-send IQ containing the results """ try: reply = iq.buildReply("result") limit = int(iq.getTag("query").getTag("archipel").getAttr("limit")) output = commands.getoutput("tail -n %d %s" % (limit, self.logfile)) nodes = [] for line in output.split("\n"): try: infos = line.split("::") log_node = xmpp.Node("log", attrs={ "level": infos[0], "date": infos[1], "file": "", "method": "" }) log_node.setData(line) nodes.append(log_node) except Exception as ex: pass reply.setQueryPayload(nodes) except Exception as ex: print str(ex) reply = build_error_iq(self, ex, iq, ARCHIPEL_ERROR_CODE_HEALTH_LOG) return reply
def iq_users_register(self, iq): """ Register some new 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: def on_receive_registration(conn, iq): if iq.getType() == "result": self.entity.log.info("XMPPSERVER: Successfully registred user.") self.entity.log.debug("XMPPSERVER: Caching entity type %s as human" % iq.getFrom().getStripped()) self.entity.push_change("xmppserver:users", "registered") else: self.entity.push_change("xmppserver:users", "registerationerror", content_node=iq) self.entity.log.error("XMPPSERVER: Unable to register user. %s" % str(iq)) reply = iq.buildReply("result") users = iq.getTag("query").getTag("archipel").getTags("user") server = self.entity.jid.getDomain() for user in users: username = user.getAttr("username") password = user.getAttr("password") iq_string = IQ_REGISTER_USER_FORM % (self.entity.jid.getDomain(), username, password, password, "", "", "") iq = xmpp.simplexml.NodeBuilder(data=iq_string).getDom() self.entity.xmppclient.SendAndCallForResponse(iq, on_receive_registration) self.entities_types_cache[username] = "human" self.entity.log.info("XMPPSERVER: Registring a new user %s@%s" % (username, server)) except Exception as ex: reply = build_error_iq(self, ex, iq, ARCHIPEL_ERROR_CODE_XMPPSERVER_USERS_REGISTER) return reply
def iq_getgolden(self, iq): """ Get the list of golden qcow2 images @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: nodes = [] goldens = os.listdir(self.golden_drives_dir) for golden in goldens: if self._is_file_a_qcow(os.path.join(self.golden_drives_dir, golden)) \ or self._is_file_a_qcow2(os.path.join(self.golden_drives_dir, golden)): node = xmpp.Node(tag="golden", attrs={ "name": golden, "path": os.path.join(self.golden_drives_dir, golden) }) nodes.append(node) reply = iq.buildReply("result") reply.setQueryPayload(nodes) self.entity.log.info("Info about golden sent.") except Exception as ex: reply = build_error_iq(self, ex, iq, ARCHIPEL_ERROR_CODE_DRIVES_GETGOLDEN) return reply
def iq_rename(self, iq): """ Rename a disk. @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: query_node = iq.getTag("query") path = query_node.getTag("archipel").getAttr("path") newname = query_node.getTag("archipel").getAttr("newname").replace( " ", "_").replace("/", "_").replace("..", "_") extension = path.split(".")[-1] newpath = os.path.join(self.entity.folder, "%s.%s" % (newname, extension)) if os.path.exists(newpath): raise Exception("The disk with name %s already exists." % newname) os.rename(path, newpath) reply = iq.buildReply("result") self.entity.log.info("Renamed hard drive %s into %s" % (path, newname)) self.entity.shout( "disk", "I've just renamed hard drive %s into %s." % (path, newname)) self.entity.push_change("disk", "renamed") except Exception as ex: reply = build_error_iq(self, ex, iq, ARCHIPEL_ERROR_CODE_DRIVES_RENAME) return reply
def iq_jobs(self, iq): """ Get jobs. @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") nodes = [] if hasattr(self.scheduler, "get_jobs"): jobs = self.scheduler.get_jobs() else: jobs = self.scheduler.jobs for job in jobs: job_node = xmpp.Node(tag="job", attrs={ "action": str(job.args[0]), "uid": str(job.args[1]), "date": str(job.args[2]), "comment": job.args[3] }) nodes.append(job_node) reply.setQueryPayload(nodes) except Exception as ex: reply = build_error_iq(self, ex, iq) 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: def on_receive_unregistration(conn, iq): if iq.getType() == "result": self.entity.log.info("XMPPSERVER: Successfully unregistred user.") self.entity.push_change("xmppserver:users", "unregistered") else: self.entity.push_change("xmppserver:users", "unregisterationerror", content_node=iq) self.entity.log.error("XMPPSERVER: unable to unregister user. %s" % str(iq)) reply = iq.buildReply("result") users = iq.getTag("query").getTag("archipel").getTags("user") server = self.entity.jid.getDomain() jids_string_nodes = "" for user in users: username = user.getAttr("username") jid = " <value>%s</value>\n" % username jids_string_nodes = "%s%s" % (jids_string_nodes, jid) if username in self.entities_types_cache: self.entity.log.debug("XMPPSERVER: uncaching entity type for %s" % username) del self.entities_types_cache[username] iq_string = IQ_UNREGISTRATION_FORM % (self.entity.jid.getDomain(), jids_string_nodes) iq = xmpp.simplexml.NodeBuilder(data=iq_string).getDom() self.entity.xmppclient.SendAndCallForResponse(iq, on_receive_unregistration) self.entity.log.info("XMPPSERVER: Unregistring some users %s" % str(users)) except Exception as ex: reply = build_error_iq(self, ex, iq, ARCHIPEL_ERROR_CODE_XMPPSERVER_USERS_UNREGISTER) return reply
def iq_getiso(self, iq): """ Get the virtual cdrom ISO of the virtual machine. @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: nodes = [] isos = os.listdir(self.entity.folder) for iso in isos: if self._is_file_an_iso(os.path.join(self.entity.folder, iso)): node = xmpp.Node(tag="iso", attrs={"name": iso, "path": os.path.join(self.entity.folder, iso)}) nodes.append(node) sharedisos = os.listdir(self.shared_isos_folder) for iso in sharedisos: if self._is_file_an_iso(os.path.join(self.shared_isos_folder, iso)): node = xmpp.Node(tag="iso", attrs={"name": iso, "path": os.path.join(self.shared_isos_folder, iso)}) nodes.append(node) reply = iq.buildReply("result") reply.setQueryPayload(nodes) self.entity.log.info("Info about iso sent.") except Exception as ex: reply = build_error_iq(self, ex, iq, ARCHIPEL_ERROR_CODE_DRIVES_GETISO) return reply
def iq_attach(self, iq): """ Instanciate a new virtualmachine from an installed appliance. @type iq: xmpp.Protocol.Iq @param iq: the sender request IQ @rtype: xmpp.Protocol.Iq @return: a ready-to-send IQ containing the results """ reply = iq.buildReply("result") try: if self.is_installing: raise Exception("Virtual machine is already installing a package.") if (self.is_installed): raise Exception("You must detach from already attached template.") uuid = iq.getTag("query").getTag("archipel").getAttr("uuid") requester = iq.getFrom() self.cursor.execute("SELECT * FROM vmcastappliances WHERE uuid=\"%s\"" % (uuid)) for values in self.cursor: name, description, url, uuid, status, source, save_path = values self.entity.log.debug("Supported extensions : %s " % str(self.disks_extensions)) self.entity.log.info("will install appliance with uuid %s at path %s" % (uuid, save_path)) appliance_packager = appliancedecompresser.TNApplianceDecompresser(self.temp_directory, self.disks_extensions, save_path, self.entity, self.finish_installing, self.error_installing, uuid, requester) self.old_status = self.entity.xmppstatus self.old_show = self.entity.xmppstatusshow self.entity.change_presence(presence_show="dnd", presence_status="Installing from appliance...") self.is_installing = True self.installing_media_uuid = uuid appliance_packager.start() self.entity.push_change("vmcasting", "applianceinstalling") except Exception as ex: reply = build_error_iq(self, ex, iq, ARCHIPEL_ERROR_CODE_VMAPPLIANCES_INSTALL) return reply
def iq_unmanage(self, iq): """ Unanage an managed virtual machine @type iq: xmpp.Protocol.Iq @param iq: the sender request IQ @rtype: xmpp.Protocol.Iq @return: a ready-to-send IQ containing the results """ try: reply = iq.buildReply("result") items = iq.getTag("query").getTag("archipel").getTags("item") for item in items: jid = xmpp.JID(item.getAttr("jid")) uuid = jid.getNode() if not uuid in self.virtualmachines: raise Exception("Virtual machine with JID %s is not managed by Archipel" % jid) vm = self.virtualmachines[uuid] vm.terminate(clean_files=False) self.log.info("Unregistering the VM from hypervisor's database.") self.database.execute("delete from virtualmachines where jid=?", (jid.getStripped(),)) self.database.commit() del self.virtualmachines[uuid] self.log.info("Starting the vm removing procedure.") vm.inband_unregistration() self.log.info("unmanage virtual machine with UUID: %s" % uuid) self.push_change("hypervisor", "unmanage") self.update_presence() except Exception as ex: reply = build_error_iq(self, ex, iq, ARCHIPEL_ERROR_CODE_HYPERVISOR_UNMANAGE) return reply
def iq_register(self, iq): """ register to a new VMCast @type iq: xmpp.Protocol.Iq @param iq: the sender request IQ @rtype: xmpp.Protocol.Iq @return: a ready-to-send IQ containing the results """ reply = iq.buildReply("result") url = iq.getTag("query").getTag("archipel").getAttr("url") try: if not url or url == "": raise Exception("IncorrectStanza", "Stanza must have url: %s" % str(iq)) try: f = urllib.urlopen(url) except: raise Exception("The given url doesn't exist. Can't register") try: self.getFeed(f.read()) except: raise Exception("The given url doesn't contains a valid VMCast feed. Can't register") self.cursor.execute("INSERT INTO vmcastsources (url) VALUES ('%s')" % url) self.database_connection.commit() self.parseRSS() self.entity.push_change("vmcasting", "register") self.entity.shout("vmcast", "I'm now registred to vmcast %s as asked by %s" % (url, iq.getFrom())) except Exception as ex: reply = build_error_iq(self, ex, iq, ARCHIPEL_ERROR_CODE_VMCASTS_REGISTER) return reply
def iq_users_list(self, iq): """ List all registered 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") server = self.entity.jid.getDomain() answer = self.xmlrpc_server.registered_users({"host": server}) nodes = [] users = answer["users"] for user in users: entity_type = "human" try: answer = self.xmlrpc_server.get_vcard({"host": server, "user": user["username"], "name" : "ROLE"}) if answer["content"] in ("hypervisor", "virtualmachine"): entity_type = answer["content"] except: pass nodes.append(xmpp.Node("user", attrs={"jid": "%s@%s" % (user["username"], server), "type": entity_type})) self.entity.push_change("xmppserver:users", "listfetched", content_node=xmpp.Node("users", payload=nodes)) except Exception as ex: reply = build_error_iq(self, ex, iq, ARCHIPEL_ERROR_CODE_XMPPSERVER_USERS_LIST) return reply
def iq_download(self, iq): """ start a download of appliance according to its uuid @type iq: xmpp.Protocol.Iq @param iq: the sender request IQ @rtype: xmpp.Protocol.Iq @return: a ready-to-send IQ containing the results """ reply = iq.buildReply("result") dl_uuid = iq.getTag("query").getTag("archipel").getAttr("uuid") try: self.cursor.execute("UPDATE vmcastappliances SET status=%d WHERE uuid='%s'" % (ARCHIPEL_APPLIANCES_INSTALLING, dl_uuid)) self.cursor.execute("SELECT * FROM vmcastappliances WHERE uuid='%s'" % dl_uuid) self.database_connection.commit() self.old_entity_status = self.entity.xmppstatus self.entity.push_change("vmcasting", "download_start") for values in self.cursor: name, description, url, uuid, status, source, path = values downloader = TNApplianceDownloader(url, self.repository_path, uuid, name, self.entity.log, self.on_download_complete) self.download_queue[uuid] = downloader downloader.daemon = True downloader.start() self.entity.change_status("Downloading appliance...") except Exception as ex: reply = build_error_iq(self, ex, iq, ARCHIPEL_ERROR_CODE_VMCASTS_DOWNLOADAPPLIANCE) return reply
def iq_get(self, iq): """ Get the virtual hard drives of the virtual machine. @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: disks = os.listdir(self.entity.folder) nodes = [] for disk in disks: if self._is_file_a_drive(os.path.join(self.entity.folder, disk)): diskPath = os.path.join(self.entity.folder, disk) diskSize = os.path.getsize(diskPath) diskInfo = subprocess.Popen([self.qemu_img_bin, "info", diskPath], stdout=subprocess.PIPE).communicate()[0].split("\n") currentAttributes = { "name": os.path.basename(os.path.splitext(disk)[0]), "path": diskPath, "format": diskInfo[1].split(": ")[1], "virtualSize": diskInfo[2].split(" ")[3].replace("(", ""), "diskSize": diskSize } if len(diskInfo) == 7: currentAttributes["backingFile"] = os.path.basename(diskInfo[5].split()[2]) node = xmpp.Node(tag="disk", attrs=currentAttributes) nodes.append(node) reply = iq.buildReply("result") reply.setQueryPayload(nodes) self.entity.log.info("Info about disks sent.") except Exception as ex: reply = build_error_iq(self, ex, iq, ARCHIPEL_ERROR_CODE_DRIVES_GET) return reply
def iq_get(self, iq): """ Get the virtual hard drives of the virtual machine. @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: disks = os.listdir(self.entity.folder) nodes = [] for disk in disks: if self._is_file_a_drive(os.path.join(self.entity.folder, disk)): diskPath = os.path.join(self.entity.folder, disk) diskSize = os.path.getsize(diskPath) diskInfo = subprocess.Popen([self.qemu_img_bin, "info", diskPath], stdout=subprocess.PIPE).communicate()[0].split("\n") currentAttributes = { "name": os.path.basename(os.path.splitext(disk)[0]), "path": diskPath, "format": diskInfo[1].split(": ")[1], "virtualSize": diskInfo[2].split(" ")[3].replace("(", ""), "diskSize": diskSize } backing_file = filter(lambda x: x.startswith("backing file"), diskInfo) if backing_file: currentAttributes["backingFile"] = backing_file[0].split()[2] node = xmpp.Node(tag="disk", attrs=currentAttributes) nodes.append(node) reply = iq.buildReply("result") reply.setQueryPayload(nodes) self.entity.log.info("Info about disks sent.") except Exception as ex: reply = build_error_iq(self, ex, iq, ARCHIPEL_ERROR_CODE_DRIVES_GET) return reply
def process_iq(self, conn, iq): """ Process incoming IQ of type ARCHIPEL_NS_HYPERVISOR_VMCASTING. It understands IQ of type: - get - attach - detach - package @type conn: xmpp.Dispatcher @param conn: ths instance of the current connection that send the stanza @type iq: xmpp.Protocol.Iq @param iq: the received IQ """ reply = None action = self.entity.check_acp(conn, iq) self.entity.check_perm(conn, iq, action, -1, prefix="appliance_") if self.entity.is_migrating and (not action in ("get")): reply = build_error_iq( self, "Virtual machine is migrating. Can't perform any snapshoting operation.", iq, ARCHIPEL_ERROR_CODE_VM_MIGRATING) elif action == "get": reply = self.iq_get(iq) elif action == "attach": reply = self.iq_attach(iq) elif action == "detach": reply = self.iq_detach(iq) elif action == "package": reply = self.iq_package(iq) if reply: conn.send(reply) raise xmpp.protocol.NodeProcessed
def process_iq(self, conn, iq): """ Invoked when new ARCHIPEL_NS_VM_DISK IQ is received. it understands IQ of type: - create - delete - get - getiso - convert - rename @type conn: xmpp.Dispatcher @param conn: ths instance of the current connection that send the message @type iq: xmpp.Protocol.Iq @param iq: the received IQ """ reply = None action = self.entity.check_acp(conn, iq) self.entity.check_perm(conn, iq, action, -1, prefix="drives_") if self.entity.is_migrating and (not action in ("get", "getiso")): reply = build_error_iq(self, "virtual machine is migrating. Can't perform any drives operation", iq, ARCHIPEL_ERROR_CODE_VM_MIGRATING) elif action == "create": reply = self.iq_create(iq) elif action == "delete": reply = self.iq_delete(iq) elif action == "get": reply = self.iq_get(iq) elif action == "getiso": reply = self.iq_getiso(iq) elif action == "convert": reply = self.iq_convert(iq) elif action == "rename": reply = self.iq_rename(iq) if reply: conn.send(reply) raise xmpp.protocol.NodeProcessed
def iq_setgolden(self, iq): """ Set a qow2 image as golden image @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: query_node = iq.getTag("query") disk_path = query_node.getTag("archipel").getAttr("path") golden_name = query_node.getTag("archipel").getAttr("name").replace(" ", "_").replace("/", "_").replace("..", "_") if not (self._is_file_a_qcow(disk_path) or self._is_file_a_qcow2(disk_path)): raise Exception("Invalid format", "You can only use qcow/qcow2 as format for golden image") if not os.path.exists(disk_path): raise Exception("File not found", "Cannot find %s" % disk_path) if os.path.exists(os.path.join(self.golden_drives_dir, golden_name)): raise Exception("Golden image already exist", "Golden image %s already exist" % golden_name) shutil.move(disk_path, os.path.join(self.golden_drives_dir, golden_name)) reply = iq.buildReply("result") self.entity.log.info("Created golden image %s" % (golden_name)) self.entity.shout("disk", "I've just created a new golden image %s." % (golden_name)) self.entity.push_change("disk", "goldened") except Exception as ex: reply = build_error_iq(self, ex, iq, ARCHIPEL_ERROR_CODE_DRIVES_SETGOLDEN) return reply
def iq_park(self, iq): """ Park virtual machine @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: items = iq.getTag("query").getTag("archipel").getTags("item") for item in items: vm_uuid = item.getAttr("uuid") if not vm_uuid: self.entity.log.error( "VMPARKING: Unable to park vm: missing 'uuid' element." ) raise Exception( "You must must set the UUID of the vms you want to park" ) force_destroy = False if item.getAttr("force") and item.getAttr("force").lower() in ( "yes", "y", "true", "1"): force_destroy = True self.park(vm_uuid, iq.getFrom(), force=force_destroy, push=False) self.entity.push_change("vmparking", "parked") reply = iq.buildReply("result") except Exception as ex: reply = build_error_iq(self, ex, iq, ARCHIPEL_ERROR_CODE_VMPARK_PARK) return reply
def iq_download(self, iq): """ Start a download of appliance according to its uuid. @type iq: xmpp.Protocol.Iq @param iq: the sender request IQ @rtype: xmpp.Protocol.Iq @return: a ready-to-send IQ containing the results """ reply = iq.buildReply("result") dl_uuid = iq.getTag("query").getTag("archipel").getAttr("uuid") try: self.cursor.execute("UPDATE vmcastappliances SET status=%d WHERE uuid='%s'" % (ARCHIPEL_APPLIANCES_INSTALLING, dl_uuid)) self.database_connection.commit() self.cursor.execute("SELECT * FROM vmcastappliances WHERE uuid='%s'" % dl_uuid) self.old_entity_status = self.entity.xmppstatus self.entity.push_change("vmcasting", "download_start") name, description, url, uuid, status, source, path = self.cursor.fetchone() downloader = TNApplianceDownloader(url, self.repository_path, uuid, name, self.entity.log, self.on_download_complete) self.download_queue[uuid] = downloader downloader.daemon = True downloader.start() self.entity.change_status("Downloading appliance...") except Exception as ex: reply = build_error_iq(self, ex, iq, ARCHIPEL_ERROR_CODE_VMCASTS_DOWNLOADAPPLIANCE) return reply
def _on_centralagent_reply(vms): try: self.entity.log.debug("VMPARKING: here is the raw list result %s" % vms) reply = iq.buildReply("result") parked_vms = [] for vm in vms: try: parked_vms.append({"info": {"uuid": vm["uuid"], "parker": vm["parker"], "date": vm["creation_date"]}, "domain": xmpp.simplexml.NodeBuilder(vm["domain"]).getDom()}) except: self.entity.log.warning("VMPARKING: Error parsing entry %s" % vm) def sorting(a, b): a_name="" b_name="" if a["domain"]: a_name=a["domain"].getTag("name").getData() if b["domain"]: b_name=b["domain"].getTag("name").getData() return cmp(a_name, b_name) parked_vms.sort(sorting) nodes = [] for parked_vm in parked_vms: vm_node = xmpp.Node("virtualmachine", attrs=parked_vm["info"]) if parked_vm["domain"] and parked_vm["domain"].getTag('description'): parked_vm["domain"].delChild("description") vm_node.addChild(node=parked_vm["domain"]) nodes.append(vm_node) reply.setQueryPayload(nodes) except Exception as ex: reply = build_error_iq(self, ex, iq, ARCHIPEL_ERROR_CODE_VMPARK_LIST) self.entity.xmppclient.send(reply) raise xmpp.protocol.NodeProcessed
def process_iq(self, conn, iq): """ this method is invoked when a ARCHIPEL_NS_SNAPSHOTING IQ is received. it understands IQ of type: - take - delete - get - current - revert @type conn: xmpp.Dispatcher @param conn: ths instance of the current connection that send the stanza @type iq: xmpp.Protocol.Iq @param iq: the received IQ """ reply = None action = self.entity.check_acp(conn, iq) self.entity.check_perm(conn, iq, action, -1, prefix="snapshot_") if not self.entity.domain: raise xmpp.protocol.NodeProcessed if self.entity.is_migrating and (not action in ("current", "get")): reply = build_error_iq(self, "virtual machine is migrating. Can't perform any snapshoting operation", iq, ARCHIPEL_ERROR_CODE_VM_MIGRATING) elif action == "take": reply = self.iq_take(iq) elif action == "delete": reply = self.iq_delete(iq) elif action == "get": reply = self.iq_get(iq) elif action == "current": reply = self.iq_getcurrent(iq) elif action == "revert": reply = self.iq_revert(iq) if reply: conn.send(reply) raise xmpp.protocol.NodeProcessed
def iq_unpark(self, iq): """ Unpark virtual machine @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") items = iq.getTag("query").getTag("archipel").getTags("item") vms_info = [] for item in items: identifier = item.getAttr("identifier") autostart = False if item.getAttr("start") and item.getAttr("start").lower() in ("yes", "y", "true", "1"): autostart = True vms_info.append({"uuid": identifier, "start": autostart, "parker": str(iq.getFrom())}) self.unpark(vms_info) except Exception as ex: reply = build_error_iq(self, ex, iq, ARCHIPEL_ERROR_CODE_VMPARK_UNPARK) return reply
def iq_delete_appliance(self, iq): """ Delete an appliance according to its uuid. @type iq: xmpp.Protocol.Iq @param iq: the sender request IQ @rtype: xmpp.Protocol.Iq @return: a ready-to-send IQ containing the results """ try: reply = iq.buildReply("result") uuid = iq.getTag("query").getTag("archipel").getAttr("uuid") self.cursor.execute( "SELECT save_path FROM vmcastappliances WHERE uuid='%s'" % uuid) for values in self.cursor: path = values[0] os.remove(path) self.cursor.execute( "UPDATE vmcastappliances SET status=%d WHERE uuid='%s'" % (ARCHIPEL_APPLIANCES_NOT_INSTALLED, uuid)) self.database_connection.commit() self.entity.push_change("vmcasting", "appliancedeleted") self.entity.shout( "vmcast", "I've just delete appliance %s as asked by %s" % (uuid, iq.getFrom())) except Exception as ex: reply = build_error_iq( self, ex, iq, ARCHIPEL_ERROR_CODE_VMCASTS_DELETEAPPLIANCE) return reply
def process_iq(self, conn, iq): """ Process incoming IQ of type ARCHIPEL_NS_HYPERVISOR_VMCASTING. It understands IQ of type: - get - attach - detach - package @type conn: xmpp.Dispatcher @param conn: ths instance of the current connection that send the stanza @type iq: xmpp.Protocol.Iq @param iq: the received IQ """ reply = None action = self.entity.check_acp(conn, iq) self.entity.check_perm(conn, iq, action, -1, prefix="appliance_") if self.entity.is_migrating and (not action in ("get")): reply = build_error_iq(self, "Virtual machine is migrating. Can't perform any snapshoting operation.", iq, ARCHIPEL_ERROR_CODE_VM_MIGRATING) elif action == "get": reply = self.iq_get(iq) elif action == "attach": reply = self.iq_attach(iq) elif action == "detach": reply = self.iq_detach(iq) elif action == "package": reply = self.iq_package(iq) if reply: conn.send(reply) raise xmpp.protocol.NodeProcessed
def iq_group_list(self, iq): """ List shared groups. @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") server = self.entity.jid.getDomain() answer = self.xmlrpc_server.srg_list({"host": server}) groups = answer["groups"] groupsNode = [] for group in groups: answer = self.xmlrpc_server.srg_get_info({"host": server, "group": group["id"]}) informations = answer["informations"] for info in informations: if info['information'][0]["key"] == "name": displayed_name = info['information'][1]["value"] if info['information'][0]["key"] == "description": description = info['information'][1]["value"] info = {"id": group["id"], "displayed_name": displayed_name.replace("\"", ""), "description": description.replace("\"", "")} newNode = xmpp.Node("group", attrs=info) answer = self.xmlrpc_server.srg_get_members({"host": server, "group": group["id"]}) members = answer["members"] for member in members: newNode.addChild("user", attrs={"jid": member["member"]}) groupsNode.append(newNode) reply.setQueryPayload(groupsNode) except Exception as ex: reply = build_error_iq(self, ex, iq, ARCHIPEL_ERROR_CODE_XMPPSERVER_GROUP_LIST) return reply
def iq_get_installed_appliances(self, iq): """ Get all installed appliances. @type iq: xmpp.Protocol.Iq @param iq: the sender request IQ @rtype: xmpp.Protocol.Iq @return: a ready-to-send IQ containing the results """ reply = iq.buildReply("result") nodes = [] try: self.cursor.execute( "SELECT save_path, name, description FROM vmcastappliances WHERE status=%d" % (ARCHIPEL_APPLIANCES_INSTALLED)) for values in self.cursor: path, name, description = values node = xmpp.Node(tag="appliance", attrs={ "path": path, "name": name, "description": description }) nodes.append(node) reply.setQueryPayload(nodes) except Exception as ex: reply = build_error_iq(self, ex, iq, ARCHIPEL_ERROR_CODE_VMCASTS_GETINSTALLED) return reply
def iq_park(self, iq): """ Park virtual machine @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: items = iq.getTag("query").getTag("archipel").getTags("item") vms_info = [] for item in items: vm_uuid = item.getAttr("uuid") if not vm_uuid: self.entity.log.error("VMPARKING: Unable to park vm: missing 'uuid' element.") raise Exception("You must must set the UUID of the vms you want to park") vms_info.append({"uuid": vm_uuid, "status": ARCHIPEL_PARKING_STATUS_PARKED, "parker": str(iq.getFrom())}) self.park(vms_info) reply = iq.buildReply("result") except Exception as ex: reply = build_error_iq(self, ex, iq, ARCHIPEL_ERROR_CODE_VMPARK_PARK) return reply
def iq_get_logs(self, iq): """ Read the hypervisor's log file. @type iq: xmpp.Protocol.Iq @param iq: the sender request IQ @rtype: xmpp.Protocol.Iq @return: a ready-to-send IQ containing the results """ try: reply = iq.buildReply("result") limit = int(iq.getTag("query").getTag("archipel").getAttr("limit")) output = commands.getoutput("tail -n %d %s" % (limit, self.logfile)) nodes = [] for line in output.split("\n"): try: infos = line.split("::") log_node = xmpp.Node("log", attrs={"level": infos[0], "date": infos[1], "file": "", "method": ""}) log_node.setData(line) nodes.append(log_node) except Exception as ex: pass reply.setQueryPayload(nodes) except Exception as ex: print str(ex) reply = build_error_iq(self, ex, iq, ARCHIPEL_ERROR_CODE_HEALTH_LOG) return reply
def iq_users_list(self, iq): """ List all registered 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") def on_receive_users(conn, iq): if not iq.getType() == "result": return try: items = iq.getTag("query").getTags("item") users = map(lambda x: x.getAttr("jid"), items) nodes = [] number_of_users = len(users) number_of_vcards = 0 def on_receive_vcard(conn, iq): try: if not iq.getType() == "result": return entity_type = "human" if iq.getTag("vCard") and iq.getTag("vCard").getTag("ROLE"): vcard_role = iq.getTag("vCard").getTag("ROLE").getData() if vcard_role in ("hypervisor", "virtualmachine"): entity_type = vcard_role self.entities_types_cache[iq.getFrom().getStripped()] = entity_type nodes.append(xmpp.Node("user", attrs={"jid": iq.getFrom().getStripped(), "type": entity_type})) if len(nodes) >= number_of_users: self.entity.push_change("xmppserver:users", "listfetched", content_node=xmpp.Node("users", payload=nodes)) except Exception as ex: self.entity.log.error("XMPPSERVER: Error while fetching contact vCard: %s" % str(ex)) self.entity.push_change("xmppserver:users", "listfetcherror", content_node=iq) for user in users: iq_vcard = xmpp.Iq(typ="get", to=user) iq_vcard.addChild("vCard", namespace="vcard-temp") if not user in self.entities_types_cache: self.entity.log.debug("XMPPSERVER: Entity type of %s is not cached. fetching..." % user) self.entity.xmppclient.SendAndCallForResponse(iq_vcard, on_receive_vcard) else: self.entity.log.debug("XMPPSERVER: Entity type of %s is already cached (%s)" % (user, self.entities_types_cache[user])) nodes.append(xmpp.Node("user", attrs={"jid": user, "type": self.entities_types_cache[user]})) if len(nodes) >= number_of_users: self.entity.push_change("xmppserver:users", "listfetched", content_node=xmpp.Node("users", payload=nodes)) except Exception as ex: self.entity.log.error("XMPPSERVER: Unable to manage to get users or their vcards. error is %s" % str(ex)) user_iq = xmpp.Iq(typ="get", to=self.entity.jid.getDomain()) user_iq.addChild("query", attrs={"node": "all users"}, namespace="http://jabber.org/protocol/disco#items") self.entity.xmppclient.SendAndCallForResponse(user_iq, on_receive_users) except Exception as ex: reply = build_error_iq(self, ex, iq, ARCHIPEL_ERROR_CODE_XMPPSERVER_USERS_LIST) return reply
def iq_create_parked(self, iq): """ Create a VM in directly into the parking @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: items = iq.getTag("query").getTag("archipel").getTags("item") for item in items: vm_uuid = item.getAttr("uuid") if not vm_uuid: self.entity.log.error( "VMPARKING: Unable to park vm: missing 'uuid' element." ) raise Exception( "You must must set the UUID of the vms you want to park" ) vm_domain = item.getTag("domain") self.create_parked(vm_uuid, vm_domain, iq.getFrom(), push=False) self.entity.push_change("vmparking", "create_parked") reply = iq.buildReply("result") except Exception as ex: reply = build_error_iq(self, ex, iq, ARCHIPEL_ERROR_CODE_VMPARK_CREATE_PARKED) return reply
def iq_bridges(self, iq): """ List all bridge names. @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") bridges = [] for std_bridge in commands.getoutput("brctl show 2>/dev/null | grep -v -E '^[[:space:]]|bridge name' | cut -f 1").split("\n"): if std_bridge: bridges.append({"name": std_bridge, "type": "linux-bridge"}) for ovs_bridge in commands.getoutput("ovs-vsctl list-br 2>/dev/null").split("\n"): if ovs_bridge: bridges.append({"name": ovs_bridge, "type": "openvswitch"}) bridges = sorted(bridges, key=lambda k: k["name"]) bridges_list = [] for bridge in bridges: if bridge.get("name", None) and bridge.get("type", None): bridge_node = xmpp.Node(tag="bridge", attrs={"name": bridge["name"], "type": bridge["type"]}) bridges_list.append(bridge_node) reply.setQueryPayload(bridges_list) except Exception as ex: reply = build_error_iq(self, ex, iq, ARCHIPEL_ERROR_CODE_NETWORKS_BRIDGES) return reply