blob: 3f8936e6b95ac1fc4fecb18885aa55f589a3f807 [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;
daniel parkb18424c2018-02-05 15:43:43 +090030import static org.onosproject.openstacknode.api.Constants.GATEWAY;
31import static org.onosproject.openstacknode.api.Constants.HOST_NAME;
32import static org.onosproject.openstacknode.api.Constants.MANAGEMENT_IP;
33import static org.onosproject.openstacknode.api.Constants.DATA_IP;
34import static org.onosproject.openstacknode.api.Constants.VLAN_INTF_NAME;
35import static org.onosproject.openstacknode.api.Constants.UPLINK_PORT;
36
sanghof8164112017-07-14 14:33:16 +090037import org.slf4j.Logger;
38import org.slf4j.LoggerFactory;
39
40import javax.ws.rs.Consumes;
41import javax.ws.rs.DELETE;
42import javax.ws.rs.POST;
43import javax.ws.rs.PUT;
44import javax.ws.rs.Path;
45import javax.ws.rs.Produces;
46import javax.ws.rs.core.Context;
47import javax.ws.rs.core.MediaType;
48import javax.ws.rs.core.Response;
49import javax.ws.rs.core.UriBuilder;
50import javax.ws.rs.core.UriInfo;
51import java.io.InputStream;
52import java.util.Set;
53
54import static com.fasterxml.jackson.databind.SerializationFeature.INDENT_OUTPUT;
55import static javax.ws.rs.core.Response.created;
56
57@Path("configure")
58public class OpenstackNodeWebResource extends AbstractWebResource {
59 private final Logger log = LoggerFactory.getLogger(getClass());
60
61 private static final String MESSAGE_NODE = "Received node %s request";
62 private static final String NODES = "nodes";
daniel parkde735852017-08-01 19:13:24 +090063 private static final String CREATE = "CREATE";
64 private static final String UPDATE = "UPDATE";
65 private static final String NODE_ID = "NODE_ID";
66 private static final String DELETE = "DELETE";
daniel parkde735852017-08-01 19:13:24 +090067 private static final String TYPE = "type";
daniel parkde735852017-08-01 19:13:24 +090068 private static final String INTEGRATION_BRIDGE = "integrationBridge";
daniel parkde735852017-08-01 19:13:24 +090069
sanghof8164112017-07-14 14:33:16 +090070
71 private final OpenstackNodeAdminService osNodeAdminService =
72 DefaultServiceDirectory.getService(OpenstackNodeAdminService.class);
73 private final OpenstackNodeService osNodeService =
74 DefaultServiceDirectory.getService(OpenstackNodeService.class);
75
76 @Context
77 private UriInfo uriInfo;
78
79 @POST
80 @Consumes(MediaType.APPLICATION_JSON)
81 @Produces(MediaType.APPLICATION_JSON)
82 public Response createNodes(InputStream input) {
daniel parkde735852017-08-01 19:13:24 +090083 log.trace(String.format(MESSAGE_NODE, CREATE));
sanghof8164112017-07-14 14:33:16 +090084
85 readNodeConfiguration(input).forEach(osNode -> {
86 OpenstackNode existing = osNodeService.node(osNode.hostname());
87 if (existing == null) {
88 osNodeAdminService.createNode(osNode);
89 }
90 });
91
92 UriBuilder locationBuilder = uriInfo.getBaseUriBuilder()
93 .path(NODES)
daniel parkde735852017-08-01 19:13:24 +090094 .path(NODE_ID);
sanghof8164112017-07-14 14:33:16 +090095
96 return created(locationBuilder.build()).build();
97 }
98
99 @PUT
100 @Consumes(MediaType.APPLICATION_JSON)
101 @Produces(MediaType.APPLICATION_JSON)
102 public Response updateNodes(InputStream input) {
daniel parkde735852017-08-01 19:13:24 +0900103 log.trace(String.format(MESSAGE_NODE, UPDATE));
sanghof8164112017-07-14 14:33:16 +0900104
105 Set<OpenstackNode> nodes = readNodeConfiguration(input);
106 for (OpenstackNode osNode: nodes) {
107 OpenstackNode existing = osNodeService.node(osNode.hostname());
108 if (existing == null) {
109 log.warn("There is no node configuration to update : {}", osNode.hostname());
110 return Response.notModified().build();
111 } else if (!existing.equals(osNode)) {
112 osNodeAdminService.updateNode(osNode);
113 }
114 }
115
116 return Response.ok().build();
117 }
118
119 @DELETE
120 @Consumes(MediaType.APPLICATION_JSON)
121 @Produces(MediaType.APPLICATION_JSON)
122 public Response deleteNodes(InputStream input) {
daniel parkde735852017-08-01 19:13:24 +0900123 log.trace(String.format(MESSAGE_NODE, DELETE));
sanghof8164112017-07-14 14:33:16 +0900124
125 Set<OpenstackNode> nodes = readNodeConfiguration(input);
126 for (OpenstackNode osNode: nodes) {
127 OpenstackNode existing = osNodeService.node(osNode.hostname());
128 if (existing == null) {
129 log.warn("There is no node configuration to delete : {}", osNode.hostname());
130 return Response.notModified().build();
131 } else {
132 osNodeAdminService.removeNode(osNode.hostname());
133 }
134 }
135
136 return Response.ok().build();
137 }
138
139 private Set<OpenstackNode> readNodeConfiguration(InputStream input) {
140 Set<OpenstackNode> nodeSet = Sets.newHashSet();
141 try {
142 JsonNode jsonTree = mapper().enable(INDENT_OUTPUT).readTree(input);
daniel parkde735852017-08-01 19:13:24 +0900143 ArrayNode nodes = (ArrayNode) jsonTree.path(NODES);
sanghof8164112017-07-14 14:33:16 +0900144 nodes.forEach(node -> {
145 try {
daniel parkde735852017-08-01 19:13:24 +0900146 String hostname = node.get(HOST_NAME).asText();
147 String type = node.get(TYPE).asText();
148 String mIp = node.get(MANAGEMENT_IP).asText();
149 String iBridge = node.get(INTEGRATION_BRIDGE).asText();
daniel parkb18424c2018-02-05 15:43:43 +0900150
sanghof8164112017-07-14 14:33:16 +0900151 DefaultOpenstackNode.Builder nodeBuilder = DefaultOpenstackNode.builder()
152 .hostname(hostname)
153 .type(OpenstackNode.NodeType.valueOf(type))
154 .managementIp(IpAddress.valueOf(mIp))
sanghof8164112017-07-14 14:33:16 +0900155 .intgBridge(DeviceId.deviceId(iBridge))
156 .state(NodeState.INIT);
daniel parkde735852017-08-01 19:13:24 +0900157
daniel parkb18424c2018-02-05 15:43:43 +0900158 if (type.equals(GATEWAY)) {
159 nodeBuilder.uplinkPort(node.get(UPLINK_PORT).asText());
160 }
daniel parkde735852017-08-01 19:13:24 +0900161 if (node.get(VLAN_INTF_NAME) != null) {
162 nodeBuilder.vlanIntf(node.get(VLAN_INTF_NAME).asText());
163 }
164 if (node.get(DATA_IP) != null) {
165 nodeBuilder.dataIp(IpAddress.valueOf(node.get(DATA_IP).asText()));
166 }
daniel parkde735852017-08-01 19:13:24 +0900167
sanghof8164112017-07-14 14:33:16 +0900168 log.trace("node is {}", nodeBuilder.build().toString());
169 nodeSet.add(nodeBuilder.build());
170 } catch (Exception e) {
171 log.error(e.toString());
172 throw new IllegalArgumentException();
173 }
174 });
175 } catch (Exception e) {
176 throw new IllegalArgumentException(e);
177 }
178
179 return nodeSet;
180 }
181}