Add UI elements to specify QoS when creating a new network Signed-off-by: Giuseppe Scrivano <gscrivan@xxxxxxxxxx> --- ui/createnet.ui | 292 +++++++++++++++++++++++++++++++++++++++++++++++ virtManager/createnet.py | 107 ++++++++++++++++- 2 files changed, 397 insertions(+), 2 deletions(-) diff --git a/ui/createnet.ui b/ui/createnet.ui index 1596241..ccd0876 100644 --- a/ui/createnet.ui +++ b/ui/createnet.ui @@ -1440,6 +1440,298 @@ <property name="tab_fill">False</property> </packing> </child> + <child> + <object class="GtkVBox" id="vbox1"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="spacing">6</property> + <child> + <object class="GtkLabel" id="label8"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="xalign">0</property> + <property name="label" translatable="yes"><b>Quality of Service</b></property> + <property name="use_markup">True</property> + <property name="wrap">True</property> + <property name="max_width_chars">50</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkAlignment" id="alignment5"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="left_padding">15</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="grid3"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <child> + <object class="GtkEntry" id="qos-inbound-peak"> + <property name="visible">True</property> + <property name="can_focus">True</property> + </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> + </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-inbound-floor"> + <property name="visible">True</property> + <property name="can_focus">True</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">3</property> + <property name="width">1</property> + <property name="height">1</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="label9"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Average (kilobytes/second):</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="label10"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Burst (kilobytes):</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> + </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="label15"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Peak (kilobytes/second):</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="label16"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Floor (kilobytes/second):</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">3</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="grid4"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <child> + <object class="GtkEntry" id="qos-outbound-peak"> + <property name="visible">True</property> + <property name="can_focus">True</property> + </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> + </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> + </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="label18"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Burst (kilobytes):</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="label21"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Peak (kilobytes/second):</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="label17"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Average (kilobytes/second):</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> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="position">4</property> + </packing> + </child> + <child type="tab"> + <object class="GtkLabel" id="label1"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">QoS</property> + </object> + <packing> + <property name="position">4</property> + <property name="tab_fill">False</property> + </packing> + </child> </object> <packing> <property name="expand">True</property> diff --git a/virtManager/createnet.py b/virtManager/createnet.py index 0bc2fd6..d4bc063 100644 --- a/virtManager/createnet.py +++ b/virtManager/createnet.py @@ -35,7 +35,10 @@ from virtManager.baseclass import vmmGObjectUI (PAGE_NAME, PAGE_IPV4, PAGE_IPV6, -PAGE_MISC) = range(4) +PAGE_MISC, +PAGE_QOS) = range(5) + +PAGE_MAX = PAGE_QOS _green = Gdk.Color.parse("#c0ffc0")[1] _red = Gdk.Color.parse("#ffc0c0")[1] @@ -87,6 +90,9 @@ class vmmCreateNetwork(vmmGObjectUI): "on_net-routev6-enable_toggled": self.change_routev6_enable, "on_net-routev6-network_changed": self.change_routev6_network, "on_net-routev6-gateway_changed": self.change_routev6_gateway, + + "on_net-qos-inbound-enable_toggled": self.change_qos_in_enable, + "on_net-qos-outbound-enable_toggled": self.change_qos_out_enable, }) self.bind_escape_key_close() @@ -185,6 +191,18 @@ class vmmCreateNetwork(vmmGObjectUI): self.widget("net-forward-none").set_active(True) + self.widget("net-qos-inbound-enable").set_active(False) + self.widget("qos-inbound-average").set_sensitive(False) + self.widget("qos-inbound-peak").set_sensitive(False) + self.widget("qos-inbound-burst").set_sensitive(False) + self.widget("qos-inbound-floor").set_sensitive(False) + + self.widget("net-qos-outbound-enable").set_active(False) + self.widget("qos-outbound-average").set_sensitive(False) + self.widget("qos-outbound-peak").set_sensitive(False) + self.widget("qos-outbound-burst").set_sensitive(False) + + ################## # UI get helpers # ################## @@ -201,6 +219,25 @@ class vmmCreateNetwork(vmmGObjectUI): return self.widget("net-routev4-enable").get_active() def get_config_routev6_enable(self): return self.widget("net-routev6-enable").get_active() + def get_config_inbound_qos_enable(self): + return self.widget("net-qos-inbound-enable").get_active() + def get_config_outbound_qos_enable(self): + return self.widget("net-qos-outbound-enable").get_active() + + def get_config_inbound_average(self): + return self.widget("qos-inbound-average").get_text() + def get_config_inbound_peak(self): + return self.widget("qos-inbound-peak").get_text() + def get_config_inbound_burst(self): + return self.widget("qos-inbound-burst").get_text() + def get_config_inbound_floor(self): + return self.widget("qos-inbound-floor").get_text() + def get_config_outbound_average(self): + return self.widget("qos-outbound-average").get_text() + def get_config_outbound_peak(self): + return self.widget("qos-outbound-peak").get_text() + def get_config_outbound_burst(self): + return self.widget("qos-outbound-burst").get_text() def _get_network_helper(self, widgetname): widget = self.widget(widgetname) @@ -435,6 +472,41 @@ class vmmCreateNetwork(vmmGObjectUI): return True + def validate_qos(self): + def check(val, err): + if len(val) and not val.isdigit(): + return self.err.val_err(err) + return True + + inbound_qos_enable = self.get_config_inbound_qos_enable() + if inbound_qos_enable: + if not check(self.get_config_inbound_average(), + _("Invalid value for inbound average")): + return False + if not check(self.get_config_inbound_peak(), + _("Invalid value for inbound peak")): + return False + if not check(self.get_config_inbound_burst(), + _("Invalid value for inbound burst")): + return False + if not check(self.get_config_inbound_floor(), + _("Invalid value for inbound floor")): + return False + + outbound_qos_enable = self.get_config_outbound_qos_enable() + if outbound_qos_enable: + if not check(self.get_config_outbound_average(), + _("Invalid value for outbound average")): + return False + if not check(self.get_config_outbound_peak(), + _("Invalid value for outbound peak")): + return False + if not check(self.get_config_outbound_burst(), + _("Invalid value for outbound burst")): + return False + + return True + def validate(self, page_num): if page_num == PAGE_NAME: return self.validate_name() @@ -444,6 +516,8 @@ class vmmCreateNetwork(vmmGObjectUI): return self.validate_ipv6() elif page_num == PAGE_MISC: return self.validate_miscellaneous() + elif page_num == PAGE_QOS: + return self.validate_qos() return True @@ -467,7 +541,7 @@ class vmmCreateNetwork(vmmGObjectUI): page_lbl = ("<span color='#59B0E2'>%s</span>" % _("Step %(current_page)d of %(max_page)d") % {'current_page': page_number + 1, - 'max_page': PAGE_MISC + 1}) + 'max_page': PAGE_MAX}) self.widget("header-pagenum").set_markup(page_lbl) if page_number == PAGE_NAME: @@ -527,6 +601,20 @@ class vmmCreateNetwork(vmmGObjectUI): uiutil.set_grid_row_visible(start, enabled) uiutil.set_grid_row_visible(end, enabled) + def change_qos_in_enable(self, ignore): + enabled = self.get_config_inbound_qos_enable() + self.widget("qos-inbound-average").set_sensitive(enabled) + self.widget("qos-inbound-peak").set_sensitive(enabled) + self.widget("qos-inbound-burst").set_sensitive(enabled) + self.widget("qos-inbound-floor").set_sensitive(enabled) + + def change_qos_out_enable(self, ignore): + enabled = self.get_config_outbound_qos_enable() + self.widget("qos-outbound-average").set_sensitive(enabled) + self.widget("qos-outbound-peak").set_sensitive(enabled) + self.widget("qos-outbound-burst").set_sensitive(enabled) + + def change_dhcpv4_start(self, src): start = self.get_config_dhcpv4_start() self.change_dhcpv4(src, start) @@ -735,6 +823,21 @@ class vmmCreateNetwork(vmmGObjectUI): route.prefix = netaddr.prefixlen route.gateway = gwaddr.network + inbound_qos_enable = self.get_config_inbound_qos_enable() + outbound_qos_enable = self.get_config_outbound_qos_enable() + if inbound_qos_enable or outbound_qos_enable: + b = net.bandwidth + if inbound_qos_enable: + b.inbound_average = self.get_config_inbound_average() or None + b.inbound_peak = self.get_config_inbound_peak() or None + b.inbound_burst = self.get_config_inbound_burst() or None + b.inbound_floor = self.get_config_inbound_floor() or None + + if outbound_qos_enable: + b.outbound_average = self.get_config_outbound_average() or None + b.outbound_peak = self.get_config_outbound_peak() or None + b.outbound_burst = self.get_config_outbound_burst() or None + return net def _finish_cb(self, error, details): -- 1.9.3 _______________________________________________ virt-tools-list mailing list virt-tools-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/virt-tools-list