[ONOS-3801] Implements L3 REST call json parser
- Nullability check for RouterCodec, RoutingInterfaceCodec, RoutingWebResource.
- Copyright fixed.
- externalFixedIps() method in OpenstackExternalGateway class returns the immutable Map.
Change-Id: I841cc1774a074e167ffe327c6e81d3f245cc8ee0
diff --git a/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/impl/OpenstackArpHandler.java b/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/impl/OpenstackArpHandler.java
index 3bbe98b..7fb489a 100644
--- a/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/impl/OpenstackArpHandler.java
+++ b/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/impl/OpenstackArpHandler.java
@@ -1,5 +1,5 @@
/*
-* Copyright 2015 Open Networking Laboratory
+* Copyright 2015-2016 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.
@@ -28,9 +28,11 @@
import org.onosproject.net.packet.InboundPacket;
import org.onosproject.net.packet.PacketService;
import org.onosproject.openstackswitching.OpenstackPort;
+import org.onosproject.openstackswitching.OpenstackPortInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.nio.ByteBuffer;
+import java.util.Collection;
import static com.google.common.base.Preconditions.checkNotNull;
@@ -41,6 +43,7 @@
private static Logger log = LoggerFactory
.getLogger(OpenstackArpHandler.class);
+ private static final MacAddress GATEWAY_MAC = MacAddress.valueOf("1f:1f:1f:1f:1f:1f");
private PacketService packetService;
private OpenstackRestHandler restHandler;
private HostService hostService;
@@ -66,7 +69,7 @@
*
* @param pkt ARP request packet
*/
- public void processPacketIn(InboundPacket pkt) {
+ public void processPacketIn(InboundPacket pkt, Collection<OpenstackPortInfo> openstackPortInfoCollection) {
Ethernet ethRequest = pkt.parsed();
ARP arp = (ARP) ethRequest.getPayload();
@@ -74,10 +77,21 @@
return;
}
+ IpAddress sourceIp = Ip4Address.valueOf(arp.getSenderProtocolAddress());
+ MacAddress srcMac = MacAddress.valueOf(arp.getSenderHardwareAddress());
+ OpenstackPortInfo portInfo = openstackPortInfoCollection.stream()
+ .filter(p -> p.ip().equals(sourceIp) && p.mac().equals(srcMac)).findFirst().orElse(null);
IpAddress targetIp = Ip4Address.valueOf(arp.getTargetProtocolAddress());
- MacAddress dstMac = getMacFromHostService(targetIp);
- if (dstMac == null) {
- dstMac = getMacFromOpenstack(targetIp);
+
+ MacAddress dstMac;
+
+ if (targetIp.equals(portInfo == null ? null : portInfo.gatewayIP())) {
+ dstMac = GATEWAY_MAC;
+ } else {
+ dstMac = getMacFromHostService(targetIp);
+ if (dstMac == null) {
+ dstMac = getMacFromOpenstack(targetIp);
+ }
}
if (dstMac == null) {
diff --git a/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/impl/OpenstackPortInfo.java b/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/impl/OpenstackPortInfo.java
deleted file mode 100644
index 1b6250e..0000000
--- a/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/impl/OpenstackPortInfo.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright 2014-2015 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.openstackswitching.impl;
-
-import org.onlab.packet.Ip4Address;
-import org.onlab.packet.MacAddress;
-import org.onosproject.net.DeviceId;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-/**
- * Contains OpenstackPort Information.
- */
-public final class OpenstackPortInfo {
-
- private final Ip4Address hostIp;
- private final DeviceId deviceId;
- private final MacAddress hostMac;
- private final long vni;
-
- public OpenstackPortInfo(Ip4Address hostIp, MacAddress hostMac, DeviceId deviceId,
- long vni) {
- this.hostIp = hostIp;
- this.hostMac = hostMac;
- this.deviceId = deviceId;
- this.vni = vni;
- }
-
- public Ip4Address ip() {
- return hostIp;
- }
-
- public MacAddress mac() {
- return hostMac;
- }
-
- public DeviceId deviceId() {
- return deviceId;
- }
-
- public long vni() {
- return vni;
- }
-
- public static OpenstackPortInfo.Builder builder() {
- return new Builder();
- }
-
- public static final class Builder {
- private Ip4Address hostIp;
- private MacAddress hostMac;
- private DeviceId deviceId;
- private long vni;
-
- public Builder setHostIp(Ip4Address hostIp) {
- this.hostIp = checkNotNull(hostIp, "hostIp cannot be null");
- return this;
- }
-
- public Builder setHostMac(MacAddress hostMac) {
- this.hostMac = checkNotNull(hostMac, "hostMac cannot be bull");
- return this;
- }
-
- public Builder setDeviceId(DeviceId deviceId) {
- this.deviceId = checkNotNull(deviceId, "deviceId cannot be null");
- return this;
- }
-
- public Builder setVni(long vni) {
- this.vni = checkNotNull(vni, "vni cannot be null");
- return this;
- }
- public OpenstackPortInfo build() {
- return new OpenstackPortInfo(this);
- }
- }
-
- private OpenstackPortInfo(Builder builder) {
- hostIp = builder.hostIp;
- hostMac = builder.hostMac;
- deviceId = builder.deviceId;
- vni = builder.vni;
- }
-}
diff --git a/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/impl/OpenstackRestHandler.java b/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/impl/OpenstackRestHandler.java
index edf14b0..ad8328e 100644
--- a/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/impl/OpenstackRestHandler.java
+++ b/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/impl/OpenstackRestHandler.java
@@ -21,12 +21,14 @@
import com.google.common.collect.Lists;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.WebResource;
+import org.onosproject.openstackrouting.OpenstackRouter;
import org.onosproject.openstackswitching.OpenstackNetwork;
import org.onosproject.openstackswitching.OpenstackPort;
import org.onosproject.openstackswitching.OpenstackSubnet;
import org.onosproject.openstackswitching.web.OpenstackNetworkCodec;
import org.onosproject.openstackswitching.web.OpenstackPortCodec;
import org.onosproject.openstackswitching.web.OpenstackSecurityGroupCodec;
+import org.onosproject.openstackswitching.web.OpenstackRouterCodec;
import org.onosproject.openstackswitching.web.OpenstackSubnetCodec;
import org.slf4j.Logger;
import javax.ws.rs.core.MediaType;
@@ -51,6 +53,7 @@
private static final String URI_SECURITY_GROUPS = "security-groups";
private static final String URI_TOKENS = "tokens";
+ private static final String PATH_ROUTERS = "routers";
private static final String PATH_NETWORKS = "networks";
private static final String PATH_PORTS = "ports";
private static final String PATH_SUBNETS = "subnets";
@@ -137,6 +140,30 @@
return openstackPorts;
}
+ public Collection<OpenstackRouter> getRouters() {
+ WebResource.Builder builder = getClientBuilder(neutronUrl + PATH_ROUTERS);
+ String response = builder.accept(MediaType.APPLICATION_JSON_TYPE).
+ header(HEADER_AUTH_TOKEN, getToken()).get(String.class);
+
+ ObjectMapper mapper = new ObjectMapper();
+ List<OpenstackRouter> openstackRouters = Lists.newArrayList();
+
+ try {
+ ObjectNode node = (ObjectNode) mapper.readTree(response);
+ ArrayNode routerList = (ArrayNode) node.path(PATH_ROUTERS);
+ OpenstackRouterCodec openstackRouterCodec = new OpenstackRouterCodec();
+ routerList.forEach(r -> openstackRouters
+ .add(openstackRouterCodec.decode((ObjectNode) r, null)));
+ } catch (IOException e) {
+ log.warn("getRouters()", e);
+ }
+
+ log.debug("router response:" + response);
+ openstackRouters.forEach(r -> log.debug("router ID: {}", r.id()));
+
+ return openstackRouters;
+ }
+
/**
* Returns Subnet information in Neutron.
*
diff --git a/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/impl/OpenstackSwitchingConfig.java b/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/impl/OpenstackSwitchingConfig.java
index eec14f5..11eff61 100644
--- a/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/impl/OpenstackSwitchingConfig.java
+++ b/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/impl/OpenstackSwitchingConfig.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2014 Open Networking Laboratory
+ * Copyright 2015-2016 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.
@@ -28,6 +28,7 @@
public static final String KEYSTONE_SERVER = "keystone_server";
public static final String USER_NAME = "user_name";
public static final String PASSWORD = "password";
+ public static final String PHYSICAL_ROUTER_MAC = "physicalRouterMac";
/**
* Returns the flag whether the app pushes flows or not.
@@ -76,6 +77,14 @@
}
/**
+ * Returns the MacAddress for physical router.
+ *
+ * @return physical router mac
+ */
+ public String physicalRouterMac() {
+ return get(PHYSICAL_ROUTER_MAC, "");
+ }
+ /**
* Sets the flag whether the app pushes flows or not.
*
* @param flag the flag whether the app pushes flows or not
diff --git a/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/impl/OpenstackSwitchingManager.java b/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/impl/OpenstackSwitchingManager.java
index 572a395..572e204 100644
--- a/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/impl/OpenstackSwitchingManager.java
+++ b/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/impl/OpenstackSwitchingManager.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2015 Open Networking Laboratory
+ * Copyright 2015-2016 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.
@@ -50,8 +50,12 @@
import org.onosproject.net.packet.PacketContext;
import org.onosproject.net.packet.PacketProcessor;
import org.onosproject.net.packet.PacketService;
+import org.onosproject.openstackrouting.OpenstackRouter;
+import org.onosproject.openstackrouting.OpenstackRouterInterface;
+import org.onosproject.openstackrouting.OpenstackRoutingService;
import org.onosproject.openstackswitching.OpenstackNetwork;
import org.onosproject.openstackswitching.OpenstackPort;
+import org.onosproject.openstackswitching.OpenstackPortInfo;
import org.onosproject.openstackswitching.OpenstackSubnet;
import org.onosproject.openstackswitching.OpenstackSwitchingService;
import org.slf4j.Logger;
@@ -103,11 +107,14 @@
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected DriverService driverService;
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected OpenstackRoutingService openstackRoutingService;
+
public static final String PORTNAME_PREFIX_VM = "tap";
public static final String PORTNAME_PREFIX_ROUTER = "qr-";
public static final String PORTNAME_PREFIX_TUNNEL = "vxlan";
public static final String PORTNAME = "portName";
-
+ private static final String ROUTER_INTERFACE = "network:router_interface";
public static final String DEVICE_OWNER_GATEWAY = "network:router_gateway";
private ApplicationId appId;
@@ -116,6 +123,7 @@
private Ip4Address keystoneServer;
private String userName;
private String password;
+ private String physicalRouterMac;
private OpenstackArpHandler arpHandler;
private OpenstackRestHandler restHandler;
@@ -139,7 +147,6 @@
}
);
-
private Map<String, OpenstackPortInfo> openstackPortInfoMap = Maps.newHashMap();
@Activate
@@ -172,9 +179,12 @@
@Override
public void createPorts(OpenstackPort openstackPort) {
- if (!openstackPort.fixedIps().isEmpty()
- && !openstackPort.deviceOwner().equals(DEVICE_OWNER_GATEWAY)) {
- registerDhcpInfo(openstackPort);
+
+ if (!openstackPort.deviceOwner().equals(ROUTER_INTERFACE)
+ && !openstackPort.deviceOwner().equals(DEVICE_OWNER_GATEWAY)) {
+ if (!openstackPort.fixedIps().isEmpty()) {
+ registerDhcpInfo(openstackPort);
+ }
}
if (!openstackPort.securityGroups().isEmpty()) {
@@ -236,6 +246,11 @@
}
@Override
+ public Collection<OpenstackPort> ports() {
+ return restHandler.getPorts();
+ }
+
+ @Override
public OpenstackPort port(Port port) {
Collection<OpenstackPort> ports = restHandler.getPorts();
String uuid = port.annotations().value(PORTNAME).substring(3);
@@ -291,6 +306,57 @@
}
}
+ @Override
+ public void createRouter(OpenstackRouter openstackRouter) {
+ openstackRoutingService.createRouter(openstackRouter);
+ }
+ @Override
+ public void updateRouter(String routerId) {
+ openstackRoutingService.updateRouter(router(routerId));
+ }
+
+ @Override
+ public void removeRouterInterface(OpenstackRouterInterface openstackRouterInterface) {
+ openstackRoutingService.removeRouterInterface(openstackRouterInterface);
+ }
+ @Override
+ public void deleteRouter(String id) {
+ openstackRoutingService.deleteRouter(id);
+ }
+
+ @Override
+ public void updateRouterInterface(OpenstackRouterInterface openstackRouterInterface) {
+ openstackRoutingService.updateRouterInterface(openstackRouterInterface);
+ }
+
+ @Override
+ public OpenstackRouter router(String routerId) {
+ Collection<OpenstackRouter> openstackRouters = restHandler.getRouters();
+ try {
+ return openstackRouters.stream()
+ .filter(r -> r.id().equals(routerId))
+ .findAny().get();
+ } catch (NoSuchElementException e) {
+ log.warn("There is no router info for subnet ID {}", routerId);
+ return null;
+ }
+ }
+
+ @Override
+ public Collection<OpenstackRouter> routers() {
+ return restHandler.getRouters();
+ }
+
+ @Override
+ public Collection<OpenstackPortInfo> portInfos() {
+ return openstackPortInfoMap.values();
+ }
+
+ @Override
+ public String physicalRouterMac() {
+ return physicalRouterMac;
+ }
+
private void processDeviceAdded(Device device) {
log.debug("device {} is added", device.id());
}
@@ -301,8 +367,11 @@
OpenstackSwitchingRulePopulator rulePopulator =
new OpenstackSwitchingRulePopulator(appId, flowObjectiveService,
deviceService, restHandler, driverService);
+
rulePopulator.populateSwitchingRules(doNotPushFlows, device, port);
- updatePortMap(device.id(), port, restHandler.getNetworks(), rulePopulator.openstackPort(port));
+ updatePortMap(device.id(), port, restHandler.getNetworks(), restHandler.getSubnets(),
+ rulePopulator.openstackPort(port));
+
//In case portupdate event is driven by vm shutoff from openstack
} else if (!port.isEnabled() && openstackPortInfoMap.containsKey(port.annotations().value(PORTNAME))) {
log.debug("Flowrules according to the port {} were removed", port.number().toString());
@@ -327,6 +396,7 @@
deviceService, restHandler, driverService);
Collection<OpenstackNetwork> networks = restHandler.getNetworks();
+ Collection<OpenstackSubnet> subnets = restHandler.getSubnets();
deviceService.getDevices().forEach(device -> {
log.debug("device {} num of ports {} ", device.id(),
@@ -339,7 +409,7 @@
if (osPort != null && !osPort.deviceOwner().equals(DEVICE_OWNER_GATEWAY)) {
if (!doNotPushFlows) {
rulePopulator.populateSwitchingRules(doNotPushFlows, device, vmPort);
- updatePortMap(device.id(), vmPort, networks, osPort);
+ updatePortMap(device.id(), vmPort, networks, subnets, osPort);
}
registerDhcpInfo(osPort);
} else {
@@ -352,16 +422,23 @@
}
private void updatePortMap(DeviceId deviceId, Port port, Collection<OpenstackNetwork> networks,
- OpenstackPort openstackPort) {
+ Collection<OpenstackSubnet> subnets, OpenstackPort openstackPort) {
long vni = Long.parseLong(networks.stream()
.filter(n -> n.id().equals(openstackPort.networkId()))
.findAny().orElse(null).segmentId());
+ OpenstackSubnet openstackSubnet = subnets.stream()
+ .filter(n -> n.networkId().equals(openstackPort.networkId()))
+ .findFirst().get();
+
+ Ip4Address gatewayIPAddress = Ip4Address.valueOf(openstackSubnet.gatewayIp());
+
OpenstackPortInfo.Builder portBuilder = OpenstackPortInfo.builder()
.setDeviceId(deviceId)
.setHostIp((Ip4Address) openstackPort.fixedIps().values().stream().findFirst().orElse(null))
.setHostMac(openstackPort.macAddress())
- .setVni(vni);
+ .setVni(vni)
+ .setGatewayIP(gatewayIPAddress);
openstackPortInfoMap.putIfAbsent(port.annotations().value(PORTNAME),
portBuilder.build());
@@ -420,7 +497,6 @@
@Override
public void process(PacketContext context) {
-
if (context.isHandled()) {
return;
}
@@ -429,7 +505,7 @@
Ethernet ethernet = pkt.parsed();
if (ethernet != null && ethernet.getEtherType() == Ethernet.TYPE_ARP) {
- arpHandler.processPacketIn(pkt);
+ arpHandler.processPacketIn(pkt, openstackPortInfoMap.values());
}
}
}
@@ -510,6 +586,7 @@
return;
}
doNotPushFlows = cfg.doNotPushFlows();
+ physicalRouterMac = cfg.physicalRouterMac();
restHandler = new OpenstackRestHandler(cfg);
arpHandler = new OpenstackArpHandler(restHandler, packetService, hostService);
initializeFlowRules();
diff --git a/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/impl/OpenstackSwitchingRulePopulator.java b/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/impl/OpenstackSwitchingRulePopulator.java
index a02f9f5..0ebfe19 100644
--- a/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/impl/OpenstackSwitchingRulePopulator.java
+++ b/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/impl/OpenstackSwitchingRulePopulator.java
@@ -42,6 +42,7 @@
import org.onosproject.net.flowobjective.ForwardingObjective;
import org.onosproject.openstackswitching.OpenstackNetwork;
import org.onosproject.openstackswitching.OpenstackPort;
+import org.onosproject.openstackswitching.OpenstackPortInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
diff --git a/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/web/OpensatckRouterWebResource.java b/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/web/OpensatckRouterWebResource.java
new file mode 100644
index 0000000..aa9dfe4
--- /dev/null
+++ b/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/web/OpensatckRouterWebResource.java
@@ -0,0 +1,172 @@
+/*
+ * Copyright 2016 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.openstackswitching.web;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.onosproject.openstackrouting.OpenstackRouter;
+import org.onosproject.openstackrouting.OpenstackRouterInterface;
+import org.onosproject.openstackswitching.OpenstackSwitchingService;
+import org.onosproject.rest.AbstractWebResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import java.io.InputStream;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Handles REST API call of Neturon L3 plugin.
+ */
+
+@Path("routers")
+public class OpensatckRouterWebResource extends AbstractWebResource {
+ protected static final Logger log = LoggerFactory
+ .getLogger(OpenstackNetworkWebResource.class);
+
+ private static final OpenstackRouterInterfaceCodec ROUTER_INTERFACE_CODEC
+ = new OpenstackRouterInterfaceCodec();
+ private static final OpenstackRouterCodec ROUTER_CODEC
+ = new OpenstackRouterCodec();
+
+ @POST
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response createRouter(InputStream input) {
+ checkNotNull(input);
+ try {
+ ObjectMapper mapper = new ObjectMapper();
+ ObjectNode routerNode = (ObjectNode) mapper.readTree(input);
+
+ OpenstackRouter openstackRouter
+ = ROUTER_CODEC.decode(routerNode, this);
+
+ OpenstackSwitchingService switchingService
+ = getService(OpenstackSwitchingService.class);
+ switchingService.createRouter(openstackRouter);
+
+ log.debug("REST API CREATE router is called {}", input.toString());
+ return Response.status(Response.Status.OK).build();
+ } catch (Exception e) {
+ log.error("Create Router failed because of exception {}",
+ e.toString());
+ return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(e.toString())
+ .build();
+ }
+ }
+
+ @PUT
+ @Path("{id}")
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response updateRouter(@PathParam("id") String id) {
+ checkNotNull(id);
+ try {
+ OpenstackSwitchingService switchingService
+ = getService(OpenstackSwitchingService.class);
+ switchingService.updateRouter(id);
+
+ log.debug("REST API UPDATE router is called from router {}", id);
+ return Response.status(Response.Status.OK).build();
+ } catch (Exception e) {
+ log.error("Updates Router failed because of exception {}",
+ e.toString());
+ return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(e.toString())
+ .build();
+ }
+ }
+
+ @PUT
+ @Path("{id}/add_router_interface")
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response addRouterInterface(InputStream input) {
+ checkNotNull(input);
+ try {
+ ObjectMapper mapper = new ObjectMapper();
+ ObjectNode routerIfNode = (ObjectNode) mapper.readTree(input);
+
+ OpenstackRouterInterface openstackRouterInterface
+ = ROUTER_INTERFACE_CODEC.decode(routerIfNode, this);
+
+ OpenstackSwitchingService switchingService
+ = getService(OpenstackSwitchingService.class);
+ switchingService.updateRouterInterface(openstackRouterInterface);
+
+ log.debug("REST API AddRouterInterface is called from router {} portId: {}, subnetId: {}, tenantId: {}",
+ openstackRouterInterface.id(), openstackRouterInterface.portId(),
+ openstackRouterInterface.subnetId(), openstackRouterInterface.tenantId());
+
+ return Response.status(Response.Status.OK).build();
+ } catch (Exception e) {
+ log.error("AddRouterInterface failed because of exception {}",
+ e.toString());
+ return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(e.toString())
+ .build();
+ }
+ }
+
+ @DELETE
+ @Path("{id}")
+ public Response deleteRouter(@PathParam("id") String id) {
+ checkNotNull(id);
+ OpenstackSwitchingService switchingService =
+ getService(OpenstackSwitchingService.class);
+ switchingService.deleteRouter(id);
+
+ log.debug("REST API DELETE routers is called {}", id);
+ return Response.status(Response.Status.OK).build();
+ }
+
+ @PUT
+ @Path("{id}/remove_router_interface")
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response removeRouterInterface(@PathParam("id") String id, InputStream input) {
+ checkNotNull(id);
+ checkNotNull(input);
+ try {
+ ObjectMapper mapper = new ObjectMapper();
+ ObjectNode routerIfNode = (ObjectNode) mapper.readTree(input);
+
+ OpenstackRouterInterface openstackRouterInterface
+ = ROUTER_INTERFACE_CODEC.decode(routerIfNode, this);
+
+ OpenstackSwitchingService switchingService
+ = getService(OpenstackSwitchingService.class);
+ switchingService.removeRouterInterface(openstackRouterInterface);
+
+ log.debug("REST API RemoveRouterInterface is called from router {} portId: {}, subnetId: {}," +
+ "tenantId: {}", openstackRouterInterface.id(), openstackRouterInterface.portId(),
+ openstackRouterInterface.subnetId(), openstackRouterInterface.tenantId());
+
+ return Response.status(Response.Status.OK).build();
+ } catch (Exception e) {
+ log.error("RemoveRouterInterface failed because of exception {}",
+ e.toString());
+ return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(e.toString())
+ .build();
+ }
+ }
+}
diff --git a/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/web/OpenstackPortWebResource.java b/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/web/OpenstackPortWebResource.java
index 4e23753..206e4b1 100644
--- a/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/web/OpenstackPortWebResource.java
+++ b/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/web/OpenstackPortWebResource.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2015 Open Networking Laboratory
+ * Copyright 2015-2016 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.
diff --git a/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/web/OpenstackRouterCodec.java b/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/web/OpenstackRouterCodec.java
new file mode 100644
index 0000000..afcf560
--- /dev/null
+++ b/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/web/OpenstackRouterCodec.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2016 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.openstackswitching.web;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.google.common.collect.Maps;
+import org.onlab.packet.Ip4Address;
+import org.onosproject.codec.CodecContext;
+import org.onosproject.codec.JsonCodec;
+import org.onosproject.openstackrouting.OpenstackExternalGateway;
+import org.onosproject.openstackrouting.OpenstackRouter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.Map;
+/**
+ * Implementation of the OpenstackRouter Codec.
+ */
+public class OpenstackRouterCodec extends JsonCodec<OpenstackRouter> {
+ protected static final Logger log = LoggerFactory
+ .getLogger(OpenstackNetworkCodec.class);
+
+ private static final String ROUTER = "router";
+ private static final String TENANT_ID = "tenant_id";
+ private static final String NETWORK_ID = "network_id";
+ private static final String ID = "id";
+ private static final String NAME = "name";
+ private static final String STATUS = "status";
+ private static final String ADMIN_STATE_UP = "admin_state_up";
+ private static final String EXTERNAL_GW_INFO = "external_gateway_info";
+ private static final String EXTERNAL_FIXED_IPS = "external_fixed_ips";
+ private static final String SUBNET_ID = "subnet_id";
+ private static final String IP_ADDRESS = "ip_address";
+
+ /**
+ * Decodes the OpenstackRouter.
+ *
+ * @param json JSON to decode
+ * @param context decoding context
+ * @return OpenstackRouter
+ */
+ @Override
+ public OpenstackRouter decode(ObjectNode json, CodecContext context) {
+
+ if (json == null || !json.isObject()) {
+ return null;
+ }
+ JsonNode routerInfo = json.get(ROUTER);
+ if (routerInfo == null) {
+ routerInfo = json;
+ }
+
+ String tenantId = checkNotNull(routerInfo.path(TENANT_ID).asText());
+ String id = checkNotNull(routerInfo.path(ID).asText());
+ String name = checkNotNull(routerInfo.path(NAME).asText());
+ String status = checkNotNull(routerInfo.path(STATUS).asText());
+ String adminStateUp = checkNotNull(routerInfo.path(ADMIN_STATE_UP).asText());
+
+ OpenstackExternalGateway.Builder osExtBuiler = OpenstackExternalGateway.builder();
+
+ if (!routerInfo.path(EXTERNAL_GW_INFO).isMissingNode()) {
+ String externalGatewayNetId = checkNotNull(routerInfo.path(EXTERNAL_GW_INFO).path(NETWORK_ID).asText());
+ Map<String, Ip4Address> fixedIpMap = Maps.newHashMap();
+
+
+ if (!routerInfo.path(EXTERNAL_GW_INFO).path(EXTERNAL_FIXED_IPS).isMissingNode()) {
+ ArrayNode fixedIpList = (ArrayNode) routerInfo.path(EXTERNAL_GW_INFO).path(EXTERNAL_FIXED_IPS);
+
+ for (JsonNode fixedIpInfo : fixedIpList) {
+ String subnetId = checkNotNull(fixedIpInfo.path(SUBNET_ID).asText());
+ String ipAddressStr = checkNotNull(fixedIpInfo.path(IP_ADDRESS).asText());
+ if (!fixedIpInfo.path(IP_ADDRESS).isMissingNode() && ipAddressStr != null) {
+ fixedIpMap.put(subnetId, Ip4Address.valueOf(ipAddressStr));
+ }
+ }
+ }
+
+ osExtBuiler.networkId(externalGatewayNetId)
+ .enablePnat(true)
+ .externalFixedIps(fixedIpMap);
+ }
+ OpenstackRouter.Builder osBuilder = new OpenstackRouter.Builder()
+ .tenantId(tenantId)
+ .id(id)
+ .name(name)
+ .status(OpenstackRouter.RouterStatus.valueOf(status))
+ .adminStateUp(Boolean.valueOf(adminStateUp))
+ .gatewayExternalInfo(osExtBuiler.build());
+
+ return osBuilder.build();
+ }
+}
diff --git a/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/web/OpenstackRouterInterfaceCodec.java b/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/web/OpenstackRouterInterfaceCodec.java
new file mode 100644
index 0000000..88de443
--- /dev/null
+++ b/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/web/OpenstackRouterInterfaceCodec.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2016 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.openstackswitching.web;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.onosproject.codec.CodecContext;
+import org.onosproject.codec.JsonCodec;
+import org.onosproject.openstackrouting.OpenstackRouterInterface;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import static com.google.common.base.Preconditions.checkNotNull;
+/**
+ * Implementation of the OpenstackRouterInterface Codec.
+ */
+public class OpenstackRouterInterfaceCodec extends JsonCodec<OpenstackRouterInterface> {
+ protected static final Logger log = LoggerFactory
+ .getLogger(OpenstackNetworkCodec.class);
+
+ private static final String ID = "id";
+ private static final String TENANT_ID = "tenant_id";
+ private static final String SUBNET_ID = "subnet_id";
+ private static final String PORT_ID = "port_id";
+
+ /**
+ * Decodes the OpenstackRouterInterface.
+ *
+ * @param json JSON to decode
+ * @param context decoding context
+ * @return OpenstackRouterInterface
+ */
+ @Override
+ public OpenstackRouterInterface decode(ObjectNode json, CodecContext context) {
+ if (json == null || !json.isObject()) {
+ return null;
+ }
+ JsonNode routerIfInfo = json;
+
+ String id = checkNotNull(routerIfInfo.path(ID).asText());
+ String tenantId = checkNotNull(routerIfInfo.path(TENANT_ID).asText());
+ String subnetId = checkNotNull(routerIfInfo.path(SUBNET_ID).asText());
+ String portId = checkNotNull(routerIfInfo.path(PORT_ID).asText());
+
+ OpenstackRouterInterface.Builder osBuilder = new OpenstackRouterInterface.Builder()
+ .id(id)
+ .tenantId(tenantId)
+ .subnetId(subnetId)
+ .portId(portId);
+
+ return osBuilder.build();
+ }
+}