HONEYCOMB-91: fix restoring BD from persisted config.
[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 import static io.fd.honeycomb.v3po.translate.v3po.util.TranslateUtils.booleanToByte;
22
23 import com.google.common.base.Optional;
24 import com.google.common.base.Preconditions;
25 import io.fd.honeycomb.v3po.translate.spi.write.ListWriterCustomizer;
26 import io.fd.honeycomb.v3po.translate.v3po.util.FutureJVppCustomizer;
27 import io.fd.honeycomb.v3po.translate.v3po.util.NamingContext;
28 import io.fd.honeycomb.v3po.translate.v3po.util.TranslateUtils;
29 import io.fd.honeycomb.v3po.translate.write.WriteContext;
30 import io.fd.honeycomb.v3po.translate.write.WriteFailedException;
31 import java.util.List;
32 import javax.annotation.Nonnull;
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.VppBaseCallException;
39 import org.openvpp.jvpp.dto.BridgeDomainAddDel;
40 import org.openvpp.jvpp.dto.BridgeDomainAddDelReply;
41 import org.openvpp.jvpp.future.FutureJVpp;
42 import org.slf4j.Logger;
43 import org.slf4j.LoggerFactory;
44
45 public class BridgeDomainCustomizer
46     extends FutureJVppCustomizer
47     implements ListWriterCustomizer<BridgeDomain, BridgeDomainKey> {
48
49     private static final Logger LOG = LoggerFactory.getLogger(BridgeDomainCustomizer.class);
50
51     private static final byte ADD_OR_UPDATE_BD = (byte) 1;
52     private final NamingContext bdContext;
53
54     public BridgeDomainCustomizer(@Nonnull final FutureJVpp futureJvpp, @Nonnull final NamingContext bdContext) {
55         super(futureJvpp);
56         this.bdContext = Preconditions.checkNotNull(bdContext, "bdContext should not be null");
57     }
58
59     @Nonnull
60     @Override
61     public Optional<List<BridgeDomain>> extract(@Nonnull final InstanceIdentifier<BridgeDomain> currentId,
62                                                 @Nonnull final DataObject parentData) {
63         return Optional.fromNullable(((BridgeDomains) parentData).getBridgeDomain());
64     }
65
66     private BridgeDomainAddDelReply addOrUpdateBridgeDomain(final int bdId, @Nonnull final BridgeDomain bd)
67         throws VppBaseCallException {
68         final BridgeDomainAddDelReply reply;
69         final BridgeDomainAddDel request = new BridgeDomainAddDel();
70         request.bdId = bdId;
71         request.flood = booleanToByte(bd.isFlood());
72         request.forward = booleanToByte(bd.isForward());
73         request.learn = booleanToByte(bd.isLearn());
74         request.uuFlood = booleanToByte(bd.isUnknownUnicastFlood());
75         request.arpTerm = booleanToByte(bd.isArpTermination());
76         request.isAdd = ADD_OR_UPDATE_BD;
77
78         reply = TranslateUtils.getReply(getFutureJVpp().bridgeDomainAddDel(request).toCompletableFuture());
79         LOG.debug("Bridge domain {} (id={}) add/update successful", bd.getName(), bdId);
80         return reply;
81     }
82
83     @Override
84     public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<BridgeDomain> id,
85                                        @Nonnull final BridgeDomain dataBefore,
86                                        @Nonnull final WriteContext ctx)
87         throws WriteFailedException.CreateFailedException {
88         LOG.debug("writeCurrentAttributes: id={}, current={}, ctx={}", id, dataBefore, ctx);
89         final String bdName = dataBefore.getName();
90
91         try {
92             int index;
93             if (bdContext.containsIndex(bdName, ctx.getMappingContext())) {
94                 index = bdContext.getIndex(bdName, ctx.getMappingContext());
95             } else {
96                 // FIXME we need the bd index to be returned by VPP or we should have a counter field
97                 // (maybe in context similar to artificial name)
98                 // Here we assign the next available ID from bdContext's perspective
99                 index = 1;
100                 while (bdContext.containsName(index, ctx.getMappingContext())) {
101                     index++;
102                 }
103             }
104             addOrUpdateBridgeDomain(index, dataBefore);
105             bdContext.addName(index, bdName, ctx.getMappingContext());
106         } catch (VppBaseCallException e) {
107             LOG.warn("Failed to create bridge domain", e);
108             throw new WriteFailedException.CreateFailedException(id, dataBefore, e);
109         }
110     }
111
112     @Override
113     public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<BridgeDomain> id,
114                                         @Nonnull final BridgeDomain dataBefore,
115                                         @Nonnull final WriteContext ctx)
116         throws WriteFailedException.DeleteFailedException {
117         LOG.debug("deleteCurrentAttributes: id={}, dataBefore={}, ctx={}", id, dataBefore, ctx);
118         final String bdName = id.firstKeyOf(BridgeDomain.class).getName();
119         int bdId = bdContext.getIndex(bdName, ctx.getMappingContext());
120         try {
121
122             final BridgeDomainAddDel request = new BridgeDomainAddDel();
123             request.bdId = bdId;
124
125             TranslateUtils.getReply(getFutureJVpp().bridgeDomainAddDel(request).toCompletableFuture());
126             LOG.debug("Bridge domain {} (id={}) deleted successfully", bdName, bdId);
127         } catch (VppBaseCallException e) {
128             LOG.warn("Bridge domain {} (id={}) delete failed", bdName, bdId);
129             throw new WriteFailedException.DeleteFailedException(id, e);
130         }
131     }
132
133     @Override
134     public void updateCurrentAttributes(@Nonnull final InstanceIdentifier<BridgeDomain> id,
135                                         @Nonnull final BridgeDomain dataBefore, @Nonnull final BridgeDomain dataAfter,
136                                         @Nonnull final WriteContext ctx)
137         throws WriteFailedException.UpdateFailedException {
138         LOG.debug("updateCurrentAttributes: id={}, dataBefore={}, dataAfter={}, ctx={}", id, dataBefore, dataAfter,
139             ctx);
140
141         final String bdName = checkNotNull(dataAfter.getName());
142         checkArgument(bdName.equals(dataBefore.getName()),
143             "BridgeDomain name changed. It should be deleted and then created.");
144
145         try {
146             addOrUpdateBridgeDomain(bdContext.getIndex(bdName, ctx.getMappingContext()), dataAfter);
147         } catch (VppBaseCallException e) {
148             LOG.warn("Failed to create bridge domain", e);
149             throw new WriteFailedException.UpdateFailedException(id, dataBefore, dataAfter, e);
150         }
151     }
152
153 }