036ff44d46f881aff2b9080c4f73d57d5e43ef23
[ccsdk/sli/adaptors.git] / netbox-client / provider / src / main / java / org / onap / ccsdk / sli / adaptors / netbox / impl / NetboxClientImpl.java
1 /*
2  * Copyright (C) 2018 Bell Canada.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package org.onap.ccsdk.sli.adaptors.netbox.impl;
17
18 import com.google.common.annotations.VisibleForTesting;
19 import com.google.common.collect.Lists;
20 import com.google.gson.Gson;
21 import com.google.gson.GsonBuilder;
22 import com.google.gson.JsonSerializer;
23 import java.io.IOException;
24 import java.io.InputStreamReader;
25 import java.io.Reader;
26 import java.sql.SQLException;
27 import java.util.ArrayList;
28 import java.util.concurrent.CompletionException;
29 import org.apache.http.HttpResponse;
30 import org.onap.ccsdk.sli.adaptors.netbox.api.IpamException;
31 import org.onap.ccsdk.sli.adaptors.netbox.api.NetboxClient;
32 import org.onap.ccsdk.sli.adaptors.netbox.model.IPAddress;
33 import org.onap.ccsdk.sli.adaptors.netbox.model.Prefix;
34 import org.onap.ccsdk.sli.adaptors.netbox.model.Status;
35 import org.onap.ccsdk.sli.core.dblib.DbLibService;
36 import org.onap.ccsdk.sli.core.sli.SvcLogicJavaPlugin;
37
38 public class NetboxClientImpl implements NetboxClient, SvcLogicJavaPlugin {
39
40     private static final String NEXT_AVAILABLE_IP_IN_PREFIX_PATH = "/api/ipam/prefixes/%s/available-ips/";
41     private static final String IP_ADDRESS_PATH = "/api/ipam/ip-addresses/%s/";
42     private static final String EMPTY_STRING = "";
43     private static final String ID_MISSING_MSG = "Id must be set";
44
45     private static final String ASSIGN_IP_SQL_STATEMENT =
46         "INSERT INTO IPAM_IP_ASSIGNEMENT (service_instance_id, vf_module_id, prefix_id, ip_address_id, ip_adress, ip_status) \n"
47             + "VALUES (?, ?, ?, ?, ?, ?)";
48     private static final String UNASSIGN_IP_SQL_STATEMENT =
49         "DELETE FROM IPAM_IP_ASSIGNEMENT WHERE service_instance_id = ? AND vf_module_id = ? AND ip_address_id = ?";
50
51     private final NetboxHttpClient client;
52     private final Gson gson;
53     private final DbLibService dbLibService;
54
55     public NetboxClientImpl(final NetboxHttpClient client, final DbLibService dbLibService) {
56         this.client = client;
57         this.dbLibService = dbLibService;
58         final JsonSerializer<Status> vlanStatusDeserializer = (val, type, context) -> val.toJson();
59         gson = new GsonBuilder()
60             .registerTypeAdapter(Status.class, vlanStatusDeserializer)
61             .create();
62     }
63
64     @Override
65     public IPAddress assign(final Prefix prefix, final String serviceInstanceId, final String vfModuleId)
66         throws IpamException, SQLException {
67
68         checkArgument(prefix.getId() != null);
69         try {
70             IPAddress ipAddress = client
71                 .post(String.format(NEXT_AVAILABLE_IP_IN_PREFIX_PATH, prefix.getId()), EMPTY_STRING)
72                 .thenApply(this::getIpAddress)
73                 .toCompletableFuture()
74                 .join();
75
76             ArrayList<String> args = Lists.newArrayList(serviceInstanceId,
77                 vfModuleId,
78                 String.valueOf(prefix.getId()),
79                 String.valueOf(ipAddress.getId()),
80                 ipAddress.getAddress(),
81                 ipAddress.getStatus().getLabel());
82             dbLibService.writeData(ASSIGN_IP_SQL_STATEMENT, args, null);
83
84             return ipAddress;
85         } catch (CompletionException e) {
86             // Unwrap the CompletionException and wrap in IpamException
87             throw new IpamException("Fail to assign IP for Prefix(id= " + prefix.getId() + "). " + e.getMessage(),
88                 e.getCause());
89         }
90     }
91
92     @Override
93     public void unassign(final IPAddress ipAddress, final String serviceInstanceId, final String vfModuleId)
94         throws IpamException, SQLException {
95
96         checkArgument(ipAddress.getId() != null);
97         try {
98             client.delete(String.format(IP_ADDRESS_PATH, ipAddress.getId()))
99                 .thenAccept(this::checkResult)
100                 .toCompletableFuture()
101                 .join();
102
103             ArrayList<String> args = Lists.newArrayList(
104                 serviceInstanceId,
105                 vfModuleId,
106                 String.valueOf(ipAddress.getId()));
107             dbLibService.writeData(UNASSIGN_IP_SQL_STATEMENT, args, null);
108
109         } catch (CompletionException e) {
110             // Unwrap the CompletionException and wrap in IpamException
111             throw new IpamException(
112                 "Fail to unassign IP for IPAddress(id= " + ipAddress.getId() + "). " + e.getMessage(),
113                 e.getCause());
114         }
115     }
116
117     @VisibleForTesting
118     IPAddress getIpAddress(final HttpResponse response) {
119         if (response.getStatusLine().getStatusCode() != 201) {
120             throw new IllegalStateException(NetboxHttpClient.getBodyAsString(response));
121         }
122         try (final Reader reader = new InputStreamReader(response.getEntity().getContent())) {
123             return gson.fromJson(reader, IPAddress.class);
124         } catch (final IOException e) {
125             throw new IllegalStateException(e);
126         }
127     }
128
129     private static void checkArgument(final boolean argument) throws IpamException {
130         if (!argument) {
131             throw new IpamException(ID_MISSING_MSG);
132         }
133     }
134
135     private void checkResult(final HttpResponse response) {
136         if (response.getStatusLine().getStatusCode() - 200 >= 100) {
137             throw new IllegalStateException(
138                 "Netbox request failed with status: " + NetboxHttpClient.getBodyAsString(response));
139         }
140     }
141 }