Exemplo n.º 1
0
def configure_resources(*args):
    """Create/discover resources for management of load balancer instances."""
    if not reactive.is_flag_set('leadership.is_leader'):
        return ch_core.hookenv.action_fail('action must be run on the leader '
                                           'unit.')
    if not reactive.all_flags_set(
            'identity-service.available', 'neutron-api.available',
            'sdn-subordinate.available', 'amqp.available'):
        return ch_core.hookenv.action_fail('all required relations not '
                                           'available, please defer action'
                                           'until deployment is complete.')
    identity_service = reactive.endpoint_from_flag(
        'identity-service.available')
    try:
        (network, secgrp) = api_crud.get_mgmt_network(
            identity_service,
            create=reactive.is_flag_set('config.default.create-mgmt-network'),
        )
    except api_crud.APIUnavailable as e:
        ch_core.hookenv.action_fail(
            'Neutron API not available yet, deferring '
            'network creation/discovery. ("{}")'.format(e))
        return
    if network and secgrp:
        leadership.leader_set({
            'amp-boot-network-list': network['id'],
            'amp-secgroup-list': secgrp['id']
        })
    if reactive.is_flag_set('config.default.custom-amp-flavor-id'):
        # NOTE(fnordahl): custom flavor provided through configuration is
        # handled in the charm class configuration property.
        try:
            flavor = api_crud.get_nova_flavor(identity_service)
        except api_crud.APIUnavailable as e:
            ch_core.hookenv.action_fail('Nova API not available yet, '
                                        'deferring flavor '
                                        'creation. ("{}")'.format(e))
            return
        else:
            leadership.leader_set({'amp-flavor-id': flavor.id})

    amp_key_name = ch_core.hookenv.config('amp-ssh-key-name')
    if amp_key_name:
        identity_service = reactive.endpoint_from_flag(
            'identity-service.available')
        api_crud.create_nova_keypair(identity_service, amp_key_name)

    # Set qutotas to unlimited
    try:
        api_crud.set_service_quotas_unlimited(identity_service)
    except api_crud.APIUnavailable as e:
        ch_core.hookenv.action_fail(
            'Unbable to set quotas to unlimited: {}'.format(e))

    # execute port setup for leader, the followers will execute theirs on
    # `leader-settings-changed` hook
    with charm.provide_charm_instance() as octavia_charm:
        api_crud.setup_hm_port(identity_service, octavia_charm)
        octavia_charm.render_all_configs()
        octavia_charm._assess_status()
 def test_setup_hm_port(self):
     self.patch('subprocess.check_output', 'check_output')
     self.patch('subprocess.check_call', 'check_call')
     self.patch_object(api_crud, 'get_hm_port')
     self.patch_object(api_crud, 'toggle_hm_port')
     identity_service = mock.MagicMock()
     octavia_charm = mock.MagicMock()
     port_uuid = 'fake-port-uuid'
     port_mac_address = 'fake-mac-address'
     self.get_hm_port.return_value = {
         'id': port_uuid,
         'mac_address': port_mac_address,
         'admin_state_up': False,
         'status': 'DOWN',
     }
     e = subprocess.CalledProcessError(returncode=1, cmd=None)
     e.output = ('Device "{}" does not exist.'.format(
         api_crud.octavia.OCTAVIA_MGMT_INTF))
     self.check_output.side_effect = e
     api_crud.setup_hm_port(identity_service, octavia_charm)
     self.get_hm_port.assert_called_with(identity_service,
                                         octavia_charm.local_unit_name,
                                         octavia_charm.local_address,
                                         host_id=None)
     self.check_output.assert_called_with(
         ['ip', 'link', 'show', api_crud.octavia.OCTAVIA_MGMT_INTF],
         stderr=-2,
         universal_newlines=True)
     self.check_call.assert_has_calls([
         mock.call([
             'ovs-vsctl', '--', 'add-port',
             api_crud.octavia.OCTAVIA_INT_BRIDGE,
             api_crud.octavia.OCTAVIA_MGMT_INTF, '--', 'set', 'Interface',
             api_crud.octavia.OCTAVIA_MGMT_INTF, 'type=internal', '--',
             'set', 'Interface', api_crud.octavia.OCTAVIA_MGMT_INTF,
             'external-ids:iface-status=active', '--', 'set', 'Interface',
             api_crud.octavia.OCTAVIA_MGMT_INTF,
             'external-ids:attached-mac={}'.format(port_mac_address), '--',
             'set', 'Interface', api_crud.octavia.OCTAVIA_MGMT_INTF,
             'external-ids:iface-id={}'.format(port_uuid), '--', 'set',
             'Interface', api_crud.octavia.OCTAVIA_MGMT_INTF,
             'external-ids:skip_cleanup=true'
         ]),
         mock.call([
             'ip', 'link', 'set', 'o-hm0', 'up', 'address',
             'fake-mac-address'
         ]),
     ])
     self.check_call.assert_called_with([
         'ip', 'link', 'set', api_crud.octavia.OCTAVIA_MGMT_INTF, 'up',
         'address', port_mac_address
     ])
     self.toggle_hm_port.assert_called
def setup_hm_port():
    """Create a per unit Neutron and OVS port for Octavia Health Manager.

    This is used to plug the unit into the overlay network for direct
    communication with the octavia managed load balancer instances running
    within the deployed cloud.
    """
    neutron_ovs = reactive.endpoint_from_flag('neutron-openvswitch.connected')
    ovsdb = reactive.endpoint_from_flag('ovsdb-subordinate.available')
    host_id = neutron_ovs.host() if neutron_ovs else ovsdb.chassis_name
    with charm.provide_charm_instance() as octavia_charm:
        identity_service = reactive.endpoint_from_flag(
            'identity-service.available')
        try:
            if api_crud.setup_hm_port(
                    identity_service,
                    octavia_charm,
                    host_id=host_id):
                # trigger config render to make systemd-networkd bring up
                # automatic IP configuration of the new port right now.
                reactive.set_flag('config.changed')
                if reactive.is_flag_set('charm.octavia.action_setup_hm_port'):
                    reactive.clear_flag('charm.octavia.action_setup_hm_port')
        except api_crud.APIUnavailable as e:
            ch_core.hookenv.log('Neutron API not available yet, deferring '
                                'port discovery. ("{}")'
                                .format(e),
                                level=ch_core.hookenv.DEBUG)
            return