c33fdefd7b4a87b9da85548054e7936cbfdccb9f
[controller.git] / opendaylight / configuration / implementation / src / main / java / org / opendaylight / controller / configuration / internal / ContainerConfigurationService.java
1
2 /*
3  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
4  *
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
8  */
9
10 package org.opendaylight.controller.configuration.internal;
11
12 import java.io.File;
13 import java.util.Collections;
14 import java.util.Dictionary;
15 import java.util.EnumSet;
16 import java.util.HashSet;
17 import java.util.List;
18 import java.util.Set;
19 import java.util.concurrent.ConcurrentMap;
20
21 import org.apache.felix.dm.Component;
22 import org.opendaylight.controller.clustering.services.CacheConfigException;
23 import org.opendaylight.controller.clustering.services.CacheExistException;
24 import org.opendaylight.controller.clustering.services.ICacheUpdateAware;
25 import org.opendaylight.controller.clustering.services.IClusterContainerServices;
26 import org.opendaylight.controller.clustering.services.IClusterServices;
27 import org.opendaylight.controller.configuration.ConfigurationEvent;
28 import org.opendaylight.controller.configuration.ConfigurationObject;
29 import org.opendaylight.controller.configuration.IConfigurationAware;
30 import org.opendaylight.controller.configuration.IConfigurationContainerAware;
31 import org.opendaylight.controller.configuration.IConfigurationContainerService;
32 import org.opendaylight.controller.sal.utils.GlobalConstants;
33 import org.opendaylight.controller.sal.utils.IObjectReader;
34 import org.opendaylight.controller.sal.utils.ObjectReader;
35 import org.opendaylight.controller.sal.utils.ObjectWriter;
36 import org.opendaylight.controller.sal.utils.Status;
37 import org.opendaylight.controller.sal.utils.StatusCode;
38 import org.slf4j.Logger;
39 import org.slf4j.LoggerFactory;
40
41 /**
42  * @file   ConfigurationImpl.java
43  *
44  * @brief  Backend functionality for all ConfigurationService related tasks.
45  *
46  */
47
48 public class ContainerConfigurationService implements IConfigurationContainerService,
49         IConfigurationAware, ICacheUpdateAware<ConfigurationEvent, String> {
50     public static final String CONTAINER_SAVE_EVENT_CACHE = "config.container.event.save";
51     private static final Logger logger = LoggerFactory.getLogger(ContainerConfigurationService.class);
52     private IClusterContainerServices clusterServices;
53     private ConcurrentMap <ConfigurationEvent, String> containerConfigEvent;
54     /*
55      * Collection containing the configuration objects.
56      * This is configuration world: container names (also the map key)
57      * are maintained as they were configured by user, same case
58      */
59     private Set<IConfigurationContainerAware> configurationAwareList = Collections
60             .synchronizedSet(new HashSet<IConfigurationContainerAware>());
61     private String root;
62     private ObjectReader objReader;
63     private ObjectWriter objWriter;
64
65     public void addConfigurationContainerAware(
66             IConfigurationContainerAware configurationAware) {
67         if (!this.configurationAwareList.contains(configurationAware)) {
68             this.configurationAwareList.add(configurationAware);
69         }
70     }
71
72     public int getConfigurationAwareListSize() {
73         return this.configurationAwareList.size();
74     }
75
76     public void removeConfigurationContainerAware(
77             IConfigurationContainerAware configurationAware) {
78         this.configurationAwareList.remove(configurationAware);
79     }
80
81     public void setClusterServices(IClusterContainerServices i) {
82         this.clusterServices = i;
83         logger.debug("IClusterServices set");
84     }
85
86     public void unsetClusterServices(IClusterContainerServices i) {
87         if (this.clusterServices == i) {
88             this.clusterServices = null;
89             logger.debug("IClusterServices Unset");
90         }
91     }
92
93     void init(Component c) {
94         Dictionary<?, ?> props = c.getServiceProperties();
95         String containerName = (props != null) ? (String) props.get("containerName") : GlobalConstants.DEFAULT.toString();
96         root = String.format("%s%s/", GlobalConstants.STARTUPHOME.toString(), containerName);
97         if (!new File(root).exists()) {
98             boolean created = new File(root).mkdir();
99             if (!created) {
100                 logger.error("Failed to create startup config directory for container {}", containerName);
101             }
102         }
103     }
104
105     public void start() {
106         allocateCache();
107         retrieveCache();
108         objReader = new ObjectReader();
109         objWriter = new ObjectWriter();
110     }
111
112     public void destroy() {
113         // Clear local states
114         this.configurationAwareList.clear();
115     }
116
117     /**
118      * Function called by the dependency manager before Container is Stopped and Destroyed.
119      */
120     public void containerStop() {
121         // Remove container directory along with its startup files
122         File[] files = new File(root).listFiles();
123         for (File file : files) {
124             file.delete();
125         }
126         new File(root).delete();
127     }
128
129     @Override
130     public Status saveConfiguration() {
131         boolean success = true;
132         for (IConfigurationContainerAware configurationAware : configurationAwareList) {
133             logger.trace("Save Config triggered for {}", configurationAware.getClass().getSimpleName());
134
135             Status status = configurationAware.saveConfiguration();
136             if (!status.isSuccess()) {
137                 success = false;
138                 logger.warn("Failed to save config for {}", configurationAware.getClass().getSimpleName());
139             }
140         }
141         if (success) {
142             return new Status(StatusCode.SUCCESS);
143         } else {
144             return new Status(StatusCode.INTERNALERROR, "Failed to Save All Configurations");
145         }
146     }
147
148     @Override
149     public Status saveConfigurations() {
150         containerConfigEvent.put(ConfigurationEvent.SAVE, "");
151         return saveConfiguration();
152     }
153
154     @Override
155     public void entryCreated(ConfigurationEvent key, String cacheName,
156             boolean originLocal) {
157         if (originLocal) {
158             return;
159         }
160     }
161
162     @Override
163     public void entryUpdated(ConfigurationEvent key, String new_value,
164             String cacheName, boolean originLocal) {
165         if (originLocal) {
166             return;
167         }
168         logger.debug("Processing {} event", key);
169         if (key == ConfigurationEvent.SAVE) {
170             saveConfiguration();
171         }
172     }
173
174     @Override
175     public void entryDeleted(ConfigurationEvent key, String cacheName,
176             boolean originLocal) {
177         if (originLocal) {
178             return;
179         }
180     }
181
182     private void allocateCache() {
183         if (this.clusterServices == null) {
184             logger.error("uninitialized clusterServices, can't create cache");
185             return;
186         }
187         try {
188             this.clusterServices.createCache(CONTAINER_SAVE_EVENT_CACHE,
189                     EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
190         } catch (CacheConfigException cce) {
191             logger.debug("Error creating ContainerConfigurationService cache ", cce);
192         } catch (CacheExistException cce) {
193             logger.debug("ConfigurationService Cache already exists, destroy and recreate ", cce);
194         }
195     }
196
197     @SuppressWarnings({ "unchecked" })
198     private void retrieveCache() {
199         if (this.clusterServices == null) {
200             logger.error("uninitialized clusterServices, can't retrieve cache");
201             return;
202         }
203         containerConfigEvent = (ConcurrentMap<ConfigurationEvent, String>) this.clusterServices.getCache(CONTAINER_SAVE_EVENT_CACHE);
204         if (containerConfigEvent == null) {
205             logger.error("Failed to retrieve configuration Cache");
206         }
207     }
208
209     @Override
210     public Status persistConfiguration(List<ConfigurationObject> config, String fileName) {
211         String destination = String.format("%s%s", root, fileName);
212         return objWriter.write(config, destination);
213     }
214
215     @Override
216     public List<ConfigurationObject> retrieveConfiguration(IObjectReader reader, String fileName) {
217         if (!clusterServices.amICoordinator()) {
218             return Collections.emptyList();
219         }
220         String source = String.format("%s%s", root, fileName);
221         Object obj = objReader.read(reader, source);
222         return (obj == null || !(obj instanceof List)) ? Collections.<ConfigurationObject> emptyList()
223                 : (List<ConfigurationObject>) obj;
224     }
225 }