~felipe-alfaro-gmail/charms/xenial/neutron-api/trunk

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
# Copyright 2014-2016 Canonical Limited.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#  http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

#
# Copyright 2016 Canonical Ltd.
#
# Authors:
#  Openstack Charmers <
#

"""
Helpers for high availability.
"""

import re

from charmhelpers.core.hookenv import (
    log,
    relation_set,
    charm_name,
    config,
    status_set,
    DEBUG,
)

from charmhelpers.core.host import (
    lsb_release
)

from charmhelpers.contrib.openstack.ip import (
    resolve_address,
)


class DNSHAException(Exception):
    """Raised when an error occurs setting up DNS HA
    """

    pass


def update_dns_ha_resource_params(resources, resource_params,
                                  relation_id=None,
                                  crm_ocf='ocf:maas:dns'):
    """ Check for os-*-hostname settings and update resource dictionaries for
    the HA relation.

    @param resources: Pointer to dictionary of resources.
                      Usually instantiated in ha_joined().
    @param resource_params: Pointer to dictionary of resource parameters.
                            Usually instantiated in ha_joined()
    @param relation_id: Relation ID of the ha relation
    @param crm_ocf: Corosync Open Cluster Framework resource agent to use for
                    DNS HA
    """

    # Validate the charm environment for DNS HA
    assert_charm_supports_dns_ha()

    settings = ['os-admin-hostname', 'os-internal-hostname',
                'os-public-hostname', 'os-access-hostname']

    # Check which DNS settings are set and update dictionaries
    hostname_group = []
    for setting in settings:
        hostname = config(setting)
        if hostname is None:
            log('DNS HA: Hostname setting {} is None. Ignoring.'
                ''.format(setting),
                DEBUG)
            continue
        m = re.search('os-(.+?)-hostname', setting)
        if m:
            networkspace = m.group(1)
        else:
            msg = ('Unexpected DNS hostname setting: {}. '
                   'Cannot determine network space name'
                   ''.format(setting))
            status_set('blocked', msg)
            raise DNSHAException(msg)

        hostname_key = 'res_{}_{}_hostname'.format(charm_name(), networkspace)
        if hostname_key in hostname_group:
            log('DNS HA: Resource {}: {} already exists in '
                'hostname group - skipping'.format(hostname_key, hostname),
                DEBUG)
            continue

        hostname_group.append(hostname_key)
        resources[hostname_key] = crm_ocf
        resource_params[hostname_key] = (
            'params fqdn="{}" ip_address="{}" '
            ''.format(hostname, resolve_address(endpoint_type=networkspace,
                                                override=False)))

    if len(hostname_group) >= 1:
        log('DNS HA: Hostname group is set with {} as members. '
            'Informing the ha relation'.format(' '.join(hostname_group)),
            DEBUG)
        relation_set(relation_id=relation_id, groups={
            'grp_{}_hostnames'.format(charm_name()): ' '.join(hostname_group)})
    else:
        msg = 'DNS HA: Hostname group has no members.'
        status_set('blocked', msg)
        raise DNSHAException(msg)


def assert_charm_supports_dns_ha():
    """Validate prerequisites for DNS HA
    The MAAS client is only available on Xenial or greater
    """
    if lsb_release().get('DISTRIB_RELEASE') < '16.04':
        msg = ('DNS HA is only supported on 16.04 and greater '
               'versions of Ubuntu.')
        status_set('blocked', msg)
        raise DNSHAException(msg)
    return True


def expect_ha():
    """ Determine if the unit expects to be in HA

    Check for VIP or dns-ha settings which indicate the unit should expect to
    be related to hacluster.

    @returns boolean
    """
    return config('vip') or config('dns-ha')