diff --git a/main.py b/main.py index 39b571d8..3390a864 100644 --- a/main.py +++ b/main.py @@ -271,6 +271,27 @@ def delete_circuit(self, circuit_id): emit_event(self.controller, 'deleted', evc_id=evc.id) return jsonify(result), status + @rest('/v2/evc//redeploy', methods=['PATCH']) + def redeploy(self, circuit_id): + """Endpoint to force the redeployment of an EVC.""" + log.debug('redeploy /v2/evc/%s/redeploy', circuit_id) + try: + evc = self.circuits[circuit_id] + except KeyError: + result = f'circuit_id {circuit_id} not found' + raise NotFound(result) + if evc.is_enabled(): + with evc.lock: + evc.remove_current_flows() + evc.deploy() + result = {'response': f'Circuit {circuit_id} redeploy received.'} + status = 202 + else: + result = {'response': f'Circuit {circuit_id} is disabled.'} + status = 409 + + return jsonify(result), status + @rest('/v2/evc/schedule', methods=['GET']) def list_schedules(self): """Endpoint to return all schedules stored for all circuits. @@ -320,7 +341,7 @@ def create_schedule(self): """ log.debug('create_schedule /v2/evc/schedule/') - json_data = self.json_from_request('create_schedule') + json_data = self._json_from_request('create_schedule') try: circuit_id = json_data['circuit_id'] except TypeError: @@ -407,7 +428,7 @@ def update_schedule(self, schedule_id): log.debug('update_schedule result %s %s', result, 403) raise Forbidden(result) - data = self.json_from_request('update_schedule') + data = self._json_from_request('update_schedule') new_schedule = CircuitSchedule.from_dict(data) new_schedule.id = found_schedule.id @@ -702,7 +723,7 @@ def _get_circuits_buffer(self): return self.circuits @staticmethod - def json_from_request(caller): + def _json_from_request(caller): """Return a json from request. If it was not possible to get a json from the request, log, for debug, diff --git a/openapi.yml b/openapi.yml index f7caa98b..6c8fd3a4 100644 --- a/openapi.yml +++ b/openapi.yml @@ -113,6 +113,23 @@ paths: '200': description: OK + /v2/evc/{circuit_id}/redeploy: + patch: + summary: Redeploy an EVC + description: Redeploy an EVC removing and then recreating the flows. + operationId: redeploy + parameters: + - name: circuit_id + in: path + required: true + schema: + type: string + responses: + '202': + description: Accepted + '409': + description: Circuit disabled + /v2/evc/schedule/: get: summary: List all schedules stored for all circuits . diff --git a/tests/unit/test_main.py b/tests/unit/test_main.py index 7ff71373..665bc33e 100644 --- a/tests/unit/test_main.py +++ b/tests/unit/test_main.py @@ -60,6 +60,9 @@ def test_verify_api_urls(self): ({'circuit_id': '[circuit_id]'}, {'OPTIONS', 'PATCH'}, '/api/kytos/mef_eline/v2/evc/'), + ({'circuit_id': '[circuit_id]'}, {'OPTIONS', 'PATCH'}, + '/api/kytos/mef_eline/v2/evc//redeploy'), + ({}, {'OPTIONS', 'GET', 'HEAD'}, '/api/kytos/mef_eline/v2/evc/schedule'), @@ -712,6 +715,39 @@ def test_load_circuits_by_interface(self): # pylint: disable=protected-access self.assertEqual(self.napp._circuits_by_interface, expected_result) + def test_redeploy_evc(self): + """Test endpoint to redeploy an EVC.""" + evc1 = MagicMock() + evc1.is_enabled.return_value = True + self.napp.circuits = {'1': evc1, + '2': MagicMock()} + api = self.get_app_test_client(self.napp) + url = f'{self.server_name_url}/v2/evc/1/redeploy' + response = api.patch(url) + self.assertEqual(response.status_code, 202, response.data) + + def test_redeploy_evc_disabled(self): + """Test endpoint to redeploy an EVC.""" + evc1 = MagicMock() + evc1.is_enabled.return_value = False + self.napp.circuits = {'1': evc1, + '2': MagicMock()} + api = self.get_app_test_client(self.napp) + url = f'{self.server_name_url}/v2/evc/1/redeploy' + response = api.patch(url) + self.assertEqual(response.status_code, 409, response.data) + + def test_redeploy_evc_deleted(self): + """Test endpoint to redeploy an EVC.""" + evc1 = MagicMock() + evc1.is_enabled.return_value = True + self.napp.circuits = {'1': evc1, + '2': MagicMock()} + api = self.get_app_test_client(self.napp) + url = f'{self.server_name_url}/v2/evc/3/redeploy' + response = api.patch(url) + self.assertEqual(response.status_code, 404, response.data) + def test_list_schedules__no_data(self): """Test list of schedules.""" api = self.get_app_test_client(self.napp)