Updating Microsemi Driver to onos-yang-tools 2.x

Change-Id: I80e3348087518a8f9a742c813b6238371a3f8f97
diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/AbstractYangServiceImpl.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/AbstractYangServiceImpl.java
new file mode 100644
index 0000000..3867a2f
--- /dev/null
+++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/AbstractYangServiceImpl.java
@@ -0,0 +1,245 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi.yang.impl;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.List;
+import java.util.Set;
+import java.util.regex.Pattern;
+
+import com.google.common.base.Charsets;
+import com.google.common.io.ByteSource;
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.apache.felix.scr.annotations.Service;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.CoreService;
+import org.onosproject.netconf.DatastoreId;
+import org.onosproject.netconf.NetconfException;
+import org.onosproject.netconf.NetconfSession;
+import org.onosproject.yang.model.ModelConverter;
+import org.onosproject.yang.model.ModelObjectData;
+import org.onosproject.yang.model.ResourceData;
+import org.onosproject.yang.model.ResourceId;
+import org.onosproject.yang.model.SchemaContext;
+import org.onosproject.yang.model.SchemaContextProvider;
+import org.onosproject.yang.runtime.AnnotatedNodeInfo;
+import org.onosproject.yang.runtime.CompositeData;
+import org.onosproject.yang.runtime.CompositeStream;
+import org.onosproject.yang.runtime.DefaultCompositeData;
+import org.onosproject.yang.runtime.DefaultCompositeStream;
+import org.onosproject.yang.runtime.DefaultYangSerializerContext;
+import org.onosproject.yang.runtime.YangModelRegistry;
+import org.onosproject.yang.runtime.YangSerializer;
+import org.onosproject.yang.runtime.YangSerializerContext;
+import org.onosproject.yang.runtime.YangSerializerRegistry;
+import org.onosproject.yang.serializers.xml.XmlSerializer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Abstract class that implements some of the core functions of a YANG model service.
+ *
+ */
+@Component(immediate = true)
+@Service
+public abstract class AbstractYangServiceImpl {
+    public static final String NC_OPERATION = "nc:operation";
+    public static final String OP_DELETE = "delete";
+
+    protected final Logger log = LoggerFactory.getLogger(getClass());
+    protected boolean alreadyLoaded = false;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected CoreService coreService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected YangModelRegistry yangModelRegistry;
+
+//    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+//    protected SchemaContextProvider schemaContextProvider;
+
+    protected ApplicationId appId;
+
+    // xSer is not a service and is a class variable. Can be lost on deactivate.
+    // Must be recreated on activate
+    protected XmlSerializer xSer;
+    protected YangSerializerContext yCtx;
+
+    protected static final Pattern REGEX_XML_HEADER =
+            Pattern.compile("(<\\?xml).*(\\?>)", Pattern.DOTALL);
+    protected static final Pattern REGEX_RPC_REPLY =
+            Pattern.compile("(<rpc-reply)[ ]*" +
+                    "(xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\")[ ]*" +
+                    "(message-id=\")[0-9]*(\">)", Pattern.DOTALL);
+    protected static final Pattern REGEX_RPC_REPLY_DATA_NS =
+            Pattern.compile("(<data)[ ]*(xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">)");
+    protected static final Pattern REGEX_RPC_REPLY_DATA =
+            Pattern.compile("(<data>)");
+    protected static final Pattern REGEX_RPC_REPLY_DATA_CLOSE =
+            Pattern.compile("(</data>)");
+    protected static final Pattern REGEX_RPC_REPLY_DATA_EMPTY =
+            Pattern.compile("(<data/>)");
+    protected static final Pattern REGEX_RPC_REPLY_CLOSE =
+            Pattern.compile("(</rpc-reply>)");
+
+    @Activate
+    public void activate() {
+        Set<YangSerializer> yangSer = ((YangSerializerRegistry) yangModelRegistry).getSerializers();
+        yangSer.forEach(ser -> {
+            if (ser instanceof XmlSerializer) {
+                xSer = (XmlSerializer) ser;
+            }
+        });
+        SchemaContext context = ((SchemaContextProvider) yangModelRegistry)
+                .getSchemaContext(ResourceId.builder().addBranchPointSchema("/", null).build());
+
+        yCtx = new DefaultYangSerializerContext(context, null);
+    };
+
+    @Deactivate
+    public void deactivate() {
+        alreadyLoaded = false;
+    }
+
+    /**
+     * Internal method to generically make a NETCONF get query from YANG objects.
+     * @param moFilter A YANG object model
+     * @param session A NETCONF session
+     * @return YangObjectModel
+     * @throws NetconfException if the session has any error
+     */
+    protected final ModelObjectData getNetconfObject(
+            ModelObjectData moFilter, NetconfSession session)
+                throws NetconfException {
+
+        return getConfigNetconfObject(moFilter, session, null);
+    }
+
+    /**
+     * Internal method to generically make a NETCONF get-config query from YANG objects.
+     *
+     * @param moFilter A YANG object model
+     * @param session A NETCONF session
+     * @param targetDs - running,candidate or startup
+     * @return YangObjectModel
+     * @throws NetconfException if the session has any error
+     */
+    protected final ModelObjectData getConfigNetconfObject(
+            ModelObjectData moFilter, NetconfSession session, DatastoreId targetDs)
+                throws NetconfException {
+        if (session == null) {
+            throw new NetconfException("Session is null when calling getConfigNetconfObject()");
+        }
+
+        if (moFilter == null) {
+            throw new NetconfException("Query object cannot be null");
+        }
+
+        String xmlQueryStr = encodeMoToXmlStr(moFilter, null);
+
+        log.debug("Sending <get-(config)> query on NETCONF session " + session.getSessionId() +
+                ":\n" + xmlQueryStr);
+        String xmlResult;
+        if (targetDs == null) {
+            xmlResult = session.get(xmlQueryStr, null);
+        } else {
+            xmlResult = session.getConfig(targetDs, xmlQueryStr);
+        }
+        xmlResult = removeRpcReplyData(xmlResult);
+
+        DefaultCompositeStream resultDcs = new DefaultCompositeStream(
+                null, new ByteArrayInputStream(xmlResult.getBytes()));
+        CompositeData compositeData = xSer.decode(resultDcs, yCtx);
+
+        return ((ModelConverter) yangModelRegistry).createModel(compositeData.resourceData());
+    }
+
+    /**
+     * Internal method to generically make a NETCONF edit-config call from a set of YANG objects.
+     *
+     * @param moConfig A YANG object model
+     * @param session A NETCONF session
+     * @param targetDs - running,candidate or startup
+     * @param annotations A list of AnnotatedNodeInfos to be added to the DataNodes
+     * @return Boolean value indicating success or failure of command
+     * @throws NetconfException if the session has any error
+     */
+    protected final boolean setNetconfObject(
+            ModelObjectData moConfig, NetconfSession session, DatastoreId targetDs,
+            List<AnnotatedNodeInfo> annotations) throws NetconfException {
+        if (moConfig == null) {
+            throw new NetconfException("Query object cannot be null");
+        } else if (session == null) {
+            throw new NetconfException("Session is null when calling getMseaSaFiltering()");
+        } else if (targetDs == null) {
+            throw new NetconfException("TargetDs is null when calling getMseaSaFiltering()");
+        }
+
+        String xmlQueryStr = encodeMoToXmlStr(moConfig, annotations);
+        log.debug("Sending <edit-config> query on NETCONF session " + session.getSessionId() +
+                ":\n" + xmlQueryStr);
+
+        return session.editConfig(targetDs, null, xmlQueryStr);
+    }
+
+    protected final String encodeMoToXmlStr(ModelObjectData yangObjectOpParamFilter,
+                                            List<AnnotatedNodeInfo> annotations)
+            throws NetconfException {
+        //Convert the param to XML to use as a filter
+        ResourceData rd = ((ModelConverter) yangModelRegistry).createDataNode(yangObjectOpParamFilter);
+
+        DefaultCompositeData.Builder cdBuilder =
+                        DefaultCompositeData.builder().resourceData(rd);
+        if (annotations != null) {
+            for (AnnotatedNodeInfo ani : annotations) {
+                cdBuilder.addAnnotatedNodeInfo(ani);
+            }
+        }
+        CompositeStream cs = xSer.encode(cdBuilder.build(), yCtx);
+        //Convert the param to XML to use as a filter
+
+        try {
+            ByteSource byteSource = new ByteSource() {
+                @Override
+                public InputStream openStream() throws IOException {
+                    return cs.resourceData();
+                }
+            };
+
+            return byteSource.asCharSource(Charsets.UTF_8).read();
+        } catch (IOException e) {
+            throw new NetconfException("Error decoding CompositeStream to String", e);
+        }
+    }
+
+    protected static final String removeRpcReplyData(String rpcReplyXml) {
+        rpcReplyXml = REGEX_XML_HEADER.matcher(rpcReplyXml).replaceFirst("");
+        rpcReplyXml = REGEX_RPC_REPLY.matcher(rpcReplyXml).replaceFirst("");
+        rpcReplyXml = REGEX_RPC_REPLY_DATA_NS.matcher(rpcReplyXml).replaceFirst("");
+        rpcReplyXml = REGEX_RPC_REPLY_DATA.matcher(rpcReplyXml).replaceFirst("");
+        rpcReplyXml = REGEX_RPC_REPLY_DATA_CLOSE.matcher(rpcReplyXml).replaceFirst("");
+        rpcReplyXml = REGEX_RPC_REPLY_DATA_EMPTY.matcher(rpcReplyXml).replaceFirst("");
+        rpcReplyXml = REGEX_RPC_REPLY_CLOSE.matcher(rpcReplyXml).replaceFirst("");
+        rpcReplyXml = rpcReplyXml.replace("\t", "");
+        return rpcReplyXml;
+    }
+}
diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/IetfSystemManager.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/IetfSystemManager.java
new file mode 100644
index 0000000..3673594
--- /dev/null
+++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/IetfSystemManager.java
@@ -0,0 +1,215 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi.yang.impl;
+
+import java.io.ByteArrayInputStream;
+import java.time.OffsetDateTime;
+import java.time.format.DateTimeFormatter;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Service;
+import org.onosproject.drivers.microsemi.yang.IetfSystemNetconfService;
+import org.onosproject.netconf.DatastoreId;
+import org.onosproject.netconf.NetconfException;
+import org.onosproject.netconf.NetconfSession;
+import org.onosproject.yang.gen.v1.ietfsystem.rev20140806.ietfsystem.DefaultSystem;
+import org.onosproject.yang.gen.v1.ietfsystem.rev20140806.ietfsystem.DefaultSystemState;
+import org.onosproject.yang.gen.v1.ietfsystemmicrosemi.rev20160505.ietfsystemmicrosemi.doupgradeandreboot.DoUpgradeAndRebootInput;
+import org.onosproject.yang.gen.v1.ietfsystemmicrosemi.rev20160505.ietfsystemmicrosemi.doupgradeandreboot.DoUpgradeAndRebootOutput;
+import org.onosproject.yang.gen.v1.ietfsystemmicrosemi.rev20160505.ietfsystemmicrosemi.pullupdatetarfromtftp.PullUpdateTarFromTftpInput;
+import org.onosproject.yang.gen.v1.ietfsystemmicrosemi.rev20160505.ietfsystemmicrosemi.readfromsyslog.ReadFromSyslogInput;
+import org.onosproject.yang.gen.v1.ietfsystemmicrosemi.rev20160505.ietfsystemmicrosemi.readfromsyslog.ReadFromSyslogOutput;
+import org.onosproject.yang.gen.v1.ietfsystem.rev20140806.IetfSystem;
+import org.onosproject.yang.gen.v1.ietfsystem.rev20140806.IetfSystemOpParam;
+import org.onosproject.yang.gen.v1.ietfsystem.rev20140806.ietfsystem.systemrestart.SystemRestartInput;
+import org.onosproject.yang.model.DefaultModelObjectData;
+import org.onosproject.yang.model.ModelConverter;
+import org.onosproject.yang.model.ModelObject;
+import org.onosproject.yang.model.ModelObjectData;
+import org.onosproject.yang.runtime.CompositeData;
+import org.onosproject.yang.runtime.DefaultCompositeStream;
+
+/**
+ * Implementation of the IetfService YANG model service.
+ */
+@Component(immediate = true, inherit = true)
+@Service
+public class IetfSystemManager extends AbstractYangServiceImpl
+    implements IetfSystemNetconfService {
+
+    protected static final String IETF_SYSTEM = "org.onosproject.drivers.microsemi.yang.ietfsystem";
+
+    @Activate
+    public void activate() {
+        super.activate();
+        appId = coreService.registerApplication(IETF_SYSTEM);
+        log.info("IetfSystemManager Started");
+    }
+
+    @Deactivate
+    public void deactivate() {
+        super.deactivate();
+        log.info("IetfSystemManager Stopped");
+    }
+
+    /**
+     * Get a filtered subset of the model.
+     * This is meant to filter the current live model
+     * against the attribute(s) given in the argument
+     * and return the filtered model.
+     * @throws NetconfException if the session has any error
+     */
+    @Override
+    public IetfSystem getIetfSystem(IetfSystemOpParam ietfSystemFilter, NetconfSession session)
+            throws NetconfException {
+
+        ModelObjectData moQuery = DefaultModelObjectData.builder()
+                .addModelObject((ModelObject) ietfSystemFilter.system())
+                .build();
+
+        ModelObjectData moReply = getNetconfObject(moQuery, session);
+
+        IetfSystemOpParam ietfSystem = new IetfSystemOpParam();
+        for (ModelObject mo:moReply.modelObjects()) {
+            if (mo instanceof DefaultSystem) {
+                ietfSystem.system((DefaultSystem) mo);
+            } else if (mo instanceof DefaultSystemState) {
+                ietfSystem.systemState((DefaultSystemState) mo);
+            }
+        }
+
+        return ietfSystem;
+    }
+
+    @Override
+    public IetfSystem getIetfSystemInit(NetconfSession session) throws NetconfException {
+        if (session == null) {
+            throw new NetconfException("Session is null when calling getIetfSystemInit()");
+        }
+
+        String xmlResult = session.get(getInitRequestBuilder(), null);
+
+        xmlResult = removeRpcReplyData(xmlResult);
+        DefaultCompositeStream resultDcs = new DefaultCompositeStream(
+                null, new ByteArrayInputStream(xmlResult.getBytes()));
+        CompositeData compositeData = xSer.decode(resultDcs, yCtx);
+
+        ModelObjectData mod = ((ModelConverter) yangModelRegistry).createModel(compositeData.resourceData());
+
+        IetfSystemOpParam ietfSystem = new IetfSystemOpParam();
+        for (ModelObject mo:mod.modelObjects()) {
+            if (mo instanceof DefaultSystem) {
+                ietfSystem.system((DefaultSystem) mo);
+            } else if (mo instanceof DefaultSystemState) {
+                ietfSystem.systemState((DefaultSystemState) mo);
+            }
+        }
+
+        return ietfSystem;
+    }
+
+    /**
+     * Call NETCONF edit-config with a configuration.
+     */
+    @Override
+    public boolean setIetfSystem(IetfSystemOpParam ietfSystem, NetconfSession session,
+                              DatastoreId ncDs) throws NetconfException {
+        ModelObjectData mo = DefaultModelObjectData.builder()
+                                .addModelObject(ietfSystem).build();
+        return setNetconfObject(mo, session, ncDs, null);
+    }
+
+    @Override
+    public void setCurrentDatetime(OffsetDateTime date, NetconfSession session)
+            throws NetconfException {
+        String xmlQueryStr = getSetCurrentDatetimeBuilder(date);
+        log.info("Sending <get> query on NETCONF session " + session.getSessionId() +
+                ":\n" + xmlQueryStr);
+
+        String xmlResult = session.doWrappedRpc(xmlQueryStr);
+        log.info("Result from NETCONF RPC <set-current-datetime>: {}", xmlResult);
+    }
+
+    @Override
+    public void systemRestart(SystemRestartInput inputVar, NetconfSession session) {
+        throw new UnsupportedOperationException("Not yet implemented");
+    }
+
+    @Override
+    public void systemShutdown(NetconfSession session) {
+        throw new UnsupportedOperationException("Not yet implemented");
+    }
+
+    @Override
+    public DoUpgradeAndRebootOutput doUpgradeAndReboot(DoUpgradeAndRebootInput inputVar, NetconfSession session)
+            throws NetconfException {
+        throw new UnsupportedOperationException("Not yet implemented");
+    }
+
+    @Override
+    public void pullUpdateTarFromTftp(PullUpdateTarFromTftpInput inputVar, NetconfSession session)
+            throws NetconfException {
+        throw new UnsupportedOperationException("Not yet implemented");
+    }
+
+    @Override
+    public ReadFromSyslogOutput readFromSyslog(ReadFromSyslogInput inputVar, NetconfSession session)
+            throws NetconfException {
+        throw new UnsupportedOperationException("Not yet implemented");
+    }
+
+
+    /**
+     * Builds a request crafted to get the configuration required to create
+     * details descriptions for the device.
+     *
+     * @return The request string.
+     */
+    private static String getInitRequestBuilder() {
+        StringBuilder rpc = new StringBuilder();
+        rpc.append("<system-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-system\" ");
+        rpc.append("xmlns:sysms=\"http://www.microsemi.com/microsemi-edge-assure/msea-system\">");
+        rpc.append("<platform>");
+        rpc.append("<os-release/>");
+        rpc.append("<sysms:device-identification>");
+        rpc.append("<sysms:serial-number/>");
+        rpc.append("</sysms:device-identification>");
+        rpc.append("</platform>");
+        rpc.append("<clock>");
+        rpc.append("<current-datetime/>");
+        rpc.append("</clock>");
+        rpc.append("</system-state>");
+        rpc.append("<system xmlns=\"urn:ietf:params:xml:ns:yang:ietf-system\" ");
+        rpc.append("xmlns:sysms=\"http://www.microsemi.com/microsemi-edge-assure/msea-system\">");
+        rpc.append("<sysms:longitude/>");
+        rpc.append("<sysms:latitude/>");
+        rpc.append("</system>");
+        return rpc.toString();
+    }
+
+    private static String getSetCurrentDatetimeBuilder(OffsetDateTime date) {
+        StringBuilder rpc = new StringBuilder();
+        rpc.append("<set-current-datetime xmlns=\"urn:ietf:params:xml:ns:yang:ietf-system\">");
+        rpc.append("<current-datetime>");
+        rpc.append(date.format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssxxx")));
+        rpc.append("</current-datetime>");
+        rpc.append("</set-current-datetime>");
+
+        return rpc.toString();
+    }
+}
diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/MseaCfmManager.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/MseaCfmManager.java
new file mode 100644
index 0000000..36f48c4
--- /dev/null
+++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/MseaCfmManager.java
@@ -0,0 +1,200 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi.yang.impl;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Service;
+import org.onosproject.drivers.microsemi.yang.MseaCfmNetconfService;
+import org.onosproject.netconf.DatastoreId;
+import org.onosproject.netconf.NetconfException;
+import org.onosproject.netconf.NetconfSession;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.MseaCfm;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.MseaCfmOpParam;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.DefaultMefCfm;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.abortloopback.AbortLoopbackInput;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.transmitlinktrace.TransmitLinktraceInput;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.transmitlinktrace.TransmitLinktraceOutput;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.transmitloopback.TransmitLoopbackInput;
+import org.onosproject.yang.model.DefaultModelObjectData;
+import org.onosproject.yang.model.ModelConverter;
+import org.onosproject.yang.model.ModelObject;
+import org.onosproject.yang.model.ModelObjectData;
+import org.onosproject.yang.runtime.CompositeData;
+import org.onosproject.yang.runtime.DefaultCompositeStream;
+
+import java.io.ByteArrayInputStream;
+
+/**
+ * Implementation of the MseaCfmServiceNetconf YANG model service.
+ */
+@Component(immediate = true, inherit = true)
+@Service
+public class MseaCfmManager extends AbstractYangServiceImpl
+    implements MseaCfmNetconfService {
+
+    public static final String MSEA_CFM = "org.onosproject.drivers.microsemi.yang.mseacfmservice";
+
+    @Activate
+    public void activate() {
+        super.activate();
+        appId = coreService.registerApplication(MSEA_CFM);
+        log.info("MseaCfmService Started");
+    }
+
+    @Deactivate
+    public void deactivate() {
+        super.deactivate();
+        log.info("MseaCfmService Stopped");
+    }
+
+    @Override
+    public MseaCfm getMepEssentials(String mdName, String maName, int mepId,
+            NetconfSession session) throws NetconfException {
+        if (session == null) {
+            throw new NetconfException("Session is null when calling getMepEssentials()");
+        }
+
+        String xmlQueryStr = buildMepQueryString(mdName, maName, mepId);
+        log.debug("Sending <get> for " +
+                " query on NETCONF session " + session.getSessionId() +
+                ":\n" + xmlQueryStr);
+
+        String xmlResult = session.get(xmlQueryStr, null);
+
+        xmlResult = removeRpcReplyData(xmlResult);
+        DefaultCompositeStream resultDcs = new DefaultCompositeStream(
+                null, new ByteArrayInputStream(xmlResult.getBytes()));
+        CompositeData compositeData = xSer.decode(resultDcs, yCtx);
+
+        ModelObjectData mod = ((ModelConverter) yangModelRegistry).createModel(compositeData.resourceData());
+
+        MseaCfmOpParam mseaCfm = new MseaCfmOpParam();
+        for (ModelObject mo:mod.modelObjects()) {
+            if (mo instanceof DefaultMefCfm) {
+                mseaCfm.mefCfm((DefaultMefCfm) mo);
+            }
+        }
+
+        return mseaCfm;
+    }
+
+    @Override
+    public MseaCfm getSoamDm(String mdName, String maName, int mepId,
+            int dmId, NetconfSession session) throws NetconfException {
+        String xmlQueryStr = buildDmQueryString(mdName, maName, mepId, dmId);
+        throw new UnsupportedOperationException("Not yet implemented");
+    }
+
+    @Override
+    public boolean setMseaCfm(MseaCfmOpParam mseaCfm, NetconfSession session,
+              DatastoreId targetDs) throws NetconfException {
+        ModelObjectData moEdit = DefaultModelObjectData.builder()
+                .addModelObject(mseaCfm).build();
+
+        return setNetconfObject(moEdit, session, targetDs, null);
+    }
+
+    /**
+     * Call RPCs on the device through NETCONF.
+     */
+    @Override
+    public void transmitLoopback(TransmitLoopbackInput inputVar, NetconfSession session) throws NetconfException {
+        throw new UnsupportedOperationException("Not yet implemented");
+    }
+
+    @Override
+    public void abortLoopback(AbortLoopbackInput inputVar, NetconfSession session) throws NetconfException {
+        throw new UnsupportedOperationException("Not yet implemented");
+    }
+
+    @Override
+    public TransmitLinktraceOutput transmitLinktrace(TransmitLinktraceInput inputVar, NetconfSession session)
+            throws NetconfException {
+        throw new UnsupportedOperationException("Not yet implemented");
+    }
+
+    private String buildMepQueryString(String mdName, String maName, int mepId) {
+        StringBuilder rpc = new StringBuilder();
+
+        rpc.append("<mef-cfm xmlns=\"http://www.microsemi.com/microsemi-edge-assure/msea-cfm\" ");
+        rpc.append(" xmlns:msea-soam-fm=\"http://www.microsemi.com/microsemi-edge-assure/msea-soam-fm\" ");
+        rpc.append("xmlns:msea-soam-pm=\"http://www.microsemi.com/microsemi-edge-assure/msea-soam-pm\">\n");
+        rpc.append("<maintenance-domain>\n");
+        rpc.append("<id/>\n");
+        rpc.append("<name>" + mdName + "</name>\n");
+        rpc.append("<md-level/>\n");
+        rpc.append("<maintenance-association>\n");
+        rpc.append("<id/>\n");
+        rpc.append("<name>" + maName + "</name>\n");
+        rpc.append("<ccm-interval>10ms</ccm-interval>\n");
+        rpc.append("<remote-meps/>\n");
+        rpc.append("<component-list/>\n");
+        rpc.append("<maintenance-association-end-point>\n");
+        rpc.append("<mep-identifier>" + mepId + "</mep-identifier>\n");
+        rpc.append("<interface/>\n");
+        rpc.append("<primary-vid/>\n");
+        rpc.append("<administrative-state/>\n");
+        rpc.append("<ccm-ltm-priority/>\n");
+        rpc.append("<continuity-check/>\n");
+        rpc.append("<mac-address/>\n");
+        rpc.append("<msea-soam-fm:port-status/>\n");
+        rpc.append("<msea-soam-fm:interface-status/>\n");
+        rpc.append("<msea-soam-fm:last-defect-sent/>\n");
+        rpc.append("<msea-soam-fm:rdi-transmit-status/>\n");
+        rpc.append("<loopback/>\n");
+        rpc.append("<remote-mep-database/>\n");
+        rpc.append("<linktrace/>\n");
+        rpc.append("</maintenance-association-end-point>\n");
+        rpc.append("</maintenance-association>\n");
+        rpc.append("</maintenance-domain>\n");
+        rpc.append("</mef-cfm>");
+
+        return rpc.toString();
+    }
+
+
+    private String buildDmQueryString(String mdName, String maName, int mepId, int dmId) {
+        StringBuilder rpc = new StringBuilder();
+
+        rpc.append("<mef-cfm xmlns=\"http://www.microsemi.com/microsemi-edge-assure/msea-cfm\" ");
+        rpc.append(" xmlns:msea-soam-fm=\"http://www.microsemi.com/microsemi-edge-assure/msea-soam-fm\" ");
+        rpc.append("xmlns:msea-soam-pm=\"http://www.microsemi.com/microsemi-edge-assure/msea-soam-pm\">\n");
+        rpc.append("<maintenance-domain>\n");
+        rpc.append("<id/>\n");
+        rpc.append("<name>" + mdName + "</name>\n");
+        rpc.append("<md-level/>\n");
+        rpc.append("<maintenance-association>\n");
+        rpc.append("<id/>\n");
+        rpc.append("<name>" + maName + "</name>\n");
+        rpc.append("<ccm-interval>10ms</ccm-interval>\n");
+        rpc.append("<maintenance-association-end-point>\n");
+        rpc.append("<mep-identifier>" + mepId + "</mep-identifier>\n");
+        rpc.append("<msea-soam-pm:delay-measurements>");
+        rpc.append("<msea-soam-pm:delay-measurement>");
+        rpc.append("<msea-soam-pm:dm-id>" + dmId + "</msea-soam-pm:dm-id>");
+        rpc.append("</msea-soam-pm:delay-measurement>");
+        rpc.append("</msea-soam-pm:delay-measurements>");
+        rpc.append("</maintenance-association-end-point>\n");
+        rpc.append("</maintenance-association>\n");
+        rpc.append("</maintenance-domain>\n");
+        rpc.append("</mef-cfm>");
+
+        return rpc.toString();
+    }
+
+}
diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/MseaSaFilteringManager.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/MseaSaFilteringManager.java
new file mode 100644
index 0000000..01af138
--- /dev/null
+++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/MseaSaFilteringManager.java
@@ -0,0 +1,202 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi.yang.impl;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Service;
+import org.onosproject.drivers.microsemi.yang.MseaSaFilteringNetconfService;
+import org.onosproject.netconf.DatastoreId;
+import org.onosproject.netconf.NetconfException;
+import org.onosproject.netconf.NetconfSession;
+import org.onosproject.yang.gen.v1.mseasafiltering.rev20160412.MseaSaFiltering;
+import org.onosproject.yang.gen.v1.mseasafiltering.rev20160412.MseaSaFilteringOpParam;
+import org.onosproject.yang.gen.v1.mseasafiltering.rev20160412.mseasafiltering.SourceIpaddressFiltering;
+import org.onosproject.yang.gen.v1.mseasafiltering.rev20160412.mseasafiltering.sourceipaddressfiltering.interfaceeth0.SourceAddressRange;
+import org.onosproject.yang.model.DefaultModelObjectData;
+import org.onosproject.yang.model.ModelConverter;
+import org.onosproject.yang.model.ModelObject;
+import org.onosproject.yang.model.ModelObjectData;
+import org.onosproject.yang.model.ResourceId;
+import org.onosproject.yang.runtime.AnnotatedNodeInfo;
+import org.onosproject.yang.runtime.CompositeData;
+import org.onosproject.yang.runtime.DefaultAnnotatedNodeInfo;
+import org.onosproject.yang.runtime.DefaultAnnotation;
+import org.onosproject.yang.runtime.DefaultCompositeStream;
+
+import java.io.ByteArrayInputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Implementation of the MseaSaFiltering YANG model service.
+ */
+@Component(immediate = true, inherit = true)
+@Service
+public class MseaSaFilteringManager extends AbstractYangServiceImpl
+    implements MseaSaFilteringNetconfService {
+    public static final String MSEA_SA_FILTERING =
+            "org.onosproject.drivers.microsemi.yang.mseasafiltering";
+    public static final String MSEA_SA_FILTERING_NS =
+            "http://www.microsemi.com/microsemi-edge-assure/msea-sa-filtering";
+
+    @Activate
+    public void activate() {
+        super.activate();
+        appId = coreService.registerApplication(MSEA_SA_FILTERING);
+        log.info("MseaSaFilteringManager Started");
+    }
+
+    @Deactivate
+    public void deactivate() {
+        super.deactivate();
+        log.info("MseaSaFilteringManager Stopped");
+    }
+
+    /**
+     * Get a filtered subset of the model.
+     * This is meant to filter the current live model
+     * against the attribute(s) given in the argument
+     * and return the filtered model.
+     */
+    @Override
+    public MseaSaFiltering getMseaSaFiltering(
+            MseaSaFilteringOpParam mseaSaFilteringFilter, NetconfSession session)
+            throws NetconfException {
+        ModelObjectData moQuery = DefaultModelObjectData.builder()
+                .addModelObject((ModelObject) mseaSaFilteringFilter
+                        .sourceIpaddressFiltering())
+                .build();
+
+
+        ModelObjectData moReply = getNetconfObject(moQuery, session);
+
+        MseaSaFiltering reply = new MseaSaFilteringOpParam();
+        for (ModelObject mo:moReply.modelObjects()) {
+            if (mo instanceof SourceIpaddressFiltering) {
+                reply.sourceIpaddressFiltering((SourceIpaddressFiltering) mo);
+            }
+        }
+        return reply;
+    }
+
+    /**
+     * Get a filtered subset of the config model (from running)
+     * This is meant to filter the current live model
+     * against the attribute(s) given in the argument
+     * and return the filtered model.
+     */
+    @Override
+    public List<SourceAddressRange> getConfigMseaSaFilterIds(NetconfSession session)
+            throws NetconfException {
+
+        String xmlResult = session.getConfig(DatastoreId.RUNNING, saFilterQuery());
+        xmlResult = removeRpcReplyData(xmlResult);
+
+        DefaultCompositeStream resultDcs = new DefaultCompositeStream(
+                null, new ByteArrayInputStream(xmlResult.getBytes()));
+        CompositeData compositeData = xSer.decode(resultDcs, yCtx);
+
+        ModelObjectData moReply = ((ModelConverter) yangModelRegistry).createModel(compositeData.resourceData());
+
+        MseaSaFiltering reply = new MseaSaFilteringOpParam();
+        for (ModelObject mo:moReply.modelObjects()) {
+            if (mo instanceof SourceIpaddressFiltering) {
+                reply.sourceIpaddressFiltering((SourceIpaddressFiltering) mo);
+            }
+        }
+        if (reply != null && reply.sourceIpaddressFiltering() != null &&
+                reply.sourceIpaddressFiltering().interfaceEth0() != null) {
+            return reply.sourceIpaddressFiltering().interfaceEth0().sourceAddressRange();
+        } else {
+            return new ArrayList<SourceAddressRange>();
+        }
+    }
+
+    /**
+     * Call NETCONF edit-config with a configuration.
+     */
+    @Override
+    public boolean setMseaSaFiltering(MseaSaFilteringOpParam mseaSaFiltering,
+           NetconfSession session, DatastoreId ncDs) throws NetconfException {
+
+        ModelObjectData moQuery = DefaultModelObjectData.builder()
+                .addModelObject((ModelObject) mseaSaFiltering
+                        .sourceIpaddressFiltering()).build();
+
+        return setNetconfObject(moQuery, session, ncDs, null);
+    }
+
+    @Override
+    public boolean deleteMseaSaFilteringRange(MseaSaFilteringOpParam mseaSaFiltering,
+                                      NetconfSession session, DatastoreId ncDs) throws NetconfException {
+
+        ModelObjectData moQuery = DefaultModelObjectData.builder()
+                .addModelObject((ModelObject) mseaSaFiltering
+                        .sourceIpaddressFiltering()).build();
+
+        ArrayList anis = new ArrayList<AnnotatedNodeInfo>();
+        if (mseaSaFiltering.sourceIpaddressFiltering().interfaceEth0() != null &&
+                mseaSaFiltering.sourceIpaddressFiltering().interfaceEth0().sourceAddressRange() != null) {
+
+            for (SourceAddressRange sar:mseaSaFiltering.sourceIpaddressFiltering()
+                    .interfaceEth0().sourceAddressRange()) {
+                String sarRangeIdStr = String.valueOf(sar.rangeId());
+
+                ResourceId.Builder ridBuilder = ResourceId.builder()
+                        .addBranchPointSchema("/", null)
+                        .addBranchPointSchema("source-ipaddress-filtering", MSEA_SA_FILTERING_NS)
+                        .addBranchPointSchema("interface-eth0", MSEA_SA_FILTERING_NS)
+                        .addBranchPointSchema("source-address-range", MSEA_SA_FILTERING_NS)
+                        .addKeyLeaf("range-id", MSEA_SA_FILTERING_NS, sarRangeIdStr);
+
+                AnnotatedNodeInfo ani = DefaultAnnotatedNodeInfo.builder()
+                        .resourceId(ridBuilder.build())
+                        .addAnnotation(new DefaultAnnotation(NC_OPERATION, OP_DELETE))
+                        .build();
+
+                anis.add(ani);
+            }
+        } else {
+            //Delete all
+            ResourceId.Builder ridBuilder = ResourceId.builder()
+                    .addBranchPointSchema("/", null)
+                    .addBranchPointSchema("source-ipaddress-filtering", MSEA_SA_FILTERING_NS);
+            AnnotatedNodeInfo ani = DefaultAnnotatedNodeInfo.builder()
+                    .resourceId(ridBuilder.build())
+                    .addAnnotation(new DefaultAnnotation(NC_OPERATION, OP_DELETE))
+                    .build();
+            anis.add(ani);
+        }
+
+        return setNetconfObject(moQuery, session, ncDs, anis);
+    }
+
+
+    private static String saFilterQuery() {
+        StringBuilder sb = new StringBuilder("<source-ipaddress-filtering " +
+                "xmlns=\"http://www.microsemi.com/microsemi-edge-assure/msea-sa-filtering\">");
+        sb.append("<interface-eth0>");
+        sb.append("<filter-admin-state>blacklist</filter-admin-state>");
+        sb.append("<source-address-range>");
+        sb.append("<range-id/>");
+        sb.append("</source-address-range>");
+        sb.append("</interface-eth0>");
+        sb.append("</source-ipaddress-filtering>");
+        return sb.toString();
+    }
+}
diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/MseaUniEvcServiceManager.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/MseaUniEvcServiceManager.java
new file mode 100644
index 0000000..f965541
--- /dev/null
+++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/MseaUniEvcServiceManager.java
@@ -0,0 +1,292 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.microsemi.yang.impl;
+
+import java.io.ByteArrayInputStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Service;
+import org.onosproject.drivers.microsemi.yang.MseaUniEvcServiceNetconfService;
+import org.onosproject.netconf.DatastoreId;
+import org.onosproject.netconf.NetconfException;
+import org.onosproject.netconf.NetconfSession;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.MseaUniEvcService;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.MseaUniEvcServiceOpParam;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.MefServices;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.profiles.BwpGroup;
+import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.uni.UniSideInterfaceAssignmentEnum;
+import org.onosproject.yang.model.DefaultModelObjectData;
+import org.onosproject.yang.model.ModelConverter;
+import org.onosproject.yang.model.ModelObject;
+import org.onosproject.yang.model.ModelObjectData;
+import org.onosproject.yang.model.ResourceId;
+import org.onosproject.yang.runtime.AnnotatedNodeInfo;
+import org.onosproject.yang.runtime.CompositeData;
+import org.onosproject.yang.runtime.DefaultAnnotatedNodeInfo;
+import org.onosproject.yang.runtime.DefaultAnnotation;
+import org.onosproject.yang.runtime.DefaultCompositeStream;
+
+/**
+ * Implementation of the MseaUniEvcServiceService YANG model service.
+ */
+@Component(immediate = true, inherit = true)
+@Service
+public class MseaUniEvcServiceManager extends AbstractYangServiceImpl
+        implements MseaUniEvcServiceNetconfService {
+    public static final String MSEA_UNI_EVC_SVC =
+            "org.onosproject.drivers.microsemi.yang.mseaunievcservice";
+    public static final String MSEA_UNI_EVC_SVC_NS =
+            "http://www.microsemi.com/microsemi-edge-assure/msea-uni-evc-service";
+
+    @Activate
+    public void activate() {
+        super.activate();
+        appId = coreService.registerApplication(MSEA_UNI_EVC_SVC);
+        log.info("MseaUniEvcServiceManager Started");
+    }
+
+    @Deactivate
+    public void deactivate() {
+        super.deactivate();
+        log.info("MseaUniEvcServiceManager Stopped");
+    }
+
+    @Override
+    public MseaUniEvcService getMseaUniEvcService(
+            MseaUniEvcServiceOpParam mseaUniEvcService, NetconfSession session)
+            throws NetconfException {
+
+        return getConfigMseaUniEvcService(mseaUniEvcService, session, null);
+    }
+
+    @Override
+    public MseaUniEvcService getConfigMseaUniEvcService(
+            MseaUniEvcServiceOpParam mseaUniEvcService, NetconfSession session,
+            DatastoreId targetDs) throws NetconfException {
+
+        ModelObjectData moFilter = DefaultModelObjectData.builder()
+                .addModelObject((ModelObject) mseaUniEvcService.mefServices()).build();
+
+        ModelObjectData moReply = getConfigNetconfObject(moFilter, session, targetDs);
+
+        MseaUniEvcService reply = new MseaUniEvcServiceOpParam();
+        for (ModelObject mo:moReply.modelObjects()) {
+            if (mo instanceof MefServices) {
+                reply.mefServices((MefServices) mo);
+            }
+        }
+        return reply;
+    }
+
+    /**
+     * Modify the configuration.
+     */
+    @Override
+    public boolean setMseaUniEvcService(MseaUniEvcServiceOpParam mseaUniEvcService,
+                 NetconfSession session, DatastoreId ncDs) throws NetconfException {
+        ModelObjectData moEdit = DefaultModelObjectData.builder()
+                .addModelObject((ModelObject) mseaUniEvcService.mefServices()).build();
+
+        return setNetconfObject(moEdit, session, ncDs, null);
+    }
+
+    /**
+     * Delete the configuration.
+     */
+    @Override
+    public boolean deleteMseaUniEvcService(MseaUniEvcServiceOpParam mseaUniEvcService,
+                NetconfSession session, DatastoreId ncDs) throws NetconfException {
+        ModelObjectData moEdit = DefaultModelObjectData.builder()
+                .addModelObject((ModelObject) mseaUniEvcService.mefServices()).build();
+
+        ArrayList anis = new ArrayList<AnnotatedNodeInfo>();
+        for (BwpGroup bwpGrp:mseaUniEvcService.mefServices().profiles().bwpGroup()) {
+            String bwpGroupIndex = String.valueOf(bwpGrp.groupIndex());
+
+            ResourceId.Builder ridBuilder = ResourceId.builder()
+                    .addBranchPointSchema("/", null)
+                    .addBranchPointSchema("mef-services", MSEA_UNI_EVC_SVC_NS)
+                    .addBranchPointSchema("profiles", MSEA_UNI_EVC_SVC_NS)
+                    .addBranchPointSchema("bwp-group", MSEA_UNI_EVC_SVC_NS)
+                    .addKeyLeaf("group-index", MSEA_UNI_EVC_SVC_NS, bwpGroupIndex);
+
+            AnnotatedNodeInfo ani = DefaultAnnotatedNodeInfo.builder()
+                    .resourceId(ridBuilder.build())
+                    .addAnnotation(new DefaultAnnotation(NC_OPERATION, OP_DELETE))
+                    .build();
+
+            anis.add(ani);
+        }
+
+
+        return setNetconfObject(moEdit, session, ncDs, anis);
+    }
+
+
+    @Override
+    public MseaUniEvcService getmseaUniEvcCeVlanMaps(
+            NetconfSession session, DatastoreId ncDs)
+            throws NetconfException {
+        if (session == null) {
+            throw new NetconfException("Session is null when calling getMseaSaFiltering()");
+        }
+
+        String xmlResult = session.getConfig(ncDs, evcFilterQuery());
+        xmlResult = removeRpcReplyData(xmlResult);
+
+        DefaultCompositeStream resultDcs = new DefaultCompositeStream(
+                null, new ByteArrayInputStream(xmlResult.getBytes()));
+        CompositeData compositeData = xSer.decode(resultDcs, yCtx);
+
+        ModelObjectData moReply = ((ModelConverter) yangModelRegistry).createModel(compositeData.resourceData());
+
+        MseaUniEvcService reply = new MseaUniEvcServiceOpParam();
+        for (ModelObject mo:moReply.modelObjects()) {
+            if (mo instanceof MefServices) {
+                reply.mefServices((MefServices) mo);
+            }
+        }
+        return reply;
+    }
+
+    @Override
+    public void removeEvcUniFlowEntries(
+            Map<Integer, String> ceVlanUpdates,
+            Map<Integer, List<Short>> flowVlanIds,
+            NetconfSession session, DatastoreId targetDs,
+            UniSideInterfaceAssignmentEnum portAssign) throws NetconfException {
+
+        List<Integer> evcAlreadyHandled = new ArrayList<>();
+        StringBuilder xmlEvcUpdate = new StringBuilder(evcUniOpener());
+        for (Integer evcKey:ceVlanUpdates.keySet()) {
+            int evcId = (evcKey & ((1 << 8) - 100)) >> 2;
+            if (evcAlreadyHandled.contains(new Integer(evcId))) {
+                continue;
+            }
+            evcAlreadyHandled.add(evcId);
+            int port = (evcKey & 3);
+            String ceVlanMapThis = ceVlanUpdates.get(evcKey);
+            String ceVlanMapOpposite = ceVlanUpdates.get(evcKey ^ 1);
+
+            if ((ceVlanMapThis == null || ceVlanMapThis.isEmpty()) &&
+                    (ceVlanMapOpposite == null || ceVlanMapOpposite.isEmpty())) {
+                xmlEvcUpdate.append("<evc nc:operation=\"delete\">\n<evc-index>");
+                xmlEvcUpdate.append(Integer.toString(evcId));
+                xmlEvcUpdate.append("</evc-index>\n</evc>\n");
+            } else {
+                xmlEvcUpdate.append("<evc>\n<evc-index>");
+                xmlEvcUpdate.append(Integer.toString(evcId));
+                xmlEvcUpdate.append("</evc-index>\n<evc-per-uni>\n");
+                if (port == 0 && portAssign == UniSideInterfaceAssignmentEnum.UNI_C_ON_OPTICS ||
+                        port == 1 && portAssign == UniSideInterfaceAssignmentEnum.UNI_C_ON_HOST) {
+                    if (ceVlanMapThis != null) {
+                        xmlEvcUpdate.append("<evc-per-uni-c>\n<ce-vlan-map nc:operation=\"replace\">");
+                        xmlEvcUpdate.append(ceVlanMapThis);
+                        xmlEvcUpdate.append("</ce-vlan-map>\n");
+                        xmlEvcUpdate.append(deleteFlowMapping(flowVlanIds.get(evcKey)));
+                        xmlEvcUpdate.append("</evc-per-uni-c>\n");
+                    }
+                    if (ceVlanMapOpposite != null) {
+                        xmlEvcUpdate.append("<evc-per-uni-n>\n<ce-vlan-map nc:operation=\"replace\">");
+                        xmlEvcUpdate.append(ceVlanMapOpposite);
+                        xmlEvcUpdate.append("</ce-vlan-map>\n");
+                        xmlEvcUpdate.append(deleteFlowMapping(flowVlanIds.get(evcKey ^ 1)));
+                        xmlEvcUpdate.append("</evc-per-uni-n>\n");
+                    }
+                } else {
+                    if (ceVlanMapThis != null) {
+                        xmlEvcUpdate.append("<evc-per-uni-n>\n<ce-vlan-map nc:operation=\"replace\">");
+                        xmlEvcUpdate.append(ceVlanMapThis);
+                        xmlEvcUpdate.append("</ce-vlan-map>\n");
+                        xmlEvcUpdate.append(deleteFlowMapping(flowVlanIds.get(evcKey)));
+                        xmlEvcUpdate.append("</evc-per-uni-n>\n");
+                    }
+                    if (ceVlanMapOpposite != null) {
+                        xmlEvcUpdate.append("<evc-per-uni-c>\n<ce-vlan-map nc:operation=\"replace\">");
+                        xmlEvcUpdate.append(ceVlanMapOpposite);
+                        xmlEvcUpdate.append("</ce-vlan-map>\n");
+                        xmlEvcUpdate.append(deleteFlowMapping(flowVlanIds.get(evcKey ^ 1)));
+                        xmlEvcUpdate.append("</evc-per-uni-c>\n");
+                    }
+                }
+
+                xmlEvcUpdate.append("</evc-per-uni>\n</evc>\n");
+            }
+        }
+        xmlEvcUpdate.append("</uni>\n</mef-services>");
+
+        log.info("Sending XML <edit-config> on NETCONF session " + session.getSessionId() +
+                ":\n" + xmlEvcUpdate.toString());
+
+
+        session.editConfig(targetDs, null, xmlEvcUpdate.toString());
+    }
+
+
+    private static String deleteFlowMapping(List<Short> vlanIds) {
+        if (vlanIds == null || vlanIds.size() == 0) {
+            return "";
+        }
+        StringBuilder fmXmlBuilder = new StringBuilder();
+        for (long vlanId:vlanIds) {
+            fmXmlBuilder.append("<flow-mapping nc:operation=\"delete\">\n");
+            fmXmlBuilder.append("<ce-vlan-id>");
+            fmXmlBuilder.append(String.valueOf(vlanId));
+            fmXmlBuilder.append("</ce-vlan-id>\n");
+            fmXmlBuilder.append("</flow-mapping>\n");
+        }
+
+        return fmXmlBuilder.toString();
+    }
+
+    private String evcFilterQuery() {
+        StringBuilder sb = new StringBuilder("<mef-services "
+                + "xmlns=\"http://www.microsemi.com/microsemi-edge-assure/msea-uni-evc-service\">");
+        sb.append("<uni>");
+        sb.append("<evc>");
+        sb.append("<evc-index/>");
+        sb.append("<evc-per-uni>");
+        sb.append("<evc-per-uni-c>");
+        sb.append("<ce-vlan-map/>");
+        sb.append("<flow-mapping/>");
+        sb.append("<ingress-bwp-group-index/>");
+        sb.append("</evc-per-uni-c>");
+        sb.append("<evc-per-uni-n>");
+        sb.append("<ce-vlan-map/>");
+        sb.append("<flow-mapping/>");
+        sb.append("<ingress-bwp-group-index/>");
+        sb.append("</evc-per-uni-n>");
+        sb.append("</evc-per-uni>");
+        sb.append("</evc>");
+        sb.append("</uni>");
+        sb.append("</mef-services>");
+
+        return sb.toString();
+    }
+
+    private String evcUniOpener() {
+        StringBuilder sb = new StringBuilder("<mef-services ");
+        sb.append("xmlns=\"http://www.microsemi.com/microsemi-edge-assure/msea-uni-evc-service\">\n");
+        sb.append("<uni>\n");
+
+        return sb.toString();
+    }
+}
\ No newline at end of file
diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/package-info.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/package-info.java
new file mode 100644
index 0000000..ccf0dd2
--- /dev/null
+++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Package for Microsemi device drivers support for NETCONF for EA1000.
+ */
+package org.onosproject.drivers.microsemi.yang.impl;
\ No newline at end of file