HONEYCOMB-61: Add BA broker for context data tree
[honeycomb.git] / v3po / v3po2vpp / src / main / java / io / fd / honeycomb / v3po / translate / v3po / vpp / BridgeDomainCustomizer.java
1 /*
2  * Copyright (c) 2016 Cisco and/or its affiliates.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at:
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package io.fd.honeycomb.v3po.translate.v3po.vpp;
18
19 import static com.google.common.base.Preconditions.checkArgument;
20 import static com.google.common.base.Preconditions.checkNotNull;
21
22 import com.google.common.base.Preconditions;
23 import io.fd.honeycomb.v3po.translate.spi.write.ListWriterCustomizer;
24 import io.fd.honeycomb.v3po.translate.v3po.util.FutureJVppCustomizer;
25 import io.fd.honeycomb.v3po.translate.v3po.util.NamingContext;
26 import io.fd.honeycomb.v3po.translate.v3po.util.VppApiInvocationException;
27 import io.fd.honeycomb.v3po.translate.v3po.utils.V3poUtils;
28 import io.fd.honeycomb.v3po.translate.write.WriteContext;
29 import io.fd.honeycomb.v3po.translate.write.WriteFailedException;
30 import java.util.List;
31 import javax.annotation.Nonnull;
32 import javax.annotation.Nullable;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.BridgeDomains;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.bridge.domains.BridgeDomain;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.bridge.domains.BridgeDomainKey;
36 import org.opendaylight.yangtools.yang.binding.DataObject;
37 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
38 import org.openvpp.jvpp.dto.BridgeDomainAddDel;
39 import org.openvpp.jvpp.dto.BridgeDomainAddDelReply;
40 import org.openvpp.jvpp.future.FutureJVpp;
41 import org.slf4j.Logger;
42 import org.slf4j.LoggerFactory;
43
44 public class BridgeDomainCustomizer
45         extends FutureJVppCustomizer
46         implements ListWriterCustomizer<BridgeDomain, BridgeDomainKey> {
47
48     private static final Logger LOG = LoggerFactory.getLogger(BridgeDomainCustomizer.class);
49
50     private static final byte ADD_OR_UPDATE_BD = (byte) 1;
51     private final NamingContext bdContext;
52
53     public BridgeDomainCustomizer(@Nonnull final FutureJVpp futureJvpp, @Nonnull final NamingContext bdContext) {
54         super(futureJvpp);
55         this.bdContext = Preconditions.checkNotNull(bdContext, "bdContext should not be null");
56     }
57
58     @Nonnull
59     @Override
60     public List<BridgeDomain> extract(@Nonnull final InstanceIdentifier<BridgeDomain> currentId,
61                                       @Nonnull final DataObject parentData) {
62         return ((BridgeDomains) parentData).getBridgeDomain();
63     }
64
65     private BridgeDomainAddDelReply addOrUpdateBridgeDomain(final int bdId, @Nonnull final BridgeDomain bd)
66             throws VppApiInvocationException {
67         final BridgeDomainAddDel request = new BridgeDomainAddDel();
68         request.bdId = bdId;
69         request.flood = booleanToByte(bd.isFlood());
70         request.forward = booleanToByte(bd.isForward());
71         request.learn = booleanToByte(bd.isLearn());
72         request.uuFlood = booleanToByte(bd.isUnknownUnicastFlood());
73         request.arpTerm = booleanToByte(bd.isArpTermination());
74         request.isAdd = ADD_OR_UPDATE_BD;
75
76         final BridgeDomainAddDelReply reply =
77                 V3poUtils.getReply(getFutureJVpp().bridgeDomainAddDel(request).toCompletableFuture());
78         if (reply.retval < 0) {
79             LOG.warn("Bridge domain {} (id={}) add/update failed", bd.getName(), bdId);
80             throw new VppApiInvocationException("bridgeDomainAddDel", reply.context, reply.retval);
81         } else {
82             LOG.debug("Bridge domain {} (id={}) add/update successful", bd.getName(), bdId);
83         }
84
85         return reply;
86     }
87
88     @Override
89     public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<BridgeDomain> id,
90                                        @Nonnull final BridgeDomain dataBefore,
91                                        @Nonnull final WriteContext ctx) throws WriteFailedException.CreateFailedException {
92         LOG.debug("writeCurrentAttributes: id={}, current={}, ctx={}", id, dataBefore, ctx);
93         final String bdName = dataBefore.getName();
94
95         try {
96             // FIXME we need the bd index to be returned by VPP or we should have a counter field (maybe in context similar to artificial name)
97             // Here we assign the next available ID from bdContext's perspective
98             int index = 1;
99             while(bdContext.containsName(index, ctx.getMappingContext())) {
100                 index++;
101             }
102             addOrUpdateBridgeDomain(index, dataBefore);
103             bdContext.addName(index, bdName, ctx.getMappingContext());
104         } catch (VppApiInvocationException e) {
105             LOG.warn("Failed to create bridge domain", e);
106             throw new WriteFailedException.CreateFailedException(id, dataBefore, e);
107         }
108     }
109
110     private byte booleanToByte(@Nullable final Boolean aBoolean) {
111         return aBoolean != null && aBoolean
112                 ? (byte) 1
113                 : (byte) 0;
114     }
115
116     @Override
117     public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<BridgeDomain> id,
118                                         @Nonnull final BridgeDomain dataBefore,
119                                         @Nonnull final WriteContext ctx) throws WriteFailedException.DeleteFailedException {
120         LOG.debug("deleteCurrentAttributes: id={}, dataBefore={}, ctx={}", id, dataBefore, ctx);
121
122         final String bdName = id.firstKeyOf(BridgeDomain.class).getName();
123         int bdId = bdContext.getIndex(bdName, ctx.getMappingContext());
124         final BridgeDomainAddDel request = new BridgeDomainAddDel();
125         request.bdId = bdId;
126
127         final BridgeDomainAddDelReply reply =
128                 V3poUtils.getReply(getFutureJVpp().bridgeDomainAddDel(request).toCompletableFuture());
129         if (reply.retval < 0) {
130             LOG.warn("Bridge domain {} (id={}) delete failed", bdName, bdId);
131             throw new WriteFailedException.DeleteFailedException(id,
132                     new VppApiInvocationException("bridgeDomainAddDel", reply.context, reply.retval));
133         } else {
134             LOG.debug("Bridge domain {} (id={}) deleted successfully", bdName, bdId);
135         }
136     }
137
138     @Override
139     public void updateCurrentAttributes(@Nonnull final InstanceIdentifier<BridgeDomain> id,
140                                         @Nonnull final BridgeDomain dataBefore, @Nonnull final BridgeDomain dataAfter,
141                                         @Nonnull final WriteContext ctx) throws WriteFailedException.UpdateFailedException {
142         LOG.debug("updateCurrentAttributes: id={}, dataBefore={}, dataAfter={}, ctx={}", id, dataBefore, dataAfter,
143                 ctx);
144
145         // FIXME can be removed after updating mdsal-binding-dom-codec to 0.8.2-Beryllium-SR2
146         // and restoring equality check in AbstractCompositeWriter
147         if (dataBefore.equals(dataAfter)) {
148             LOG.debug("dataBefore equals dataAfter, update will not be performed");
149             return;
150         }
151
152         final String bdName = checkNotNull(dataAfter.getName());
153         checkArgument(bdName.equals(dataBefore.getName()),
154                 "BridgeDomain name changed. It should be deleted and then created.");
155
156         try {
157             addOrUpdateBridgeDomain(bdContext.getIndex(bdName, ctx.getMappingContext()), dataAfter);
158         } catch (VppApiInvocationException e) {
159             LOG.warn("Failed to create bridge domain", e);
160             throw new WriteFailedException.UpdateFailedException(id, dataBefore, dataAfter, e);
161         }
162     }
163
164 }