From: Alexis de Talhouët Date: Mon, 20 Aug 2018 19:27:59 +0000 (-0400) Subject: Add DB update support for IPAM interaction X-Git-Tag: 0.3.0~17^2 X-Git-Url: https://gerrit.onap.org/r/gitweb?a=commitdiff_plain;h=e864171d3d4f378a150466161f7162070368e554;p=ccsdk%2Fsli%2Fadaptors.git Add DB update support for IPAM interaction 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 --- 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))); }