mirror of
https://github.com/GNS3/gns3-server
synced 2024-11-28 03:08:14 +00:00
Improve suspend a link for Qemu and VirtualBox VMs.
A suspended link will be unplugged allowing the VMs to be notified of the change.
This commit is contained in:
parent
cde30f8f53
commit
8b91894fa4
@ -418,8 +418,9 @@ class BaseManager:
|
|||||||
sock.connect(sa)
|
sock.connect(sa)
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
raise aiohttp.web.HTTPInternalServerError(text="Could not create an UDP connection to {}:{}: {}".format(rhost, rport, e))
|
raise aiohttp.web.HTTPInternalServerError(text="Could not create an UDP connection to {}:{}: {}".format(rhost, rport, e))
|
||||||
filters = nio_settings.get("filters", {})
|
nio = NIOUDP(lport, rhost, rport)
|
||||||
nio = NIOUDP(lport, rhost, rport, filters)
|
nio.filters = nio_settings.get("filters", {})
|
||||||
|
nio.suspend = nio_settings.get("suspend", False)
|
||||||
elif nio_settings["type"] == "nio_tap":
|
elif nio_settings["type"] == "nio_tap":
|
||||||
tap_device = nio_settings["tap_device"]
|
tap_device = nio_settings["tap_device"]
|
||||||
# if not is_interface_up(tap_device):
|
# if not is_interface_up(tap_device):
|
||||||
|
@ -39,6 +39,8 @@ class NIO:
|
|||||||
|
|
||||||
self._hypervisor = hypervisor
|
self._hypervisor = hypervisor
|
||||||
self._name = name
|
self._name = name
|
||||||
|
self._filters = {}
|
||||||
|
self._suspended = False
|
||||||
self._bandwidth = None # no bandwidth constraint by default
|
self._bandwidth = None # no bandwidth constraint by default
|
||||||
self._input_filter = None # no input filter applied by default
|
self._input_filter = None # no input filter applied by default
|
||||||
self._output_filter = None # no output filter applied by default
|
self._output_filter = None # no output filter applied by default
|
||||||
@ -236,6 +238,47 @@ class NIO:
|
|||||||
yield from self._hypervisor.send("nio set_bandwidth {name} {bandwidth}".format(name=self._name, bandwidth=bandwidth))
|
yield from self._hypervisor.send("nio set_bandwidth {name} {bandwidth}".format(name=self._name, bandwidth=bandwidth))
|
||||||
self._bandwidth = bandwidth
|
self._bandwidth = bandwidth
|
||||||
|
|
||||||
|
@property
|
||||||
|
def suspend(self):
|
||||||
|
"""
|
||||||
|
Returns if this link is suspended or not.
|
||||||
|
|
||||||
|
:returns: boolean
|
||||||
|
"""
|
||||||
|
|
||||||
|
return self._suspended
|
||||||
|
|
||||||
|
@suspend.setter
|
||||||
|
def suspend(self, suspended):
|
||||||
|
"""
|
||||||
|
Suspend this link.
|
||||||
|
|
||||||
|
:param suspended: boolean
|
||||||
|
"""
|
||||||
|
|
||||||
|
self._suspended = suspended
|
||||||
|
|
||||||
|
@property
|
||||||
|
def filters(self):
|
||||||
|
"""
|
||||||
|
Returns the list of packet filters for this NIO.
|
||||||
|
|
||||||
|
:returns: packet filters (dictionary)
|
||||||
|
"""
|
||||||
|
|
||||||
|
return self._filters
|
||||||
|
|
||||||
|
@filters.setter
|
||||||
|
def filters(self, new_filters):
|
||||||
|
"""
|
||||||
|
Set a list of packet filters for this NIO.
|
||||||
|
|
||||||
|
:param new_filters: packet filters (dictionary)
|
||||||
|
"""
|
||||||
|
|
||||||
|
assert isinstance(new_filters, dict)
|
||||||
|
self._filters = new_filters
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
"""
|
"""
|
||||||
NIO string representation.
|
NIO string representation.
|
||||||
|
@ -41,27 +41,18 @@ class NIOUDP(NIO):
|
|||||||
:param rport: remote port number
|
:param rport: remote port number
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, node, lport, rhost, rport, filters):
|
def __init__(self, node, lport, rhost, rport):
|
||||||
|
|
||||||
# create an unique name
|
# create an unique name
|
||||||
name = 'udp-{}'.format(uuid.uuid4())
|
name = 'udp-{}'.format(uuid.uuid4())
|
||||||
self._lport = lport
|
self._lport = lport
|
||||||
self._rhost = rhost
|
self._rhost = rhost
|
||||||
self._rport = rport
|
self._rport = rport
|
||||||
self._filters = filters
|
|
||||||
self._local_tunnel_lport = None
|
self._local_tunnel_lport = None
|
||||||
self._local_tunnel_rport = None
|
self._local_tunnel_rport = None
|
||||||
self._node = node
|
self._node = node
|
||||||
super().__init__(name, node.hypervisor)
|
super().__init__(name, node.hypervisor)
|
||||||
|
|
||||||
@property
|
|
||||||
def filters(self):
|
|
||||||
return self._filters
|
|
||||||
|
|
||||||
@filters.setter
|
|
||||||
def filters(self, val):
|
|
||||||
self._filters = val
|
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def create(self):
|
def create(self):
|
||||||
if not self._hypervisor:
|
if not self._hypervisor:
|
||||||
|
@ -36,8 +36,6 @@ log = logging.getLogger(__name__)
|
|||||||
|
|
||||||
from ...base_node import BaseNode
|
from ...base_node import BaseNode
|
||||||
from ..dynamips_error import DynamipsError
|
from ..dynamips_error import DynamipsError
|
||||||
from ..nios.nio_udp import NIOUDP
|
|
||||||
|
|
||||||
|
|
||||||
from gns3server.utils.file_watcher import FileWatcher
|
from gns3server.utils.file_watcher import FileWatcher
|
||||||
from gns3server.utils.asyncio import wait_run_in_executor, monitor_process, asyncio_ensure_future
|
from gns3server.utils.asyncio import wait_run_in_executor, monitor_process, asyncio_ensure_future
|
||||||
|
@ -29,6 +29,8 @@ class NIO(object):
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
|
||||||
self._capturing = False
|
self._capturing = False
|
||||||
|
self._suspended = False
|
||||||
|
self._filters = {}
|
||||||
self._pcap_output_file = ""
|
self._pcap_output_file = ""
|
||||||
self._pcap_data_link_type = ""
|
self._pcap_data_link_type = ""
|
||||||
|
|
||||||
@ -61,6 +63,7 @@ class NIO(object):
|
|||||||
def pcap_output_file(self):
|
def pcap_output_file(self):
|
||||||
"""
|
"""
|
||||||
Returns the path to the PCAP output file.
|
Returns the path to the PCAP output file.
|
||||||
|
|
||||||
:returns: path to the PCAP output file
|
:returns: path to the PCAP output file
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@ -70,7 +73,49 @@ class NIO(object):
|
|||||||
def pcap_data_link_type(self):
|
def pcap_data_link_type(self):
|
||||||
"""
|
"""
|
||||||
Returns the PCAP data link type
|
Returns the PCAP data link type
|
||||||
|
|
||||||
:returns: PCAP data link type (DLT_* value)
|
:returns: PCAP data link type (DLT_* value)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
return self._pcap_data_link_type
|
return self._pcap_data_link_type
|
||||||
|
|
||||||
|
@property
|
||||||
|
def suspend(self):
|
||||||
|
"""
|
||||||
|
Returns if this link is suspended or not.
|
||||||
|
|
||||||
|
:returns: boolean
|
||||||
|
"""
|
||||||
|
|
||||||
|
return self._suspended
|
||||||
|
|
||||||
|
@suspend.setter
|
||||||
|
def suspend(self, suspended):
|
||||||
|
"""
|
||||||
|
Suspend this link.
|
||||||
|
|
||||||
|
:param suspended: boolean
|
||||||
|
"""
|
||||||
|
|
||||||
|
self._suspended = suspended
|
||||||
|
|
||||||
|
@property
|
||||||
|
def filters(self):
|
||||||
|
"""
|
||||||
|
Returns the list of packet filters for this NIO.
|
||||||
|
|
||||||
|
:returns: packet filters (dictionary)
|
||||||
|
"""
|
||||||
|
|
||||||
|
return self._filters
|
||||||
|
|
||||||
|
@filters.setter
|
||||||
|
def filters(self, new_filters):
|
||||||
|
"""
|
||||||
|
Set a list of packet filters for this NIO.
|
||||||
|
|
||||||
|
:param new_filters: packet filters (dictionary)
|
||||||
|
"""
|
||||||
|
|
||||||
|
assert isinstance(new_filters, dict)
|
||||||
|
self._filters = new_filters
|
||||||
|
@ -32,25 +32,12 @@ class NIOUDP(NIO):
|
|||||||
:param rport: remote port number
|
:param rport: remote port number
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, lport, rhost, rport, filters):
|
def __init__(self, lport, rhost, rport):
|
||||||
|
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self._lport = lport
|
self._lport = lport
|
||||||
self._rhost = rhost
|
self._rhost = rhost
|
||||||
self._rport = rport
|
self._rport = rport
|
||||||
assert isinstance(filters, dict)
|
|
||||||
self._filters = filters
|
|
||||||
|
|
||||||
@property
|
|
||||||
def filters(self):
|
|
||||||
"""
|
|
||||||
Return the list of filter on this NIO
|
|
||||||
"""
|
|
||||||
return self._filters
|
|
||||||
|
|
||||||
@filters.setter
|
|
||||||
def filters(self, val):
|
|
||||||
self._filters = val
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def lport(self):
|
def lport(self):
|
||||||
|
@ -957,6 +957,8 @@ class QemuVM(BaseNode):
|
|||||||
yield from self.add_ubridge_udp_connection("QEMU-{}-{}".format(self._id, adapter_number),
|
yield from self.add_ubridge_udp_connection("QEMU-{}-{}".format(self._id, adapter_number),
|
||||||
self._local_udp_tunnels[adapter_number][1],
|
self._local_udp_tunnels[adapter_number][1],
|
||||||
nio)
|
nio)
|
||||||
|
if nio.suspend:
|
||||||
|
yield from self._control_vm("set_link gns3-{} off".format(adapter_number))
|
||||||
else:
|
else:
|
||||||
yield from self._control_vm("set_link gns3-{} off".format(adapter_number))
|
yield from self._control_vm("set_link gns3-{} off".format(adapter_number))
|
||||||
|
|
||||||
@ -1191,6 +1193,10 @@ class QemuVM(BaseNode):
|
|||||||
yield from self.update_ubridge_udp_connection("QEMU-{}-{}".format(self._id, adapter_number),
|
yield from self.update_ubridge_udp_connection("QEMU-{}-{}".format(self._id, adapter_number),
|
||||||
self._local_udp_tunnels[adapter_number][1],
|
self._local_udp_tunnels[adapter_number][1],
|
||||||
nio)
|
nio)
|
||||||
|
if nio.suspend:
|
||||||
|
yield from self._control_vm("set_link gns3-{} off".format(adapter_number))
|
||||||
|
else:
|
||||||
|
yield from self._control_vm("set_link gns3-{} on".format(adapter_number))
|
||||||
except IndexError:
|
except IndexError:
|
||||||
raise QemuError('Adapter {adapter_number} does not exist on QEMU VM "{name}"'.format(name=self._name,
|
raise QemuError('Adapter {adapter_number} does not exist on QEMU VM "{name}"'.format(name=self._name,
|
||||||
adapter_number=adapter_number))
|
adapter_number=adapter_number))
|
||||||
@ -1595,6 +1601,8 @@ class QemuVM(BaseNode):
|
|||||||
nio.rport,
|
nio.rport,
|
||||||
"127.0.0.1",
|
"127.0.0.1",
|
||||||
nio.lport)])
|
nio.lport)])
|
||||||
|
elif isinstance(nio, NIOTAP):
|
||||||
|
network_options.extend(["-net", "tap,name=gns3-{},ifname={}".format(adapter_number, nio.tap_device)])
|
||||||
else:
|
else:
|
||||||
network_options.extend(["-net", "nic,vlan={},macaddr={},model={}".format(adapter_number, mac, self._adapter_type)])
|
network_options.extend(["-net", "nic,vlan={},macaddr={},model={}".format(adapter_number, mac, self._adapter_type)])
|
||||||
|
|
||||||
@ -1614,6 +1622,8 @@ class QemuVM(BaseNode):
|
|||||||
nio.rport,
|
nio.rport,
|
||||||
"127.0.0.1",
|
"127.0.0.1",
|
||||||
nio.lport)])
|
nio.lport)])
|
||||||
|
elif isinstance(nio, NIOTAP):
|
||||||
|
network_options.extend(["-netdev", "tap,id=gns3-{},ifname={},script=no,downscript=no".format(adapter_number, nio.tap_device)])
|
||||||
else:
|
else:
|
||||||
network_options.extend(["-device", device_string])
|
network_options.extend(["-device", device_string])
|
||||||
|
|
||||||
|
@ -873,7 +873,10 @@ class VirtualBoxVM(BaseNode):
|
|||||||
yield from self._modify_vm("--nicproperty{} sport={}".format(adapter_number + 1, nio.lport))
|
yield from self._modify_vm("--nicproperty{} sport={}".format(adapter_number + 1, nio.lport))
|
||||||
yield from self._modify_vm("--nicproperty{} dest={}".format(adapter_number + 1, nio.rhost))
|
yield from self._modify_vm("--nicproperty{} dest={}".format(adapter_number + 1, nio.rhost))
|
||||||
yield from self._modify_vm("--nicproperty{} dport={}".format(adapter_number + 1, nio.rport))
|
yield from self._modify_vm("--nicproperty{} dport={}".format(adapter_number + 1, nio.rport))
|
||||||
yield from self._modify_vm("--cableconnected{} on".format(adapter_number + 1))
|
if nio.suspend:
|
||||||
|
yield from self._modify_vm("--cableconnected{} off".format(adapter_number + 1))
|
||||||
|
else:
|
||||||
|
yield from self._modify_vm("--cableconnected{} on".format(adapter_number + 1))
|
||||||
|
|
||||||
if nio.capturing:
|
if nio.capturing:
|
||||||
yield from self._modify_vm("--nictrace{} on".format(adapter_number + 1))
|
yield from self._modify_vm("--nictrace{} on".format(adapter_number + 1))
|
||||||
@ -1016,10 +1019,13 @@ class VirtualBoxVM(BaseNode):
|
|||||||
|
|
||||||
if self.is_running():
|
if self.is_running():
|
||||||
try:
|
try:
|
||||||
yield from self.update_ubridge_udp_connection(
|
yield from self.update_ubridge_udp_connection("VBOX-{}-{}".format(self._id, adapter_number),
|
||||||
"VBOX-{}-{}".format(self._id, adapter_number),
|
self._local_udp_tunnels[adapter_number][1],
|
||||||
self._local_udp_tunnels[adapter_number][1],
|
nio)
|
||||||
nio)
|
if nio.suspend:
|
||||||
|
yield from self._control_vm("setlinkstate{} off".format(adapter_number + 1))
|
||||||
|
else:
|
||||||
|
yield from self._control_vm("setlinkstate{} on".format(adapter_number + 1))
|
||||||
except IndexError:
|
except IndexError:
|
||||||
raise VirtualBoxError('Adapter {adapter_number} does not exist on VirtualBox VM "{name}"'.format(
|
raise VirtualBoxError('Adapter {adapter_number} does not exist on VirtualBox VM "{name}"'.format(
|
||||||
name=self._name,
|
name=self._name,
|
||||||
|
@ -124,7 +124,7 @@ class Link:
|
|||||||
self._streaming_pcap = None
|
self._streaming_pcap = None
|
||||||
self._created = False
|
self._created = False
|
||||||
self._link_type = "ethernet"
|
self._link_type = "ethernet"
|
||||||
self._suspend = False
|
self._suspended = False
|
||||||
self._filters = {}
|
self._filters = {}
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -146,7 +146,8 @@ class Link:
|
|||||||
Return the active filters.
|
Return the active filters.
|
||||||
Filters are overridden if the link is suspended.
|
Filters are overridden if the link is suspended.
|
||||||
"""
|
"""
|
||||||
if self._suspend:
|
if self._suspended:
|
||||||
|
# this is to allow all node types to support suspend link
|
||||||
return {"frequency_drop": [-1]}
|
return {"frequency_drop": [-1]}
|
||||||
return self._filters
|
return self._filters
|
||||||
|
|
||||||
@ -178,8 +179,8 @@ class Link:
|
|||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def update_suspend(self, value):
|
def update_suspend(self, value):
|
||||||
if value != self._suspend:
|
if value != self._suspended:
|
||||||
self._suspend = value
|
self._suspended = value
|
||||||
yield from self.update()
|
yield from self.update()
|
||||||
self._project.controller.notification.emit("link.updated", self.__json__())
|
self._project.controller.notification.emit("link.updated", self.__json__())
|
||||||
self._project.dump()
|
self._project.dump()
|
||||||
@ -452,7 +453,7 @@ class Link:
|
|||||||
"nodes": res,
|
"nodes": res,
|
||||||
"link_id": self._id,
|
"link_id": self._id,
|
||||||
"filters": self._filters,
|
"filters": self._filters,
|
||||||
"suspend": self._suspend
|
"suspend": self._suspended
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
"nodes": res,
|
"nodes": res,
|
||||||
@ -463,5 +464,5 @@ class Link:
|
|||||||
"capture_file_path": self.capture_file_path,
|
"capture_file_path": self.capture_file_path,
|
||||||
"link_type": self._link_type,
|
"link_type": self._link_type,
|
||||||
"filters": self._filters,
|
"filters": self._filters,
|
||||||
"suspend": self._suspend
|
"suspend": self._suspended
|
||||||
}
|
}
|
||||||
|
@ -76,7 +76,8 @@ class UDPLink(Link):
|
|||||||
"rhost": node2_host,
|
"rhost": node2_host,
|
||||||
"rport": self._node2_port,
|
"rport": self._node2_port,
|
||||||
"type": "nio_udp",
|
"type": "nio_udp",
|
||||||
"filters": node1_filters
|
"filters": node1_filters,
|
||||||
|
"suspend": self._suspended
|
||||||
})
|
})
|
||||||
yield from node1.post("/adapters/{adapter_number}/ports/{port_number}/nio".format(adapter_number=adapter_number1, port_number=port_number1), data=self._link_data[0], timeout=120)
|
yield from node1.post("/adapters/{adapter_number}/ports/{port_number}/nio".format(adapter_number=adapter_number1, port_number=port_number1), data=self._link_data[0], timeout=120)
|
||||||
|
|
||||||
@ -85,7 +86,8 @@ class UDPLink(Link):
|
|||||||
"rhost": node1_host,
|
"rhost": node1_host,
|
||||||
"rport": self._node1_port,
|
"rport": self._node1_port,
|
||||||
"type": "nio_udp",
|
"type": "nio_udp",
|
||||||
"filters": node2_filters
|
"filters": node2_filters,
|
||||||
|
"suspend": self._suspended
|
||||||
})
|
})
|
||||||
try:
|
try:
|
||||||
yield from node2.post("/adapters/{adapter_number}/ports/{port_number}/nio".format(adapter_number=adapter_number2, port_number=port_number2), data=self._link_data[1], timeout=120)
|
yield from node2.post("/adapters/{adapter_number}/ports/{port_number}/nio".format(adapter_number=adapter_number2, port_number=port_number2), data=self._link_data[1], timeout=120)
|
||||||
@ -97,22 +99,34 @@ class UDPLink(Link):
|
|||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def update(self):
|
def update(self):
|
||||||
|
"""
|
||||||
|
Update the link on the nodes
|
||||||
|
"""
|
||||||
|
|
||||||
if len(self._link_data) == 0:
|
if len(self._link_data) == 0:
|
||||||
return
|
return
|
||||||
node1 = self._nodes[0]["node"]
|
node1 = self._nodes[0]["node"]
|
||||||
node2 = self._nodes[1]["node"]
|
node2 = self._nodes[1]["node"]
|
||||||
filter_node = self._get_filter_node()
|
|
||||||
|
|
||||||
if node1 == filter_node:
|
node1_filters = {}
|
||||||
adapter_number1 = self._nodes[0]["adapter_number"]
|
node2_filters = {}
|
||||||
port_number1 = self._nodes[0]["port_number"]
|
filter_node = self._get_filter_node()
|
||||||
self._link_data[0]["filters"] = self.get_active_filters()
|
if filter_node == node1:
|
||||||
yield from node1.put("/adapters/{adapter_number}/ports/{port_number}/nio".format(adapter_number=adapter_number1, port_number=port_number1), data=self._link_data[0], timeout=120)
|
node1_filters = self.get_active_filters()
|
||||||
elif node2 == filter_node:
|
elif filter_node == node2:
|
||||||
adapter_number2 = self._nodes[1]["adapter_number"]
|
node2_filters = self.get_active_filters()
|
||||||
port_number2 = self._nodes[1]["port_number"]
|
|
||||||
self._link_data[1]["filters"] = self.get_active_filters()
|
adapter_number1 = self._nodes[0]["adapter_number"]
|
||||||
yield from node2.put("/adapters/{adapter_number}/ports/{port_number}/nio".format(adapter_number=adapter_number2, port_number=port_number2), data=self._link_data[1], timeout=221)
|
port_number1 = self._nodes[0]["port_number"]
|
||||||
|
self._link_data[0]["filters"] = node1_filters
|
||||||
|
self._link_data[0]["suspend"] = self._suspended
|
||||||
|
yield from node1.put("/adapters/{adapter_number}/ports/{port_number}/nio".format(adapter_number=adapter_number1, port_number=port_number1), data=self._link_data[0], timeout=120)
|
||||||
|
|
||||||
|
adapter_number2 = self._nodes[1]["adapter_number"]
|
||||||
|
port_number2 = self._nodes[1]["port_number"]
|
||||||
|
self._link_data[1]["filters"] = node2_filters
|
||||||
|
self._link_data[1]["suspend"] = self._suspended
|
||||||
|
yield from node2.put("/adapters/{adapter_number}/ports/{port_number}/nio".format(adapter_number=adapter_number2, port_number=port_number2), data=self._link_data[1], timeout=221)
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def delete(self):
|
def delete(self):
|
||||||
|
@ -284,7 +284,7 @@ class QEMUHandler:
|
|||||||
qemu_manager = Qemu.instance()
|
qemu_manager = Qemu.instance()
|
||||||
vm = qemu_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
|
vm = qemu_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
|
||||||
nio_type = request.json["type"]
|
nio_type = request.json["type"]
|
||||||
if nio_type not in ("nio_udp", "nio_tap", "nio_nat"):
|
if nio_type not in ("nio_udp"):
|
||||||
raise aiohttp.web.HTTPConflict(text="NIO of type {} is not supported".format(nio_type))
|
raise aiohttp.web.HTTPConflict(text="NIO of type {} is not supported".format(nio_type))
|
||||||
nio = qemu_manager.create_nio(request.json)
|
nio = qemu_manager.create_nio(request.json)
|
||||||
yield from vm.adapter_add_nio_binding(int(request.match_info["adapter_number"]), nio)
|
yield from vm.adapter_add_nio_binding(int(request.match_info["adapter_number"]), nio)
|
||||||
@ -314,6 +314,8 @@ class QEMUHandler:
|
|||||||
nio = vm.ethernet_adapters[int(request.match_info["adapter_number"])]
|
nio = vm.ethernet_adapters[int(request.match_info["adapter_number"])]
|
||||||
if "filters" in request.json and nio:
|
if "filters" in request.json and nio:
|
||||||
nio.filters = request.json["filters"]
|
nio.filters = request.json["filters"]
|
||||||
|
if "suspend" in request.json and nio:
|
||||||
|
nio.suspend = request.json["suspend"]
|
||||||
yield from vm.adapter_update_nio_binding(int(request.match_info["adapter_number"]), nio)
|
yield from vm.adapter_update_nio_binding(int(request.match_info["adapter_number"]), nio)
|
||||||
response.set_status(201)
|
response.set_status(201)
|
||||||
response.json(request.json)
|
response.json(request.json)
|
||||||
|
@ -313,6 +313,8 @@ class VirtualBoxHandler:
|
|||||||
nio = vm.ethernet_adapters[int(request.match_info["adapter_number"])]
|
nio = vm.ethernet_adapters[int(request.match_info["adapter_number"])]
|
||||||
if "filters" in request.json and nio:
|
if "filters" in request.json and nio:
|
||||||
nio.filters = request.json["filters"]
|
nio.filters = request.json["filters"]
|
||||||
|
if "suspend" in request.json and nio:
|
||||||
|
nio.suspend = request.json["suspend"]
|
||||||
yield from vm.adapter_update_nio_binding(int(request.match_info["adapter_number"]), nio)
|
yield from vm.adapter_update_nio_binding(int(request.match_info["adapter_number"]), nio)
|
||||||
response.set_status(201)
|
response.set_status(201)
|
||||||
response.json(request.json)
|
response.json(request.json)
|
||||||
|
@ -46,6 +46,10 @@ NIO_SCHEMA = {
|
|||||||
"minimum": 1,
|
"minimum": 1,
|
||||||
"maximum": 65535
|
"maximum": 65535
|
||||||
},
|
},
|
||||||
|
"suspend": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Suspend the link"
|
||||||
|
},
|
||||||
"filters": FILTER_OBJECT_SCHEMA
|
"filters": FILTER_OBJECT_SCHEMA
|
||||||
},
|
},
|
||||||
"required": ["type", "lport", "rhost", "rport"],
|
"required": ["type", "lport", "rhost", "rport"],
|
||||||
|
Loading…
Reference in New Issue
Block a user