2 * Copyright (c) 2017 Hewlett Packard Enterprise, Co. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.netvirt.dhcpservice;
10 import java.util.ArrayList;
11 import java.util.Collections;
12 import java.util.EventListener;
13 import java.util.List;
15 import java.util.Optional;
16 import java.util.concurrent.ExecutionException;
17 import java.util.concurrent.Future;
18 import java.util.stream.Collectors;
19 import javax.annotation.PostConstruct;
20 import javax.annotation.PreDestroy;
21 import javax.inject.Inject;
22 import javax.inject.Singleton;
23 import org.eclipse.jdt.annotation.NonNull;
24 import org.eclipse.jdt.annotation.Nullable;
25 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
26 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
27 import org.opendaylight.infrautils.utils.concurrent.LoggingFutures;
28 import org.opendaylight.mdsal.binding.api.DataBroker;
29 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
30 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInput;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInputBuilder;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdOutput;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolInput;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolInputBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolOutput;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.DeleteIdPoolInput;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.DeleteIdPoolInputBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.DeleteIdPoolOutput;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdInput;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdInputBuilder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.dhcp_allocation_pool.rev161214.DhcpAllocationPool;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.dhcp_allocation_pool.rev161214.dhcp_allocation_pool.Network;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.dhcp_allocation_pool.rev161214.dhcp_allocation_pool.NetworkKey;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.dhcp_allocation_pool.rev161214.dhcp_allocation_pool.network.AllocationPool;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanDpnInterfaces;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanInterfaces;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.dpn.interfaces.ElanDpnInterfacesList;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.dpn.interfaces.ElanDpnInterfacesListKey;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.dpn.interfaces.elan.dpn.interfaces.list.DpnInterfaces;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterface;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterfaceKey;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.dhcpservice.config.rev150710.DhcpserviceConfig;
55 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
56 import org.opendaylight.yangtools.yang.common.RpcResult;
57 import org.opendaylight.yangtools.yang.common.Uint64;
58 import org.slf4j.Logger;
59 import org.slf4j.LoggerFactory;
62 public class DhcpAllocationPoolManager implements AutoCloseable, EventListener {
63 private static final Logger LOG = LoggerFactory.getLogger(DhcpAllocationPoolManager.class);
65 private DhcpAllocationPoolListener dhcpAllocationPoolListener;
67 private final DataBroker dataBroker;
68 private final IdManagerService idManager;
69 private final DhcpserviceConfig config;
70 private final JobCoordinator jobCoordinator;
73 public DhcpAllocationPoolManager(final DataBroker dataBroker, final IdManagerService idManager,
74 final DhcpserviceConfig config, final JobCoordinator jobCoordinator) {
75 this.dataBroker = dataBroker;
76 this.idManager = idManager;
78 this.jobCoordinator = jobCoordinator;
83 if (config.isDhcpDynamicAllocationPoolEnabled()) {
84 dhcpAllocationPoolListener = new DhcpAllocationPoolListener(this, dataBroker, jobCoordinator);
85 LOG.info("DHCP Allocation Pool Service initialized");
92 LOG.info("{} close", getClass().getSimpleName());
93 if (dhcpAllocationPoolListener != null) {
94 dhcpAllocationPoolListener.close();
99 public IpAddress getIpAllocation(String networkId, AllocationPool pool, String macAddress) {
100 String poolIdKey = getPoolKeyIdByAllocationPool(networkId, pool);
101 long allocatedIpLong = createIdAllocation(poolIdKey, macAddress);
102 LOG.debug("allocated id {} for mac {}, from pool {}", allocatedIpLong, macAddress, poolIdKey);
103 return allocatedIpLong != 0 ? DhcpServiceUtils.convertLongToIp(allocatedIpLong) : null;
106 public void releaseIpAllocation(String networkId, AllocationPool pool, String macAddress) {
107 String poolIdKey = getPoolKeyIdByAllocationPool(networkId, pool);
108 LOG.debug("going to release id for mac {}, from pool {}", macAddress, poolIdKey);
109 releaseIdAllocation(poolIdKey, macAddress);
113 public AllocationPool getAllocationPoolByNetwork(String networkId) throws ExecutionException, InterruptedException {
114 InstanceIdentifier<Network> network = InstanceIdentifier.builder(DhcpAllocationPool.class)
115 .child(Network.class, new NetworkKey(networkId)).build();
116 Optional<Network> optionalNetworkConfData = SingleTransactionDataBroker.syncReadOptional(dataBroker,
117 LogicalDatastoreType.CONFIGURATION, network);
118 if (!optionalNetworkConfData.isPresent()) {
119 LOG.info("No network configuration data for network {}", networkId);
122 Network networkConfData = optionalNetworkConfData.get();
123 List<AllocationPool> allocationPoolList = new ArrayList<>(networkConfData.nonnullAllocationPool().values());
124 // if network has allocation pool list - get the first element
125 // as we have no info about a specific subnet
126 if (allocationPoolList != null && !allocationPoolList.isEmpty()) {
127 return allocationPoolList.get(0);
129 LOG.warn("No allocation pools for network {}", networkId);
135 public Map<Uint64, List<String>> getElanDpnInterfacesByName(DataBroker broker, String elanInstanceName) {
136 InstanceIdentifier<ElanDpnInterfacesList> elanDpnIfacesIid = InstanceIdentifier.builder(ElanDpnInterfaces.class)
137 .child(ElanDpnInterfacesList.class, new ElanDpnInterfacesListKey(elanInstanceName)).build();
138 Optional<ElanDpnInterfacesList> elanDpnIfacesOpc;
140 elanDpnIfacesOpc = SingleTransactionDataBroker.syncReadOptional(broker, LogicalDatastoreType.OPERATIONAL,
142 } catch (ExecutionException | InterruptedException e) {
143 LOG.error("getElanDpnInterfacesByName: Exception while reading the ElanDpnInterfacesList DS for the "
144 + "elan-instance {}", elanInstanceName, e);
145 return Collections.emptyMap();
147 if (!elanDpnIfacesOpc.isPresent()) {
148 LOG.warn("Could not find DpnInterfaces for elan {}", elanInstanceName);
149 return Collections.emptyMap();
152 return elanDpnIfacesOpc.get().nonnullDpnInterfaces().values() == null
153 ? Collections.<Uint64, List<String>>emptyMap()
154 : elanDpnIfacesOpc.get().nonnullDpnInterfaces().values().stream()
155 .collect(Collectors.toMap(DpnInterfaces::getDpId,
156 value -> value.getInterfaces() != null ? value.getInterfaces() : Collections.emptyList()));
160 public String getNetworkByPort(String portUuid) throws ExecutionException, InterruptedException {
161 InstanceIdentifier<ElanInterface> elanInterfaceName = InstanceIdentifier.builder(ElanInterfaces.class)
162 .child(ElanInterface.class, new ElanInterfaceKey(portUuid)).build();
163 Optional<ElanInterface> optionalElanInterface = SingleTransactionDataBroker.syncReadOptional(dataBroker,
164 LogicalDatastoreType.CONFIGURATION, elanInterfaceName);
165 if (!optionalElanInterface.isPresent()) {
166 LOG.info("No elan interface data for port {}", portUuid);
169 ElanInterface elanInterface = optionalElanInterface.get();
170 return elanInterface.getElanInstanceName();
173 private static String getPoolKeyIdByAllocationPool(String networkId, AllocationPool pool) {
174 return "dhcpAllocationPool." + networkId + "." + pool.getSubnet().stringValue();
177 private long createIdAllocation(String groupIdKey, String idKey) {
178 AllocateIdInput getIdInput = new AllocateIdInputBuilder().setPoolName(groupIdKey).setIdKey(idKey).build();
180 Future<RpcResult<AllocateIdOutput>> result = idManager.allocateId(getIdInput);
181 RpcResult<AllocateIdOutput> rpcResult = result.get();
182 return rpcResult.getResult().getIdValue().toJava();
183 } catch (NullPointerException | InterruptedException | ExecutionException e) {
184 LOG.trace("Failed to allocate id for DHCP Allocation Pool Service", e);
189 private void releaseIdAllocation(String groupIdKey, String idKey) {
190 ReleaseIdInput getIdInput = new ReleaseIdInputBuilder().setPoolName(groupIdKey).setIdKey(idKey).build();
191 LoggingFutures.addErrorLogging(idManager.releaseId(getIdInput), LOG, "Release Id");
194 protected void createIdAllocationPool(String networkId, AllocationPool pool) {
195 String poolName = getPoolKeyIdByAllocationPool(networkId, pool);
196 long low = DhcpServiceUtils.convertIpToLong(pool.getAllocateFrom());
197 long high = DhcpServiceUtils.convertIpToLong(pool.getAllocateTo());
198 CreateIdPoolInput createPool = new CreateIdPoolInputBuilder().setPoolName(poolName).setLow(low).setHigh(high)
201 Future<RpcResult<CreateIdPoolOutput>> result = idManager.createIdPool(createPool);
202 if (result != null && result.get().isSuccessful()) {
203 LOG.info("DHCP Allocation Pool Service : Created IdPool name {}", poolName);
205 LOG.error("DHCP Allocation Pool Service : Unable to create IdPool name {}", poolName);
207 } catch (InterruptedException | ExecutionException e) {
208 LOG.error("Failed to create Pool for DHCP Allocation Pool Service", e);
212 protected void releaseIdAllocationPool(String networkId, AllocationPool pool) {
213 String poolName = getPoolKeyIdByAllocationPool(networkId, pool);
214 DeleteIdPoolInput deletePool = new DeleteIdPoolInputBuilder().setPoolName(poolName).build();
216 Future<RpcResult<DeleteIdPoolOutput>> result = idManager.deleteIdPool(deletePool);
217 if (result != null && result.get().isSuccessful()) {
218 LOG.info("DHCP Allocation Pool Service : Deleted IdPool name {}", poolName);
220 LOG.error("DHCP Allocation Pool Service : Unable to delete IdPool name {}", poolName);
222 } catch (InterruptedException | ExecutionException e) {
223 LOG.error("Failed to delete Pool for DHCP Allocation Pool Service", e);