2 * Copyright (c) 2015 NEC Corporation. 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
9 package org.opendaylight.vtn.manager.internal.config;
11 import java.net.NetworkInterface;
12 import java.util.Enumeration;
14 import java.util.TreeMap;
15 import java.util.concurrent.TimeoutException;
16 import java.util.concurrent.atomic.AtomicReference;
18 import org.slf4j.Logger;
19 import org.slf4j.LoggerFactory;
21 import org.opendaylight.vtn.manager.VTNException;
22 import org.opendaylight.vtn.manager.util.EtherAddress;
24 import org.opendaylight.vtn.manager.internal.TxContext;
25 import org.opendaylight.vtn.manager.internal.VTNConfig;
26 import org.opendaylight.vtn.manager.internal.VTNManagerProvider;
27 import org.opendaylight.vtn.manager.internal.util.DataStoreUtils;
28 import org.opendaylight.vtn.manager.internal.util.XmlConfigFile;
29 import org.opendaylight.vtn.manager.internal.util.concurrent.VTNFuture;
30 import org.opendaylight.vtn.manager.internal.util.tx.AbstractTxTask;
31 import org.opendaylight.vtn.manager.internal.util.tx.TxQueueImpl;
33 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
34 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
35 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
37 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.config.rev150209.VtnConfig;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.config.rev150209.VtnConfigBuilder;
43 * VTN global configuration manager.
45 public final class VTNConfigManager implements AutoCloseable, VTNConfig {
49 private static final Logger LOG =
50 LoggerFactory.getLogger(VTNConfigManager.class);
53 * Instance identifier of the global configuration.
55 static final InstanceIdentifier<VtnConfig> CONFIG_IDENT =
56 InstanceIdentifier.create(VtnConfig.class);
59 * The key associated with the global configuration file.
61 static final String KEY_VTN_CONFIG = "vtn-config";
64 * The current configuration.
66 private final AtomicReference<VTNConfigImpl> current;
69 * A MD-SAL datastore transaction queue for the global configuration.
71 private final AtomicReference<TxQueueImpl> configQueue =
72 new AtomicReference<TxQueueImpl>();
75 * Listener of VTN configuration for configuration view.
77 private final AtomicReference<ConfigListener> confListener =
78 new AtomicReference<ConfigListener>();
81 * Listener of VTN configuration for operational view.
83 private final AtomicReference<OperationalListener> operListener =
84 new AtomicReference<OperationalListener>();
87 * Set true if the local node is configuration provider.
89 private boolean configProvider;
92 * MD-SAL transaction task for initialization of VTN configuration data.
95 * This task returns the current value of "init-state".
98 private static final class ConfigInitTask extends AbstractTxTask<Boolean> {
100 * MAC address of the local node.
102 private final EtherAddress macAddress;
105 * A {@link VTNConfigImpl} instance to be saved into file.
107 private VTNConfigImpl saveConfig;
110 * Construct a new instance.
112 * @param mac MAC address of the local node.
114 private ConfigInitTask(EtherAddress mac) {
122 public Boolean execute(TxContext ctx) throws VTNException {
125 // Read current VTN configuration in configuration view.
126 LogicalDatastoreType cstore = LogicalDatastoreType.CONFIGURATION;
127 ReadWriteTransaction tx = ctx.getReadWriteTransaction();
129 DataStoreUtils.read(tx, cstore, CONFIG_IDENT).orNull();
131 // Try to load configuration from file.
132 VTNConfigImpl vconf = XmlConfigFile.load(
133 XmlConfigFile.Type.CONFIG, KEY_VTN_CONFIG,
134 VTNConfigImpl.class);
136 vcfg = vconf.getJaxbValue().build();
137 tx.put(cstore, CONFIG_IDENT, vcfg, true);
140 // Save current configuration into file.
141 saveConfig = new VTNConfigImpl(vcfg);
144 // Read current VTN configuration in operational view.
146 LogicalDatastoreType ostore = LogicalDatastoreType.OPERATIONAL;
147 VtnConfig voper = DataStoreUtils.read(tx, ostore, CONFIG_IDENT).
150 // Initialize operational view.
151 VtnConfigBuilder builder =
152 VTNConfigImpl.builder(vcfg, macAddress);
154 // Set false to init-state to notify that the configuration
156 builder.setInitState(Boolean.FALSE);
157 tx.put(ostore, CONFIG_IDENT, builder.build(), true);
160 ret = voper.isInitState();
170 public void onSuccess(VTNManagerProvider provider, Boolean result) {
171 if (saveConfig != null) {
172 XmlConfigFile.save(XmlConfigFile.Type.CONFIG, KEY_VTN_CONFIG,
179 * MD-SAL transaction task to change "init-state" to true.
181 private static class ConfigInitDoneTask extends AbstractTxTask<Void> {
186 public Void execute(TxContext ctx) throws VTNException {
187 ReadWriteTransaction tx = ctx.getReadWriteTransaction();
188 LogicalDatastoreType ostore = LogicalDatastoreType.OPERATIONAL;
189 VtnConfigBuilder builder = new VtnConfigBuilder();
190 builder.setInitState(Boolean.TRUE);
191 tx.merge(ostore, CONFIG_IDENT, builder.build(), true);
199 public void onSuccess(VTNManagerProvider provider, Void result) {
200 LOG.info("VTN configuration has been initialized.");
205 * Determine the MAC address of the local controller.
207 * @return An {@link EtherAddress} which represents the MAC address of
208 * the controller. {@code null} on failure.
210 static EtherAddress getLocalMacAddress() {
211 Enumeration<NetworkInterface> nifs = null;
213 nifs = NetworkInterface.getNetworkInterfaces();
214 } catch (Exception e) {
215 LOG.warn("Failed to get network interfaces.", e);
219 EtherAddress ea = getMacAddress(nifs);
221 LOG.warn("No network interface was found.");
228 * Get a MAC address configured in the given interface.
230 * @param nifs An enumeration of {@link NetworkInterface} instances.
231 * @return An {@link EtherAddress} which represents the MAC address of
232 * the controller. {@code null} on failure.
234 private static EtherAddress getMacAddress(
235 Enumeration<NetworkInterface> nifs) {
240 // Sort interfaces by index.
241 // This code expects that lower index is assigned to physical network
243 Map<Integer, NetworkInterface> niMap = new TreeMap<>();
244 while (nifs.hasMoreElements()) {
245 NetworkInterface nif = nifs.nextElement();
246 niMap.put(nif.getIndex(), nif);
249 NetworkInterface altIf = null;
250 EtherAddress altAddr = null;
251 for (NetworkInterface nif: niMap.values()) {
253 if (nif.isLoopback() || nif.isVirtual() ||
254 nif.isPointToPoint()) {
258 byte[] mac = nif.getHardwareAddress();
263 EtherAddress ea = new EtherAddress(mac);
265 LOG.debug("Use HW address of {} as local address: {}",
266 nif.getName(), ea.getText());
274 } catch (Exception e) {
275 LOG.debug("Ignore network interface: " + nif.getName(), e);
279 if (altAddr != null) {
280 LOG.debug("Use inactive HW address of {} as local address: ",
281 altIf.getName(), altAddr.getText());
289 * Construct a new instance.
291 * @param provider A VTN Manager provider service.
293 public VTNConfigManager(VTNManagerProvider provider) {
294 XmlConfigFile.init();
296 // Determine MAC address of the local node.
297 EtherAddress ea = getLocalMacAddress();
298 VTNConfigImpl vconf = new VTNConfigImpl(ea);
300 ea = vconf.getControllerMacAddress();
301 LOG.warn("Use custom MAC address as local address: {}",
304 LOG.info("Local MAC address: {}", ea.getText());
306 current = new AtomicReference<VTNConfigImpl>(vconf);
309 initialize(provider, ea);
310 } catch (RuntimeException e) {
311 LOG.error("Failed to initialize VTN config manager.", e);
318 * Complete the initialization of global configuration.
320 public void initDone() {
321 if (configProvider) {
322 TxQueueImpl cfq = configQueue.get();
324 // Change init-state to true.
325 ConfigInitDoneTask task = new ConfigInitDoneTask();
332 * Determine whether the local node is the configuration provider or not.
334 * @return {@code true} if the local node is the configuration provider.
335 * Otherwise {@code false}.
337 public boolean isConfigProvider() {
338 return configProvider;
344 * Close the configuration service.
347 public void close() {
348 ConfigListener cfg = confListener.getAndSet(null);
353 OperationalListener op = operListener.getAndSet(null);
358 TxQueueImpl cfq = configQueue.getAndSet(null);
365 * Initialize the VTN configuration.
367 * @param provider A VTN Manager provider service.
368 * @param mac MAC address of the local node.
370 private void initialize(VTNManagerProvider provider, EtherAddress mac) {
371 DataBroker broker = provider.getDataBroker();
372 TxQueueImpl cfq = new TxQueueImpl("VTN Config", provider);
373 configQueue.set(cfq);
374 confListener.set(new ConfigListener(cfq, broker, mac));
375 OperationalListener opl = new OperationalListener(broker, current);
376 operListener.set(opl);
378 // Post initialization task.
379 ConfigInitTask task = new ConfigInitTask(mac);
380 VTNFuture<Boolean> f = cfq.postFirst(task);
382 // Start transaction queue processing.
385 // Wait for the initialization task to complete.
388 initState = f.checkedGet();
389 } catch (Exception e) {
390 String msg = "Failed to initialize global configuration.";
392 throw new IllegalStateException(msg, e);
395 if (initState == null) {
396 LOG.debug("The local node is configuration provider.");
397 configProvider = true;
401 // We need to wait for another controller in the cluster to complete
403 long millis = current.get().getInitTimeout();
405 opl.awaitConfig(millis);
406 } catch (InterruptedException e) {
407 String msg = "Initialization thread was interrupted.";
409 throw new IllegalStateException(msg, e);
410 } catch (TimeoutException e) {
411 LOG.warn("Initialization did not complete within {} milliseconds.",
413 configProvider = true;
423 public int getTopologyWait() {
424 return current.get().getTopologyWait();
431 public int getL2FlowPriority() {
432 return current.get().getL2FlowPriority();
439 public int getFlowModTimeout() {
440 return current.get().getFlowModTimeout();
447 public int getBulkFlowModTimeout() {
448 return current.get().getBulkFlowModTimeout();
455 public int getInitTimeout() {
456 return current.get().getInitTimeout();
463 public int getMaxRedirections() {
464 return current.get().getMaxRedirections();
471 public EtherAddress getControllerMacAddress() {
472 return current.get().getControllerMacAddress();