3 * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
5 * This program and the accompanying materials are made available under the
6 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
7 * and is available at http://www.eclipse.org/legal/epl-v10.html
10 package org.opendaylight.controller.configuration.internal;
13 import java.util.ArrayList;
14 import java.util.Collections;
15 import java.util.Dictionary;
16 import java.util.EnumSet;
17 import java.util.HashSet;
18 import java.util.List;
20 import java.util.concurrent.ConcurrentMap;
22 import org.apache.felix.dm.Component;
23 import org.opendaylight.controller.clustering.services.CacheConfigException;
24 import org.opendaylight.controller.clustering.services.CacheExistException;
25 import org.opendaylight.controller.clustering.services.ICacheUpdateAware;
26 import org.opendaylight.controller.clustering.services.IClusterContainerServices;
27 import org.opendaylight.controller.clustering.services.IClusterServices;
28 import org.opendaylight.controller.configuration.ConfigurationEvent;
29 import org.opendaylight.controller.configuration.ConfigurationObject;
30 import org.opendaylight.controller.configuration.IConfigurationAware;
31 import org.opendaylight.controller.configuration.IConfigurationContainerAware;
32 import org.opendaylight.controller.configuration.IConfigurationContainerService;
33 import org.opendaylight.controller.sal.utils.GlobalConstants;
34 import org.opendaylight.controller.sal.utils.IObjectReader;
35 import org.opendaylight.controller.sal.utils.ObjectReader;
36 import org.opendaylight.controller.sal.utils.ObjectWriter;
37 import org.opendaylight.controller.sal.utils.Status;
38 import org.opendaylight.controller.sal.utils.StatusCode;
39 import org.slf4j.Logger;
40 import org.slf4j.LoggerFactory;
43 * @file ConfigurationImpl.java
45 * @brief Backend functionality for all ConfigurationService related tasks.
49 public class ContainerConfigurationService implements IConfigurationContainerService,
51 ICacheUpdateAware<String, String> {
52 public static final String CONTAINER_SAVE_EVENT_CACHE = "config.container.event.save";
53 private static final Logger logger = LoggerFactory.getLogger(ContainerConfigurationService.class);
54 private IClusterContainerServices clusterServices;
55 private ConcurrentMap<String, String> containerConfigEvent;
56 // Directory which contains the startup files for this container
58 private Set<IConfigurationContainerAware> configurationAwareList = Collections
59 .synchronizedSet(new HashSet<IConfigurationContainerAware>());
60 private ObjectReader objReader;
61 private ObjectWriter objWriter;
62 private String containerName;
64 public void addConfigurationContainerAware(
65 IConfigurationContainerAware configurationAware) {
66 if (!this.configurationAwareList.contains(configurationAware)) {
67 this.configurationAwareList.add(configurationAware);
71 public int getConfigurationAwareListSize() {
72 return this.configurationAwareList.size();
75 public void removeConfigurationContainerAware(
76 IConfigurationContainerAware configurationAware) {
77 this.configurationAwareList.remove(configurationAware);
80 public void setClusterServices(IClusterContainerServices i) {
81 this.clusterServices = i;
82 logger.debug("IClusterServices set");
85 public void unsetClusterServices(IClusterContainerServices i) {
86 if (this.clusterServices == i) {
87 this.clusterServices = null;
88 logger.debug("IClusterServices Unset");
92 void init(Component c) {
93 Dictionary<?, ?> props = c.getServiceProperties();
94 containerName = (props != null) ? (String) props.get("containerName") :
95 GlobalConstants.DEFAULT.toString();
96 root = String.format("%s%s/", GlobalConstants.STARTUPHOME.toString(), containerName);
102 objReader = new ObjectReader();
103 objWriter = new ObjectWriter();
106 public void destroy() {
107 // Clear local states
108 this.configurationAwareList.clear();
112 * Function called by the dependency manager before Container is Stopped and Destroyed.
114 public void containerStop() {
119 public String getConfigurationRoot() {
124 public Status saveConfiguration() {
125 boolean success = true;
127 for (IConfigurationContainerAware configurationAware : configurationAwareList) {
128 logger.trace("Save Config triggered for {}", configurationAware.getClass().getSimpleName());
130 Status status = configurationAware.saveConfiguration();
131 if (!status.isSuccess()) {
133 logger.warn("Failed to save config for {} ({})", configurationAware.getClass().getSimpleName(),
134 status.getDescription());
138 return new Status(StatusCode.SUCCESS);
140 return new Status(StatusCode.INTERNALERROR, "Failed to save one or more configurations");
145 public Status saveConfigurations() {
146 containerConfigEvent.put(ConfigurationEvent.SAVE.toString(), "");
147 return saveConfiguration();
151 public void entryCreated(String key, String cacheName,
152 boolean originLocal) {
159 public void entryUpdated(String key, String new_value,
160 String cacheName, boolean originLocal) {
164 logger.debug("Processing {} event", key);
165 if (key.equals(ConfigurationEvent.SAVE.toString())) {
171 public void entryDeleted(String key, String cacheName,
172 boolean originLocal) {
178 private void allocateCache() {
179 if (this.clusterServices == null) {
180 logger.error("uninitialized clusterServices, can't create cache");
184 this.clusterServices.createCache(CONTAINER_SAVE_EVENT_CACHE,
185 EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
186 } catch (CacheConfigException cce) {
187 logger.debug("Error creating ContainerConfigurationService cache ", cce);
188 } catch (CacheExistException cce) {
189 logger.debug("ConfigurationService Cache already exists, destroy and recreate ", cce);
193 @SuppressWarnings({ "unchecked" })
194 private void retrieveCache() {
195 if (this.clusterServices == null) {
196 logger.error("uninitialized clusterServices, can't retrieve cache");
199 containerConfigEvent =
200 (ConcurrentMap<String, String>) this.clusterServices.getCache(CONTAINER_SAVE_EVENT_CACHE);
201 if (containerConfigEvent == null) {
202 logger.error("Failed to retrieve configuration Cache");
207 public Status persistConfiguration(List<ConfigurationObject> config, String fileName) {
208 if (!hasBeenSaved()) {
209 return new Status(StatusCode.NOTALLOWED,
210 String.format("Container %s has not been saved yet", containerName));
212 String destination = String.format("%s%s", root, fileName);
213 return objWriter.write(config, destination);
217 public List<ConfigurationObject> retrieveConfiguration(IObjectReader reader, String fileName) {
218 if (!clusterServices.amICoordinator()) {
219 return Collections.emptyList();
221 String source = String.format("%s%s", root, fileName);
222 Object obj = objReader.read(reader, source);
224 return Collections.<ConfigurationObject> emptyList();
226 if (obj instanceof ConcurrentMap) {
227 return new ArrayList<ConfigurationObject>(((ConcurrentMap)obj).values());
229 return (List<ConfigurationObject>) obj;
233 public boolean hasBeenSaved() {
235 File configRoot = new File(this.getConfigurationRoot());
236 return configRoot.exists();
237 } catch (Exception e) {