~openstack-charmers/charms/trusty/glance-simplestreams-sync/next

« back to all changes in this revision

Viewing changes to hooks/charmhelpers/contrib/openstack/ip.py

[freyes,r=billy-olsen]

Refactor config-changed hook to ensure that cron jobs are installed
properly.

Closes-Bug: #1434356

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright 2014-2015 Canonical Limited.
2
 
#
3
 
# This file is part of charm-helpers.
4
 
#
5
 
# charm-helpers is free software: you can redistribute it and/or modify
6
 
# it under the terms of the GNU Lesser General Public License version 3 as
7
 
# published by the Free Software Foundation.
8
 
#
9
 
# charm-helpers is distributed in the hope that it will be useful,
10
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 
# GNU Lesser General Public License for more details.
13
 
#
14
 
# You should have received a copy of the GNU Lesser General Public License
15
 
# along with charm-helpers.  If not, see <http://www.gnu.org/licenses/>.
16
 
 
17
 
from charmhelpers.core.hookenv import (
18
 
    config,
19
 
    unit_get,
20
 
    service_name,
21
 
)
22
 
from charmhelpers.contrib.network.ip import (
23
 
    get_address_in_network,
24
 
    is_address_in_network,
25
 
    is_ipv6,
26
 
    get_ipv6_addr,
27
 
)
28
 
from charmhelpers.contrib.hahelpers.cluster import is_clustered
29
 
 
30
 
PUBLIC = 'public'
31
 
INTERNAL = 'int'
32
 
ADMIN = 'admin'
33
 
 
34
 
ADDRESS_MAP = {
35
 
    PUBLIC: {
36
 
        'config': 'os-public-network',
37
 
        'fallback': 'public-address',
38
 
        'override': 'os-public-hostname',
39
 
    },
40
 
    INTERNAL: {
41
 
        'config': 'os-internal-network',
42
 
        'fallback': 'private-address',
43
 
        'override': 'os-internal-hostname',
44
 
    },
45
 
    ADMIN: {
46
 
        'config': 'os-admin-network',
47
 
        'fallback': 'private-address',
48
 
        'override': 'os-admin-hostname',
49
 
    }
50
 
}
51
 
 
52
 
 
53
 
def canonical_url(configs, endpoint_type=PUBLIC):
54
 
    """Returns the correct HTTP URL to this host given the state of HTTPS
55
 
    configuration, hacluster and charm configuration.
56
 
 
57
 
    :param configs: OSTemplateRenderer config templating object to inspect
58
 
                    for a complete https context.
59
 
    :param endpoint_type: str endpoint type to resolve.
60
 
    :param returns: str base URL for services on the current service unit.
61
 
    """
62
 
    scheme = _get_scheme(configs)
63
 
 
64
 
    address = resolve_address(endpoint_type)
65
 
    if is_ipv6(address):
66
 
        address = "[{}]".format(address)
67
 
 
68
 
    return '%s://%s' % (scheme, address)
69
 
 
70
 
 
71
 
def _get_scheme(configs):
72
 
    """Returns the scheme to use for the url (either http or https)
73
 
    depending upon whether https is in the configs value.
74
 
 
75
 
    :param configs: OSTemplateRenderer config templating object to inspect
76
 
                    for a complete https context.
77
 
    :returns: either 'http' or 'https' depending on whether https is
78
 
              configured within the configs context.
79
 
    """
80
 
    scheme = 'http'
81
 
    if configs and 'https' in configs.complete_contexts():
82
 
        scheme = 'https'
83
 
    return scheme
84
 
 
85
 
 
86
 
def _get_address_override(endpoint_type=PUBLIC):
87
 
    """Returns any address overrides that the user has defined based on the
88
 
    endpoint type.
89
 
 
90
 
    Note: this function allows for the service name to be inserted into the
91
 
    address if the user specifies {service_name}.somehost.org.
92
 
 
93
 
    :param endpoint_type: the type of endpoint to retrieve the override
94
 
                          value for.
95
 
    :returns: any endpoint address or hostname that the user has overridden
96
 
              or None if an override is not present.
97
 
    """
98
 
    override_key = ADDRESS_MAP[endpoint_type]['override']
99
 
    addr_override = config(override_key)
100
 
    if not addr_override:
101
 
        return None
102
 
    else:
103
 
        return addr_override.format(service_name=service_name())
104
 
 
105
 
 
106
 
def resolve_address(endpoint_type=PUBLIC):
107
 
    """Return unit address depending on net config.
108
 
 
109
 
    If unit is clustered with vip(s) and has net splits defined, return vip on
110
 
    correct network. If clustered with no nets defined, return primary vip.
111
 
 
112
 
    If not clustered, return unit address ensuring address is on configured net
113
 
    split if one is configured.
114
 
 
115
 
    :param endpoint_type: Network endpoing type
116
 
    """
117
 
    resolved_address = _get_address_override(endpoint_type)
118
 
    if resolved_address:
119
 
        return resolved_address
120
 
 
121
 
    vips = config('vip')
122
 
    if vips:
123
 
        vips = vips.split()
124
 
 
125
 
    net_type = ADDRESS_MAP[endpoint_type]['config']
126
 
    net_addr = config(net_type)
127
 
    net_fallback = ADDRESS_MAP[endpoint_type]['fallback']
128
 
    clustered = is_clustered()
129
 
    if clustered:
130
 
        if not net_addr:
131
 
            # If no net-splits defined, we expect a single vip
132
 
            resolved_address = vips[0]
133
 
        else:
134
 
            for vip in vips:
135
 
                if is_address_in_network(net_addr, vip):
136
 
                    resolved_address = vip
137
 
                    break
138
 
    else:
139
 
        if config('prefer-ipv6'):
140
 
            fallback_addr = get_ipv6_addr(exc_list=vips)[0]
141
 
        else:
142
 
            fallback_addr = unit_get(net_fallback)
143
 
 
144
 
        resolved_address = get_address_in_network(net_addr, fallback_addr)
145
 
 
146
 
    if resolved_address is None:
147
 
        raise ValueError("Unable to resolve a suitable IP address based on "
148
 
                         "charm state and configuration. (net_type=%s, "
149
 
                         "clustered=%s)" % (net_type, clustered))
150
 
 
151
 
    return resolved_address