From e1d1fe5329c8b060f9a9b44acfb56db09a484aba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Louis-Francis=20Ratt=C3=A9-Boulianne?= <lfrb@collabora.com> Date: Fri, 9 Dec 2016 16:13:29 -0500 Subject: [PATCH] Add device class and option to retrieve the image version MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Louis-Francis Ratté-Boulianne <lfrb@collabora.com> Reviewed-by: Guillaume Desmottes <guillaume.desmottes@collabora.co.uk> Differential Revision: https://phabricator.apertis.org/D5227 --- doc/man/ade-info.1 | 7 ++++ tools/ade | 85 +++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 91 insertions(+), 1 deletion(-) diff --git a/doc/man/ade-info.1 b/doc/man/ade-info.1 index ca20162..d460c65 100644 --- a/doc/man/ade-info.1 +++ b/doc/man/ade-info.1 @@ -12,6 +12,7 @@ ade-info \- Print information about an entity .SH SYNOPSIS .sp .nf +\fIade info\fR --device [<user>[:<pass>]@]<hostname>[:<port>] \fIade info\fR --sysroot <sysroot> .fi .sp @@ -22,6 +23,12 @@ Retrieve information about a sysroot or another ADE object\&. .SH OPTIONS .sp .PP +\fI\-\-device\fR +.RS 4 +Return image version of given device (e.g. user@apertis)\&. +.sp +.RE +.PP \fI\-\-sysroot\fR .RS 4 Return installed version and path of given sysroot (e.g. apertis-16.12-armhf)\&. diff --git a/tools/ade b/tools/ade index 65c54e4..99d8816 100755 --- a/tools/ade +++ b/tools/ade @@ -17,6 +17,7 @@ import glob import logging import os import pathlib +import paramiko import re import shutil import struct @@ -26,6 +27,7 @@ import tempfile import urllib import xdg.BaseDirectory +from contextlib import contextmanager, closing from urllib.error import URLError from urllib.parse import urlparse from urllib.request import urlopen, urlretrieve @@ -53,6 +55,14 @@ class SysrootManagerError(Exception): return self.message +class InvalidDeviceError(Exception): + def __init__(self, message): + self.message = message + + def __str__(self): + return self.message + + class InvalidSysrootArchiveError(Exception): def __init__(self, message): self.message = message @@ -120,6 +130,66 @@ class TargetTriplet: raise NotSupportedError +class Device: + + def __init__(self, host, port=22, user=None, password=None): + self.host = host + if port is None: + port = 22 + self.port = port + self.user = user + if not self.user: + self.user = "user" + self.password = password + self.version = None + self._ssh = None + + def from_uri(uri): + try: + r = urlparse("ssh://" + uri) + except Exception: + raise InvalidDeviceError("Invalid URI format") + return Device(r.hostname, r.port, r.username, r.password) + + def __str__(self): + string = "" + if self.user: + string += user + if self.password: + string += ':' + self.password + string += '@' + string += self.host + if self.port != 22: + string += ':' + str(self.port) + return string + + def _connect(self): + ssh = paramiko.SSHClient() + ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) + ssh.connect(self.host, port=self.port, + allow_agent=False, look_for_keys=False, gss_auth=False, + username=self.user, password=self.password, + key_filename=os.path.expanduser("~/.ssh/apertis.ssh")) + return ssh + + def _exec(self, *args): + with closing(self._connect()) as ssh: + stdin, stdout, stderr = ssh.exec_command(' '.join(args)) + return stdout.read().decode().strip() + + def load_sysroot_version(self): + try: + v = self._exec('cat', '/etc/image_version') + self.version = SysrootVersion.from_string(v) + except Exception as e: + print(e) + raise InvalidDeviceError("No image_version file found") + a = self._exec('uname', '-m') + if a not in TargetTriplet.SUPPORTED: + raise InvalidDeviceError("Unsupported architecture") + self.version.arch = a + + class SysrootVersion: def __init__(self, distro, release, arch, date=None, build=None, author=None, url=None): @@ -486,6 +556,7 @@ class Ade: self.target = None self.sysroot = None + self.device = None self.sysroot_version = None self.distro = None @@ -550,8 +621,14 @@ class Ade: except InvalidSysrootError: self.die("Invalid sysroot installed for {0}{1}{2}" \ .format(Colors.OKBLUE, version.get_name(), Colors.ENDC)) + elif self.device: + try: + self.target = Device.from_uri(self.device) + self.target.load_sysroot_version() + except InvalidDeviceError as e: + self.die("Invalid device: {0}".format(e)) else: - self.die("No target (sysroot) specified") + self.die("No target (sysroot or device) specified") return self.target @@ -749,6 +826,11 @@ class Ade: if self.format == 'parseable': print("SysrootVersion:{0}".format(self.target.version.get_tag())) print("SysrootPath:{0}".format(self.target.path)) + elif isinstance(target, Device): + self.info("* Device has image version {0}{1}{2}" + .format(Colors.WARNING, self.target.version, Colors.ENDC)) + if self.format == 'parseable': + print("ImageVersion:{0}".format(self.target.version.get_tag())) def info(self, message): if self.format == 'friendly': @@ -780,6 +862,7 @@ if __name__ == '__main__': info_parser = subparsers.add_parser('info', help="Retrieve information about an object") group = info_parser.add_mutually_exclusive_group() group.add_argument('--sysroot', help="Use sysroot as target (e.g. apertis-16.12-armhf)") + group.add_argument('--device', help="Use device as target (e.g. user:pass@apertis)") # Sysroot parser sysroot_parser = subparsers.add_parser('sysroot', help='Sysroot related commands') -- GitLab