http://git-wip-us.apache.org/repos/asf/cloudstack/blob/83fd8f60/utils/src/main/java/com/cloud/utils/cisco/n1kv/vsm/VsmCommand.java ---------------------------------------------------------------------- diff --git a/utils/src/main/java/com/cloud/utils/cisco/n1kv/vsm/VsmCommand.java b/utils/src/main/java/com/cloud/utils/cisco/n1kv/vsm/VsmCommand.java new file mode 100644 index 0000000..447e21b --- /dev/null +++ b/utils/src/main/java/com/cloud/utils/cisco/n1kv/vsm/VsmCommand.java @@ -0,0 +1,999 @@ +// +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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 com.cloud.utils.cisco.n1kv.vsm; + +import java.util.List; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +import org.apache.log4j.Logger; +import org.w3c.dom.DOMException; +import org.w3c.dom.DOMImplementation; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.ls.DOMImplementationLS; +import org.w3c.dom.ls.LSSerializer; + +import com.cloud.utils.Pair; + +public class VsmCommand { + + private static final Logger s_logger = Logger.getLogger(VsmCommand.class); + private static final String s_namespace = "urn:ietf:params:xml:ns:netconf:base:1.0"; + private static final String s_ciscons = "http://www.cisco.com/nxos:1.0:ppm"; + private static final String s_configuremode = "__XML__MODE__exec_configure"; + private static final String s_portprofmode = "__XML__MODE_port-prof"; + private static final String s_policymapmode = "__XML__MODE_policy-map"; + private static final String s_classtypemode = "__XML__MODE_policy-map_class_type"; + private static final String s_paramvalue = "__XML__PARAM_value"; + + public enum PortProfileType { + none, vethernet, ethernet; + } + + public enum BindingType { + none, portbindingstatic, portbindingdynamic, portbindingephermal; + } + + public enum SwitchPortMode { + none, access, trunk, privatevlanhost, privatevlanpromiscuous + } + + public enum OperationType { + addvlanid, removevlanid + } + + public static String getAddPortProfile(String name, PortProfileType type, BindingType binding, SwitchPortMode mode, int vlanid, String vdc, String espName) { + try { + // Create the document and root element. + DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilder docBuilder = docFactory.newDocumentBuilder(); + DOMImplementation domImpl = docBuilder.getDOMImplementation(); + Document doc = createDocument(domImpl); + + // Edit configuration command. + Element editConfig = doc.createElement("nf:edit-config"); + doc.getDocumentElement().appendChild(editConfig); + + // Command to get into exec configure mode. + Element target = doc.createElement("nf:target"); + Element running = doc.createElement("nf:running"); + target.appendChild(running); + editConfig.appendChild(target); + + // Command to create the port profile with the desired configuration. + Element config = doc.createElement("nf:config"); + config.appendChild(configPortProfileDetails(doc, name, type, binding, mode, vlanid, vdc, espName)); + editConfig.appendChild(config); + + return serialize(domImpl, doc); + } catch (ParserConfigurationException e) { + s_logger.error("Error while creating add port profile message : " + e.getMessage()); + return null; + } catch (DOMException e) { + s_logger.error("Error while creating add port profile message : " + e.getMessage()); + return null; + } + } + + public static String getAddPortProfile(String name, PortProfileType type, BindingType binding, SwitchPortMode mode, int vlanid) { + try { + // Create the document and root element. + DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilder docBuilder = docFactory.newDocumentBuilder(); + DOMImplementation domImpl = docBuilder.getDOMImplementation(); + Document doc = createDocument(domImpl); + + // Edit configuration command. + Element editConfig = doc.createElement("nf:edit-config"); + doc.getDocumentElement().appendChild(editConfig); + + // Command to get into exec configure mode. + Element target = doc.createElement("nf:target"); + Element running = doc.createElement("nf:running"); + target.appendChild(running); + editConfig.appendChild(target); + + // Command to create the port profile with the desired configuration. + Element config = doc.createElement("nf:config"); + config.appendChild(configPortProfileDetails(doc, name, type, binding, mode, vlanid)); + editConfig.appendChild(config); + + return serialize(domImpl, doc); + } catch (ParserConfigurationException e) { + s_logger.error("Error while creating add port profile message : " + e.getMessage()); + return null; + } catch (DOMException e) { + s_logger.error("Error while creating add port profile message : " + e.getMessage()); + return null; + } + } + + public static String getUpdatePortProfile(String name, SwitchPortMode mode, List<Pair<VsmCommand.OperationType, String>> params) { + try { + // Create the document and root element. + DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilder docBuilder = docFactory.newDocumentBuilder(); + DOMImplementation domImpl = docBuilder.getDOMImplementation(); + Document doc = createDocument(domImpl); + + // Edit configuration command. + Element editConfig = doc.createElement("nf:edit-config"); + doc.getDocumentElement().appendChild(editConfig); + + // Command to get into exec configure mode. + Element target = doc.createElement("nf:target"); + Element running = doc.createElement("nf:running"); + target.appendChild(running); + editConfig.appendChild(target); + + // Command to update the port profile with the desired configuration. + Element config = doc.createElement("nf:config"); + config.appendChild(configPortProfileDetails(doc, name, mode, params)); + editConfig.appendChild(config); + + return serialize(domImpl, doc); + } catch (ParserConfigurationException e) { + s_logger.error("Error while creating update port profile message : " + e.getMessage()); + return null; + } catch (DOMException e) { + s_logger.error("Error while creating update port profile message : " + e.getMessage()); + return null; + } + } + + public static String getDeletePortProfile(String portName) { + try { + // Create the document and root element. + DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilder docBuilder = docFactory.newDocumentBuilder(); + DOMImplementation domImpl = docBuilder.getDOMImplementation(); + Document doc = createDocument(domImpl); + + // Edit configuration command. + Element editConfig = doc.createElement("nf:edit-config"); + doc.getDocumentElement().appendChild(editConfig); + + // Command to get into exec configure mode. + Element target = doc.createElement("nf:target"); + Element running = doc.createElement("nf:running"); + target.appendChild(running); + editConfig.appendChild(target); + + // Command to create the port profile with the desired configuration. + Element config = doc.createElement("nf:config"); + config.appendChild(deletePortProfileDetails(doc, portName)); + editConfig.appendChild(config); + + return serialize(domImpl, doc); + } catch (ParserConfigurationException e) { + s_logger.error("Error while creating delete port profile message : " + e.getMessage()); + return null; + } catch (DOMException e) { + s_logger.error("Error while creating delete port profile message : " + e.getMessage()); + return null; + } + } + + public static String getAddPolicyMap(String name, int averageRate, int maxRate, int burstRate) { + try { + // Create the document and root element. + DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilder docBuilder = docFactory.newDocumentBuilder(); + DOMImplementation domImpl = docBuilder.getDOMImplementation(); + Document doc = createDocument(domImpl); + + // Edit configuration command. + Element editConfig = doc.createElement("nf:edit-config"); + doc.getDocumentElement().appendChild(editConfig); + + // Command to get into exec configure mode. + Element target = doc.createElement("nf:target"); + Element running = doc.createElement("nf:running"); + target.appendChild(running); + editConfig.appendChild(target); + + // Command to create the port profile with the desired configuration. + Element config = doc.createElement("nf:config"); + config.appendChild(policyMapDetails(doc, name, averageRate, maxRate, burstRate)); + editConfig.appendChild(config); + + return serialize(domImpl, doc); + } catch (ParserConfigurationException e) { + s_logger.error("Error while creating policy map message : " + e.getMessage()); + return null; + } catch (DOMException e) { + s_logger.error("Error while creating policy map message : " + e.getMessage()); + return null; + } + } + + public static String getDeletePolicyMap(String name) { + try { + // Create the document and root element. + DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilder docBuilder = docFactory.newDocumentBuilder(); + DOMImplementation domImpl = docBuilder.getDOMImplementation(); + Document doc = createDocument(domImpl); + + // Edit configuration command. + Element editConfig = doc.createElement("nf:edit-config"); + doc.getDocumentElement().appendChild(editConfig); + + // Command to get into exec configure mode. + Element target = doc.createElement("nf:target"); + Element running = doc.createElement("nf:running"); + target.appendChild(running); + editConfig.appendChild(target); + + // Command to create the port profile with the desired configuration. + Element config = doc.createElement("nf:config"); + config.appendChild(deletePolicyMapDetails(doc, name)); + editConfig.appendChild(config); + + return serialize(domImpl, doc); + } catch (ParserConfigurationException e) { + s_logger.error("Error while creating delete policy map message : " + e.getMessage()); + return null; + } catch (DOMException e) { + s_logger.error("Error while creating delete policy map message : " + e.getMessage()); + return null; + } + } + + public static String getServicePolicy(String policyMap, String portProfile, boolean attach) { + try { + // Create the document and root element. + DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilder docBuilder = docFactory.newDocumentBuilder(); + DOMImplementation domImpl = docBuilder.getDOMImplementation(); + Document doc = createDocument(domImpl); + + // Edit configuration command. + Element editConfig = doc.createElement("nf:edit-config"); + doc.getDocumentElement().appendChild(editConfig); + + // Command to get into exec configure mode. + Element target = doc.createElement("nf:target"); + Element running = doc.createElement("nf:running"); + target.appendChild(running); + editConfig.appendChild(target); + + // Command to create the port profile with the desired configuration. + Element config = doc.createElement("nf:config"); + config.appendChild(serviceDetails(doc, policyMap, portProfile, attach)); + editConfig.appendChild(config); + + return serialize(domImpl, doc); + } catch (ParserConfigurationException e) { + s_logger.error("Error while creating attach/detach service policy message : " + e.getMessage()); + return null; + } catch (DOMException e) { + s_logger.error("Error while creating attach/detach service policy message : " + e.getMessage()); + return null; + } + } + + public static String getPortProfile(String name) { + try { + DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilder docBuilder = docFactory.newDocumentBuilder(); + DOMImplementation domImpl = docBuilder.getDOMImplementation(); + Document doc = createDocument(domImpl); + + Element get = doc.createElement("nf:get"); + doc.getDocumentElement().appendChild(get); + + Element filter = doc.createElement("nf:filter"); + filter.setAttribute("type", "subtree"); + get.appendChild(filter); + + // Create the show port-profile name <profile-name> command. + Element show = doc.createElement("show"); + filter.appendChild(show); + Element portProfile = doc.createElement("port-profile"); + show.appendChild(portProfile); + Element nameNode = doc.createElement("name"); + portProfile.appendChild(nameNode); + + // Profile name + Element profileName = doc.createElement("profile_name"); + profileName.setTextContent(name); + nameNode.appendChild(profileName); + + return serialize(domImpl, doc); + } catch (ParserConfigurationException e) { + s_logger.error("Error while creating the message to get port profile details: " + e.getMessage()); + return null; + } catch (DOMException e) { + s_logger.error("Error while creating the message to get port profile details: " + e.getMessage()); + return null; + } + } + + public static String getPolicyMap(String name) { + try { + DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilder docBuilder = docFactory.newDocumentBuilder(); + DOMImplementation domImpl = docBuilder.getDOMImplementation(); + Document doc = createDocument(domImpl); + + Element get = doc.createElement("nf:get"); + doc.getDocumentElement().appendChild(get); + + Element filter = doc.createElement("nf:filter"); + filter.setAttribute("type", "subtree"); + get.appendChild(filter); + + // Create the show port-profile name <profile-name> command. + Element show = doc.createElement("show"); + filter.appendChild(show); + Element policyMap = doc.createElement("policy-map"); + show.appendChild(policyMap); + Element nameNode = doc.createElement("name"); + nameNode.setTextContent(name); + policyMap.appendChild(nameNode); + + return serialize(domImpl, doc); + } catch (ParserConfigurationException e) { + s_logger.error("Error while creating the message to get policy map details : " + e.getMessage()); + return null; + } catch (DOMException e) { + s_logger.error("Error while creating the message to get policy map details : " + e.getMessage()); + return null; + } + } + + public static String getHello() { + try { + DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilder docBuilder = docFactory.newDocumentBuilder(); + DOMImplementation domImpl = docBuilder.getDOMImplementation(); + + // Root elements. + Document doc = domImpl.createDocument(s_namespace, "nc:hello", null); + + // Client capacity. We are only supporting basic capacity. + Element capabilities = doc.createElement("nc:capabilities"); + Element capability = doc.createElement("nc:capability"); + capability.setTextContent("urn:ietf:params:xml:ns:netconf:base:1.0"); + + capabilities.appendChild(capability); + doc.getDocumentElement().appendChild(capabilities); + + return serialize(domImpl, doc); + } catch (ParserConfigurationException e) { + s_logger.error("Error while creating hello message : " + e.getMessage()); + return null; + } catch (DOMException e) { + s_logger.error("Error while creating hello message : " + e.getMessage()); + return null; + } + } + + public static String getVServiceNode(String vlanId, String ipAddr) { + try { + // Create the document and root element. + DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilder docBuilder = docFactory.newDocumentBuilder(); + DOMImplementation domImpl = docBuilder.getDOMImplementation(); + Document doc = createDocument(domImpl); + + // Edit configuration command. + Element editConfig = doc.createElement("nf:edit-config"); + doc.getDocumentElement().appendChild(editConfig); + + // Command to get into exec configure mode. + Element target = doc.createElement("nf:target"); + Element running = doc.createElement("nf:running"); + target.appendChild(running); + editConfig.appendChild(target); + + // Command to create the port profile with the desired configuration. + Element config = doc.createElement("nf:config"); + config.appendChild(configVServiceNodeDetails(doc, vlanId, ipAddr)); + editConfig.appendChild(config); + + return serialize(domImpl, doc); + } catch (ParserConfigurationException e) { + s_logger.error("Error while adding vservice node for vlan " + vlanId + ", " + e.getMessage()); + return null; + } catch (DOMException e) { + s_logger.error("Error while adding vservice node for vlan " + vlanId + ", " + e.getMessage()); + return null; + } + } + + private static Element configVServiceNodeDetails(Document doc, String vlanId, String ipAddr) { + // In mode, exec_configure. + Element configure = doc.createElementNS(s_ciscons, "nxos:configure"); + Element modeConfigure = doc.createElement("nxos:" + s_configuremode); + configure.appendChild(modeConfigure); + + // vservice node %name% type asa + Element vservice = doc.createElement("vservice"); + vservice.appendChild(doc.createElement("node")) + .appendChild(doc.createElement("ASA_" + vlanId)) + .appendChild(doc.createElement("type")) + .appendChild(doc.createElement("asa")); + modeConfigure.appendChild(vservice); + + Element address = doc.createElement(s_paramvalue); + address.setAttribute("isKey", "true"); + address.setTextContent(ipAddr); + + // ip address %ipAddr% + modeConfigure.appendChild(doc.createElement("ip")).appendChild(doc.createElement("address")).appendChild(doc.createElement("value")).appendChild(address); + + Element vlan = doc.createElement(s_paramvalue); + vlan.setAttribute("isKey", "true"); + vlan.setTextContent(vlanId); + + // adjacency l2 vlan %vlanId% + modeConfigure.appendChild(doc.createElement("adjacency")) + .appendChild(doc.createElement("l2")) + .appendChild(doc.createElement("vlan")) + .appendChild(doc.createElement("value")) + .appendChild(vlan); + + // fail-mode close + modeConfigure.appendChild(doc.createElement("fail-mode")).appendChild(doc.createElement("close")); + + // Persist the configuration across reboots. + modeConfigure.appendChild(persistConfiguration(doc)); + + return configure; + } + + private static Element configPortProfileDetails(Document doc, String name, PortProfileType type, BindingType binding, SwitchPortMode mode, int vlanid, String vdc, + String espName) { + + // In mode, exec_configure. + Element configure = doc.createElementNS(s_ciscons, "nxos:configure"); + Element modeConfigure = doc.createElement("nxos:" + s_configuremode); + configure.appendChild(modeConfigure); + + // Port profile name and type configuration. + Element portProfile = doc.createElement("port-profile"); + modeConfigure.appendChild(portProfile); + + // Port profile type. + Element portDetails = doc.createElement("name"); + switch (type) { + case none: + portProfile.appendChild(portDetails); + break; + case ethernet: { + Element typetag = doc.createElement("type"); + Element ethernettype = doc.createElement("ethernet"); + portProfile.appendChild(typetag); + typetag.appendChild(ethernettype); + ethernettype.appendChild(portDetails); + } + break; + case vethernet: { + Element typetag = doc.createElement("type"); + Element ethernettype = doc.createElement("vethernet"); + portProfile.appendChild(typetag); + typetag.appendChild(ethernettype); + ethernettype.appendChild(portDetails); + } + break; + } + + // Port profile name. + Element value = doc.createElement(s_paramvalue); + value.setAttribute("isKey", "true"); + value.setTextContent(name); + portDetails.appendChild(value); + + // element for port prof mode. + Element portProf = doc.createElement(s_portprofmode); + portDetails.appendChild(portProf); + + // Binding type. + if (binding != BindingType.none) { + portProf.appendChild(getBindingType(doc, binding)); + } + + if (mode != SwitchPortMode.none) { + // Switchport mode. + portProf.appendChild(getSwitchPortMode(doc, mode)); + // Adding vlan details. + if (vlanid > 0) { + portProf.appendChild(getAddVlanDetails(doc, mode, Integer.toString(vlanid))); + } + } + + // Command "vmware port-group". + Element vmware = doc.createElement("vmware"); + Element portgroup = doc.createElement("port-group"); + vmware.appendChild(portgroup); + portProf.appendChild(vmware); + + // org %vdc% + // vservice node <Node Name> profile <Edge Security Profile Name in VNMC> + Element vdcValue = doc.createElement(s_paramvalue); + vdcValue.setAttribute("isKey", "true"); + vdcValue.setTextContent(vdc); + + Element org = doc.createElement("org"); + org.appendChild(doc.createElement("orgname")).appendChild(vdcValue); + portProf.appendChild(org); + + String asaNodeName = "ASA_" + vlanid; + Element vservice = doc.createElement("vservice"); + vservice.appendChild(doc.createElement("node")) + .appendChild(doc.createElement(asaNodeName)) + .appendChild(doc.createElement("profile")) + .appendChild(doc.createElement(espName)); + portProf.appendChild(vservice); + + // no shutdown. + Element no = doc.createElement("no"); + Element shutdown = doc.createElement("shutdown"); + no.appendChild(shutdown); + portProf.appendChild(no); + + // Enable the port profile. + Element state = doc.createElement("state"); + Element enabled = doc.createElement("enabled"); + state.appendChild(enabled); + portProf.appendChild(state); + + // Persist the configuration across reboots. + modeConfigure.appendChild(persistConfiguration(doc)); + + return configure; + } + + private static Element configPortProfileDetails(Document doc, String name, PortProfileType type, BindingType binding, SwitchPortMode mode, int vlanid) { + + // In mode, exec_configure. + Element configure = doc.createElementNS(s_ciscons, "nxos:configure"); + Element modeConfigure = doc.createElement("nxos:" + s_configuremode); + configure.appendChild(modeConfigure); + + // Port profile name and type configuration. + Element portProfile = doc.createElement("port-profile"); + modeConfigure.appendChild(portProfile); + + // Port profile type. + Element portDetails = doc.createElement("name"); + switch (type) { + case none: + portProfile.appendChild(portDetails); + break; + case ethernet: { + Element typetag = doc.createElement("type"); + Element ethernettype = doc.createElement("ethernet"); + portProfile.appendChild(typetag); + typetag.appendChild(ethernettype); + ethernettype.appendChild(portDetails); + } + break; + case vethernet: { + Element typetag = doc.createElement("type"); + Element ethernettype = doc.createElement("vethernet"); + portProfile.appendChild(typetag); + typetag.appendChild(ethernettype); + ethernettype.appendChild(portDetails); + } + break; + } + + // Port profile name. + Element value = doc.createElement(s_paramvalue); + value.setAttribute("isKey", "true"); + value.setTextContent(name); + portDetails.appendChild(value); + + // element for port prof mode. + Element portProf = doc.createElement(s_portprofmode); + portDetails.appendChild(portProf); + + // Binding type. + if (binding != BindingType.none) { + portProf.appendChild(getBindingType(doc, binding)); + } + + if (mode != SwitchPortMode.none) { + // Switchport mode. + portProf.appendChild(getSwitchPortMode(doc, mode)); + // Adding vlan details. + if (vlanid > 0) { + portProf.appendChild(getAddVlanDetails(doc, mode, Integer.toString(vlanid))); + } + } + + // Command "vmware port-group". + Element vmware = doc.createElement("vmware"); + Element portgroup = doc.createElement("port-group"); + vmware.appendChild(portgroup); + portProf.appendChild(vmware); + + // no shutdown. + Element no = doc.createElement("no"); + Element shutdown = doc.createElement("shutdown"); + no.appendChild(shutdown); + portProf.appendChild(no); + + // Enable the port profile. + Element state = doc.createElement("state"); + Element enabled = doc.createElement("enabled"); + state.appendChild(enabled); + portProf.appendChild(state); + + // Persist the configuration across reboots. + modeConfigure.appendChild(persistConfiguration(doc)); + + return configure; + } + + private static Element configPortProfileDetails(Document doc, String name, SwitchPortMode mode, List<Pair<VsmCommand.OperationType, String>> params) { + + // In mode, exec_configure. + Element configure = doc.createElementNS(s_ciscons, "nxos:configure"); + Element modeConfigure = doc.createElement("nxos:" + s_configuremode); + configure.appendChild(modeConfigure); + + // Port profile name and type configuration. + Element portProfile = doc.createElement("port-profile"); + modeConfigure.appendChild(portProfile); + + // Port profile type. + Element portDetails = doc.createElement("name"); + portProfile.appendChild(portDetails); + + // Name of the profile to update. + Element value = doc.createElement(s_paramvalue); + value.setAttribute("isKey", "true"); + value.setTextContent(name); + portDetails.appendChild(value); + + // element for port prof mode. + Element portProfMode = doc.createElement(s_portprofmode); + portDetails.appendChild(portProfMode); + + for (Pair<VsmCommand.OperationType, String> item : params) { + if (item.first() == OperationType.addvlanid) { + // Set the access mode configuration or the list + // of allowed vlans on the trunking interface. + portProfMode.appendChild(getAddVlanDetails(doc, mode, item.second())); + } else if (item.first() == OperationType.removevlanid) { + portProfMode.appendChild(getDeleteVlanDetails(doc, mode, item.second())); + } + } + + // Persist the configuration across reboots. + modeConfigure.appendChild(persistConfiguration(doc)); + + return configure; + } + + private static Element deletePortProfileDetails(Document doc, String name) { + Element configure = doc.createElementNS(s_ciscons, "nxos:configure"); + Element modeConfigure = doc.createElement("nxos:" + s_configuremode); + configure.appendChild(modeConfigure); + + // Command and name for the port profile to be deleted. + Element deletePortProfile = doc.createElement("no"); + modeConfigure.appendChild(deletePortProfile); + + Element portProfile = doc.createElement("port-profile"); + deletePortProfile.appendChild(portProfile); + + Element portDetails = doc.createElement("name"); + portProfile.appendChild(portDetails); + + // Name of the profile to delete. + Element value = doc.createElement(s_paramvalue); + value.setAttribute("isKey", "true"); + value.setTextContent(name); + portDetails.appendChild(value); + + // Persist the configuration across reboots. + modeConfigure.appendChild(persistConfiguration(doc)); + + return configure; + } + + private static Element policyMapDetails(Document doc, String name, int averageRate, int maxRate, int burstRate) { + Element configure = doc.createElementNS(s_ciscons, "nxos:configure"); + Element modeConfigure = doc.createElement("nxos:" + s_configuremode); + configure.appendChild(modeConfigure); + + // Policy map details + Element policyMap = doc.createElement("policy-map"); + modeConfigure.appendChild(policyMap); + + Element policyDetails = doc.createElement("name"); + policyMap.appendChild(policyDetails); + + // Name of the policy to create/update. + Element value = doc.createElement(s_paramvalue); + value.setAttribute("isKey", "true"); + value.setTextContent(name); + policyDetails.appendChild(value); + + Element policyMapMode = doc.createElement(s_policymapmode); + policyDetails.appendChild(policyMapMode); + + // Create the default class to match all traffic. + Element classRoot = doc.createElement("class"); + Element classDefault = doc.createElement("class-default"); + policyMapMode.appendChild(classRoot); + classRoot.appendChild(classDefault); + + Element classMode = doc.createElement(s_classtypemode); + classDefault.appendChild(classMode); + + // Set the average, max and burst rate. + // TODO: Add handling for max and burst. + Element police = doc.createElement("police"); + classMode.appendChild(police); + + // Set the committed information rate and its value in mbps. + Element cir = doc.createElement("cir"); + police.appendChild(cir); + Element cirValue = doc.createElement("cir-val"); + cir.appendChild(cirValue); + Element value2 = doc.createElement(s_paramvalue); + Element mbps = doc.createElement("mbps"); + value2.setTextContent(Integer.toString(averageRate)); + cirValue.appendChild(value2); + cirValue.appendChild(mbps); + + // Persist the configuration across reboots. + modeConfigure.appendChild(persistConfiguration(doc)); + + return configure; + } + + private static Element deletePolicyMapDetails(Document doc, String name) { + Element configure = doc.createElementNS(s_ciscons, "nxos:configure"); + Element modeConfigure = doc.createElement("nxos:" + s_configuremode); + configure.appendChild(modeConfigure); + + // Delete Policy map details + Element deletePolicyMap = doc.createElement("no"); + Element policyMap = doc.createElement("policy-map"); + deletePolicyMap.appendChild(policyMap); + modeConfigure.appendChild(deletePolicyMap); + + Element policyDetails = doc.createElement("name"); + policyMap.appendChild(policyDetails); + + // Name of the policy to create/update. + Element value = doc.createElement(s_paramvalue); + value.setAttribute("isKey", "true"); + value.setTextContent(name); + policyDetails.appendChild(value); + + // Persist the configuration across reboots. + modeConfigure.appendChild(persistConfiguration(doc)); + + return configure; + } + + private static Element serviceDetails(Document doc, String policyMap, String portProfile, boolean attach) { + // In mode, exec_configure. + Element configure = doc.createElementNS(s_ciscons, "nxos:configure"); + Element modeConfigure = doc.createElement("nxos:" + s_configuremode); + configure.appendChild(modeConfigure); + + // Port profile name and type configuration. + Element profile = doc.createElement("port-profile"); + modeConfigure.appendChild(profile); + + // Port profile type. + Element portDetails = doc.createElement("name"); + profile.appendChild(portDetails); + + // Name of the profile to update. + Element value = doc.createElement(s_paramvalue); + value.setAttribute("isKey", "true"); + value.setTextContent(portProfile); + portDetails.appendChild(value); + + // element for port prof mode. + Element portProfMode = doc.createElement(s_portprofmode); + portDetails.appendChild(portProfMode); + + // Associate/Remove the policy for input. + if (attach) { + portProfMode.appendChild(getServicePolicyCmd(doc, policyMap, "input")); + } else { + Element detach = doc.createElement("no"); + portProfMode.appendChild(detach); + detach.appendChild(getServicePolicyCmd(doc, policyMap, "input")); + } + + // Associate/Remove the policy for output. + if (attach) { + portProfMode.appendChild(getServicePolicyCmd(doc, policyMap, "output")); + } else { + Element detach = doc.createElement("no"); + portProfMode.appendChild(detach); + detach.appendChild(getServicePolicyCmd(doc, policyMap, "output")); + } + + // Persist the configuration across reboots. + modeConfigure.appendChild(persistConfiguration(doc)); + + return configure; + } + + private static Element persistConfiguration(Document doc) { + Element copy = doc.createElement("copy"); + Element running = doc.createElement("running-config"); + Element startup = doc.createElement("startup-config"); + copy.appendChild(running); + running.appendChild(startup); + return copy; + } + + private static Element getAddVlanDetails(Document doc, SwitchPortMode mode, String vlanid) { + Element switchport = doc.createElement("switchport"); + + // Details of the vlanid to add. + Element vlancreate = doc.createElement("vlan-id-create-delete"); + Element value = doc.createElement(s_paramvalue); + value.setTextContent(vlanid); + vlancreate.appendChild(value); + + // Handling is there only for 'access' and 'trunk allowed' mode command. + if (mode == SwitchPortMode.access) { + Element access = doc.createElement("access"); + switchport.appendChild(access); + + Element vlan = doc.createElement("vlan"); + access.appendChild(vlan); + + vlan.appendChild(vlancreate); + } else if (mode == SwitchPortMode.trunk) { + Element trunk = doc.createElement("trunk"); + switchport.appendChild(trunk); + + Element allowed = doc.createElement("allowed"); + trunk.appendChild(allowed); + + Element vlan = doc.createElement("vlan"); + allowed.appendChild(vlan); + + Element add = doc.createElement("add"); + vlan.appendChild(add); + + add.appendChild(vlancreate); + } + + return switchport; + } + + private static Node getDeleteVlanDetails(Document doc, SwitchPortMode mode, String vlanid) { + Node parentNode = null; + Element switchport = doc.createElement("switchport"); + + // Handling is there only for 'access' and 'trunk allowed' mode command. + if (mode == SwitchPortMode.access) { + Element no = doc.createElement("no"); + no.appendChild(switchport); + parentNode = no; + + Element access = doc.createElement("access"); + switchport.appendChild(access); + + Element vlan = doc.createElement("vlan"); + access.appendChild(vlan); + } else if (mode == SwitchPortMode.trunk) { + parentNode = switchport; + + Element trunk = doc.createElement("trunk"); + switchport.appendChild(trunk); + + Element allowed = doc.createElement("allowed"); + trunk.appendChild(allowed); + + Element vlan = doc.createElement("vlan"); + allowed.appendChild(vlan); + + Element remove = doc.createElement("remove"); + vlan.appendChild(remove); + + // Details of the vlanid to add. + Element vlancreate = doc.createElement("vlan-id-create-delete"); + Element value = doc.createElement(s_paramvalue); + value.setTextContent(vlanid); + vlancreate.appendChild(value); + + remove.appendChild(vlancreate); + } + + return parentNode; + } + + private static Element getBindingType(Document doc, BindingType binding) { + Element portBinding = doc.createElement("port-binding"); + + // We only have handling for access or trunk mode. Handling for private-vlan + // host/promiscuous command will have to be added. + if (binding == BindingType.portbindingstatic) { + Element type = doc.createElement("static"); + portBinding.appendChild(type); + } else if (binding == BindingType.portbindingdynamic) { + Element type = doc.createElement("dynamic"); + portBinding.appendChild(type); + } else if (binding == BindingType.portbindingephermal) { + Element type = doc.createElement("ephemeral"); + portBinding.appendChild(type); + } + + return portBinding; + } + + private static Element getSwitchPortMode(Document doc, SwitchPortMode mode) { + Element switchport = doc.createElement("switchport"); + Element accessmode = doc.createElement("mode"); + switchport.appendChild(accessmode); + + // We only have handling for access or trunk mode. Handling for private-vlan + // host/promiscuous command will have to be added. + if (mode == SwitchPortMode.access) { + Element access = doc.createElement("access"); + accessmode.appendChild(access); + } else if (mode == SwitchPortMode.trunk) { + Element trunk = doc.createElement("trunk"); + accessmode.appendChild(trunk); + } + + return switchport; + } + + private static Element getServicePolicyCmd(Document doc, String policyMap, String type) { + Element service = doc.createElement("service-policy"); + Element input = doc.createElement(type); + service.appendChild(input); + + Element name = doc.createElement("name"); + input.appendChild(name); + + Element policyValue = doc.createElement(s_paramvalue); + policyValue.setTextContent(policyMap); + name.appendChild(policyValue); + + return service; + } + + private static Document createDocument(DOMImplementation dom) { + Document doc = dom.createDocument(s_namespace, "nf:rpc", null); + doc.getDocumentElement().setAttribute("message-id", "101"); + doc.getDocumentElement().setAttributeNS(s_ciscons, "portprofile", "true"); + return doc; + } + + private static String serialize(DOMImplementation domImpl, Document document) { + DOMImplementationLS ls = (DOMImplementationLS)domImpl; + LSSerializer lss = ls.createLSSerializer(); + return lss.writeToString(document); + } +}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/83fd8f60/utils/src/main/java/com/cloud/utils/cisco/n1kv/vsm/VsmOkResponse.java ---------------------------------------------------------------------- diff --git a/utils/src/main/java/com/cloud/utils/cisco/n1kv/vsm/VsmOkResponse.java b/utils/src/main/java/com/cloud/utils/cisco/n1kv/vsm/VsmOkResponse.java new file mode 100644 index 0000000..8c56b22 --- /dev/null +++ b/utils/src/main/java/com/cloud/utils/cisco/n1kv/vsm/VsmOkResponse.java @@ -0,0 +1,44 @@ +// +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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 com.cloud.utils.cisco.n1kv.vsm; + +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; + +public class VsmOkResponse extends VsmResponse { + + VsmOkResponse(String response) { + super(response); + initialize(); + } + + @Override + protected void parse(Element root) { + NodeList list = root.getElementsByTagName("nf:rpc-error"); + if (list.getLength() == 0) { + // No rpc-error tag; means response was ok. + assert (root.getElementsByTagName("nf:ok").getLength() > 0); + _responseOk = true; + } else { + parseError(list.item(0)); + _responseOk = false; + } + } +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/83fd8f60/utils/src/main/java/com/cloud/utils/cisco/n1kv/vsm/VsmPolicyMapResponse.java ---------------------------------------------------------------------- diff --git a/utils/src/main/java/com/cloud/utils/cisco/n1kv/vsm/VsmPolicyMapResponse.java b/utils/src/main/java/com/cloud/utils/cisco/n1kv/vsm/VsmPolicyMapResponse.java new file mode 100644 index 0000000..c0ed6ee --- /dev/null +++ b/utils/src/main/java/com/cloud/utils/cisco/n1kv/vsm/VsmPolicyMapResponse.java @@ -0,0 +1,84 @@ +// +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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 com.cloud.utils.cisco.n1kv.vsm; + +import org.apache.log4j.Logger; +import org.w3c.dom.DOMException; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +public class VsmPolicyMapResponse extends VsmResponse { + private static final Logger s_logger = Logger.getLogger(VsmPolicyMapResponse.class); + private static final String s_policyMapDetails = "__XML__OPT_Cmd_show_policy-map___readonly__"; + + private PolicyMap _policyMap = new PolicyMap(); + + VsmPolicyMapResponse(String response) { + super(response); + initialize(); + } + + public PolicyMap getPolicyMap() { + return _policyMap; + } + + @Override + protected void parse(Element root) { + NodeList list = root.getElementsByTagName("nf:rpc-error"); + if (list.getLength() == 0) { + // No rpc-error tag; means response was ok. + NodeList dataList = root.getElementsByTagName("nf:data"); + if (dataList.getLength() > 0) { + parseData(dataList.item(0)); + _responseOk = true; + } + } else { + super.parseError(list.item(0)); + _responseOk = false; + } + } + + protected void parseData(Node data) { + try { + NodeList list = ((Element)data).getElementsByTagName(s_policyMapDetails); + if (list.getLength() > 0) { + NodeList readOnlyList = ((Element)list.item(0)).getElementsByTagName("__readonly__"); + Element readOnly = (Element)readOnlyList.item(0); + + for (Node node = readOnly.getFirstChild(); node != null; node = node.getNextSibling()) { + String currentNode = node.getNodeName(); + String value = node.getTextContent(); + if ("pmap-name-out".equalsIgnoreCase(currentNode)) { + _policyMap.policyMapName = value; + } else if ("cir".equalsIgnoreCase(currentNode)) { + _policyMap.committedRate = Integer.parseInt(value.trim()); + } else if ("bc".equalsIgnoreCase(currentNode)) { + _policyMap.burstRate = Integer.parseInt(value.trim()); + } else if ("pir".equalsIgnoreCase(currentNode)) { + _policyMap.peakRate = Integer.parseInt(value.trim()); + } + } + } + } catch (DOMException e) { + s_logger.error("Error parsing the response : " + e.toString()); + } + } +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/83fd8f60/utils/src/main/java/com/cloud/utils/cisco/n1kv/vsm/VsmPortProfileResponse.java ---------------------------------------------------------------------- diff --git a/utils/src/main/java/com/cloud/utils/cisco/n1kv/vsm/VsmPortProfileResponse.java b/utils/src/main/java/com/cloud/utils/cisco/n1kv/vsm/VsmPortProfileResponse.java new file mode 100644 index 0000000..0a3de18 --- /dev/null +++ b/utils/src/main/java/com/cloud/utils/cisco/n1kv/vsm/VsmPortProfileResponse.java @@ -0,0 +1,166 @@ +// +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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 com.cloud.utils.cisco.n1kv.vsm; + +import java.util.StringTokenizer; + +import org.apache.log4j.Logger; +import org.w3c.dom.DOMException; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import com.cloud.utils.cisco.n1kv.vsm.VsmCommand.BindingType; +import com.cloud.utils.cisco.n1kv.vsm.VsmCommand.PortProfileType; +import com.cloud.utils.cisco.n1kv.vsm.VsmCommand.SwitchPortMode; + +public class VsmPortProfileResponse extends VsmResponse { + private static final Logger s_logger = Logger.getLogger(VsmPortProfileResponse.class); + private static final String s_portProfileDetails = "__XML__OPT_Cmd_show_port_profile___readonly__"; + + private PortProfile _portProfile = new PortProfile(); + + VsmPortProfileResponse(String response) { + super(response); + initialize(); + } + + public PortProfile getPortProfile() { + return _portProfile; + } + + @Override + protected void parse(Element root) { + NodeList list = root.getElementsByTagName("nf:rpc-error"); + if (list.getLength() == 0) { + // No rpc-error tag; means response was ok. + NodeList dataList = root.getElementsByTagName("nf:data"); + if (dataList.getLength() > 0) { + parseData(dataList.item(0)); + _responseOk = true; + } + } else { + super.parseError(list.item(0)); + _responseOk = false; + } + } + + protected void parseData(Node data) { + try { + NodeList list = ((Element)data).getElementsByTagName(s_portProfileDetails); + if (list.getLength() > 0) { + NodeList readOnlyList = ((Element)list.item(0)).getElementsByTagName("__readonly__"); + Element readOnly = (Element)readOnlyList.item(0); + + for (Node node = readOnly.getFirstChild(); node != null; node = node.getNextSibling()) { + String currentNode = node.getNodeName(); + String value = node.getTextContent(); + if ("port_binding".equalsIgnoreCase(currentNode)) { + setPortBinding(value); + } else if ("profile_name".equalsIgnoreCase(currentNode)) { + // Set the port profile name. + _portProfile.profileName = value; + } else if ("profile_cfg".equalsIgnoreCase(currentNode)) { + setProfileConfiguration(value); + } else if ("type".equalsIgnoreCase(currentNode)) { + setPortType(value); + } else if ("status".equalsIgnoreCase(currentNode)) { + // Has the profile been enabled. + if (value.equalsIgnoreCase("1")) { + _portProfile.status = true; + } + } else if ("max_ports".equalsIgnoreCase(currentNode)) { + // Has the profile been enabled. + _portProfile.maxPorts = Integer.parseInt(value.trim()); + } + } + } + } catch (DOMException e) { + s_logger.error("Error parsing the response : " + e.toString()); + } + } + + private void setProfileConfiguration(String value) { + StringTokenizer tokens = new StringTokenizer(value.trim()); + if (tokens.hasMoreTokens()) { + String currentToken = tokens.nextToken(); + if ("switchport".equalsIgnoreCase(currentToken)) { + parseProfileMode(tokens); + } else if ("service-policy".equalsIgnoreCase(currentToken)) { + String ioType = tokens.nextToken(); + if ("input".equalsIgnoreCase(ioType)) { + _portProfile.inputPolicyMap = tokens.nextToken(); + } else if ("output".equalsIgnoreCase(ioType)) { + _portProfile.outputPolicyMap = tokens.nextToken(); + } + } + } + } + + private void parseProfileMode(StringTokenizer tokens) { + if (tokens.hasMoreTokens()) { + String firstToken = tokens.nextToken(); + if ("mode".equalsIgnoreCase(firstToken)) { + setPortMode(tokens.nextToken()); + } else if ("access".equalsIgnoreCase(firstToken)) { + if (tokens.hasMoreTokens()) { + String secondToken = tokens.nextToken(); + assert ("vlan".equalsIgnoreCase(secondToken)); + if (tokens.hasMoreTokens()) { + _portProfile.vlan = tokens.nextToken(); + } + } + } + } + } + + private void setPortMode(String value) { + // Set the mode for port profile. + if ("access".equalsIgnoreCase(value)) { + _portProfile.mode = SwitchPortMode.access; + } else if ("trunk".equalsIgnoreCase(value)) { + _portProfile.mode = SwitchPortMode.trunk; + } else if ("privatevlanhost".equalsIgnoreCase(value)) { + _portProfile.mode = SwitchPortMode.privatevlanhost; + } else if ("privatevlanpromiscuous".equalsIgnoreCase(value)) { + _portProfile.mode = SwitchPortMode.privatevlanpromiscuous; + } + } + + private void setPortBinding(String value) { + // Set the binding type for the port profile. + if ("static".equalsIgnoreCase(value)) { + _portProfile.binding = BindingType.portbindingstatic; + } else if ("dynamic".equalsIgnoreCase(value)) { + _portProfile.binding = BindingType.portbindingdynamic; + } else if ("ephermal".equalsIgnoreCase(value)) { + _portProfile.binding = BindingType.portbindingephermal; + } + } + + private void setPortType(String value) { + // Set the type field (vethernet/ethernet). + if ("vethernet".equalsIgnoreCase(value)) { + _portProfile.type = PortProfileType.vethernet; + } else if ("ethernet".equalsIgnoreCase(value)) { + _portProfile.type = PortProfileType.ethernet; + } + } +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/83fd8f60/utils/src/main/java/com/cloud/utils/cisco/n1kv/vsm/VsmResponse.java ---------------------------------------------------------------------- diff --git a/utils/src/main/java/com/cloud/utils/cisco/n1kv/vsm/VsmResponse.java b/utils/src/main/java/com/cloud/utils/cisco/n1kv/vsm/VsmResponse.java new file mode 100644 index 0000000..d82b0dc --- /dev/null +++ b/utils/src/main/java/com/cloud/utils/cisco/n1kv/vsm/VsmResponse.java @@ -0,0 +1,222 @@ +// +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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 com.cloud.utils.cisco.n1kv.vsm; + +import java.io.IOException; +import java.io.StringReader; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +import org.apache.log4j.Logger; +import org.w3c.dom.DOMException; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.ls.DOMImplementationLS; +import org.w3c.dom.ls.LSSerializer; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; + +public abstract class VsmResponse { + + // Following error tags, error types and severity have been taken from RFC 4741. + public enum ErrorTag { + InUse, // in-use + InvalidValue, // invalid-value + TooBig, // too-big + MissingAttribute, // missing-attribute + BadAttribute, // bad-attribute + UnknownAttribute, // unknown-attribute + MissingElement, // missing-element + BadElement, // bad-element + UnknownElement, // unknown-element + UnknownNamespace, // unknown-namespace + AccessDenied, // access-denied + LockDenied, // lock-denied + ResourceDenied, // resource-denied + RollbackFailed, // rollback-failed + DataExists, // data-exists + DataMissing, // data-missing + OperationNotSupported, // operation-not-supported + OperationFailed, // operation-failed + PartialOperation, // partial-operation + } + + public enum ErrorType { + transport, rpc, protocol, application; + } + + public enum ErrorSeverity { + error, warning; + } + + private static final Logger s_logger = Logger.getLogger(VsmResponse.class); + + protected String _xmlResponse; + protected Document _docResponse; + protected boolean _responseOk; + + protected ErrorTag _tag; + protected ErrorType _type; + protected ErrorSeverity _severity; + protected String _path; + protected String _message; + protected String _info; + + VsmResponse(String response) { + _xmlResponse = response; + _responseOk = false; + _tag = ErrorTag.InUse; + _type = ErrorType.rpc; + _severity = ErrorSeverity.error; + _docResponse = null; + } + + protected void initialize() { + try { + DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); + docFactory.setNamespaceAware(true); + DocumentBuilder docBuilder = docFactory.newDocumentBuilder(); + _docResponse = docBuilder.parse(new InputSource(new StringReader(_xmlResponse))); + if (_docResponse != null) { + parse(_docResponse.getDocumentElement()); + } + } catch (ParserConfigurationException e) { + s_logger.error("Error parsing the response : " + e.toString()); + } catch (SAXException e) { + s_logger.error("Error parsing the response : " + e.toString()); + } catch (IOException e) { + s_logger.error("Error parsing the response : " + e.toString()); + } + } + + public boolean isResponseOk() { + return _responseOk; + } + + @Override + public String toString() { + StringBuffer error = new StringBuffer(""); + + error.append(" Severity: " + _severity).append(", Error code: " + _tag).append(", Error type: " + _type); + + if (_message != null) { + error.append(", Error Message: " + _message); + } + + if (_info != null) { + error.append(", Error info: " + _info); + } + + if (_path != null) { + error.append(", Path: " + _path); + } + + return error.toString(); + } + + protected abstract void parse(Element root); + + protected void parseError(Node element) { + Element rpcError = (Element)element; + + try { + assert (rpcError.getNodeName().equalsIgnoreCase("nf:rpc-error")); + for (Node node = rpcError.getFirstChild(); node != null; node = node.getNextSibling()) { + if (node.getNodeName().equalsIgnoreCase("nf:error-type")) { + _type = ErrorType.valueOf(node.getTextContent().trim()); + } else if (node.getNodeName().equalsIgnoreCase("nf:error-tag")) { + _tag = getErrorTag(node.getTextContent().trim()); + } else if (node.getNodeName().equalsIgnoreCase("nf:error-severity")) { + _severity = ErrorSeverity.valueOf(node.getTextContent().trim()); + } else if (node.getNodeName().equalsIgnoreCase("nf:error-path")) { + _path = node.getTextContent(); + } else if (node.getNodeName().equalsIgnoreCase("nf:error-message")) { + _message = node.getTextContent(); + } else if (node.getNodeName().equalsIgnoreCase("nf:error-info")) { + _info = node.getTextContent(); + } + } + } catch (DOMException e) { + s_logger.error("Error parsing the response : " + e.toString()); + } + } + + protected ErrorTag getErrorTag(String tagText) { + ErrorTag tag = ErrorTag.InUse; + + if (tagText.equals("in-use")) { + tag = ErrorTag.InUse; + } else if (tagText.equals("invalid-value")) { + tag = ErrorTag.InvalidValue; + } else if (tagText.equals("too-big")) { + tag = ErrorTag.TooBig; + } else if (tagText.equals("missing-attribute")) { + tag = ErrorTag.MissingAttribute; + } else if (tagText.equals("bad-attribute")) { + tag = ErrorTag.BadAttribute; + } else if (tagText.equals("unknown-attribute")) { + tag = ErrorTag.UnknownAttribute; + } else if (tagText.equals("missing-element")) { + tag = ErrorTag.MissingElement; + } else if (tagText.equals("bad-element")) { + tag = ErrorTag.BadElement; + } else if (tagText.equals("unknown-element")) { + tag = ErrorTag.UnknownElement; + } else if (tagText.equals("unknown-namespace")) { + tag = ErrorTag.UnknownNamespace; + } else if (tagText.equals("access-denied")) { + tag = ErrorTag.AccessDenied; + } else if (tagText.equals("lock-denied")) { + tag = ErrorTag.LockDenied; + } else if (tagText.equals("resource-denied")) { + tag = ErrorTag.ResourceDenied; + } else if (tagText.equals("rollback-failed")) { + tag = ErrorTag.RollbackFailed; + } else if (tagText.equals("data-exists")) { + tag = ErrorTag.DataExists; + } else if (tagText.equals("data-missing")) { + tag = ErrorTag.DataMissing; + } else if (tagText.equals("operation-not-supported")) { + tag = ErrorTag.OperationNotSupported; + } else if (tagText.equals("operation-failed")) { + tag = ErrorTag.OperationFailed; + } else if (tagText.equals("partial-operation")) { + tag = ErrorTag.PartialOperation; + } + + return tag; + } + + // Helper routine to check for the response received. + protected void printResponse() { + try { + DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilder docBuilder = docFactory.newDocumentBuilder(); + DOMImplementationLS ls = (DOMImplementationLS)docBuilder.getDOMImplementation(); + LSSerializer lss = ls.createLSSerializer(); + System.out.println(lss.writeToString(_docResponse)); + } catch (ParserConfigurationException e) { + s_logger.error("Error parsing the repsonse : " + e.toString()); + } + } +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/83fd8f60/utils/src/main/java/com/cloud/utils/component/Adapter.java ---------------------------------------------------------------------- diff --git a/utils/src/main/java/com/cloud/utils/component/Adapter.java b/utils/src/main/java/com/cloud/utils/component/Adapter.java new file mode 100644 index 0000000..d50b8d9 --- /dev/null +++ b/utils/src/main/java/com/cloud/utils/component/Adapter.java @@ -0,0 +1,27 @@ +// +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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 com.cloud.utils.component; + +/** + * Adapter defines methods for pluggable code within the Cloud Stack. An + * Adapters are a departure from regular structured programming. + */ +public interface Adapter extends ComponentLifecycle { +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/83fd8f60/utils/src/main/java/com/cloud/utils/component/AdapterBase.java ---------------------------------------------------------------------- diff --git a/utils/src/main/java/com/cloud/utils/component/AdapterBase.java b/utils/src/main/java/com/cloud/utils/component/AdapterBase.java new file mode 100644 index 0000000..703b532 --- /dev/null +++ b/utils/src/main/java/com/cloud/utils/component/AdapterBase.java @@ -0,0 +1,40 @@ +// +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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 com.cloud.utils.component; + +import java.util.List; + +// Typical Adapter implementation. +public class AdapterBase extends ComponentLifecycleBase implements Adapter, ComponentMethodInterceptable { + + public AdapterBase() { + super(); + // set default run level for adapter components + setRunLevel(ComponentLifecycle.RUN_LEVEL_COMPONENT); + } + + public static <T extends Adapter> T getAdapterByName(List<T> adapters, String name) { + for (T adapter : adapters) { + if (adapter.getName() != null && adapter.getName().equalsIgnoreCase(name)) + return adapter; + } + return null; + } +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/83fd8f60/utils/src/main/java/com/cloud/utils/component/AdapterList.java ---------------------------------------------------------------------- diff --git a/utils/src/main/java/com/cloud/utils/component/AdapterList.java b/utils/src/main/java/com/cloud/utils/component/AdapterList.java new file mode 100644 index 0000000..dad3391 --- /dev/null +++ b/utils/src/main/java/com/cloud/utils/component/AdapterList.java @@ -0,0 +1,37 @@ +// +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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 com.cloud.utils.component; + +import java.util.List; + +public class AdapterList<T extends Adapter> { + protected List<T> adapters; + + public AdapterList() { + } + + public List<T> getAdapters() { + return adapters; + } + + public void setAdapters(List<T> adapters) { + this.adapters = adapters; + } +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/83fd8f60/utils/src/main/java/com/cloud/utils/component/ComponentContext.java ---------------------------------------------------------------------- diff --git a/utils/src/main/java/com/cloud/utils/component/ComponentContext.java b/utils/src/main/java/com/cloud/utils/component/ComponentContext.java new file mode 100644 index 0000000..8948b27 --- /dev/null +++ b/utils/src/main/java/com/cloud/utils/component/ComponentContext.java @@ -0,0 +1,282 @@ +// +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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 com.cloud.utils.component; + +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; + +import javax.management.InstanceAlreadyExistsException; +import javax.management.MBeanRegistrationException; +import javax.management.MalformedObjectNameException; +import javax.management.NotCompliantMBeanException; +import javax.naming.ConfigurationException; + +import org.apache.log4j.Logger; +import org.springframework.aop.framework.Advised; +import org.springframework.beans.factory.NoSuchBeanDefinitionException; +import org.springframework.beans.factory.config.AutowireCapableBeanFactory; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.context.annotation.Primary; + +import com.cloud.utils.mgmt.JmxUtil; +import com.cloud.utils.mgmt.ManagementBean; + +/** + * + * ComponentContext.setApplication() and ComponentContext.getApplication() + * are not recommended to be used outside, they exist to help wire Spring Framework + * + */ +@SuppressWarnings("unchecked") +public class ComponentContext implements ApplicationContextAware { + private static final Logger s_logger = Logger.getLogger(ComponentContext.class); + + private static ApplicationContext s_appContext; + private static Map<Class<?>, ApplicationContext> s_appContextDelegates; + private static boolean s_initializeBeans = true; + + @Override + public void setApplicationContext(ApplicationContext applicationContext) { + s_logger.info("Setup Spring Application context"); + s_appContext = applicationContext; + } + + public static ApplicationContext getApplicationContext() { + return s_appContext; + } + + public static void initComponentsLifeCycle() { + if (!s_initializeBeans) + return; + + AutowireCapableBeanFactory beanFactory = s_appContext.getAutowireCapableBeanFactory(); + + Map<String, ComponentMethodInterceptable> interceptableComponents = getApplicationContext().getBeansOfType(ComponentMethodInterceptable.class); + for (Map.Entry<String, ComponentMethodInterceptable> entry : interceptableComponents.entrySet()) { + Object bean = getTargetObject(entry.getValue()); + beanFactory.configureBean(bean, entry.getKey()); + } + + Map<String, ComponentLifecycle> lifecycleComponents = getApplicationContext().getBeansOfType(ComponentLifecycle.class); + + Map<String, ComponentLifecycle>[] classifiedComponents = new Map[ComponentLifecycle.MAX_RUN_LEVELS]; + for (int i = 0; i < ComponentLifecycle.MAX_RUN_LEVELS; i++) { + classifiedComponents[i] = new HashMap<String, ComponentLifecycle>(); + } + + for (Map.Entry<String, ComponentLifecycle> entry : lifecycleComponents.entrySet()) { + classifiedComponents[entry.getValue().getRunLevel()].put(entry.getKey(), entry.getValue()); + } + + // Run the SystemIntegrityCheckers first + Map<String, SystemIntegrityChecker> integrityCheckers = getApplicationContext().getBeansOfType(SystemIntegrityChecker.class); + for (Entry<String, SystemIntegrityChecker> entry : integrityCheckers.entrySet()) { + s_logger.info("Running SystemIntegrityChecker " + entry.getKey()); + try { + entry.getValue().check(); + } catch (Throwable e) { + s_logger.error("System integrity check failed. Refuse to startup", e); + System.exit(1); + } + } + + // configuration phase + Map<String, String> avoidMap = new HashMap<String, String>(); + for (int i = 0; i < ComponentLifecycle.MAX_RUN_LEVELS; i++) { + for (Map.Entry<String, ComponentLifecycle> entry : classifiedComponents[i].entrySet()) { + ComponentLifecycle component = entry.getValue(); + String implClassName = ComponentContext.getTargetClass(component).getName(); + s_logger.info("Configuring " + implClassName); + + if (avoidMap.containsKey(implClassName)) { + s_logger.info("Skip configuration of " + implClassName + " as it is already configured"); + continue; + } + + try { + component.configure(component.getName(), component.getConfigParams()); + } catch (ConfigurationException e) { + s_logger.error("Unhandled exception", e); + throw new RuntimeException("Unable to configure " + implClassName, e); + } + + avoidMap.put(implClassName, implClassName); + } + } + + // starting phase + avoidMap.clear(); + for (int i = 0; i < ComponentLifecycle.MAX_RUN_LEVELS; i++) { + for (Map.Entry<String, ComponentLifecycle> entry : classifiedComponents[i].entrySet()) { + ComponentLifecycle component = entry.getValue(); + String implClassName = ComponentContext.getTargetClass(component).getName(); + s_logger.info("Starting " + implClassName); + + if (avoidMap.containsKey(implClassName)) { + s_logger.info("Skip configuration of " + implClassName + " as it is already configured"); + continue; + } + + try { + component.start(); + + if (getTargetObject(component) instanceof ManagementBean) + registerMBean((ManagementBean)getTargetObject(component)); + } catch (Exception e) { + s_logger.error("Unhandled exception", e); + throw new RuntimeException("Unable to start " + implClassName, e); + } + + avoidMap.put(implClassName, implClassName); + } + } + } + + static void registerMBean(ManagementBean mbean) { + try { + JmxUtil.registerMBean(mbean); + } catch (MalformedObjectNameException e) { + s_logger.warn("Unable to register MBean: " + mbean.getName(), e); + } catch (InstanceAlreadyExistsException e) { + s_logger.warn("Unable to register MBean: " + mbean.getName(), e); + } catch (MBeanRegistrationException e) { + s_logger.warn("Unable to register MBean: " + mbean.getName(), e); + } catch (NotCompliantMBeanException e) { + s_logger.warn("Unable to register MBean: " + mbean.getName(), e); + } + s_logger.info("Registered MBean: " + mbean.getName()); + } + + public static <T> T getComponent(String name) { + assert (s_appContext != null); + return (T)s_appContext.getBean(name); + } + + public static <T> T getComponent(Class<T> beanType) { + assert (s_appContext != null); + Map<String, T> matchedTypes = getComponentsOfType(beanType); + if (matchedTypes.size() > 0) { + for (Map.Entry<String, T> entry : matchedTypes.entrySet()) { + Primary primary = getTargetClass(entry.getValue()).getAnnotation(Primary.class); + if (primary != null) + return entry.getValue(); + } + + if (matchedTypes.size() > 1) { + s_logger.warn("Unable to uniquely locate bean type " + beanType.getName()); + for (Map.Entry<String, T> entry : matchedTypes.entrySet()) { + s_logger.warn("Candidate " + getTargetClass(entry.getValue()).getName()); + } + } + + return (T)matchedTypes.values().toArray()[0]; + } + + throw new NoSuchBeanDefinitionException(beanType.getName()); + } + + public static <T> Map<String, T> getComponentsOfType(Class<T> beanType) { + return s_appContext.getBeansOfType(beanType); + } + + public static Class<?> getTargetClass(Object instance) { + while (instance instanceof Advised) { + try { + instance = ((Advised)instance).getTargetSource().getTarget(); + } catch (Exception e) { + return instance.getClass(); + } + } + return instance.getClass(); + } + + public static <T> T getTargetObject(Object instance) { + while (instance instanceof Advised) { + try { + instance = ((Advised)instance).getTargetSource().getTarget(); + } catch (Exception e) { + return (T)instance; + } + } + + return (T)instance; + } + + public static <T> T inject(Class<T> clz) { + T instance; + try { + instance = clz.newInstance(); + return inject(instance); + } catch (InstantiationException e) { + s_logger.error("Unhandled InstantiationException", e); + throw new RuntimeException("Unable to instantiate object of class " + clz.getName() + ", make sure it has public constructor"); + } catch (IllegalAccessException e) { + s_logger.error("Unhandled IllegalAccessException", e); + throw new RuntimeException("Unable to instantiate object of class " + clz.getName() + ", make sure it has public constructor"); + } + } + + public static <T> T inject(Object instance) { + // autowire dynamically loaded object + AutowireCapableBeanFactory beanFactory = getApplicationContext(instance).getAutowireCapableBeanFactory(); + beanFactory.autowireBean(instance); + return (T)instance; + } + + private static ApplicationContext getApplicationContext(Object instance) { + ApplicationContext result = null; + + synchronized (s_appContextDelegates) { + if (instance != null && s_appContextDelegates != null) { + result = s_appContextDelegates.get(instance.getClass()); + } + } + + return result == null ? s_appContext : result; + } + + public static synchronized void addDelegateContext(Class<?> clazz, ApplicationContext context) { + if (s_appContextDelegates == null) { + s_appContextDelegates = new HashMap<Class<?>, ApplicationContext>(); + } + + s_appContextDelegates.put(clazz, context); + } + + public static synchronized void removeDelegateContext(Class<?> clazz) { + if (s_appContextDelegates != null) { + s_appContextDelegates.remove(clazz); + } + } + + public boolean isInitializeBeans() { + return s_initializeBeans; + } + + public void setInitializeBeans(boolean initializeBeans) { + initInitializeBeans(initializeBeans); + } + + private static synchronized void initInitializeBeans(boolean initializeBeans) { + s_initializeBeans = initializeBeans; + } +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/83fd8f60/utils/src/main/java/com/cloud/utils/component/ComponentInstantiationPostProcessor.java ---------------------------------------------------------------------- diff --git a/utils/src/main/java/com/cloud/utils/component/ComponentInstantiationPostProcessor.java b/utils/src/main/java/com/cloud/utils/component/ComponentInstantiationPostProcessor.java new file mode 100644 index 0000000..6704371 --- /dev/null +++ b/utils/src/main/java/com/cloud/utils/component/ComponentInstantiationPostProcessor.java @@ -0,0 +1,149 @@ +// +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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 com.cloud.utils.component; + +import java.beans.PropertyDescriptor; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; + +import net.sf.cglib.proxy.Callback; +import net.sf.cglib.proxy.CallbackFilter; +import net.sf.cglib.proxy.Enhancer; +import net.sf.cglib.proxy.MethodInterceptor; +import net.sf.cglib.proxy.MethodProxy; +import net.sf.cglib.proxy.NoOp; + +import org.apache.log4j.Logger; +import org.springframework.beans.BeansException; +import org.springframework.beans.PropertyValues; +import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor; + +import com.cloud.utils.Pair; + +public class ComponentInstantiationPostProcessor implements InstantiationAwareBeanPostProcessor { + private static final Logger s_logger = Logger.getLogger(ComponentInstantiationPostProcessor.class); + + private List<ComponentMethodInterceptor> _interceptors = new ArrayList<ComponentMethodInterceptor>(); + private Callback[] _callbacks; + private CallbackFilter _callbackFilter; + + public ComponentInstantiationPostProcessor() { + _callbacks = new Callback[2]; + _callbacks[0] = NoOp.INSTANCE; + _callbacks[1] = new InterceptorDispatcher(); + + _callbackFilter = new InterceptorFilter(); + } + + public List<ComponentMethodInterceptor> getInterceptors() { + return _interceptors; + } + + public void setInterceptors(List<ComponentMethodInterceptor> interceptors) { + _interceptors = interceptors; + } + + private Callback[] getCallbacks() { + return _callbacks; + } + + private CallbackFilter getCallbackFilter() { + return _callbackFilter; + } + + @Override + public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { + return bean; + } + + @Override + public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { + return bean; + } + + @Override + public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException { + if (_interceptors != null && _interceptors.size() > 0) { + if (ComponentMethodInterceptable.class.isAssignableFrom(beanClass)) { + Enhancer enhancer = new Enhancer(); + enhancer.setSuperclass(beanClass); + enhancer.setCallbacks(getCallbacks()); + enhancer.setCallbackFilter(getCallbackFilter()); + enhancer.setNamingPolicy(ComponentNamingPolicy.INSTANCE); + + Object bean = enhancer.create(); + return bean; + } + } + return null; + } + + @Override + public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException { + return true; + } + + @Override + public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException { + return pvs; + } + + protected class InterceptorDispatcher implements MethodInterceptor { + @Override + public Object intercept(Object target, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { + ArrayList<Pair<ComponentMethodInterceptor, Object>> interceptors = new ArrayList<Pair<ComponentMethodInterceptor, Object>>(); + + for (ComponentMethodInterceptor interceptor : getInterceptors()) { + if (interceptor.needToIntercept(method)) { + Object objReturnedInInterceptStart = interceptor.interceptStart(method, target); + interceptors.add(new Pair<ComponentMethodInterceptor, Object>(interceptor, objReturnedInInterceptStart)); + } + } + boolean success = false; + try { + Object obj = methodProxy.invokeSuper(target, args); + success = true; + return obj; + } finally { + for (Pair<ComponentMethodInterceptor, Object> interceptor : interceptors) { + if (success) { + interceptor.first().interceptComplete(method, target, interceptor.second()); + } else { + interceptor.first().interceptException(method, target, interceptor.second()); + } + } + } + } + } + + protected class InterceptorFilter implements CallbackFilter { + @Override + public int accept(Method method) { + for (ComponentMethodInterceptor interceptor : getInterceptors()) { + + if (interceptor.needToIntercept(method)) { + return 1; + } + } + return 0; + } + } +}