forked from M-Labs/artiq
Add lockfile support to artiq_devtool.
This commit is contained in:
parent
b89929565c
commit
b5d098c6db
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
import argparse
|
import argparse
|
||||||
|
import logging
|
||||||
import subprocess
|
import subprocess
|
||||||
import socket
|
import socket
|
||||||
import select
|
import select
|
||||||
|
@ -22,20 +23,23 @@ def get_argparser():
|
||||||
|
|
||||||
verbosity_args(parser)
|
verbosity_args(parser)
|
||||||
|
|
||||||
parser.add_argument("-H", "--host", metavar="HOST",
|
parser.add_argument("-H", "--host", metavar="HOSTNAME",
|
||||||
type=str, default="lab.m-labs.hk",
|
type=str, default="lab.m-labs.hk",
|
||||||
help="SSH host where the development board is located")
|
help="SSH host where the development board is located")
|
||||||
parser.add_argument("-D", "--device", metavar="DEVICE",
|
parser.add_argument("-D", "--device", metavar="HOSTNAME",
|
||||||
type=str, default="kc705.lab.m-labs.hk",
|
type=str, default="kc705.lab.m-labs.hk",
|
||||||
help="address or domain corresponding to the development board")
|
help="address or domain corresponding to the development board")
|
||||||
parser.add_argument("-s", "--serial", metavar="SERIAL",
|
parser.add_argument("-s", "--serial", metavar="PATH",
|
||||||
type=str, default="/dev/ttyUSB_kc705",
|
type=str, default="/dev/ttyUSB_kc705",
|
||||||
help="TTY device corresponding to the development board")
|
help="TTY device corresponding to the development board")
|
||||||
|
parser.add_argument("-l", "--lockfile", metavar="PATH",
|
||||||
|
type=str, default="/run/boards/kc705",
|
||||||
|
help="The lockfile to be acquired for the duration of the script")
|
||||||
parser.add_argument("-t", "--target", metavar="TARGET",
|
parser.add_argument("-t", "--target", metavar="TARGET",
|
||||||
type=str, default="kc705_dds",
|
type=str, default="kc705_dds",
|
||||||
help="Target to build, one of: "
|
help="Target to build, one of: "
|
||||||
"kc705_dds kc705_drtio_master kc705_drtio_satellite")
|
"kc705_dds kc705_drtio_master kc705_drtio_satellite")
|
||||||
parser.add_argument("-c", "--config", metavar="TARGET_CFG",
|
parser.add_argument("-c", "--config", metavar="PATH",
|
||||||
type=str, default="openocd-kc705.cfg",
|
type=str, default="openocd-kc705.cfg",
|
||||||
help="OpenOCD configuration file corresponding to the development board")
|
help="OpenOCD configuration file corresponding to the development board")
|
||||||
|
|
||||||
|
@ -50,6 +54,8 @@ def get_argparser():
|
||||||
def main():
|
def main():
|
||||||
args = get_argparser().parse_args()
|
args = get_argparser().parse_args()
|
||||||
init_logger(args)
|
init_logger(args)
|
||||||
|
if args.verbose == args.quiet == 0:
|
||||||
|
logging.getLogger().setLevel(logging.INFO)
|
||||||
|
|
||||||
if args.target == "kc705_dds" or args.target == "kc705_drtio_master":
|
if args.target == "kc705_dds" or args.target == "kc705_drtio_master":
|
||||||
firmware = "runtime"
|
firmware = "runtime"
|
||||||
|
@ -65,6 +71,27 @@ def main():
|
||||||
"firmware": firmware,
|
"firmware": firmware,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lock_acquired = False
|
||||||
|
def lock():
|
||||||
|
nonlocal lock_acquired
|
||||||
|
|
||||||
|
if not lock_acquired:
|
||||||
|
logger.info("Acquiring device lock")
|
||||||
|
flock = client.spawn_command("flock --verbose --nonblock {} /bin/sleep 86400"
|
||||||
|
.format(args.lockfile),
|
||||||
|
get_pty=True)
|
||||||
|
flock_file = flock.makefile('r')
|
||||||
|
while not lock_acquired:
|
||||||
|
line = flock_file.readline()
|
||||||
|
if not line:
|
||||||
|
break
|
||||||
|
logger.debug(line.rstrip())
|
||||||
|
if line.startswith("flock: executing"):
|
||||||
|
lock_acquired = True
|
||||||
|
elif line.startswith("flock: failed"):
|
||||||
|
logger.error("Failed to get lock")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
for action in args.actions:
|
for action in args.actions:
|
||||||
if action == "build":
|
if action == "build":
|
||||||
logger.info("Building firmware")
|
logger.info("Building firmware")
|
||||||
|
@ -85,6 +112,8 @@ def main():
|
||||||
shutil.rmtree(target_dir)
|
shutil.rmtree(target_dir)
|
||||||
|
|
||||||
elif action == "reset":
|
elif action == "reset":
|
||||||
|
lock()
|
||||||
|
|
||||||
logger.info("Resetting device")
|
logger.info("Resetting device")
|
||||||
client.run_command(
|
client.run_command(
|
||||||
"{env} artiq_flash start" +
|
"{env} artiq_flash start" +
|
||||||
|
@ -92,6 +121,8 @@ def main():
|
||||||
**substs)
|
**substs)
|
||||||
|
|
||||||
elif action == "boot" or action == "boot+log":
|
elif action == "boot" or action == "boot+log":
|
||||||
|
lock()
|
||||||
|
|
||||||
logger.info("Uploading firmware")
|
logger.info("Uploading firmware")
|
||||||
client.get_sftp().put("/tmp/{target}/software/{firmware}/{firmware}.bin"
|
client.get_sftp().put("/tmp/{target}/software/{firmware}/{firmware}.bin"
|
||||||
.format(target=args.target, firmware=firmware),
|
.format(target=args.target, firmware=firmware),
|
||||||
|
@ -111,6 +142,8 @@ def main():
|
||||||
client.drain(flterm)
|
client.drain(flterm)
|
||||||
|
|
||||||
elif action == "connect":
|
elif action == "connect":
|
||||||
|
lock()
|
||||||
|
|
||||||
transport = client.get_transport()
|
transport = client.get_transport()
|
||||||
|
|
||||||
def forwarder(local_stream, remote_stream):
|
def forwarder(local_stream, remote_stream):
|
||||||
|
@ -141,10 +174,6 @@ def main():
|
||||||
local_stream, peer_addr = listener.accept()
|
local_stream, peer_addr = listener.accept()
|
||||||
logger.info("Accepting %s:%s and opening SSH channel to %s:%s",
|
logger.info("Accepting %s:%s and opening SSH channel to %s:%s",
|
||||||
*peer_addr, args.device, port)
|
*peer_addr, args.device, port)
|
||||||
if client.get_transport() is None:
|
|
||||||
logger.error("Trying to open a channel before the transport is ready!")
|
|
||||||
continue
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
remote_stream = \
|
remote_stream = \
|
||||||
transport.open_channel('direct-tcpip', (args.device, port), peer_addr)
|
transport.open_channel('direct-tcpip', (args.device, port), peer_addr)
|
||||||
|
@ -156,12 +185,14 @@ def main():
|
||||||
name="forward-{}".format(port), daemon=True)
|
name="forward-{}".format(port), daemon=True)
|
||||||
thread.start()
|
thread.start()
|
||||||
|
|
||||||
for port in (1380, 1381, 1382, 1383):
|
ports = [1380, 1381, 1382, 1383]
|
||||||
|
for port in ports:
|
||||||
thread = threading.Thread(target=listener, args=(port,),
|
thread = threading.Thread(target=listener, args=(port,),
|
||||||
name="listen-{}".format(port), daemon=True)
|
name="listen-{}".format(port), daemon=True)
|
||||||
thread.start()
|
thread.start()
|
||||||
|
|
||||||
logger.info("Connecting to device")
|
logger.info("Forwarding ports {} to core device and logs from core device"
|
||||||
|
.format(", ".join(map(str, ports))))
|
||||||
client.run_command(
|
client.run_command(
|
||||||
"{env} python3 flterm.py {serial} --output-only",
|
"{env} python3 flterm.py {serial} --output-only",
|
||||||
**substs)
|
**substs)
|
||||||
|
|
|
@ -269,10 +269,12 @@ class SSHClient:
|
||||||
def get_ssh(self):
|
def get_ssh(self):
|
||||||
if self.ssh is None:
|
if self.ssh is None:
|
||||||
import paramiko
|
import paramiko
|
||||||
|
logging.getLogger("paramiko").setLevel(logging.WARNING)
|
||||||
self.ssh = paramiko.SSHClient()
|
self.ssh = paramiko.SSHClient()
|
||||||
self.ssh.load_system_host_keys()
|
self.ssh.load_system_host_keys()
|
||||||
self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||||
self.ssh.connect(self.host)
|
self.ssh.connect(self.host)
|
||||||
|
logger.debug("Connecting to {}".format(self.host))
|
||||||
return self.ssh
|
return self.ssh
|
||||||
|
|
||||||
def get_transport(self):
|
def get_transport(self):
|
||||||
|
@ -286,11 +288,11 @@ class SSHClient:
|
||||||
return self.sftp
|
return self.sftp
|
||||||
|
|
||||||
def spawn_command(self, cmd, get_pty=False, **kws):
|
def spawn_command(self, cmd, get_pty=False, **kws):
|
||||||
logger.info("Executing {}".format(cmd))
|
chan = self.get_transport().open_session()
|
||||||
chan = self.get_ssh().get_transport().open_session()
|
chan.set_combine_stderr(True)
|
||||||
if get_pty:
|
if get_pty:
|
||||||
chan.get_pty()
|
chan.get_pty()
|
||||||
chan.set_combine_stderr(True)
|
logger.debug("Executing {}".format(cmd))
|
||||||
chan.exec_command(cmd.format(tmp=self.tmp, **kws))
|
chan.exec_command(cmd.format(tmp=self.tmp, **kws))
|
||||||
return chan
|
return chan
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue