~gandelman-a/charms/precise/keystone/swift_redux

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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
#!/usr/bin/python

# Common python helper functions used for OpenStack charms.

import subprocess

CLOUD_ARCHIVE_URL = "http://ubuntu-cloud.archive.canonical.com/ubuntu"
CLOUD_ARCHIVE_KEY_ID = '5EDB1B62EC4926EA'

ubuntu_openstack_release = {
    'oneiric': 'diablo',
    'precise': 'essex',
    'quantal': 'folsom',
    'raring' : 'grizzly'
}


openstack_codenames = {
    '2011.2': 'diablo',
    '2012.1': 'essex',
    '2012.2': 'folsom',
    '2012.3': 'grizzly'
}


def juju_log(msg):
    subprocess.check_call(['juju-log', msg])


def error_out(msg):
    juju_log("FATAL ERROR: %s" % msg)
    exit(1)


def lsb_release():
    '''Return /etc/lsb-release in a dict'''
    lsb = open('/etc/lsb-release', 'r')
    d = {}
    for l in lsb:
        k, v = l.split('=')
        d[k.strip()] = v.strip()
    return d


def get_os_codename_install_source(src):
    '''Derive OpenStack release codename from a given installation source.'''
    ubuntu_rel = lsb_release()['DISTRIB_CODENAME']

    rel = ''
    if src == 'distro':
        try:
            rel = ubuntu_openstack_release[ubuntu_rel]
        except KeyError:
            e = 'Code not derive openstack release for '\
                'this Ubuntu release: %s' % rel
            error_out(e)
        return rel

    if src.startswith('cloud:'):
        ca_rel = src.split(':')[1]
        ca_rel = ca_rel.split('%s-' % ubuntu_rel)[1].split('/')[0]
        return ca_rel

    # Best guess match based on deb string provided
    if src.startswith('deb'):
        for k, v in openstack_codenames.iteritems():
            if v in src:
                return v

def get_os_codename_version(vers):
    '''Determine OpenStack codename from version number.'''
    try:
        return openstack_codenames[vers]
    except KeyError:
        e = 'Could not determine OpenStack codename for version %s' % vers
        error_out(e)


def get_os_version_codename(codename):
    '''Determine OpenStack version number from codename.'''
    for k, v in openstack_codenames.iteritems():
        if v == codename:
            return k
    e = 'Code not derive OpenStack version for '\
        'codename: %s' % codename
    error_out(e)


def get_os_codename_package(pkg):
    '''Derive OpenStack release codename from an installed package.'''
    cmd = ['dpkg', '-l', pkg]

    try:
        output = subprocess.check_output(cmd)
    except subprocess.CalledProcessError:
        e = 'Could not derive OpenStack version from package that is not '\
            'installed; %s' % pkg
        error_out(e)

    def _clean(line):
        line = line.split(' ')
        clean = []
        for c in line:
            if c != '':
                clean.append(c)
        return clean

    vers = None
    for l in output.split('\n'):
        if l.startswith('ii'):
            l = _clean(l)
            if l[1] == pkg:
                vers = l[2]

    if not vers:
        e = 'Could not determine version of installed package: %s' % pkg
        error_out(e)

    vers = vers[:6]
    try:
        return openstack_codenames[vers]
    except KeyError:
        e = 'Could not determine OpenStack codename for version %s' % vers
        error_out(e)


def configure_installation_source(rel):
    '''Configure apt installation source.'''

    def _import_key(id):
        cmd = "apt-key adv --keyserver keyserver.ubuntu.com " \
              "--recv-keys %s" % id
        try:
            subprocess.check_call(cmd.split(' '))
        except:
            error_out("Error importing repo key %s" % id)

    if rel == 'distro':
        return
    elif rel[:4] == "ppa:":
        src = rel
        subprocess.check_call(["add-apt-repository", "-y", src])
    elif rel[:3] == "deb":
        l = len(rel.split('|'))
        if l ==  2:
            src, key = rel.split('|')
            juju_log("Importing PPA key from keyserver for %s" % src)
            _import_key(key)
        elif l == 1:
            src = rel
        else:
            error_out("Invalid openstack-release: %s" % rel)

        with open('/etc/apt/sources.list.d/juju_deb.list', 'w') as f:
            f.write(src)
    elif rel[:6] == 'cloud:':
        ubuntu_rel = lsb_release()['DISTRIB_CODENAME']
        rel = rel.split(':')[1]
        u_rel = rel.split('-')[0]
        ca_rel = rel.split('-')[1]

        if u_rel != ubuntu_rel:
            e = 'Cannot install from Cloud Archive pocket %s on this Ubuntu '\
                'version (%s)' % (ca_rel, ubuntu_rel)
            error_out(e)

        if ca_rel == 'folsom/staging':
            # staging is just a regular PPA.
            cmd = 'add-apt-repository -y ppa:ubuntu-cloud-archive/folsom-staging'
            subprocess.check_call(cmd.split(' '))
            return

        # map charm config options to actual archive pockets.
        pockets = {
            'folsom': 'precise-updates/folsom',
            'folsom/updates': 'precise-updates/folsom',
            'folsom/proposed': 'precise-proposed/folsom'
        }

        try:
            pocket = pockets[ca_rel]
        except KeyError:
            e = 'Invalid Cloud Archive release specified: %s' % rel
            error_out(e)

        src = "deb %s %s main" % (CLOUD_ARCHIVE_URL, pocket)
        _import_key(CLOUD_ARCHIVE_KEY_ID)

        with open('/etc/apt/sources.list.d/cloud-archive.list', 'w') as f:
            f.write(src)
    else:
        error_out("Invalid openstack-release specified: %s" % rel)