~openstack-charmers-next/charms/trusty/neutron-api-odl/trunk

« back to all changes in this revision

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

  • Committer: Liam Young
  • Date: 2015-06-24 12:22:08 UTC
  • Revision ID: liam.young@canonical.com-20150624122208-u7h333w734rilf5q
First cut

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