diff --git a/bin/melange-client b/bin/melange-client index 22f5e3fb..2551c66f 100755 --- a/bin/melange-client +++ b/bin/melange-client @@ -123,6 +123,7 @@ categories = { 'ip_address': client.IpAddressesClient, 'ip_route': client.IpRouteClient, 'interface': client.InterfaceClient, + 'mac_address_range': client.MacAddressRangeClient, } diff --git a/melange/ipam/client.py b/melange/ipam/client.py index 4488ad3a..c2a18fd4 100644 --- a/melange/ipam/client.py +++ b/melange/ipam/client.py @@ -288,3 +288,18 @@ class InterfaceClient(BaseClient): def delete(self, vif_id): return self._resource.delete(vif_id) + + +class MacAddressRangeClient(BaseClient): + + TENANT_ID_REQUIRED = False + + def __init__(self, client, auth_client, tenant_id=None): + self._resource = Resource("mac_address_ranges", + "mac_address_range", + client, + auth_client, + tenant_id) + + def create(self, cidr): + return self._resource.create(cidr=cidr) diff --git a/melange/ipam/service.py b/melange/ipam/service.py index c485d5d8..02a42542 100644 --- a/melange/ipam/service.py +++ b/melange/ipam/service.py @@ -408,6 +408,15 @@ class InterfacesController(BaseController): return dict(interface=view_data) +class MacAddressRangesController(BaseController): + + def create(self, request, body=None): + params = self._extract_required_params(body, 'mac_address_range') + mac_range = models.MacAddressRange.create(**params) + + return wsgi.Result(dict(mac_address_range=mac_range.data()), 201) + + class API(wsgi.Router): def __init__(self): @@ -425,6 +434,7 @@ class API(wsgi.Router): self._allocated_ips_mapper(mapper) self._ip_routes_mapper(mapper) self._interface_mapper(mapper) + self._mac_address_range_mapper(mapper) def _allocated_ips_mapper(self, mapper): allocated_ips_res = AllocatedIpAddressesController().create_resource() @@ -454,6 +464,11 @@ class API(wsgi.Router): action="show", conditions=dict(method=['GET'])) + def _mac_address_range_mapper(self, mapper): + range_res = MacAddressRangesController().create_resource() + path = ("/ipam/mac_address_ranges") + mapper.resource("mac_address_ranges", path, controller=range_res) + def _network_mapper(self, mapper): path = ("/ipam/tenants/{tenant_id}/networks" "/{network_id}/interfaces/{interface_id}") diff --git a/melange/tests/functional/test_cli.py b/melange/tests/functional/test_cli.py index 1aae765e..90495382 100644 --- a/melange/tests/functional/test_cli.py +++ b/melange/tests/functional/test_cli.py @@ -531,6 +531,17 @@ class TestDeleteDeallocatedIps(tests.BaseTest): deallocated_ip.update(deallocated_at=(new_deallocated_date)) +class TestMacAddressRangeCLI(tests.BaseTest): + + def test_create(self): + exitcode, out, err = run("mac_address_range create " + "ab-bc-cd-12-23-34/24") + + self.assertEqual(exitcode, 0) + self.assertIsNotNone(models.MacAddressRange.get_by( + cidr="ab-bc-cd-12-23-34/24")) + + def run_melange_manage(command): melange_manage = melange.melange_bin_path('melange-manage') config_file = functional.test_config_file() diff --git a/melange/tests/unit/test_ipam_service.py b/melange/tests/unit/test_ipam_service.py index 8c85aefa..c1f7a806 100644 --- a/melange/tests/unit/test_ipam_service.py +++ b/melange/tests/unit/test_ipam_service.py @@ -2194,6 +2194,19 @@ class TestInterfacesController(BaseTestController): views.IpConfigurationView(*iface.ip_addresses).data()) +class TestMacAddressRangesController(BaseTestController): + + def test_create(self): + params = {'mac_address_range': {'cidr': "ab-bc-cd-12-23-34/40"}} + response = self.app.post_json("/ipam/mac_address_ranges", params) + + mac_range = models.MacAddressRange.get_by(cidr="ab-bc-cd-12-23-34/40") + self.assertEqual(response.status_int, 201) + self.assertIsNotNone(mac_range) + self.assertEqual(response.json['mac_address_range'], + _data(mac_range)) + + def _allocate_ips(*args): interface = factory_models.InterfaceFactory() return [models.sort([_allocate_ip(ip_block, interface=interface)