Separating renderers into features.
[groupbasedpolicy.git] / renderers / oc / src / main / java / org / opendaylight / groupbasedpolicy / renderer / oc / L2DomainManager.java
1 /*
2  * Copyright (c) 2015 Juniper Networks, Inc.  All rights reserved.
3  *
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
7  */
8
9 package org.opendaylight.groupbasedpolicy.renderer.oc;
10
11 import java.io.IOException;
12 import java.net.HttpURLConnection;
13 import java.util.List;
14 import java.util.Map;
15 import java.util.Map.Entry;
16 import java.util.UUID;
17 import java.util.concurrent.CopyOnWriteArrayList;
18 import java.util.concurrent.ScheduledExecutorService;
19
20 import net.juniper.contrail.api.ApiConnector;
21 import net.juniper.contrail.api.types.Project;
22 import net.juniper.contrail.api.types.VirtualNetwork;
23
24 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
25 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
26 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
27 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
28 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
29 import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.Tenants;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.Tenant;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.L2FloodDomain;
33 import org.opendaylight.yangtools.concepts.ListenerRegistration;
34 import org.opendaylight.yangtools.yang.binding.DataObject;
35 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
36 import org.slf4j.Logger;
37 import org.slf4j.LoggerFactory;
38
39
40 public class L2DomainManager implements AutoCloseable, DataChangeListener {
41         private static final Logger LOG = LoggerFactory
42                         .getLogger(L2DomainManager.class);
43         static ApiConnector apiConnector;
44         private static final InstanceIdentifier<Tenant> TenantIid = InstanceIdentifier
45                         .builder(Tenants.class).child(Tenant.class).build();
46         private ListenerRegistration<DataChangeListener> listenerReg;
47
48         private final DataBroker dataProvider;
49         private List<L2DomainListener> listeners = new CopyOnWriteArrayList<>();
50
51         public L2DomainManager(DataBroker dataProvider,
52                         RpcProviderRegistry rpcRegistry, ScheduledExecutorService executor) {
53
54                 super();
55                 this.dataProvider = dataProvider;
56                 if (dataProvider != null) {
57                         listenerReg = dataProvider.registerDataChangeListener(
58                                         LogicalDatastoreType.CONFIGURATION, TenantIid, this,
59                                         DataChangeScope.ONE);
60                 } else
61                         listenerReg = null;
62
63                 LOG.debug("Initialized L2 Domain manager");
64         }
65
66     public void registerListener(L2DomainListener listener) {
67         listeners.add(listener);
68     }
69
70         // ******************
71         // DataChangeListener
72         // ******************
73
74         @Override
75         public void onDataChanged(
76                         AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
77                 for (DataObject dao : change.getCreatedData().values()) {
78                         if (dao instanceof Tenant)
79                         try {
80                                 createL2FloodDomain((Tenant)dao);
81                         } catch (IOException e) {
82                                 // TODO Auto-generated catch block
83                                 e.printStackTrace();
84                         }
85                 }
86                 Map<InstanceIdentifier<?>,DataObject> d = change.getUpdatedData();
87         for (Entry<InstanceIdentifier<?>, DataObject> entry : d.entrySet()) {
88             if (!(entry.getValue() instanceof Tenant)) continue;
89             DataObject old = change.getOriginalData().get(entry.getKey());
90             Tenant olddata = null;
91             if (old != null && old instanceof Tenant)
92                 olddata = (Tenant)old;
93                 try {
94                         updateL2FloodDomain(olddata, (Tenant)entry.getValue());
95                         } catch (IOException e) {
96                                 // TODO Auto-generated catch block
97                                 e.printStackTrace();
98                         }
99         }
100         }
101
102         @Override
103         public void close() throws Exception {
104                 // TODO Auto-generated method stub
105         }
106
107          /**
108      * Invoked when a L2FloodDomain create is requested
109      *
110      *@param  tenant
111      *                An instance of tenant data
112      */
113
114         public void createL2FloodDomain(Tenant tenant) throws IOException{
115                 String tenantID = tenant.getId().toString();
116                 if (tenant.getL2FloodDomain() != null){
117                         for(L2FloodDomain l2FloodDomain : tenant.getL2FloodDomain()) {
118                                 canCreateFloodDomain(l2FloodDomain, tenantID);
119                                 createFloodDomain(l2FloodDomain, tenantID);
120                         }
121                 }
122         }
123
124          /**
125      * Invoked when a L2FloodDomain create is requested to indicate if the specified
126      * L2FloodDomain can be created using the specified delta.
127      *
128      *@param  l2FloodDomain
129      *                An instance of l2FloodDomain
130      *@param  tenantid
131      *                Tenant id
132      */
133
134         public int canCreateFloodDomain(L2FloodDomain l2FloodDomain, String tenantID) {
135         apiConnector = OcRenderer.apiConnector;
136
137         if (l2FloodDomain.getId() == null || l2FloodDomain.getName() == null
138                         || l2FloodDomain.getId().equals("") || l2FloodDomain.getName().equals("")) {
139             LOG.error("l2FloodDomain id or name can't be null/empty...");
140             return HttpURLConnection.HTTP_BAD_REQUEST;
141         }
142
143         try {
144             String l2FloodDomainUUID = Utils.uuidNameFormat(l2FloodDomain.getId().toString());
145             String projectUUID = Utils.uuidNameFormat(tenantID);
146             try {
147                 if (!(l2FloodDomainUUID.contains("-"))) {
148                         l2FloodDomainUUID = Utils.uuidFormater(l2FloodDomainUUID);
149                 }
150                 if (!(projectUUID.contains("-"))) {
151                     projectUUID = Utils.uuidFormater(projectUUID);
152                 }
153                 boolean isValidl2FloodDomainUUID = Utils.isValidHexNumber(l2FloodDomainUUID);
154                 boolean isValidprojectUUID = Utils.isValidHexNumber(projectUUID);
155                 if (!isValidl2FloodDomainUUID || !isValidprojectUUID) {
156                     LOG.info("Badly formed Hexadecimal UUID...");
157                     return HttpURLConnection.HTTP_BAD_REQUEST;
158                 }
159                 projectUUID = UUID.fromString(projectUUID).toString();
160                 l2FloodDomainUUID = UUID.fromString(l2FloodDomainUUID).toString();
161             } catch (Exception ex) {
162                 LOG.error("UUID input incorrect", ex);
163                 return HttpURLConnection.HTTP_BAD_REQUEST;
164             }
165
166             Project project = (Project) apiConnector.findById(Project.class, projectUUID);
167             if (project == null) {
168                 try {
169                     Thread.currentThread();
170                     Thread.sleep(3000);
171                 } catch (InterruptedException e) {
172                     LOG.error("InterruptedException :    ", e);
173                     return HttpURLConnection.HTTP_BAD_REQUEST;
174                 }
175                project = (Project) apiConnector.findById(Project.class, projectUUID);
176                 if (project == null) {
177                     LOG.error("Could not find projectUUID...");
178                     return HttpURLConnection.HTTP_NOT_FOUND;
179                 }
180            }
181            VirtualNetwork virtualNetworkById = (VirtualNetwork) apiConnector.findById(VirtualNetwork.class, l2FloodDomainUUID);
182             if (virtualNetworkById != null) {
183                 LOG.warn("l2FloodDomain already exists with UUID" + l2FloodDomainUUID);
184                 return HttpURLConnection.HTTP_FORBIDDEN;
185             }
186             return HttpURLConnection.HTTP_OK;
187         } catch (Exception e) {
188             LOG.error("Exception :   " + e);
189             return HttpURLConnection.HTTP_INTERNAL_ERROR;
190         }
191     }
192
193     /**
194      * Invoked to create the specified L2FloodDomain.
195      *
196      * @param L2FloodDomain
197      *            An instance of new L2FloodDomain object.
198      *
199      * @param  tenantid
200      *            Tenant id
201      */
202     private void createFloodDomain(L2FloodDomain l2FloodDomain, String tenantid) throws IOException {
203         VirtualNetwork virtualNetwork = new VirtualNetwork();
204         virtualNetwork = mapNetworkProperties(l2FloodDomain, virtualNetwork, tenantid);
205         boolean l2FloodDomainCreated;
206         try {
207                 l2FloodDomainCreated = apiConnector.create(virtualNetwork);
208             if (!l2FloodDomainCreated) {
209                 LOG.warn("l2FloodDomain creation failed..");
210             }
211         } catch (IOException ioEx) {
212             LOG.error("Exception : " + ioEx);
213         }
214         LOG.info("l2FloodDomain : " + virtualNetwork.getName() + "  having UUID : " + virtualNetwork.getUuid() + "  sucessfully created...");
215     }
216
217     /**
218      * Invoked to map the L2FloodDomain object properties to the virtualNetwork
219      * object.
220      *
221      * @param L2FloodDomain
222      *            An instance of L2FloodDomain object.
223      * @param virtualNetwork
224      *            An instance of new virtualNetwork object.
225      *
226      * @param tenantid
227      *            tenant id
228      * @return {@link VirtualNetwork}
229      */
230     private VirtualNetwork mapNetworkProperties(L2FloodDomain l2FloodDomain, VirtualNetwork virtualNetwork, String tenantid) {
231         String l2FloodDomainUUID = Utils.uuidNameFormat(l2FloodDomain.getId().toString());
232         String projectUUID = Utils.uuidNameFormat(tenantid);
233         String l2FloodDomainName = Utils.uuidNameFormat(l2FloodDomain.getName().toString());
234         try {
235             if (!(l2FloodDomainUUID.contains("-"))) {
236                 l2FloodDomainUUID = Utils.uuidFormater(l2FloodDomainUUID);
237             }
238             l2FloodDomainUUID = UUID.fromString(l2FloodDomainUUID).toString();
239             if (!(projectUUID.contains("-"))) {
240                 projectUUID = Utils.uuidFormater(projectUUID);
241             }
242             projectUUID = UUID.fromString(projectUUID).toString();
243             Project project = (Project) apiConnector.findById(Project.class, projectUUID);
244             virtualNetwork.setParent(project);
245         } catch (Exception ex) {
246             LOG.error("UUID input incorrect", ex);
247         }
248         virtualNetwork.setName(l2FloodDomainName);
249         virtualNetwork.setUuid(l2FloodDomainUUID);
250         virtualNetwork.setDisplayName(l2FloodDomainName);
251         return virtualNetwork;
252     }
253
254     /**
255      * Invoked when a L2FloodDomain update is requested
256      *
257      *@param  oldData
258      *                An instance of Old tenant data
259      *@param  newData
260      *                An instance of New tenant data
261      */
262
263     public void updateL2FloodDomain(Tenant oldData, Tenant newData) throws IOException{
264                 String tenantID = newData.getId().toString();
265                 if (newData.getL2FloodDomain() != null){
266                         if(oldData.getL2FloodDomain() == null){
267                                 for(L2FloodDomain l2FloodDomain : newData.getL2FloodDomain()) {
268                                         canCreateFloodDomain(l2FloodDomain, tenantID);
269                                         createFloodDomain(l2FloodDomain, tenantID);
270                                 }
271                         }
272                         else {
273                                 for(L2FloodDomain l2FloodDomainNew : newData.getL2FloodDomain()) {
274                                         for(L2FloodDomain l2FloodDomainOld : oldData.getL2FloodDomain()) {
275                                                 String l2FloodDomainNewId = Utils.uuidNameFormat(l2FloodDomainNew.getId().toString());
276                                                 String l2FloodDomainOldId = Utils.uuidNameFormat(l2FloodDomainOld.getId().toString());
277                                                 if(l2FloodDomainNewId.equals(l2FloodDomainOldId)){
278                                                         canUpdateFloodDomain(l2FloodDomainNew, l2FloodDomainOld, tenantID);
279                                                         updateFloodDomain(l2FloodDomainNew, tenantID);
280                                                 }
281                                                 else{
282                                                         canCreateFloodDomain(l2FloodDomainNew, tenantID);
283                                                         createFloodDomain(l2FloodDomainNew, tenantID);
284                                                 }
285                                         }
286                                 }
287                         }
288                 }
289         }
290
291     /**
292      * Invoked when a L2FloodDomain update is requested to indicate if the specified
293      * L2FloodDomain can be changed using the specified delta.
294      *
295      *@param  l2FloodDomainNew
296      *                An instance of updated l2FloodDomain
297      *@param  l2FloodDomainOld
298      *                An instance of old l2FloodDomain
299      *@param  tenantid
300      *                Tenant id
301      */
302
303     public int canUpdateFloodDomain(L2FloodDomain l2FloodDomainNew, L2FloodDomain l2FloodDomainOld, String tenantID ) {
304         VirtualNetwork virtualnetwork;
305         apiConnector = OcRenderer.apiConnector;
306
307         String l2FloodDomainUUID = Utils.uuidNameFormat(l2FloodDomainOld.getId().toString());
308         String projectUUID = Utils.uuidNameFormat(tenantID);
309         try {
310             if (!(l2FloodDomainUUID.contains("-"))) {
311                 l2FloodDomainUUID = Utils.uuidFormater(l2FloodDomainUUID);
312                 l2FloodDomainUUID = UUID.fromString(l2FloodDomainUUID).toString();
313             }
314             if (!(projectUUID.contains("-"))) {
315                 projectUUID = Utils.uuidFormater(projectUUID);
316                 projectUUID = UUID.fromString(projectUUID).toString();
317             }
318         } catch (Exception ex) {
319             LOG.error("UUID input incorrect", ex);
320         }
321         if(l2FloodDomainNew.getName() == null){
322             LOG.error("L2 flood domain Name to be update can't be empty..");
323             return HttpURLConnection.HTTP_BAD_REQUEST;
324         }
325         try {
326             Project project = (Project) apiConnector.findById(Project.class, projectUUID);
327             String virtualNetworkByName = apiConnector.findByName(VirtualNetwork.class, project, l2FloodDomainNew.getName().toString());
328             if (virtualNetworkByName != null) {
329                 LOG.warn("L2 flood domain with name  " + l2FloodDomainNew.getName() + "  already exists with UUID : " + virtualNetworkByName);
330                 return HttpURLConnection.HTTP_FORBIDDEN;
331             }
332         } catch (IOException ioEx) {
333             LOG.error("IOException :     " + ioEx);
334             return HttpURLConnection.HTTP_INTERNAL_ERROR;
335         }
336         try {
337             virtualnetwork = (VirtualNetwork) apiConnector.findById(VirtualNetwork.class, l2FloodDomainUUID);
338         } catch (IOException ex) {
339             LOG.error("Exception :     " + ex);
340             return HttpURLConnection.HTTP_INTERNAL_ERROR;
341         }
342         if (virtualnetwork == null) {
343             LOG.error("No L2 flood domain exists for the specified UUID...");
344             return HttpURLConnection.HTTP_FORBIDDEN;
345         }
346         return HttpURLConnection.HTTP_OK;
347     }
348
349     /**
350      * Invoked to update the L2 Flood Domain
351      *
352      *@param  l2FloodDomain
353      *                An instance of updated l2FloodDomain
354      *@param  tenantid
355      *                Tenant id
356      */
357     private void updateFloodDomain(L2FloodDomain l2FloodDomain, String tenantid) throws IOException {
358         String l2FloodDomainUUID = Utils.uuidNameFormat(l2FloodDomain.getId().toString());
359         try {
360             if (!(l2FloodDomainUUID.contains("-"))) {
361                 l2FloodDomainUUID = Utils.uuidFormater(l2FloodDomainUUID);
362             }
363             l2FloodDomainUUID = UUID.fromString(l2FloodDomainUUID).toString();
364         } catch (Exception ex) {
365             LOG.error("UUID input incorrect", ex);
366         }
367         VirtualNetwork virtualNetwork = (VirtualNetwork) apiConnector.findById(VirtualNetwork.class, l2FloodDomainUUID);
368         virtualNetwork.setDisplayName(Utils.uuidNameFormat(l2FloodDomain.getName().toString()));
369         boolean l2FloodDomainUpdate;
370         try {
371                 l2FloodDomainUpdate = apiConnector.update(virtualNetwork);
372             if (!l2FloodDomainUpdate) {
373                 LOG.warn("L2 flood domain Updation failed..");
374             }
375         } catch (IOException e) {
376             LOG.warn("L2 flood domain Updation failed..");
377         }
378         LOG.info("L2 flood domain having UUID : " + virtualNetwork.getUuid() + "  has been sucessfully updated...");
379     }
380 }