def configure(self, worker_context, failure_state=RESTART, attempts=None): self.log.debug('Begin router config') self.state = UP attempts = attempts or cfg.CONF.max_retries # FIXME: This might raise an error, which doesn't mean the # *router* is broken, but does mean we can't update it. # Change the exception to something the caller can catch # safely. self._ensure_cache(worker_context) if self.state == GONE: return addr = _get_management_address(self.router_obj) # FIXME: This should raise an explicit exception so the caller # knows that we could not talk to the router (versus the issue # above). interfaces = router_api.get_interfaces( addr, cfg.CONF.akanda_mgt_service_port) if not self._verify_interfaces(self.router_obj, interfaces): # FIXME: Need a REPLUG state when we support hot-plugging # interfaces. self.log.debug("Interfaces aren't plugged as expected.") self.state = REPLUG return # FIXME: Need to catch errors talking to neutron here. config = configuration.build_config(worker_context.neutron, self.router_obj, interfaces) self.log.debug('preparing to update config to %r', config) for i in xrange(attempts): try: router_api.update_config(addr, cfg.CONF.akanda_mgt_service_port, config) except Exception: if i == attempts - 1: # Only log the traceback if we encounter it many times. self.log.exception('failed to update config') else: self.log.debug('failed to update config, attempt %d', i) time.sleep(cfg.CONF.retry_delay) else: self.state = CONFIGURED self.log.info('Router config updated') return else: # FIXME: We failed to configure the router too many times, # so restart it. self.state = failure_state
def update_config(self, management_address, config): """Updates appliance configuration This is responsible for pushing configuration to the managed appliance """ self.log.info(_('Updating config for %s'), self.name) start_time = timeutils.utcnow() akanda_client.update_config(management_address, self.mgt_port, config) delta = timeutils.delta_seconds(start_time, timeutils.utcnow()) self.log.info(_('Config updated for %s after %s seconds'), self.name, round(delta, 2))
def update_config(self, management_address, config): """Updates appliance configuration This is responsible for pushing configuration to the managed appliance """ self.log.info(_('Updating config for %s'), self.name) start_time = timeutils.utcnow() akanda_client.update_config( management_address, self.mgt_port, config) delta = timeutils.delta_seconds(start_time, timeutils.utcnow()) self.log.info(_('Config updated for %s after %s seconds'), self.name, round(delta, 2))
def test_update_config_failure(self): config = {'foo': 'bar'} self.mock_put.return_value.status_code = 500 self.mock_put.return_value.text = 'error_text' with self.assertRaises(Exception): akanda_client.update_config('fe80::2', 5000, config) self.mock_put.assert_called_once_with( 'http://[fe80::2]:5000/v1/system/config', data='{"foo": "bar"}', headers={'Content-type': 'application/json'}, timeout=90)
def configure(self, worker_context, failure_state=RESTART, attempts=None): self.log.debug("Begin router config") self.state = UP attempts = attempts or cfg.CONF.max_retries # FIXME: This might raise an error, which doesn't mean the # *router* is broken, but does mean we can't update it. # Change the exception to something the caller can catch # safely. self._ensure_cache(worker_context) if self.state == GONE: return addr = _get_management_address(self.router_obj) # FIXME: This should raise an explicit exception so the caller # knows that we could not talk to the router (versus the issue # above). interfaces = router_api.get_interfaces(addr, cfg.CONF.akanda_mgt_service_port) if not self._verify_interfaces(self.router_obj, interfaces): # FIXME: Need a REPLUG state when we support hot-plugging # interfaces. self.log.debug("Interfaces aren't plugged as expected.") self.state = REPLUG return # FIXME: Need to catch errors talking to neutron here. config = configuration.build_config(worker_context.neutron, self.router_obj, interfaces) self.log.debug("preparing to update config to %r", config) for i in xrange(attempts): try: router_api.update_config(addr, cfg.CONF.akanda_mgt_service_port, config) except Exception: if i == attempts - 1: # Only log the traceback if we encounter it many times. self.log.exception("failed to update config") else: self.log.debug("failed to update config, attempt %d", i) time.sleep(cfg.CONF.retry_delay) else: self.state = CONFIGURED self.log.info("Router config updated") return else: # FIXME: We failed to configure the router too many times, # so restart it. self.state = failure_state
def test_update_config_failure(self): config = {"foo": "bar"} self.mock_put.return_value.status_code = 500 self.mock_put.return_value.text = "error_text" with self.assertRaises(Exception): akanda_client.update_config("fe80::2", 5000, config) self.mock_put.assert_called_once_with( "http://[fe80::2]:5000/v1/system/config", data='{"foo": "bar"}', headers={"Content-type": "application/json"}, timeout=90, )
def test_update_config_failure(self): config = {'foo': 'bar'} self.mock_put.return_value.status_code = 500 self.mock_put.return_value.text = 'error_text' with self.assertRaises(Exception): akanda_client.update_config('fe80::2', 5000, config) self.mock_put.assert_called_once_with( 'http://[fe80::2]:5000/v1/system/config', data='{"foo": "bar"}', headers={'Content-type': 'application/json'}, timeout=90 )
def test_update_config(self): config = {'foo': 'bar'} self.mock_put.return_value.status_code = 200 self.mock_put.return_value.json.return_value = config resp = akanda_client.update_config('fe80::2', 5000, config) self.mock_put.assert_called_once_with( 'http://[fe80::2]:5000/v1/system/config', data='{"foo": "bar"}', headers={'Content-type': 'application/json'}, timeout=90) self.assertEqual(resp, config)
def test_update_config(self): config = {"foo": "bar"} self.mock_put.return_value.status_code = 200 self.mock_put.return_value.json.return_value = config resp = akanda_client.update_config("fe80::2", 5000, config) self.mock_put.assert_called_once_with( "http://[fe80::2]:5000/v1/system/config", data='{"foo": "bar"}', headers={"Content-type": "application/json"}, timeout=90, ) self.assertEqual(resp, config)
def test_update_config_with_custom_config(self): config = {"foo": "bar"} self.mock_put.return_value.status_code = 200 self.mock_put.return_value.json.return_value = config with mock.patch.object(akanda_client.cfg, "CONF") as cfg: cfg.config_timeout = 5 resp = akanda_client.update_config("fe80::2", 5000, config) self.mock_put.assert_called_once_with( "http://[fe80::2]:5000/v1/system/config", data='{"foo": "bar"}', headers={"Content-type": "application/json"}, timeout=5, ) self.assertEqual(resp, config)
def configure(self, worker_context, failure_state=RESTART, attempts=None): self.log.debug("Begin router config") self.state = UP attempts = attempts or cfg.CONF.max_retries # FIXME: This might raise an error, which doesn't mean the # *router* is broken, but does mean we can't update it. # Change the exception to something the caller can catch # safely. self._ensure_cache(worker_context) if self.state == GONE: return # FIXME: This should raise an explicit exception so the caller # knows that we could not talk to the router (versus the issue # above). interfaces = router_api.get_interfaces(self.instance_info.management_address, cfg.CONF.akanda_mgt_service_port) if not self._verify_interfaces(self.router_obj, interfaces): # FIXME: Need a REPLUG state when we support hot-plugging # interfaces. self.log.debug("Interfaces aren't plugged as expected.") self.state = REPLUG return # TODO(mark): We're in the first phase of VRRP, so we need # map the interface to the network ID. # Eventually we'll send VRRP data and real interface data port_mac_to_net = {p.mac_address: p.network_id for p in self.instance_info.ports} # Add in the management port mgt_port = self.instance_info.management_port port_mac_to_net[mgt_port.mac_address] = mgt_port.network_id # this is a network to logical interface id iface_map = {port_mac_to_net[i["lladdr"]]: i["ifname"] for i in interfaces if i["lladdr"] in port_mac_to_net} # FIXME: Need to catch errors talking to neutron here. config = configuration.build_config(worker_context.neutron, self.router_obj, mgt_port, iface_map) self.log.debug("preparing to update config to %r", config) for i in xrange(attempts): try: router_api.update_config( self.instance_info.management_address, cfg.CONF.akanda_mgt_service_port, config ) except Exception: if i == attempts - 1: # Only log the traceback if we encounter it many times. self.log.exception(_LE("Failed to update config")) else: self.log.debug("failed to update config, attempt %d", i) time.sleep(cfg.CONF.retry_delay) else: self.state = CONFIGURED self.log.info(_LI("Router config updated")) return else: # FIXME: We failed to configure the router too many times, # so restart it. self.state = failure_state