3
# Copyright 2014 Canonical Ltd.
5
# This program is free software: you can redistribute it and/or modify it
6
# under the terms of the GNU Affero General Public License version 3, as
7
# published by the Free Software Foundation.
9
# This program is distributed in the hope that it will be useful, but
10
# WITHOUT ANY WARRANTY; without even the implied warranties of
11
# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
12
# PURPOSE. See the GNU Affero General Public License for more details.
14
# You should have received a copy of the GNU Affero General Public License
15
# along with this program. If not, see <http://www.gnu.org/licenses/>.
24
from charmhelpers import (
29
CHROOT_USER_HOME = '/root'
30
CHROOT_ROOT_PATH = '/var/cache/pbuilder'
33
def juju_info(msg, level='INFO'):
34
core.hookenv.log(msg, level)
37
def chroot_exists(path, dist, arch):
38
chroot_path = os.path.join(path, '{}-{}'.format(dist, arch))
39
return os.path.isdir(chroot_path)
42
def get_chroot_from_url(path, dist, arch, url):
45
chroot_path = os.path.join(path, '{}-{}'.format(dist, arch))
46
wget_path = os.path.join(path, '{}-{}.tgz'.format(dist, arch))
47
url_path = '{}/{}-{}.tgz'.format(url, dist, arch)
49
subprocess.check_call(['wget', '-O', wget_path, url_path])
50
subprocess.check_call(['tar', '-xzf', wget_path, '-C', path])
51
except subprocess.CalledProcessError:
52
juju_info('Could not download or extract {}'.format(url_path),
56
subprocess.check_call(['rm', '-rf', chroot_path])
57
subprocess.check_call(['rm', '-rf', wget_path])
58
except subprocess.CalledProcessError:
59
raise EnvironmentError(
60
'Could not cleanup chroot {}'.format(chroot_path))
65
def update_chroot(path, dist, arch):
66
chroot_path = os.path.join(path, '{}-{}'.format(dist, arch))
67
chroot_env = copy.copy(os.environ)
68
chroot_env['DIST'] = dist
69
chroot_env['ARCH'] = arch
70
chroot_env['HOME'] = CHROOT_USER_HOME
72
start = datetime.datetime.now()
73
subprocess.check_call(['cowbuilder', '--update'],
75
end = datetime.datetime.now()
76
juju_info('chroot update: {}'.format(end - start))
77
except subprocess.CalledProcessError:
78
raise EnvironmentError(
79
'Could not update chroot {}'.format(chroot_path))
82
def create_chroot(path, dist, arch):
83
'''Creates a cowbuilder chroot given the dist and arch.'''
84
chroot_env = copy.copy(os.environ)
85
chroot_env['DIST'] = dist
86
chroot_env['ARCH'] = arch
87
chroot_env['HOME'] = CHROOT_USER_HOME
88
start = datetime.datetime.now()
89
juju_info('Attempting: cowbuilder --create for {}-{}'.format(dist, arch))
91
subprocess.check_call(['cowbuilder', '--create',
92
'--distribution', dist,
93
'--architecture', arch,
94
'--debootstrapopts', '--variant=buildd'],
96
subprocess.check_call(['cowbuilder', '--save',
97
'--execute', '--', '/usr/bin/apt-get',
98
'install', 'eatmydata', 'bzr-builddeb',
99
'software-properties-common', '-yq',
102
except subprocess.CalledProcessError as e:
103
raise EnvironmentError(
104
'Could not create chroot for {}-{} return: {}'.format(
105
dist, arch, e.returncode))
106
end = datetime.datetime.now()
107
juju_info('chroot create: {}'.format(end - start))
110
def setup_chroots(config):
111
distros = config['distros']
112
architectures = config['architectures']
113
base_url = config.get('chroot_base_url', '')
116
dist_list = distros.split()
118
juju_info('''Can't determine distros from [{}]'''.format(distros),
123
architecture_list = architectures.split()
125
juju_info('''Can't determine architectures from [{}]'''.format(
126
architectures), 'ERROR')
129
for dist in dist_list:
130
for arch in architecture_list:
132
if chroot_exists(CHROOT_ROOT_PATH, dist, arch):
133
update_chroot(CHROOT_ROOT_PATH, dist, arch)
134
elif get_chroot_from_url(CHROOT_ROOT_PATH, dist, arch,
136
update_chroot(CHROOT_ROOT_PATH, dist, arch)
138
create_chroot(CHROOT_ROOT_PATH, dist, arch)
139
except EnvironmentError as e:
140
juju_info('{}'.format(e), 'ERROR')
145
def setup_dependencies(config):
146
required_packages = ['bzr', 'cowbuilder']
148
juju_info('installing apt packages...')
149
fetch.apt_install(required_packages, fatal=True)
152
def setup_pbuilderrc(config):
153
cu2d_dir = '/srv/cu2d'
154
if os.path.exists(cu2d_dir):
155
subprocess.check_call(['bzr', 'update', cu2d_dir])
158
subprocess.check_call(['bzr', 'branch',
159
'lp:cupstream2distro/uci-airline',
161
except subprocess.CalledProcessError as e:
162
raise EnvironmentError(
163
'Could not get cu2d (return: {})'.format(e.returncode))
165
shutil.copy(os.path.join(cu2d_dir, 'chroot-tools', '.pbuilderrc'),
169
def config_changed(config):
170
setup_dependencies(config)
171
setup_pbuilderrc(config)
172
setup_chroots(config)
176
hook = os.path.basename(sys.argv[0])
177
juju_info('Running hook: {}'.format(hook))
179
hook_py = hook.replace('-', '_')
181
if hook_py not in funcs:
182
print('Unknown hook: {}'.format(hook))
185
config = core.hookenv.config()
186
juju_info('Config: {}'.format(config))
188
return funcs[hook_py](config)
189
except subprocess.CalledProcessError as e:
190
juju_info('Error running: {}: {}'.format(e.cmd, e.output))
194
if __name__ == '__main__':