blob: 8b5484f550563470d4115b13bcbf8c77e17eee74 [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;
Ray Milkey86ee5e82018-04-02 15:33:07 -070043import static org.onlab.util.Tools.readTreeFromStream;
Jian Lif96d41f2016-05-03 09:49:12 -070044
45/**
46 * Manage the mastership of ONOS instances.
47 */
48@Path("mastership")
49public final class MastershipWebResource extends AbstractWebResource {
50
Jian Li0409b702016-05-03 18:21:37 -070051 private static final String DEVICE_IDS = "deviceIds";
Jian Lif96d41f2016-05-03 09:49:12 -070052 private static final String DEVICE_ID = "deviceId";
53 private static final String NODE_ID = "nodeId";
54
55 private static final String DEVICE_ID_INVALID = "Invalid deviceId for setting role";
56 private static final String NODE_ID_INVALID = "Invalid nodeId for setting role";
57
Kavitha Alagesan60093392016-10-26 17:04:26 +053058 private static final String DEVICE_ID_NOT_FOUND = "Device Id is not found";
Jian Lif96d41f2016-05-03 09:49:12 -070059 private static final String NODE_ID_NOT_FOUND = "Node id is not found";
60 private static final String ROLE_INFO_NOT_FOUND = "Role info is not found";
61 private static final String MASTERSHIP_ROLE_NOT_FOUND = "Mastership role is not found";
Jian Lif96d41f2016-05-03 09:49:12 -070062
Jian Lif96d41f2016-05-03 09:49:12 -070063 /**
64 * Returns the role of the local node for the specified device.
65 *
66 * @param deviceId device identifier
Jian Licc730a62016-05-10 16:36:16 -070067 * @return 200 OK with role of the current node
Jian Lif96d41f2016-05-03 09:49:12 -070068 * @onos.rsModel MastershipRole
69 */
70 @GET
71 @Produces(MediaType.APPLICATION_JSON)
72 @Path("{deviceId}/local")
73 public Response getLocalRole(@PathParam("deviceId") String deviceId) {
Harshada Chaundkar4f62a1e2019-02-18 12:27:34 -050074 MastershipService mastershipService = get(MastershipService.class);
Jian Lif96d41f2016-05-03 09:49:12 -070075 MastershipRole role = mastershipService.getLocalRole(DeviceId.deviceId(deviceId));
76 ObjectNode root = codec(MastershipRole.class).encode(role, this);
77 return ok(root).build();
78 }
79
80 /**
81 * Returns the current master for a given device.
82 *
83 * @param deviceId device identifier
Jian Licc730a62016-05-10 16:36:16 -070084 * @return 200 OK with the identifier of the master controller for the device
Jian Li0409b702016-05-03 18:21:37 -070085 * @onos.rsModel NodeId
Jian Lif96d41f2016-05-03 09:49:12 -070086 */
87 @GET
88 @Produces(MediaType.APPLICATION_JSON)
89 @Path("{deviceId}/master")
90 public Response getMasterFor(@PathParam("deviceId") String deviceId) {
Harshada Chaundkar4f62a1e2019-02-18 12:27:34 -050091 MastershipService mastershipService = get(MastershipService.class);
Jian Lif96d41f2016-05-03 09:49:12 -070092 NodeId id = nullIsNotFound(mastershipService.getMasterFor(
93 DeviceId.deviceId(deviceId)), NODE_ID_NOT_FOUND);
94
95 ObjectNode root = mapper().createObjectNode();
Jian Li0409b702016-05-03 18:21:37 -070096 root.put(NODE_ID, id.id());
Jian Lif96d41f2016-05-03 09:49:12 -070097 return ok(root).build();
98 }
99
100 /**
101 * Returns controllers connected to a given device, in order of
102 * preference. The first entry in the list is the current master.
103 *
104 * @param deviceId device identifier
Jian Licc730a62016-05-10 16:36:16 -0700105 * @return 200 OK with a list of controller identifiers
Jian Lif96d41f2016-05-03 09:49:12 -0700106 * @onos.rsModel RoleInfo
107 */
108 @GET
109 @Produces(MediaType.APPLICATION_JSON)
110 @Path("{deviceId}/role")
111 public Response getNodesFor(@PathParam("deviceId") String deviceId) {
Harshada Chaundkar4f62a1e2019-02-18 12:27:34 -0500112 MastershipService mastershipService = get(MastershipService.class);
Jian Lif96d41f2016-05-03 09:49:12 -0700113 RoleInfo info = nullIsNotFound(mastershipService.getNodesFor(
114 DeviceId.deviceId(deviceId)), ROLE_INFO_NOT_FOUND);
115 ObjectNode root = codec(RoleInfo.class).encode(info, this);
116 return ok(root).build();
117 }
118
119 /**
120 * Returns the devices for which a controller is master.
121 *
122 * @param nodeId controller identifier
Jian Licc730a62016-05-10 16:36:16 -0700123 * @return 200 OK with a set of device identifiers
Jian Li0409b702016-05-03 18:21:37 -0700124 * @onos.rsModel DeviceIds
Jian Lif96d41f2016-05-03 09:49:12 -0700125 */
126 @GET
127 @Produces(MediaType.APPLICATION_JSON)
128 @Path("{nodeId}/device")
129 public Response getDeviceOf(@PathParam("nodeId") String nodeId) {
Harshada Chaundkar4f62a1e2019-02-18 12:27:34 -0500130 MastershipService mastershipService = get(MastershipService.class);
Jian Lif96d41f2016-05-03 09:49:12 -0700131 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) {
Harshada Chaundkar4f62a1e2019-02-18 12:27:34 -0500154 MastershipService mastershipService = get(MastershipService.class);
155 DeviceService deviceService = get(DeviceService.class);
Kavitha Alagesan60093392016-10-26 17:04:26 +0530156 DeviceId id = DeviceId.deviceId(deviceId);
157 nullIsNotFound(deviceService.getDevice(id), DEVICE_ID_NOT_FOUND);
158
159 MastershipRole role = nullIsNotFound(mastershipService.requestRoleForSync(id),
160 MASTERSHIP_ROLE_NOT_FOUND);
Jian Li0409b702016-05-03 18:21:37 -0700161 ObjectNode root = codec(MastershipRole.class).encode(role, this);
162 return ok(root).build();
Jian Lif96d41f2016-05-03 09:49:12 -0700163 }
164
165 /**
166 * Abandons mastership of the specified device on the local node thus
167 * forcing selection of a new master. If the local node is not a master
168 * for this device, no master selection will occur.
169 *
170 * @param deviceId device identifier
Jian Licc730a62016-05-10 16:36:16 -0700171 * @return status of the request - CREATED if the JSON is correct
Jian Lif96d41f2016-05-03 09:49:12 -0700172 */
173 @GET
174 @Produces(MediaType.APPLICATION_JSON)
175 @Path("{deviceId}/relinquish")
176 public Response relinquishMastership(@PathParam("deviceId") String deviceId) {
Harshada Chaundkar4f62a1e2019-02-18 12:27:34 -0500177 MastershipService mastershipService = get(MastershipService.class);
Jian Lif96d41f2016-05-03 09:49:12 -0700178 DeviceId id = DeviceId.deviceId(deviceId);
Jian Li0409b702016-05-03 18:21:37 -0700179 mastershipService.relinquishMastershipSync(id);
180 return Response.created(id.uri()).build();
Jian Lif96d41f2016-05-03 09:49:12 -0700181 }
182
183 /**
184 * Applies the current mastership role for the specified device.
185 *
186 * @param stream JSON representation of device, node, mastership info
187 * @return status of the request - CREATED if the JSON is correct,
188 * BAD_REQUEST if the JSON is invalid
189 * @onos.rsModel MastershipPut
190 */
191 @PUT
192 @Consumes(MediaType.APPLICATION_JSON)
Jian Lif96d41f2016-05-03 09:49:12 -0700193 public Response setRole(InputStream stream) {
Harshada Chaundkar4f62a1e2019-02-18 12:27:34 -0500194 MastershipAdminService mastershipAdminService = get(MastershipAdminService.class);
Jian Lif96d41f2016-05-03 09:49:12 -0700195
196 try {
Ray Milkey86ee5e82018-04-02 15:33:07 -0700197 ObjectNode jsonTree = readTreeFromStream(mapper(), stream);
Jian Lif96d41f2016-05-03 09:49:12 -0700198 JsonNode deviceIdJson = jsonTree.get(DEVICE_ID);
199 JsonNode nodeIdJson = jsonTree.get(NODE_ID);
200 MastershipRole role = codec(MastershipRole.class).decode(jsonTree, this);
201
202 if (deviceIdJson == null) {
203 throw new IllegalArgumentException(DEVICE_ID_INVALID);
204 }
205
206 if (nodeIdJson == null) {
207 throw new IllegalArgumentException(NODE_ID_INVALID);
208 }
209
Jian Li0409b702016-05-03 18:21:37 -0700210 mastershipAdminService.setRoleSync(NodeId.nodeId(nodeIdJson.asText()),
211 DeviceId.deviceId(deviceIdJson.asText()), role);
Jian Lif96d41f2016-05-03 09:49:12 -0700212
213 return Response.ok().build();
Jian Li0409b702016-05-03 18:21:37 -0700214 } catch (IOException e) {
Jian Lif96d41f2016-05-03 09:49:12 -0700215 throw new IllegalArgumentException(e);
216 }
217 }
218
219 /**
220 * Balances the mastership to be shared as evenly as possibly by all
221 * online instances.
222 *
223 * @return status of the request - OK if the request is successfully processed
224 */
225 @GET
226 @Produces(MediaType.APPLICATION_JSON)
227 public Response balanceRoles() {
Harshada Chaundkar4f62a1e2019-02-18 12:27:34 -0500228 MastershipAdminService mastershipAdminService = get(MastershipAdminService.class);
Jian Lif96d41f2016-05-03 09:49:12 -0700229 mastershipAdminService.balanceRoles();
230 return Response.ok().build();
231 }
232}