BUG-6650: ep-ip/sgt, implement and wire template provider
[groupbasedpolicy.git] / sxp-integration / sxp-ise-adapter / src / main / java / org / opendaylight / groupbasedpolicy / sxp_ise_adapter / impl / GbpIseSgtHarvesterImpl.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_ise_adapter.impl;
10
11 import com.google.common.base.Function;
12 import com.google.common.util.concurrent.AsyncFunction;
13 import com.google.common.util.concurrent.Futures;
14 import com.google.common.util.concurrent.ListenableFuture;
15 import com.sun.jersey.api.client.Client;
16 import com.sun.jersey.api.client.WebResource;
17 import java.net.URI;
18 import java.util.ArrayList;
19 import java.util.List;
20 import javax.annotation.Nonnull;
21 import javax.annotation.Nullable;
22 import javax.xml.xpath.XPath;
23 import javax.xml.xpath.XPathConstants;
24 import javax.xml.xpath.XPathExpressionException;
25 import org.opendaylight.groupbasedpolicy.sxp_ise_adapter.impl.util.IseReplyUtil;
26 import org.opendaylight.groupbasedpolicy.sxp_ise_adapter.impl.util.RestClientFactory;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.gbp.sxp.ise.adapter.model.rev160630.gbp.sxp.ise.adapter.IseSourceConfig;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.gbp.sxp.ise.adapter.model.rev160630.gbp.sxp.ise.adapter.ise.source.config.ConnectionConfig;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.gbp.sxp.ise.adapter.model.rev160630.gbp.sxp.ise.adapter.ise.source.config.connection.config.Header;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.Sgt;
31 import org.slf4j.Logger;
32 import org.slf4j.LoggerFactory;
33 import org.w3c.dom.Node;
34 import org.w3c.dom.NodeList;
35 import org.xml.sax.InputSource;
36
37 /**
38  * Purpose: harvest sgt + names available via ise-rest-api
39  */
40 public class GbpIseSgtHarvesterImpl implements GbpIseSgtHarvester {
41
42     private static final Logger LOG = LoggerFactory.getLogger(GbpIseSgtHarvesterImpl.class);
43
44     private final SgtInfoProcessor[] sgtInfoProcessors;
45
46     /**
47      * @param sgtInfoProcessors generator delegate
48      */
49     public GbpIseSgtHarvesterImpl(final SgtInfoProcessor... sgtInfoProcessors) {
50         this.sgtInfoProcessors = sgtInfoProcessors;
51     }
52
53     @Override
54     public ListenableFuture<Integer> harvest(@Nonnull final IseSourceConfig configuration) {
55         final ConnectionConfig connectionConfig = configuration.getConnectionConfig();
56         ListenableFuture<Integer> result;
57         try {
58             final Client iseClient = RestClientFactory.createIseClient(connectionConfig);
59             final WebResource baseWebResource = iseClient.resource(connectionConfig.getIseRestUrl().getValue());
60
61             final WebResource.Builder requestBuilder = RestClientFactory.createRequestBuilder(baseWebResource,
62                     connectionConfig.getHeader(), RestClientFactory.PATH_ERS_CONFIG_SGT);
63             final String rawSgtSummary = IseReplyUtil.deliverResponse(requestBuilder);
64
65             final List<SgtInfo> sgtInfos = harvestDetails(rawSgtSummary, baseWebResource, connectionConfig.getHeader());
66
67             ListenableFuture<Void> processingResult = Futures.immediateCheckedFuture(null);
68             for (SgtInfoProcessor processor : sgtInfoProcessors) {
69                 processingResult = Futures.transform(processingResult, new AsyncFunction<Void, Void>() {
70                     @Override
71                     public ListenableFuture<Void> apply(final Void input) throws Exception {
72                         LOG.debug("entering stg-info processor {}", processor.getClass().getSimpleName());
73                         return processor.processSgtInfo(configuration.getTenant(), sgtInfos);
74                     }
75                 });
76             }
77             result = Futures.transform(processingResult, new Function<Void, Integer>() {
78                 @Nullable
79                 @Override
80                 public Integer apply(@Nullable final Void input) {
81                     // always success, otherwise there will be TransactionCommitFailedException thrown
82                     return sgtInfos.size();
83                 }
84             });
85         } catch (Exception e) {
86             LOG.debug("failed to harvest ise", e);
87             result = Futures.immediateFailedFuture(e);
88         }
89
90         return result;
91     }
92
93     private List<SgtInfo> harvestDetails(final String rawSgtSummary, final WebResource baseWebResource, final List<Header> headers) {
94         LOG.trace("rawSgtSummary: {}", rawSgtSummary);
95         final List<SgtInfo> sgtInfos = new ArrayList<>();
96
97         // parse sgtSummary
98         final XPath xpath = IseReplyUtil.setupXpath();
99
100         InputSource inputSource = IseReplyUtil.createInputSource(rawSgtSummary);
101         try {
102             final NodeList sgtLinkNodes = (NodeList) xpath.evaluate(IseReplyUtil.EXPRESSION_SGT_ALL_LINK_HREFS, inputSource,
103                     XPathConstants.NODESET);
104             for (int i = 0; i < sgtLinkNodes.getLength(); i++) {
105                 final String sgtLinkHrefValue = sgtLinkNodes.item(i).getNodeValue();
106                 LOG.debug("found sgt resource [{}]: {}", i, sgtLinkHrefValue);
107
108                 // query all sgt entries (serial-vise)
109                 final URI hrefToSgtDetailUri = URI.create(sgtLinkHrefValue);
110                 final WebResource.Builder requestBuilder = RestClientFactory.createRequestBuilder(baseWebResource, headers, hrefToSgtDetailUri.getPath());
111                 final String rawSgtDetail = IseReplyUtil.deliverResponse(requestBuilder);
112                 LOG.trace("rawSgtDetail: {}", rawSgtDetail);
113
114                 final Node sgtNode = (Node) xpath.evaluate(IseReplyUtil.EXPRESSION_SGT_DETAIL, IseReplyUtil.createInputSource(rawSgtDetail),
115                         XPathConstants.NODE);
116                 final Node sgtName = (Node) xpath.evaluate(IseReplyUtil.EXPRESSION_SGT_NAME_ATTR, sgtNode, XPathConstants.NODE);
117                 final Node sgtValue = (Node) xpath.evaluate(IseReplyUtil.EXPRESSION_SGT_VALUE, sgtNode, XPathConstants.NODE);
118                 LOG.debug("sgt value [{}]: {} -> {}", i, sgtValue, sgtName);
119
120                 // store replies into list of SgtInfo
121                 final Sgt sgt = new Sgt(Integer.parseInt(sgtValue.getNodeValue(), 10));
122                 final SgtInfo sgtInfo = new SgtInfo(sgt, sgtName.getNodeValue());
123                 sgtInfos.add(sgtInfo);
124             }
125         } catch (XPathExpressionException e) {
126             LOG.warn("failed to parse all-sgt response", e);
127         }
128
129         return sgtInfos;
130     }
131
132 }