Skip to content

Commit

Permalink
devices: add support for running cmd's instead of ssh to host
Browse files Browse the repository at this point in the history
This let's use run commands instead of ssh to a specific ip addr. The
example is extended to use a Docker container and map two ethernet
interfaces to the WAN and LAN and run the tests with those.

The example config is updated as well and it relies on starting and
cleanup up docker containers. You could easily configure it to use a
persistant docker container as well by changing the cmd's

Signed-off-by: Matthew McClintock <msm-oss@mcclintock.net>
  • Loading branch information
mattsm committed Aug 24, 2017
1 parent 393d849 commit b750c10
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 42 deletions.
28 changes: 18 additions & 10 deletions bft
Original file line number Diff line number Diff line change
Expand Up @@ -66,13 +66,17 @@ def setup_dynamic_devices(config):
config.devices = []
for device in config.board['devices']:
if device['type'] == 'debian':
#TODO: support conn_cmd and ipaddr (for ssh)
d = debian.DebianBox(name=device['ipaddr'],
d = debian.DebianBox(name=device.get('ipaddr', None),
color=device.get('color', 'black'),
reboot=config.reboot_vms,
username=device.get('username', "root"),
password=device.get('password', "bigfoot1"),
port=config.board.get('port', "22"))
port=config.board.get('port', "22"),
pre_cmd_host=device.get('pre_cmd_host', None),
cmd=device.get('cmd', None),
post_cmd_host=device.get('post_cmd_host', None),
post_cmd=device.get('post_cmd', None),
cleanup_cmd=device.get('cleanup_cmd', None))
setattr(config, device['name'], d)
config.devices.append(device['name'])
else:
Expand Down Expand Up @@ -104,14 +108,18 @@ def main():
print_bold("Connecting to board named = %s, type = %s ..." % (name, config.board['board_type']))
try:
# If we find a dynamic device with the tftpd-server option let's use that for the server
# otherwise we use the device with the 'wan' name
# otherwise we use the device with the 'wan' name... finally if we don't find an ip address let's
# manually figure it out later
tftp_server = None
if 'devices' in config.board:
tftp_servers = [ x['ipaddr'] for x in config.board['devices'] if 'tftpd-server' in x.get('options', "") ]
if len(tftp_servers) == 1:
tftp_server = tftp_servers[0]
elif tftp_server is None:
tftp_server = [ x['ipaddr'] for x in config.board['devices'] if x['name'] == 'wan' ][0]
try:
if 'devices' in config.board:
tftp_servers = [ x['ipaddr'] for x in config.board['devices'] if 'tftpd-server' in x.get('options', "") ]
if len(tftp_servers) == 1:
tftp_server = tftp_servers[0]
elif tftp_server is None:
tftp_server = [ x['ipaddr'] for x in config.board['devices'] if x['name'] == 'wan' ][0]
except:
pass

# Connect to board
config.console = board_decider.board(config.board['board_type'],
Expand Down
47 changes: 28 additions & 19 deletions boardfarm_config_example.json
Original file line number Diff line number Diff line change
@@ -1,22 +1,31 @@
{
"board01": {
"board_type": "apXYZ",
"conn_cmd": "telnet consoleserver.mysite.com 6001",
"lan_device": "machine01",
"location": "austin",
"powerip": "pdu.mysite.com",
"powerport": "8",
"wan_device": "machine02",
"notes": "Old board"
},
"board02": {
"board_type": "apXYZ",
"conn_cmd": "telnet consoleserver.mysite.com 6002",
"lan_device": "machine03",
"location": "austin",
"powerip": "pdu.mysite.com",
"powerport": "3",
"wan_device": "machine04",
"notes": "Has 512 MB of memory"
"rpi3-1": {
"board_type": "rpi3",
"conn_cmd": "cu -l /dev/ttyUSB4 -s 115200",
"devices": [
{
"type": "debian",
"name": "wan",
"pre_cmd_host": "docker build -t bft:node bft-node",
"cmd": "docker run --name wan --privileged -it bft:node /bin/bash",
"post_cmd_host": "sudo ip link set netns $(docker inspect --format '{{.State.Pid}}' wan) dev enx00249b14dc6e",
"post_cmd": "ip link set enx00249b14dc6e name eth1",
"cleanup_cmd": "docker stop wan; docker rm wan",
"color": "cyan",
"options": "tftpd-server"
},
{
"type": "debian",
"name": "lan",
"pre_cmd_host": "docker build -t bft:node bft-node",
"cmd": "docker run --name lan --privileged -it bft:node /bin/bash",
"post_cmd_host": "sudo ip link set netns $(docker inspect --format '{{.State.Pid}}' lan) dev enx0050b61bfde4",
"post_cmd": "ip link set enx0050b61bfde4 name eth1",
"cleanup_cmd": "docker stop lan; docker rm lan",
"color": "blue"
}
],
"connection_type": "local_serial",
"notes": "Rpi3 device with docker containers attached to WAN/LAN"
}
}
76 changes: 63 additions & 13 deletions devices/debian.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import time
import pexpect
import base
import atexit

from termcolor import colored, cprint

Expand All @@ -28,25 +29,43 @@ def __init__(self,
port,
output=sys.stdout,
reboot=False,
location=None):
if name is None:
return
pexpect.spawn.__init__(self,
command="ssh",
args=['%s@%s' % (username, name),
'-p', port,
'-o', 'StrictHostKeyChecking=no',
'-o', 'UserKnownHostsFile=/dev/null'])
self.name = name
location=None,
pre_cmd_host=None,
cmd=None,
post_cmd_host=None,
post_cmd=None,
cleanup_cmd=None):
if name is not None:
pexpect.spawn.__init__(self,
command="ssh",
args=['%s@%s' % (username, name),
'-p', port,
'-o', 'StrictHostKeyChecking=no',
'-o', 'UserKnownHostsFile=/dev/null'])
self.name = name
else:
name = None
if pre_cmd_host is not None:
sys.stdout.write("\tRunning pre_host_cmd.... ")
sys.stdout.flush()
phc = pexpect.spawn(command='bash', args=['-c', pre_cmd_host])
phc.expect(pexpect.EOF, timeout=120)
print("\tpre_host_cmd done")

if cleanup_cmd is not None:
self.cleanup_cmd = cleanup_cmd
atexit.register(self.run_cleanup_cmd)

pexpect.spawn.__init__(self, command="bash", args=['-c', cmd])

self.color = color
self.output = output
self.username = username
self.password = password
self.port = port
self.location = location
cprint("%s device console = %s" % (name, colored(color, color)), None, attrs=['bold'])
try:
i = self.expect(["yes/no", "assword:", "Last login"], timeout=30)
i = self.expect(["yes/no", "assword:", "Last login"] + self.prompt, timeout=30)
except pexpect.TIMEOUT as e:
raise Exception("Unable to connect to %s." % name)
except pexpect.EOF as e:
Expand All @@ -60,13 +79,44 @@ def __init__(self,
self.sendline(password)
else:
pass
self.expect(self.prompt)
# if we did initially get a prompt wait for one here
if i < 3:
self.expect(self.prompt)

if name is None:
self.sendline('hostname')
self.expect('hostname')
self.expect(self.prompt)
name = self.name = self.before.strip()

cprint("%s device console = %s" % (name, colored(color, color)), None, attrs=['bold'])

if post_cmd_host is not None:
sys.stdout.write("\tRunning post_cmd_host.... ")
sys.stdout.flush()
phc = pexpect.spawn(command='bash', args=['-c', post_cmd_host])
i = phc.expect([pexpect.EOF, pexpect.TIMEOUT, 'password'])
if i > 0:
print("\tpost_cmd_host did not complete, it likely failed\n")
else:
print("\tpost_cmd_host done")

if post_cmd is not None:
self.sendline(post_cmd)
self.expect(self.prompt)

if reboot:
self.reset()

self.logfile_read = output

def run_cleanup_cmd(self):
sys.stdout.write("Running cleanup_cmd on %s..." % self.name)
sys.stdout.flush()
cc = pexpect.spawn(command='bash', args=['-c', self.cleanup_cmd])
cc.expect(pexpect.EOF, timeout=120)
print("cleanup_cmd done.")

def reset(self):
self.sendline('reboot')
self.expect(['going down','disconnected'])
Expand Down

0 comments on commit b750c10

Please sign in to comment.