|
Adam Saleh |
f8f954 |
from argparse import ArgumentParser
|
|
Adam Saleh |
f8f954 |
import io
|
|
Adam Saleh |
f8f954 |
import os
|
|
Adam Saleh |
f8f954 |
import tempfile
|
|
Adam Saleh |
f8f954 |
|
|
Adam Saleh |
f8f954 |
from duffy.client import DuffyClient
|
|
Adam Saleh |
f8f954 |
from fabric import Connection
|
|
Adam Saleh |
f8f954 |
from invoke import run as local
|
|
Adam Saleh |
f8f954 |
|
|
Adam Saleh |
f8f954 |
class DuffyWrapper:
|
|
Adam Saleh |
f8f954 |
def __init__(self, auth_name, auth_key):
|
|
Adam Saleh |
f8f954 |
self.c = DuffyClient(url="https://duffy.ci.centos.org/api/v1", auth_name=auth_name, auth_key=auth_key)
|
|
Adam Saleh |
4b64c8 |
self.last_session = None
|
|
Adam Saleh |
4b64c8 |
|
|
Adam Saleh |
f8f954 |
def get_hostnames(self, *query):
|
|
Adam Saleh |
f8f954 |
if not self.last_session:
|
|
Adam Saleh |
f8f954 |
self.request_session(*query)
|
|
Adam Saleh |
4b64c8 |
|
|
Adam Saleh |
f8f954 |
nodes = [n for n in self.last_session.session.nodes
|
|
Adam Saleh |
f8f954 |
if all(q in n.pool for q in query)]
|
|
Adam Saleh |
f8f954 |
return [n
|
|
Adam Saleh |
f8f954 |
for n in [n.data.get('provision',{}).get('public_hostname',None) for n in nodes]
|
|
Adam Saleh |
f8f954 |
if n]
|
|
Adam Saleh |
4b64c8 |
|
|
Adam Saleh |
f8f954 |
def find_hostnames(self, *query):
|
|
Adam Saleh |
f8f954 |
ls = self.c.list_sessions()
|
|
Adam Saleh |
f8f954 |
nodes = [n for s in ls.sessions for n in s.nodes
|
|
Adam Saleh |
f8f954 |
if all(q in n.pool for q in query)]
|
|
Adam Saleh |
f8f954 |
return [n
|
|
Adam Saleh |
f8f954 |
for n in [n.data.get('provision',{}).get('public_hostname',None) for n in nodes]
|
|
Adam Saleh |
f8f954 |
if n]
|
|
Adam Saleh |
f8f954 |
|
|
Adam Saleh |
f8f954 |
def find_pool_name(self, *query):
|
|
Adam Saleh |
f8f954 |
return [p.name for p in self.c.list_pools().pools if all(q in p.name for q in query)]
|
|
Adam Saleh |
4b64c8 |
|
|
Adam Saleh |
f8f954 |
def request_session(self, *query):
|
|
Adam Saleh |
f8f954 |
pool = self.find_pool_name(*query)
|
|
Adam Saleh |
f8f954 |
session = self.c.request_session([{"pool":pool[0], "quantity":"1"}])
|
|
Adam Saleh |
997ff5 |
if hasattr(session, 'session'):
|
|
Adam Saleh |
997ff5 |
self.last_session = session
|
|
Adam Saleh |
997ff5 |
return session
|
|
Adam Saleh |
997ff5 |
else:
|
|
Adam Saleh |
289721 |
raise Exception(repr(session))
|
|
Adam Saleh |
4b64c8 |
|
|
Adam Saleh |
f8f954 |
class TmuxWrapper:
|
|
Adam Saleh |
4b64c8 |
def __init__(self, host, session='default-session', private_key=None, **rest):
|
|
Adam Saleh |
f8f954 |
self.host = host
|
|
Adam Saleh |
4b64c8 |
if private_key:
|
|
Adam Saleh |
4b64c8 |
self.c = Connection(host,connect_kwargs={
|
|
Adam Saleh |
4b64c8 |
"key_filename": private_key,
|
|
Adam Saleh |
4b64c8 |
}, **rest)
|
|
Adam Saleh |
4b64c8 |
else:
|
|
Adam Saleh |
4b64c8 |
self.c = Connection(host, **rest)
|
|
Adam Saleh |
4b64c8 |
|
|
Adam Saleh |
f8f954 |
self.c.run("dnf -y install git tmux")
|
|
Adam Saleh |
f8f954 |
self.ensure_session(session)
|
|
Adam Saleh |
4b64c8 |
|
|
Adam Saleh |
f8f954 |
def ensure_session(self,session='default-session'):
|
|
Adam Saleh |
f8f954 |
return self.c.run("tmux has-session -t {session} || tmux new -s {session} -d".format(session=session))
|
|
Adam Saleh |
4b64c8 |
|
|
Adam Saleh |
f8f954 |
def run(self, cmd, session='default-session'):
|
|
Adam Saleh |
f8f954 |
return self.c.run("tmux send-keys -t {session}:0 '{cmd}' ENTER".format(session=session, cmd=cmd))
|
|
Adam Saleh |
4b64c8 |
|
|
Adam Saleh |
f8f954 |
def run_and_notify(self, cmd, session='default-session'):
|
|
Adam Saleh |
f8f954 |
return self.c.run("tmux send-keys -t {session}:0 '{cmd}; tmux wait-for -S {session}' ENTER".format(session=session, cmd=cmd))
|
|
Adam Saleh |
f8f954 |
|
|
Adam Saleh |
f8f954 |
def wait_for(self, session='default-session'):
|
|
Adam Saleh |
f8f954 |
return self.c.run("tmux wait-for {session}".format(session=session))
|
|
Adam Saleh |
4b64c8 |
|
|
Adam Saleh |
f8f954 |
def send_folder(self, path, remote):
|
|
Adam Saleh |
f8f954 |
with tempfile.NamedTemporaryFile() as t:
|
|
Adam Saleh |
f8f954 |
local("tar cf {to} -C {path} .".format(path=path, to=t.name))
|
|
Adam Saleh |
f8f954 |
print(t.name)
|
|
Adam Saleh |
f8f954 |
self.c.run("mkdir -p {}".format(remote))
|
|
Adam Saleh |
f8f954 |
self.c.put(local=t.name, remote=remote)
|
|
Adam Saleh |
f8f954 |
self.c.run("cd {path} && tar xf {name}".format(path=remote, name=t.name.split('/')[-1]))
|
|
Adam Saleh |
f8f954 |
def get_pane(self):
|
|
Adam Saleh |
f8f954 |
return tmux.c.run("tmux capture-pane -p -t default-session")
|
|
Adam Saleh |
f8f954 |
def set_repo(self, baseurl="https://composes.stream.centos.org/development/latest-CentOS-Stream/compose/"):
|
|
Adam Saleh |
f8f954 |
repo = io.StringIO("""
|
|
Adam Saleh |
f8f954 |
[baseos-compose]
|
|
Adam Saleh |
f8f954 |
name=CentOS Stream $releasever - BaseOS
|
|
Adam Saleh |
f8f954 |
baseurl={baseurl}/BaseOS/$arch/os/
|
|
Adam Saleh |
f8f954 |
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
|
|
Adam Saleh |
f8f954 |
gpgcheck=0
|
|
Adam Saleh |
f8f954 |
repo_gpgcheck=0
|
|
Adam Saleh |
f8f954 |
metadata_expire=6h
|
|
Adam Saleh |
f8f954 |
countme=1
|
|
Adam Saleh |
f8f954 |
enabled=1
|
|
Adam Saleh |
f8f954 |
|
|
Adam Saleh |
f8f954 |
[appstream-compose]
|
|
Adam Saleh |
f8f954 |
name=CentOS Stream $releasever - AppStream
|
|
Adam Saleh |
f8f954 |
baseurl={baseurl}/AppStream/$arch/os/
|
|
Adam Saleh |
f8f954 |
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
|
|
Adam Saleh |
f8f954 |
gpgcheck=0
|
|
Adam Saleh |
f8f954 |
repo_gpgcheck=0
|
|
Adam Saleh |
f8f954 |
metadata_expire=6h
|
|
Adam Saleh |
f8f954 |
countme=1
|
|
Adam Saleh |
f8f954 |
enabled=1
|
|
Adam Saleh |
f8f954 |
""".format(baseurl=baseurl))
|
|
Adam Saleh |
f8f954 |
self.c.put(repo, "/tmp/compose.repo")
|
|
Adam Saleh |
f8f954 |
self.c.run("dnf repolist | awk '(NR>1) {print $1}' | xargs dnf config-manager --disable")
|
|
Adam Saleh |
f8f954 |
self.c.run("dnf config-manager --add-repo /tmp/compose.repo")
|
|
Adam Saleh |
f8f954 |
self.c.run("dnf config-manager --enable baseos-compose")
|
|
Adam Saleh |
f8f954 |
self.c.run("dnf config-manager --enable appstream-compose")
|
|
Adam Saleh |
f8f954 |
self.c.run("dnf clean all")
|
|
Adam Saleh |
f8f954 |
|
|
Adam Saleh |
f8f954 |
|
|
Adam Saleh |
4b64c8 |
|
|
Adam Saleh |
4b64c8 |
def runtests(auth_name, auth_key, query, path=None, compose=None, private_key=None):
|
|
Adam Saleh |
f8f954 |
d = DuffyWrapper(auth_name=auth_name, auth_key=auth_key)
|
|
Adam Saleh |
f8f954 |
print("Getting", *query)
|
|
Adam Saleh |
f8f954 |
hostnames = d.get_hostnames(*query)
|
|
Adam Saleh |
f8f954 |
if not hostnames:
|
|
Adam Saleh |
f8f954 |
raise Exception("Didn't manage to find or provision matching machine.")
|
|
Adam Saleh |
f8f954 |
|
|
Adam Saleh |
f8f954 |
hostname = hostnames[0]
|
|
Adam Saleh |
f8f954 |
print("root@"+hostname)
|
|
Adam Saleh |
4b64c8 |
tmux = TmuxWrapper("root@"+hostname, private_key=private_key)
|
|
Adam Saleh |
f8f954 |
if compose:
|
|
Adam Saleh |
f8f954 |
print("Setting compose", compose)
|
|
Adam Saleh |
f8f954 |
tmux.set_repo(compose)
|
|
Adam Saleh |
f8f954 |
if path:
|
|
Adam Saleh |
f8f954 |
print("Sending local repo",path )
|
|
Adam Saleh |
f8f954 |
tmux.send_folder(path, "/opt/t_functional")
|
|
Adam Saleh |
f8f954 |
else:
|
|
Adam Saleh |
f8f954 |
tmux.c.run("git clone https://github.com/CentOS/sig-core-t_functional /opt/t_functional")
|
|
Adam Saleh |
f8f954 |
tmux.ensure_session()
|
|
Adam Saleh |
f8f954 |
tmux.run("cd /opt/t_functional")
|
|
Adam Saleh |
f8f954 |
tmux.run("export SYSTEMD_PAGER=")
|
|
Adam Saleh |
f8f954 |
tmux.run("ls -l")
|
|
Adam Saleh |
f8f954 |
tmux.c.run("cd /opt//t_functional && /bin/bash runtests.sh 0_common")
|
|
Adam Saleh |
f8f954 |
return tmux
|
|
Adam Saleh |
f8f954 |
|
|
Adam Saleh |
f8f954 |
|
|
Adam Saleh |
f8f954 |
def main():
|
|
Adam Saleh |
f8f954 |
parser = ArgumentParser(prog='My App')
|
|
Adam Saleh |
f8f954 |
parser.add_argument('--arch', help="The duffy query.")
|
|
Adam Saleh |
f8f954 |
parser.add_argument('--path', help="", default=None, required=False)
|
|
Adam Saleh |
f8f954 |
parser.add_argument('--release', help="" )
|
|
Adam Saleh |
f8f954 |
parser.add_argument('--compose', help="", default=None, required=False)
|
|
Adam Saleh |
4b64c8 |
parser.add_argument('--sshkey', help="", default=None, required=False)
|
|
Adam Saleh |
f8f954 |
args = parser.parse_args()
|
|
Adam Saleh |
f8f954 |
auth_name=os.getenv("DUFFY_AUTH_NAME")
|
|
Adam Saleh |
f8f954 |
auth_key=os.getenv("DUFFY_AUTH_KEY")
|
|
Adam Saleh |
4b64c8 |
print("Running with args:",args.arch, args.release, args.path, args.compose, args.sshkey)
|
|
Adam Saleh |
f8f954 |
if auth_name and auth_key:
|
|
Adam Saleh |
4b64c8 |
runtests(auth_name, auth_key, ['virt', args.arch, args.release], path=args.path, compose=args.compose, private_key=args.sshkey)
|
|
|
afb6f8 |
else:
|
|
|
afb6f8 |
raise Exception("Duffy key or auth name not available")
|
|
Adam Saleh |
f8f954 |
|
|
Adam Saleh |
f8f954 |
if __name__ == "__main__":
|
|
|
afb6f8 |
print("Running tests")
|
|
Adam Saleh |
f8f954 |
main()
|