[ONOS-3953] Implements Security Group of Openstack
Change-Id: I30766097a2894a26e46a7a399176d99e95af6abf
diff --git a/apps/openstacknetworking/api/src/main/java/org/onosproject/openstacknetworking/OpenstackPortInfo.java b/apps/openstacknetworking/api/src/main/java/org/onosproject/openstacknetworking/OpenstackPortInfo.java
index 0099ea9..0ab8681 100644
--- a/apps/openstacknetworking/api/src/main/java/org/onosproject/openstacknetworking/OpenstackPortInfo.java
+++ b/apps/openstacknetworking/api/src/main/java/org/onosproject/openstacknetworking/OpenstackPortInfo.java
@@ -18,6 +18,10 @@
import org.onlab.packet.Ip4Address;
import org.onlab.packet.MacAddress;
import org.onosproject.net.DeviceId;
+
+import java.util.Collection;
+import java.util.Collections;
+
import static com.google.common.base.Preconditions.checkNotNull;
/**
@@ -29,70 +33,174 @@
private final DeviceId deviceId;
private final long vni;
private final Ip4Address gatewayIP;
+ private final Collection<String> securityGroups;
- public OpenstackPortInfo(Ip4Address hostIp, MacAddress hostMac, DeviceId deviceId, long vni, Ip4Address gatewayIP) {
+ /**
+ * Returns OpenstackPortInfo reference.
+ *
+ * @param hostIp host IP address
+ * @param hostMac host MAC address
+ * @param deviceId device ID
+ * @param vni tunnel ID
+ * @param gatewayIP gateway IP address
+ * @param securityGroups security group list
+ */
+ public OpenstackPortInfo(Ip4Address hostIp, MacAddress hostMac, DeviceId deviceId, long vni,
+ Ip4Address gatewayIP, Collection<String> securityGroups) {
this.hostIp = hostIp;
this.hostMac = hostMac;
this.deviceId = deviceId;
this.vni = vni;
this.gatewayIP = gatewayIP;
+ this.securityGroups = securityGroups;
}
+ /**
+ * Returns IP address of the port.
+ *
+ * @return IP address
+ */
public Ip4Address ip() {
return hostIp;
}
+ /**
+ * Returns MAC address of the port.
+ *
+ * @return MAC address
+ */
public MacAddress mac() {
return hostMac;
}
+ /**
+ * Returns device ID.
+ *
+ * @return device ID
+ */
public DeviceId deviceId() {
return deviceId;
}
+ /**
+ * Returns tunnel ID.
+ *
+ * @return tunnel ID
+ */
public long vni() {
return vni;
}
+ /**
+ * Returns gateway IP address.
+ *
+ * @return gateway IP address
+ */
public Ip4Address gatewayIP() {
return gatewayIP;
}
+ /**
+ * Returns Security Group ID list.
+ *
+ * @return list of Security Group ID
+ */
+ public Collection<String> securityGroups() {
+ return Collections.unmodifiableCollection(securityGroups);
+ }
+
+ /**
+ * Returns the builder of the OpenstackPortInfo.
+ *
+ * @return OpenstackPortInfo builder reference
+ */
public static OpenstackPortInfo.Builder builder() {
return new Builder();
}
+ /**
+ * Represents the OpenstackPortInfo Builder.
+ *
+ */
public static final class Builder {
private Ip4Address hostIp;
private MacAddress hostMac;
private DeviceId deviceId;
private long vni;
private Ip4Address gatewayIP;
+ private Collection<String> securityGroups;
+ /**
+ * Sets the IP address of the port.
+ *
+ * @param gatewayIP
+ * @return Builder reference
+ */
public Builder setGatewayIP(Ip4Address gatewayIP) {
this.gatewayIP = checkNotNull(gatewayIP, "gatewayIP cannot be null");
return this;
}
+ /**
+ * Sets the host IP address of the port.
+ *
+ * @param hostIp host IP address
+ * @return Builder reference
+ */
public Builder setHostIp(Ip4Address hostIp) {
this.hostIp = checkNotNull(hostIp, "hostIp cannot be null");
return this;
}
+ /**
+ * Sets the host MAC address of the port.
+ *
+ * @param hostMac host MAC address
+ * @return Builder reference
+ */
public Builder setHostMac(MacAddress hostMac) {
this.hostMac = checkNotNull(hostMac, "hostMac cannot be bull");
return this;
}
+ /**
+ * Sets the device ID.
+ *
+ * @param deviceId device ID
+ * @return Builder reference
+ */
public Builder setDeviceId(DeviceId deviceId) {
this.deviceId = checkNotNull(deviceId, "deviceId cannot be null");
return this;
}
+ /**
+ * Sets the tunnel ID.
+ *
+ * @param vni tunnel ID
+ * @return Builder reference
+ */
public Builder setVni(long vni) {
this.vni = checkNotNull(vni, "vni cannot be null");
return this;
}
+
+ /**
+ * Sets the security group ID list.
+ *
+ * @param securityGroups security group ID list
+ * @return Builder reference
+ */
+ public Builder setSecurityGroups(Collection<String> securityGroups) {
+ this.securityGroups = securityGroups;
+ return this;
+ }
+
+ /**
+ * Builds the OpenstackPortInfo reference.
+ *
+ * @return OpenstackPortInfo reference
+ */
public OpenstackPortInfo build() {
return new OpenstackPortInfo(this);
}
@@ -104,5 +212,6 @@
deviceId = builder.deviceId;
vni = builder.vni;
gatewayIP = builder.gatewayIP;
+ securityGroups = builder.securityGroups;
}
}
diff --git a/apps/openstacknetworking/openstackswitching/src/main/java/org/onosproject/openstacknetworking/switching/OpenstackSecurityGroupRulePopulator.java b/apps/openstacknetworking/openstackswitching/src/main/java/org/onosproject/openstacknetworking/switching/OpenstackSecurityGroupRulePopulator.java
new file mode 100644
index 0000000..b16a6bf
--- /dev/null
+++ b/apps/openstacknetworking/openstackswitching/src/main/java/org/onosproject/openstacknetworking/switching/OpenstackSecurityGroupRulePopulator.java
@@ -0,0 +1,274 @@
+/*
+* 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.openstacknetworking.switching;
+
+import org.onlab.packet.Ethernet;
+import org.onlab.packet.IPv4;
+import org.onlab.packet.Ip4Address;
+import org.onlab.packet.Ip4Prefix;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.IpPrefix;
+import org.onlab.packet.TpPort;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.flow.DefaultTrafficSelector;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.flowobjective.DefaultForwardingObjective;
+import org.onosproject.net.flowobjective.FlowObjectiveService;
+import org.onosproject.net.flowobjective.ForwardingObjective;
+import org.onosproject.openstackinterface.OpenstackInterfaceService;
+import org.onosproject.openstackinterface.OpenstackSecurityGroup;
+import org.onosproject.openstackinterface.OpenstackSecurityGroupRule;
+import org.onosproject.openstacknetworking.OpenstackPortInfo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Map;
+
+/**
+ * Populates flows rules for Security Groups of VMs.
+ *
+ */
+public class OpenstackSecurityGroupRulePopulator {
+
+ private static Logger log = LoggerFactory
+ .getLogger(OpenstackSecurityGroupRulePopulator.class);
+
+ private OpenstackInterfaceService openstackService;
+ private FlowObjectiveService flowObjectiveService;
+
+ private ApplicationId appId;
+
+ private static final String PROTO_ICMP = "ICMP";
+ private static final String PROTO_TCP = "TCP";
+ private static final String PROTO_UDP = "UDP";
+
+ private static final String ETHTYPE_IPV4 = "IPV4";
+
+ private static final IpPrefix IP_PREFIX_ANY = Ip4Prefix.valueOf("0.0.0.0/0");
+
+ private static final int ACL_RULE_PRIORITY = 30000;
+
+ /**
+ * Constructor.
+ *
+ * @param appId
+ * @param openstackService
+ * @param flowObjectiveService
+ */
+ public OpenstackSecurityGroupRulePopulator(ApplicationId appId, OpenstackInterfaceService openstackService,
+ FlowObjectiveService flowObjectiveService) {
+ this.appId = appId;
+ this.openstackService = openstackService;
+ this.flowObjectiveService = flowObjectiveService;
+ }
+
+ /**
+ * Populates flow rules for security groups.
+ *
+ * @param id Device ID
+ * @param sgId Security Group ID
+ * @param vmIp VM IP address
+ * @param portInfoMap Port Info map
+ */
+ public void populateSecurityGroupRules(DeviceId id, String sgId, Ip4Address vmIp,
+ Map<String, OpenstackPortInfo> portInfoMap) {
+ OpenstackSecurityGroup securityGroup = openstackService.getSecurityGroup(sgId);
+ if (securityGroup != null) {
+ securityGroup.rules().stream().forEach(sgRule -> {
+ if (sgRule.remoteGroupId() != null && !sgRule.remoteGroupId().equals("null")) {
+ openstackService.ports().stream()
+ .filter(port -> port.securityGroups().contains(sgRule.remoteGroupId()))
+ .flatMap(port -> port.fixedIps().values().stream())
+ .forEach(remoteIp -> setSecurityGroupRule(id, sgRule,
+ vmIp, IpPrefix.valueOf((IpAddress) remoteIp, 32)));
+ } else {
+ setSecurityGroupRule(id, sgRule, vmIp, sgRule.remoteIpPrefix());
+ }
+ });
+
+ openstackService.ports().stream().forEach(osPort ->
+ osPort.securityGroups().stream().forEach(remoteVmSgId -> {
+ OpenstackSecurityGroup remoteVmSg = openstackService.getSecurityGroup(remoteVmSgId);
+ remoteVmSg.rules().stream()
+ .filter(remoteVmSgRule -> remoteVmSgRule.remoteGroupId().equals(sgId))
+ .forEach(remoteVmSgRule -> {
+ Ip4Address remoteVmIp =
+ (Ip4Address) osPort.fixedIps().values().stream().findAny().orElse(null);
+ OpenstackPortInfo osPortInfo = portInfoMap.get(OpenstackSwitchingManager.PORTNAME_PREFIX_VM
+ + osPort.id().substring(0, 11));
+ if (osPortInfo != null && remoteVmIp != null) {
+ setSecurityGroupRule(osPortInfo.deviceId(), remoteVmSgRule, remoteVmIp,
+ IpPrefix.valueOf(vmIp, 32));
+ }
+ });
+ }));
+ }
+ }
+
+ /**
+ * Removes flow rules for security groups.
+ *
+ * @param id Device ID
+ * @param sgId Security Group ID to remove
+ * @param vmIp VM IP address
+ * @param portInfoMap port info map
+ * @param securityGroupMap security group info map
+ */
+ public void removeSecurityGroupRules(DeviceId id, String sgId, Ip4Address vmIp,
+ Map<String, OpenstackPortInfo> portInfoMap,
+ Map<String, OpenstackSecurityGroup> securityGroupMap) {
+ OpenstackSecurityGroup securityGroup = securityGroupMap.get(sgId);
+ if (securityGroup != null) {
+ securityGroup.rules().stream().forEach(sgRule -> {
+ if (sgRule.remoteGroupId() != null && !sgRule.remoteGroupId().equals("null")) {
+ portInfoMap.values().stream()
+ .filter(portInfo -> portInfo.securityGroups().contains(sgRule.remoteGroupId()))
+ .map(OpenstackPortInfo::ip)
+ .forEach(remoteIp -> {
+ removeSecurityGroupRule(id, sgRule, vmIp, IpPrefix.valueOf(remoteIp, 32));
+ });
+ } else {
+ removeSecurityGroupRule(id, sgRule, vmIp, sgRule.remoteIpPrefix());
+ }
+ });
+
+ portInfoMap.values().stream()
+ .forEach(portInfo -> portInfo.securityGroups()
+ .forEach(remoteVmSgId -> {
+ OpenstackSecurityGroup remoteVmSg = securityGroupMap.get(remoteVmSgId);
+ remoteVmSg.rules().stream()
+ .filter(remoteVmSgRule -> remoteVmSgRule.remoteGroupId().equals(sgId))
+ .forEach(remoteVmSgRule -> removeSecurityGroupRule(portInfo.deviceId(),
+ remoteVmSgRule, portInfo.ip(), IpPrefix.valueOf(vmIp, 32)));
+ }));
+ }
+ }
+
+ private void setSecurityGroupRule(DeviceId id, OpenstackSecurityGroupRule sgRule,
+ Ip4Address vmIp, IpPrefix remoteIp) {
+ ForwardingObjective.Builder foBuilder = buildFlowObjective(id, sgRule, vmIp, remoteIp);
+ if (foBuilder != null) {
+ flowObjectiveService.forward(id, foBuilder.add());
+ }
+ }
+
+ private void removeSecurityGroupRule(DeviceId id, OpenstackSecurityGroupRule sgRule,
+ Ip4Address vmIp, IpPrefix remoteIp) {
+ ForwardingObjective.Builder foBuilder = buildFlowObjective(id, sgRule, vmIp, remoteIp);
+ if (foBuilder != null) {
+ flowObjectiveService.forward(id, foBuilder.remove());
+ }
+ }
+
+ ForwardingObjective.Builder buildFlowObjective(DeviceId id, OpenstackSecurityGroupRule sgRule,
+ Ip4Address vmIp, IpPrefix remoteIp) {
+ if (remoteIp != null && remoteIp.equals(IpPrefix.valueOf(vmIp, 32))) {
+ return null;
+ }
+ TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
+ TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
+
+ buildMatchs(sBuilder, sgRule, vmIp, remoteIp);
+
+ ForwardingObjective.Builder foBuilder = DefaultForwardingObjective.builder()
+ .withSelector(sBuilder.build())
+ .withTreatment(tBuilder.build())
+ .withPriority(ACL_RULE_PRIORITY)
+ .withFlag(ForwardingObjective.Flag.SPECIFIC)
+ .fromApp(appId);
+
+ return foBuilder;
+ }
+
+ private void buildMatchs(TrafficSelector.Builder sBuilder, OpenstackSecurityGroupRule sgRule,
+ Ip4Address vmIp, IpPrefix remoteIp) {
+ buildMatchEthType(sBuilder, sgRule.ethertype());
+ buildMatchDirection(sBuilder, sgRule.direction(), vmIp);
+ buildMatchProto(sBuilder, sgRule.protocol());
+ buildMatchPort(sBuilder, sgRule.protocol(), sgRule.direction(), sgRule.portRangeMax(), sgRule.portRangeMin());
+ buildMatchRemoteIp(sBuilder, remoteIp, sgRule.direction());
+ }
+
+ private void buildMatchDirection(TrafficSelector.Builder sBuilder,
+ OpenstackSecurityGroupRule.Direction direction, Ip4Address vmIp) {
+ if (direction.equals(OpenstackSecurityGroupRule.Direction.EGRESS)) {
+ sBuilder.matchIPSrc(IpPrefix.valueOf(vmIp, 32));
+ } else {
+ sBuilder.matchIPDst(IpPrefix.valueOf(vmIp, 32));
+ }
+ }
+
+ private void buildMatchEthType(TrafficSelector.Builder sBuilder, String ethertype) {
+ // Either IpSrc or IpDst (or both) is set by default, and we need to set EthType as IPv4.
+ sBuilder.matchEthType(Ethernet.TYPE_IPV4);
+ if (ethertype != null && ethertype != "null" &&
+ !ethertype.toUpperCase().equals(ETHTYPE_IPV4)) {
+ log.error("EthType {} is not supported yet in Security Group", ethertype);
+ }
+ }
+
+ private void buildMatchRemoteIp(TrafficSelector.Builder sBuilder, IpPrefix remoteIpPrefix,
+ OpenstackSecurityGroupRule.Direction direction) {
+ if (remoteIpPrefix != null && !remoteIpPrefix.getIp4Prefix().equals(IP_PREFIX_ANY)) {
+ if (direction.equals(OpenstackSecurityGroupRule.Direction.EGRESS)) {
+ sBuilder.matchIPDst(remoteIpPrefix);
+ } else {
+ sBuilder.matchIPSrc(remoteIpPrefix);
+ }
+ }
+ }
+
+ private void buildMatchProto(TrafficSelector.Builder sBuilder, String protocol) {
+ if (protocol != null) {
+ switch (protocol.toUpperCase()) {
+ case PROTO_ICMP:
+ sBuilder.matchIPProtocol(IPv4.PROTOCOL_ICMP);
+ break;
+ case PROTO_TCP:
+ sBuilder.matchIPProtocol(IPv4.PROTOCOL_TCP);
+ break;
+ case PROTO_UDP:
+ sBuilder.matchIPProtocol(IPv4.PROTOCOL_UDP);
+ break;
+ default:
+ }
+ }
+ }
+
+ private void buildMatchPort(TrafficSelector.Builder sBuilder, String protocol,
+ OpenstackSecurityGroupRule.Direction direction,
+ int portMin, int portMax) {
+ if (portMin > 0 && portMax > 0 && portMin == portMax) {
+ if (protocol.toUpperCase().equals(PROTO_TCP)) {
+ if (direction.equals(OpenstackSecurityGroupRule.Direction.EGRESS)) {
+ sBuilder.matchTcpDst(TpPort.tpPort(portMax));
+ } else {
+ sBuilder.matchTcpSrc(TpPort.tpPort(portMax));
+ }
+ } else if (protocol.toUpperCase().equals(PROTO_UDP)) {
+ if (direction.equals(OpenstackSecurityGroupRule.Direction.EGRESS)) {
+ sBuilder.matchUdpDst(TpPort.tpPort(portMax));
+ } else {
+ sBuilder.matchUdpSrc(TpPort.tpPort(portMax));
+ }
+ }
+ }
+ }
+}
diff --git a/apps/openstacknetworking/openstackswitching/src/main/java/org/onosproject/openstacknetworking/switching/OpenstackSwitchingManager.java b/apps/openstacknetworking/openstackswitching/src/main/java/org/onosproject/openstacknetworking/switching/OpenstackSwitchingManager.java
index 4e66d95..2c88b3a 100644
--- a/apps/openstacknetworking/openstackswitching/src/main/java/org/onosproject/openstacknetworking/switching/OpenstackSwitchingManager.java
+++ b/apps/openstacknetworking/openstackswitching/src/main/java/org/onosproject/openstacknetworking/switching/OpenstackSwitchingManager.java
@@ -104,7 +104,9 @@
public static final String DEVICE_OWNER_GATEWAY = "network:router_gateway";
private ApplicationId appId;
- private OpenstackArpHandler arpHandler = new OpenstackArpHandler(openstackService, packetService, hostService);
+
+ private OpenstackArpHandler arpHandler;
+ private OpenstackSecurityGroupRulePopulator sgRulePopulator;
private ExecutorService deviceEventExcutorService =
Executors.newSingleThreadExecutor(groupedThreads("onos/openstackswitching", "device-event"));
@@ -114,6 +116,7 @@
private InternalHostListener internalHostListener = new InternalHostListener();
private Map<String, OpenstackPortInfo> openstackPortInfoMap = Maps.newHashMap();
+ private Map<String, OpenstackSecurityGroup> securityGroupMap = Maps.newConcurrentMap();
@Activate
protected void activate() {
@@ -124,6 +127,9 @@
deviceService.addListener(internalDeviceListener);
hostService.addListener(internalHostListener);
+ arpHandler = new OpenstackArpHandler(openstackService, packetService, hostService);
+ sgRulePopulator = new OpenstackSecurityGroupRulePopulator(appId, openstackService, flowObjectiveService);
+
initializeFlowRules();
log.info("Started");
@@ -148,13 +154,6 @@
registerDhcpInfo(openstackPort);
}
}
-
- if (!openstackPort.securityGroups().isEmpty()) {
- openstackPort.securityGroups().forEach(sgId -> {
- OpenstackSecurityGroup sg = openstackService.getSecurityGroup(sgId);
- log.debug("SecurityGroup : {}", sg.toString());
- });
- }
}
@Override
@@ -185,6 +184,22 @@
@Override
public void updatePort(OpenstackPort openstackPort) {
+ if (openstackPort.status().equals(OpenstackPort.PortStatus.ACTIVE)) {
+ String portName = PORTNAME_PREFIX_VM + openstackPort.id().substring(0, 11);
+ OpenstackPortInfo osPortInfo = openstackPortInfoMap.get(portName);
+ if (osPortInfo != null) {
+ // Remove all security group rules based on the ones stored in security group map.
+ osPortInfo.securityGroups().stream().forEach(
+ sgId -> sgRulePopulator.removeSecurityGroupRules(osPortInfo.deviceId(), sgId,
+ osPortInfo.ip(), openstackPortInfoMap, securityGroupMap));
+ // Add all security group rules based on the updated security group.
+ openstackPort.securityGroups().stream().forEach(
+ sgId -> sgRulePopulator.populateSecurityGroupRules(osPortInfo.deviceId(), sgId,
+ osPortInfo.ip(), openstackPortInfoMap));
+ updatePortMap(osPortInfo.deviceId(), portName, openstackService.networks(),
+ openstackService.subnets(), openstackPort);
+ }
+ }
}
@Override
@@ -205,26 +220,37 @@
}
private void processPortUpdated(Device device, Port port) {
- if (!port.annotations().value(PORTNAME).equals(PORTNAME_PREFIX_TUNNEL)) {
- if (port.isEnabled() || port.annotations().value(PORTNAME).startsWith(PORTNAME_PREFIX_ROUTER)) {
- OpenstackSwitchingRulePopulator rulePopulator =
- new OpenstackSwitchingRulePopulator(appId, flowObjectiveService,
- deviceService, openstackService, driverService);
+ String portName = port.annotations().value(PORTNAME);
+ synchronized (openstackPortInfoMap) {
+ if (portName.startsWith(PORTNAME_PREFIX_VM)) {
+ if (port.isEnabled()) {
+ OpenstackSwitchingRulePopulator rulePopulator =
+ new OpenstackSwitchingRulePopulator(appId, flowObjectiveService,
+ deviceService, openstackService, driverService);
- rulePopulator.populateSwitchingRules(device, port);
- updatePortMap(device.id(), port, openstackService.networks(), openstackService.subnets(),
- rulePopulator.openstackPort(port));
+ rulePopulator.populateSwitchingRules(device, port);
+ OpenstackPort openstackPort = rulePopulator.openstackPort(port);
+ Ip4Address vmIp = (Ip4Address) openstackPort.fixedIps().values().stream()
+ .findAny().orElseGet(null);
+ openstackPort.securityGroups().stream().forEach(
+ sgId -> sgRulePopulator.populateSecurityGroupRules(device.id(), sgId, vmIp,
+ openstackPortInfoMap));
+ updatePortMap(device.id(), port.annotations().value(PORTNAME),
+ openstackService.networks(), openstackService.subnets(), openstackPort);
- //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());
- OpenstackSwitchingRulePopulator rulePopulator =
- new OpenstackSwitchingRulePopulator(appId, flowObjectiveService,
- deviceService, openstackService, driverService);
-
- rulePopulator.removeSwitchingRules(port, openstackPortInfoMap);
- dhcpService.removeStaticMapping(openstackPortInfoMap.get(port.annotations().value(PORTNAME)).mac());
- openstackPortInfoMap.remove(port.annotations().value(PORTNAME));
+ //In case portupdate event is driven by vm shutoff from openstack
+ } else if (!port.isEnabled() && openstackPortInfoMap.containsKey(portName)) {
+ log.debug("Flowrules according to the port {} were removed", port.number().toString());
+ OpenstackSwitchingRulePopulator rulePopulator =
+ new OpenstackSwitchingRulePopulator(appId, flowObjectiveService,
+ deviceService, openstackService, driverService);
+ rulePopulator.removeSwitchingRules(port, openstackPortInfoMap);
+ openstackPortInfoMap.get(portName).securityGroups().stream().forEach(
+ sgId -> sgRulePopulator.removeSecurityGroupRules(device.id(), sgId,
+ openstackPortInfoMap.get(portName).ip(), openstackPortInfoMap, securityGroupMap));
+ dhcpService.removeStaticMapping(openstackPortInfoMap.get(port.annotations().value(PORTNAME)).mac());
+ openstackPortInfoMap.remove(port.annotations().value(PORTNAME));
+ }
}
}
}
@@ -242,27 +268,33 @@
Collection<OpenstackSubnet> subnets = openstackService.subnets();
deviceService.getDevices().forEach(device -> {
- log.debug("device {} num of ports {} ", device.id(),
- deviceService.getPorts(device.id()).size());
- deviceService.getPorts(device.id()).stream()
- .filter(port -> port.annotations().value(PORTNAME).startsWith(PORTNAME_PREFIX_VM) ||
- port.annotations().value(PORTNAME).startsWith(PORTNAME_PREFIX_ROUTER))
- .forEach(vmPort -> {
- OpenstackPort osPort = rulePopulator.openstackPort(vmPort);
- if (osPort != null && !osPort.deviceOwner().equals(DEVICE_OWNER_GATEWAY)) {
- rulePopulator.populateSwitchingRules(device, vmPort);
- updatePortMap(device.id(), vmPort, networks, subnets, osPort);
- registerDhcpInfo(osPort);
- } else {
- log.warn("No openstackPort information for port {}", vmPort);
- }
- }
- );
+ log.debug("device {} num of ports {} ", device.id(),
+ deviceService.getPorts(device.id()).size());
+ deviceService.getPorts(device.id()).stream()
+ .filter(port -> port.annotations().value(PORTNAME).startsWith(PORTNAME_PREFIX_VM) ||
+ port.annotations().value(PORTNAME).startsWith(PORTNAME_PREFIX_ROUTER))
+ .forEach(vmPort -> {
+ OpenstackPort osPort = rulePopulator.openstackPort(vmPort);
+ if (osPort != null && !osPort.deviceOwner().equals(DEVICE_OWNER_GATEWAY)) {
+ rulePopulator.populateSwitchingRules(device, vmPort);
+ Ip4Address vmIp = (Ip4Address) osPort.fixedIps().values().stream()
+ .findAny().orElseGet(null);
+ osPort.securityGroups().stream().forEach(
+ sgId -> sgRulePopulator.populateSecurityGroupRules(device.id(),
+ sgId, vmIp, openstackPortInfoMap));
+ updatePortMap(device.id(), vmPort.annotations().value(PORTNAME), networks,
+ subnets, osPort);
+ registerDhcpInfo(osPort);
+ } else {
+ log.warn("No openstackPort information for port {}", vmPort);
+ }
+ }
+ );
}
);
}
- private void updatePortMap(DeviceId deviceId, Port port, Collection<OpenstackNetwork> networks,
+ private void updatePortMap(DeviceId deviceId, String portName, Collection<OpenstackNetwork> networks,
Collection<OpenstackSubnet> subnets, OpenstackPort openstackPort) {
long vni = Long.parseLong(networks.stream()
.filter(n -> n.id().equals(openstackPort.networkId()))
@@ -279,10 +311,17 @@
.setHostIp((Ip4Address) openstackPort.fixedIps().values().stream().findFirst().orElse(null))
.setHostMac(openstackPort.macAddress())
.setVni(vni)
- .setGatewayIP(gatewayIPAddress);
+ .setGatewayIP(gatewayIPAddress)
+ .setSecurityGroups(openstackPort.securityGroups());
- openstackPortInfoMap.putIfAbsent(port.annotations().value(PORTNAME),
- portBuilder.build());
+ openstackPortInfoMap.put(portName, portBuilder.build());
+
+ openstackPort.securityGroups().stream().forEach(sgId -> {
+ if (!securityGroupMap.containsKey(sgId)) {
+ securityGroupMap.put(sgId, openstackService.getSecurityGroup(sgId));
+ }
+ });
+
}
private void processHostRemoved(Host host) {
diff --git a/apps/openstacknetworking/openstackswitching/src/main/java/org/onosproject/openstacknetworking/switching/OpenstackSwitchingRulePopulator.java b/apps/openstacknetworking/openstackswitching/src/main/java/org/onosproject/openstacknetworking/switching/OpenstackSwitchingRulePopulator.java
index 79ae523..9248d35 100644
--- a/apps/openstacknetworking/openstackswitching/src/main/java/org/onosproject/openstacknetworking/switching/OpenstackSwitchingRulePopulator.java
+++ b/apps/openstacknetworking/openstackswitching/src/main/java/org/onosproject/openstacknetworking/switching/OpenstackSwitchingRulePopulator.java
@@ -58,7 +58,6 @@
private static Logger log = LoggerFactory
.getLogger(OpenstackSwitchingRulePopulator.class);
private static final int SWITCHING_RULE_PRIORITY = 30000;
- private static final int EAST_WEST_ROUTING_RULE_PRIORITY = 29000;
private static final int TUNNELTAG_RULE_PRIORITY = 30000;
private FlowObjectiveService flowObjectiveService;
@@ -490,4 +489,5 @@
}
return port.number();
}
+
}
diff --git a/apps/openstacknetworking/web/src/main/java/org/onosproject/openstacknetworking/web/OpenstackPortWebResource.java b/apps/openstacknetworking/web/src/main/java/org/onosproject/openstacknetworking/web/OpenstackPortWebResource.java
index ce6fd7e..ce4fe52 100644
--- a/apps/openstacknetworking/web/src/main/java/org/onosproject/openstacknetworking/web/OpenstackPortWebResource.java
+++ b/apps/openstacknetworking/web/src/main/java/org/onosproject/openstacknetworking/web/OpenstackPortWebResource.java
@@ -84,6 +84,23 @@
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response updatePorts(InputStream input) {
- return Response.status(Response.Status.OK).build();
+ try {
+ ObjectMapper mapper = new ObjectMapper();
+ ObjectNode portNode = (ObjectNode) mapper.readTree(input);
+
+ OpenstackPort openstackPort = PORT_CODEC.decode(portNode, this);
+ OpenstackSwitchingService switchingService =
+ getService(OpenstackSwitchingService.class);
+ switchingService.updatePort(openstackPort);
+
+ log.debug("REST API update port is called with {}", portNode.toString());
+ return Response.status(Response.Status.OK).build();
+
+ } catch (Exception e) {
+ log.error("Update Port failed because of exception {}",
+ e.toString());
+ return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(e.toString())
+ .build();
+ }
}
}