From e864171d3d4f378a150466161f7162070368e554 Mon Sep 17 00:00:00 2001 From: Alexis de Talhouët Date: Mon, 20 Aug 2018 15:27:59 -0400 Subject: Add DB update support for IPAM interaction MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For assign and unassign scenario, we need to interact with the SDNC DB in order to cache the IP Address information used for a given ServiceInstance / VfModule. Change-Id: Id349338216d12d2dc9efd76cd672b5cc9fdc6192 Issue-ID: CCSDK-462 Signed-off-by: Alexis de Talhouët --- .../sli/adaptors/netbox/api/NetboxClient.java | 23 +++++++--- .../sli/adaptors/netbox/impl/NetboxClientImpl.java | 52 ++++++++++++++++++---- .../org/opendaylight/blueprint/netbox-client.xml | 4 ++ .../adaptors/netbox/impl/NetboxClientImplTest.java | 34 ++++++++++---- 4 files changed, 90 insertions(+), 23 deletions(-) diff --git a/netbox-client/provider/src/main/java/org/onap/ccsdk/sli/adaptors/netbox/api/NetboxClient.java b/netbox-client/provider/src/main/java/org/onap/ccsdk/sli/adaptors/netbox/api/NetboxClient.java index 57d727ad..e11fe8bc 100644 --- a/netbox-client/provider/src/main/java/org/onap/ccsdk/sli/adaptors/netbox/api/NetboxClient.java +++ b/netbox-client/provider/src/main/java/org/onap/ccsdk/sli/adaptors/netbox/api/NetboxClient.java @@ -15,26 +15,37 @@ */ package org.onap.ccsdk.sli.adaptors.netbox.api; +import java.sql.SQLException; import org.onap.ccsdk.sli.adaptors.netbox.model.IPAddress; import org.onap.ccsdk.sli.adaptors.netbox.model.Prefix; +/** + * This client is meant to interact both with the IPAM system, and the SDNC DB, in order to provide, at any time, + * an up to date status of the assigned resources. + */ public interface NetboxClient { /** - * Assign next available IP in prefix. + * Assign next available IP in prefix and store it in the SDNC database, table IPAM_IP_ASSIGNEMENT. * * @param prefix The prefix from which to get next available IP. + * @param serviceInstanceId The service instance ID uniquely identifying the service. + * @param vfModuleId The VF module ID uniquely identifying the VF. * @return The IPAddress - * @throws IpamException If something goes wrong. + * @throws IpamException If something goes wrong while communicating with the IPAM system. + * @throws SQLException If something goes wrong while communicating with the SDNC DB. */ - IPAddress assign(Prefix prefix) throws IpamException; + IPAddress assign(Prefix prefix, String serviceInstanceId, String vfModuleId) throws IpamException, SQLException; /** - * Free the IP. + * Release the IP and remove the entry in the SDNC database, table IPAM_IP_ASSIGNEMENT. * * @param ip The IP to release. - * @throws IpamException If something goes wrong. + * @param serviceInstanceId The service instance ID uniquely identifying the service. + * @param vfModuleId The VF module ID uniquely identifying the VF. + * @throws IpamException If something goes wrong while communicating with the IPAM system. + * @throws SQLException If something goes wrong while communicating with the SDNC DB. */ - void unassign(IPAddress ip) throws IpamException; + void unassign(IPAddress ip, String serviceInstanceId, String vfModuleId) throws IpamException, SQLException; } diff --git a/netbox-client/provider/src/main/java/org/onap/ccsdk/sli/adaptors/netbox/impl/NetboxClientImpl.java b/netbox-client/provider/src/main/java/org/onap/ccsdk/sli/adaptors/netbox/impl/NetboxClientImpl.java index 0520ad5e..036ff44d 100644 --- a/netbox-client/provider/src/main/java/org/onap/ccsdk/sli/adaptors/netbox/impl/NetboxClientImpl.java +++ b/netbox-client/provider/src/main/java/org/onap/ccsdk/sli/adaptors/netbox/impl/NetboxClientImpl.java @@ -16,12 +16,15 @@ package org.onap.ccsdk.sli.adaptors.netbox.impl; import com.google.common.annotations.VisibleForTesting; +import com.google.common.collect.Lists; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonSerializer; import java.io.IOException; import java.io.InputStreamReader; import java.io.Reader; +import java.sql.SQLException; +import java.util.ArrayList; import java.util.concurrent.CompletionException; import org.apache.http.HttpResponse; import org.onap.ccsdk.sli.adaptors.netbox.api.IpamException; @@ -29,19 +32,29 @@ import org.onap.ccsdk.sli.adaptors.netbox.api.NetboxClient; import org.onap.ccsdk.sli.adaptors.netbox.model.IPAddress; import org.onap.ccsdk.sli.adaptors.netbox.model.Prefix; import org.onap.ccsdk.sli.adaptors.netbox.model.Status; +import org.onap.ccsdk.sli.core.dblib.DbLibService; +import org.onap.ccsdk.sli.core.sli.SvcLogicJavaPlugin; -public class NetboxClientImpl implements NetboxClient { +public class NetboxClientImpl implements NetboxClient, SvcLogicJavaPlugin { private static final String NEXT_AVAILABLE_IP_IN_PREFIX_PATH = "/api/ipam/prefixes/%s/available-ips/"; private static final String IP_ADDRESS_PATH = "/api/ipam/ip-addresses/%s/"; private static final String EMPTY_STRING = ""; private static final String ID_MISSING_MSG = "Id must be set"; + private static final String ASSIGN_IP_SQL_STATEMENT = + "INSERT INTO IPAM_IP_ASSIGNEMENT (service_instance_id, vf_module_id, prefix_id, ip_address_id, ip_adress, ip_status) \n" + + "VALUES (?, ?, ?, ?, ?, ?)"; + private static final String UNASSIGN_IP_SQL_STATEMENT = + "DELETE FROM IPAM_IP_ASSIGNEMENT WHERE service_instance_id = ? AND vf_module_id = ? AND ip_address_id = ?"; + private final NetboxHttpClient client; private final Gson gson; + private final DbLibService dbLibService; - public NetboxClientImpl(final NetboxHttpClient client) { + public NetboxClientImpl(final NetboxHttpClient client, final DbLibService dbLibService) { this.client = client; + this.dbLibService = dbLibService; final JsonSerializer vlanStatusDeserializer = (val, type, context) -> val.toJson(); gson = new GsonBuilder() .registerTypeAdapter(Status.class, vlanStatusDeserializer) @@ -49,31 +62,54 @@ public class NetboxClientImpl implements NetboxClient { } @Override - public IPAddress assign(final Prefix prefix) throws IpamException { + public IPAddress assign(final Prefix prefix, final String serviceInstanceId, final String vfModuleId) + throws IpamException, SQLException { + checkArgument(prefix.getId() != null); try { - return client.post(String.format(NEXT_AVAILABLE_IP_IN_PREFIX_PATH, prefix.getId()), EMPTY_STRING) + IPAddress ipAddress = client + .post(String.format(NEXT_AVAILABLE_IP_IN_PREFIX_PATH, prefix.getId()), EMPTY_STRING) .thenApply(this::getIpAddress) .toCompletableFuture() .join(); + + ArrayList args = Lists.newArrayList(serviceInstanceId, + vfModuleId, + String.valueOf(prefix.getId()), + String.valueOf(ipAddress.getId()), + ipAddress.getAddress(), + ipAddress.getStatus().getLabel()); + dbLibService.writeData(ASSIGN_IP_SQL_STATEMENT, args, null); + + return ipAddress; } catch (CompletionException e) { - // Unwrap the ComplettionException and wrap in IpamException + // Unwrap the CompletionException and wrap in IpamException throw new IpamException("Fail to assign IP for Prefix(id= " + prefix.getId() + "). " + e.getMessage(), e.getCause()); } } @Override - public void unassign(final IPAddress ipAddress) throws IpamException { + public void unassign(final IPAddress ipAddress, final String serviceInstanceId, final String vfModuleId) + throws IpamException, SQLException { + checkArgument(ipAddress.getId() != null); try { client.delete(String.format(IP_ADDRESS_PATH, ipAddress.getId())) .thenAccept(this::checkResult) .toCompletableFuture() .join(); + + ArrayList args = Lists.newArrayList( + serviceInstanceId, + vfModuleId, + String.valueOf(ipAddress.getId())); + dbLibService.writeData(UNASSIGN_IP_SQL_STATEMENT, args, null); + } catch (CompletionException e) { - // Unwrap the ComplettionException and wrap in IpamException - throw new IpamException("Fail to unassign IP for IPAddress(id= " + ipAddress.getId() + "). " + e.getMessage(), + // Unwrap the CompletionException and wrap in IpamException + throw new IpamException( + "Fail to unassign IP for IPAddress(id= " + ipAddress.getId() + "). " + e.getMessage(), e.getCause()); } } diff --git a/netbox-client/provider/src/main/resources/org/opendaylight/blueprint/netbox-client.xml b/netbox-client/provider/src/main/resources/org/opendaylight/blueprint/netbox-client.xml index cf8a1af4..950fd97b 100644 --- a/netbox-client/provider/src/main/resources/org/opendaylight/blueprint/netbox-client.xml +++ b/netbox-client/provider/src/main/resources/org/opendaylight/blueprint/netbox-client.xml @@ -17,6 +17,9 @@ + + @@ -25,6 +28,7 @@ + { @@ -93,11 +107,11 @@ public class NetboxClientImplTest { } @Test - public void nextAvailableIpInPrefixTestNoId() { + public void nextAvailableIpInPrefixTestNoId() throws SQLException { Prefix prefix = mock(Prefix.class); doReturn(null).when(prefix).getId(); try { - netboxClient.assign(prefix); + netboxClient.assign(prefix, serviceInstanceId, vfModuleId); } catch (IpamException e) { Assert.assertEquals("Id must be set", e.getMessage()); return; @@ -106,7 +120,7 @@ public class NetboxClientImplTest { } @Test - public void nextAvailableIpInPrefixTest() throws IOException, IpamException { + public void nextAvailableIpInPrefixTest() throws IOException, IpamException, SQLException { Integer id = 3; Prefix prefix = mock(Prefix.class); doReturn(id).when(prefix).getId(); @@ -117,16 +131,17 @@ public class NetboxClientImplTest { String expectedUrl = "/api/ipam/prefixes/" + id + "/available-ips/"; givenThat(post(urlEqualTo(expectedUrl)).willReturn(created().withBody(response))); - netboxClient.assign(prefix); + netboxClient.assign(prefix, serviceInstanceId, vfModuleId); verify(postRequestedFor(urlEqualTo(expectedUrl)) .withHeader(ACCEPT, equalTo(APPLICATION_JSON)) .withHeader(CONTENT_TYPE, equalTo(APPLICATION_JSON)) .withHeader(AUTHORIZATION, equalTo("Token " + token))); + Mockito.verify(dbLib).writeData(anyString(), any(ArrayList.class), eq((null))); } @Test - public void deleteIpTestError500() { + public void deleteIpTestError500() throws SQLException { Integer id = 3; IPAddress ipAddress = mock(IPAddress.class); doReturn(id).when(ipAddress).getId(); @@ -134,7 +149,7 @@ public class NetboxClientImplTest { String expectedUrl = "/api/ipam/ip-addresses/" + id + "/"; givenThat(delete(urlEqualTo(expectedUrl)).willReturn(serverError())); try { - netboxClient.unassign(ipAddress); + netboxClient.unassign(ipAddress, serviceInstanceId, vfModuleId); } catch (IpamException e) { Assert.assertEquals(IllegalStateException.class, e.getCause().getClass()); Assert.assertTrue(e.getMessage().contains( @@ -145,18 +160,19 @@ public class NetboxClientImplTest { } @Test - public void deleteIpTest() throws IpamException { + public void deleteIpTest() throws IpamException, SQLException { Integer id = 3; IPAddress ipAddress = mock(IPAddress.class); doReturn(id).when(ipAddress).getId(); String expectedUrl = "/api/ipam/ip-addresses/" + id + "/"; givenThat(delete(urlEqualTo(expectedUrl)).willReturn(ok())); - netboxClient.unassign(ipAddress); + netboxClient.unassign(ipAddress, serviceInstanceId, vfModuleId); verify(deleteRequestedFor(urlEqualTo(expectedUrl)) .withHeader(ACCEPT, equalTo(APPLICATION_JSON)) .withHeader(CONTENT_TYPE, equalTo(APPLICATION_JSON)) .withHeader(AUTHORIZATION, equalTo("Token " + token))); + Mockito.verify(dbLib).writeData(anyString(), any(ArrayList.class), eq((null))); } -- cgit 1.2.3-korg