Esempio n. 1
0
    def get_network_addresses(self):
        """For each network configured, return corresponding address and vip
           (if available).

        Returns a list of tuples of the form:

            [(address_in_net_a, vip_in_net_a),
             (address_in_net_b, vip_in_net_b),
             ...]

            or, if no vip(s) available:

            [(address_in_net_a, address_in_net_a),
             (address_in_net_b, address_in_net_b),
             ...]
        """
        addresses = []
        for net_type in ADDRESS_TYPES:
            net_cfg_opt = os_ip.ADDRESS_MAP[net_type]['config'].replace(
                '-', '_')
            config_cidr = getattr(self, net_cfg_opt, None)
            addr = ch_ip.get_address_in_network(
                config_cidr, hookenv.unit_get('private-address'))
            addresses.append(
                (addr, os_ip.resolve_address(endpoint_type=net_type)))
        return sorted(addresses)
Esempio n. 2
0
    def external_endpoints(self):
        """Dict of service names and attributes that clients use to connect

        @return {
                    'svc1': {
                        'proto': 'http',
                        'ip': '10.0.0.10',
                        'port': '8080',
                        'url': 'http://10.0.0.10:8080},
                    'svc2': {
                        'proto': 'https',
                        'ip': '10.0.0.20',
                        'port': '8443',
                        'url': 'https://10.0.0.20:8443},
                ...

        """
        info = {}
        proto = 'https' if self.apache_enabled else 'http'
        if self.port_map:
            for service in self.port_map.keys():
                key = service.replace('-', '_')
                info[key] = {
                    'proto': proto,
                    'ip': os_ip.resolve_address(os_ip.ADMIN),
                    'port': self.port_map[service][os_ip.ADMIN]
                }
                info[key]['url'] = '{proto}://{ip}:{port}'.format(**info[key])
        return info
Esempio n. 3
0
    def get_default_cn(self):
        """Return the default Canonical Name to be used for TLS setup

        :returns: 'canonical_name'
        :rtype: str
        """
        return os_ip.resolve_address(endpoint_type=os_ip.INTERNAL)
Esempio n. 4
0
    def external_endpoints(self):
        """Dict of service names and attributes that clients use to connect

        @return {
                    'svc1': {
                        'proto': 'http',
                        'ip': '10.0.0.10',
                        'port': '8080',
                        'url': 'http://10.0.0.10:8080},
                    'svc2': {
                        'proto': 'https',
                        'ip': '10.0.0.20',
                        'port': '8443',
                        'url': 'https://10.0.0.20:8443},
                ...

        """
        info = {}
        proto = 'https' if self.apache_enabled else 'http'
        if self.port_map:
            for service in self.port_map.keys():
                key = service.replace('-', '_')
                info[key] = {
                    'proto': proto,
                    'ip': os_ip.resolve_address(os_ip.ADMIN),
                    'port': self.port_map[service][os_ip.ADMIN]}
                info[key]['url'] = '{proto}://{ip}:{port}'.format(**info[key])
        return info
Esempio n. 5
0
    def _add_dnsha_config(self, hacluster):
        """Add a DNSHA object to self.resources

        @param hacluster instance of interface class HAClusterRequires
        """
        if not self.config.get(DNSHA_KEY):
            return
        settings = ['os-admin-hostname', 'os-internal-hostname',
                    'os-public-hostname', 'os-access-hostname']

        for setting in settings:
            hostname = self.config.get(setting)
            if hostname is None:
                hookenv.log(
                    'DNS HA: Hostname setting {} is None. Ignoring.'.format(
                        setting),
                    hookenv.DEBUG)
                continue
            m = re.search('os-(.+?)-hostname', setting)
            if m:
                endpoint_type = m.group(1)
                # resolve_address's ADDRESS_MAP uses 'int' not 'internal'
                if endpoint_type == 'internal':
                    endpoint_type = 'int'
            else:
                msg = (
                    'Unexpected DNS hostname setting: {}. Cannot determine '
                    'endpoint_type name'.format(setting))
                hookenv.status_set('blocked', msg)
                raise os_ha.DNSHAException(msg)
            ip = os_ip.resolve_address(
                endpoint_type=endpoint_type,
                override=False)
            hacluster.add_dnsha(self.name, ip, hostname, endpoint_type)
Esempio n. 6
0
    def get_network_addresses(self):
        """For each network configured, return corresponding address and vip
           (if available).

        Returns a list of tuples of the form:

            [(address_in_net_a, vip_in_net_a),
             (address_in_net_b, vip_in_net_b),
             ...]

            or, if no vip(s) available:

            [(address_in_net_a, address_in_net_a),
             (address_in_net_b, address_in_net_b),
             ...]
        """
        addresses = []
        for net_type in ADDRESS_TYPES:
            net_cfg_opt = os_ip.ADDRESS_MAP[net_type]['config'].replace('-',
                                                                        '_')
            config_cidr = getattr(self, net_cfg_opt, None)
            addr = ch_ip.get_address_in_network(
                config_cidr,
                hookenv.unit_get('private-address'))
            addresses.append(
                (addr, os_ip.resolve_address(endpoint_type=net_type)))
        return sorted(addresses)
Esempio n. 7
0
    def _add_dnsha_config(self, hacluster):
        """Add a DNSHA object to self.resources

        @param hacluster instance of interface class HAClusterRequires
        """
        if not self.config.get(DNSHA_KEY):
            return
        settings = ['os-admin-hostname', 'os-internal-hostname',
                    'os-public-hostname', 'os-access-hostname']

        for setting in settings:
            hostname = self.config.get(setting)
            if hostname is None:
                hookenv.log(
                    'DNS HA: Hostname setting {} is None. Ignoring.'.format(
                        setting),
                    hookenv.DEBUG)
                continue
            m = re.search('os-(.+?)-hostname', setting)
            if m:
                endpoint_type = m.group(1)
                # resolve_address's ADDRESS_MAP uses 'int' not 'internal'
                if endpoint_type == 'internal':
                    endpoint_type = 'int'
            else:
                msg = (
                    'Unexpected DNS hostname setting: {}. Cannot determine '
                    'endpoint_type name'.format(setting))
                hookenv.status_set('blocked', msg)
                raise os_ha.DNSHAException(msg)
            ip = os_ip.resolve_address(
                endpoint_type=endpoint_type,
                override=False)
            hacluster.add_dnsha(self.name, ip, hostname, endpoint_type)
Esempio n. 8
0
    def get_certs_and_keys(self, keystone_interface=None,
                           certificates_interface=None):
        """Collect SSL config for local endpoints

        SSL keys and certs may come from user specified configuration for this
        charm or they may come directly from Keystone.

        If collecting from keystone there may be a certificate and key per
        endpoint (public, admin etc).

        @returns [
            {'key': 'key1', 'cert': 'cert1', 'ca': 'ca1', 'cn': 'cn1'}
            {'key': 'key2', 'cert': 'cert2', 'ca': 'ca2', 'cn': 'cn2'}
            ...
        ]
        """
        if self.config_defined_ssl_key and self.config_defined_ssl_cert:
            ssl_artifacts = []
            for ep_type in [os_ip.INTERNAL, os_ip.ADMIN, os_ip.PUBLIC]:
                ssl_artifacts.append({
                    'key': self.config_defined_ssl_key.decode('utf-8'),
                    'cert': self.config_defined_ssl_cert.decode('utf-8'),
                    'ca': (self.config_defined_ssl_ca.decode('utf-8')
                           if self.config_defined_ssl_ca else None),
                    'cn': os_ip.resolve_address(endpoint_type=ep_type)})
            return ssl_artifacts
        elif keystone_interface:
            keys_and_certs = []
            for addr in self.get_local_addresses():
                key = keystone_interface.get_ssl_key(addr)
                cert = keystone_interface.get_ssl_cert(addr)
                ca = keystone_interface.get_ssl_ca()
                if key and cert:
                    keys_and_certs.append({
                        'key': key,
                        'cert': cert,
                        'ca': ca,
                        'cn': addr})
            return keys_and_certs
        elif certificates_interface:
            keys_and_certs = []
            reqs = certificates_interface.get_batch_requests()
            ca = certificates_interface.get_ca()
            chain = certificates_interface.get_chain()
            for cn, data in sorted(reqs.items()):
                cert = data['cert']
                if chain:
                    cert = cert + os.linesep + chain
                keys_and_certs.append({
                    'key': data['key'],
                    'cert': cert,
                    'ca': ca,
                    'cn': cn})
            return keys_and_certs
        else:
            return []
    def get_certs_and_keys(self,
                           keystone_interface=None,
                           certificates_interface=None):
        """Collect TLS config for local endpoints

        TLS keys and certs may come from user specified configuration for this
        charm or they may come directly from the ``certificates`` relation.

        If collecting from ``certificates`` relation there may be a certificate
        and key per endpoint (public, admin etc).

        :param keystone_interface: DEPRECATED Functionality removed.
        :type keystone_interace: Option[None, KeystoneRequires(RelationBase)]
        :param certificates_interface: Certificates interface object
        :type certificates_interface: TlsRequires(Endpoint)
        :returns: [
            {'key': 'key1', 'cert': 'cert1', 'ca': 'ca1', 'cn': 'cn1'}
            {'key': 'key2', 'cert': 'cert2', 'ca': 'ca2', 'cn': 'cn2'}
            ...
        ]
        :rtype: List[Dict[str,str]]
        """
        if self.config_defined_ssl_key and self.config_defined_ssl_cert:
            ssl_artifacts = []
            for ep_type in [os_ip.INTERNAL, os_ip.ADMIN, os_ip.PUBLIC]:
                ssl_artifacts.append({
                    'key':
                    self.config_defined_ssl_key.decode('utf-8'),
                    'cert':
                    self.config_defined_ssl_cert.decode('utf-8'),
                    'ca': (self.config_defined_ssl_ca.decode('utf-8')
                           if self.config_defined_ssl_ca else None),
                    'cn':
                    os_ip.resolve_address(endpoint_type=ep_type)
                })
            return ssl_artifacts
        elif certificates_interface:
            keys_and_certs = []
            reqs = certificates_interface.get_batch_requests()
            ca = certificates_interface.get_ca()
            chain = certificates_interface.get_chain()
            for cn, data in sorted(reqs.items()):
                cert = data['cert']
                if chain:
                    cert = cert + os.linesep + chain
                keys_and_certs.append({
                    'key': data['key'],
                    'cert': cert,
                    'ca': ca,
                    'chain': chain,
                    'cn': cn
                })
            return keys_and_certs
        else:
            return []
Esempio n. 10
0
    def get_local_addresses(self):
        """Return list of local addresses on each configured network

        For each network return an address the local unit has on that network
        if one exists.

        @returns [private_addr, admin_addr, public_addr, ...]
        """
        addresses = [os_utils.get_host_ip(hookenv.unit_get('private-address'))]
        for addr_type in os_ip.ADDRESS_MAP.keys():
            laddr = os_ip.resolve_address(endpoint_type=addr_type)
            if laddr:
                addresses.append(laddr)
        return sorted(list(set(addresses)))
Esempio n. 11
0
    def get_local_addresses(self):
        """Return list of local addresses on each configured network

        For each network return an address the local unit has on that network
        if one exists.

        @returns [private_addr, admin_addr, public_addr, ...]
        """
        addresses = [
            os_utils.get_host_ip(hookenv.unit_get('private-address'))]
        for addr_type in os_ip.ADDRESS_MAP.keys():
            laddr = os_ip.resolve_address(endpoint_type=addr_type)
            if laddr:
                addresses.append(laddr)
        return sorted(list(set(addresses)))
Esempio n. 12
0
    def configure_cert(self, cert, key, cn=None):
        """Configure service SSL cert and key

        Write out service SSL certificate and key for Apache.

        @param cert string SSL Certificate
        @param key string SSL Key
        @param cn string Canonical name for service
        """
        if not cn:
            cn = os_ip.resolve_address(endpoint_type=os_ip.INTERNAL)
        ssl_dir = os.path.join('/etc/apache2/ssl/', self.name)
        ch_host.mkdir(path=ssl_dir)
        if cn:
            cert_filename = 'cert_{}'.format(cn)
            key_filename = 'key_{}'.format(cn)
        else:
            cert_filename = 'cert'
            key_filename = 'key'

        ch_host.write_file(path=os.path.join(ssl_dir, cert_filename),
                           content=cert.encode('utf-8'))
        ch_host.write_file(path=os.path.join(ssl_dir, key_filename),
                           content=key.encode('utf-8'))
Esempio n. 13
0
    def configure_cert(self, cert, key, cn=None):
        """Configure service SSL cert and key

        Write out service SSL certificate and key for Apache.

        @param cert string SSL Certificate
        @param key string SSL Key
        @param cn string Canonical name for service
        """
        if not cn:
            cn = os_ip.resolve_address(endpoint_type=os_ip.INTERNAL)
        ssl_dir = os.path.join('/etc/apache2/ssl/', self.name)
        ch_host.mkdir(path=ssl_dir)
        if cn:
            cert_filename = 'cert_{}'.format(cn)
            key_filename = 'key_{}'.format(cn)
        else:
            cert_filename = 'cert'
            key_filename = 'key'

        ch_host.write_file(path=os.path.join(ssl_dir, cert_filename),
                           content=cert.encode('utf-8'))
        ch_host.write_file(path=os.path.join(ssl_dir, key_filename),
                           content=key.encode('utf-8'))
Esempio n. 14
0
    def get_default_cn(self):
        """Return the default Canonical Name to be used for SSL setup

        @returns 'canonical_name'
        """
        return os_ip.resolve_address(endpoint_type=os_ip.INTERNAL)
Esempio n. 15
0
    def test_resolve_address(self):
        self.patch_object(ip.cluster, 'is_clustered')
        self.patch_object(ip.hookenv, 'config')
        self.patch_object(ip.hookenv, 'network_get_primary_address')
        self.patch_object(ip.net_ip, 'is_address_in_network')
        self.patch_object(ip.net_ip, 'get_ipv6_addr')
        self.patch_object(ip.hookenv, 'unit_get')
        self.patch_object(ip.net_ip, 'get_address_in_network')

        # define a fake_config() that returns predictable results and remembers
        # what it was called with.
        calls_list = []
        _config = {
            'vip': 'vip-address',
            'prefer-ipv6': False,
            'os-public-network': 'the-public-network',
            'os-public-hostname': None,
            'os-internal-network': 'the-internal-network',
            'os-admin-network': 'the-admin-network',
        }

        def fake_config(*args):
            calls_list.append(args)
            return _config[args[0]]

        self.config.side_effect = fake_config

        # Juju pre 2.0 behaviour where network-get is not implemented
        self.network_get_primary_address.side_effect = NotImplementedError

        # first test, if not clustered, that the function uses unit_get() and
        # get_address_in_network to get a real address.
        # for the default PUBLIC endpoint
        self.is_clustered.return_value = False
        self.get_address_in_network.return_value = 'got-address'
        self.unit_get.return_value = 'unit-get-address'
        addr = ip.resolve_address()
        self.assertEqual(addr, 'got-address')
        self.assertEqual(calls_list, [('os-public-hostname', ), ('vip', ),
                                      ('os-public-network', ),
                                      ('prefer-ipv6', )])
        self.unit_get.assert_called_once_with('public-address')
        self.get_address_in_network.assert_called_once_with(
            'the-public-network', 'unit-get-address')

        # second test: not clustered, prefer-ipv6 is True
        _config['prefer-ipv6'] = True
        calls_list = []
        self.get_ipv6_addr.return_value = ['ipv6-addr']
        self.get_address_in_network.reset_mock()
        addr = ip.resolve_address()
        self.get_ipv6_addr.assert_called_once_with(exc_list=['vip-address'])
        self.get_address_in_network.assert_called_once_with(
            'the-public-network', 'ipv6-addr')

        # Third test: clustered, and config(...) returns None
        self.is_clustered.return_value = True
        _config['os-public-network'] = None
        calls_list = []
        addr = ip.resolve_address()
        self.assertEqual(calls_list, [('os-public-hostname', ), ('vip', ),
                                      ('os-public-network', )])

        # Fourth test: clustered, and config(...) returns not None
        _config['os-public-network'] = 'the-public-network'
        calls_list = []
        _config['vip'] = 'vip1 vip2'

        def _fake_addr_in_net(address, vip):
            return True if vip == 'vip2' else False

        self.is_address_in_network.side_effect = _fake_addr_in_net
        addr = ip.resolve_address()
        self.assertEqual(calls_list, [
            ('os-public-hostname', ),
            ('vip', ),
            ('os-public-network', ),
        ])
        self.assertEqual(addr, 'vip2')

        # Finally resolved_address returns None -> ValueError()
        # allow vip to not be found:
        self.is_address_in_network.return_value = False
        self.is_address_in_network.side_effect = None
        with self.assertRaises(ValueError):
            addr = ip.resolve_address()
Esempio n. 16
0
    def get_certs_and_keys(self,
                           keystone_interface=None,
                           certificates_interface=None):
        """Collect SSL config for local endpoints

        SSL keys and certs may come from user specified configuration for this
        charm or they may come directly from Keystone.

        If collecting from keystone there may be a certificate and key per
        endpoint (public, admin etc).

        @returns [
            {'key': 'key1', 'cert': 'cert1', 'ca': 'ca1', 'cn': 'cn1'}
            {'key': 'key2', 'cert': 'cert2', 'ca': 'ca2', 'cn': 'cn2'}
            ...
        ]
        """
        if self.config_defined_ssl_key and self.config_defined_ssl_cert:
            ssl_artifacts = []
            for ep_type in [os_ip.INTERNAL, os_ip.ADMIN, os_ip.PUBLIC]:
                ssl_artifacts.append({
                    'key':
                    self.config_defined_ssl_key.decode('utf-8'),
                    'cert':
                    self.config_defined_ssl_cert.decode('utf-8'),
                    'ca': (self.config_defined_ssl_ca.decode('utf-8')
                           if self.config_defined_ssl_ca else None),
                    'cn':
                    os_ip.resolve_address(endpoint_type=ep_type)
                })
            return ssl_artifacts
        elif keystone_interface:
            keys_and_certs = []
            for addr in self.get_local_addresses():
                key = keystone_interface.get_ssl_key(addr)
                cert = keystone_interface.get_ssl_cert(addr)
                ca = keystone_interface.get_ssl_ca()
                if key and cert:
                    keys_and_certs.append({
                        'key': key,
                        'cert': cert,
                        'ca': ca,
                        'cn': addr
                    })
            return keys_and_certs
        elif certificates_interface:
            keys_and_certs = []
            reqs = certificates_interface.get_batch_requests()
            ca = certificates_interface.get_ca()
            chain = certificates_interface.get_chain()
            for cn, data in sorted(reqs.items()):
                cert = data['cert']
                if chain:
                    cert = cert + os.linesep + chain
                keys_and_certs.append({
                    'key': data['key'],
                    'cert': cert,
                    'ca': ca,
                    'cn': cn
                })
            return keys_and_certs
        else:
            return []
Esempio n. 17
0
 def access_ip(self):
     return resolve_address()
Esempio n. 18
0
def rndc_master_ip(config):
    """Returns IP address slave DNS slave should use to query master
    """
    return os_ip.resolve_address(endpoint_type=os_ip.INTERNAL)
    def test_resolve_address_network_binding(self):
        self.patch_object(ip.cluster, 'is_clustered')
        self.patch_object(ip.hookenv, 'config')
        self.patch_object(ip.hookenv, 'network_get_primary_address')
        self.patch_object(ip.net_ip, 'is_address_in_network')
        self.patch_object(ip.net_ip, 'get_ipv6_addr')
        self.patch_object(ip.hookenv, 'unit_get')
        self.patch_object(ip.net_ip, 'get_address_in_network')
        self.patch_object(ip, '_resolve_network_cidr')

        # define a fake_config() that returns predictable results and remembers
        # what it was called with.
        calls_list = []
        _config = {
            'vip': 'vip1 vip2',
            'prefer-ipv6': False,
            'os-public-network': None,
            'os-public-hostname': None,
            'os-internal-network': None,
            'os-admin-network': None,
        }

        def fake_config(*args):
            calls_list.append(args)
            return _config[args[0]]

        self.config.side_effect = fake_config

        # first test, if not clustered, that the function uses unit_get
        # network_get_primary_address to get a real address.
        # for the default PUBLIC endpoint
        self.is_clustered.return_value = False
        self.network_get_primary_address.return_value = 'got-address'
        self._resolve_network_cidr.return_value = 'cidr'
        self.unit_get.return_value = 'unit-get-address'
        addr = ip.resolve_address()
        self.assertEqual(addr, 'got-address')
        self.assertEqual(calls_list,
                         [('os-public-hostname',),
                          ('vip',),
                          ('os-public-network',),
                          ('prefer-ipv6',)])
        self.unit_get.assert_called_once_with('public-address')
        self.network_get_primary_address.assert_called_with(
            'public'
        )

        # second test: not clustered, prefer-ipv6 is True, ensure
        # that ipv6 address is fallback and network-get is still
        # used to determine the public endpoint binding
        _config['prefer-ipv6'] = True
        calls_list = []
        self.get_ipv6_addr.return_value = ['ipv6-addr']
        self.get_address_in_network.reset_mock()
        addr = ip.resolve_address()
        self.get_ipv6_addr.assert_called_once_with(exc_list=['vip1', 'vip2'])
        self.network_get_primary_address.assert_called_with(
            'public'
        )

        def _fake_addr_in_net(address, vip):
            return True if vip == 'vip2' else False

        self.is_address_in_network.side_effect = _fake_addr_in_net

        # Third test: clustered
        self.is_clustered.return_value = True
        calls_list = []
        addr = ip.resolve_address()
        self.assertEqual(calls_list, [('os-public-hostname',),
                                      ('vip',),
                                      ('os-public-network',)])
        self.network_get_primary_address.assert_called_with(
            'public'
        )

        # Fourth test: clustered, and config(...) returns not None
        _config['os-public-network'] = 'the-public-network'
        calls_list = []
        _config['vip'] = 'vip1 vip2'

        addr = ip.resolve_address()
        self.assertEqual(calls_list, [
            ('os-public-hostname',),
            ('vip',),
            ('os-public-network',),
        ])
        self.assertEqual(addr, 'vip2')
        self.network_get_primary_address.assert_called_with(
            'public'
        )
Esempio n. 20
0
    def get_default_cn(self):
        """Return the default Canonical Name to be used for SSL setup

        @returns 'canonical_name'
        """
        return os_ip.resolve_address(endpoint_type=os_ip.INTERNAL)
Esempio n. 21
0
    def test_resolve_address_network_binding(self):
        self.patch_object(ip.cluster, 'is_clustered')
        self.patch_object(ip.hookenv, 'config')
        self.patch_object(ip.hookenv, 'network_get_primary_address')
        self.patch_object(ip.net_ip, 'is_address_in_network')
        self.patch_object(ip.net_ip, 'get_ipv6_addr')
        self.patch_object(ip.hookenv, 'unit_get')
        self.patch_object(ip.net_ip, 'get_address_in_network')
        self.patch_object(ip, '_resolve_network_cidr')

        # define a fake_config() that returns predictable results and remembers
        # what it was called with.
        calls_list = []
        _config = {
            'vip': 'vip1 vip2',
            'prefer-ipv6': False,
            'os-public-network': None,
            'os-public-hostname': None,
            'os-internal-network': None,
            'os-admin-network': None,
        }

        def fake_config(*args):
            calls_list.append(args)
            return _config[args[0]]

        self.config.side_effect = fake_config

        # first test, if not clustered, that the function uses unit_get
        # network_get_primary_address to get a real address.
        # for the default PUBLIC endpoint
        self.is_clustered.return_value = False
        self.network_get_primary_address.return_value = 'got-address'
        self._resolve_network_cidr.return_value = 'cidr'
        self.unit_get.return_value = 'unit-get-address'
        addr = ip.resolve_address()
        self.assertEqual(addr, 'got-address')
        self.assertEqual(calls_list, [('os-public-hostname', ), ('vip', ),
                                      ('os-public-network', ),
                                      ('prefer-ipv6', )])
        self.unit_get.assert_called_once_with('public-address')
        self.network_get_primary_address.assert_called_with('public')

        # second test: not clustered, prefer-ipv6 is True, ensure
        # that ipv6 address is fallback and network-get is still
        # used to determine the public endpoint binding
        _config['prefer-ipv6'] = True
        calls_list = []
        self.get_ipv6_addr.return_value = ['ipv6-addr']
        self.get_address_in_network.reset_mock()
        addr = ip.resolve_address()
        self.get_ipv6_addr.assert_called_once_with(exc_list=['vip1', 'vip2'])
        self.network_get_primary_address.assert_called_with('public')

        def _fake_addr_in_net(address, vip):
            return True if vip == 'vip2' else False

        self.is_address_in_network.side_effect = _fake_addr_in_net

        # Third test: clustered
        self.is_clustered.return_value = True
        calls_list = []
        addr = ip.resolve_address()
        self.assertEqual(calls_list, [('os-public-hostname', ), ('vip', ),
                                      ('os-public-network', )])
        self.network_get_primary_address.assert_called_with('public')

        # Fourth test: clustered, and config(...) returns not None
        _config['os-public-network'] = 'the-public-network'
        calls_list = []
        _config['vip'] = 'vip1 vip2'

        addr = ip.resolve_address()
        self.assertEqual(calls_list, [
            ('os-public-hostname', ),
            ('vip', ),
            ('os-public-network', ),
        ])
        self.assertEqual(addr, 'vip2')
        self.network_get_primary_address.assert_called_with('public')
    def test_resolve_address(self):
        self.patch_object(ip.cluster, 'is_clustered')
        self.patch_object(ip.hookenv, 'config')
        self.patch_object(ip.hookenv, 'network_get_primary_address')
        self.patch_object(ip.net_ip, 'is_address_in_network')
        self.patch_object(ip.net_ip, 'get_ipv6_addr')
        self.patch_object(ip.hookenv, 'unit_get')
        self.patch_object(ip.net_ip, 'get_address_in_network')

        # define a fake_config() that returns predictable results and remembers
        # what it was called with.
        calls_list = []
        _config = {
            'vip': 'vip-address',
            'prefer-ipv6': False,
            'os-public-network': 'the-public-network',
            'os-public-hostname': None,
            'os-internal-network': 'the-internal-network',
            'os-admin-network': 'the-admin-network',
        }

        def fake_config(*args):
            calls_list.append(args)
            return _config[args[0]]

        self.config.side_effect = fake_config

        # Juju pre 2.0 behaviour where network-get is not implemented
        self.network_get_primary_address.side_effect = NotImplementedError

        # first test, if not clustered, that the function uses unit_get() and
        # get_address_in_network to get a real address.
        # for the default PUBLIC endpoint
        self.is_clustered.return_value = False
        self.get_address_in_network.return_value = 'got-address'
        self.unit_get.return_value = 'unit-get-address'
        addr = ip.resolve_address()
        self.assertEqual(addr, 'got-address')
        self.assertEqual(calls_list,
                         [('os-public-hostname',),
                          ('vip',),
                          ('os-public-network',),
                          ('prefer-ipv6',)])
        self.unit_get.assert_called_once_with('public-address')
        self.get_address_in_network.assert_called_once_with(
            'the-public-network', 'unit-get-address')

        # second test: not clustered, prefer-ipv6 is True
        _config['prefer-ipv6'] = True
        calls_list = []
        self.get_ipv6_addr.return_value = ['ipv6-addr']
        self.get_address_in_network.reset_mock()
        addr = ip.resolve_address()
        self.get_ipv6_addr.assert_called_once_with(exc_list=['vip-address'])
        self.get_address_in_network.assert_called_once_with(
            'the-public-network', 'ipv6-addr')

        # Third test: clustered, and config(...) returns None
        self.is_clustered.return_value = True
        _config['os-public-network'] = None
        calls_list = []
        addr = ip.resolve_address()
        self.assertEqual(calls_list, [('os-public-hostname',),
                                      ('vip',),
                                      ('os-public-network',)])

        # Fourth test: clustered, and config(...) returns not None
        _config['os-public-network'] = 'the-public-network'
        calls_list = []
        _config['vip'] = 'vip1 vip2'

        def _fake_addr_in_net(address, vip):
            return True if vip == 'vip2' else False

        self.is_address_in_network.side_effect = _fake_addr_in_net
        addr = ip.resolve_address()
        self.assertEqual(calls_list, [
            ('os-public-hostname',),
            ('vip',),
            ('os-public-network',),
        ])
        self.assertEqual(addr, 'vip2')

        # Finally resolved_address returns None -> ValueError()
        # allow vip to not be found:
        self.is_address_in_network.return_value = False
        self.is_address_in_network.side_effect = None
        with self.assertRaises(ValueError):
            addr = ip.resolve_address()
Esempio n. 23
0
 def rndc_master_ip(self):
     """Returns IP address slave DNS slave should use to query master
     """
     return os_ip.resolve_address(endpoint_type=os_ip.INTERNAL)