diff options
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 57d727add..e11fe8bcc 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 0520ad5e5..036ff44d4 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<Status> 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<String> 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<String> 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 cf8a1af4d..950fd97b0 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 @@ <blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0" odl:use-default-for-reference-types="true"> + <reference id="dbLibService" + interface="org.onap.ccsdk.sli.core.dblib.DbLibService"/> + <bean id="netboxProperty" class="org.onap.ccsdk.sli.adaptors.netbox.property.NetboxProperties"/> <bean id="httpClient" class="org.onap.ccsdk.sli.adaptors.netbox.impl.NetboxHttpClient" init-method="init" destroy-method="close"> @@ -25,6 +28,7 @@ <bean id="netboxClient" class="org.onap.ccsdk.sli.adaptors.netbox.impl.NetboxClientImpl"> <argument ref="httpClient"/> + <argument ref="dbLibService"/> </bean> <service ref="netboxClient" diff --git a/netbox-client/provider/src/test/java/org/onap/ccsdk/sli/adaptors/netbox/impl/NetboxClientImplTest.java b/netbox-client/provider/src/test/java/org/onap/ccsdk/sli/adaptors/netbox/impl/NetboxClientImplTest.java index 19b178c9a..f1eda736a 100644 --- a/netbox-client/provider/src/test/java/org/onap/ccsdk/sli/adaptors/netbox/impl/NetboxClientImplTest.java +++ b/netbox-client/provider/src/test/java/org/onap/ccsdk/sli/adaptors/netbox/impl/NetboxClientImplTest.java @@ -30,6 +30,9 @@ import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMoc import static org.apache.http.HttpHeaders.ACCEPT; import static org.apache.http.HttpHeaders.AUTHORIZATION; import static org.apache.http.HttpHeaders.CONTENT_TYPE; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; @@ -41,6 +44,9 @@ import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.nio.charset.StandardCharsets; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.UUID; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.StatusLine; @@ -50,11 +56,14 @@ import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.Mockito; import org.mockito.runners.MockitoJUnitRunner; import org.onap.ccsdk.sli.adaptors.netbox.api.IpamException; 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.Values; +import org.onap.ccsdk.sli.core.dblib.DbLibService; @RunWith(MockitoJUnitRunner.class) public class NetboxClientImplTest { @@ -64,7 +73,12 @@ public class NetboxClientImplTest { @Rule public WireMockRule wm = new WireMockRule(wireMockConfig().dynamicPort()); + @Mock + private DbLibService dbLib; + private String token = "token"; + private String serviceInstanceId = UUID.randomUUID().toString(); + private String vfModuleId = UUID.randomUUID().toString(); private NetboxHttpClient httpClient; private NetboxClientImpl netboxClient; @@ -76,7 +90,7 @@ public class NetboxClientImplTest { httpClient = new NetboxHttpClient(baseUrl, token); httpClient.init(); - netboxClient = new NetboxClientImpl(httpClient); + netboxClient = new NetboxClientImpl(httpClient, dbLib); wm.addMockServiceRequestListener( (request, response) -> { @@ -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))); } |