From adfdad013ca88d91952bd6d4056348580913a53f Mon Sep 17 00:00:00 2001
From: catborise <catborise@yahoo.com>
Date: Fri, 20 Dec 2019 16:43:14 +0300
Subject: [PATCH 1/7] change cd-rom bus for q35 type machines; it is sata not
 ide

---
 instances/views.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/instances/views.py b/instances/views.py
index 6daa554..39f88fa 100644
--- a/instances/views.py
+++ b/instances/views.py
@@ -616,7 +616,7 @@ def instance(request, compute_id, vname):
                 return HttpResponseRedirect(request.get_full_path() + '#disks')
 
             if 'add_cdrom' in request.POST and allow_admin_or_not_template:
-                bus = request.POST.get('bus', 'ide')
+                bus = request.POST.get('bus', 'ide' if machine == 'pc' else 'sata')
                 target = get_new_disk_dev(media, disks, bus)
                 conn.attach_disk("", target, device='cdrom', cache='none', targetbus=bus)
                 msg = _('Add CD-ROM: ' + target)

From 592112590c1ab3fa6dc3102b4e81246a4524efb8 Mon Sep 17 00:00:00 2001
From: catborise <catborise@yahoo.com>
Date: Mon, 23 Dec 2019 15:48:11 +0300
Subject: [PATCH 2/7] add ability to show interface's ip address with qemu
 agent. Add checking agent if installed or not

---
 instances/templates/instance.html |  10 +--
 instances/views.py                |   3 +-
 interfaces/views.py               |   2 +-
 vrtManager/connection.py          |   2 +-
 vrtManager/instance.py            | 115 +++++++++++++++++++++++++-----
 vrtManager/network.py             |  13 ++++
 6 files changed, 122 insertions(+), 23 deletions(-)

diff --git a/instances/templates/instance.html b/instances/templates/instance.html
index 2cbd079..b83809b 100644
--- a/instances/templates/instance.html
+++ b/instances/templates/instance.html
@@ -876,7 +876,8 @@
                                     <tr>
                                         <th>{% trans 'Name' %}</th>
                                         <th>{% trans 'MAC' %}</th>
-                                        <th>{% trans 'NIC' %}</th>
+                                        <th>{% trans 'IP Address' %}</th>
+                                        <th>{% trans 'Source' %}</th>
                                         <th>{% trans 'Filter' %}</th>
                                         <th>{% trans 'Qos' %}</th>
                                         <th>{% trans 'Actions' %}</th>
@@ -886,9 +887,10 @@
                                         {% for network in networks %}
                                         <tr>
                                             <td class="col-sm-2"><label>eth{{ forloop.counter0 }}({{ network.target|default:"no target" }})</label></td>
-                                            <td><input class="form-control" type="text" value="{{ network.mac }}" readonly/></td>
-                                            <td><input class="form-control" type="text" value="{{ network.nic }}" readonly/></td>
-                                            <td><input class="form-control" type="text" value="{{ network.filterref }}" readonly/></td>
+                                            <td><label>{{ network.mac }}</label></td>
+                                            <td><label>{{ network.ipv4|default:"unknown" }}</label></td>
+                                            <td><label>{{ network.nic }}</label></td>
+                                            <td><label>{{ network.filterref|default:"None" }}</label></td>
                                             <td>
                                                 <form class="form-horizontal" method="post" name="add_qos{{ forloop.counter0 }}" role="form">{% csrf_token %}
                                                     <input type="text" name="net-mac-{{ forloop.counter0 }}" value="{{ network.mac }}" hidden/>
diff --git a/instances/views.py b/instances/views.py
index 39f88fa..ac24121 100644
--- a/instances/views.py
+++ b/instances/views.py
@@ -266,6 +266,7 @@ def instance(request, compute_id, vname):
                            compute.password,
                            compute.type,
                            vname)
+
         status = conn.get_status()
         autostart = conn.get_autostart()
         bootmenu = conn.get_bootmenu()
@@ -282,7 +283,7 @@ def instance(request, compute_id, vname):
         cur_memory = conn.get_cur_memory()
         title = conn.get_title()
         description = conn.get_description()
-        networks = conn.get_net_device()
+        networks = conn.get_net_devices()
         qos = conn.get_all_qos()
         disks = conn.get_disk_devices()
         media = conn.get_media_devices()
diff --git a/interfaces/views.py b/interfaces/views.py
index a747120..6ac9dd6 100644
--- a/interfaces/views.py
+++ b/interfaces/views.py
@@ -30,7 +30,7 @@ def interfaces(request, compute_id):
                              compute.type)
         ifaces = conn.get_ifaces()
         try:
-            netdevs = conn.get_net_device()
+            netdevs = conn.get_net_devices()
         except:
             netdevs = ['eth0', 'eth1']
 
diff --git a/vrtManager/connection.py b/vrtManager/connection.py
index 8e826f0..19b9684 100644
--- a/vrtManager/connection.py
+++ b/vrtManager/connection.py
@@ -686,7 +686,7 @@ class wvmConnect(object):
                 instance.append(dom.name())
         return instance
 
-    def get_net_device(self):
+    def get_net_devices(self):
         netdevice = []
 
         def get_info(doc):
diff --git a/vrtManager/instance.py b/vrtManager/instance.py
index 8a18559..3609bb2 100644
--- a/vrtManager/instance.py
+++ b/vrtManager/instance.py
@@ -11,6 +11,7 @@ try:
         VIR_MIGRATE_COMPRESSED, \
         VIR_MIGRATE_AUTO_CONVERGE, \
         VIR_MIGRATE_POSTCOPY
+    from libvirt import VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_AGENT
 except:
     from libvirt import libvirtError, VIR_DOMAIN_XML_SECURE, VIR_MIGRATE_LIVE
 
@@ -148,6 +149,7 @@ class wvmInstances(wvmConnect):
 class wvmInstance(wvmConnect):
     def __init__(self, host, login, passwd, conn, vname):
         wvmConnect.__init__(self, host, login, passwd, conn)
+        self._ip_cache = None
         self.instance = self.get_instance(vname)
 
     def start(self):
@@ -276,17 +278,73 @@ class wvmInstance(wvmConnect):
         range_pcpus = xrange(1, int(pcpus + 1))
         return range_pcpus
 
-    def get_net_device(self):
-        def get_mac_ipaddr(net, mac_host):
-            def fixed(doc):
-                for net in doc.xpath('/network/ip/dhcp/host'):
-                    mac = net.xpath('@mac')[0]
-                    host = net.xpath('@ip')[0]
-                    if mac == mac_host:
-                        return host
-                return None
+    def get_interface_addresses(self, iface_mac):
+        if self._ip_cache is None:
+            self.refresh_interface_addresses()
 
-            return util.get_xml_path(net.XMLDesc(0), func=fixed)
+        qemuga = self._ip_cache["qemuga"]
+        arp = self._ip_cache["arp"]
+        leases = []
+
+        def extract_dom(info):
+            ipv4 = None
+            ipv6 = None
+            for addrs in info.values():
+                if addrs["hwaddr"] != iface_mac:
+                    continue
+                if not addrs["addrs"]:
+                    continue
+                for addr in addrs["addrs"]:
+                    if addr["type"] == 0:
+                        ipv4 = addr["addr"]
+                    elif (addr["type"] == 1 and
+                          not str(addr["addr"]).startswith("fe80")):
+                        ipv6 = addr["addr"] + "/" + str(addr["prefix"])
+            return ipv4, ipv6
+
+        def extract_lease(info):
+            ipv4 = None
+            ipv6 = None
+            if info["mac"] == iface_mac:
+                if info["type"] == 0:
+                    ipv4 = info["ipaddr"]
+                elif info["type"] == 1:
+                    ipv6 = info["ipaddr"]
+            return ipv4, ipv6
+
+        for ips in ([qemuga] + leases + [arp]):
+            if "expirytime" in ips:
+                ipv4, ipv6 = extract_lease(ips)
+            else:
+                ipv4, ipv6 = extract_dom(ips)
+            if ipv4 or ipv6:
+                return ipv4, ipv6
+        return None, None
+
+    def _get_interface_addresses(self, source):
+        #("Calling interfaceAddresses source=%s", source)
+        try:
+            return self.instance.interfaceAddresses(source)
+        except Exception as e:
+            #log.debug("interfaceAddresses failed: %s", str(e))
+            pass
+        return {}
+
+    def refresh_interface_addresses(self):
+
+        self._ip_cache = {"qemuga": {}, "arp": {}}
+
+        if not self.get_status() == 1:
+            return
+
+        if self.agent_ready():
+            self._ip_cache["qemuga"] = self._get_interface_addresses(
+                VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_AGENT)
+
+        arp_flag = 3 # libvirt."VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_ARP"
+        self._ip_cache["arp"] = self._get_interface_addresses(arp_flag)
+
+    def get_net_devices(self):
 
         def networks(ctx):
             result = []
@@ -310,14 +368,14 @@ class wvmInstance(wvmConnect):
                     outbound = {'average': out_av, 'peak': out_peak, 'burst': out_burst}
 
                 try:
-                    net = self.get_network(nic_inst)
-                    ip = get_mac_ipaddr(net, mac_inst)
-                except libvirtError:
-                    ip = None
+                    ipv4, ipv6 = self.get_interface_addresses(mac_inst)
+                except:
+                    ipv4, ipv6 = None, None
                 result.append({'mac': mac_inst,
                                'nic': nic_inst,
                                'target': target_inst,
-                               'ip': ip,
+                               'ipv4': ipv4,
+                               'ipv6': ipv6,
                                'filterref': filterref_inst,
                                'inbound': inbound,
                                'outbound': outbound,
@@ -709,7 +767,7 @@ class wvmInstance(wvmConnect):
                 tx_diff_usage = (tx_use_now - tx_use_ago) * 8
                 dev_usage.append({'dev': i, 'rx': rx_diff_usage, 'tx': tx_diff_usage})
         else:
-            for i, dev in enumerate(self.get_net_device()):
+            for i, dev in enumerate(self.get_net_devices()):
                 dev_usage.append({'dev': i, 'rx': 0, 'tx': 0})
         return dev_usage
 
@@ -1311,4 +1369,29 @@ class wvmInstance(wvmConnect):
 
         self.wvm.defineXML(etree.tostring(tree))
 
+    def agent_ready(self):
+        """
+        Return connected state of an agent.
+        """
+        # we need to get a fresh agent channel object on each call so it
+        # reflects the current state
+        def _get_agent(doc):
+            """
+            Return agent channel object if it is defined.
+            """
+            for channel in doc.xpath('/domain/devices/channel'):
+                type = channel.get("type")
+                target = channel.find("target")
+                target_name = target.get("name")
+                if type == "unix" and target_name == "org.qemu.guest_agent.0":
+                    return channel
+            return None
+
+        dev = util.get_xml_path(self._XMLDesc(0), func=_get_agent)
+        state = dev.xpath("target/@state")[0]
+        if dev and state == "connected":
+            return True
+        return False
+
+
 
diff --git a/vrtManager/network.py b/vrtManager/network.py
index 87333da..560bd42 100644
--- a/vrtManager/network.py
+++ b/vrtManager/network.py
@@ -89,6 +89,7 @@ class wvmNetworks(wvmConnect):
 class wvmNetwork(wvmConnect):
     def __init__(self, host, login, passwd, conn, net):
         wvmConnect.__init__(self, host, login, passwd, conn)
+        self.leases = None
         self.net = self.get_network(net)
         self.parent_count = len(self.get_ip_networks())
 
@@ -347,3 +348,15 @@ class wvmNetwork(wvmConnect):
 
     def edit_network(self, new_xml):
         self.wvm.networkDefineXML(new_xml)
+
+    def refresh_dhcp_leases(self):
+        try:
+            self.leases = self.net.DHCPLeases()
+        except Exception as e:
+            self.leases = []
+            raise "Error getting %s DHCP leases: %s" % self, str(e)
+
+    def get_dhcp_leases(self):
+        if self.leases is None:
+            self.refresh_dhcp_leases()
+        return self.leases

From 01f2290dd9b3070855d5b94dbc2d81f8b61bdb39 Mon Sep 17 00:00:00 2001
From: catborise <catborise@yahoo.com>
Date: Tue, 24 Dec 2019 09:23:49 +0300
Subject: [PATCH 3/7] host ifaces configuration error prevents management of
 instance. It is isolated.

---
 instances/views.py | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/instances/views.py b/instances/views.py
index ac24121..0de54b0 100644
--- a/instances/views.py
+++ b/instances/views.py
@@ -343,10 +343,15 @@ def instance(request, compute_id, vname):
         bus_host = conn.get_disk_bus_types(arch, machine)
         videos_host = conn.get_video_models(arch, machine)
         networks_host = sorted(conn.get_networks())
-        interfaces_host = sorted(conn.get_ifaces())
         nwfilters_host = conn.get_nwfilters()
         storages_host = sorted(conn.get_storages(True))
 
+        try:
+            interfaces_host = sorted(conn.get_ifaces())
+        except Exception as e:
+            addlogmsg(request.user.username, instance.name, e)
+            error_messages.append(e)
+
         if request.method == 'POST':
             if 'poweron' in request.POST:
                 if instance.is_template:

From ecf31b0b5b9a7d88f31d2b85739d52017d9c3ebb Mon Sep 17 00:00:00 2001
From: catborise <catborise@yahoo.com>
Date: Tue, 24 Dec 2019 14:54:04 +0300
Subject: [PATCH 4/7] adds link state option for instance networks.
 Enable/disable link while instance running

---
 instances/templates/instance.html | 20 +++++++++++++++-----
 instances/views.py                |  9 +++++++++
 vrtManager/instance.py            | 31 ++++++++++++++++++++++++++-----
 3 files changed, 50 insertions(+), 10 deletions(-)

diff --git a/instances/templates/instance.html b/instances/templates/instance.html
index b83809b..7b45eef 100644
--- a/instances/templates/instance.html
+++ b/instances/templates/instance.html
@@ -878,6 +878,7 @@
                                         <th>{% trans 'MAC' %}</th>
                                         <th>{% trans 'IP Address' %}</th>
                                         <th>{% trans 'Source' %}</th>
+                                        <th>{% trans 'LinkState' %}</th>
                                         <th>{% trans 'Filter' %}</th>
                                         <th>{% trans 'Qos' %}</th>
                                         <th>{% trans 'Actions' %}</th>
@@ -886,11 +887,20 @@
                                     <tbody>
                                         {% for network in networks %}
                                         <tr>
-                                            <td class="col-sm-2"><label>eth{{ forloop.counter0 }}({{ network.target|default:"no target" }})</label></td>
-                                            <td><label>{{ network.mac }}</label></td>
-                                            <td><label>{{ network.ipv4|default:"unknown" }}</label></td>
-                                            <td><label>{{ network.nic }}</label></td>
-                                            <td><label>{{ network.filterref|default:"None" }}</label></td>
+                                            <td class="col-sm-1">eth{{ forloop.counter0 }}({{ network.target|default:"no target" }})</td>
+                                            <td>{{ network.mac }}</td>
+                                            <td>{{ network.ipv4|default:"unknown" }}</td>
+                                            <td>{{ network.nic }}</td>
+                                            <td>
+                                            <form method="post">{% csrf_token %}
+                                                <input name="mac" value="{{ network.mac }}" hidden/>
+                                                <input name="set_link_state" value="{{ network.state }}" hidden/>
+                                                <input type="checkbox" {% if network.state == 'up' %} checked
+                                                {% endif %} onclick='submit();' />
+                                                {% trans 'active' %}
+                                            </form>
+                                            </td>
+                                            <td>{{ network.filterref|default:"None" }}</td>
                                             <td>
                                                 <form class="form-horizontal" method="post" name="add_qos{{ forloop.counter0 }}" role="form">{% csrf_token %}
                                                     <input type="text" name="net-mac-{{ forloop.counter0 }}" value="{{ network.mac }}" hidden/>
diff --git a/instances/views.py b/instances/views.py
index 0de54b0..495c790 100644
--- a/instances/views.py
+++ b/instances/views.py
@@ -873,6 +873,15 @@ def instance(request, compute_id, vname):
                     addlogmsg(request.user.username, instance.name, msg)
                     return HttpResponseRedirect(request.get_full_path() + '#network')
 
+                if 'set_link_state' in request.POST:
+                    mac_address = request.POST.get('mac', '')
+                    state = request.POST.get('set_link_state')
+                    state = 'down' if state == 'up' else 'up'
+                    conn.set_link_state(mac_address, state)
+                    msg = _("Set Link State: {}".format(state))
+                    addlogmsg(request.user.username, instance.name, msg)
+                    return HttpResponseRedirect(request.get_full_path() + '#network')
+
                 if 'set_qos' in request.POST:
                     qos_dir = request.POST.get('qos_direction', '')
                     average = request.POST.get('qos_average') or 0
diff --git a/vrtManager/instance.py b/vrtManager/instance.py
index 3609bb2..2605b93 100644
--- a/vrtManager/instance.py
+++ b/vrtManager/instance.py
@@ -331,7 +331,6 @@ class wvmInstance(wvmConnect):
         return {}
 
     def refresh_interface_addresses(self):
-
         self._ip_cache = {"qemuga": {}, "arp": {}}
 
         if not self.get_status() == 1:
@@ -353,6 +352,7 @@ class wvmInstance(wvmConnect):
                 mac_inst = net.xpath('mac/@address')[0]
                 nic_inst = net.xpath('source/@network|source/@bridge|source/@dev')[0]
                 target_inst = '' if not net.xpath('target/@dev') else net.xpath('target/@dev')[0]
+                link_state = 'up' if not net.xpath('link') else net.xpath('link/@state')[0]
                 filterref_inst = '' if not net.xpath('filterref/@filter') else net.xpath('filterref/@filter')[0]
                 if net.xpath('bandwidth/inbound'):
                     in_attr = net.xpath('bandwidth/inbound')[0]
@@ -374,6 +374,7 @@ class wvmInstance(wvmConnect):
                 result.append({'mac': mac_inst,
                                'nic': nic_inst,
                                'target': target_inst,
+                               'state': link_state,
                                'ipv4': ipv4,
                                'ipv6': ipv6,
                                'filterref': filterref_inst,
@@ -1275,6 +1276,24 @@ class wvmInstance(wvmConnect):
         new_xml = ElementTree.tostring(tree)
         self._defineXML(new_xml)
 
+    def set_link_state(self, mac_address, state):
+        tree = etree.fromstring(self._XMLDesc(0))
+        for interface in tree.findall('devices/interface'):
+            source = interface.find('mac')
+            if source.get('address') == mac_address:
+                link = interface.find('link')
+                if link is not None:
+                    interface.remove(link)
+                link_el = etree.Element("link")
+                link_el.attrib["state"] = state
+                interface.append(link_el)
+                new_xml = etree.tostring(interface)
+                if self.get_status() == 1:
+                    self.instance.updateDeviceFlags(new_xml, VIR_DOMAIN_AFFECT_LIVE)
+                    self.instance.updateDeviceFlags(new_xml, VIR_DOMAIN_AFFECT_CONFIG)
+                if self.get_status() == 5:
+                    self.instance.updateDeviceFlags(new_xml, VIR_DOMAIN_AFFECT_CONFIG)
+
     def _set_options(self, tree, options):
         for o in ['title', 'description']:
             option = tree.find(o)
@@ -1388,10 +1407,12 @@ class wvmInstance(wvmConnect):
             return None
 
         dev = util.get_xml_path(self._XMLDesc(0), func=_get_agent)
-        state = dev.xpath("target/@state")[0]
-        if dev and state == "connected":
-            return True
-        return False
+        if len(dev) > 0:
+            states = dev.xpath("target/@state")
+            state = states[0] if len(states) > 0 else ''
+            if state == "connected":
+                return True
+            return False
 
 
 

From 9d58e56d165194deb9d005b0bc4b9df303fc2322 Mon Sep 17 00:00:00 2001
From: catborise <catborise@yahoo.com>
Date: Tue, 24 Dec 2019 17:19:11 +0300
Subject: [PATCH 5/7] add/remove guest agent channel function added

---
 instances/templates/instance.html | 29 +++++++++++++++++--
 instances/views.py                | 13 +++++++++
 vrtManager/instance.py            | 46 ++++++++++++++++++++++++-------
 3 files changed, 76 insertions(+), 12 deletions(-)

diff --git a/instances/templates/instance.html b/instances/templates/instance.html
index 7b45eef..2ca73a5 100644
--- a/instances/templates/instance.html
+++ b/instances/templates/instance.html
@@ -1411,11 +1411,11 @@
                             </form>
                             <div class="clearfix"></div>
                         </div>
-                         <div class="well">
+                        <div class="well">
                             <p>{% trans "To set instance vCPUs hotpluggable" %}</p>
                             <form class="form-horizontal" method="post" role="form">{% csrf_token %}
                                 <div class="form-group">
-                                    <label for="video_model_select" class="col-sm-3 control-label">{% trans "vCPU Hot Plug" %}</label>
+                                    <label for="vcpu_hotplug" class="col-sm-3 control-label">{% trans "vCPU Hot Plug" %}</label>
                                     <div class="col-sm-6">
                                       <div class="input-group">
                                         <select id="vcpu_hotplug" class="form-control" name="vcpu_hotplug">
@@ -1435,6 +1435,31 @@
                             </form>
                             <div class="clearfix"></div>
                         </div>
+                        <div class="well">
+                            <p>{% trans "To Enable/Disable Qemu Guest Agent. Status:" %}
+                                {% if guest_agent_ready %}
+                                    <label class="label label-success">{% trans 'Connected' %}</label>
+                                {% else %}
+                                    <label class="label label-danger">{% trans 'Disconnected' %}</label>
+                                {% endif %}</p>
+                            <form class="form-horizontal" method="post" role="form">{% csrf_token %}
+                                <div class="form-group">
+                                    <label for="guest_agent" class="col-sm-3 control-label">{% trans "Qemu Guest Agent" %}</label>
+                                    <div class="col-sm-6">
+                                      <div class="input-group">
+                                        <select id="guest_agent" class="form-control" name="guest_agent">
+                                            <option value="True" {% if guest_agent %} selected {% endif %}>{% trans 'Enabled' %}</option>
+                                            <option value="False" {% if not guest_agent %} selected {% endif %}>{% trans 'Disabled' %}</option>
+                                        </select>
+                                        <span class="input-group-btn">
+                                            <button type="submit" class="btn btn-success" name="set_guest_agent">{% trans "Set" %}</button>
+                                        </span>
+                                      </div>
+                                    </div>
+                                </div>
+                            </form>
+                            <div class="clearfix"></div>
+                        </div>
                     </div>
                     {% endif %}
                 </div>
diff --git a/instances/views.py b/instances/views.py
index 495c790..78982d4 100644
--- a/instances/views.py
+++ b/instances/views.py
@@ -303,6 +303,8 @@ def instance(request, compute_id, vname):
         console_port = conn.get_console_port()
         console_keymap = conn.get_console_keymap()
         console_listen_address = conn.get_console_listen_addr()
+        guest_agent = False if conn.get_guest_agent() is None else True
+        guest_agent_ready = conn.is_agent_ready()
         video_model = conn.get_video_model()
         snapshots = sorted(conn.get_snapshot(), reverse=True, key=lambda k: k['date'])
         inst_xml = conn._XMLDesc(VIR_DOMAIN_XML_SECURE)
@@ -810,6 +812,17 @@ def instance(request, compute_id, vname):
                     return HttpResponseRedirect(request.get_full_path() + '#vncsettings')
 
             if request.user.is_superuser:
+                if 'set_guest_agent' in request.POST:
+                    status = request.POST.get('guest_agent')
+                    if status == 'True':
+                        conn.add_guest_agent()
+                    if status == 'False':
+                        conn.remove_guest_agent()
+
+                    msg = _("Set Quest Agent {}".format(status))
+                    addlogmsg(request.user.username, instance.name, msg)
+                    return HttpResponseRedirect(request.get_full_path() + '#options')
+
                 if 'set_video_model' in request.POST:
                     video_model = request.POST.get('video_model', 'vga')
                     conn.set_video_model(video_model)
diff --git a/vrtManager/instance.py b/vrtManager/instance.py
index 2605b93..71d44a2 100644
--- a/vrtManager/instance.py
+++ b/vrtManager/instance.py
@@ -336,7 +336,7 @@ class wvmInstance(wvmConnect):
         if not self.get_status() == 1:
             return
 
-        if self.agent_ready():
+        if self.is_agent_ready():
             self._ip_cache["qemuga"] = self._get_interface_addresses(
                 VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_AGENT)
 
@@ -1381,19 +1381,37 @@ class wvmInstance(wvmConnect):
         tree = etree.fromstring(self._XMLDesc(0))
         for direct in tree.xpath("/domain/devices/interface/bandwidth/{}".format(direction)):
             band_el = direct.getparent()
-            interface_el = band_el.getparent() # parent bandwidth,it parent is interface
+            interface_el = band_el.getparent()  # parent bandwidth,its parent is interface
             parent_mac = interface_el.xpath('mac/@address')
             if parent_mac[0] == mac:
                 band_el.remove(direct)
 
         self.wvm.defineXML(etree.tostring(tree))
 
-    def agent_ready(self):
-        """
-        Return connected state of an agent.
-        """
-        # we need to get a fresh agent channel object on each call so it
-        # reflects the current state
+    def add_guest_agent(self):
+        channel_xml = """
+                        <channel type='unix'>
+                            <target type='virtio' name='org.qemu.guest_agent.0'/>
+                        </channel>
+                      """
+        if self.get_status() == 1:
+            self.instance.attachDeviceFlags(channel_xml, VIR_DOMAIN_AFFECT_LIVE)
+            self.instance.attachDeviceFlags(channel_xml, VIR_DOMAIN_AFFECT_CONFIG)
+        if self.get_status() == 5:
+            self.instance.attachDeviceFlags(channel_xml, VIR_DOMAIN_AFFECT_CONFIG)
+
+    def remove_guest_agent(self):
+        tree = etree.fromstring(self._XMLDesc(0))
+        for target in tree.xpath("/domain/devices/channel[@type='unix']/target[@name='org.qemu.guest_agent.0']"):
+            parent = target.getparent()
+            channel_xml = etree.tostring(parent)
+            if self.get_status() == 1:
+                self.instance.detachDeviceFlags(channel_xml, VIR_DOMAIN_AFFECT_LIVE)
+                self.instance.detachDeviceFlags(channel_xml, VIR_DOMAIN_AFFECT_CONFIG)
+            if self.get_status() == 5:
+                self.instance.detachDeviceFlags(channel_xml, VIR_DOMAIN_AFFECT_CONFIG)
+
+    def get_guest_agent(self):
         def _get_agent(doc):
             """
             Return agent channel object if it is defined.
@@ -1406,8 +1424,16 @@ class wvmInstance(wvmConnect):
                     return channel
             return None
 
-        dev = util.get_xml_path(self._XMLDesc(0), func=_get_agent)
-        if len(dev) > 0:
+        return util.get_xml_path(self._XMLDesc(0), func=_get_agent)
+
+    def is_agent_ready(self):
+        """
+        Return connected state of an agent.
+        """
+        # we need to get a fresh agent channel object on each call so it
+        # reflects the current state
+        dev = self.get_guest_agent()
+        if dev is not None:
             states = dev.xpath("target/@state")
             state = states[0] if len(states) > 0 else ''
             if state == "connected":

From e87d7463fedaabdfc2a35aea960b722b3df5d7f4 Mon Sep 17 00:00:00 2001
From: catborise <catborise@yahoo.com>
Date: Wed, 25 Dec 2019 14:34:55 +0300
Subject: [PATCH 6/7] check if host supports kvm, if it is, use kvm else qemu

---
 vrtManager/connection.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/vrtManager/connection.py b/vrtManager/connection.py
index 19b9684..a1105a8 100644
--- a/vrtManager/connection.py
+++ b/vrtManager/connection.py
@@ -351,7 +351,7 @@ class wvmConnect(object):
     def get_dom_cap_xml(self, arch, machine):
         """ Return domain capabilities xml"""
         emulatorbin = self.get_emulator(arch)
-        virttype = self.get_hypervisors_domain_types()[arch][0]
+        virttype = 'kvm' if 'kvm' in self.get_hypervisors_domain_types()[arch] else 'qemu'
 
         machine_types = self.get_machine_types(arch)
         if not machine or machine not in machine_types:

From 38054d9882ef40c7e112118b7f27b8a3981cab67 Mon Sep 17 00:00:00 2001
From: catborise <catborise@yahoo.com>
Date: Wed, 25 Dec 2019 14:36:43 +0300
Subject: [PATCH 7/7] for instances add guest agent indicator: installed,
 connected.

---
 instances/templates/instance.html | 32 +++++++++++++++++++++++++------
 vrtManager/instance.py            |  4 ++--
 2 files changed, 28 insertions(+), 8 deletions(-)

diff --git a/instances/templates/instance.html b/instances/templates/instance.html
index 2ca73a5..261ab76 100644
--- a/instances/templates/instance.html
+++ b/instances/templates/instance.html
@@ -13,15 +13,15 @@
         </div>
         <div>
             <div>
-                {% ifequal status 5 %}
+                {% if status == 5 %}
                    <span class="label label-danger">{% trans "Off" %}</span>
-                {% endifequal %}
-                {% ifequal status 1 %}
+                {% endif %}
+                {% if status == 1 %}
                     <span class="label label-success">{% trans "Active" %}</span>
-                {% endifequal %}
-                {% ifequal status 3 %}
+                {% endif %}
+                {% if status == 3 %}
                     <span class="label label-warning">{% trans "Suspend" %}</span>
-                {% endifequal %}
+                {% endif %}
                 |
                 {% if cur_vcpu %}
                     {{ cur_vcpu }} {% trans "Vcpu" %}
@@ -34,6 +34,22 @@
                 {% for disk in disks %}
                     {{ disk.size|filesizeformat }} {% trans "Disk" %} |
                 {% endfor %}
+                <button
+                    {% if guest_agent == True %}
+                        {% if guest_agent_ready == True %}
+                            class="btn btn-xs btn-success"
+                            title="Guest Agent Enabled & Connected"
+                        {% else %}
+                            class="btn btn-xs btn-default"
+                            title="Guest Agent Enabled but not Connected"
+                        {% endif %}
+                    {% else %}
+                        class="btn btn-xs btn-danger"
+                        title="Guest Agent Not Enabled & Not Connected"
+                    {% endif %} disabled>
+                        <span class="glyphicon glyphicon-flash"></span>
+                </button>
+                |
                 <a href="{% url 'instance' compute.id vname %}" type="button" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-refresh"></span></a>
                 <em>on</em>
                 <a href="{% url 'overview' compute.id %}"><span class="label label-primary">{{ compute.name }}{% if compute.name != compute.hostname %} - {{ compute.hostname }}{% endif %} </span></a>
@@ -1437,11 +1453,15 @@
                         </div>
                         <div class="well">
                             <p>{% trans "To Enable/Disable Qemu Guest Agent. Status:" %}
+                            {% if status == 1 %}
                                 {% if guest_agent_ready %}
                                     <label class="label label-success">{% trans 'Connected' %}</label>
                                 {% else %}
                                     <label class="label label-danger">{% trans 'Disconnected' %}</label>
                                 {% endif %}</p>
+                            {% else %}
+                                <label class="label label-default">{% trans 'Unknown' %}</label>
+                            {% endif %}
                             <form class="form-horizontal" method="post" role="form">{% csrf_token %}
                                 <div class="form-group">
                                     <label for="guest_agent" class="col-sm-3 control-label">{% trans "Qemu Guest Agent" %}</label>
diff --git a/vrtManager/instance.py b/vrtManager/instance.py
index 71d44a2..27354db 100644
--- a/vrtManager/instance.py
+++ b/vrtManager/instance.py
@@ -1417,10 +1417,10 @@ class wvmInstance(wvmConnect):
             Return agent channel object if it is defined.
             """
             for channel in doc.xpath('/domain/devices/channel'):
-                type = channel.get("type")
+                ch_type = channel.get("type")
                 target = channel.find("target")
                 target_name = target.get("name")
-                if type == "unix" and target_name == "org.qemu.guest_agent.0":
+                if ch_type == "unix" and target_name == "org.qemu.guest_agent.0":
                     return channel
             return None