Java tutorial
/* * Copyright 2014 Midokura SARL * * 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.midonet.cluster; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Queue; import java.util.Set; import java.util.UUID; import java.util.concurrent.ConcurrentLinkedQueue; import javax.annotation.CheckForNull; import javax.annotation.Nonnull; import javax.annotation.Nullable; import javax.inject.Inject; import javax.inject.Named; import com.google.common.base.Strings; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.tuple.MutablePair; import org.apache.commons.lang3.tuple.Pair; import org.apache.zookeeper.CreateMode; import org.apache.zookeeper.Op; import org.apache.zookeeper.Watcher; import org.apache.zookeeper.ZooDefs; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.midonet.cluster.data.AdRoute; import org.midonet.cluster.data.BGP; import org.midonet.cluster.data.Bridge; import org.midonet.cluster.data.Chain; import org.midonet.cluster.data.Converter; import org.midonet.cluster.data.HostVersion; import org.midonet.cluster.data.IpAddrGroup; import org.midonet.cluster.data.Port; import org.midonet.cluster.data.PortGroup; import org.midonet.cluster.data.Route; import org.midonet.cluster.data.Router; import org.midonet.cluster.data.Rule; import org.midonet.cluster.data.SystemState; import org.midonet.cluster.data.TunnelZone; import org.midonet.cluster.data.VTEP; import org.midonet.cluster.data.VtepBinding; import org.midonet.cluster.data.WriteVersion; import org.midonet.cluster.data.dhcp.Subnet; import org.midonet.cluster.data.dhcp.Subnet6; import org.midonet.cluster.data.dhcp.V6Host; import org.midonet.cluster.data.host.Host; import org.midonet.cluster.data.host.Interface; import org.midonet.cluster.data.host.VirtualPortMapping; import org.midonet.cluster.data.l4lb.HealthMonitor; import org.midonet.cluster.data.l4lb.LoadBalancer; import org.midonet.cluster.data.l4lb.Pool; import org.midonet.cluster.data.l4lb.PoolMember; import org.midonet.cluster.data.l4lb.VIP; import org.midonet.cluster.data.ports.BridgePort; import org.midonet.cluster.data.ports.VlanMacPort; import org.midonet.cluster.data.ports.VxLanPort; import org.midonet.midolman.SystemDataProvider; import org.midonet.midolman.guice.zookeeper.ZKConnectionProvider; import org.midonet.midolman.host.state.HostDirectory; import org.midonet.midolman.host.state.HostZkManager; import org.midonet.midolman.rules.RuleList; import org.midonet.midolman.serialization.SerializationException; import org.midonet.midolman.serialization.Serializer; import org.midonet.midolman.state.Directory; import org.midonet.midolman.state.DirectoryCallback; import org.midonet.midolman.state.InvalidStateOperationException; import org.midonet.midolman.state.Ip4ToMacReplicatedMap; import org.midonet.midolman.state.MacPortMap; import org.midonet.midolman.state.NoStatePathException; import org.midonet.midolman.state.PathBuilder; import org.midonet.midolman.state.PoolHealthMonitorMappingStatus; import org.midonet.midolman.state.PortConfig; import org.midonet.midolman.state.PortConfigCache; import org.midonet.midolman.state.PortDirectory; import org.midonet.midolman.state.PortDirectory.VxLanPortConfig; import org.midonet.midolman.state.StateAccessException; import org.midonet.midolman.state.ZkLeaderElectionWatcher; import org.midonet.midolman.state.ZkManager; import org.midonet.midolman.state.ZkUtil; import org.midonet.midolman.state.ZookeeperConnectionWatcher; import org.midonet.midolman.state.l4lb.LBStatus; import org.midonet.midolman.state.l4lb.MappingStatusException; import org.midonet.midolman.state.l4lb.MappingViolationException; import org.midonet.midolman.state.zkManagers.AdRouteZkManager; import org.midonet.midolman.state.zkManagers.BgpZkManager; import org.midonet.midolman.state.zkManagers.BridgeDhcpV6ZkManager; import org.midonet.midolman.state.zkManagers.BridgeDhcpZkManager; import org.midonet.midolman.state.zkManagers.BridgeZkManager; import org.midonet.midolman.state.zkManagers.BridgeZkManager.BridgeConfig; import org.midonet.midolman.state.zkManagers.ChainZkManager; import org.midonet.midolman.state.zkManagers.ConfigGetter; import org.midonet.midolman.state.zkManagers.HealthMonitorZkManager; import org.midonet.midolman.state.zkManagers.IpAddrGroupZkManager; import org.midonet.midolman.state.zkManagers.LoadBalancerZkManager; import org.midonet.midolman.state.zkManagers.PoolHealthMonitorZkManager.PoolHealthMonitorConfig; import org.midonet.midolman.state.zkManagers.PoolHealthMonitorZkManager.PoolHealthMonitorConfig.HealthMonitorConfigWithId; import org.midonet.midolman.state.zkManagers.PoolHealthMonitorZkManager.PoolHealthMonitorConfig.LoadBalancerConfigWithId; import org.midonet.midolman.state.zkManagers.PoolHealthMonitorZkManager.PoolHealthMonitorConfig.PoolMemberConfigWithId; import org.midonet.midolman.state.zkManagers.PoolHealthMonitorZkManager.PoolHealthMonitorConfig.VipConfigWithId; import org.midonet.midolman.state.zkManagers.PoolMemberZkManager; import org.midonet.midolman.state.zkManagers.PoolZkManager; import org.midonet.midolman.state.zkManagers.PortGroupZkManager; import org.midonet.midolman.state.zkManagers.PortZkManager; import org.midonet.midolman.state.zkManagers.RouteZkManager; import org.midonet.midolman.state.zkManagers.RouterZkManager; import org.midonet.midolman.state.zkManagers.RuleZkManager; import org.midonet.midolman.state.zkManagers.TenantZkManager; import org.midonet.midolman.state.zkManagers.TunnelZoneZkManager; import org.midonet.midolman.state.zkManagers.VipZkManager; import org.midonet.midolman.state.zkManagers.VtepZkManager; import org.midonet.packets.IPv4Addr; import org.midonet.packets.IPv4Subnet; import org.midonet.packets.IPv6Subnet; import org.midonet.packets.MAC; import org.midonet.util.eventloop.Reactor; import org.midonet.util.functors.Callback2; import org.midonet.util.functors.CollectionFunctors; import org.midonet.util.functors.Functor; import static com.google.common.base.Preconditions.checkNotNull; import static org.midonet.cluster.data.Rule.RuleIndexOutOfBoundsException; @SuppressWarnings("unused") public class LocalDataClientImpl implements DataClient { @Inject private TenantZkManager tenantZkManager; @Inject private BridgeDhcpZkManager dhcpZkManager; @Inject private BridgeDhcpV6ZkManager dhcpV6ZkManager; @Inject private BgpZkManager bgpZkManager; @Inject private AdRouteZkManager adRouteZkManager; @Inject private BridgeZkManager bridgeZkManager; @Inject private ChainZkManager chainZkManager; @Inject private RouteZkManager routeZkManager; @Inject private RouterZkManager routerZkManager; @Inject private RuleZkManager ruleZkManager; @Inject private PortZkManager portZkManager; @Inject private PortConfigCache portCache; @Inject private RouteZkManager routeMgr; @Inject private PortGroupZkManager portGroupZkManager; @Inject private HostZkManager hostZkManager; @Inject private LoadBalancerZkManager loadBalancerZkManager; @Inject private HealthMonitorZkManager healthMonitorZkManager; @Inject private PoolMemberZkManager poolMemberZkManager; @Inject private PoolZkManager poolZkManager; @Inject private VipZkManager vipZkManager; @Inject private TunnelZoneZkManager zonesZkManager; @Inject private ZkManager zkManager; @Inject private PathBuilder pathBuilder; @Inject private ClusterRouterManager routerManager; @Inject private ClusterBridgeManager bridgeManager; @Inject private Serializer serializer; @Inject private SystemDataProvider systemDataProvider; @Inject private IpAddrGroupZkManager ipAddrGroupZkManager; @Inject private VtepZkManager vtepZkManager; @Inject @Named(ZKConnectionProvider.DIRECTORY_REACTOR_TAG) private Reactor reactor; final Queue<Callback2<UUID, Boolean>> subscriptionPortsActive = new ConcurrentLinkedQueue<>(); private final static Logger log = LoggerFactory.getLogger(LocalDataClientImpl.class); @Override public @CheckForNull AdRoute adRoutesGet(UUID id) throws StateAccessException, SerializationException { log.debug("Entered: id={}", id); AdRoute adRoute = null; if (adRouteZkManager.exists(id)) { adRoute = Converter.fromAdRouteConfig(adRouteZkManager.get(id)); adRoute.setId(id); } log.debug("Exiting: adRoute={}", adRoute); return adRoute; } @Override public void adRoutesDelete(UUID id) throws StateAccessException, SerializationException { adRouteZkManager.delete(id); } @Override public UUID adRoutesCreate(@Nonnull AdRoute adRoute) throws StateAccessException, SerializationException { return adRouteZkManager.create(Converter.toAdRouteConfig(adRoute)); } @Override public List<AdRoute> adRoutesFindByBgp(@Nonnull UUID bgpId) throws StateAccessException, SerializationException { List<UUID> adRouteIds = adRouteZkManager.list(bgpId); List<AdRoute> adRoutes = new ArrayList<>(); for (UUID adRouteId : adRouteIds) { adRoutes.add(adRoutesGet(adRouteId)); } return adRoutes; } @Override public @CheckForNull BGP bgpGet(@Nonnull UUID id) throws StateAccessException, SerializationException { return new BGP(id, bgpZkManager.get(id)); } @Override public void bgpDelete(UUID id) throws StateAccessException, SerializationException { bgpZkManager.delete(id); } @Override public UUID bgpCreate(@Nonnull BGP bgp) throws StateAccessException, SerializationException { return bgpZkManager.create(bgp); } @Override public List<BGP> bgpFindByPort(UUID portId) throws StateAccessException, SerializationException { List<UUID> bgpIds = bgpZkManager.list(portId); List<BGP> bgps = new ArrayList<>(); for (UUID bgpId : bgpIds) { bgps.add(bgpGet(bgpId)); } return bgps; } public List<Bridge> bridgesFindByTenant(String tenantId) throws StateAccessException, SerializationException { log.debug("bridgesFindByTenant entered: tenantId={}", tenantId); List<Bridge> bridges = bridgesGetAll(); for (Iterator<Bridge> it = bridges.iterator(); it.hasNext();) { if (!it.next().hasTenantId(tenantId)) { it.remove(); } } log.debug("bridgesFindByTenant exiting: {} bridges found", bridges.size()); return bridges; } /** * Returns a list of all MAC-port mappings for the specified bridge. * @throws StateAccessException */ @Override public List<VlanMacPort> bridgeGetMacPorts(@Nonnull UUID bridgeId) throws StateAccessException { // Get entries for the untagged VLAN. List<VlanMacPort> allPorts = new LinkedList<>(); allPorts.addAll(bridgeGetMacPorts(bridgeId, Bridge.UNTAGGED_VLAN_ID)); // Get entries for the other VLANs. short[] vlanIds = bridgeZkManager.getVlanIds(bridgeId); for (short vlanId : vlanIds) allPorts.addAll(bridgeGetMacPorts(bridgeId, vlanId)); return allPorts; } /** * Gets MAC-port mappings for the specified bridge and VLAN. * @param bridgeId Bridge whose MAC-port mappings are requested. * @param vlanId VLAN whose MAC-port mappings are requested. The value * Bridge.UNTAGGED_VLAN_ID indicates the untagged VLAN. * @return List of MAC-port mappings. * @throws StateAccessException */ @Override public List<VlanMacPort> bridgeGetMacPorts(@Nonnull UUID bridgeId, short vlanId) throws StateAccessException { Map<MAC, UUID> portsMap = MacPortMap.getAsMap(bridgeZkManager.getMacPortMapDirectory(bridgeId, vlanId)); List<VlanMacPort> ports = new ArrayList<>(portsMap.size()); for (Map.Entry<MAC, UUID> e : portsMap.entrySet()) { ports.add(new VlanMacPort(e.getKey(), e.getValue(), vlanId)); } return ports; } @Override public void ensureBridgeHasVlanDirectory(@Nonnull UUID bridgeId) throws StateAccessException { bridgeZkManager.ensureBridgeHasVlanDirectory(bridgeId); } @Override public boolean bridgeHasMacTable(@Nonnull UUID bridgeId, short vlanId) throws StateAccessException { return bridgeZkManager.hasVlanMacTable(bridgeId, vlanId); } @Override public MacPortMap bridgeGetMacTable(@Nonnull UUID bridgeId, short vlanId, boolean ephemeral) throws StateAccessException { return new MacPortMap(bridgeZkManager.getMacPortMapDirectory(bridgeId, vlanId), ephemeral); } @Override public void bridgeAddMacPort(@Nonnull UUID bridgeId, short vlanId, @Nonnull MAC mac, @Nonnull UUID portId) throws StateAccessException { MacPortMap.addPersistentEntry(bridgeZkManager.getMacPortMapDirectory(bridgeId, vlanId), mac, portId); } @Override public boolean bridgeHasMacPort(@Nonnull UUID bridgeId, Short vlanId, @Nonnull MAC mac, @Nonnull UUID portId) throws StateAccessException { return MacPortMap.hasPersistentEntry(bridgeZkManager.getMacPortMapDirectory(bridgeId, vlanId), mac, portId); } @Override public void bridgeDeleteMacPort(@Nonnull UUID bridgeId, Short vlanId, @Nonnull MAC mac, @Nonnull UUID portId) throws StateAccessException { MacPortMap.deleteEntry(bridgeZkManager.getMacPortMapDirectory(bridgeId, vlanId), mac, portId); } @Override public Ip4ToMacReplicatedMap bridgeGetArpTable(@Nonnull UUID bridgeId) throws StateAccessException { return new Ip4ToMacReplicatedMap(bridgeZkManager.getIP4MacMapDirectory(bridgeId)); } @Override public Map<IPv4Addr, MAC> bridgeGetIP4MacPairs(@Nonnull UUID bridgeId) throws StateAccessException { return Ip4ToMacReplicatedMap.getAsMap(bridgeZkManager.getIP4MacMapDirectory(bridgeId)); } @Override public void bridgeAddIp4Mac(@Nonnull UUID bridgeId, @Nonnull IPv4Addr ip4, @Nonnull MAC mac) throws StateAccessException { // TODO: potential race conditions // The following code fixes the unobvious behavior of // replicated maps, but is still subject to potential race conditions // See MN-2637 Directory dir = bridgeZkManager.getIP4MacMapDirectory(bridgeId); if (Ip4ToMacReplicatedMap.hasPersistentEntry(dir, ip4, mac)) { return; } MAC oldMac = Ip4ToMacReplicatedMap.getEntry(dir, ip4); if (oldMac != null) { Ip4ToMacReplicatedMap.deleteEntry(dir, ip4, oldMac); } Ip4ToMacReplicatedMap.addPersistentEntry(bridgeZkManager.getIP4MacMapDirectory(bridgeId), ip4, mac); } @Override public void bridgeAddLearnedIp4Mac(@Nonnull UUID bridgeId, @Nonnull IPv4Addr ip4, @Nonnull MAC mac) throws StateAccessException { // TODO: potential race conditions (see MN-2637) Directory dir = bridgeZkManager.getIP4MacMapDirectory(bridgeId); MAC oldMac = Ip4ToMacReplicatedMap.getEntry(dir, ip4); if (oldMac != null) { if (mac.equals(oldMac) || Ip4ToMacReplicatedMap.hasPersistentEntry(dir, ip4, oldMac)) { return; } Ip4ToMacReplicatedMap.deleteEntry(dir, ip4, oldMac); } Ip4ToMacReplicatedMap.addLearnedEntry(bridgeZkManager.getIP4MacMapDirectory(bridgeId), ip4, mac); } @Override public boolean bridgeHasIP4MacPair(@Nonnull UUID bridgeId, @Nonnull IPv4Addr ip, @Nonnull MAC mac) throws StateAccessException { Directory dir = bridgeZkManager.getIP4MacMapDirectory(bridgeId); return Ip4ToMacReplicatedMap.hasPersistentEntry(dir, ip, mac) || Ip4ToMacReplicatedMap.hasLearnedEntry(dir, ip, mac); } @Override public boolean bridgeCheckPersistentIP4MacPair(@Nonnull UUID bridgeId, @Nonnull IPv4Addr ip, @Nonnull MAC mac) throws StateAccessException { return Ip4ToMacReplicatedMap.hasPersistentEntry(bridgeZkManager.getIP4MacMapDirectory(bridgeId), ip, mac); } @Override public boolean bridgeCheckLearnedIP4MacPair(@Nonnull UUID bridgeId, @Nonnull IPv4Addr ip, @Nonnull MAC mac) throws StateAccessException { return Ip4ToMacReplicatedMap.hasLearnedEntry(bridgeZkManager.getIP4MacMapDirectory(bridgeId), ip, mac); } @Override public MAC bridgeGetIp4Mac(@Nonnull UUID bridgeId, @Nonnull IPv4Addr ip) throws StateAccessException { return Ip4ToMacReplicatedMap.getEntry(bridgeZkManager.getIP4MacMapDirectory(bridgeId), ip); } @Override public void bridgeDeleteIp4Mac(@Nonnull UUID bridgeId, @Nonnull IPv4Addr ip4, @Nonnull MAC mac) throws StateAccessException { Ip4ToMacReplicatedMap.deleteEntry(bridgeZkManager.getIP4MacMapDirectory(bridgeId), ip4, mac); } @Override public void bridgeDeleteLearnedIp4Mac(@Nonnull UUID bridgeId, @Nonnull IPv4Addr ip4, @Nonnull MAC mac) throws StateAccessException { Ip4ToMacReplicatedMap.deleteLearnedEntry(bridgeZkManager.getIP4MacMapDirectory(bridgeId), ip4, mac); } @Override public Set<IPv4Addr> bridgeGetIp4ByMac(@Nonnull UUID bridgeId, @Nonnull MAC mac) throws StateAccessException { return Ip4ToMacReplicatedMap.getByMacValue(bridgeZkManager.getIP4MacMapDirectory(bridgeId), mac); } @Override public UUID bridgesCreate(@Nonnull Bridge bridge) throws StateAccessException, SerializationException { log.debug("bridgesCreate entered: bridge={}", bridge); if (bridge.getId() == null) { bridge.setId(UUID.randomUUID()); } BridgeZkManager.BridgeConfig bridgeConfig = Converter.toBridgeConfig(bridge); List<Op> ops = bridgeZkManager.prepareBridgeCreate(bridge.getId(), bridgeConfig); // Create the top level directories for String tenantId = bridge.getProperty(Bridge.Property.tenant_id); if (!Strings.isNullOrEmpty(tenantId)) { ops.addAll(tenantZkManager.prepareCreate(tenantId)); } zkManager.multi(ops); log.debug("bridgesCreate exiting: bridge={}", bridge); return bridge.getId(); } @Override public void bridgesUpdate(@Nonnull Bridge b) throws StateAccessException, SerializationException { List<Op> ops = new ArrayList<>(); // Get the original data Bridge oldBridge = bridgesGet(b.getId()); BridgeZkManager.BridgeConfig bridgeConfig = Converter.toBridgeConfig(b); // Update the config ops.addAll(bridgeZkManager.prepareUpdate(b.getId(), bridgeConfig)); if (!ops.isEmpty()) { zkManager.multi(ops); } } @Override public List<Bridge> bridgesGetAll() throws StateAccessException, SerializationException { log.debug("bridgesGetAll entered"); List<Bridge> bridges = new ArrayList<>(); for (UUID id : bridgeZkManager.getUuidList(pathBuilder.getBridgesPath())) { Bridge bridge = bridgesGet(id); if (bridge != null) { bridges.add(bridge); } } log.debug("bridgesGetAll exiting: {} bridges found", bridges.size()); return bridges; } @Override public Set<UUID> bridgesBoundToVtep(IPv4Addr mgmtIp) throws StateAccessException, SerializationException { assert (mgmtIp != null); // more efficient to go via the VTEP List<VtepBinding> bindings = vtepGetBindings(mgmtIp); Set<UUID> bridgeIds = new HashSet<>(); for (VtepBinding b : bindings) { bridgeIds.add(b.getNetworkId()); } return bridgeIds; } @Override public EntityMonitor<UUID, BridgeConfig, Bridge> bridgesGetMonitor(ZookeeperConnectionWatcher zkConnection) { return new EntityMonitor<>(bridgeZkManager, zkConnection, new EntityMonitor.Transformer<UUID, BridgeConfig, Bridge>() { @Override public Bridge transform(UUID id, BridgeConfig data) { Bridge bridge = Converter.fromBridgeConfig(data); bridge.setId(id); return bridge; } }); } @Override public EntityIdSetMonitor<UUID> bridgesGetUuidSetMonitor(ZookeeperConnectionWatcher zkConnection) throws StateAccessException { return new EntityIdSetMonitor<>(bridgeZkManager, zkConnection); } @Override public boolean bridgeExists(UUID id) throws StateAccessException { return bridgeZkManager.exists(id); } @Override public @CheckForNull Bridge bridgesGet(UUID id) throws StateAccessException, SerializationException { log.debug("Entered: id={}", id); Bridge bridge = null; if (bridgeZkManager.exists(id)) { bridge = Converter.fromBridgeConfig(bridgeZkManager.get(id)); bridge.setId(id); } log.debug("Exiting: bridge={}", bridge); return bridge; } @Override public void bridgesDelete(UUID id) throws StateAccessException, SerializationException { Bridge bridge = bridgesGet(id); if (bridge == null) { return; } List<Op> ops = bridgeZkManager.prepareBridgeDelete(id); zkManager.multi(ops); } @Override public List<Chain> chainsGetAll() throws StateAccessException, SerializationException { log.debug("chainsGetAll entered"); List<Chain> chains = new ArrayList<>(); String path = pathBuilder.getChainsPath(); if (zkManager.exists(path)) { Set<String> chainIds = zkManager.getChildren(path); for (String id : chainIds) { Chain chain = chainsGet(UUID.fromString(id)); if (chain != null) { chains.add(chain); } } } log.debug("chainsGetAll exiting: {} chains found", chains.size()); return chains; } @Override public @CheckForNull Chain chainsGet(UUID id) throws StateAccessException, SerializationException { log.debug("Entered: id={}", id); Chain chain = null; if (chainZkManager.exists(id)) { chain = Converter.fromChainConfig(chainZkManager.get(id)); chain.setId(id); } log.debug("Exiting: chain={}", chain); return chain; } @Override public void chainsDelete(UUID id) throws StateAccessException, SerializationException { Chain chain = chainsGet(id); if (chain == null) { return; } List<Op> ops = chainZkManager.prepareDelete(id); zkManager.multi(ops); } @Override public UUID chainsCreate(@Nonnull Chain chain) throws StateAccessException, SerializationException { log.debug("chainsCreate entered: chain={}", chain); if (chain.getId() == null) { chain.setId(UUID.randomUUID()); } ChainZkManager.ChainConfig chainConfig = Converter.toChainConfig(chain); List<Op> ops = chainZkManager.prepareCreate(chain.getId(), chainConfig); // Create the top level directories for String tenantId = chain.getProperty(Chain.Property.tenant_id); if (!Strings.isNullOrEmpty(tenantId)) { ops.addAll(tenantZkManager.prepareCreate(tenantId)); } zkManager.multi(ops); log.debug("chainsCreate exiting: chain={}", chain); return chain.getId(); } @Override public void subscribeToLocalActivePorts(@Nonnull Callback2<UUID, Boolean> cb) { subscriptionPortsActive.offer(cb); } @Override public UUID tunnelZonesCreate(@Nonnull TunnelZone zone) throws StateAccessException, SerializationException { return zonesZkManager.createZone(zone, null); } @Override public void tunnelZonesDelete(UUID uuid) throws StateAccessException { zonesZkManager.deleteZone(uuid); } @Override public boolean tunnelZonesExists(UUID uuid) throws StateAccessException { return zonesZkManager.exists(uuid); } @Override public @CheckForNull TunnelZone tunnelZonesGet(UUID uuid) throws StateAccessException, SerializationException { return zonesZkManager.getZone(uuid, null); } @Override public List<TunnelZone> tunnelZonesGetAll() throws StateAccessException, SerializationException { Collection<UUID> ids = zonesZkManager.getZoneIds(); List<TunnelZone> tunnelZones = new ArrayList<>(); for (UUID id : ids) { TunnelZone zone = tunnelZonesGet(id); if (zone != null) { tunnelZones.add(zone); } } return tunnelZones; } @Override public void tunnelZonesUpdate(@Nonnull TunnelZone zone) throws StateAccessException, SerializationException { zonesZkManager.updateZone(zone); } @Override public @CheckForNull TunnelZone.HostConfig tunnelZonesGetMembership(UUID id, UUID hostId) throws StateAccessException, SerializationException { return zonesZkManager.getZoneMembership(id, hostId, null); } @Override public boolean tunnelZonesContainHost(UUID hostId) throws StateAccessException, SerializationException { List<TunnelZone> tunnelZones = tunnelZonesGetAll(); boolean hostExistsInTunnelZone = false; for (TunnelZone tunnelZone : tunnelZones) { if (zonesZkManager.membershipExists(tunnelZone.getId(), hostId)) { hostExistsInTunnelZone = true; break; } } return hostExistsInTunnelZone; } @Override public Set<TunnelZone.HostConfig> tunnelZonesGetMemberships(final UUID uuid) throws StateAccessException { return CollectionFunctors.map(zonesZkManager.getZoneMemberships(uuid, null), new Functor<UUID, TunnelZone.HostConfig>() { @Override public TunnelZone.HostConfig apply(UUID arg0) { try { return zonesZkManager.getZoneMembership(uuid, arg0, null); } catch (StateAccessException e) { // return null; } catch (SerializationException e) { return null; } } }, new HashSet<TunnelZone.HostConfig>()); } @Override public UUID tunnelZonesAddMembership(@Nonnull UUID zoneId, @Nonnull TunnelZone.HostConfig hostConfig) throws StateAccessException, SerializationException { return zonesZkManager.addMembership(zoneId, hostConfig); } @Override public void tunnelZonesDeleteMembership(UUID zoneId, UUID membershipId) throws StateAccessException { zonesZkManager.delMembership(zoneId, membershipId); } @Override public EntityMonitor<UUID, TunnelZone.Data, TunnelZone> tunnelZonesGetMonitor( ZookeeperConnectionWatcher zkConnection) { return new EntityMonitor<>(zonesZkManager, zkConnection, new EntityMonitor.Transformer<UUID, TunnelZone.Data, TunnelZone>() { @Override public TunnelZone transform(UUID id, TunnelZone.Data data) { return new TunnelZone(id, data); } }); } @Override public EntityIdSetMonitor<UUID> tunnelZonesGetUuidSetMonitor(ZookeeperConnectionWatcher zkConnection) throws StateAccessException { return new EntityIdSetMonitor(zonesZkManager, zkConnection); } @Override public EntityIdSetMonitor<UUID> tunnelZonesGetMembershipsMonitor(@Nonnull final UUID zoneId, ZookeeperConnectionWatcher zkConnection) throws StateAccessException { return new EntityIdSetMonitor<>(new WatchableZkManager<UUID, TunnelZone.HostConfig>() { @Override public List<UUID> getAndWatchIdList(Runnable watcher) throws StateAccessException { return zonesZkManager.getAndWatchMembershipsList(zoneId, watcher); } @Override public TunnelZone.HostConfig get(UUID id, Runnable watcher) throws StateAccessException, SerializationException { return null; } }, zkConnection); } @Override public void portsSetLocalAndActive(final UUID portID, final UUID host, final boolean active) { // use the reactor thread for this operations reactor.submit(new Runnable() { @Override public void run() { PortConfig config = null; try { portZkManager.setActivePort(portID, host, active); config = portZkManager.get(portID); } catch (StateAccessException e) { log.error("Error retrieving the configuration for port {}", portID, e); } catch (SerializationException e) { log.error("Error serializing the configuration for port " + "{}", portID, e); } // update the subscribers for (Callback2<UUID, Boolean> cb : subscriptionPortsActive) { cb.call(portID, active); } if (config instanceof PortDirectory.RouterPortConfig) { UUID deviceId = config.device_id; routerManager.updateRoutesBecauseLocalPortChangedStatus(deviceId, portID, active); } } }); } @Override public List<Chain> chainsFindByTenant(String tenantId) throws StateAccessException, SerializationException { log.debug("chainsFindByTenant entered: tenantId={}", tenantId); List<Chain> chains = chainsGetAll(); for (Iterator<Chain> it = chains.iterator(); it.hasNext();) { if (!it.next().hasTenantId(tenantId)) { it.remove(); } } log.debug("chainsFindByTenant exiting: {} chains found", chains.size()); return chains; } @Override public void dhcpSubnetsCreate(@Nonnull UUID bridgeId, @Nonnull Subnet subnet) throws StateAccessException, SerializationException { dhcpZkManager.createSubnet(bridgeId, Converter.toDhcpSubnetConfig(subnet)); } @Override public void dhcpSubnetsUpdate(@Nonnull UUID bridgeId, @Nonnull Subnet subnet) throws StateAccessException, SerializationException { Subnet oldSubnet = dhcpSubnetsGet(bridgeId, subnet.getSubnetAddr()); if (oldSubnet == null) { return; } // If isEnabled was not specified in the request, just set it to the // previous value. if (subnet.isEnabled() == null) { subnet.setEnabled(oldSubnet.isEnabled()); } dhcpZkManager.updateSubnet(bridgeId, Converter.toDhcpSubnetConfig(subnet)); } @Override public void dhcpSubnetsDelete(UUID bridgeId, IPv4Subnet subnetAddr) throws StateAccessException { dhcpZkManager.deleteSubnet(bridgeId, subnetAddr); } @Override public @CheckForNull Subnet dhcpSubnetsGet(UUID bridgeId, IPv4Subnet subnetAddr) throws StateAccessException, SerializationException { Subnet subnet = null; if (dhcpZkManager.existsSubnet(bridgeId, subnetAddr)) { BridgeDhcpZkManager.Subnet subnetConfig = dhcpZkManager.getSubnet(bridgeId, subnetAddr); subnet = Converter.fromDhcpSubnetConfig(subnetConfig); subnet.setId(subnetAddr.toZkString()); } return subnet; } @Override public List<Subnet> dhcpSubnetsGetByBridge(UUID bridgeId) throws StateAccessException, SerializationException { List<IPv4Subnet> subnetConfigs = dhcpZkManager.listSubnets(bridgeId); List<Subnet> subnets = new ArrayList<>(subnetConfigs.size()); for (IPv4Subnet subnetAddr : subnetConfigs) { subnets.add(dhcpSubnetsGet(bridgeId, subnetAddr)); } return subnets; } @Override public List<Subnet> dhcpSubnetsGetByBridgeEnabled(UUID bridgeId) throws StateAccessException, SerializationException { List<BridgeDhcpZkManager.Subnet> subnetConfigs = dhcpZkManager.getEnabledSubnets(bridgeId); List<Subnet> subnets = new ArrayList<>(subnetConfigs.size()); for (BridgeDhcpZkManager.Subnet subnetConfig : subnetConfigs) { subnets.add(dhcpSubnetsGet(bridgeId, subnetConfig.getSubnetAddr())); } return subnets; } @Override public void dhcpHostsCreate(@Nonnull UUID bridgeId, @Nonnull IPv4Subnet subnet, org.midonet.cluster.data.dhcp.Host host) throws StateAccessException, SerializationException { dhcpZkManager.addHost(bridgeId, subnet, Converter.toDhcpHostConfig(host)); } @Override public void dhcpHostsUpdate(@Nonnull UUID bridgeId, @Nonnull IPv4Subnet subnet, org.midonet.cluster.data.dhcp.Host host) throws StateAccessException, SerializationException { dhcpZkManager.updateHost(bridgeId, subnet, Converter.toDhcpHostConfig(host)); } @Override public @CheckForNull org.midonet.cluster.data.dhcp.Host dhcpHostsGet(UUID bridgeId, IPv4Subnet subnet, String mac) throws StateAccessException, SerializationException { org.midonet.cluster.data.dhcp.Host host = null; if (dhcpZkManager.existsHost(bridgeId, subnet, mac)) { BridgeDhcpZkManager.Host hostConfig = dhcpZkManager.getHost(bridgeId, subnet, mac); host = Converter.fromDhcpHostConfig(hostConfig); host.setId(MAC.fromString(mac)); } return host; } @Override public void dhcpHostsDelete(UUID bridgId, IPv4Subnet subnet, String mac) throws StateAccessException { dhcpZkManager.deleteHost(bridgId, subnet, mac); } @Override public List<org.midonet.cluster.data.dhcp.Host> dhcpHostsGetBySubnet(UUID bridgeId, IPv4Subnet subnet) throws StateAccessException, SerializationException { List<BridgeDhcpZkManager.Host> hostConfigs = dhcpZkManager.getHosts(bridgeId, subnet); List<org.midonet.cluster.data.dhcp.Host> hosts = new ArrayList<>(); for (BridgeDhcpZkManager.Host hostConfig : hostConfigs) { hosts.add(Converter.fromDhcpHostConfig(hostConfig)); } return hosts; } @Override public void dhcpSubnet6Create(@Nonnull UUID bridgeId, @Nonnull Subnet6 subnet) throws StateAccessException, SerializationException { dhcpV6ZkManager.createSubnet6(bridgeId, Converter.toDhcpSubnet6Config(subnet)); } @Override public void dhcpSubnet6Update(@Nonnull UUID bridgeId, @Nonnull Subnet6 subnet) throws StateAccessException, SerializationException { dhcpV6ZkManager.updateSubnet6(bridgeId, Converter.toDhcpSubnet6Config(subnet)); } @Override public void dhcpSubnet6Delete(UUID bridgeId, IPv6Subnet prefix) throws StateAccessException { dhcpV6ZkManager.deleteSubnet6(bridgeId, prefix); } public @CheckForNull Subnet6 dhcpSubnet6Get(UUID bridgeId, IPv6Subnet prefix) throws StateAccessException, SerializationException { Subnet6 subnet = null; if (dhcpV6ZkManager.existsSubnet6(bridgeId, prefix)) { BridgeDhcpV6ZkManager.Subnet6 subnetConfig = dhcpV6ZkManager.getSubnet6(bridgeId, prefix); subnet = Converter.fromDhcpSubnet6Config(subnetConfig); subnet.setPrefix(prefix); } return subnet; } @Override public List<Subnet6> dhcpSubnet6sGetByBridge(UUID bridgeId) throws StateAccessException, SerializationException { List<IPv6Subnet> subnet6Configs = dhcpV6ZkManager.listSubnet6s(bridgeId); List<Subnet6> subnets = new ArrayList<>(subnet6Configs.size()); for (IPv6Subnet subnet6Config : subnet6Configs) { subnets.add(dhcpSubnet6Get(bridgeId, subnet6Config)); } return subnets; } @Override public void dhcpV6HostCreate(@Nonnull UUID bridgeId, @Nonnull IPv6Subnet prefix, V6Host host) throws StateAccessException, SerializationException { dhcpV6ZkManager.addHost(bridgeId, prefix, Converter.toDhcpV6HostConfig(host)); } @Override public void dhcpV6HostUpdate(@Nonnull UUID bridgeId, @Nonnull IPv6Subnet prefix, V6Host host) throws StateAccessException, SerializationException { dhcpV6ZkManager.updateHost(bridgeId, prefix, Converter.toDhcpV6HostConfig(host)); } @Override public @CheckForNull V6Host dhcpV6HostGet(UUID bridgeId, IPv6Subnet prefix, String clientId) throws StateAccessException, SerializationException { V6Host host = null; if (dhcpV6ZkManager.existsHost(bridgeId, prefix, clientId)) { BridgeDhcpV6ZkManager.Host hostConfig = dhcpV6ZkManager.getHost(bridgeId, prefix, clientId); host = Converter.fromDhcpV6HostConfig(hostConfig); host.setId(clientId); } return host; } @Override public void dhcpV6HostDelete(UUID bridgId, IPv6Subnet prefix, String clientId) throws StateAccessException { dhcpV6ZkManager.deleteHost(bridgId, prefix, clientId); } @Override public List<V6Host> dhcpV6HostsGetByPrefix(UUID bridgeId, IPv6Subnet prefix) throws StateAccessException, SerializationException { List<BridgeDhcpV6ZkManager.Host> hostConfigs = dhcpV6ZkManager.getHosts(bridgeId, prefix); List<V6Host> hosts = new ArrayList<>(); for (BridgeDhcpV6ZkManager.Host hostConfig : hostConfigs) { hosts.add(Converter.fromDhcpV6HostConfig(hostConfig)); } return hosts; } @Override public @CheckForNull Host hostsGet(UUID hostId) throws StateAccessException, SerializationException { Host host = null; if (hostsExists(hostId)) { HostDirectory.Metadata hostMetadata = hostZkManager.get(hostId); if (hostMetadata == null) { log.error("Failed to fetch metadata for host {}", hostId); return null; } Integer floodingProxyWeight = hostZkManager.getFloodingProxyWeight(hostId); host = Converter.fromHostConfig(hostMetadata); host.setId(hostId); host.setIsAlive(hostsIsAlive(hostId)); host.setInterfaces(interfacesGetByHost(hostId)); /* The flooding proxy weight might have not been initialized * for this host; if so, leave the default value set by Host * constructor; otherwise, set the stored value. */ if (floodingProxyWeight != null) host.setFloodingProxyWeight(floodingProxyWeight); } return host; } @Override public void hostsDelete(UUID hostId) throws StateAccessException { hostZkManager.deleteHost(hostId); } @Override public boolean hostsExists(UUID hostId) throws StateAccessException { return hostZkManager.exists(hostId); } @Override public boolean hostsIsAlive(UUID hostId) throws StateAccessException { return hostZkManager.isAlive(hostId); } @Override public boolean hostsIsAlive(UUID hostId, Watcher watcher) throws StateAccessException { return hostZkManager.isAlive(hostId, watcher); } @Override public boolean hostsHasPortBindings(UUID hostId) throws StateAccessException { return hostZkManager.hasPortBindings(hostId); } @Override public List<Host> hostsGetAll() throws StateAccessException { Collection<UUID> ids = hostZkManager.getHostIds(); List<Host> hosts = new ArrayList<>(); for (UUID id : ids) { try { Host host = hostsGet(id); if (host != null) { hosts.add(host); } } catch (StateAccessException | SerializationException e) { log.warn("Cannot get host {} while enumerating hosts", id); } } return hosts; } @Override public EntityMonitor<UUID, HostDirectory.Metadata, Host> hostsGetMonitor( ZookeeperConnectionWatcher zkConnection) { return new EntityMonitor<>(hostZkManager, zkConnection, new EntityMonitor.Transformer<UUID, HostDirectory.Metadata, Host>() { @Override public Host transform(UUID id, HostDirectory.Metadata data) { Host host = Converter.fromHostConfig(data); host.setId(id); Integer floodingProxyWeight = null; try { floodingProxyWeight = hostZkManager.getFloodingProxyWeight(id); } catch (StateAccessException | SerializationException e) { log.warn("Failure getting flooding proxy weight", e); } try { host.setIsAlive(hostsIsAlive(id)); } catch (StateAccessException e) { log.warn("Failure getting host status", e); } if (floodingProxyWeight != null) { host.setFloodingProxyWeight(floodingProxyWeight); } return host; } }); } @Override public EntityIdSetMonitor<UUID> hostsGetUuidSetMonitor(ZookeeperConnectionWatcher zkConnection) throws StateAccessException { return new EntityIdSetMonitor<>(hostZkManager, zkConnection); } @Override public List<Interface> interfacesGetByHost(UUID hostId) throws StateAccessException, SerializationException { List<Interface> interfaces = new ArrayList<>(); Collection<String> interfaceNames = hostZkManager.getInterfaces(hostId); for (String interfaceName : interfaceNames) { try { Interface anInterface = interfacesGet(hostId, interfaceName); if (anInterface != null) { interfaces.add(anInterface); } } catch (StateAccessException e) { log.warn("An interface description went missing in action while " + "we were looking for it host: {}, interface: " + "{}.", hostId, interfaceName, e); } } return interfaces; } @Override public @CheckForNull Interface interfacesGet(UUID hostId, String interfaceName) throws StateAccessException, SerializationException { Interface anInterface = null; if (hostZkManager.existsInterface(hostId, interfaceName)) { HostDirectory.Interface interfaceData = hostZkManager.getInterfaceData(hostId, interfaceName); anInterface = Converter.fromHostInterfaceConfig(interfaceData); anInterface.setId(interfaceName); } return anInterface; } @Override public List<VirtualPortMapping> hostsGetVirtualPortMappingsByHost(UUID hostId) throws StateAccessException, SerializationException { Set<HostDirectory.VirtualPortMapping> zkMaps = hostZkManager.getVirtualPortMappings(hostId, null); List<VirtualPortMapping> maps = new ArrayList<>(zkMaps.size()); for (HostDirectory.VirtualPortMapping zkMap : zkMaps) { maps.add(Converter.fromHostVirtPortMappingConfig(zkMap)); } return maps; } @Override public boolean hostsVirtualPortMappingExists(UUID hostId, UUID portId) throws StateAccessException { return hostZkManager.virtualPortMappingExists(hostId, portId); } @Override public @CheckForNull VirtualPortMapping hostsGetVirtualPortMapping(UUID hostId, UUID portId) throws StateAccessException, SerializationException { HostDirectory.VirtualPortMapping mapping = hostZkManager.getVirtualPortMapping(hostId, portId); if (mapping == null) { return null; } return Converter.fromHostVirtPortMappingConfig(mapping); } @Override public boolean portsExists(UUID id) throws StateAccessException { return portZkManager.exists(id); } @Override public void portsDelete(UUID id) throws StateAccessException, SerializationException { portZkManager.delete(id); } @Override public List<BridgePort> portsFindByBridge(UUID bridgeId) throws StateAccessException, SerializationException { Collection<UUID> ids = portZkManager.getBridgePortIDs(bridgeId); List<BridgePort> ports = new ArrayList<>(); for (UUID id : ids) { Port<?, ?> port = portsGet(id); if (port instanceof BridgePort) { // Skip the VxLanPort, since it's not really a // BridgePort and is accessible in other ways. ports.add((BridgePort) portsGet(id)); } } ids = portZkManager.getBridgeLogicalPortIDs(bridgeId); for (UUID id : ids) { ports.add((BridgePort) portsGet(id)); } return ports; } @Override public List<Port<?, ?>> portsFindPeersByBridge(UUID bridgeId) throws StateAccessException, SerializationException { Collection<UUID> ids = portZkManager.getBridgeLogicalPortIDs(bridgeId); List<Port<?, ?>> ports = new ArrayList<>(); for (UUID id : ids) { Port<?, ?> portData = portsGet(id); if (portData.getPeerId() != null) { ports.add(portsGet(portData.getPeerId())); } } return ports; } @Override public List<Port<?, ?>> portsFindByRouter(UUID routerId) throws StateAccessException, SerializationException { Collection<UUID> ids = portZkManager.getRouterPortIDs(routerId); List<Port<?, ?>> ports = new ArrayList<>(); for (UUID id : ids) { ports.add(portsGet(id)); } return ports; } @Override public List<Port<?, ?>> portsFindPeersByRouter(UUID routerId) throws StateAccessException, SerializationException { Collection<UUID> ids = portZkManager.getRouterPortIDs(routerId); List<Port<?, ?>> ports = new ArrayList<>(); for (UUID id : ids) { Port<?, ?> portData = portsGet(id); if (portData.getPeerId() != null) { ports.add(portsGet(portData.getPeerId())); } } return ports; } @Override public UUID portsCreate(@Nonnull final Port<?, ?> port) throws StateAccessException, SerializationException { return portZkManager.create(Converter.toPortConfig(port)); } @Override public List<Port<?, ?>> portsGetAll() throws StateAccessException, SerializationException { log.debug("portsGetAll entered"); List<Port<?, ?>> ports = new ArrayList<>(); String path = pathBuilder.getPortsPath(); if (zkManager.exists(path)) { Set<String> portIds = zkManager.getChildren(path); for (String id : portIds) { Port<?, ?> port = portsGet(UUID.fromString(id)); if (port != null) { ports.add(port); } } } log.debug("portsGetAll exiting: {} routers found", ports.size()); return ports; } @Override public @CheckForNull Port<?, ?> portsGet(UUID id) throws StateAccessException, SerializationException { Port<?, ?> port = null; if (portZkManager.exists(id)) { port = Converter.fromPortConfig(portZkManager.get(id)); port.setId(id); } return port; } @Override public void portsUpdate(@Nonnull Port<?, ?> port) throws StateAccessException, SerializationException { log.debug("portsUpdate entered: port={}", port); // Whatever sent is what gets stored. portZkManager.update(UUID.fromString(port.getId().toString()), Converter.toPortConfig(port)); log.debug("portsUpdate exiting"); } @Override public void portsLink(@Nonnull UUID portId, @Nonnull UUID peerPortId) throws StateAccessException, SerializationException { portZkManager.link(portId, peerPortId); } @Override public void portsUnlink(@Nonnull UUID portId) throws StateAccessException, SerializationException { portZkManager.unlink(portId); } @Override public List<Port<?, ?>> portsFindByPortGroup(UUID portGroupId) throws StateAccessException, SerializationException { Set<UUID> portIds = portZkManager.getPortGroupPortIds(portGroupId); List<Port<?, ?>> ports = new ArrayList<>(portIds.size()); for (UUID portId : portIds) { ports.add(portsGet(portId)); } return ports; } @Override public IpAddrGroup ipAddrGroupsGet(UUID id) throws StateAccessException, SerializationException { IpAddrGroup g = Converter.fromIpAddrGroupConfig(ipAddrGroupZkManager.get(id)); g.setId(id); return g; } @Override public void ipAddrGroupsDelete(UUID id) throws StateAccessException, SerializationException { ipAddrGroupZkManager.delete(id); } @Override public UUID ipAddrGroupsCreate(@Nonnull IpAddrGroup ipAddrGroup) throws StateAccessException, SerializationException { return ipAddrGroupZkManager.create(Converter.toIpAddrGroupConfig(ipAddrGroup)); } @Override public boolean ipAddrGroupsExists(UUID id) throws StateAccessException { return ipAddrGroupZkManager.exists(id); } @Override public List<IpAddrGroup> ipAddrGroupsGetAll() throws StateAccessException, SerializationException { Set<UUID> ids = ipAddrGroupZkManager.getAllIds(); List<IpAddrGroup> groups = new ArrayList<>(); for (UUID id : ids) { IpAddrGroupZkManager.IpAddrGroupConfig config = ipAddrGroupZkManager.get(id); IpAddrGroup group = Converter.fromIpAddrGroupConfig(config); group.setId(id); groups.add(group); } return groups; } @Override public boolean ipAddrGroupHasAddr(UUID id, String addr) throws StateAccessException { return ipAddrGroupZkManager.isMember(id, addr); } @Override public void ipAddrGroupAddAddr(@Nonnull UUID id, @Nonnull String addr) throws StateAccessException, SerializationException { ipAddrGroupZkManager.addAddr(id, addr); } @Override public void ipAddrGroupRemoveAddr(UUID id, String addr) throws StateAccessException, SerializationException { ipAddrGroupZkManager.removeAddr(id, addr); } @Override public Set<String> getAddrsByIpAddrGroup(UUID id) throws StateAccessException, SerializationException { return ipAddrGroupZkManager.getAddrs(id); } @Override public List<PortGroup> portGroupsFindByTenant(String tenantId) throws StateAccessException, SerializationException { log.debug("portGroupsFindByTenant entered: tenantId={}", tenantId); List<PortGroup> portGroups = portGroupsGetAll(); for (Iterator<PortGroup> it = portGroups.iterator(); it.hasNext();) { if (!it.next().hasTenantId(tenantId)) { it.remove(); } } log.debug("portGroupsFindByTenant exiting: {} portGroups found", portGroups.size()); return portGroups; } @Override public List<PortGroup> portGroupsFindByPort(UUID portId) throws StateAccessException, SerializationException { log.debug("portGroupsFindByPort entered: portId={}", portId); List<PortGroup> portGroups = new ArrayList<>(); if (portsExists(portId)) { for (UUID portGroupId : portsGet(portId).getPortGroups()) { PortGroup portGroup = portGroupsGet(portGroupId); if (portGroup != null) { portGroups.add(portGroup); } } } log.debug("portGroupsFindByPort exiting: {} portGroups found", portGroups.size()); return portGroups; } @Override public boolean portGroupsIsPortMember(@Nonnull UUID id, @Nonnull UUID portId) throws StateAccessException { return portGroupZkManager.portIsMember(id, portId); } @Override public void portGroupsAddPortMembership(@Nonnull UUID id, @Nonnull UUID portId) throws StateAccessException, SerializationException { portGroupZkManager.addPortToPortGroup(id, portId); } @Override public void portGroupsRemovePortMembership(UUID id, UUID portId) throws StateAccessException, SerializationException { portGroupZkManager.removePortFromPortGroup(id, portId); } @Override public UUID portGroupsCreate(@Nonnull PortGroup portGroup) throws StateAccessException, SerializationException { log.debug("portGroupsCreate entered: portGroup={}", portGroup); if (portGroup.getId() == null) { portGroup.setId(UUID.randomUUID()); } PortGroupZkManager.PortGroupConfig portGroupConfig = Converter.toPortGroupConfig(portGroup); List<Op> ops = portGroupZkManager.prepareCreate(portGroup.getId(), portGroupConfig); String tenantId = portGroup.getProperty(PortGroup.Property.tenant_id); if (!Strings.isNullOrEmpty(tenantId)) { ops.addAll(tenantZkManager.prepareCreate(tenantId)); } zkManager.multi(ops); log.debug("portGroupsCreate exiting: portGroup={}", portGroup); return portGroup.getId(); } @Override public void portGroupsUpdate(@Nonnull PortGroup portGroup) throws StateAccessException, SerializationException { PortGroupZkManager.PortGroupConfig pgConfig = Converter.toPortGroupConfig(portGroup); List<Op> ops = new ArrayList<>(); // Update the config ops.addAll(portGroupZkManager.prepareUpdate(portGroup.getId(), pgConfig)); if (!ops.isEmpty()) { zkManager.multi(ops); } } @Override public boolean portGroupsExists(UUID id) throws StateAccessException { return portGroupZkManager.exists(id); } @Override public List<PortGroup> portGroupsGetAll() throws StateAccessException, SerializationException { log.debug("portGroupsGetAll entered"); List<PortGroup> portGroups = new ArrayList<>(); String path = pathBuilder.getPortGroupsPath(); if (zkManager.exists(path)) { Set<String> portGroupIds = zkManager.getChildren(path); for (String id : portGroupIds) { PortGroup portGroup = portGroupsGet(UUID.fromString(id)); if (portGroup != null) { portGroups.add(portGroup); } } } log.debug("portGroupsGetAll exiting: {} port groups found", portGroups.size()); return portGroups; } @Override @CheckForNull public PortGroup portGroupsGet(UUID id) throws StateAccessException, SerializationException { log.debug("Entered: id={}", id); PortGroup portGroup = null; if (portGroupZkManager.exists(id)) { portGroup = Converter.fromPortGroupConfig(portGroupZkManager.get(id)); portGroup.setId(id); } log.debug("Exiting: portGroup={}", portGroup); return portGroup; } @Override public void portGroupsDelete(UUID id) throws StateAccessException, SerializationException { PortGroup portGroup = portGroupsGet(id); if (portGroup == null) { return; } List<Op> ops = portGroupZkManager.prepareDelete(id); zkManager.multi(ops); } @Override public UUID hostsCreate(@Nonnull UUID hostId, @Nonnull Host host) throws StateAccessException, SerializationException { hostZkManager.createHost(hostId, Converter.toHostConfig(host)); return hostId; } @Override public void hostsAddVrnPortMapping(@Nonnull UUID hostId, @Nonnull UUID portId, @Nonnull String localPortName) throws StateAccessException, SerializationException { hostZkManager.addVirtualPortMapping(hostId, new HostDirectory.VirtualPortMapping(portId, localPortName)); } /** * Does the same thing as @hostsAddVrnPortMapping(), * except this returns the updated port object. */ @Override public Port<?, ?> hostsAddVrnPortMappingAndReturnPort(@Nonnull UUID hostId, @Nonnull UUID portId, @Nonnull String localPortName) throws StateAccessException, SerializationException { return hostZkManager.addVirtualPortMapping(hostId, new HostDirectory.VirtualPortMapping(portId, localPortName)); } @Override public void hostsAddDatapathMapping(@Nonnull UUID hostId, @Nonnull String datapathName) throws StateAccessException, SerializationException { hostZkManager.addVirtualDatapathMapping(hostId, datapathName); } @Override public void hostsDelVrnPortMapping(UUID hostId, UUID portId) throws StateAccessException, SerializationException { hostZkManager.delVirtualPortMapping(hostId, portId); } @Override public void hostsSetFloodingProxyWeight(UUID hostId, int weight) throws StateAccessException, SerializationException { hostZkManager.setFloodingProxyWeight(hostId, weight); } /* load balancer related methods */ @Override @CheckForNull public LoadBalancer loadBalancerGet(UUID id) throws StateAccessException, SerializationException { LoadBalancer loadBalancer = null; if (loadBalancerZkManager.exists(id)) { loadBalancer = Converter.fromLoadBalancerConfig(loadBalancerZkManager.get(id)); loadBalancer.setId(id); } return loadBalancer; } @Override public void loadBalancerDelete(UUID id) throws StateAccessException, SerializationException { List<Op> ops = new ArrayList<>(); Set<UUID> poolIds = loadBalancerZkManager.getPoolIds(id); for (UUID poolId : poolIds) { ops.addAll(buildPoolDeleteOps(poolId)); } LoadBalancerZkManager.LoadBalancerConfig loadBalancerConfig = loadBalancerZkManager.get(id); if (loadBalancerConfig.routerId != null) { ops.addAll(routerZkManager.prepareClearRefsToLoadBalancer(loadBalancerConfig.routerId, id)); } ops.addAll(loadBalancerZkManager.prepareDelete(id)); zkManager.multi(ops); } @Override public UUID loadBalancerCreate(@Nonnull LoadBalancer loadBalancer) throws StateAccessException, SerializationException, InvalidStateOperationException { if (loadBalancer.getId() == null) { loadBalancer.setId(UUID.randomUUID()); } LoadBalancerZkManager.LoadBalancerConfig loadBalancerConfig = Converter.toLoadBalancerConfig(loadBalancer); loadBalancerZkManager.create(loadBalancer.getId(), loadBalancerConfig); return loadBalancer.getId(); } @Override public void loadBalancerUpdate(@Nonnull LoadBalancer loadBalancer) throws StateAccessException, SerializationException, InvalidStateOperationException { LoadBalancerZkManager.LoadBalancerConfig loadBalancerConfig = Converter.toLoadBalancerConfig(loadBalancer); loadBalancerZkManager.update(loadBalancer.getId(), loadBalancerConfig); } @Override public List<LoadBalancer> loadBalancersGetAll() throws StateAccessException, SerializationException { List<LoadBalancer> loadBalancers = new ArrayList<>(); String path = pathBuilder.getLoadBalancersPath(); if (zkManager.exists(path)) { Set<String> loadBalancerIds = zkManager.getChildren(path); for (String id : loadBalancerIds) { LoadBalancer loadBalancer = loadBalancerGet(UUID.fromString(id)); if (loadBalancer != null) { loadBalancers.add(loadBalancer); } } } return loadBalancers; } @Override public List<Pool> loadBalancerGetPools(UUID id) throws StateAccessException, SerializationException { Set<UUID> poolIds = loadBalancerZkManager.getPoolIds(id); List<Pool> pools = new ArrayList<>(poolIds.size()); for (UUID poolId : poolIds) { Pool pool = Converter.fromPoolConfig(poolZkManager.get(poolId)); pool.setId(poolId); pools.add(pool); } return pools; } @Override public List<VIP> loadBalancerGetVips(UUID id) throws StateAccessException, SerializationException { Set<UUID> vipIds = loadBalancerZkManager.getVipIds(id); List<VIP> vips = new ArrayList<>(vipIds.size()); for (UUID vipId : vipIds) { VIP vip = Converter.fromVipConfig(vipZkManager.get(vipId)); vip.setId(vipId); vips.add(vip); } return vips; } private void validatePoolConfigMappingStatus(UUID poolId) throws MappingStatusException, StateAccessException, SerializationException { PoolZkManager.PoolConfig poolConfig = poolZkManager.get(poolId); if (poolConfig.isImmutable()) { throw new MappingStatusException(poolConfig.mappingStatus.toString()); } } /* * Returns the pair of the mapping path and the mapping config. If the * given pool is not associated with any health monitor, it returns `null`. */ private MutablePair<String, PoolHealthMonitorConfig> preparePoolHealthMonitorMappings(@Nonnull UUID poolId, @Nonnull PoolZkManager.PoolConfig poolConfig, ConfigGetter<UUID, PoolMemberZkManager.PoolMemberConfig> poolMemberConfigGetter, ConfigGetter<UUID, VipZkManager.VipConfig> vipConfigGetter) throws MappingStatusException, SerializationException, StateAccessException { UUID healthMonitorId = poolConfig.healthMonitorId; // If the health monitor ID is null, the mapping should not be created // and therefore `null` is returned. if (healthMonitorId == null) { return null; } // If `mappingStatus` property of Pool is in PENDING_*, it throws the // exception and prevent the mapping from being updated. validatePoolConfigMappingStatus(poolId); String mappingPath = pathBuilder.getPoolHealthMonitorMappingsPath(poolId, healthMonitorId); assert poolConfig.loadBalancerId != null; UUID loadBalancerId = checkNotNull(poolConfig.loadBalancerId, "LoadBalancer ID is null."); LoadBalancerConfigWithId loadBalancerConfig = new LoadBalancerConfigWithId( loadBalancerZkManager.get(loadBalancerId)); List<UUID> memberIds = poolZkManager.getMemberIds(poolId); List<PoolMemberConfigWithId> memberConfigs = new ArrayList<>(memberIds.size()); for (UUID memberId : memberIds) { PoolMemberZkManager.PoolMemberConfig config = poolMemberConfigGetter.get(memberId); if (config != null) { config.id = memberId; memberConfigs.add(new PoolMemberConfigWithId(config)); } } List<UUID> vipIds = poolZkManager.getVipIds(poolId); List<VipConfigWithId> vipConfigs = new ArrayList<>(vipIds.size()); for (UUID vipId : vipIds) { VipZkManager.VipConfig config = vipConfigGetter.get(vipId); if (config != null) { config.id = vipId; vipConfigs.add(new VipConfigWithId(config)); } } HealthMonitorConfigWithId healthMonitorConfig = new HealthMonitorConfigWithId( healthMonitorZkManager.get(healthMonitorId)); PoolHealthMonitorConfig mappingConfig = new PoolHealthMonitorConfig(loadBalancerConfig, vipConfigs, memberConfigs, healthMonitorConfig); return new MutablePair<>(mappingPath, mappingConfig); } private List<Op> preparePoolHealthMonitorMappingUpdate(Pair<String, PoolHealthMonitorConfig> pair) throws SerializationException { List<Op> ops = new ArrayList<>(); if (pair != null) { String mappingPath = pair.getLeft(); PoolHealthMonitorConfig mappingConfig = pair.getRight(); ops.add(Op.setData(mappingPath, serializer.serialize(mappingConfig), -1)); } return ops; } /* health monitors related methods */ private List<Pair<String, PoolHealthMonitorConfig>> buildPoolHealthMonitorMappings(UUID healthMonitorId, @Nullable HealthMonitorZkManager.HealthMonitorConfig config) throws MappingStatusException, SerializationException, StateAccessException { List<UUID> poolIds = healthMonitorZkManager.getPoolIds(healthMonitorId); List<Pair<String, PoolHealthMonitorConfig>> pairs = new ArrayList<>(); for (UUID poolId : poolIds) { PoolZkManager.PoolConfig poolConfig = poolZkManager.get(poolId); MutablePair<String, PoolHealthMonitorConfig> pair = preparePoolHealthMonitorMappings(poolId, poolConfig, poolMemberZkManager, vipZkManager); if (pair != null) { // Update health monitor config, which can be null PoolHealthMonitorConfig updatedMappingConfig = pair.getRight(); updatedMappingConfig.healthMonitorConfig = new HealthMonitorConfigWithId(config); pair.setRight(updatedMappingConfig); pairs.add(pair); } } return pairs; } @Override @CheckForNull public HealthMonitor healthMonitorGet(UUID id) throws StateAccessException, SerializationException { HealthMonitor healthMonitor = null; if (healthMonitorZkManager.exists(id)) { healthMonitor = Converter.fromHealthMonitorConfig(healthMonitorZkManager.get(id)); healthMonitor.setId(id); } return healthMonitor; } @Override public void healthMonitorDelete(UUID id) throws MappingStatusException, StateAccessException, SerializationException { List<Op> ops = new ArrayList<>(); List<UUID> poolIds = healthMonitorZkManager.getPoolIds(id); for (UUID poolId : poolIds) { validatePoolConfigMappingStatus(poolId); PoolZkManager.PoolConfig poolConfig = poolZkManager.get(poolId); ops.add(Op.setData(pathBuilder.getPoolPath(poolId), serializer.serialize(poolConfig), -1)); // Pool-HealthMonitor mappings ops.add(Op.delete(pathBuilder.getPoolHealthMonitorMappingsPath(poolId, id), -1)); poolConfig.healthMonitorId = null; // Indicate the mapping is being deleted. poolConfig.mappingStatus = PoolHealthMonitorMappingStatus.PENDING_DELETE; ops.addAll(poolZkManager.prepareUpdate(poolId, poolConfig)); ops.addAll(healthMonitorZkManager.prepareRemovePool(id, poolId)); } ops.addAll(healthMonitorZkManager.prepareDelete(id)); zkManager.multi(ops); } @Override public UUID healthMonitorCreate(@Nonnull HealthMonitor healthMonitor) throws StateAccessException, SerializationException { if (healthMonitor.getId() == null) { healthMonitor.setId(UUID.randomUUID()); } HealthMonitorZkManager.HealthMonitorConfig config = Converter.toHealthMonitorConfig(healthMonitor); zkManager.multi(healthMonitorZkManager.prepareCreate(healthMonitor.getId(), config)); return healthMonitor.getId(); } @Override public void healthMonitorUpdate(@Nonnull HealthMonitor healthMonitor) throws MappingStatusException, StateAccessException, SerializationException { HealthMonitorZkManager.HealthMonitorConfig newConfig = Converter.toHealthMonitorConfig(healthMonitor); HealthMonitorZkManager.HealthMonitorConfig oldConfig = healthMonitorZkManager.get(healthMonitor.getId()); UUID id = healthMonitor.getId(); if (newConfig.equals(oldConfig)) { return; } List<Op> ops = new ArrayList<>(); ops.addAll(healthMonitorZkManager.prepareUpdate(id, newConfig)); // Pool-HealthMonitor mappings for (Pair<String, PoolHealthMonitorConfig> pair : buildPoolHealthMonitorMappings(id, newConfig)) { List<UUID> poolIds = healthMonitorZkManager.getPoolIds(id); for (UUID poolId : poolIds) { validatePoolConfigMappingStatus(poolId); PoolZkManager.PoolConfig poolConfig = poolZkManager.get(poolId); // Indicate the mapping is being updated. poolConfig.mappingStatus = PoolHealthMonitorMappingStatus.PENDING_UPDATE; ops.add(Op.setData(pathBuilder.getPoolPath(poolId), serializer.serialize(poolConfig), -1)); } ops.addAll(preparePoolHealthMonitorMappingUpdate(pair)); } zkManager.multi(ops); } @Override public List<HealthMonitor> healthMonitorsGetAll() throws StateAccessException, SerializationException { List<HealthMonitor> healthMonitors = new ArrayList<>(); String path = pathBuilder.getHealthMonitorsPath(); if (zkManager.exists(path)) { Set<String> healthMonitorIds = zkManager.getChildren(path); for (String id : healthMonitorIds) { HealthMonitor healthMonitor = healthMonitorGet(UUID.fromString(id)); if (healthMonitor != null) { healthMonitors.add(healthMonitor); } } } return healthMonitors; } @Override public List<Pool> healthMonitorGetPools(@Nonnull UUID id) throws StateAccessException, SerializationException { List<UUID> poolIds = healthMonitorZkManager.getPoolIds(id); List<Pool> pools = new ArrayList<>(poolIds.size()); for (UUID poolId : poolIds) { Pool pool = Converter.fromPoolConfig(poolZkManager.get(poolId)); pool.setId(poolId); pools.add(pool); } return pools; } /* pool member related methods */ private Pair<String, PoolHealthMonitorConfig> buildPoolHealthMonitorMappings(final UUID poolMemberId, final @Nonnull PoolMemberZkManager.PoolMemberConfig config, final boolean deletePoolMember) throws MappingStatusException, SerializationException, StateAccessException { UUID poolId = checkNotNull(config.poolId, "Pool ID is null."); PoolZkManager.PoolConfig poolConfig = poolZkManager.get(poolId); // Since we haven't deleted/updated this PoolMember in Zookeeper yet, // preparePoolHealthMonitorMappings() will get an outdated version of // this PoolMember when it fetches the Pool's members. The ConfigGetter // intercepts the request for this PoolMember and returns the updated // PoolMemberConfig, or null if it's been deleted. ConfigGetter<UUID, PoolMemberZkManager.PoolMemberConfig> configGetter = new ConfigGetter<UUID, PoolMemberZkManager.PoolMemberConfig>() { @Override public PoolMemberZkManager.PoolMemberConfig get(UUID key) throws StateAccessException, SerializationException { if (key.equals(poolMemberId)) { return deletePoolMember ? null : config; } return poolMemberZkManager.get(key); } }; return preparePoolHealthMonitorMappings(poolId, poolConfig, configGetter, vipZkManager); } private List<Op> buildPoolMappingStatusUpdate(PoolMemberZkManager.PoolMemberConfig poolMemberConfig) throws StateAccessException, SerializationException { UUID poolId = poolMemberConfig.poolId; PoolZkManager.PoolConfig poolConfig = poolZkManager.get(poolId); // Indicate the mapping is being updated. poolConfig.mappingStatus = PoolHealthMonitorMappingStatus.PENDING_UPDATE; return Arrays.asList(Op.setData(pathBuilder.getPoolPath(poolId), serializer.serialize(poolConfig), -1)); } @Override @CheckForNull public boolean poolMemberExists(UUID id) throws StateAccessException { return poolMemberZkManager.exists(id); } @Override @CheckForNull public PoolMember poolMemberGet(UUID id) throws StateAccessException, SerializationException { PoolMember poolMember = null; if (poolMemberZkManager.exists(id)) { poolMember = Converter.fromPoolMemberConfig(poolMemberZkManager.get(id)); poolMember.setId(id); } return poolMember; } @Override public void poolMemberDelete(UUID id) throws MappingStatusException, StateAccessException, SerializationException { List<Op> ops = new ArrayList<>(); PoolMemberZkManager.PoolMemberConfig config = poolMemberZkManager.get(id); if (config.poolId != null) { ops.addAll(poolZkManager.prepareRemoveMember(config.poolId, id)); } ops.addAll(poolMemberZkManager.prepareDelete(id)); // Pool-HealthMonitor mappings Pair<String, PoolHealthMonitorConfig> pair = buildPoolHealthMonitorMappings(id, config, true); ops.addAll(preparePoolHealthMonitorMappingUpdate(pair)); if (pair != null) { ops.addAll(buildPoolMappingStatusUpdate(config)); } zkManager.multi(ops); } @Override public UUID poolMemberCreate(@Nonnull PoolMember poolMember) throws MappingStatusException, StateAccessException, SerializationException { validatePoolConfigMappingStatus(poolMember.getPoolId()); if (poolMember.getId() == null) { poolMember.setId(UUID.randomUUID()); } UUID id = poolMember.getId(); PoolMemberZkManager.PoolMemberConfig config = Converter.toPoolMemberConfig(poolMember); List<Op> ops = new ArrayList<>(); ops.addAll(poolMemberZkManager.prepareCreate(id, config)); ops.addAll(poolZkManager.prepareAddMember(config.poolId, id)); // Flush the pool member create ops first zkManager.multi(ops); ops.clear(); Pair<String, PoolHealthMonitorConfig> pair = buildPoolHealthMonitorMappings(id, config, false); ops.addAll(preparePoolHealthMonitorMappingUpdate(pair)); if (pair != null) { ops.addAll(buildPoolMappingStatusUpdate(config)); } zkManager.multi(ops); return id; } @Override public void poolMemberUpdate(@Nonnull PoolMember poolMember) throws MappingStatusException, StateAccessException, SerializationException { validatePoolConfigMappingStatus(poolMember.getPoolId()); UUID id = poolMember.getId(); PoolMemberZkManager.PoolMemberConfig newConfig = Converter.toPoolMemberConfig(poolMember); PoolMemberZkManager.PoolMemberConfig oldConfig = poolMemberZkManager.get(id); boolean isPoolIdChanged = !com.google.common.base.Objects.equal(newConfig.poolId, oldConfig.poolId); if (newConfig.equals(oldConfig)) { return; } List<Op> ops = new ArrayList<>(); if (isPoolIdChanged) { ops.addAll(poolZkManager.prepareRemoveMember(oldConfig.poolId, id)); ops.addAll(poolZkManager.prepareAddMember(newConfig.poolId, id)); } ops.addAll(poolMemberZkManager.prepareUpdate(id, newConfig)); // Flush the update of the pool members first zkManager.multi(ops); ops.clear(); if (isPoolIdChanged) { // Remove pool member from its old owner's mapping node. Pair<String, PoolHealthMonitorConfig> oldPair = buildPoolHealthMonitorMappings(id, oldConfig, true); ops.addAll(preparePoolHealthMonitorMappingUpdate(oldPair)); } // Update the pool's pool-HM mapping with the new member. Pair<String, PoolHealthMonitorConfig> pair = buildPoolHealthMonitorMappings(id, newConfig, false); ops.addAll(preparePoolHealthMonitorMappingUpdate(pair)); if (pair != null) { ops.addAll(buildPoolMappingStatusUpdate(newConfig)); } zkManager.multi(ops); } @Override public void poolMemberUpdateStatus(UUID poolMemberId, LBStatus status) throws StateAccessException, SerializationException { PoolMemberZkManager.PoolMemberConfig config = poolMemberZkManager.get(poolMemberId); if (config == null) { log.error("pool member does not exist" + poolMemberId.toString()); return; } config.status = status; List<Op> ops = poolMemberZkManager.prepareUpdate(poolMemberId, config); zkManager.multi(ops); } @Override public List<PoolMember> poolMembersGetAll() throws StateAccessException, SerializationException { List<PoolMember> poolMembers = new ArrayList<>(); String path = pathBuilder.getPoolMembersPath(); if (zkManager.exists(path)) { Set<String> poolMemberIds = zkManager.getChildren(path); for (String id : poolMemberIds) { PoolMember poolMember = poolMemberGet(UUID.fromString(id)); if (poolMember != null) { poolMembers.add(poolMember); } } } return poolMembers; } /* pool related methods */ private List<Op> prepareDeletePoolHealthMonitorMappingOps(UUID poolId) throws SerializationException, StateAccessException { PoolZkManager.PoolConfig poolConfig = poolZkManager.get(poolId); List<Op> ops = new ArrayList<>(); if (poolConfig.healthMonitorId != null) { ops.add(Op.delete(pathBuilder.getPoolHealthMonitorMappingsPath(poolId, poolConfig.healthMonitorId), -1)); } return ops; } @Override @CheckForNull public Pool poolGet(UUID id) throws StateAccessException, SerializationException { Pool pool = null; if (poolZkManager.exists(id)) { pool = Converter.fromPoolConfig(poolZkManager.get(id)); pool.setId(id); } return pool; } private List<Op> buildPoolDeleteOps(UUID id) throws StateAccessException, SerializationException { List<Op> ops = new ArrayList<>(); PoolZkManager.PoolConfig config = poolZkManager.get(id); List<UUID> memberIds = poolZkManager.getMemberIds(id); for (UUID memberId : memberIds) { ops.addAll(poolZkManager.prepareRemoveMember(id, memberId)); ops.addAll(poolMemberZkManager.prepareDelete(memberId)); } List<UUID> vipIds = poolZkManager.getVipIds(id); for (UUID vipId : vipIds) { ops.addAll(poolZkManager.prepareRemoveVip(id, vipId)); ops.addAll(vipZkManager.prepareDelete(vipId)); ops.addAll(loadBalancerZkManager.prepareRemoveVip(config.loadBalancerId, vipId)); } if (config.healthMonitorId != null) { ops.addAll(healthMonitorZkManager.prepareRemovePool(config.healthMonitorId, id)); } ops.addAll(loadBalancerZkManager.prepareRemovePool(config.loadBalancerId, id)); ops.addAll(poolZkManager.prepareDelete(id)); return ops; } @Override public void poolDelete(UUID id) throws MappingStatusException, StateAccessException, SerializationException { List<Op> ops = buildPoolDeleteOps(id); // Pool-HealthMonitor mappings PoolZkManager.PoolConfig poolConfig = poolZkManager.get(id); validatePoolConfigMappingStatus(id); if (poolConfig.healthMonitorId != null) { ops.add(Op.delete(pathBuilder.getPoolHealthMonitorMappingsPath(id, poolConfig.healthMonitorId), -1)); } zkManager.multi(ops); } @Override public UUID poolCreate(@Nonnull Pool pool) throws MappingStatusException, StateAccessException, SerializationException { if (pool.getId() == null) { pool.setId(UUID.randomUUID()); } UUID id = pool.getId(); PoolZkManager.PoolConfig config = Converter.toPoolConfig(pool); List<Op> ops = new ArrayList<>(); ops.addAll(poolZkManager.prepareCreate(id, config)); if (config.loadBalancerId != null) { ops.addAll(loadBalancerZkManager.prepareAddPool(config.loadBalancerId, id)); } if (config.healthMonitorId != null) { ops.addAll(healthMonitorZkManager.prepareAddPool(config.healthMonitorId, id)); } // Flush the pool create ops first. zkManager.multi(ops); ops.clear(); // Pool-HealthMonitor mappings Pair<String, PoolHealthMonitorConfig> pair = preparePoolHealthMonitorMappings(id, config, poolMemberZkManager, vipZkManager); if (pair != null) { String mappingPath = pair.getLeft(); PoolHealthMonitorConfig mappingConfig = pair.getRight(); ops.add(Op.create(mappingPath, serializer.serialize(mappingConfig), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT)); config.mappingStatus = PoolHealthMonitorMappingStatus.PENDING_CREATE; ops.addAll(poolZkManager.prepareUpdate(id, config)); } zkManager.multi(ops); return id; } @Override public void poolUpdate(@Nonnull Pool pool) throws MappingStatusException, MappingViolationException, SerializationException, StateAccessException { UUID id = pool.getId(); PoolZkManager.PoolConfig newConfig = Converter.toPoolConfig(pool); PoolZkManager.PoolConfig oldConfig = poolZkManager.get(id); boolean isHealthMonitorChanged = !com.google.common.base.Objects.equal(newConfig.healthMonitorId, oldConfig.healthMonitorId); if (newConfig.equals(oldConfig)) { return; } // Set the internal status for the Pool-HealthMonitor mapping with the // previous value. newConfig.mappingStatus = oldConfig.mappingStatus; List<Op> ops = new ArrayList<>(); if (isHealthMonitorChanged) { if (oldConfig.healthMonitorId != null) { ops.addAll(healthMonitorZkManager.prepareRemovePool(oldConfig.healthMonitorId, id)); } if (newConfig.healthMonitorId != null) { ops.addAll(healthMonitorZkManager.prepareAddPool(newConfig.healthMonitorId, id)); } } if (!com.google.common.base.Objects.equal(oldConfig.loadBalancerId, newConfig.loadBalancerId)) { // Move the pool from the previous load balancer to the new one. ops.addAll(loadBalancerZkManager.prepareRemovePool(oldConfig.loadBalancerId, id)); ops.addAll(loadBalancerZkManager.prepareAddPool(newConfig.loadBalancerId, id)); // Move the VIPs belong to the pool from the previous load balancer // to the new one. List<UUID> vipIds = poolZkManager.getVipIds(id); for (UUID vipId : vipIds) { ops.addAll(loadBalancerZkManager.prepareRemoveVip(oldConfig.loadBalancerId, vipId)); ops.addAll(loadBalancerZkManager.prepareAddVip(newConfig.loadBalancerId, vipId)); VipZkManager.VipConfig vipConfig = vipZkManager.get(vipId); // Update the load balancer ID of the VIPs with the pool's one. vipConfig.loadBalancerId = newConfig.loadBalancerId; ops.addAll(vipZkManager.prepareUpdate(vipId, vipConfig)); } } // Pool-HealthMonitor mappings // If the reference to the health monitor is changed, the previous // entries are deleted and the new entries are created. if (isHealthMonitorChanged) { PoolZkManager.PoolConfig poolConfig = poolZkManager.get(id); // Indicate the mapping is being deleted and once it's confirmed // by the health monitor, it's replaced with INACTIVE. if (pool.getHealthMonitorId() == null) { validatePoolConfigMappingStatus(id); newConfig.mappingStatus = PoolHealthMonitorMappingStatus.PENDING_DELETE; // Delete the old entry ops.add(Op.delete(pathBuilder.getPoolHealthMonitorMappingsPath(id, poolConfig.healthMonitorId), -1)); } // Throws an exception if users try to update the health monitor ID // with another one even if the pool is already associated with // another health monitor. if (poolConfig.healthMonitorId != null && pool.getHealthMonitorId() != null) { throw new MappingViolationException(); } Pair<String, PoolHealthMonitorConfig> pair = preparePoolHealthMonitorMappings(id, newConfig, poolMemberZkManager, vipZkManager); if (pair != null) { String mappingPath = pair.getLeft(); PoolHealthMonitorConfig mappingConfig = pair.getRight(); ops.add(Op.create(mappingPath, serializer.serialize(mappingConfig), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT)); // Indicate the update is being processed and once it's confirmed // by the health monitor, it's replaced with ACTIVE. if (com.google.common.base.Objects.equal(oldConfig.mappingStatus, PoolHealthMonitorMappingStatus.INACTIVE)) { newConfig.mappingStatus = PoolHealthMonitorMappingStatus.PENDING_CREATE; } else { newConfig.mappingStatus = PoolHealthMonitorMappingStatus.PENDING_UPDATE; } } } ops.addAll(poolZkManager.prepareUpdate(id, newConfig)); zkManager.multi(ops); } @Override public List<Pool> poolsGetAll() throws StateAccessException, SerializationException { List<Pool> pools = new ArrayList<>(); String path = pathBuilder.getPoolsPath(); if (zkManager.exists(path)) { Set<String> poolIds = zkManager.getChildren(path); for (String id : poolIds) { Pool pool = poolGet(UUID.fromString(id)); if (pool != null) { pools.add(pool); } } } return pools; } @Override public List<PoolMember> poolGetMembers(@Nonnull UUID id) throws StateAccessException, SerializationException { List<UUID> memberIds = poolZkManager.getMemberIds(id); List<PoolMember> members = new ArrayList<>(memberIds.size()); for (UUID memberId : memberIds) { PoolMember member = Converter.fromPoolMemberConfig(poolMemberZkManager.get(memberId)); member.setId(memberId); members.add(member); } return members; } @Override public List<VIP> poolGetVips(@Nonnull UUID id) throws StateAccessException, SerializationException { List<UUID> vipIds = poolZkManager.getVipIds(id); List<VIP> vips = new ArrayList<>(vipIds.size()); for (UUID vipId : vipIds) { VIP vip = Converter.fromVipConfig(vipZkManager.get(vipId)); vip.setId(vipId); vips.add(vip); } return vips; } @Override public void poolSetMapStatus(UUID id, PoolHealthMonitorMappingStatus status) throws StateAccessException, SerializationException { PoolZkManager.PoolConfig pool = poolZkManager.get(id); if (pool == null) { return; } pool.mappingStatus = status; zkManager.multi(poolZkManager.prepareUpdate(id, pool)); } private Pair<String, PoolHealthMonitorConfig> buildPoolHealthMonitorMappings(final UUID vipId, final @Nonnull VipZkManager.VipConfig config, final boolean deleteVip) throws MappingStatusException, SerializationException, StateAccessException { UUID poolId = checkNotNull(config.poolId, "Pool ID is null."); PoolZkManager.PoolConfig poolConfig = poolZkManager.get(poolId); // Since we haven't deleted/updated this VIP in Zookeeper yet, // preparePoolHealthMonitorMappings() will get an outdated version of // this VIP when it fetches the Pool's vips. The ConfigGetter // intercepts the request for this VIP and returns the updated // VipConfig, or null if it's been deleted. ConfigGetter<UUID, VipZkManager.VipConfig> configGetter = new ConfigGetter<UUID, VipZkManager.VipConfig>() { @Override public VipZkManager.VipConfig get(UUID key) throws StateAccessException, SerializationException { if (key.equals(vipId)) { return deleteVip ? null : config; } return vipZkManager.get(key); } }; return preparePoolHealthMonitorMappings(poolId, poolConfig, poolMemberZkManager, configGetter); } private List<Op> buildPoolMappingStatusUpdate(VipZkManager.VipConfig vipConfig) throws StateAccessException, SerializationException { UUID poolId = vipConfig.poolId; PoolZkManager.PoolConfig poolConfig = poolZkManager.get(poolId); // Indicate the mapping is being updated. poolConfig.mappingStatus = PoolHealthMonitorMappingStatus.PENDING_UPDATE; return Arrays.asList(Op.setData(pathBuilder.getPoolPath(poolId), serializer.serialize(poolConfig), -1)); } @Override @CheckForNull public VIP vipGet(UUID id) throws StateAccessException, SerializationException { VIP vip = null; if (vipZkManager.exists(id)) { vip = Converter.fromVipConfig(vipZkManager.get(id)); vip.setId(id); } return vip; } @Override public void vipDelete(UUID id) throws MappingStatusException, StateAccessException, SerializationException { List<Op> ops = new ArrayList<>(); VipZkManager.VipConfig config = vipZkManager.get(id); if (config.loadBalancerId != null) { ops.addAll(loadBalancerZkManager.prepareRemoveVip(config.loadBalancerId, id)); } if (config.poolId != null) { ops.addAll(poolZkManager.prepareRemoveVip(config.poolId, id)); } ops.addAll(vipZkManager.prepareDelete(id)); // Pool-HealthMonitor mappings Pair<String, PoolHealthMonitorConfig> pair = buildPoolHealthMonitorMappings(id, config, true); ops.addAll(preparePoolHealthMonitorMappingUpdate(pair)); if (pair != null) { ops.addAll(buildPoolMappingStatusUpdate(config)); } zkManager.multi(ops); } @Override public UUID vipCreate(@Nonnull VIP vip) throws MappingStatusException, StateAccessException, SerializationException { validatePoolConfigMappingStatus(vip.getPoolId()); if (vip.getId() == null) { vip.setId(UUID.randomUUID()); } UUID id = vip.getId(); // Get the VipConfig and set its loadBalancerId from the PoolConfig. VipZkManager.VipConfig config = Converter.toVipConfig(vip); PoolZkManager.PoolConfig poolConfig = poolZkManager.get(config.poolId); config.loadBalancerId = poolConfig.loadBalancerId; List<Op> ops = new ArrayList<>(); ops.addAll(vipZkManager.prepareCreate(id, config)); ops.addAll(poolZkManager.prepareAddVip(config.poolId, id)); ops.addAll(loadBalancerZkManager.prepareAddVip(config.loadBalancerId, id)); // Flush the VIP first. zkManager.multi(ops); ops.clear(); // Pool-HealthMonitor mappings Pair<String, PoolHealthMonitorConfig> pair = buildPoolHealthMonitorMappings(id, config, false); ops.addAll(preparePoolHealthMonitorMappingUpdate(pair)); if (pair != null) { ops.addAll(buildPoolMappingStatusUpdate(config)); } zkManager.multi(ops); return id; } @Override public void vipUpdate(@Nonnull VIP vip) throws MappingStatusException, StateAccessException, SerializationException { validatePoolConfigMappingStatus(vip.getPoolId()); // See if new config is different from old config. UUID id = vip.getId(); VipZkManager.VipConfig newConfig = Converter.toVipConfig(vip); VipZkManager.VipConfig oldConfig = vipZkManager.get(id); // User can't set loadBalancerId directly because we get it from // from the pool indicated by poolId. newConfig.loadBalancerId = oldConfig.loadBalancerId; if (newConfig.equals(oldConfig)) { return; } List<Op> ops = new ArrayList<>(); boolean poolIdChanged = !com.google.common.base.Objects.equal(newConfig.poolId, oldConfig.poolId); if (poolIdChanged) { ops.addAll(poolZkManager.prepareRemoveVip(oldConfig.poolId, id)); ops.addAll(loadBalancerZkManager.prepareRemoveVip(oldConfig.loadBalancerId, id)); PoolZkManager.PoolConfig newPoolConfig = poolZkManager.get(newConfig.poolId); newConfig.loadBalancerId = newPoolConfig.loadBalancerId; ops.addAll(poolZkManager.prepareAddVip(newConfig.poolId, id)); ops.addAll(loadBalancerZkManager.prepareAddVip(newPoolConfig.loadBalancerId, id)); } ops.addAll(vipZkManager.prepareUpdate(id, newConfig)); zkManager.multi(ops); ops.clear(); if (poolIdChanged) { // Remove the VIP from the old pool-HM mapping. Pair<String, PoolHealthMonitorConfig> oldPair = buildPoolHealthMonitorMappings(id, oldConfig, true); ops.addAll(preparePoolHealthMonitorMappingUpdate(oldPair)); } // Update the appropriate pool-HM mapping with the new VIP config. Pair<String, PoolHealthMonitorConfig> pair = buildPoolHealthMonitorMappings(id, newConfig, false); ops.addAll(preparePoolHealthMonitorMappingUpdate(pair)); if (pair != null) { ops.addAll(buildPoolMappingStatusUpdate(newConfig)); } zkManager.multi(ops); } @Override public List<VIP> vipGetAll() throws StateAccessException, SerializationException { List<VIP> vips = new ArrayList<>(); String path = pathBuilder.getVipsPath(); if (zkManager.exists(path)) { Set<String> vipIds = zkManager.getChildren(path); for (String id : vipIds) { VIP vip = vipGet(UUID.fromString(id)); if (vip != null) { vips.add(vip); } } } return vips; } @Override public Integer hostsGetFloodingProxyWeight(UUID hostId, Watcher watcher) throws StateAccessException, SerializationException { return hostZkManager.getFloodingProxyWeight(hostId, watcher); } @Override public @CheckForNull Route routesGet(UUID id) throws StateAccessException, SerializationException { log.debug("Entered: id={}", id); Route route = null; if (routeZkManager.exists(id)) { route = Converter.fromRouteConfig(routeZkManager.get(id)); route.setId(id); } log.debug("Exiting: route={}", route); return route; } @Override public void routesDelete(UUID id) throws StateAccessException, SerializationException { routeZkManager.delete(id); } @Override public UUID routesCreate(@Nonnull Route route) throws StateAccessException, SerializationException { return routeZkManager.create(Converter.toRouteConfig(route)); } @Override public UUID routesCreateEphemeral(@Nonnull Route route) throws StateAccessException, SerializationException { return routeZkManager.create(Converter.toRouteConfig(route), false); } @Override public List<Route> routesFindByRouter(UUID routerId) throws StateAccessException, SerializationException { List<UUID> routeIds = routeZkManager.list(routerId); List<Route> routes = new ArrayList<>(); for (UUID id : routeIds) { routes.add(routesGet(id)); } return routes; } @Override public boolean routerExists(UUID id) throws StateAccessException { return routerZkManager.exists(id); } @Override public List<Router> routersGetAll() throws StateAccessException, SerializationException { log.debug("routersGetAll entered"); List<Router> routers = new ArrayList<>(); String path = pathBuilder.getRoutersPath(); if (zkManager.exists(path)) { Set<String> routerIds = zkManager.getChildren(path); for (String id : routerIds) { Router router = routersGet(UUID.fromString(id)); if (router != null) { routers.add(router); } } } log.debug("routersGetAll exiting: {} routers found", routers.size()); return routers; } @Override public @CheckForNull Router routersGet(UUID id) throws StateAccessException, SerializationException { log.debug("Entered: id={}", id); Router router = null; if (routerZkManager.exists(id)) { router = Converter.fromRouterConfig(routerZkManager.get(id)); router.setId(id); } log.debug("Exiting: router={}", router); return router; } @Override public void routersDelete(UUID id) throws StateAccessException, SerializationException { Router router = routersGet(id); if (router == null) { return; } List<Op> ops = routerZkManager.prepareRouterDelete(id); zkManager.multi(ops); } @Override public UUID routersCreate(@Nonnull Router router) throws StateAccessException, SerializationException { log.debug("routersCreate entered: router={}", router); if (router.getId() == null) { router.setId(UUID.randomUUID()); } RouterZkManager.RouterConfig routerConfig = Converter.toRouterConfig(router); List<Op> ops = routerZkManager.prepareRouterCreate(router.getId(), routerConfig); // Create the top level directories String tenantId = router.getProperty(Router.Property.tenant_id); if (!Strings.isNullOrEmpty(tenantId)) { ops.addAll(tenantZkManager.prepareCreate(tenantId)); } zkManager.multi(ops); log.debug("routersCreate ex.ing: router={}", router); return router.getId(); } @Override public void routersUpdate(@Nonnull Router router) throws StateAccessException, SerializationException { // Get the original data Router oldRouter = routersGet(router.getId()); RouterZkManager.RouterConfig routerConfig = Converter.toRouterConfig(router); List<Op> ops = new ArrayList<>(); // Update the config ops.addAll(routerZkManager.prepareUpdate(router.getId(), routerConfig)); if (!ops.isEmpty()) { zkManager.multi(ops); } } @Override public List<Router> routersFindByTenant(String tenantId) throws StateAccessException, SerializationException { log.debug("routersFindByTenant entered: tenantId={}", tenantId); List<Router> routers = routersGetAll(); for (Iterator<Router> it = routers.iterator(); it.hasNext();) { if (!it.next().hasTenantId(tenantId)) { it.remove(); } } log.debug("routersFindByTenant exiting: {} routers found", routers.size()); return routers; } @Override public @CheckForNull Rule<?, ?> rulesGet(UUID id) throws StateAccessException, SerializationException { log.debug("Entered: id={}", id); Rule<?, ?> rule = null; if (ruleZkManager.exists(id)) { rule = Converter.fromRuleConfig(ruleZkManager.get(id)); rule.setId(id); // Find position of rule in chain RuleList ruleList = ruleZkManager.getRuleList(rule.getChainId()); int position = ruleList.getRuleList().indexOf(id) + 1; rule.setPosition(position); } log.debug("Exiting: rule={}", rule); return rule; } @Override public void rulesDelete(UUID id) throws StateAccessException, SerializationException { ruleZkManager.delete(id); } @Override public UUID rulesCreate(@Nonnull Rule<?, ?> rule) throws StateAccessException, RuleIndexOutOfBoundsException, SerializationException { return ruleZkManager.create(Converter.toRuleConfig(rule), rule.getPosition()); } @Override public List<Rule<?, ?>> rulesFindByChain(UUID chainId) throws StateAccessException, SerializationException { List<UUID> ruleIds = ruleZkManager.getRuleList(chainId).getRuleList(); List<Rule<?, ?>> rules = new ArrayList<>(); int position = 1; for (UUID id : ruleIds) { Rule<?, ?> rule = rulesGet(id); rule.setPosition(position); position++; rules.add(rule); } return rules; } /** * Gets all the tenants stored in the data store. * * @return Set containing tenant IDs * @throws StateAccessException */ @Override public Set<String> tenantsGetAll() throws StateAccessException { return tenantZkManager.list(); } /** * Get the current write version. * * @return current write version. */ public WriteVersion writeVersionGet() throws StateAccessException { WriteVersion writeVersion = new WriteVersion(); String version = systemDataProvider.getWriteVersion(); writeVersion.setVersion(version); return writeVersion; } /** * Overwrites the current write version with the string supplied * @param newVersion The new version to set the write version to. */ public void writeVersionUpdate(WriteVersion newVersion) throws StateAccessException { systemDataProvider.setWriteVersion(newVersion.getVersion()); } /** * Get the system state info. * * @return System State info. * @throws StateAccessException */ public SystemState systemStateGet() throws StateAccessException { SystemState systemState = new SystemState(); boolean upgrade = systemDataProvider.systemUpgradeStateExists(); boolean readonly = systemDataProvider.configReadOnly(); String writeVersion = systemDataProvider.getWriteVersion(); systemState.setState(upgrade ? SystemState.State.UPGRADE.toString() : SystemState.State.ACTIVE.toString()); systemState.setAvailability(readonly ? SystemState.Availability.READONLY.toString() : SystemState.Availability.READWRITE.toString()); systemState.setWriteVersion(writeVersion); return systemState; } /** * Update the system state info. * * @param systemState the new system state * @throws StateAccessException */ public void systemStateUpdate(SystemState systemState) throws StateAccessException { systemDataProvider.setOperationState(systemState.getState()); systemDataProvider.setConfigState(systemState.getAvailability()); systemDataProvider.setWriteVersion(systemState.getWriteVersion()); } /** * Get the Host Version info * * @return A list containing HostVersion objects, each of which * contains version information about a specific host. * @throws StateAccessException */ public List<HostVersion> hostVersionsGet() throws StateAccessException { List<HostVersion> hostVersionList = new ArrayList<>(); List<String> versions = systemDataProvider.getVersionsInDeployment(); for (String version : versions) { List<String> hosts = systemDataProvider.getHostsWithVersion(version); for (String host : hosts) { HostVersion hostVersion = new HostVersion(); hostVersion.setHostId(UUID.fromString(host)); hostVersion.setVersion(version); hostVersionList.add(hostVersion); } } return hostVersionList; } @Override public Integer getPrecedingHealthMonitorLeader(Integer myNode) throws StateAccessException { String path = pathBuilder.getHealthMonitorLeaderDirPath(); Set<String> set = zkManager.getChildren(path); String seqNumPath = ZkUtil.getNextLowerSequenceNumberPath(set, myNode); return seqNumPath == null ? null : ZkUtil.getSequenceNumberFromPath(seqNumPath); } @Override public Integer registerAsHealthMonitorNode(ZkLeaderElectionWatcher.ExecuteOnBecomingLeader cb) throws StateAccessException { String path = pathBuilder.getHealthMonitorLeaderDirPath(); return ZkLeaderElectionWatcher.registerLeaderNode(cb, path, zkManager); } @Override public void removeHealthMonitorLeaderNode(Integer node) throws StateAccessException { if (node == null) return; String path = pathBuilder.getHealthMonitorLeaderDirPath() + "/" + StringUtils.repeat("0", 10 - node.toString().length()) + node.toString(); zkManager.delete(path); } @Override public void vtepCreate(VTEP vtep) throws StateAccessException, SerializationException { VtepZkManager.VtepConfig config = Converter.toVtepConfig(vtep); zkManager.multi(vtepZkManager.prepareCreate(vtep.getId(), config)); } @Override public VTEP vtepGet(IPv4Addr ipAddr) throws StateAccessException, SerializationException { if (!vtepZkManager.exists(ipAddr)) return null; VTEP vtep = Converter.fromVtepConfig(vtepZkManager.get(ipAddr)); vtep.setId(ipAddr); return vtep; } @Override public List<VTEP> vtepsGetAll() throws StateAccessException, SerializationException { List<VTEP> vteps = new ArrayList<>(); String path = pathBuilder.getVtepsPath(); if (zkManager.exists(path)) { Set<String> vtepIps = zkManager.getChildren(path); for (String vtepIp : vtepIps) { VTEP vtep = vtepGet(IPv4Addr.fromString(vtepIp)); if (vtep != null) { vteps.add(vtep); } } } return vteps; } @Override public void vtepDelete(IPv4Addr ipAddr) throws StateAccessException, SerializationException { List<Op> deleteNoOwner = new ArrayList<>(vtepZkManager.prepareDelete(ipAddr)); List<Op> deleteOwner = new ArrayList<>(vtepZkManager.prepareDeleteOwner(ipAddr)); deleteOwner.addAll(deleteNoOwner); try { zkManager.multi(deleteOwner); } catch (NoStatePathException e) { zkManager.multi(deleteNoOwner); } } @Override public void vtepUpdate(VTEP vtep) throws StateAccessException, SerializationException { VtepZkManager.VtepConfig config = Converter.toVtepConfig(vtep); zkManager.multi(vtepZkManager.prepareUpdate(vtep.getId(), config)); } @Override public void vtepAddBinding(@Nonnull IPv4Addr ipAddr, @Nonnull String portName, short vlanId, @Nonnull UUID networkId) throws StateAccessException { zkManager.multi(vtepZkManager.prepareCreateBinding(ipAddr, portName, vlanId, networkId)); } @Override public void vtepDeleteBinding(@Nonnull IPv4Addr ipAddr, @Nonnull String portName, short vlanId) throws StateAccessException { zkManager.multi(vtepZkManager.prepareDeleteBinding(ipAddr, portName, vlanId)); } @Override public List<VtepBinding> vtepGetBindings(@Nonnull IPv4Addr ipAddr) throws StateAccessException { return vtepZkManager.getBindings(ipAddr); } @Override public List<VtepBinding> bridgeGetVtepBindings(@Nonnull UUID bridgeId) throws StateAccessException, SerializationException { List<VtepBinding> bindings = new ArrayList<>(); Bridge br = bridgesGet(bridgeId); if ((br == null) || (br.getVxLanPortId() == null)) { return bindings; } VxLanPort vxLanPort = (VxLanPort) portsGet(br.getVxLanPortId()); if (vxLanPort == null) { return bindings; } List<VtepBinding> all = vtepZkManager.getBindings(vxLanPort.getMgmtIpAddr()); for (VtepBinding b : all) { if (b.getNetworkId().equals(bridgeId)) { bindings.add(b); } } return bindings; } @Override public VtepBinding vtepGetBinding(@Nonnull IPv4Addr ipAddr, @Nonnull String portName, short vlanId) throws StateAccessException { return vtepZkManager.getBinding(ipAddr, portName, vlanId); } @Override public EntityMonitor<IPv4Addr, VtepZkManager.VtepConfig, VTEP> vtepsGetMonitor( ZookeeperConnectionWatcher zkConnection) { return new EntityMonitor<>(vtepZkManager, zkConnection, new EntityMonitor.Transformer<IPv4Addr, VtepZkManager.VtepConfig, VTEP>() { @Override public VTEP transform(IPv4Addr ipAddr, VtepZkManager.VtepConfig data) { VTEP vtep = Converter.fromVtepConfig(data); vtep.setId(ipAddr); return vtep; } }); } @Override public EntityIdSetMonitor<IPv4Addr> vtepsGetAllSetMonitor(ZookeeperConnectionWatcher zkConnection) throws StateAccessException { return new EntityIdSetMonitor<>(vtepZkManager, zkConnection); } @Override public int getNewVni() throws StateAccessException { return vtepZkManager.getNewVni(); } @Override public IPv4Addr vxlanTunnelEndpointFor(UUID id) throws SerializationException, StateAccessException { BridgePort port = (BridgePort) portsGet(id); if (port == null) { return null; } if (!port.isExterior()) { throw new IllegalArgumentException("Port " + port.getId() + " is " + "not exterior"); } Bridge b = bridgesGet(port.getDeviceId()); if (null == b) { log.warn("Bridge {} for port {} does not exist anymore", port.getDeviceId(), port.getId()); return null; } return vxlanTunnelEndpointForInternal(b, port); } /* * Utility method to use internaly. It assumes that the caller has verified * that both the bridge and port are non-null. * It's convenient to slice this out so other methods can fetch the * parameters as they prefer, and then use this to retrieve the vxlan * tunnel endpoint. The method returns a null IP if the endpoint cannot * be retrieved for any reason (bridge unbound, etc.) * * @param b a bridge, expected to exist, be bound to a VTEP, and contain the * given port * @param port a bridge port on the given bridge, that must be exterior * @return the IP address of the bound host's membership in the VTEP's * tunnel zone. */ private IPv4Addr vxlanTunnelEndpointForInternal(Bridge b, BridgePort port) throws SerializationException, StateAccessException { if (b.getVxLanPortId() == null) { log.warn("Bridge {} is not bound to a vtep", b.getId()); return null; } VxLanPort vxlanPort = (VxLanPort) this.portsGet(b.getVxLanPortId()); if (vxlanPort == null) { log.warn("VxLanPort {} at bridge {} does not exist anymore", b.getVxLanPortId(), b.getId()); return null; } IPv4Addr vtepMgmtIp = vxlanPort.getMgmtIpAddr(); log.debug("Port's bridge {} has a VxLanPort {}", port.getId(), vxlanPort.getId()); // We will need the host where the given BridgePort is bound UUID hostId = port.getHostId(); if (hostId == null) { log.error("Port {} is not bound to a host", port.getId()); return null; } // Let's get the tunnel zone this host should be in, and get the IP of // the host in that tunnel zone. VTEP vtep = vtepGet(vtepMgmtIp); if (vtep == null) { log.warn("Vtep {} bound to bridge {} does not exist anymore", vtepMgmtIp, b.getId()); return null; } UUID tzId = vtep.getTunnelZoneId(); TunnelZone.HostConfig hostCfg = this.tunnelZonesGetMembership(tzId, hostId); if (hostCfg == null) { log.error( "Port {} on bridge {} bount to an interface in host {} " + "was expected to belong to tunnel zone {} through " + "binding to VTEP {}", port.getId(), b.getId(), hostId, tzId, vtepMgmtIp); return null; } return hostCfg.getIp(); } @Override public VxLanPort bridgeCreateVxLanPort(UUID bridgeId, IPv4Addr mgmtIp, int mgmtPort, int vni, IPv4Addr tunnelIp, UUID tunnelZoneId) throws StateAccessException, SerializationException { BridgeConfig bridgeConfig = bridgeZkManager.get(bridgeId); if (bridgeConfig.vxLanPortId != null) { throw new IllegalStateException("Attempted to create VxLanPort for bridge " + bridgeId + ", which already has one: " + bridgeConfig.vxLanPortId); } VxLanPort port = new VxLanPort(bridgeId, mgmtIp, mgmtPort, vni, tunnelIp, tunnelZoneId); PortConfig portConfig = Converter.toPortConfig(port); List<Op> ops = new ArrayList<>(); ops.addAll(portZkManager.prepareCreate(port.getId(), portConfig)); bridgeConfig.vxLanPortId = port.getId(); ops.addAll(bridgeZkManager.prepareUpdate(bridgeId, bridgeConfig)); zkManager.multi(ops); return port; } @Override public void bridgeDeleteVxLanPort(UUID bridgeId) throws SerializationException, StateAccessException { // Make sure the bridge has a VXLAN port. BridgeConfig bridgeConfig = bridgeZkManager.get(bridgeId); UUID vxLanPortId = bridgeConfig.vxLanPortId; if (vxLanPortId == null) { throw new IllegalStateException( "Attempted to delete VxLanPort for bridge " + bridgeId + ", which has no VxLanPort."); } List<Op> ops = new ArrayList<>(); // Clear bridge's vxLanPortId property. bridgeConfig.vxLanPortId = null; ops.addAll(bridgeZkManager.prepareUpdate(bridgeId, bridgeConfig)); // Delete the port. VxLanPortConfig portConfig = (VxLanPortConfig) portZkManager.get(vxLanPortId); ops.addAll(portZkManager.prepareDelete(vxLanPortId)); // Delete its bindings in Zookeeper. ops.addAll(vtepZkManager.prepareDeleteAllBindings(IPv4Addr.fromString(portConfig.mgmtIpAddr), portConfig.device_id)); zkManager.multi(ops); } @Override public UUID tryOwnVtep(IPv4Addr mgmtIp, UUID ownerId) throws SerializationException, StateAccessException { return vtepZkManager.tryOwnVtep(mgmtIp, ownerId); } @Override public UUID tryOwnVtep(IPv4Addr mgmtIp, UUID ownerId, Watcher watcher) throws SerializationException, StateAccessException { return vtepZkManager.tryOwnVtep(mgmtIp, ownerId, watcher); } @Override public boolean deleteVtepOwner(IPv4Addr mgmtIp, UUID ownerId) throws SerializationException, StateAccessException { return vtepZkManager.deleteVtepOwner(mgmtIp, ownerId); } @Override public boolean portWatch(UUID portId, Directory.TypedWatcher typedWatcher) throws StateAccessException, SerializationException { try { return null != portZkManager.get(portId, typedWatcher); } catch (NoStatePathException e) { return false; } } @Override public void vxLanPortIdsAsyncGet(DirectoryCallback<Set<UUID>> callback, Directory.TypedWatcher watcher) throws StateAccessException { portZkManager.getVxLanPortIdsAsync(callback, watcher); } @Override public Ip4ToMacReplicatedMap getIp4MacMap(UUID bridgeId) throws StateAccessException { return new Ip4ToMacReplicatedMap(bridgeZkManager.getIP4MacMapDirectory(bridgeId)); } }