blob: 8339501cb784a3c335f8c9d26a8e1d4132a4234d [file] [log] [blame]
Sean Condon06613e92017-06-09 15:14:01 +01001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2017-present Open Networking Foundation
Sean Condon06613e92017-06-09 15:14:01 +01003 *
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 */
16package org.onosproject.drivers.microsemi.yang.impl;
17
18import java.io.ByteArrayInputStream;
19import java.io.IOException;
20import java.io.InputStream;
21import java.util.List;
22import java.util.Set;
23import java.util.regex.Pattern;
24
25import com.google.common.base.Charsets;
26import com.google.common.io.ByteSource;
27import org.apache.felix.scr.annotations.Activate;
28import org.apache.felix.scr.annotations.Component;
29import org.apache.felix.scr.annotations.Deactivate;
30import org.apache.felix.scr.annotations.Reference;
31import org.apache.felix.scr.annotations.ReferenceCardinality;
32import org.apache.felix.scr.annotations.Service;
33import org.onosproject.core.ApplicationId;
34import org.onosproject.core.CoreService;
35import org.onosproject.netconf.DatastoreId;
36import org.onosproject.netconf.NetconfException;
37import org.onosproject.netconf.NetconfSession;
38import org.onosproject.yang.model.ModelConverter;
39import org.onosproject.yang.model.ModelObjectData;
40import org.onosproject.yang.model.ResourceData;
41import org.onosproject.yang.model.ResourceId;
42import org.onosproject.yang.model.SchemaContext;
43import org.onosproject.yang.model.SchemaContextProvider;
44import org.onosproject.yang.runtime.AnnotatedNodeInfo;
45import org.onosproject.yang.runtime.CompositeData;
46import org.onosproject.yang.runtime.CompositeStream;
47import org.onosproject.yang.runtime.DefaultCompositeData;
48import org.onosproject.yang.runtime.DefaultCompositeStream;
49import org.onosproject.yang.runtime.DefaultYangSerializerContext;
50import org.onosproject.yang.runtime.YangModelRegistry;
51import org.onosproject.yang.runtime.YangSerializer;
52import org.onosproject.yang.runtime.YangSerializerContext;
53import org.onosproject.yang.runtime.YangSerializerRegistry;
54import org.onosproject.yang.serializers.xml.XmlSerializer;
55import org.slf4j.Logger;
56import org.slf4j.LoggerFactory;
57
58/**
59 * Abstract class that implements some of the core functions of a YANG model service.
60 *
61 */
62@Component(immediate = true)
63@Service
64public abstract class AbstractYangServiceImpl {
65 public static final String NC_OPERATION = "nc:operation";
66 public static final String OP_DELETE = "delete";
67
68 protected final Logger log = LoggerFactory.getLogger(getClass());
69 protected boolean alreadyLoaded = false;
70
71 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
72 protected CoreService coreService;
73
74 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
75 protected YangModelRegistry yangModelRegistry;
76
77// @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
78// protected SchemaContextProvider schemaContextProvider;
79
80 protected ApplicationId appId;
81
82 // xSer is not a service and is a class variable. Can be lost on deactivate.
83 // Must be recreated on activate
84 protected XmlSerializer xSer;
85 protected YangSerializerContext yCtx;
86
87 protected static final Pattern REGEX_XML_HEADER =
88 Pattern.compile("(<\\?xml).*(\\?>)", Pattern.DOTALL);
89 protected static final Pattern REGEX_RPC_REPLY =
90 Pattern.compile("(<rpc-reply)[ ]*" +
91 "(xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\")[ ]*" +
92 "(message-id=\")[0-9]*(\">)", Pattern.DOTALL);
93 protected static final Pattern REGEX_RPC_REPLY_DATA_NS =
94 Pattern.compile("(<data)[ ]*(xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">)");
95 protected static final Pattern REGEX_RPC_REPLY_DATA =
96 Pattern.compile("(<data>)");
97 protected static final Pattern REGEX_RPC_REPLY_DATA_CLOSE =
98 Pattern.compile("(</data>)");
99 protected static final Pattern REGEX_RPC_REPLY_DATA_EMPTY =
100 Pattern.compile("(<data/>)");
101 protected static final Pattern REGEX_RPC_REPLY_CLOSE =
102 Pattern.compile("(</rpc-reply>)");
103
104 @Activate
105 public void activate() {
106 Set<YangSerializer> yangSer = ((YangSerializerRegistry) yangModelRegistry).getSerializers();
107 yangSer.forEach(ser -> {
108 if (ser instanceof XmlSerializer) {
109 xSer = (XmlSerializer) ser;
110 }
111 });
112 SchemaContext context = ((SchemaContextProvider) yangModelRegistry)
113 .getSchemaContext(ResourceId.builder().addBranchPointSchema("/", null).build());
114
115 yCtx = new DefaultYangSerializerContext(context, null);
116 };
117
118 @Deactivate
119 public void deactivate() {
120 alreadyLoaded = false;
121 }
122
123 /**
124 * Internal method to generically make a NETCONF get query from YANG objects.
125 * @param moFilter A YANG object model
126 * @param session A NETCONF session
127 * @return YangObjectModel
128 * @throws NetconfException if the session has any error
129 */
130 protected final ModelObjectData getNetconfObject(
131 ModelObjectData moFilter, NetconfSession session)
132 throws NetconfException {
133
134 return getConfigNetconfObject(moFilter, session, null);
135 }
136
137 /**
138 * Internal method to generically make a NETCONF get-config query from YANG objects.
139 *
140 * @param moFilter A YANG object model
141 * @param session A NETCONF session
142 * @param targetDs - running,candidate or startup
143 * @return YangObjectModel
144 * @throws NetconfException if the session has any error
145 */
146 protected final ModelObjectData getConfigNetconfObject(
147 ModelObjectData moFilter, NetconfSession session, DatastoreId targetDs)
148 throws NetconfException {
149 if (session == null) {
150 throw new NetconfException("Session is null when calling getConfigNetconfObject()");
151 }
152
153 if (moFilter == null) {
154 throw new NetconfException("Query object cannot be null");
155 }
156
157 String xmlQueryStr = encodeMoToXmlStr(moFilter, null);
158
159 log.debug("Sending <get-(config)> query on NETCONF session " + session.getSessionId() +
160 ":\n" + xmlQueryStr);
161 String xmlResult;
162 if (targetDs == null) {
163 xmlResult = session.get(xmlQueryStr, null);
164 } else {
165 xmlResult = session.getConfig(targetDs, xmlQueryStr);
166 }
167 xmlResult = removeRpcReplyData(xmlResult);
168
169 DefaultCompositeStream resultDcs = new DefaultCompositeStream(
170 null, new ByteArrayInputStream(xmlResult.getBytes()));
171 CompositeData compositeData = xSer.decode(resultDcs, yCtx);
172
173 return ((ModelConverter) yangModelRegistry).createModel(compositeData.resourceData());
174 }
175
176 /**
177 * Internal method to generically make a NETCONF edit-config call from a set of YANG objects.
178 *
179 * @param moConfig A YANG object model
180 * @param session A NETCONF session
181 * @param targetDs - running,candidate or startup
182 * @param annotations A list of AnnotatedNodeInfos to be added to the DataNodes
183 * @return Boolean value indicating success or failure of command
184 * @throws NetconfException if the session has any error
185 */
186 protected final boolean setNetconfObject(
187 ModelObjectData moConfig, NetconfSession session, DatastoreId targetDs,
188 List<AnnotatedNodeInfo> annotations) throws NetconfException {
189 if (moConfig == null) {
190 throw new NetconfException("Query object cannot be null");
191 } else if (session == null) {
192 throw new NetconfException("Session is null when calling getMseaSaFiltering()");
193 } else if (targetDs == null) {
194 throw new NetconfException("TargetDs is null when calling getMseaSaFiltering()");
195 }
196
197 String xmlQueryStr = encodeMoToXmlStr(moConfig, annotations);
198 log.debug("Sending <edit-config> query on NETCONF session " + session.getSessionId() +
199 ":\n" + xmlQueryStr);
200
201 return session.editConfig(targetDs, null, xmlQueryStr);
202 }
203
204 protected final String encodeMoToXmlStr(ModelObjectData yangObjectOpParamFilter,
205 List<AnnotatedNodeInfo> annotations)
206 throws NetconfException {
207 //Convert the param to XML to use as a filter
208 ResourceData rd = ((ModelConverter) yangModelRegistry).createDataNode(yangObjectOpParamFilter);
209
210 DefaultCompositeData.Builder cdBuilder =
211 DefaultCompositeData.builder().resourceData(rd);
212 if (annotations != null) {
213 for (AnnotatedNodeInfo ani : annotations) {
214 cdBuilder.addAnnotatedNodeInfo(ani);
215 }
216 }
217 CompositeStream cs = xSer.encode(cdBuilder.build(), yCtx);
218 //Convert the param to XML to use as a filter
219
220 try {
221 ByteSource byteSource = new ByteSource() {
222 @Override
223 public InputStream openStream() throws IOException {
224 return cs.resourceData();
225 }
226 };
227
228 return byteSource.asCharSource(Charsets.UTF_8).read();
229 } catch (IOException e) {
230 throw new NetconfException("Error decoding CompositeStream to String", e);
231 }
232 }
233
234 protected static final String removeRpcReplyData(String rpcReplyXml) {
235 rpcReplyXml = REGEX_XML_HEADER.matcher(rpcReplyXml).replaceFirst("");
236 rpcReplyXml = REGEX_RPC_REPLY.matcher(rpcReplyXml).replaceFirst("");
237 rpcReplyXml = REGEX_RPC_REPLY_DATA_NS.matcher(rpcReplyXml).replaceFirst("");
238 rpcReplyXml = REGEX_RPC_REPLY_DATA.matcher(rpcReplyXml).replaceFirst("");
239 rpcReplyXml = REGEX_RPC_REPLY_DATA_CLOSE.matcher(rpcReplyXml).replaceFirst("");
240 rpcReplyXml = REGEX_RPC_REPLY_DATA_EMPTY.matcher(rpcReplyXml).replaceFirst("");
241 rpcReplyXml = REGEX_RPC_REPLY_CLOSE.matcher(rpcReplyXml).replaceFirst("");
242 rpcReplyXml = rpcReplyXml.replace("\t", "");
243 return rpcReplyXml;
244 }
245}