1
0
Fork 0
mirror of https://github.com/retspen/webvirtcloud synced 2025-01-24 06:05:20 +00:00

instance network revamped. Qos config for instance net is added

This commit is contained in:
catborise 2019-11-20 08:37:59 +03:00
parent 718388ffef
commit ddd3dd5f65
4 changed files with 314 additions and 90 deletions

View file

@ -851,25 +851,47 @@
</p> </p>
<div class="col-xs-12 col-sm-12"> <div class="col-xs-12 col-sm-12">
<form method="post" role="form">{% csrf_token %}
{% for network in networks %}
{% if forloop.first %}
<p><strong>{% trans "Network Devices" %}</strong></p> <p><strong>{% trans "Network Devices" %}</strong></p>
{% endif %} <table class="table table-hover">
<div class="panel panel-default"> <thead>
<div class="panel-heading"> <tr>
<label>eth{{ forloop.counter0 }}({{ network.target|default:"no target" }})</label> <th>{% trans 'Name' %}</th>
<button class="btn btn-sm pull-right btn-danger" value="{{ network.mac }}" name="delete_network" title="{% trans "Delete Device" %}" onclick="return confirm('{% trans "Are you sure?" %}')">{% trans "Delete" %}</button> <th>{% trans 'MAC' %}</th>
<th>{% trans 'NIC' %}</th>
<th>{% trans 'Filter' %}</th>
<th>{% trans 'Actions' %}</th>
</tr>
</thead>
<tbody>
{% 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 class="col-sm-2">
<form class="form-horizontal" method="post" name="set_qos{{ forloop.counter0 }}" role="form">{% csrf_token %}
<button data-target="#editInstanceNetwork{{ forloop.counter0 }}" type="button" class="btn btn-sm btn-primary"
title="Edit NIC" data-toggle="modal">
<span class="glyphicon glyphicon-edit" aria-hidden="true"></span>
</button>
<div class="modal fade" id="editInstanceNetwork{{ forloop.counter0 }}" role="dialog" aria-labelledby="editInstanceNetworkLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h4 class="modal-title">{% trans "Edit Instance Network" %}</h4>
</div> </div>
<div class="panel-body"> <div class="modal-body">
<div class="form-group form-inline"> <div class="form-group form-inline">
<label class="col-sm-2 col-sm-offset-1 control-label">{% trans "MAC" %} </label> <label class="col-sm-2 control-label">{% trans "MAC" %} </label>
<input class="form-control" type="text" value="{{ network.mac }}" readonly/> <input class="form-control" type="text" value="{{ network.mac }}" readonly/>
<label class="control-label"><em>to</em></label> <label class="control-label"><em>to</em></label>
<input class="form-control" type="text" name="net-mac-{{ forloop.counter0 }}" value="{{ network.mac }}"/> <input class="form-control" type="text" name="net-mac-{{ forloop.counter0 }}" value="{{ network.mac }}"/>
</div> </div>
<div class="form-group form-inline"> <div class="form-group form-inline">
<label class="col-sm-2 col-sm-offset-1 control-label">{% trans "NIC" %} </label> <label class="col-sm-2 control-label">{% trans "NIC" %} </label>
<input class="form-control" type="text" value="{{ network.nic }}" readonly/> <input class="form-control" type="text" value="{{ network.nic }}" readonly/>
<label class="control-label"><em>to</em></label> <label class="control-label"><em>to</em></label>
<select class="form-control" name="net-source-{{ forloop.counter0 }}"> <select class="form-control" name="net-source-{{ forloop.counter0 }}">
@ -882,7 +904,7 @@
</select> </select>
</div> </div>
<div class="form-group form-inline"> <div class="form-group form-inline">
<label class="col-sm-2 col-sm-offset-1">{% trans "Filter" %} </label> <label class="col-sm-2 control-label">{% trans "Filter" %} </label>
<input class="form-control" type="text" value="{{ network.filterref }}" readonly/> <input class="form-control" type="text" value="{{ network.filterref }}" readonly/>
<label class="control-label"><em>to</em></label> <label class="control-label"><em>to</em></label>
<select class="form-control" name="net-nwfilter-{{ forloop.counter0 }}"> <select class="form-control" name="net-nwfilter-{{ forloop.counter0 }}">
@ -895,9 +917,73 @@
<button class="btn btn-sm btn-primary btn-block" name="change_network" title="{% trans "Apply Network Changes" %}">{% trans "Apply" %}</button> <button class="btn btn-sm btn-primary btn-block" name="change_network" title="{% trans "Apply Network Changes" %}">{% trans "Apply" %}</button>
</div> </div>
</div> </div>
{% endfor %}
</form>
</div> </div>
</div>
<button class="btn btn-sm btn-danger" value="{{ network.mac }}" name="delete_network" title="{% trans "Delete Device" %}"
onclick="return confirm('{% trans "Are you sure?" %}')">
<i class="glyphicon glyphicon-trash"></i>
</button>
{% include 'add_network_qos.html' with id=forloop.counter0 %}
</form>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% if qos %}
<div class="col-xs-10 col-sm-10">
<p><strong>{% trans "Qos Configuration" %}</strong></p>
</div>
<div class="col-xs-12 col-sm-12">
<table class="table table-hover">
<thead>
<tr>
<th>{% trans "Direction" %}</th>
<th>{% trans "Average" %}</th>
<th>{% trans "Peak" %}</th>
<th>{% trans "Burst" %}</th>
<th>{% trans "Actions" %}</th>
</tr>
</thead>
<tbody>
{% for q, attrs in qos.items %}
{% for att in attrs %}
<form method="post" role="form">{% csrf_token %}
<tr>
<td><label class="control-label">{{ q }} {{ att.direction | capfirst }}</label></td>
<td><input id="qos_average" class="form-control" name="qos_average"
value="{{ att.average|default:'' }}"/></td>
<td><input id="qos_peak" class="form-control" name="qos_peak"
value="{{ att.peak|default:'' }}"/></td>
<td><input id="qos_burst" class="form-control" name="qos_burst"
value="{{ att.burst|default:'' }}"/></td>
<td class="col-sm-2">
<input name="qos_direction" value="{{ att.direction }}" hidden/>
<input name="net-mac" value="{{ q }}" hidden/>
<button type="submit" class="btn btn-sm btn-primary"
name="set_qos" data-toggle="modal"
title="Edit Qos" onclick="return confirm('{% trans "Are you sure?" %}')">
<i class="glyphicon glyphicon-save"></i>
</button>
<button type="submit" class="btn btn-sm btn-danger"
name="unset_qos"
title="Delete Qos" onclick="return confirm('{% trans "Are you sure?" %}')">
<i class="glyphicon glyphicon-trash"></i>
</button>
</td>
</tr>
</form>
{% endfor %}
{% endfor %}
</tbody>
</table>
</div>
{% endif %}
<div class="clearfix"></div> <div class="clearfix"></div>
</div> </div>
<div role="tabpanel" class="tab-pane tab-pane-bordered" id="migrate"> <div role="tabpanel" class="tab-pane tab-pane-bordered" id="migrate">

View file

@ -272,6 +272,7 @@ def instance(request, compute_id, vname):
title = conn.get_title() title = conn.get_title()
description = conn.get_description() description = conn.get_description()
networks = conn.get_net_device() networks = conn.get_net_device()
qos = conn.get_all_qos()
disks = conn.get_disk_devices() disks = conn.get_disk_devices()
media = conn.get_media_devices() media = conn.get_media_devices()
if len(media) != 0: if len(media) != 0:
@ -482,8 +483,9 @@ def instance(request, compute_id, vname):
addlogmsg(request.user.username, instance.name, msg) addlogmsg(request.user.username, instance.name, msg)
return HttpResponseRedirect(request.get_full_path() + '#resize') return HttpResponseRedirect(request.get_full_path() + '#resize')
if 'resizevm_mem' in request.POST and ( if 'resizevm_mem' in request.POST and (request.user.is_superuser or
request.user.is_superuser or request.user.is_staff or userinstance.is_change): request.user.is_staff or
userinstance.is_change):
new_memory = request.POST.get('memory', '') new_memory = request.POST.get('memory', '')
new_memory_custom = request.POST.get('memory_custom', '') new_memory_custom = request.POST.get('memory_custom', '')
if new_memory_custom: if new_memory_custom:
@ -699,7 +701,8 @@ def instance(request, compute_id, vname):
msg = _("Set boot order") msg = _("Set boot order")
if not conn.get_status() == 5: if not conn.get_status() == 5:
messages.success(request, _("Boot menu changes applied. But it will be activated after shutdown")) messages.success(request, _("Boot menu changes applied. " +
"But it will be activated after shutdown"))
else: else:
messages.success(request, _("Boot order changed successfully.")) messages.success(request, _("Boot order changed successfully."))
addlogmsg(request.user.username, instance.name, msg) addlogmsg(request.user.username, instance.name, msg)
@ -727,7 +730,8 @@ def instance(request, compute_id, vname):
error_messages.append(msg) error_messages.append(msg)
if not error_messages: if not error_messages:
if not conn.set_console_passwd(passwd): if not conn.set_console_passwd(passwd):
msg = _("Error setting console password. You should check that your instance have an graphic device.") msg = _("Error setting console password. " +
"You should check that your instance have an graphic device.")
error_messages.append(msg) error_messages.append(msg)
else: else:
msg = _("Set VNC password") msg = _("Set VNC password")
@ -808,6 +812,40 @@ def instance(request, compute_id, vname):
addlogmsg(request.user.username, instance.name, msg) addlogmsg(request.user.username, instance.name, msg)
return HttpResponseRedirect(request.get_full_path() + '#network') 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
peak = request.POST.get('qos_peak') or 0
burst = request.POST.get('qos_burst') or 0
keys = request.POST.keys()
mac_key = [key for key in keys if 'mac' in key]
if mac_key: mac = request.POST.get(mac_key[0])
try:
conn.set_qos(mac, qos_dir, average, peak, burst)
if conn.get_status() == 5:
messages.success(request, "{} Qos is set".format(qos_dir.capitalize()))
else:
messages.success(request,
"{} Qos is set. Network XML is changed.".format(qos_dir.capitalize()) +
"Stop and start network to activate new config")
except libvirtError as le:
messages.error(request, le.message)
return HttpResponseRedirect(request.get_full_path() + '#network')
if 'unset_qos' in request.POST:
qos_dir = request.POST.get('qos_direction', '')
mac = request.POST.get('net-mac')
conn.unset_qos(mac, qos_dir)
if conn.get_status() == 5:
messages.success(request, "{} Qos is deleted".format(qos_dir.capitalize()))
else:
messages.success(request,
"{} Qos is deleted. Network XML is changed. ".format(qos_dir.capitalize()) +
"Stop and start network to activate new config.")
return HttpResponseRedirect(request.get_full_path() + '#network')
if 'add_owner' in request.POST: if 'add_owner' in request.POST:
user_id = int(request.POST.get('user_id', '')) user_id = int(request.POST.get('user_id', ''))

View file

@ -1,11 +1,11 @@
{% load i18n %} {% load i18n %}
{% if request.user.is_superuser %} {% if request.user.is_superuser %}
<a href="#AddQos" type="button" class="btn btn-sm btn-success pull-right" data-toggle="modal" title="add qos"> <a href="#AddQos{{ id }}" type="button" class="btn btn-sm btn-success pull-right" data-toggle="modal" title="add qos">
<span class="glyphicon glyphicon-plus" aria-hidden="true"></span> <span class="glyphicon glyphicon-plus" aria-hidden="true"></span>
</a> </a>
<!-- Modal pool --> <!-- Modal pool -->
<div class="modal fade" id="AddQos" tabindex="-1" role="dialog" aria-labelledby="AddQosLabel" <div class="modal fade" id="AddQos{{ id }}" tabindex="-1" role="dialog" aria-labelledby="AddQosLabel"
aria-hidden="true"> aria-hidden="true">
<div class="modal-dialog"> <div class="modal-dialog">
<div class="modal-content"> <div class="modal-content">
@ -14,7 +14,6 @@
<h4 class="modal-title">{% trans "Add Inbound Qos for Network" %}</h4> <h4 class="modal-title">{% trans "Add Inbound Qos for Network" %}</h4>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<form class="form-horizontal" method="post" name="set_qos" role="form">{% csrf_token %}
<div class="form-group"> <div class="form-group">
<label class="col-sm-4 control-label">{% trans "Direction" %}:</label> <label class="col-sm-4 control-label">{% trans "Direction" %}:</label>
<div class="col-sm-6"> <div class="col-sm-6">
@ -27,32 +26,30 @@
<div class="form-group"> <div class="form-group">
<label class="col-sm-4 control-label">{% trans "Average" %}:</label> <label class="col-sm-4 control-label">{% trans "Average" %}:</label>
<div class="col-sm-6"> <div class="col-sm-6">
<input class="form-control" name="qos_inbound_average" placeholder="kilobytes" <input class="form-control" name="qos_average" placeholder="kilobytes"
required pattern="[0-9]+"/> required pattern="[0-9]+"/>
</div> </div>
</div> </div>
<div class="form-group"> <div class="form-group">
<label class="col-sm-4 control-label">{% trans "Peak" %}:</label> <label class="col-sm-4 control-label">{% trans "Peak" %}:</label>
<div class="col-sm-6"> <div class="col-sm-6">
<input class="form-control" name="qos_inbound_peak" placeholder="kilobytes" <input class="form-control" name="qos_peak" placeholder="kilobytes"
required pattern="[0-9]+"/> pattern="[0-9]+"/>
</div> </div>
</div> </div>
<div class="form-group"> <div class="form-group">
<label class="col-sm-4 control-label">{% trans "Burst" %}:</label> <label class="col-sm-4 control-label">{% trans "Burst" %}:</label>
<div class="col-sm-6"> <div class="col-sm-6">
<input class="form-control" name="qos_inbound_burst" placeholder="kilobytes" <input class="form-control" name="qos_burst" placeholder="kilobytes"
required pattern="[0-9]+"/> pattern="[0-9]+"/>
</div> </div>
</div> </div>
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">{% trans 'Close' %}</button> <button type="button" class="btn btn-default" data-dismiss="modal">{% trans 'Close' %}</button>
<button type="submit" class="btn btn-primary" name="set_qos">{% trans 'Save' %}</button> <button type="submit" class="btn btn-primary" name="set_qos">{% trans 'Save' %}</button>
</div> </div>
</form>
</div> </div>
</div> <!-- /.modal-dialog --> </div> <!-- /.modal-dialog -->
</div> <!-- /.modal --> </div> <!-- /.modal -->

View file

@ -7,6 +7,7 @@ except:
from libvirt import libvirtError, VIR_DOMAIN_XML_SECURE, VIR_MIGRATE_LIVE from libvirt import libvirtError, VIR_DOMAIN_XML_SECURE, VIR_MIGRATE_LIVE
from vrtManager import util from vrtManager import util
from xml.etree import ElementTree from xml.etree import ElementTree
from lxml import etree
from datetime import datetime from datetime import datetime
from vrtManager.connection import wvmConnect from vrtManager.connection import wvmConnect
from vrtManager.storage import wvmStorage from vrtManager.storage import wvmStorage
@ -157,6 +158,12 @@ class wvmInstance(wvmConnect):
return self.wvm.defineXML(xml) return self.wvm.defineXML(xml)
def get_status(self): def get_status(self):
"""
VIR_DOMAIN_NOSTATE = 0
VIR_DOMAIN_RUNNING = 1
VIR_DOMAIN_PAUSED = 3
VIR_DOMAIN_SHUTOFF = 5
"""
return self.instance.info()[0] return self.instance.info()[0]
def get_autostart(self): def get_autostart(self):
@ -229,17 +236,38 @@ class wvmInstance(wvmConnect):
def networks(ctx): def networks(ctx):
result = [] result = []
inbound = outbound = []
for net in ctx.xpath('/domain/devices/interface'): for net in ctx.xpath('/domain/devices/interface'):
mac_host = net.xpath('mac/@address')[0] mac_inst = net.xpath('mac/@address')[0]
network_host = net.xpath('source/@network|source/@bridge|source/@dev')[0] nic_inst = net.xpath('source/@network|source/@bridge|source/@dev')[0]
target_host = '' if not net.xpath('target/@dev') else net.xpath('target/@dev')[0] target_inst = '' if not net.xpath('target/@dev') else net.xpath('target/@dev')[0]
filterref_host = '' if not net.xpath('filterref/@filter') else net.xpath('filterref/@filter')[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]
in_av = in_attr.get('average')
in_peak = in_attr.get('peak')
in_burst = in_attr.get('burst')
inbound = {'average': in_av, 'peak': in_peak, 'burst': in_burst}
if net.xpath('bandwidth/outbound'):
out_attr = net.xpath('bandwidth/outbound')[0]
out_av = out_attr.get('average')
out_peak = out_attr.get('peak')
out_burst = out_attr.get('burst')
outbound = {'average': out_av, 'peak': out_peak, 'burst': out_burst}
try: try:
net = self.get_network(network_host) net = self.get_network(nic_inst)
ip = get_mac_ipaddr(net, mac_host) ip = get_mac_ipaddr(net, mac_inst)
except libvirtError: except libvirtError:
ip = None ip = None
result.append({'mac': mac_host, 'nic': network_host, 'target': target_host, 'ip': ip, 'filterref': filterref_host}) result.append({'mac': mac_inst,
'nic': nic_inst,
'target': target_inst,
'ip': ip,
'filterref': filterref_inst,
'inbound': inbound,
'outbound': outbound,
})
return result return result
return util.get_xml_path(self._XMLDesc(0), func=networks) return util.get_xml_path(self._XMLDesc(0), func=networks)
@ -680,8 +708,7 @@ class wvmInstance(wvmConnect):
def get_console_port(self, console_type=None): def get_console_port(self, console_type=None):
if console_type is None: if console_type is None:
console_type = self.get_console_type() console_type = self.get_console_type()
port = util.get_xml_path(self._XMLDesc(0), port = util.get_xml_path(self._XMLDesc(0), "/domain/devices/graphics[@type='%s']/@port" % console_type)
"/domain/devices/graphics[@type='%s']/@port" % console_type)
return port return port
def get_console_websocket_port(self): def get_console_websocket_port(self):
@ -691,8 +718,7 @@ class wvmInstance(wvmConnect):
return websocket_port return websocket_port
def get_console_passwd(self): def get_console_passwd(self):
return util.get_xml_path(self._XMLDesc(VIR_DOMAIN_XML_SECURE), return util.get_xml_path(self._XMLDesc(VIR_DOMAIN_XML_SECURE), "/domain/devices/graphics/@passwd")
"/domain/devices/graphics/@passwd")
def set_console_passwd(self, passwd): def set_console_passwd(self, passwd):
xml = self._XMLDesc(VIR_DOMAIN_XML_SECURE) xml = self._XMLDesc(VIR_DOMAIN_XML_SECURE)
@ -735,8 +761,7 @@ class wvmInstance(wvmConnect):
self._defineXML(newxml) self._defineXML(newxml)
def get_console_keymap(self): def get_console_keymap(self):
return util.get_xml_path(self._XMLDesc(VIR_DOMAIN_XML_SECURE), return util.get_xml_path(self._XMLDesc(VIR_DOMAIN_XML_SECURE), "/domain/devices/graphics/@keymap") or ''
"/domain/devices/graphics/@keymap") or ''
def resize(self, cur_memory, memory, cur_vcpu, vcpu, disks=[]): def resize(self, cur_memory, memory, cur_vcpu, vcpu, disks=[]):
""" """
@ -1007,25 +1032,34 @@ class wvmInstance(wvmConnect):
bridge_name = net.bridgeName() bridge_name = net.bridgeName()
return bridge_name return bridge_name
def add_network(self, mac_address, source, source_type='net', interface_type='bridge', model='virtio', nwfilter=None): def add_network(self, mac_address, source, source_type='net', model='virtio', nwfilter=None):
bridge_name = self.get_bridge_name(source, source_type) bridge_name = self.get_bridge_name(source, source_type)
xml_interface = """
forward_mode = self.get_network_forward(source)
if forward_mode in ['nat', 'isolated', 'routed']:
interface_type = 'network'
else:
interface_type = 'bridge'
xml_iface = """
<interface type='%s'> <interface type='%s'>
<mac address='%s'/> <mac address='%s'/>""" % (interface_type, mac_address)
<source bridge='%s'/> if interface_type == 'network':
<model type='%s'/> xml_iface += """<source network='%s'/>""" % source
""" % (interface_type, mac_address, bridge_name, model) else:
xml_iface += """<source bridge='%s'/>""" % bridge_name
xml_iface += """<model type='%s'/>""" % model
if nwfilter: if nwfilter:
xml_interface += """ xml_iface += """
<filterref filter='%s'/> <filterref filter='%s'/>
""" % nwfilter """ % nwfilter
xml_interface += """</interface>""" xml_iface += """</interface>"""
if self.get_status() == 1: if self.get_status() == 1:
self.instance.attachDeviceFlags(xml_interface, VIR_DOMAIN_AFFECT_LIVE) self.instance.attachDeviceFlags(xml_iface, VIR_DOMAIN_AFFECT_LIVE)
self.instance.attachDeviceFlags(xml_interface, VIR_DOMAIN_AFFECT_CONFIG) self.instance.attachDeviceFlags(xml_iface, VIR_DOMAIN_AFFECT_CONFIG)
if self.get_status() == 5: if self.get_status() == 5:
self.instance.attachDeviceFlags(xml_interface, VIR_DOMAIN_AFFECT_CONFIG) self.instance.attachDeviceFlags(xml_iface, VIR_DOMAIN_AFFECT_CONFIG)
def delete_network(self, mac_address): def delete_network(self, mac_address):
tree = ElementTree.fromstring(self._XMLDesc(0)) tree = ElementTree.fromstring(self._XMLDesc(0))
@ -1044,10 +1078,11 @@ class wvmInstance(wvmConnect):
xml = self._XMLDesc(VIR_DOMAIN_XML_SECURE) xml = self._XMLDesc(VIR_DOMAIN_XML_SECURE)
tree = ElementTree.fromstring(xml) tree = ElementTree.fromstring(xml)
for num, interface in enumerate(tree.findall('devices/interface')): for num, interface in enumerate(tree.findall('devices/interface')):
net_source = network_data['net-source-' + str(num)] net_mac = network_data.get('net-mac-' + str(num))
net_source_type = network_data['net-source-' + str(num) + '-type'] if net_mac is None: continue
net_mac = network_data['net-mac-' + str(num)] net_source = network_data.get('net-source-' + str(num))
net_filter = network_data['net-nwfilter-' + str(num)] net_source_type = network_data.get('net-source-' + str(num) + '-type')
net_filter = network_data.get('net-nwfilter-' + str(num))
bridge_name = self.get_bridge_name(net_source, net_source_type) bridge_name = self.get_bridge_name(net_source, net_source_type)
if interface.get('type') == 'bridge': if interface.get('type') == 'bridge':
source = interface.find('mac') source = interface.find('mac')
@ -1103,10 +1138,78 @@ class wvmInstance(wvmConnect):
tree = ElementTree.fromstring(xml) tree = ElementTree.fromstring(xml)
self._set_options(tree, options) self._set_options(tree, options)
new_xml = ElementTree.tostring(tree) new_xml = ElementTree.tostring(tree)
self._defineXML(new_xml) self._defineXML(new_xml)
def set_memory(self, size, flags=0): def set_memory(self, size, flags=0):
self.instance.setMemoryFlags(size, flags) self.instance.setMemoryFlags(size, flags)
def get_all_qos(self):
qos_values = dict()
tree = etree.fromstring(self._XMLDesc(0))
qos = tree.xpath("/domain/devices/interface")
for q in qos:
bound_list = list()
mac = q.xpath('mac/@address')
band = q.find('bandwidth')
if band is not None:
in_qos = band.find('inbound')
if in_qos is not None:
in_av = in_qos.get('average')
in_peak = in_qos.get('peak')
in_burst = in_qos.get('burst')
in_floor = in_qos.get('floor')
bound_list.append({'direction': 'inbound', 'average': in_av, 'peak': in_peak, 'floor': in_floor, 'burst': in_burst})
out_qos = band.find('outbound')
if out_qos is not None:
out_av = out_qos.get('average')
out_peak = out_qos.get('peak')
out_burst = out_qos.get('burst')
bound_list.append({'direction': 'outbound', 'average': out_av, 'peak': out_peak, 'burst': out_burst})
qos_values[mac[0]] = bound_list
return qos_values
def set_qos(self, mac, direction, average, peak, burst):
if direction == "inbound":
xml = "<inbound average='{}' peak='{}' burst='{}'/>".format(average, peak, burst)
elif direction == "outbound":
xml = "<outbound average='{}' peak='{}' burst='{}'/>".format(average, peak, burst)
else:
raise Exception('Direction must be inbound or outbound')
tree = etree.fromstring(self._XMLDesc(0))
macs = tree.xpath("/domain/devices/interface/mac")
for cur_mac in macs:
if cur_mac.get("address") == mac:
interface = cur_mac.getparent()
band = interface.find('bandwidth')
if band is None:
xml = "<bandwidth>" + xml + "</bandwidth>"
interface.append(etree.fromstring(xml))
else:
direct = band.find(direction)
if direct is not None:
parent = direct.getparent()
parent.remove(direct)
parent.append(etree.fromstring(xml))
else:
band.append(etree.fromstring(xml))
new_xml = etree.tostring(tree)
self.wvm.defineXML(new_xml)
def unset_qos(self, mac, direction):
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
parent_mac = interface_el.xpath('mac/@address')
if parent_mac[0] == mac:
band_el.remove(direct)
self.wvm.defineXML(etree.tostring(tree))