blob: 8a85941b7e5b8b91703560b59e22b2771619eb1f [file] [log] [blame]
/*
* Copyright 2016-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.xran.rest;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.collect.Lists;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.onosproject.rest.AbstractWebResource;
import org.onosproject.xran.XranStore;
import org.onosproject.xran.annotations.Patch;
import org.onosproject.xran.controller.XranController;
import org.onosproject.xran.entities.RnibCell;
import org.onosproject.xran.entities.RnibLink;
import org.onosproject.xran.entities.RnibUe;
import org.openmuc.jasn1.ber.types.BerInteger;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.TimeUnit;
/**
* Link web resource.
*/
@Path("links")
public class LinkWebResource extends AbstractWebResource {
private static final Logger log =
LoggerFactory.getLogger(LinkWebResource.class);
/**
* test.
*
* @param eciHex test
* @param ue test
* @return test
*/
@GET
@Produces(MediaType.APPLICATION_JSON)
public Response getLinksBetween(@DefaultValue("") @QueryParam("cell") String eciHex,
@DefaultValue("-1") @QueryParam("ue") long ue) {
List<RnibLink> list = Lists.newArrayList();
if (!eciHex.isEmpty() && ue != -1) {
RnibLink link = get(XranStore.class).getLinkBetweenCellIdUeId(eciHex, ue);
if (link != null) {
list.add(link);
}
} else if (!eciHex.isEmpty()) {
list.addAll(get(XranStore.class).getLinksByCellId(eciHex));
} else if (ue != -1) {
list.addAll(get(XranStore.class).getLinksByUeId(ue));
} else {
list.addAll(get(XranStore.class).getLinks());
}
try {
ObjectNode rootNode = mapper().createObjectNode();
JsonNode jsonNode = mapper().readTree(list.toString());
rootNode.put("links", jsonNode);
return Response.ok(rootNode.toString()).build();
} catch (IOException e) {
log.error(ExceptionUtils.getFullStackTrace(e));
e.printStackTrace();
return Response.serverError()
.entity(ExceptionUtils.getFullStackTrace(e))
.build();
}
}
/**
* test.
*
* @param src test
* @param dst test
* @param stream test
* @return test
*/
@Patch
@Path("{src},{dst}")
@Consumes(MediaType.APPLICATION_JSON)
public Response patchLinks(@PathParam("src") String src, @PathParam("dst") long dst, InputStream stream) {
RnibLink link = get(XranStore.class).getLinkBetweenCellIdUeId(src, dst);
if (link != null) {
try {
ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
JsonNode type = jsonTree.path("type");
if (!type.isMissingNode()) {
RnibLink.Type anEnum = RnibLink.Type.getEnum(type.asText());
return handleTypeChange(link, anEnum);
}
JsonNode trafficpercent = jsonTree.path("trafficpercent");
if (!trafficpercent.isMissingNode()) {
return handleTrafficChange(link, trafficpercent);
}
JsonNode rrmConf = jsonTree.path("RRMConf");
if (!rrmConf.isMissingNode()) {
return handleRRMChange(link, rrmConf);
}
} catch (Exception e) {
log.error(ExceptionUtils.getFullStackTrace(e));
e.printStackTrace();
return Response.serverError().entity(ExceptionUtils.getFullStackTrace(e)).build();
}
}
return Response.serverError().entity("link not found use POST request").build();
}
/**
* test.
*
* @param src test
* @param dst test
* @param stream test
* @return test
*/
@POST
@Path("{src},{dst}")
@Consumes(MediaType.APPLICATION_JSON)
public Response postLinks(@PathParam("src") String src, @PathParam("dst") long dst, InputStream stream) {
RnibCell cell = get(XranStore.class).getCell(src);
RnibUe ue = get(XranStore.class).getUe(dst);
if (cell == null) {
return Response.serverError()
.entity("cell not found")
.build();
}
if (ue == null) {
return Response.serverError()
.entity("ue not found")
.build();
}
if (get(XranStore.class).getLink(cell.getEcgi(), ue.getMmeS1apId()) != null) {
return Response.serverError()
.entity("link exists use PATCH request")
.build();
}
try {
ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
JsonNode type = jsonTree.path("type");
RnibLink link = new RnibLink(cell, ue);
// store it as non-serving when creating link
get(XranStore.class).storeLink(link);
if (!type.isMissingNode()) {
return handleTypeChange(link, RnibLink.Type.getEnum(type.asText()));
}
JsonNode trafficpercent = jsonTree.path("trafficpercent");
if (!trafficpercent.isMissingNode()) {
return handleTrafficChange(link, trafficpercent);
}
JsonNode rrmConf = jsonTree.path("RRMConf");
if (!rrmConf.isMissingNode()) {
return handleRRMChange(link, rrmConf);
}
} catch (Exception e) {
log.error(ExceptionUtils.getFullStackTrace(e));
e.printStackTrace();
return Response.serverError()
.entity(ExceptionUtils.getFullStackTrace(e))
.build();
}
return Response.serverError()
.entity("unreachable code")
.build();
}
private Response handleTypeChange(RnibLink link, RnibLink.Type newType) throws InterruptedException {
final SynchronousQueue<String>[] queue = new SynchronousQueue[1];
if (newType.equals(RnibLink.Type.SERVING_PRIMARY)) {
switch (link.getType()) {
case SERVING_PRIMARY: {
return Response.serverError()
.entity("link already a primary")
.build();
}
case SERVING_SECONDARY_CA:
case SERVING_SECONDARY_DC:
case NON_SERVING: {
List<RnibLink> linksByUeId = get(XranStore.class).getLinksByUeId(link.getLinkId().getMmeues1apid().longValue());
Optional<RnibLink> primary = linksByUeId.stream()
.filter(l -> l.getType().equals(RnibLink.Type.SERVING_PRIMARY))
.findFirst();
if (primary.isPresent()) {
queue[0] = get(XranController.class).sendHORequest(link, primary.get());
String poll = queue[0].poll(5, TimeUnit.SECONDS);
if (poll != null) {
return Response.ok()
.entity(poll)
.build();
} else {
return Response.serverError()
.entity("did not receive response in time")
.build();
}
} else {
link.setType(RnibLink.Type.SERVING_PRIMARY);
return Response.ok()
.entity("there was not another primary link")
.build();
}
}
}
} else if (newType.equals(RnibLink.Type.NON_SERVING)) {
switch (link.getType()) {
case NON_SERVING:
return Response.ok()
.entity("It's already a non serving link!" + link)
.build();
case SERVING_PRIMARY:
return Response.serverError()
.entity("Cannot change a Primary link.")
.build();
case SERVING_SECONDARY_CA:
case SERVING_SECONDARY_DC:
if (get(XranController.class).sendScellDelete(link)) {
return Response.ok()
.entity("Successfully changed link type to " + link.getType())
.build();
} else {
return Response.serverError()
.entity("Could not change link type.")
.build();
}
}
} else if (newType.equals(RnibLink.Type.SERVING_SECONDARY_CA)) {
switch (link.getType()) {
case SERVING_PRIMARY:
return Response.serverError()
.entity("Cannot change a Primary link.")
.build();
case SERVING_SECONDARY_DC:
case NON_SERVING:
queue[0] = get(XranController.class).sendScellAdd(link);
String poll = queue[0].poll(5, TimeUnit.SECONDS);
if (poll != null) {
return Response.ok()
.entity("Successfully changed link type to " + link.getType())
.build();
} else {
return Response.serverError()
.entity("did not receive response in time")
.build();
}
case SERVING_SECONDARY_CA:
return Response.ok()
.entity("It's already a service secondary ca link!")
.build();
}
}
return Response.serverError()
.entity("Unknown type")
.build();
}
private Response handleTrafficChange(RnibLink link, JsonNode trafficpercent) {
JsonNode jsonNode = trafficpercent.path("traffic-percent-dl");
if (!jsonNode.isMissingNode()) {
link.getTrafficPercent().setTrafficPercentDl(new BerInteger(jsonNode.asInt()));
}
jsonNode = trafficpercent.path("traffic-percent-ul");
if (!jsonNode.isMissingNode()) {
link.getTrafficPercent().setTrafficPercentUl(new BerInteger(jsonNode.asInt()));
}
return Response.ok("trafficpercent changed successfully").build();
}
private Response handleRRMChange(RnibLink link, JsonNode rrmConf) throws InterruptedException {
final SynchronousQueue<String>[] queue = new SynchronousQueue[1];
get(XranStore.class).modifyLinkRrmConf(link, rrmConf);
queue[0] = get(XranController.class).sendModifiedRRMConf(link.getRrmParameters(),
link.getLinkId().getCell().getVersion().equals("3"));
String poll = queue[0].poll(5, TimeUnit.SECONDS);
if (poll != null) {
return Response.ok()
.entity(poll)
.build();
} else {
return Response.serverError()
.entity("did not receive response in time")
.build();
}
}
}