Add UI elements to display and modify QoS settings in the network details. Closes: https://bugzilla.redhat.com/show_bug.cgi?id=1089117 Signed-off-by: Giuseppe Scrivano <gscrivan@xxxxxxxxxx> --- ui/host.ui | 246 +++++++++++++++++++++++++++++++++++++++++++++++++ virtManager/host.py | 78 +++++++++++++++- virtManager/network.py | 15 ++- 3 files changed, 337 insertions(+), 2 deletions(-) diff --git a/ui/host.ui b/ui/host.ui index e1e2088..07b06a1 100644 --- a/ui/host.ui +++ b/ui/host.ui @@ -1091,6 +1091,252 @@ <property name="position">2</property> </packing> </child> + <child> + <object class="GtkExpander" id="net-qos-expander"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <child> + <object class="GtkBox" id="box14"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="orientation">vertical</property> + <child> + <object class="GtkCheckButton" id="net-qos-inbound-enable"> + <property name="label" translatable="yes">Enable inbound QoS</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="xalign">0</property> + <property name="draw_indicator">True</property> + <signal name="toggled" handler="on_net_qos_inbound_enable_toggled" swapped="no"/> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkGrid" id="net-qos-inbound-grid"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="row_spacing">5</property> + <property name="column_spacing">6</property> + <child> + <object class="GtkEntry" id="qos-inbound-peak"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <signal name="changed" handler="on_qos_inbound_peak_changed" swapped="no"/> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">1</property> + <property name="width">1</property> + <property name="height">1</property> + </packing> + </child> + <child> + <object class="GtkEntry" id="qos-inbound-burst"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <signal name="changed" handler="on_qos_inbound_burst_changed" swapped="no"/> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">2</property> + <property name="width">1</property> + <property name="height">1</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="label35"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Average (KiB/sec):</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">0</property> + <property name="width">1</property> + <property name="height">1</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="label36"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Burst (KiB):</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">2</property> + <property name="width">1</property> + <property name="height">1</property> + </packing> + </child> + <child> + <object class="GtkEntry" id="qos-inbound-average"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <signal name="changed" handler="on_qos_inbound_average_changed" swapped="no"/> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">0</property> + <property name="width">1</property> + <property name="height">1</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="label37"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Peak (KiB/sec):</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">1</property> + <property name="width">1</property> + <property name="height">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkCheckButton" id="net-qos-outbound-enable"> + <property name="label" translatable="yes">Enable outbound QoS</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="xalign">0</property> + <property name="draw_indicator">True</property> + <signal name="toggled" handler="on_net_qos_outbound_enable_toggled" swapped="no"/> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">2</property> + </packing> + </child> + <child> + <object class="GtkGrid" id="net-qos-outbound-grid"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="row_spacing">5</property> + <property name="column_spacing">6</property> + <child> + <object class="GtkEntry" id="qos-outbound-peak"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <signal name="changed" handler="on_qos_outbound_peak_changed" swapped="no"/> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">1</property> + <property name="width">1</property> + <property name="height">1</property> + </packing> + </child> + <child> + <object class="GtkEntry" id="qos-outbound-burst"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <signal name="changed" handler="on_qos_outbound_burst_changed" swapped="no"/> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">2</property> + <property name="width">1</property> + <property name="height">1</property> + </packing> + </child> + <child> + <object class="GtkEntry" id="qos-outbound-average"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <signal name="changed" handler="on_qos_outbound_average_changed" swapped="no"/> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">0</property> + <property name="width">1</property> + <property name="height">1</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="label42"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Burst (KiB/sec):</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">2</property> + <property name="width">1</property> + <property name="height">1</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="label44"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Peak (KiB/sec):</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">1</property> + <property name="width">1</property> + <property name="height">1</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="label45"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Average (KiB/sec):</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">0</property> + <property name="width">1</property> + <property name="height">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">3</property> + </packing> + </child> + </object> + </child> + <child type="label"> + <object class="GtkLabel" id="label38"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes"><b>QoS configuration</b></property> + <property name="use_markup">True</property> + </object> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">3</property> + </packing> + </child> </object> </child> </object> diff --git a/virtManager/host.py b/virtManager/host.py index 4166929..3c53a20 100644 --- a/virtManager/host.py +++ b/virtManager/host.py @@ -43,10 +43,11 @@ INTERFACE_PAGE_ERROR = 1 (EDIT_NET_NAME, EDIT_NET_AUTOSTART, +EDIT_NET_QOS, EDIT_POOL_NAME, EDIT_POOL_AUTOSTART, -) = range(4) +) = range(5) class vmmHost(vmmGObjectUI): @@ -127,6 +128,22 @@ class vmmHost(vmmGObjectUI): "on_interface_list_changed": self.interface_selected, "on_config_autoconnect_toggled": self.toggle_autoconnect, + + "on_qos_inbound_average_changed": (lambda *x: + self.enable_net_apply(x, EDIT_NET_QOS)), + "on_qos_inbound_peak_changed": (lambda *x: + self.enable_net_apply(x, EDIT_NET_QOS)), + "on_qos_inbound_burst_changed": (lambda *x: + self.enable_net_apply(x, EDIT_NET_QOS)), + "on_qos_outbound_average_changed": (lambda *x: + self.enable_net_apply(x, EDIT_NET_QOS)), + "on_qos_outbound_peak_changed": (lambda *x: + self.enable_net_apply(x, EDIT_NET_QOS)), + "on_qos_outbound_burst_changed": (lambda *x: + self.enable_net_apply(x, EDIT_NET_QOS)), + + "on_net_qos_inbound_enable_toggled": self.change_qos_in_enable, + "on_net_qos_outbound_enable_toggled": self.change_qos_out_enable, }) self.repopulate_networks() @@ -481,6 +498,33 @@ class vmmHost(vmmGObjectUI): if EDIT_NET_NAME in self.active_edits: net.define_name(self.widget("net-name").get_text()) self.repopulate_networks() + if EDIT_NET_QOS in self.active_edits: + in_qos = self.widget("net-qos-inbound-enable").get_active() + out_qos = self.widget("net-qos-outbound-enable").get_active() + + def get_value(name, enabled): + if not enabled: + return None + return self.widget(name).get_text() or None + + args = {} + args['inbound_average'] = get_value("qos-inbound-average", in_qos) + args['inbound_peak'] = get_value("qos-inbound-peak", in_qos) + args['inbound_burst'] = get_value("qos-inbound-burst", in_qos) + + args['outbound_average'] = get_value("qos-outbound-average", out_qos) + args['outbound_peak'] = get_value("qos-outbound-peak", out_qos) + args['outbound_burst'] = get_value("qos-outbound-burst", out_qos) + + if net.set_qos(**args): + self.err.show_err( + _("Network could not be updated"), + text2=_("This change will take effect when the " + "network is restarted"), + buttons=Gtk.ButtonsType.OK, + dialog_type=Gtk.MessageType.INFO) + + except Exception, e: self.err.show_err(_("Error changing network settings: %s") % str(e)) return @@ -615,6 +659,37 @@ class vmmHost(vmmGObjectUI): routevia = routeaddr + ", gateway=" + routevia self.widget("net-ipv6-route").set_text(routevia or "") + def update_qos_widgets(self): + enabled = self.widget("net-qos-inbound-enable").get_active() + self.widget("net-qos-inbound-grid").set_visible(enabled) + + enabled = self.widget("net-qos-outbound-enable").get_active() + self.widget("net-qos-outbound-grid").set_visible(enabled) + + def change_qos_in_enable(self, ignore): + self.enable_net_apply(EDIT_NET_QOS) + self.update_qos_widgets() + + def change_qos_out_enable(self, ignore): + self.enable_net_apply(EDIT_NET_QOS) + self.update_qos_widgets() + + def _populate_qos_state(self, net): + qos = net.get_qos() + + self.widget("net-qos-inbound-enable").set_active(qos.is_inbound()) + self.widget("net-qos-outbound-enable").set_active(qos.is_outbound()) + + self.update_qos_widgets() + + self.widget("qos-inbound-average").set_text(qos.inbound_average or "") + self.widget("qos-inbound-peak").set_text(qos.inbound_peak or "") + self.widget("qos-inbound-burst").set_text(qos.inbound_burst or "") + + self.widget("qos-outbound-average").set_text(qos.outbound_average or "") + self.widget("qos-outbound-peak").set_text(qos.outbound_peak or "") + self.widget("qos-outbound-burst").set_text(qos.outbound_burst or "") + def populate_net_state(self, net): active = net.is_active() @@ -644,6 +719,7 @@ class vmmHost(vmmGObjectUI): self._populate_net_ipv4_state(net) self._populate_net_ipv6_state(net) + self._populate_qos_state(net) def reset_net_state(self): diff --git a/virtManager/network.py b/virtManager/network.py index 163a0c0..4ad4c94 100644 --- a/virtManager/network.py +++ b/virtManager/network.py @@ -1,5 +1,5 @@ # -# Copyright (C) 2006, 2013 Red Hat, Inc. +# Copyright (C) 2006, 2013-2014 Red Hat, Inc. # Copyright (C) 2006 Daniel P. Berrange <berrange@xxxxxxxxxx> # # This program is free software; you can redistribute it and/or modify @@ -121,6 +121,17 @@ class vmmNetwork(vmmLibvirtObject): def tick(self): self.force_update_status() + def set_qos(self, **kwargs): + q = self.get_qos() + for key, val in kwargs.items(): + setattr(q, key, val) + + xml = self.get_xml() + + self._redefine_xml(xml) + return self.is_active() + + def define_name(self, newname): return self._define_name_helper("network", self.conn.rename_network, @@ -143,6 +154,8 @@ class vmmNetwork(vmmLibvirtObject): return self.get_xmlobj().forward.mode def pretty_forward_mode(self): return self.get_xmlobj().forward.pretty_desc() + def get_qos(self): + return self.get_xmlobj().bandwidth def can_pxe(self): return self.get_xmlobj().can_pxe() -- 1.9.3 _______________________________________________ virt-tools-list mailing list virt-tools-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/virt-tools-list