blob: a729fe5306bc9ce121d6c08346a8f1b5935e751b [file] [log] [blame]
sanghof8164112017-07-14 14:33:16 +09001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2017-present Open Networking Foundation
sanghof8164112017-07-14 14:33:16 +09003 *
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 */
16package org.onosproject.openstacknode.web;
17
18import com.fasterxml.jackson.databind.JsonNode;
19import com.fasterxml.jackson.databind.node.ArrayNode;
20import com.google.common.collect.Sets;
21import org.onlab.osgi.DefaultServiceDirectory;
22import org.onlab.packet.IpAddress;
23import org.onosproject.net.DeviceId;
24import org.onosproject.openstacknode.api.NodeState;
25import org.onosproject.openstacknode.api.OpenstackNode;
26import org.onosproject.openstacknode.api.OpenstackNodeAdminService;
27import org.onosproject.openstacknode.api.OpenstackNodeService;
28import org.onosproject.openstacknode.impl.DefaultOpenstackNode;
29import org.onosproject.rest.AbstractWebResource;
30import org.slf4j.Logger;
31import org.slf4j.LoggerFactory;
32
33import javax.ws.rs.Consumes;
34import javax.ws.rs.DELETE;
35import javax.ws.rs.POST;
36import javax.ws.rs.PUT;
37import javax.ws.rs.Path;
38import javax.ws.rs.Produces;
39import javax.ws.rs.core.Context;
40import javax.ws.rs.core.MediaType;
41import javax.ws.rs.core.Response;
42import javax.ws.rs.core.UriBuilder;
43import javax.ws.rs.core.UriInfo;
44import java.io.InputStream;
45import java.util.Set;
46
47import static com.fasterxml.jackson.databind.SerializationFeature.INDENT_OUTPUT;
48import static javax.ws.rs.core.Response.created;
Ray Milkeyb784adb2018-04-02 15:33:07 -070049import static org.onlab.util.Tools.readTreeFromStream;
50
51/**
52 * Handles REST API call of openstack node config.
53 */
sanghof8164112017-07-14 14:33:16 +090054
55@Path("configure")
56public class OpenstackNodeWebResource extends AbstractWebResource {
57 private final Logger log = LoggerFactory.getLogger(getClass());
58
59 private static final String MESSAGE_NODE = "Received node %s request";
60 private static final String NODES = "nodes";
daniel parkde735852017-08-01 19:13:24 +090061 private static final String CREATE = "CREATE";
62 private static final String UPDATE = "UPDATE";
63 private static final String NODE_ID = "NODE_ID";
64 private static final String DELETE = "DELETE";
65
66 private static final String HOST_NAME = "hostname";
67 private static final String TYPE = "type";
68 private static final String MANAGEMENT_IP = "managementIp";
69 private static final String DATA_IP = "dataIp";
70 private static final String INTEGRATION_BRIDGE = "integrationBridge";
71 private static final String VLAN_INTF_NAME = "vlanPort";
72
73 // GATEWAY node specific fields
74 private static final String ROUTER_BRIDGE = "routerBridge";
75
sanghof8164112017-07-14 14:33:16 +090076
77 private final OpenstackNodeAdminService osNodeAdminService =
78 DefaultServiceDirectory.getService(OpenstackNodeAdminService.class);
79 private final OpenstackNodeService osNodeService =
80 DefaultServiceDirectory.getService(OpenstackNodeService.class);
81
82 @Context
83 private UriInfo uriInfo;
84
85 @POST
86 @Consumes(MediaType.APPLICATION_JSON)
87 @Produces(MediaType.APPLICATION_JSON)
88 public Response createNodes(InputStream input) {
daniel parkde735852017-08-01 19:13:24 +090089 log.trace(String.format(MESSAGE_NODE, CREATE));
sanghof8164112017-07-14 14:33:16 +090090
91 readNodeConfiguration(input).forEach(osNode -> {
92 OpenstackNode existing = osNodeService.node(osNode.hostname());
93 if (existing == null) {
94 osNodeAdminService.createNode(osNode);
95 }
96 });
97
98 UriBuilder locationBuilder = uriInfo.getBaseUriBuilder()
99 .path(NODES)
daniel parkde735852017-08-01 19:13:24 +0900100 .path(NODE_ID);
sanghof8164112017-07-14 14:33:16 +0900101
102 return created(locationBuilder.build()).build();
103 }
104
105 @PUT
106 @Consumes(MediaType.APPLICATION_JSON)
107 @Produces(MediaType.APPLICATION_JSON)
108 public Response updateNodes(InputStream input) {
daniel parkde735852017-08-01 19:13:24 +0900109 log.trace(String.format(MESSAGE_NODE, UPDATE));
sanghof8164112017-07-14 14:33:16 +0900110
111 Set<OpenstackNode> nodes = readNodeConfiguration(input);
112 for (OpenstackNode osNode: nodes) {
113 OpenstackNode existing = osNodeService.node(osNode.hostname());
114 if (existing == null) {
115 log.warn("There is no node configuration to update : {}", osNode.hostname());
116 return Response.notModified().build();
117 } else if (!existing.equals(osNode)) {
118 osNodeAdminService.updateNode(osNode);
119 }
120 }
121
122 return Response.ok().build();
123 }
124
125 @DELETE
126 @Consumes(MediaType.APPLICATION_JSON)
127 @Produces(MediaType.APPLICATION_JSON)
128 public Response deleteNodes(InputStream input) {
daniel parkde735852017-08-01 19:13:24 +0900129 log.trace(String.format(MESSAGE_NODE, DELETE));
sanghof8164112017-07-14 14:33:16 +0900130
131 Set<OpenstackNode> nodes = readNodeConfiguration(input);
132 for (OpenstackNode osNode: nodes) {
133 OpenstackNode existing = osNodeService.node(osNode.hostname());
134 if (existing == null) {
135 log.warn("There is no node configuration to delete : {}", osNode.hostname());
136 return Response.notModified().build();
137 } else {
138 osNodeAdminService.removeNode(osNode.hostname());
139 }
140 }
141
142 return Response.ok().build();
143 }
144
145 private Set<OpenstackNode> readNodeConfiguration(InputStream input) {
146 Set<OpenstackNode> nodeSet = Sets.newHashSet();
147 try {
Ray Milkeyb784adb2018-04-02 15:33:07 -0700148 JsonNode jsonTree = readTreeFromStream(mapper().enable(INDENT_OUTPUT), input);
daniel parkde735852017-08-01 19:13:24 +0900149 ArrayNode nodes = (ArrayNode) jsonTree.path(NODES);
sanghof8164112017-07-14 14:33:16 +0900150 nodes.forEach(node -> {
151 try {
daniel parkde735852017-08-01 19:13:24 +0900152 String hostname = node.get(HOST_NAME).asText();
153 String type = node.get(TYPE).asText();
154 String mIp = node.get(MANAGEMENT_IP).asText();
155 String iBridge = node.get(INTEGRATION_BRIDGE).asText();
sanghof8164112017-07-14 14:33:16 +0900156 String rBridge = null;
daniel parkde735852017-08-01 19:13:24 +0900157 if (node.get(ROUTER_BRIDGE) != null) {
158 rBridge = node.get(ROUTER_BRIDGE).asText();
sanghof8164112017-07-14 14:33:16 +0900159 }
160 DefaultOpenstackNode.Builder nodeBuilder = DefaultOpenstackNode.builder()
161 .hostname(hostname)
162 .type(OpenstackNode.NodeType.valueOf(type))
163 .managementIp(IpAddress.valueOf(mIp))
sanghof8164112017-07-14 14:33:16 +0900164 .intgBridge(DeviceId.deviceId(iBridge))
165 .state(NodeState.INIT);
daniel parkde735852017-08-01 19:13:24 +0900166
167 if (node.get(VLAN_INTF_NAME) != null) {
168 nodeBuilder.vlanIntf(node.get(VLAN_INTF_NAME).asText());
169 }
170 if (node.get(DATA_IP) != null) {
171 nodeBuilder.dataIp(IpAddress.valueOf(node.get(DATA_IP).asText()));
172 }
sanghof8164112017-07-14 14:33:16 +0900173 if (rBridge != null) {
174 nodeBuilder.routerBridge(DeviceId.deviceId(rBridge));
175 }
daniel parkde735852017-08-01 19:13:24 +0900176
sanghof8164112017-07-14 14:33:16 +0900177 log.trace("node is {}", nodeBuilder.build().toString());
178 nodeSet.add(nodeBuilder.build());
179 } catch (Exception e) {
180 log.error(e.toString());
181 throw new IllegalArgumentException();
182 }
183 });
184 } catch (Exception e) {
185 throw new IllegalArgumentException(e);
186 }
187
188 return nodeSet;
189 }
190}