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
|
# This file is part of cloud-init. See LICENSE file for license information.
import os
import uuid
class Instance(object):
"""
Base instance object
"""
platform_name = None
def __init__(self, name):
"""
setup
"""
self.name = name
def execute(self, command, stdin=None, stdout=None, stderr=None, env={}):
"""
command: the command to execute as root inside the image
stdin, stderr, stdout: file handles
env: environment variables
Execute assumes functional networking and execution as root with the
target filesystem being available at /.
return_value: tuple containing stdout data, stderr data, exit code
"""
raise NotImplementedError
def read_data(self, remote_path, encode=False):
"""
read_data from instance filesystem
remote_path: path in instance
decode: return as string
return_value: data as str or bytes
"""
raise NotImplementedError
def write_data(self, remote_path, data):
"""
write data to instance filesystem
remote_path: path in instance
data: data to write, either str or bytes
"""
raise NotImplementedError
def pull_file(self, remote_path, local_path):
"""
copy file at 'remote_path', from instance to 'local_path'
"""
with open(local_path, 'wb') as fp:
fp.write(self.read_data(remote_path), encode=True)
def push_file(self, local_path, remote_path):
"""
copy file at 'local_path' to instance at 'remote_path'
"""
with open(local_path, 'rb') as fp:
self.write_data(remote_path, fp.read())
def run_script(self, script):
"""
run script in target and return stdout
"""
script_path = os.path.join('/tmp', str(uuid.uuid1()))
self.write_data(script_path, script)
(out, err, exit_code) = self.execute(['/bin/bash', script_path])
return out
def console_log(self):
"""
return_value: bytes of this instance’s console
"""
raise NotImplementedError
def reboot(self, wait=True):
"""
reboot instance
"""
raise NotImplementedError
def shutdown(self, wait=True):
"""
shutdown instance
"""
raise NotImplementedError
def start(self, wait=True):
"""
start instance
"""
raise NotImplementedError
def destroy(self):
"""
clean up instance
"""
pass
def _wait_for_cloud_init(self, wait_time):
"""
wait until system has fully booted and cloud-init has finished
"""
if not wait_time:
return
found_msg = 'found'
cmd = ('for ((i=0;i<{wait};i++)); do [ -f "{file}" ] && '
'{{ echo "{msg}";break; }} || sleep 1; done').format(
file='/run/cloud-init/result.json',
wait=wait_time, msg=found_msg)
(out, err, exit) = self.execute(['/bin/bash', '-c', cmd])
if out.strip() != found_msg:
raise OSError('timeout: after {}s, cloud-init has not started'
.format(wait_time))
# vi: ts=4 expandtab
|