11d1189573244abad3c5bdac9f231065737a4da4
[controller.git] / opendaylight / md-sal / forwardingrules-manager / src / main / java / org / opendaylight / controller / forwardingrulesmanager / consumer / impl / TableFeaturesConsumerImpl.java
1 package org.opendaylight.controller.forwardingrulesmanager.consumer.impl;
2
3 import java.util.HashMap;
4 import java.util.List;
5 import java.util.Map;
6 import java.util.Map.Entry;
7 import java.util.Set;
8
9 import org.opendaylight.controller.clustering.services.IClusterContainerServices;
10 import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler;
11 import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction;
12 import org.opendaylight.controller.md.sal.common.api.data.DataModification;
13 import org.opendaylight.controller.sal.common.util.Rpcs;
14 import org.opendaylight.controller.sal.core.IContainer;
15 import org.opendaylight.controller.sal.utils.ServiceHelper;
16 import org.opendaylight.controller.sal.utils.Status;
17 import org.opendaylight.controller.sal.utils.StatusCode;
18 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.config.rev131024.Tables;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.config.rev131024.tables.Table;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.SalTableService;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.UpdateTableInputBuilder;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.table.update.UpdatedTableBuilder;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.features.TableFeatures;
24 import org.opendaylight.yangtools.yang.binding.DataObject;
25 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
26 import org.opendaylight.yangtools.yang.common.RpcResult;
27 import org.slf4j.Logger;
28 import org.slf4j.LoggerFactory;
29
30 public class TableFeaturesConsumerImpl {
31     protected static final Logger logger = LoggerFactory.getLogger(TableFeaturesConsumerImpl.class);
32     private SalTableService tableService;
33     private TableDataCommitHandler commitHandler;
34     private final IClusterContainerServices clusterContainerService = null;
35     private IContainer container;
36     private static final String NAMEREGEX = "^[a-zA-Z0-9]+$";
37     private boolean inContainerMode; // being used by global instance only
38
39     public TableFeaturesConsumerImpl() {
40         InstanceIdentifier<? extends DataObject> path = InstanceIdentifier.builder(Tables.class).toInstance();
41         tableService = FRMConsumerImpl.getProviderSession().getRpcService(SalTableService.class);
42
43         if (null == tableService) {
44             logger.error("Consumer SAL Service is down or NULL. FRM may not function as intended");
45             System.out.println("Consumer SAL Service is down or NULL.");
46             return;
47         }
48
49         System.out.println("-------------------------------------------------------------------");
50         commitHandler = new TableDataCommitHandler();
51         FRMConsumerImpl.getDataProviderService().registerCommitHandler(path, commitHandler);
52         container = (IContainer) ServiceHelper.getGlobalInstance(IContainer.class, this);
53     }
54
55     /**
56      * Updates TableFeatures to the southbound plugin and our internal database
57      *
58      * @param path
59      * @param dataObject
60      */
61     private void updateTableFeatures(InstanceIdentifier<?> path, TableFeatures dataObject) {
62
63         UpdateTableInputBuilder input = new UpdateTableInputBuilder();
64         UpdatedTableBuilder updatedtablebuilder = new UpdatedTableBuilder();
65         updatedtablebuilder.fieldsFrom(dataObject);
66         List<TableFeatures> features = updatedtablebuilder.build().getTableFeatures();
67         for (TableFeatures feature : features) {
68             if (feature != null && feature.getMaxEntries() != null) {
69                 logger.error("Max Entries field is read-only, cannot be changed");
70                 return;
71             }
72         }
73         input.setUpdatedTable(updatedtablebuilder.build());
74
75         // We send table feature update request to the sounthbound plugin
76         tableService.updateTable(input.build());
77     }
78
79     @SuppressWarnings("unchecked")
80     private void commitToPlugin(internalTransaction transaction) {
81
82         for (@SuppressWarnings("unused")
83         Entry<InstanceIdentifier<?>, TableFeatures> entry : transaction.updates.entrySet()) {
84             System.out.println("Coming update cc in TableDatacommitHandler");
85             updateTableFeatures(entry.getKey(), entry.getValue());
86         }
87
88     }
89
90     private final class TableDataCommitHandler implements DataCommitHandler<InstanceIdentifier<?>, DataObject> {
91
92         @SuppressWarnings("unchecked")
93         @Override
94         public DataCommitTransaction requestCommit(DataModification<InstanceIdentifier<?>, DataObject> modification) {
95             // We should verify transaction
96             System.out.println("Coming in TableFeaturesDatacommitHandler");
97             internalTransaction transaction = new internalTransaction(modification);
98             transaction.prepareUpdate();
99             return transaction;
100         }
101     }
102
103     private final class internalTransaction implements DataCommitTransaction<InstanceIdentifier<?>, DataObject> {
104
105         private final DataModification<InstanceIdentifier<?>, DataObject> modification;
106
107         @Override
108         public DataModification<InstanceIdentifier<?>, DataObject> getModification() {
109             return modification;
110         }
111
112         public internalTransaction(DataModification<InstanceIdentifier<?>, DataObject> modification) {
113             this.modification = modification;
114         }
115
116         Map<InstanceIdentifier<?>, TableFeatures> updates = new HashMap<>();
117         Map<InstanceIdentifier<?>, TableFeatures> createdEntries = new HashMap<>();
118
119         /**
120          * We create a plan which table features will be updated.
121          *
122          */
123         void prepareUpdate() {
124                 Set<Entry<InstanceIdentifier<?>, DataObject>> createdEntries = modification.getCreatedConfigurationData().entrySet();
125
126             Set<Entry<InstanceIdentifier<?>, DataObject>> puts = modification.getUpdatedConfigurationData().entrySet();
127             for (Entry<InstanceIdentifier<?>, DataObject> entry : puts) {
128
129                 // validating the DataObject
130
131                 Status status = validate(container, (TableFeatures) entry);
132                 if (!status.isSuccess()) {
133                     logger.warn("Invalid Configuration for table features The failure is {}", entry,
134                             status.getDescription());
135                     String error = "Invalid Configuration (" + status.getDescription() + ")";
136                     logger.error(error);
137                     return;
138                 }
139                 if (entry.getValue() instanceof TableFeatures) {
140                     TableFeatures tablefeatures = (TableFeatures) entry.getValue();
141                     preparePutEntry(entry.getKey(), tablefeatures);
142                 }
143
144             }
145         }
146
147         private void preparePutEntry(InstanceIdentifier<?> key, TableFeatures tablefeatures) {
148             if (tablefeatures != null) {
149                 // Updating the Map
150                 System.out.println("Coming update  in TableFeaturesDatacommitHandler");
151                 updates.put(key, tablefeatures);
152             }
153         }
154
155         /**
156          * We are OK to go with execution of plan
157          *
158          */
159         @Override
160         public RpcResult<Void> finish() throws IllegalStateException {
161
162             commitToPlugin(this);
163             // We return true if internal transaction is successful.
164             // return Rpcs.getRpcResult(true, null, Collections.emptySet());
165             return Rpcs.getRpcResult(true, null, null);
166         }
167
168         /**
169          *
170          * We should rollback our preparation
171          *
172          */
173         @Override
174         public RpcResult<Void> rollback() throws IllegalStateException {
175             // NOOP - we did not modified any internal state during
176             // requestCommit phase
177             // return Rpcs.getRpcResult(true, null, Collections.emptySet());
178             return Rpcs.getRpcResult(true, null, null);
179
180         }
181
182         public Status validate(IContainer container, TableFeatures dataObject) {
183
184             String tablename = dataObject.getName();
185             if (tablename == null || tablename.trim().isEmpty() || !tablename.matches(NAMEREGEX)
186                     || tablename.length() != 32) {
187                 return new Status(StatusCode.BADREQUEST, "Invalid table name");
188             }
189
190             return new Status(StatusCode.SUCCESS);
191         }
192     }
193 }