aboutsummaryrefslogtreecommitdiff
path: root/playground/a01/main.py
blob: aa6ce8eb299dc3dea7d789277226ec56487a2a45 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
import libvirt
import sys
import time
import io
import git
import os
import shutil
import pathlib
import tempfile
import paramiko.client
import paramiko.rsakey


private_key_str = """-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEA9t4sSxeHa8A0TwMOzD9M9OITtcbl3rki/QfBLIFBkKlP24Tx
BOH5dRfWq0LC7j1+ViDUyBEuPw513ADxuwUhpLbhelkDM7rrmobXvKfYfKlK6mtn
RA2tFSeJNmWO7Cz3VYR3JWUgG5TGowXWHRx42MP7fzmbWKd2HSVUUmKVONb98YjW
nZFTmBaV53lHfVLCKitxsToFL0uGzqFSMt27BK9GDaCA159zC4G7YqjiqxkqA5UY
x2IbMFKMd7eAKw/yCdBRuCWGYFvjPlHj1m4zCHZsfFQ5fYrO9NFd2ieYxQBgSfJ+
cDSmiaXXWWfooaG0h2UKMkrqU0YmHGOA2c/xJwIDAQABAoIBAE0Q4Iz0pG7ryqib
0MPMQw7zgKmvlNUpwJVzFUf6deheIrLp1n/qt4BpV7eRGN9czRLAHwzx6BkBP6PV
m6EBohYUjWEvZoOAp8pOrAyV7UxFYUC7FLq29kBzXi9gFvT9uJy2xKck4ZgaosQD
r2rZF5S74cg+yJMte/7vR1qMsf7S6eyrDVMQGP6c0apMT1GxmcAHx9T71ePoYnD2
faUzr+lVnTLGB6wv1cyaF/Nrt/leskBJ0qmKfkWMRc2uPPPDIvGW39z9OIoPqlEr
4RKqwvyqRzh0uQ/4tpZzMQTfQQSzQ3B9gxCyox7Fc8z/KOSVHzbFso9FCjidCtxR
054KmqkCgYEA/r1tdovJzv7AYJeeEV81VFCwtxIg2T04JhhfYiGg/MSSp4Jc05UM
ivVn9VIyjj9kP0mFTSH/4zLFpo9jp7a/HTfqOK6fIT0p8bQ/PJ8ZZ7cQN1MsV7bh
YaXaUF8Oh/yidnZC3dH1ByVrvZC8DolGlpLAvl8i66kUXGvHvnuYNB0CgYEA+BbG
84ge1O9aLxEKzW9soTglFJREMT3jMvK7oUPvYy6JhjoKbM3CnkFSQx+k+QA5wgKf
Z+bWGjWZ3paOP1wgmRl/3/ST08W79I6WaQVBx28DiGypyJ3V0/lkfxvsAhsPhM0n
qya+ASYuYa1OZR2sdykyYA74+lor8DzEwIfB7xMCgYEA9516QbkvuZ23siyu4YQC
eqrUm59rfr8bTSxzyxeVPR52z4zQXnqLbqeNHdGAgvTrpPj6MjfSXC6GIZlP7T6e
FvC7I83ZsJ2bn+7taSfdsgsoIB8hA0IpYpms1GMR5O2VnkDmTmhAHWoqiGGf6yFV
FBgicupXL2ty90NtLaNGF6ECgYAcvE6pEKA5m8u/XeL5bqmPdvhcjNvlNDznvtPa
1wqYW2CUio6Akci0Ge7UVYr/SHZoMXOTTlqISKMc9CVf02T3Nsvn/eVNhz7BEe78
FR7MYeBv4d48nYOR/PYV/v70M3w1rqmkmmUxruF6cN9+uNQsLTpng/R00xL5zaAg
iNj+vwKBgQCbPS90lQ+d3YSB0W5kdBigTfgMASwFiENXHEPReTTDi73y9AQL8yh7
fhwegAxBuKYUMqUh/yjE/lWE9j+TjLufPOLq3K0C+xoOQExuZ7+xEg9SjIju+Fj5
iebkM6IzOZtiCNZXEQvJiHj6aTM6wTy8OhuLry04ayXvJ6Kmj63lsw==
-----END RSA PRIVATE KEY-----
"""


def main():
    repo_path = 'repository'
    conf = {'domain': 'archlinux',
            'ssh_username': 'root',
            'ssh_key': private_key_str,
            'script': ['pwd',
                       'ls',
                       'cat test.txt']}
    with tempfile.TemporaryDirectory() as tmpdir:
        repo_arch_path = str(
            (pathlib.Path(tmpdir) / 'hatter_archive.tar').absolute())
        init_git_archive(repo_path, repo_arch_path)
        execute_libvirt(conf, repo_arch_path)


def init_git_archive(repo_path, repo_arch_path):
    shutil.rmtree(repo_path, ignore_errors=True)
    os.mkdir(repo_path)
    with open(pathlib.Path(repo_path) / 'test.txt', 'w',
              encoding='utf-8') as f:
        f.write('test123\n')
    g = git.Git(repo_path)
    g.init()
    g.add('.')
    g.commit(m='init')
    g.archive('HEAD', o=repo_arch_path)


def execute_libvirt(conf, repo_arch_path):
    conn = libvirt.open(conf.get('uri', 'qemu:///system'))
    domain = conn.lookupByName(conf['domain'])
    if domain.isActive():
        domain.destroy()
    snapshot_names = domain.snapshotListNames()
    if 'temp_hatter' in snapshot_names:
        domain.snapshotLookupByName('temp_hatter').delete()
    origin_snapshot = domain.snapshotCreateXML(
        "<domainsnapshot><name>temp_hatter</name></domainsnapshot>")
    snapshot_name = conf.get('snapshot')
    if snapshot_name:
        snapshot = domain.snapshotLookupByName(snapshot_name)
        if snapshot:
            domain.revertToSnapshot(snapshot)
    domain.create()
    address = None
    for _ in range(10):
        addresses = domain.interfaceAddresses(0)
        for i in addresses.values():
            for j in i['addrs']:
                address = j['addr']
                break
        if address:
            execute_ssh(conf, address, repo_arch_path)
            break
        time.sleep(1)
    domain.destroy()
    domain.revertToSnapshot(origin_snapshot)
    origin_snapshot.delete()
    conn.close()


def execute_ssh(conf, address, repo_arch_path):
    pkey = paramiko.rsakey.RSAKey.from_private_key(
        io.StringIO(conf['ssh_key']))
    conn = paramiko.client.SSHClient()
    conn.set_missing_host_key_policy(paramiko.client.AutoAddPolicy)
    connected = False
    for _ in range(10):
        try:
            conn.connect(address, username=conf['ssh_username'], pkey=pkey,
                         timeout=1, auth_timeout=1)
            connected = True
            break
        except Exception as e:
            time.sleep(5)
    if not connected:
        return
    sftp_conn = conn.open_sftp()
    sftp_conn.put(repo_arch_path, 'hatter_archive.tar')
    sftp_conn.close()
    execute_ssh_cmd(conn, 'rm -rf hatter_archive', '.')
    execute_ssh_cmd(conn, 'mkdir hatter_archive', '.')
    execute_ssh_cmd(conn, 'tar xf hatter_archive.tar -C hatter_archive', '.')
    for cmd in conf['script']:
        print('>> ', cmd)
        stdout, stderr = execute_ssh_cmd(conn, cmd, 'hatter_archive')
        print('>>>> stdout')
        print(stdout, end='')
        print('>>>> stderr')
        print(stderr)
    conn.close()


def execute_ssh_cmd(conn, cmd, cwd):
    _, ssh_stdout, ssh_stderr = conn.exec_command(
        'cd {} && {}'.format(cwd, cmd))
    return ssh_stdout.read().decode('utf-8'), ssh_stderr.read().decode('utf-8')


if __name__ == '__main__':
    sys.exit(main())