<commit_before># 
# archipelVirtualMachine.py
# 
# Copyright (C) 2010 <NAME> <<EMAIL>>
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
# 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
# 
# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.



"""
Contains ArchipelVirtualMachine, the XMPP capable controller

This module contain the class ArchipelVirtualMachine that represents a virtual machine
linked to a libvirt domain and allowing other XMPP entities to control it using IQ.

The ArchipelVirtualMachine is able to register to any kind of XMPP compliant Server. These 
Server MUST allow in-band registration, or you have to manually register VM before 
launching them.

Also the JID of the virtual machine MUST be the UUID use in the libvirt domain, or it will
fail.
"""
import xmpp
import sys
import socket
import os
import commands
from threading import Timer, Thread
import libvirt
import sqlite3
import thread

from archipel.utils import *
from archipel.core.archipelWebSocket import *
from archipel.core.libvirtEventLoop import *
from archipel.core.archipelEntity import *
from archipel.core.archipelTriggers import *

ARCHIPEL_ERROR_CODE_VM_CREATE                   = -1001
ARCHIPEL_ERROR_CODE_VM_SUSPEND                  = -1002
ARCHIPEL_ERROR_CODE_VM_RESUME                   = -1003
ARCHIPEL_ERROR_CODE_VM_DESTROY                  = -1004
ARCHIPEL_ERROR_CODE_VM_SHUTDOWN                 = -1005
ARCHIPEL_ERROR_CODE_VM_REBOOT                   = -1006
ARCHIPEL_ERROR_CODE_VM_DEFINE                   = -1007
ARCHIPEL_ERROR_CODE_VM_UNDEFINE                 = -1008
ARCHIPEL_ERROR_CODE_VM_INFO                     = -1009
ARCHIPEL_ERROR_CODE_VM_VNC                      = -1010
ARCHIPEL_ERROR_CODE_VM_XMLDESC                  = -1011
ARCHIPEL_ERROR_CODE_VM_LOCKED                   = -1012
ARCHIPEL_ERROR_CODE_VM_MIGRATE                  = -1013
ARCHIPEL_ERROR_CODE_VM_IS_MIGRATING             = -1014
ARCHIPEL_ERROR_CODE_VM_AUTOSTART                = -1015
ARCHIPEL_ERROR_CODE_VM_MEMORY                   = -1016
ARCHIPEL_ERROR_CODE_VM_NETWORKINFO              = -1017
ARCHIPEL_ERROR_CODE_VM_HYPERVISOR_CAPABILITIES  = -1019


class TNArchipelVirtualMachine(TNArchipelEntity):
    """
    this class represent an Virtual Machine, XMPP Capable.
    this class need to already have 
    """
    
    def __init__(self, jid, password, hypervisor, configuration, name):
        """
        contructor of the class
        """
        TNArchipelEntity.__init__(self, jid, password, configuration, name)
        
        self.hypervisor                 = hypervisor
        self.libvirt_connection         = libvirt.open(self.configuration.get("GLOBAL", "libvirt_uri"))
        self.libvirt_status             = libvirt.VIR_DOMAIN_SHUTDOWN
        self.domain                     = None
        self.definition                 = None
        self.uuid                       = self.jid.getNode()
        self.vm_disk_base_path          = self.configuration.get("VIRTUALMACHINE", "vm_base_path") + "/"
        self.folder                     = self.vm_disk_base_path + self.uuid
        self.locked                     = False
        self.lock_timer                 = None
        self.maximum_lock_time          = self.configuration.getint("VIRTUALMACHINE", "maximum_lock_time")
        self.is_migrating               = False
        self.libvirt_event_callback_id  = None
        self.triggers                   = {}
        self.watchers                   = {}
        self.entity_type                = "virtualmachine"
        self.default_avatar             = self.configuration.get("VIRTUALMACHINE", "vm_default_avatar")
        
        # create VM folders if not exists
        if not os.path.isdir(self.folder): os.makedirs(self.folder)
        
        # triggers
        self.log.info("creating/opening the trigger database file %s/triggers.sqlite3" % self.folder)
        self.trigger_database = sqlite3.connect(self.folder + "/triggers.sqlite3", check_same_thread=False)
        
        # permissions
        permission_db_file              = self.folder + "/" + self.configuration.get("VIRTUALMACHINE", "vm_permissions_database_path")
        permission_admin_name           = self.configuration.get("GLOBAL", "archipel_root_admin")
        self.permission_center          = archipel.core.archipelPermissionCenter.TNArchipelPermissionCenter(permission_db_file, permission_admin_name)
        self.init_permissions()
        
        # hooks
        self.create_hook("HOOK_VM_CREATE")
        self.create_hook("HOOK_VM_SHUTOFF")
        self.create_hook("HOOK_VM_STOP")
        self.create_hook("HOOK_VM_DESTROY")
        self.create_hook("HOOK_VM_SUSPEND")
        self.create_hook("HOOK_VM_RESUME")
        self.create_hook("HOOK_VM_UNDEFINE")
        self.create_hook("HOOK_VM_DEFINE")
        self.create_hook("HOOK_VM_INITIALIZE")
        self.create_hook("HOOK_VM_TERMINATE")
        
        # actions on auth
        self.register_actions_to_perform_on_auth("manage_trigger_persistance", None)
        self.register_actions_to_perform_on_auth("connect_domain", None)
        self.register_actions_to_perform_on_auth("manage_vcard")
        
        # vocabulary
        self.init_vocabulary()
        
        # modules
        self.initialize_modules()
    
    
    ### Utilities
    
    def lock(self):
        self.log.info("acquiring lock")
        self.locked = True
        self.lock_timer = Timer(self.maximum_lock_time, self.unlock)
        self.lock_timer.start()
    
    
    def unlock(self):
        self.log.info("releasing lock")
        self.locked = False
        if self.lock_timer:
            self.lock_timer.cancel()
    
    
    def init_vocabulary(self):
        """"
        this method register for user messages
        """
        registrar_items = [
                            {  "commands" : ["start", "create", "boot", "play", "run"], 
                                "parameters": [],
                                "method": self.message_create,
                                "permissions": ["create"],
                                "description": "I'll start" },
                            
                            {  "commands" : ["shutdown", "stop"], 
                                "parameters": [],
                                "method": self.message_shutdown,
                                "permissions": ["shutdown"],
                                "description": "I'll shutdown" },
                                
                            {  "commands" : ["destroy"], 
                                "parameters": [],
                                "method": self.message_destroy,
                                "permissions": ["destroy"],
                                "description": "I'll destroy myself" },
                                
                            {  "commands" : ["pause", "suspend"], 
                                "parameters": [],
                                "method": self.message_suspend,
                                "permissions": ["suspend"],
                                "description": "I'll suspend" },
                            
                            {  "commands" : ["resume", "unpause"], 
                                "parameters": [],
                                "method": self.message_resume,
                                "permissions": ["resume"],
                                "description": "I'll resume" },
                            
                            {  "commands" : ["info", "how are you", "and you"], 
                                "parameters": [],
                                "method": self.message_info,
                                "permissions": ["info"],
                                "description": "I'll give info about me" },
                            
                            {  "commands" : ["vnc", "screen"], 
                                "parameters": [],
                                "method": self.message_vncdisplay,
                                "permissions": ["vncdisplay"],
                                "description": "I'll show my VNC port" },
                                
                            {  "commands" : ["desc", "xml"], 
                                "parameters": [],
                                "method": self.message_xmldesc,
                                "description": "I'll show my description" },
                            
                            {  "commands" : ["net", "stat"], 
                                "parameters": [],
                                "method": self.message_networkinfo,
                                "permissions": ["networkinfo"],
                                "description": "I'll show my network stats" },
                            
                            {  "commands" : ["fuck", "asshole", "jerk", "stupid", "suck"],
                                "ignore": True,
                                "parameters": [],
                                "method": self.message_insult,
                                "description": "" },
                            
                            {  "commands" : ["hello", "hey", "hi", "good morning", "yo"], 
                                "ignore": True,
                                "parameters": [],
                                "method": self.message_hello,
                                "description": "" },
                        ]
        
        self.add_message_registrar_items(registrar_items)
    
    
    def init_permissions(self):
        """initialize the permssions"""
        TNArchipelEntity.init_permissions(self)
        self.permission_center.create_permission("info", "Authorizes users to access virtual machine information", False)
        self.permission_center.create_permission("create", "Authorizes users to create (start) virtual machine", False)
        self.permission_center.create_permission("shutdown", "Authorizes users to shutdown virtual machine", False)
        self.permission_center.create_permission("destroy", "Authorizes users to destroy virtual machine", False)
        self.permission_center.create_permission("reboot", "Authorizes users to reboot virtual machine", False)
        self.permission_center.create_permission("suspend", "Authorizes users to suspend virtual machine ", False)
        self.permission_center.create_permission("resume", "Authorizes users to resume virtual machine", False)
        self.permission_center.create_permission("vncdisplay", "Authorizes users to access the vnc display port", False)
        self.permission_center.create_permission("xmldesc", "Authorizes users to access the XML description of the virtual machine", False)
        self.permission_center.create_permission("migrate", "Authorizes users to perform live migration", False)
        self.permission_center.create_permission("autostart", "Authorizes users to set the virtual machine autostart", False)
        self.permission_center.create_permission("memory", "Authorizes users to change memory in live", False)
        self.permission_center.create_permission("setvcpus", "Authorizes users to set the number of virtual CPU in live", False)
        self.permission_center.create_permission("networkinfo", "Authorizes users to access virtual machine's network informations", False)
        self.permission_center.create_permission("define", "Authorizes users to define virtual machine", False)
        self.permission_center.create_permission("undefine", "Authorizes users to undefine virtual machine", False)
        self.permission_center.create_permission("capabilities", "Authorizes users to access virtual machine's hypervisor capabilities", False)
    
    
    def register_handler(self):
        """
        this method registers the events handlers.
        it is invoked by super class __xmpp_connect() method
        """
        self.xmppclient.RegisterHandler('iq', self.__process_iq_archipel_control, ns=ARCHIPEL_NS_VM_CONTROL)
        self.xmppclient.RegisterHandler('iq', self.__process_iq_archipel_definition, ns=ARCHIPEL_NS_VM_DEFINITION)
        
        TNArchipelEntity.register_handler(self)
    
    
    def remove_folder(self):
        """
        remove the folder of the virtual with all its contents
        """
        os.system("rm -rf " + self.folder)
    
    
    def set_automatic_libvirt_description(self, xmldesc):
        """
        set the XML description's description of the VM
        """
        if not xmldesc.getTag('description'): 
            xmldesc.addChild(name='description')
        else:
            xmldesc.delChild("description")
            xmldesc.addChild(name='description')
        
        xmldesc.getTag('description').setData("%s::::%s" % (self.jid.getStripped(), self.password))
        
        if not xmldesc.getTag('name'): xmldesc.addChild(name='name')
        xmldesc.getTag('name').setData(self.name)
        
        ret = str(xmldesc).replace('xmlns="http://www.gajim.org/xmlns/undeclared" ', '')
        self.log.debug("generated XML desc is : %s" % ret)
        return ret
    
    
    def set_presence_according_to_libvirt_info(self):
        try:
            self.push_change("virtualmachine:definition", "defined", excludedgroups=['vitualmachines'])
            
            currentXMLDesc = xmpp.simplexml.NodeBuilder(data=self.domain.XMLDesc(0)).getDom()
            self.libvirt_connection.defineXML(self.set_automatic_libvirt_description(currentXMLDesc))
            
            dominfo = self.domain.info()
            self.libvirt_status = dominfo[0]
            self.log.info("virtual machine state is %d" %  dominfo[0])
            if dominfo[0] == libvirt.VIR_DOMAIN_RUNNING or dominfo[0] == libvirt.VIR_DOMAIN_BLOCKED:
                self.change_presence("", ARCHIPEL_XMPP_SHOW_RUNNING)
                self.create_novnc_proxy()
                self.triggers["libvirt_run"].set_state(ARCHIPEL_TRIGGER_STATE_ON)
            elif dominfo[0] == libvirt.VIR_DOMAIN_PAUSED:
                self.change_presence("away", ARCHIPEL_XMPP_SHOW_PAUSED)
                self.triggers["libvirt_run"].set_state(ARCHIPEL_TRIGGER_STATE_OFF)
            elif dominfo[0] == libvirt.VIR_DOMAIN_SHUTOFF:
                self.change_presence("xa", ARCHIPEL_XMPP_SHOW_SHUTDOWNED)
            elif dominfo[0] == libvirt.VIR_DOMAIN_SHUTDOWN:
                self.change_presence("", ARCHIPEL_XMPP_SHOW_SHUTDOWNING)
            self.perform_hooks("HOOK_VM_INITIALIZE")<commit_msg>fix a bug that can cause race condition when recovering XMPP status according to libvirt<commit_after># 
# archipelVirtualMachine.py
# 
# Copyright (C) 2010 <NAME> <<EMAIL>>
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
# 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
# 
# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.



"""
Contains ArchipelVirtualMachine, the XMPP capable controller

This module contain the class ArchipelVirtualMachine that represents a virtual machine
linked to a libvirt domain and allowing other XMPP entities to control it using IQ.

The ArchipelVirtualMachine is able to register to any kind of XMPP compliant Server. These 
Server MUST allow in-band registration, or you have to manually register VM before 
launching them.

Also the JID of the virtual machine MUST be the UUID use in the libvirt domain, or it will
fail.
"""
import xmpp
import sys
import socket
import os
import commands
from threading import Timer, Thread
import libvirt
import sqlite3
import thread

from archipel.utils import *
from archipel.core.archipelWebSocket import *
from archipel.core.libvirtEventLoop import *
from archipel.core.archipelEntity import *
from archipel.core.archipelTriggers import *

ARCHIPEL_ERROR_CODE_VM_CREATE                   = -1001
ARCHIPEL_ERROR_CODE_VM_SUSPEND                  = -1002
ARCHIPEL_ERROR_CODE_VM_RESUME                   = -1003
ARCHIPEL_ERROR_CODE_VM_DESTROY                  = -1004
ARCHIPEL_ERROR_CODE_VM_SHUTDOWN                 = -1005
ARCHIPEL_ERROR_CODE_VM_REBOOT                   = -1006
ARCHIPEL_ERROR_CODE_VM_DEFINE                   = -1007
ARCHIPEL_ERROR_CODE_VM_UNDEFINE                 = -1008
ARCHIPEL_ERROR_CODE_VM_INFO                     = -1009
ARCHIPEL_ERROR_CODE_VM_VNC                      = -1010
ARCHIPEL_ERROR_CODE_VM_XMLDESC                  = -1011
ARCHIPEL_ERROR_CODE_VM_LOCKED                   = -1012
ARCHIPEL_ERROR_CODE_VM_MIGRATE                  = -1013
ARCHIPEL_ERROR_CODE_VM_IS_MIGRATING             = -1014
ARCHIPEL_ERROR_CODE_VM_AUTOSTART                = -1015
ARCHIPEL_ERROR_CODE_VM_MEMORY                   = -1016
ARCHIPEL_ERROR_CODE_VM_NETWORKINFO              = -1017
ARCHIPEL_ERROR_CODE_VM_HYPERVISOR_CAPABILITIES  = -1019


class TNArchipelVirtualMachine(TNArchipelEntity):
    """
    this class represent an Virtual Machine, XMPP Capable.
    this class need to already have 
    """
    
    def __init__(self, jid, password, hypervisor, configuration, name):
        """
        contructor of the class
        """
        TNArchipelEntity.__init__(self, jid, password, configuration, name)
        
        self.hypervisor                 = hypervisor
        self.libvirt_connection         = libvirt.open(self.configuration.get("GLOBAL", "libvirt_uri"))
        self.libvirt_status             = libvirt.VIR_DOMAIN_SHUTDOWN
        self.domain                     = None
        self.definition                 = None
        self.uuid                       = self.jid.getNode()
        self.vm_disk_base_path          = self.configuration.get("VIRTUALMACHINE", "vm_base_path") + "/"
        self.folder                     = self.vm_disk_base_path + self.uuid
        self.locked                     = False
        self.lock_timer                 = None
        self.maximum_lock_time          = self.configuration.getint("VIRTUALMACHINE", "maximum_lock_time")
        self.is_migrating               = False
        self.libvirt_event_callback_id  = None
        self.triggers                   = {}
        self.watchers                   = {}
        self.entity_type                = "virtualmachine"
        self.default_avatar             = self.configuration.get("VIRTUALMACHINE", "vm_default_avatar")
        
        # create VM folders if not exists
        if not os.path.isdir(self.folder): os.makedirs(self.folder)
        
        # triggers
        self.log.info("creating/opening the trigger database file %s/triggers.sqlite3" % self.folder)
        self.trigger_database = sqlite3.connect(self.folder + "/triggers.sqlite3", check_same_thread=False)
        
        # permissions
        permission_db_file              = self.folder + "/" + self.configuration.get("VIRTUALMACHINE", "vm_permissions_database_path")
        permission_admin_name           = self.configuration.get("GLOBAL", "archipel_root_admin")
        self.permission_center          = archipel.core.archipelPermissionCenter.TNArchipelPermissionCenter(permission_db_file, permission_admin_name)
        self.init_permissions()
        
        # hooks
        self.create_hook("HOOK_VM_CREATE")
        self.create_hook("HOOK_VM_SHUTOFF")
        self.create_hook("HOOK_VM_STOP")
        self.create_hook("HOOK_VM_DESTROY")
        self.create_hook("HOOK_VM_SUSPEND")
        self.create_hook("HOOK_VM_RESUME")
        self.create_hook("HOOK_VM_UNDEFINE")
        self.create_hook("HOOK_VM_DEFINE")
        self.create_hook("HOOK_VM_INITIALIZE")
        self.create_hook("HOOK_VM_TERMINATE")
        
        # actions on auth
        self.register_actions_to_perform_on_auth("manage_trigger_persistance", None)
        self.register_actions_to_perform_on_auth("connect_domain", None)
        self.register_actions_to_perform_on_auth("manage_vcard")
        
        # vocabulary
        self.init_vocabulary()
        
        # modules
        self.initialize_modules()
    
    
    ### Utilities
    
    def lock(self):
        self.log.info("acquiring lock")
        self.locked = True
        self.lock_timer = Timer(self.maximum_lock_time, self.unlock)
        self.lock_timer.start()
    
    
    def unlock(self):
        self.log.info("releasing lock")
        self.locked = False
        if self.lock_timer:
            self.lock_timer.cancel()
    
    
    def init_vocabulary(self):
        """"
        this method register for user messages
        """
        registrar_items = [
                            {  "commands" : ["start", "create", "boot", "play", "run"], 
                                "parameters": [],
                                "method": self.message_create,
                                "permissions": ["create"],
                                "description": "I'll start" },
                            
                            {  "commands" : ["shutdown", "stop"], 
                                "parameters": [],
                                "method": self.message_shutdown,
                                "permissions": ["shutdown"],
                                "description": "I'll shutdown" },
                                
                            {  "commands" : ["destroy"], 
                                "parameters": [],
                                "method": self.message_destroy,
                                "permissions": ["destroy"],
                                "description": "I'll destroy myself" },
                                
                            {  "commands" : ["pause", "suspend"], 
                                "parameters": [],
                                "method": self.message_suspend,
                                "permissions": ["suspend"],
                                "description": "I'll suspend" },
                            
                            {  "commands" : ["resume", "unpause"], 
                                "parameters": [],
                                "method": self.message_resume,
                                "permissions": ["resume"],
                                "description": "I'll resume" },
                            
                            {  "commands" : ["info", "how are you", "and you"], 
                                "parameters": [],
                                "method": self.message_info,
                                "permissions": ["info"],
                                "description": "I'll give info about me" },
                            
                            {  "commands" : ["vnc", "screen"], 
                                "parameters": [],
                                "method": self.message_vncdisplay,
                                "permissions": ["vncdisplay"],
                                "description": "I'll show my VNC port" },
                                
                            {  "commands" : ["desc", "xml"], 
                                "parameters": [],
                                "method": self.message_xmldesc,
                                "description": "I'll show my description" },
                            
                            {  "commands" : ["net", "stat"], 
                                "parameters": [],
                                "method": self.message_networkinfo,
                                "permissions": ["networkinfo"],
                                "description": "I'll show my network stats" },
                            
                            {  "commands" : ["fuck", "asshole", "jerk", "stupid", "suck"],
                                "ignore": True,
                                "parameters": [],
                                "method": self.message_insult,
                                "description": "" },
                            
                            {  "commands" : ["hello", "hey", "hi", "good morning", "yo"], 
                                "ignore": True,
                                "parameters": [],
                                "method": self.message_hello,
                                "description": "" },
                        ]
        
        self.add_message_registrar_items(registrar_items)
    
    
    def init_permissions(self):
        """initialize the permssions"""
        TNArchipelEntity.init_permissions(self)
        self.permission_center.create_permission("info", "Authorizes users to access virtual machine information", False)
        self.permission_center.create_permission("create", "Authorizes users to create (start) virtual machine", False)
        self.permission_center.create_permission("shutdown", "Authorizes users to shutdown virtual machine", False)
        self.permission_center.create_permission("destroy", "Authorizes users to destroy virtual machine", False)
        self.permission_center.create_permission("reboot", "Authorizes users to reboot virtual machine", False)
        self.permission_center.create_permission("suspend", "Authorizes users to suspend virtual machine ", False)
        self.permission_center.create_permission("resume", "Authorizes users to resume virtual machine", False)
        self.permission_center.create_permission("vncdisplay", "Authorizes users to access the vnc display port", False)
        self.permission_center.create_permission("xmldesc", "Authorizes users to access the XML description of the virtual machine", False)
        self.permission_center.create_permission("migrate", "Authorizes users to perform live migration", False)
        self.permission_center.create_permission("autostart", "Authorizes users to set the virtual machine autostart", False)
        self.permission_center.create_permission("memory", "Authorizes users to change memory in live", False)
        self.permission_center.create_permission("setvcpus", "Authorizes users to set the number of virtual CPU in live", False)
        self.permission_center.create_permission("networkinfo", "Authorizes users to access virtual machine's network informations", False)
        self.permission_center.create_permission("define", "Authorizes users to define virtual machine", False)
        self.permission_center.create_permission("undefine", "Authorizes users to undefine virtual machine", False)
        self.permission_center.create_permission("capabilities", "Authorizes users to access virtual machine's hypervisor capabilities", False)
    
    
    def register_handler(self):
        """
        this method registers the events handlers.
        it is invoked by super class __xmpp_connect() method
        """
        self.xmppclient.RegisterHandler('iq', self.__process_iq_archipel_control, ns=ARCHIPEL_NS_VM_CONTROL)
        self.xmppclient.RegisterHandler('iq', self.__process_iq_archipel_definition, ns=ARCHIPEL_NS_VM_DEFINITION)
        
        TNArchipelEntity.register_handler(self)
    
    
    def remove_folder(self):
        """
        remove the folder of the virtual with all its contents
        """
        os.system("rm -rf " + self.folder)
    
    
    def set_automatic_libvirt_description(self, xmldesc):
        """
        set the XML description's description of the VM
        """
        if not xmldesc.getTag('description'): 
            xmldesc.addChild(name='description')
        else:
            xmldesc.delChild("description")
            xmldesc.addChild(name='description')
        
        xmldesc.getTag('description').setData("%s::::%s" % (self.jid.getStripped(), self.password))
        
        if not xmldesc.getTag('name'): xmldesc.addChild(name='name')
        xmldesc.getTag('name').setData(self.name)
        
        ret = str(xmldesc).replace('xmlns="http://www.gajim.org/xmlns/undeclared" ', '')
        self.log.debug("generated XML desc is : %s" % ret)
        return ret
    
    
    def set_presence_according_to_libvirt_info(self):
        """
        set XMPP status according to libvirt status
        """
        try:            
            dominfo = self.domain.info()
            self.libvirt_status = dominfo[0]
            self.log.info("virtual machine state is %d" %  dominfo[0])
            if dominfo[0] == libvirt.VIR_DOMAIN_RUNNING or dominfo[0] == libvirt.VIR_DOMAIN_BLOCKED:
                self.change_presence("", ARCHIPEL_XMPP_SHOW_RUNNING)
                self.create_novnc_proxy()
                self.triggers["libvirt_run"].set_state(ARCHIPEL_TRIGGER_STATE_ON)
            elif dominfo[0] == libvirt.VIR_DOMAIN_PAUSED:
                self.change_presence("away", ARCHIPEL_XMPP_SHOW_PAUSED)
                self.triggers["libvirt_run"].set_state(ARCHIPEL_TRIGGER_STATE_OFF)
            elif dominfo[0] == libvirt.VIR_DOMAIN_SHUTOFF:
                self.change_presence("xa", ARCHIPEL_XMPP_SHOW_SHUTDOWNED)
            elif dominfo[0] == libvirt.VIR_DOMAIN_SHUTDOWN:
                self.change_presence("", ARCHIPEL_XMPP_SHOW_SHUTDOWNING)
            self.perform_hooks("HOOK_VM_INITIALIZE")
{'fraction_non_alphanumeric': 0.09053896212247622, 'fraction_numerical': 0.0059068913732688135, 'mean_word_length': 1.8430740037950664, 'pattern_counts': {'":': 86, '<': 11, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 4, 'xml': 31}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5102774', 'n_tokens_mistral': 8223, 'n_tokens_neox': 7794, 'n_words': 1696}