blob: 99ec5a43823a0281d2a22aa235970dafc59b6438 [file] [log] [blame]
Jian Lif96d41f2016-05-03 09:49:12 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2016-present Open Networking Foundation
Jian Lif96d41f2016-05-03 09:49:12 -07003 *
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.rest.resources;
17
18import com.fasterxml.jackson.databind.JsonNode;
19import com.fasterxml.jackson.databind.node.ArrayNode;
20import com.fasterxml.jackson.databind.node.ObjectNode;
21import org.onosproject.cluster.NodeId;
22import org.onosproject.cluster.RoleInfo;
23import org.onosproject.mastership.MastershipAdminService;
24import org.onosproject.mastership.MastershipService;
25import org.onosproject.net.DeviceId;
26import org.onosproject.net.MastershipRole;
Kavitha Alagesan60093392016-10-26 17:04:26 +053027import org.onosproject.net.device.DeviceService;
Jian Lif96d41f2016-05-03 09:49:12 -070028import org.onosproject.rest.AbstractWebResource;
29
30import javax.ws.rs.Consumes;
31import javax.ws.rs.GET;
32import javax.ws.rs.PUT;
33import javax.ws.rs.Path;
34import javax.ws.rs.PathParam;
35import javax.ws.rs.Produces;
36import javax.ws.rs.core.MediaType;
37import javax.ws.rs.core.Response;
38import java.io.IOException;
39import java.io.InputStream;
40import java.util.Set;
Jian Lif96d41f2016-05-03 09:49:12 -070041
42import static org.onlab.util.Tools.nullIsNotFound;
43
44/**
45 * Manage the mastership of ONOS instances.
46 */
47@Path("mastership")
48public final class MastershipWebResource extends AbstractWebResource {
49
Jian Li0409b702016-05-03 18:21:37 -070050 private static final String DEVICE_IDS = "deviceIds";
Jian Lif96d41f2016-05-03 09:49:12 -070051 private static final String DEVICE_ID = "deviceId";
52 private static final String NODE_ID = "nodeId";
53
54 private static final String DEVICE_ID_INVALID = "Invalid deviceId for setting role";
55 private static final String NODE_ID_INVALID = "Invalid nodeId for setting role";
56
Kavitha Alagesan60093392016-10-26 17:04:26 +053057 private static final String DEVICE_ID_NOT_FOUND = "Device Id is not found";
Jian Lif96d41f2016-05-03 09:49:12 -070058 private static final String NODE_ID_NOT_FOUND = "Node id is not found";
59 private static final String ROLE_INFO_NOT_FOUND = "Role info is not found";
60 private static final String MASTERSHIP_ROLE_NOT_FOUND = "Mastership role is not found";
Jian Lif96d41f2016-05-03 09:49:12 -070061
Kavitha Alagesan60093392016-10-26 17:04:26 +053062 private final DeviceService deviceService = get(DeviceService.class);
Jian Lif96d41f2016-05-03 09:49:12 -070063 private final MastershipService mastershipService = get(MastershipService.class);
64 private final MastershipAdminService mastershipAdminService =
65 get(MastershipAdminService.class);
66
67 /**
68 * Returns the role of the local node for the specified device.
69 *
70 * @param deviceId device identifier
Jian Licc730a62016-05-10 16:36:16 -070071 * @return 200 OK with role of the current node
Jian Lif96d41f2016-05-03 09:49:12 -070072 * @onos.rsModel MastershipRole
73 */
74 @GET
75 @Produces(MediaType.APPLICATION_JSON)
76 @Path("{deviceId}/local")
77 public Response getLocalRole(@PathParam("deviceId") String deviceId) {
78 MastershipRole role = mastershipService.getLocalRole(DeviceId.deviceId(deviceId));
79 ObjectNode root = codec(MastershipRole.class).encode(role, this);
80 return ok(root).build();
81 }
82
83 /**
84 * Returns the current master for a given device.
85 *
86 * @param deviceId device identifier
Jian Licc730a62016-05-10 16:36:16 -070087 * @return 200 OK with the identifier of the master controller for the device
Jian Li0409b702016-05-03 18:21:37 -070088 * @onos.rsModel NodeId
Jian Lif96d41f2016-05-03 09:49:12 -070089 */
90 @GET
91 @Produces(MediaType.APPLICATION_JSON)
92 @Path("{deviceId}/master")
93 public Response getMasterFor(@PathParam("deviceId") String deviceId) {
94 NodeId id = nullIsNotFound(mastershipService.getMasterFor(
95 DeviceId.deviceId(deviceId)), NODE_ID_NOT_FOUND);
96
97 ObjectNode root = mapper().createObjectNode();
Jian Li0409b702016-05-03 18:21:37 -070098 root.put(NODE_ID, id.id());
Jian Lif96d41f2016-05-03 09:49:12 -070099 return ok(root).build();
100 }
101
102 /**
103 * Returns controllers connected to a given device, in order of
104 * preference. The first entry in the list is the current master.
105 *
106 * @param deviceId device identifier
Jian Licc730a62016-05-10 16:36:16 -0700107 * @return 200 OK with a list of controller identifiers
Jian Lif96d41f2016-05-03 09:49:12 -0700108 * @onos.rsModel RoleInfo
109 */
110 @GET
111 @Produces(MediaType.APPLICATION_JSON)
112 @Path("{deviceId}/role")
113 public Response getNodesFor(@PathParam("deviceId") String deviceId) {
114 RoleInfo info = nullIsNotFound(mastershipService.getNodesFor(
115 DeviceId.deviceId(deviceId)), ROLE_INFO_NOT_FOUND);
116 ObjectNode root = codec(RoleInfo.class).encode(info, this);
117 return ok(root).build();
118 }
119
120 /**
121 * Returns the devices for which a controller is master.
122 *
123 * @param nodeId controller identifier
Jian Licc730a62016-05-10 16:36:16 -0700124 * @return 200 OK with a set of device identifiers
Jian Li0409b702016-05-03 18:21:37 -0700125 * @onos.rsModel DeviceIds
Jian Lif96d41f2016-05-03 09:49:12 -0700126 */
127 @GET
128 @Produces(MediaType.APPLICATION_JSON)
129 @Path("{nodeId}/device")
130 public Response getDeviceOf(@PathParam("nodeId") String nodeId) {
131 ObjectNode root = mapper().createObjectNode();
Jian Li0409b702016-05-03 18:21:37 -0700132 ArrayNode devicesNode = root.putArray(DEVICE_IDS);
Jian Lif96d41f2016-05-03 09:49:12 -0700133
134 Set<DeviceId> devices = mastershipService.getDevicesOf(NodeId.nodeId(nodeId));
135 if (devices != null) {
136 devices.forEach(id -> devicesNode.add(id.toString()));
137 }
138
139 return ok(root).build();
140 }
141
142 /**
143 * Returns the mastership status of the local controller for a given
144 * device forcing master selection if necessary.
145 *
146 * @param deviceId device identifier
Jian Licc730a62016-05-10 16:36:16 -0700147 * @return 200 OK with the role of this controller instance
Jian Lif96d41f2016-05-03 09:49:12 -0700148 * @onos.rsModel MastershipRole
149 */
150 @GET
151 @Produces(MediaType.APPLICATION_JSON)
152 @Path("{deviceId}/request")
153 public Response requestRoleFor(@PathParam("deviceId") String deviceId) {
Kavitha Alagesan60093392016-10-26 17:04:26 +0530154 DeviceId id = DeviceId.deviceId(deviceId);
155 nullIsNotFound(deviceService.getDevice(id), DEVICE_ID_NOT_FOUND);
156
157 MastershipRole role = nullIsNotFound(mastershipService.requestRoleForSync(id),
158 MASTERSHIP_ROLE_NOT_FOUND);
Jian Li0409b702016-05-03 18:21:37 -0700159 ObjectNode root = codec(MastershipRole.class).encode(role, this);
160 return ok(root).build();
Jian Lif96d41f2016-05-03 09:49:12 -0700161 }
162
163 /**
164 * Abandons mastership of the specified device on the local node thus
165 * forcing selection of a new master. If the local node is not a master
166 * for this device, no master selection will occur.
167 *
168 * @param deviceId device identifier
Jian Licc730a62016-05-10 16:36:16 -0700169 * @return status of the request - CREATED if the JSON is correct
Jian Lif96d41f2016-05-03 09:49:12 -0700170 */
171 @GET
172 @Produces(MediaType.APPLICATION_JSON)
173 @Path("{deviceId}/relinquish")
174 public Response relinquishMastership(@PathParam("deviceId") String deviceId) {
175 DeviceId id = DeviceId.deviceId(deviceId);
Jian Li0409b702016-05-03 18:21:37 -0700176 mastershipService.relinquishMastershipSync(id);
177 return Response.created(id.uri()).build();
Jian Lif96d41f2016-05-03 09:49:12 -0700178 }
179
180 /**
181 * Applies the current mastership role for the specified device.
182 *
183 * @param stream JSON representation of device, node, mastership info
184 * @return status of the request - CREATED if the JSON is correct,
185 * BAD_REQUEST if the JSON is invalid
186 * @onos.rsModel MastershipPut
187 */
188 @PUT
189 @Consumes(MediaType.APPLICATION_JSON)
Jian Lif96d41f2016-05-03 09:49:12 -0700190 public Response setRole(InputStream stream) {
191
192 try {
193 ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
194 JsonNode deviceIdJson = jsonTree.get(DEVICE_ID);
195 JsonNode nodeIdJson = jsonTree.get(NODE_ID);
196 MastershipRole role = codec(MastershipRole.class).decode(jsonTree, this);
197
198 if (deviceIdJson == null) {
199 throw new IllegalArgumentException(DEVICE_ID_INVALID);
200 }
201
202 if (nodeIdJson == null) {
203 throw new IllegalArgumentException(NODE_ID_INVALID);
204 }
205
Jian Li0409b702016-05-03 18:21:37 -0700206 mastershipAdminService.setRoleSync(NodeId.nodeId(nodeIdJson.asText()),
207 DeviceId.deviceId(deviceIdJson.asText()), role);
Jian Lif96d41f2016-05-03 09:49:12 -0700208
209 return Response.ok().build();
Jian Li0409b702016-05-03 18:21:37 -0700210 } catch (IOException e) {
Jian Lif96d41f2016-05-03 09:49:12 -0700211 throw new IllegalArgumentException(e);
212 }
213 }
214
215 /**
216 * Balances the mastership to be shared as evenly as possibly by all
217 * online instances.
218 *
219 * @return status of the request - OK if the request is successfully processed
220 */
221 @GET
222 @Produces(MediaType.APPLICATION_JSON)
223 public Response balanceRoles() {
224 mastershipAdminService.balanceRoles();
225 return Response.ok().build();
226 }
227}