Skip to content

Commit

Permalink
Fix sending data encoding to netemu
Browse files Browse the repository at this point in the history
  • Loading branch information
Marco Giusti committed Dec 26, 2020
1 parent be8b31a commit a08034c
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 71 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,6 @@ __pycache__/
/debian/debhelper-build-stamp
/debian/usr/
/debian/virtualbricks.prerm.debhelper

# Vim swap files
*.sw?
78 changes: 42 additions & 36 deletions virtualbricks/bricks.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import os
import collections
import functools
import locale
import re

from twisted.internet import protocol, reactor, error, defer
Expand All @@ -38,18 +39,21 @@
if False: # pyflakes
_ = str


system_encoding = locale.getpreferredencoding(do_setlocale=True)

logger = log.Logger(__name__)
process_started = log.Event("Process started")
process_terminated = log.Event("Process terminated. {status()}")
process_terminated = log.Event("Process terminated. {status}")
process_done = log.Event("Process terminated")
event_unavailable = log.Event("Warning. The Event {name} attached to Brick "
"{brick} is not available. Skipping execution.")
shutdown_brick = log.Event("Shutting down {name} (pid: {pid})")
start_brick = log.Event("Starting: {args()}")
open_console = log.Event("Opening console for {name}\n%{args()}\n")
start_brick = log.Event("Starting: {args}")
open_console = log.Event("Opening console for {name}\n%{args}\n")
console_done = log.Event("Console terminated\n{status}")
console_terminated = log.Event("Console terminated\n{status}\nProcess stdout:"
"\n{out()}\nProcess stderr:\n{err()}\n")
"\n{out}\nProcess stderr:\n{err}\n")
invalid_ack = log.Event("ACK received but no command sent.")


Expand Down Expand Up @@ -82,11 +86,11 @@ def connectionMade(self):

def processEnded(self, status):
if status.check(error.ProcessTerminated):
self.logger.error(process_terminated,
status=lambda: " ".join(status.value.args))
status = " ".join(status.value.args)
self.logger.error(process_terminated, status=status)
else:
assert status.check(error.ProcessDone)
self.logger.info(process_terminated, status=lambda: "")
self.logger.info(process_terminated, status="Done")
self.brick.process_ended(self, status)

def outReceived(self, data):
Expand Down Expand Up @@ -133,27 +137,28 @@ class VDEProcessProtocol(Process):
@cvar delimiter: The line-ending delimiter to use.
"""

_buffer = ""
delimiter = u"\n"
prompt = re.compile(r"^vde(?:\[[^]]*\]:|\$) ", re.MULTILINE)
_buffer = b""
delimiter = b"\n"
prompt = re.compile(rb"^vde(?:\[[^]]*\]:|\$) ", re.MULTILINE)
PIPELINE_SIZE = 1

def __init__(self, brick):
Process.__init__(self, brick)
self.queue = collections.deque()


def data_received(self, data):
def _data_received(self, data):
"""
Translates bytes into lines, and calls ack_received.
Translates bytes into lines, and calls _ack_received.
"""

acks = self.prompt.split(self._buffer + data.decode("utf-8"))
assert isinstance(data, bytes)
acks = self.prompt.split(self._buffer + data)
self._buffer = acks.pop(-1)
for ack in acks:
self.ack_received(ack)
self._ack_received(ack)

def ack_received(self, ack):
def _ack_received(self, ack):
self.logger.info(ack)
try:
self.queue.popleft()
Expand All @@ -164,23 +169,21 @@ def ack_received(self, ack):
if len(self.queue):
self._send_command()

def send_command(self, cmd):
self.queue.append(cmd)
if 0 < len(self.queue) <= self.PIPELINE_SIZE:
self._send_command()

def _send_command(self):
cmd = self.queue[0]
self.logger.info(cmd)
if cmd.decode("utf-8").endswith(self.delimiter):
if cmd.endswith(self.delimiter):
return self.transport.write(cmd)
return self.transport.writeSequence((cmd, self.delimiter.encode("utf-8")))
else:
return self.transport.writeSequence((cmd, self.delimiter))

def outReceived(self, data):
self.data_received(data)
self._data_received(data)

def write(self, cmd):
self.send_command(cmd)
self.queue.append(cmd)
if 0 < len(self.queue) <= self.PIPELINE_SIZE:
self._send_command()


class TermProtocol(protocol.ProcessProtocol):
Expand All @@ -202,17 +205,22 @@ def errReceived(self, data):

def processEnded(self, status):
if isinstance(status.value, error.ProcessTerminated):
self.logger.error(console_terminated, status=status.value,
out=lambda: "".join(self.out),
err=lambda: "".join(self.err))
self.logger.error(
console_terminated,
status=status.value,
out="".join(self.out),
err="".join(self.err)
)
else:
self.logger.info(console_done, status=status.value)


class Config(_Config):

parameters = {"pon_vbevent": String(""),
"poff_vbevent": String("")}
parameters = {
"pon_vbevent": String(""),
"poff_vbevent": String("")
}


class Brick(base.Base):
Expand Down Expand Up @@ -344,7 +352,7 @@ def build_cmd_line(self):
value = value()
else:
value = self.config.get(value)
if value is "*":
if value == "*":
res.append(switch)
elif value is not None and len(value) > 0:
if not switch.startswith("*"):
Expand All @@ -358,7 +366,7 @@ def _poweron(self, ignore):

def start_process(value):
prog, args = value
logger.info(start_brick, args=lambda: " ".join(args))
logger.info(start_brick, args=" ".join(args))
# usePTY?
if self.needsudo():
prog = settings.get("sudo")
Expand Down Expand Up @@ -414,14 +422,12 @@ def disconnect(self):

def open_console(self):
term = settings.get("term")
args = [term, "-e",
abspath_vde(self.term_command),
self.console()]
get_args = lambda: " ".join(args)
logger.info(open_console, name=self.name, args=get_args)
args = [term, "-e", abspath_vde(self.term_command), self.console()]
logger.info(open_console, name=self.name, args=" ".join(args))
reactor.spawnProcess(TermProtocol(), term, args, os.environ)

def send(self, data):
assert isinstance(data, bytes)
if self.proc:
self.proc.write(data)

Expand Down
20 changes: 10 additions & 10 deletions virtualbricks/console.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,13 +148,13 @@ class VBProtocol(Protocol):

# _is_first = False
delimiter = b"\n"
prompt = "virtualbricks> "
prompt = b"virtualbricks> "
intro = (
"Virtualbricks, version {version}\n"
"Copyright (C) 2019 Virtualbricks team\n"
"This is free software; see the source code for copying conditions.\n"
"There is ABSOLUTELY NO WARRANTY; not even for MERCHANTABILITY or\n"
"FITNESS FOR A PARTICULAR PURPOSE. For details, type `warranty'.\n\n"
b"Virtualbricks, version %s\n"
b"Copyright (C) 2019 Virtualbricks team\n"
b"This is free software; see the source code for copying conditions.\n"
b"There is ABSOLUTELY NO WARRANTY; not even for MERCHANTABILITY or\n"
b"FITNESS FOR A PARTICULAR PURPOSE. For details, type `warranty'.\n\n"
)

def __init__(self, factory):
Expand All @@ -170,14 +170,14 @@ def connectionMade(self):
# self._is_first = True
# intro = self.intro.format(version=virtualbricks.version.short())
# self.transport.write(intro)
intro = self.intro.format(version=__version__)
self.transport.write(intro.encode())
self.transport.write(self.prompt.encode())
intro = self.intro % (__version__.encode('ascii'),)
self.transport.write(intro)
self.transport.write(self.prompt)

def lineReceived(self, line):
Protocol.lineReceived(self, line)
if line != "python": # :-(
self.transport.write(self.prompt.encode())
self.transport.write(self.prompt)

def brick_action(self, obj, cmd):
"""brick action dispatcher"""
Expand Down
31 changes: 21 additions & 10 deletions virtualbricks/interfaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,28 +59,39 @@ class IBrick(Interface):
C{twisted.internet.interfaces.IProcessTransport""")

def get_type():
"""Return the type of brick."""
"""
Return the type of brick.
"""

def poweron():
"""Start the brick.
"""
Start the brick.

Return a deferred that fires when the brick is started."""
Return a deferred that fires when the brick is started.
"""

def poweroff():
"""Stop the brick.
"""
Stop the brick.

Return a deferred that fires when the brick is stopped."""
Return a deferred that fires when the brick is stopped.
"""

def get_parameters():
"""Actually used only in the main tree to show the list of the
parameters"""
"""
Used only in the main tree to show the list of the parameters.
"""
# XXX: remove this method

def configure(attrlist):
"""Configure the brick"""
"""
Configure the brick.
"""

def __eq__(other):
"""Compare two bricks"""
"""
Compare two bricks.
"""
# XXX: maybe should use is keyword?

# to be controlled
Expand Down Expand Up @@ -128,5 +139,5 @@ def signal_process(signo):
def write(data):
"""Send data to the stdin of the process.

@type data: C{str}
@type data: C{bytes}
"""
12 changes: 10 additions & 2 deletions virtualbricks/virtualmachines.py
Original file line number Diff line number Diff line change
Expand Up @@ -918,16 +918,24 @@ def poweroff(self, kill=False, term=False):
return bricks.Brick.poweroff(self, kill)

def get_parameters(self):
try:
command = self.prog()
except FileNotFoundError:
if self.config["argv0"]:
command = self.config['argv0']
else:
command = self.default_arg0

ram = self.config["ram"]
txt = [_("command:") + " %s, ram: %s" % (self.prog(), ram)]
txt = [_("command:") + " %s, ram: %s" % (command, ram)]
for i, link in enumerate(itertools.chain(self.plugs, self.socks)):
txt.append("eth%d: %s" % (i, _get_nick(link)))
return ", ".join(txt)

def update_usbdevlist(self, dev):
self.logger.debug(update_usb, old=self.config['usbdevlist'], new=dev)
for usb_dev in set(dev) - set(self.config['usbdevlist']):
self.send('usb_add host:{usb_dev.id}\n'.format(usb_dev=usb_dev))
self.send(b'usb_add host:%s\n' % (usb_dev.id,))
# FIXME: Don't know how to remove old devices, due to the ugly syntax
# of usb_del command.

Expand Down
26 changes: 13 additions & 13 deletions virtualbricks/wires.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ class NetemuConfig(bricks.Config):

class WFProcessProtocol(bricks.VDEProcessProtocol):

prompt = re.compile(r"^VDEwf\$ ", re.M)
prompt = re.compile(rb"^VDEwf\$ ", re.M)


class Netemu(Wire):
Expand Down Expand Up @@ -160,55 +160,55 @@ def _set(self, attrs, symm, left_to_right, right_to_left):

def cbset_chanbufsize(self, value):
if self.config["chanbufsizesymm"]:
self.send("chanbufsize {0}\n".format(value))
self.send(b"chanbufsize %d\n" % (value,))
else:
self.send("chanbufsize LR {0}\n".format(value))
self.send(b"chanbufsize LR %d\n" % (value,))

def cbset_chanbufsizer(self, value):
if not self.config["chanbufsizesymm"]:
self.send("chanbufsize RL {0}\n".format(value))
self.send(b"chanbufsize RL %d\n" % (value,))

def cbset_chanbufsizesymm(self, value):
self.cbset_chanbufsize(self.config["chanbufsize"])
self.cbset_chanbufsizer(self.config["chanbufsizer"])

def cbset_delay(self, value):
if self.config["delaysymm"]:
self.send("delay {0}\n".format(value))
self.send(b"delay %d\n" % (value,))
else:
self.send("delay LR {0}\n".format(value))
self.send(b"delay LR %d\n" % (value,))

def cbset_delayr(self, value):
if not self.config["delaysymm"]:
self.send("delay RL {0}\n".format(value))
self.send(b"delay RL %d\n" % (value,))

def cbset_delaysymm(self, value):
self.cbset_delay(self.config["delay"])
self.cbset_delayr(self.config["delayr"])

def cbset_loss(self, value):
if self.config["losssymm"]:
self.send("loss {0}\n".format(value))
self.send(b"loss %f\n" % (value,))
else:
self.send("loss LR {0}\n".format(value))
self.send(b"loss LR %f\n" % (value,))

def cbset_lossr(self, value):
if not self.config["losssymm"]:
self.send("loss RL {0}\n".format(value))
self.send(b"loss RL %f\n" % (value,))

def cbset_losssymm(self, value):
self.cbset_loss(self.config["loss"])
self.cbset_lossr(self.config["lossr"])

def cbset_bandwidth(self, value):
if self.config["bandwidthsymm"]:
self.send("bandwidth {0}\n".format(value))
self.send(b"bandwidth %d\n" % (value,))
else:
self.send("bandwidth LR {0}\n".format(value))
self.send(b"bandwidth LR %d\n" % (value,))

def cbset_bandwidthr(self, value):
if not self.config["bandwidthsymm"]:
self.send("bandwidth RL {0}\n".format(value))
self.send(b"bandwidth RL %d\n" % (value,))

def cbset_bandwidthsymm(self, value):
self.cbset_bandwidth(self.config["bandwidth"])
Expand Down

0 comments on commit a08034c

Please sign in to comment.