Blame t_functional_duffy_runner/src/__main__.py

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 f8f954
        self.last_session = None 
Adam Saleh f8f954
        
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 f8f954
        
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 f8f954
     
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 f8f954
    
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 f8f954
        self.last_session = session
Adam Saleh f8f954
        return session
Adam Saleh f8f954
    
Adam Saleh f8f954
class TmuxWrapper:
Adam Saleh f8f954
    def __init__(self, host, session='default-session', **rest):
Adam Saleh f8f954
        self.host = host
Adam Saleh f8f954
        self.c = Connection(host, **rest)
Adam Saleh f8f954
        self.c.run("dnf -y install git tmux")
Adam Saleh f8f954
        self.ensure_session(session)
Adam Saleh f8f954
    
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 f8f954
    
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 f8f954
    
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 f8f954
    
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 f8f954
Adam Saleh f8f954
def runtests(auth_name, auth_key, query, path=None, compose=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 f8f954
    tmux = TmuxWrapper("root@"+hostname)
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 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 f8f954
    if auth_name and auth_key:
Adam Saleh f8f954
        runtests(auth_name, auth_key, ['virt', args.arch, args.release], path=args.path, compose=args.compose)
Adam Saleh f8f954
Adam Saleh f8f954
if __name__ == "__main__":
Adam Saleh f8f954
    main()