package org.opendaylight.groupbasedpolicy.neutron.mapper.mapping;
+import static com.google.common.base.Preconditions.checkNotNull;
+
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.groupbasedpolicy.neutron.mapper.util.IidFactory;
+import org.opendaylight.groupbasedpolicy.neutron.mapper.util.Utils;
+import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
import org.opendaylight.neutron.spi.INeutronFloatingIPAware;
+import org.opendaylight.neutron.spi.INeutronPortCRUD;
+import org.opendaylight.neutron.spi.NeutronCRUDInterfaces;
import org.opendaylight.neutron.spi.NeutronFloatingIP;
+import org.opendaylight.neutron.spi.NeutronPort;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.UniqueId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.EndpointService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.floating.ip.association.mappings.floating.ip.ports.by.internal.ports.FloatingIpPortByInternalPortBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.floating.ip.association.mappings.internal.ports.by.floating.ip.ports.InternalPortByFloatingIpPort;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.floating.ip.association.mappings.internal.ports.by.floating.ip.ports.InternalPortByFloatingIpPortBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.google.common.base.Preconditions;
-
+import com.google.common.base.Strings;
public class NeutronFloatingIpAware implements INeutronFloatingIPAware {
public static final Logger LOG = LoggerFactory.getLogger(NeutronFloatingIpAware.class);
private final DataBroker dataProvider;
+ private final EndpointService epService;
- public NeutronFloatingIpAware(DataBroker dataProvider) {
- this.dataProvider = Preconditions.checkNotNull(dataProvider);
+ public NeutronFloatingIpAware(DataBroker dataProvider, EndpointService epService) {
+ this.dataProvider = checkNotNull(dataProvider);
+ this.epService = checkNotNull(epService);
}
@Override
@Override
public int canUpdateFloatingIP(NeutronFloatingIP delta, NeutronFloatingIP original) {
LOG.trace("canUpdateFloatingIP - delta: {} original: {}", delta, original);
+ // floating IP UUID is same as device ID of a port representing floating IP
+ UniqueId floatingIpPortId = NeutronPortAware.getFloatingIpPortIdByDeviceId(original.getFloatingIPUUID());
+ if (floatingIpPortId == null) {
+ LOG.warn("Illegal state - Port representing floating ip where floating IP uuid is {} does not exist.",
+ original.getFloatingIPUUID());
+ return StatusCode.INTERNAL_SERVER_ERROR;
+ }
+
+ ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
+ String oldFixedIPAddress = Strings.nullToEmpty(original.getFixedIPAddress());
+ String oldPortUUID = Strings.nullToEmpty(original.getPortUUID());
+ String newFixedIPAddress = Strings.nullToEmpty(delta.getFixedIPAddress());
+ String newPortUUID = Strings.nullToEmpty(delta.getPortUUID());
+ if (oldFixedIPAddress.equals(newFixedIPAddress) && oldPortUUID.equals(newPortUUID)) {
+ // interesting fields were not changed
+ return StatusCode.OK;
+ }
+
+ if ((!oldFixedIPAddress.isEmpty() && newFixedIPAddress.isEmpty())
+ || (!oldPortUUID.isEmpty() && newPortUUID.isEmpty())) {
+ DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
+ IidFactory.internalPortByFloatingIpPortIid(floatingIpPortId), rwTx);
+ DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
+ IidFactory.floatingIpPortByInternalPortIid(new UniqueId(oldPortUUID)), rwTx);
+ // TODO unregister EP representing floating ip port
+ } else if (!newFixedIPAddress.isEmpty() && !newPortUUID.isEmpty()) {
+ // workaround for https://bugs.opendaylight.org/show_bug.cgi?id=3368
+ // otherwise we will create port representing floating IP in NeutronPortAware
+ Integer errorCode = registerFloatingIpPort(original.getTenantUUID(), floatingIpPortId.getValue(), rwTx);
+ if (errorCode != null) {
+ rwTx.cancel();
+ return errorCode;
+ }
+
+ UniqueId internalPortId = new UniqueId(newPortUUID);
+ InternalPortByFloatingIpPort internalPortByFloatingIpPort = new InternalPortByFloatingIpPortBuilder().setFloatingIpPortId(
+ floatingIpPortId)
+ .setFloatingIpPortIpAddress(Utils.createIpAddress(original.getFloatingIPAddress()))
+ .setInternalPortId(internalPortId)
+ .setInternalPortIpAddress(Utils.createIpAddress(newFixedIPAddress))
+ .build();
+ rwTx.put(LogicalDatastoreType.OPERATIONAL, IidFactory.internalPortByFloatingIpPortIid(floatingIpPortId),
+ internalPortByFloatingIpPort, true);
+ rwTx.put(LogicalDatastoreType.OPERATIONAL, IidFactory.floatingIpPortByInternalPortIid(internalPortId),
+ new FloatingIpPortByInternalPortBuilder(internalPortByFloatingIpPort).build(), true);
+ }
+ boolean isSubmitToDsSuccessful = DataStoreHelper.submitToDs(rwTx);
+ if (!isSubmitToDsSuccessful) {
+ return StatusCode.INTERNAL_SERVER_ERROR;
+ }
+
return StatusCode.OK;
}
+ private Integer registerFloatingIpPort(String tenantUUID, String floatingIpPortUUID, ReadWriteTransaction rwTx) {
+ INeutronPortCRUD portInterface = NeutronCRUDInterfaces.getINeutronPortCRUD(this);
+ if (portInterface == null) {
+ LOG.warn("Illegal state - No provider for {}", INeutronPortCRUD.class.getName());
+ return StatusCode.INTERNAL_SERVER_ERROR;
+ }
+ NeutronPort floatingIpPort = portInterface.getPort(floatingIpPortUUID);
+ // TenantId tenantId = new TenantId(Utils.normalizeUuid());
+ floatingIpPort.setTenantID(tenantUUID);
+ boolean isNeutronPortCreated = NeutronPortAware.addNeutronPort(floatingIpPort, rwTx, epService);
+ if (!isNeutronPortCreated) {
+ rwTx.cancel();
+ return StatusCode.INTERNAL_SERVER_ERROR;
+ }
+ return null;
+ }
+
@Override
public void neutronFloatingIPUpdated(NeutronFloatingIP floatingIP) {
LOG.trace("neutronFloatingIPUpdated - {}", floatingIP);
import java.util.ArrayList;
import java.util.Collection;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoint.l3.prefix.fields.EndpointL3GatewaysBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3Key;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3PrefixKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.unregister.endpoint.input.L2;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.unregister.endpoint.input.L2Builder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.unregister.endpoint.input.L3;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.unregister.endpoint.input.L3Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.gbp.by.neutron.mappings.endpoints.by.floating.ip.ports.EndpointByFloatingIpPort;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.gbp.by.neutron.mappings.endpoints.by.ports.EndpointByPort;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.gbp.by.neutron.mappings.endpoints.by.router._interface.ports.EndpointByRouterInterfacePort;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.gbp.by.neutron.mappings.endpoints.by.router.gateway.ports.EndpointByRouterGatewayPort;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.neutron.by.gbp.mappings.floating.ip.ports.by.endpoints.FloatingIpPortByEndpoint;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.neutron.by.gbp.mappings.ports.by.endpoints.PortByEndpoint;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.neutron.by.gbp.mappings.router._interface.ports.by.endpoints.RouterInterfacePortByEndpoint;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.neutron.by.gbp.mappings.router.gateway.ports.by.endpoints.RouterGatewayPortByEndpoint;
private static final int DHCP_SERVER_PORT = 67;
private final DataBroker dataProvider;
private final EndpointService epService;
+ private final static Map<String, UniqueId> floatingIpPortByDeviceId = new HashMap<>();
public NeutronPortAware(DataBroker dataProvider, EndpointService epService) {
this.dataProvider = checkNotNull(dataProvider);
NeutronPortAware.class.getSimpleName(), NeutronRouterAware.class.getSimpleName());
return;
}
- if (isFloatingIp(port)) {
- LOG.trace("Port is floating ip - {}", port.getID());
+ if (isFloatingIpPort(port)) {
+ LOG.trace("Port is floating ip - {} device id - {}", port.getID(), port.getDeviceID());
+ floatingIpPortByDeviceId.put(port.getDeviceID(), new UniqueId(port.getID()));
return;
}
ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
}
private static void addNeutronGbpMapping(NeutronPort port, EndpointKey epKey, ReadWriteTransaction rwTx) {
+ UniqueId portId = new UniqueId(port.getID());
if (isRouterInterfacePort(port)) {
LOG.trace("Adding RouterInterfacePort-Endpoint mapping for port {} and endpoint {}", port.getID(), epKey);
- UniqueId portId = new UniqueId(port.getID());
EndpointByRouterInterfacePort endpointByPort = MappingFactory.createEndpointByRouterInterfacePort(epKey,
portId);
rwTx.put(LogicalDatastoreType.OPERATIONAL, IidFactory.endpointByRouterInterfacePortIid(portId),
portByEndpoint, true);
} else if (isRouterGatewayPort(port)) {
LOG.trace("Adding RouterGatewayPort-Endpoint mapping for port {} and endpoint {}", port.getID(), epKey);
- UniqueId portId = new UniqueId(port.getID());
EndpointByRouterGatewayPort endpointByPort = MappingFactory.createEndpointByRouterGatewayPort(epKey, portId);
rwTx.put(LogicalDatastoreType.OPERATIONAL, IidFactory.endpointByRouterGatewayPortIid(portId),
endpointByPort, true);
rwTx.put(LogicalDatastoreType.OPERATIONAL,
IidFactory.routerGatewayPortByEndpointIid(epKey.getL2Context(), epKey.getMacAddress()),
portByEndpoint, true);
+ } else if (isFloatingIpPort(port)) {
+ LOG.trace("Adding FloatingIpPort-Endpoint mapping for port {} and endpoint {}", port.getID(), epKey);
+ EndpointByFloatingIpPort endpointByPort = MappingFactory.createEndpointByFloatingIpPort(epKey, portId);
+ rwTx.put(LogicalDatastoreType.OPERATIONAL, IidFactory.endpointByFloatingIpPortIid(portId),
+ endpointByPort, true);
+ FloatingIpPortByEndpoint portByEndpoint = MappingFactory.createFloatingIpPortByEndpoint(portId, epKey);
+ rwTx.put(LogicalDatastoreType.OPERATIONAL,
+ IidFactory.floatingIpPortByEndpointIid(epKey.getL2Context(), epKey.getMacAddress()),
+ portByEndpoint, true);
} else {
LOG.trace("Adding Port-Endpoint mapping for port {} (device owner {}) and endpoint {}", port.getID(),
port.getDeviceOwner(), epKey);
- UniqueId portId = new UniqueId(port.getID());
EndpointByPort endpointByPort = MappingFactory.createEndpointByPort(epKey, portId);
rwTx.put(LogicalDatastoreType.OPERATIONAL, IidFactory.endpointByPortIid(portId), endpointByPort, true);
PortByEndpoint portByEndpoint = MappingFactory.createPortByEndpoint(portId, epKey);
LOG.trace("Port is router gateway - {}", port.getID());
return;
}
- if (isFloatingIp(port)) {
+ if (isFloatingIpPort(port)) {
LOG.trace("Port is floating ip - {}", port.getID());
return;
}
NeutronPortAware.class.getSimpleName(), NeutronRouterAware.class.getSimpleName());
return;
}
- ReadOnlyTransaction rTx = dataProvider.newReadOnlyTransaction();
+ if (isRouterGatewayPort(port)) {
+ LOG.trace("Port is router gateway - {} does nothing. {} handles router iface.",
+ NeutronPortAware.class.getSimpleName(), NeutronRouterAware.class.getSimpleName());
+ return;
+ }
+ if (isFloatingIpPort(port)) {
+ LOG.trace("Port is floating ip - {} device id - {}", port.getID(), port.getDeviceID());
+ floatingIpPortByDeviceId.remove(port.getDeviceID());
+ }
+ ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
TenantId tenantId = new TenantId(Utils.normalizeUuid(port.getTenantID()));
L2FloodDomainId l2FdId = new L2FloodDomainId(port.getNetworkUUID());
- ForwardingCtx fwCtx = MappingUtils.createForwardingContext(tenantId, l2FdId, rTx);
+ ForwardingCtx fwCtx = MappingUtils.createForwardingContext(tenantId, l2FdId, rwTx);
boolean isFwCtxValid = validateForwardingCtx(fwCtx);
if (!isFwCtxValid) {
- rTx.close();
+ rwTx.cancel();
return;
}
+ EndpointKey epKey = new EndpointKey(fwCtx.getL2BridgeDomain().getId(), new MacAddress(port.getMacAddress()));
+ deleteNeutronGbpMapping(port, epKey, rwTx);
UnregisterEndpointInput unregisterEpRpcInput = createUnregisterEndpointInput(port, fwCtx);
try {
RpcResult<Void> rpcResult = epService.unregisterEndpoint(unregisterEpRpcInput).get();
}
} catch (InterruptedException | ExecutionException e) {
LOG.error("addPort - RPC invocation failed.", e);
- } finally {
- rTx.close();
+ rwTx.cancel();
+ }
+ }
+
+ private static void deleteNeutronGbpMapping(NeutronPort port, EndpointKey epKey, ReadWriteTransaction rwTx) {
+ UniqueId portId = new UniqueId(port.getID());
+ if (isRouterInterfacePort(port)) {
+ LOG.trace("Adding RouterInterfacePort-Endpoint mapping for port {} and endpoint {}", port.getID(), epKey);
+ DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
+ IidFactory.endpointByRouterInterfacePortIid(portId), rwTx);
+ DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
+ IidFactory.routerInterfacePortByEndpointIid(epKey.getL2Context(), epKey.getMacAddress()), rwTx);
+ } else if (isRouterGatewayPort(port)) {
+ LOG.trace("Adding RouterGatewayPort-Endpoint mapping for port {} and endpoint {}", port.getID(), epKey);
+ DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
+ IidFactory.endpointByRouterGatewayPortIid(portId), rwTx);
+ DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
+ IidFactory.routerGatewayPortByEndpointIid(epKey.getL2Context(), epKey.getMacAddress()), rwTx);
+ } else if (isFloatingIpPort(port)) {
+ LOG.trace("Adding FloatingIpPort-Endpoint mapping for port {} and endpoint {}", port.getID(), epKey);
+ DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
+ IidFactory.endpointByFloatingIpPortIid(portId), rwTx);
+ DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
+ IidFactory.floatingIpPortByEndpointIid(epKey.getL2Context(), epKey.getMacAddress()), rwTx);
+ } else {
+ LOG.trace("Adding Port-Endpoint mapping for port {} (device owner {}) and endpoint {}", port.getID(),
+ port.getDeviceOwner(), epKey);
+ DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL, IidFactory.endpointByPortIid(portId), rwTx);
+ DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
+ IidFactory.portByEndpointIid(epKey.getL2Context(), epKey.getMacAddress()), rwTx);
}
}
return DEVICE_OWNER_ROUTER_GATEWAY.equals(port.getDeviceOwner());
}
- private static boolean isFloatingIp(NeutronPort port) {
+ private static boolean isFloatingIpPort(NeutronPort port) {
return DEVICE_OWNER_FLOATING_IP.equals(port.getDeviceOwner());
}
return l3s;
}
-
+ public static UniqueId getFloatingIpPortIdByDeviceId(String deviceId) {
+ return floatingIpPortByDeviceId.get(deviceId);
+ }
}