BUG-6858: adapt to ise api, change lookup from ise
[groupbasedpolicy.git] / sxp-integration / sxp-ep-provider / src / main / java / org / opendaylight / groupbasedpolicy / sxp / ep / provider / impl / dao / EPPolicyTemplateDaoFacadeImpl.java
1 /*
2  * Copyright (c) 2016 Cisco Systems, Inc. and others.  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.sxp.ep.provider.impl.dao;
10
11 import com.google.common.base.Function;
12 import com.google.common.base.Optional;
13 import com.google.common.util.concurrent.AsyncFunction;
14 import com.google.common.util.concurrent.Futures;
15 import com.google.common.util.concurrent.ListenableFuture;
16 import java.util.Collection;
17 import java.util.Collections;
18 import javax.annotation.Nonnull;
19 import javax.annotation.Nullable;
20 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
21 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
22 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
23 import org.opendaylight.groupbasedpolicy.sxp.ep.provider.api.EPPolicyTemplateDaoFacade;
24 import org.opendaylight.groupbasedpolicy.sxp.ep.provider.api.EPPolicyTemplateProvider;
25 import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.SgtGeneratorImpl;
26 import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.SimpleCachedDao;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.integration.sxp.ep.provider.model.rev160302.SxpEpMapper;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.integration.sxp.ep.provider.model.rev160302.TemplateGenerated;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.integration.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointPolicyTemplateBySgt;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.integration.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointPolicyTemplateBySgtBuilder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.integration.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointPolicyTemplateBySgtKey;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.Sgt;
33 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
36
37 /**
38  * Purpose: add template provider fallback to {@link EPPolicyTemplateDaoImpl}
39  */
40 public class EPPolicyTemplateDaoFacadeImpl implements EPPolicyTemplateDaoFacade {
41
42     private static final Logger LOG = LoggerFactory.getLogger(EPPolicyTemplateDaoFacadeImpl.class);
43
44     private final EPPolicyTemplateDaoImpl epPolicyTemplateDao;
45     private final SimpleCachedDao<Sgt, EndpointPolicyTemplateBySgt> epPolicyTemplateCachedDao;
46     private final SgtGeneratorImpl sgtGenerator;
47     private final DataBroker dataBroker;
48
49     private EPPolicyTemplateProvider templateProvider;
50
51     public EPPolicyTemplateDaoFacadeImpl(final DataBroker dataBroker, final EPPolicyTemplateDaoImpl epPolicyTemplateDao,
52                                          final SimpleCachedDao<Sgt, EndpointPolicyTemplateBySgt> epPolicyTemplateCachedDao,
53                                          final SgtGeneratorImpl sgtGenerator) {
54         this.dataBroker = dataBroker;
55         this.epPolicyTemplateDao = epPolicyTemplateDao;
56         this.epPolicyTemplateCachedDao = epPolicyTemplateCachedDao;
57         this.sgtGenerator = sgtGenerator;
58     }
59
60     @Override
61     public void setTemplateProvider(final EPPolicyTemplateProvider templateProvider) {
62         this.templateProvider = templateProvider;
63     }
64
65
66     @Override
67     public ListenableFuture<Optional<EndpointPolicyTemplateBySgt>> read(@Nonnull final Sgt key) {
68         // read from delegate
69         final ListenableFuture<Optional<EndpointPolicyTemplateBySgt>> templateFu = epPolicyTemplateDao.read(key);
70
71         // involve fallback if template is absent
72         return Futures.transform(templateFu, new AsyncFunction<Optional<EndpointPolicyTemplateBySgt>, Optional<EndpointPolicyTemplateBySgt>>() {
73             @Override
74             public ListenableFuture<Optional<EndpointPolicyTemplateBySgt>> apply(
75                     @Nonnull final Optional<EndpointPolicyTemplateBySgt> templateOpt) throws Exception {
76
77                 return templateOpt.transform(template -> Futures.immediateFuture(templateOpt))
78                         // failed to read template -> invoke fallback if available
79                         .or(() -> java.util.Optional.ofNullable(templateProvider)
80                                 .map(provider -> templateProvider.provideTemplate(key))
81                                 .map(template -> rewrapOptionalToGuavaOptional(template))
82                                 .orElse(Futures.immediateFuture(Optional.absent()))
83                         );
84             }
85         });
86     }
87
88     private <T> ListenableFuture<Optional<T>> rewrapOptionalToGuavaOptional(final ListenableFuture<java.util.Optional<T>> templateFu) {
89         return Futures.transform(templateFu, new Function<java.util.Optional<T>, Optional<T>>() {
90                     @Nullable
91                     @Override
92                     public Optional<T> apply(@Nullable final java.util.Optional<T> input) {
93                         return java.util.Optional.ofNullable(input)
94                                 .map(origNonnullInput -> Optional.fromNullable(origNonnullInput.orElse(null)))
95                                 .orElse(Optional.absent());
96                     }
97                 }
98         );
99     }
100
101
102     private Function<Void, Collection<EndpointPolicyTemplateBySgt>> createStoreOutcomeHandlerToCollection(final EndpointPolicyTemplateBySgt template) {
103         return new Function<Void, Collection<EndpointPolicyTemplateBySgt>>() {
104             @Nullable
105             @Override
106             public Collection<EndpointPolicyTemplateBySgt> apply(@Nullable final Void aVoid) {
107                 return Collections.singletonList(template);
108             }
109         };
110     }
111
112     @Override
113     public ListenableFuture<Collection<EndpointPolicyTemplateBySgt>> readBy(@Nonnull final EpPolicyTemplateValueKey templateLookupKey) {
114         //TODO: expose to ios-xe renderer,
115         final Collection<EndpointPolicyTemplateBySgt> templatesFromDao = epPolicyTemplateDao.readBy(templateLookupKey);
116         final ListenableFuture<Collection<EndpointPolicyTemplateBySgt>> result;
117         if (!templatesFromDao.isEmpty()) {
118             result = Futures.immediateFuture(templatesFromDao);
119         } else {
120             // generate
121             result = sgtGenerator.generateNextSgt(epPolicyTemplateCachedDao)
122                     // build ep-policy-template
123                     .map(sgt -> buildEpPolicyTemplate(templateLookupKey, sgt))
124                     // store the template
125                     .map(this::storeTemplate)
126                     .orElse(Futures.immediateFuture(Collections.emptyList()));
127         }
128         return result;
129     }
130
131     private ListenableFuture<Collection<EndpointPolicyTemplateBySgt>> storeTemplate(final EndpointPolicyTemplateBySgt template) {
132         final WriteTransaction wTx = dataBroker.newWriteOnlyTransaction();
133         // store ep-policy-template
134         final Sgt sgt = template.getSgt();
135         LOG.trace("storing generated epPolicyTemplate: {}", sgt.getValue());
136         final InstanceIdentifier<EndpointPolicyTemplateBySgt> epPolicyTemplatePath = InstanceIdentifier
137                 .create(SxpEpMapper.class)
138                 .child(EndpointPolicyTemplateBySgt.class, new EndpointPolicyTemplateBySgtKey(sgt));
139         wTx.put(LogicalDatastoreType.CONFIGURATION, epPolicyTemplatePath, template, true);
140
141         return Futures.transform(wTx.submit(), createStoreOutcomeHandlerToCollection(template));
142     }
143
144     private EndpointPolicyTemplateBySgt buildEpPolicyTemplate(final EpPolicyTemplateValueKey templateLookupKey, final Sgt sgt) {
145         return new EndpointPolicyTemplateBySgtBuilder()
146                 .setOrigin(TemplateGenerated.class)
147                 .setTenant(templateLookupKey.getTenantId())
148                 .setSgt(sgt)
149                 .setEndpointGroups(templateLookupKey.getEpgId())
150                 .setConditions(templateLookupKey.getConditionName())
151                 .build();
152     }
153 }