blob: 99cc28cc3b42b2a03ba68a266621b94336208fff [file] [log] [blame]
Jian Lif96d41f2016-05-03 09:49:12 -07001/*
2 * Copyright 2016-present Open Networking Laboratory
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 */
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;
27import org.onosproject.rest.AbstractWebResource;
28
29import javax.ws.rs.Consumes;
30import javax.ws.rs.GET;
31import javax.ws.rs.PUT;
32import javax.ws.rs.Path;
33import javax.ws.rs.PathParam;
34import javax.ws.rs.Produces;
35import javax.ws.rs.core.MediaType;
36import javax.ws.rs.core.Response;
37import java.io.IOException;
38import java.io.InputStream;
39import java.util.Set;
Jian Lif96d41f2016-05-03 09:49:12 -070040
41import static org.onlab.util.Tools.nullIsNotFound;
42
43/**
44 * Manage the mastership of ONOS instances.
45 */
46@Path("mastership")
47public final class MastershipWebResource extends AbstractWebResource {
48
Jian Li0409b702016-05-03 18:21:37 -070049 private static final String DEVICE_IDS = "deviceIds";
Jian Lif96d41f2016-05-03 09:49:12 -070050 private static final String DEVICE_ID = "deviceId";
51 private static final String NODE_ID = "nodeId";
52
53 private static final String DEVICE_ID_INVALID = "Invalid deviceId for setting role";
54 private static final String NODE_ID_INVALID = "Invalid nodeId for setting role";
55
56 private static final String NODE_ID_NOT_FOUND = "Node id is not found";
57 private static final String ROLE_INFO_NOT_FOUND = "Role info is not found";
58 private static final String MASTERSHIP_ROLE_NOT_FOUND = "Mastership role is not found";
Jian Lif96d41f2016-05-03 09:49:12 -070059
60 private final MastershipService mastershipService = get(MastershipService.class);
61 private final MastershipAdminService mastershipAdminService =
62 get(MastershipAdminService.class);
63
64 /**
65 * Returns the role of the local node for the specified device.
66 *
67 * @param deviceId device identifier
68 * @return role of the current node
69 * @onos.rsModel MastershipRole
70 */
71 @GET
72 @Produces(MediaType.APPLICATION_JSON)
73 @Path("{deviceId}/local")
74 public Response getLocalRole(@PathParam("deviceId") String deviceId) {
75 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
84 * @return 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) {
91 NodeId id = nullIsNotFound(mastershipService.getMasterFor(
92 DeviceId.deviceId(deviceId)), NODE_ID_NOT_FOUND);
93
94 ObjectNode root = mapper().createObjectNode();
Jian Li0409b702016-05-03 18:21:37 -070095 root.put(NODE_ID, id.id());
Jian Lif96d41f2016-05-03 09:49:12 -070096 return ok(root).build();
97 }
98
99 /**
100 * Returns controllers connected to a given device, in order of
101 * preference. The first entry in the list is the current master.
102 *
103 * @param deviceId device identifier
104 * @return a list of controller identifiers
105 * @onos.rsModel RoleInfo
106 */
107 @GET
108 @Produces(MediaType.APPLICATION_JSON)
109 @Path("{deviceId}/role")
110 public Response getNodesFor(@PathParam("deviceId") String deviceId) {
111 RoleInfo info = nullIsNotFound(mastershipService.getNodesFor(
112 DeviceId.deviceId(deviceId)), ROLE_INFO_NOT_FOUND);
113 ObjectNode root = codec(RoleInfo.class).encode(info, this);
114 return ok(root).build();
115 }
116
117 /**
118 * Returns the devices for which a controller is master.
119 *
120 * @param nodeId controller identifier
121 * @return a set of device identifiers
Jian Li0409b702016-05-03 18:21:37 -0700122 * @onos.rsModel DeviceIds
Jian Lif96d41f2016-05-03 09:49:12 -0700123 */
124 @GET
125 @Produces(MediaType.APPLICATION_JSON)
126 @Path("{nodeId}/device")
127 public Response getDeviceOf(@PathParam("nodeId") String nodeId) {
128 ObjectNode root = mapper().createObjectNode();
Jian Li0409b702016-05-03 18:21:37 -0700129 ArrayNode devicesNode = root.putArray(DEVICE_IDS);
Jian Lif96d41f2016-05-03 09:49:12 -0700130
131 Set<DeviceId> devices = mastershipService.getDevicesOf(NodeId.nodeId(nodeId));
132 if (devices != null) {
133 devices.forEach(id -> devicesNode.add(id.toString()));
134 }
135
136 return ok(root).build();
137 }
138
139 /**
140 * Returns the mastership status of the local controller for a given
141 * device forcing master selection if necessary.
142 *
143 * @param deviceId device identifier
144 * @return the role of this controller instance
145 * @onos.rsModel MastershipRole
146 */
147 @GET
148 @Produces(MediaType.APPLICATION_JSON)
149 @Path("{deviceId}/request")
150 public Response requestRoleFor(@PathParam("deviceId") String deviceId) {
Jian Li0409b702016-05-03 18:21:37 -0700151 MastershipRole role = nullIsNotFound(mastershipService.requestRoleForSync(
152 DeviceId.deviceId(deviceId)), MASTERSHIP_ROLE_NOT_FOUND);
153 ObjectNode root = codec(MastershipRole.class).encode(role, this);
154 return ok(root).build();
Jian Lif96d41f2016-05-03 09:49:12 -0700155 }
156
157 /**
158 * Abandons mastership of the specified device on the local node thus
159 * forcing selection of a new master. If the local node is not a master
160 * for this device, no master selection will occur.
161 *
162 * @param deviceId device identifier
163 * @return status of the request
164 */
165 @GET
166 @Produces(MediaType.APPLICATION_JSON)
167 @Path("{deviceId}/relinquish")
168 public Response relinquishMastership(@PathParam("deviceId") String deviceId) {
169 DeviceId id = DeviceId.deviceId(deviceId);
Jian Li0409b702016-05-03 18:21:37 -0700170 mastershipService.relinquishMastershipSync(id);
171 return Response.created(id.uri()).build();
Jian Lif96d41f2016-05-03 09:49:12 -0700172 }
173
174 /**
175 * Applies the current mastership role for the specified device.
176 *
177 * @param stream JSON representation of device, node, mastership info
178 * @return status of the request - CREATED if the JSON is correct,
179 * BAD_REQUEST if the JSON is invalid
180 * @onos.rsModel MastershipPut
181 */
182 @PUT
183 @Consumes(MediaType.APPLICATION_JSON)
184 @Produces(MediaType.APPLICATION_JSON)
185 public Response setRole(InputStream stream) {
186
187 try {
188 ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
189 JsonNode deviceIdJson = jsonTree.get(DEVICE_ID);
190 JsonNode nodeIdJson = jsonTree.get(NODE_ID);
191 MastershipRole role = codec(MastershipRole.class).decode(jsonTree, this);
192
193 if (deviceIdJson == null) {
194 throw new IllegalArgumentException(DEVICE_ID_INVALID);
195 }
196
197 if (nodeIdJson == null) {
198 throw new IllegalArgumentException(NODE_ID_INVALID);
199 }
200
Jian Li0409b702016-05-03 18:21:37 -0700201 mastershipAdminService.setRoleSync(NodeId.nodeId(nodeIdJson.asText()),
202 DeviceId.deviceId(deviceIdJson.asText()), role);
Jian Lif96d41f2016-05-03 09:49:12 -0700203
204 return Response.ok().build();
Jian Li0409b702016-05-03 18:21:37 -0700205 } catch (IOException e) {
Jian Lif96d41f2016-05-03 09:49:12 -0700206 throw new IllegalArgumentException(e);
207 }
208 }
209
210 /**
211 * Balances the mastership to be shared as evenly as possibly by all
212 * online instances.
213 *
214 * @return status of the request - OK if the request is successfully processed
215 */
216 @GET
217 @Produces(MediaType.APPLICATION_JSON)
218 public Response balanceRoles() {
219 mastershipAdminService.balanceRoles();
220 return Response.ok().build();
221 }
222}