diff --git a/utils/src/com/cloud/utils/cisco/n1kv/vsm/NetconfHelper.java b/utils/src/com/cloud/utils/cisco/n1kv/vsm/NetconfHelper.java index 742226c2bb8..009cbb6804a 100644 --- a/utils/src/com/cloud/utils/cisco/n1kv/vsm/NetconfHelper.java +++ b/utils/src/com/cloud/utils/cisco/n1kv/vsm/NetconfHelper.java @@ -4,7 +4,9 @@ import org.apache.log4j.Logger; import java.io.InputStream; import java.io.OutputStream; +import java.util.List; +import com.cloud.utils.Pair; import com.cloud.utils.ssh.*; import com.trilead.ssh2.Session; import com.trilead.ssh2.Connection; @@ -63,19 +65,41 @@ public class NetconfHelper { } public void addPortProfile(String name, PortProfileType type, BindingType binding, - SwitchPortMode mode, int vlanid) throws CloudRuntimeException { - String command = VsmCommand.getAddPortProfile(name, type, binding, mode, vlanid); - command = command.concat(SSH_NETCONF_TERMINATOR); - send(command); - // parse the rpc reply and the return success or failure. - parseReply(receive()); + SwitchPortMode mode, int vlanid, int networkRate) throws CloudRuntimeException { + String command = VsmCommand.getAddPortProfile(name, type, binding, mode, vlanid, networkRate); + if (command != null) { + command = command.concat(SSH_NETCONF_TERMINATOR); + send(command); + // parse the rpc reply and the return success or failure. + parseReply(receive()); + } else { + throw new CloudRuntimeException("Error generating rpc request for adding port profile."); + } + } + + public void updatePortProfile(String name, SwitchPortMode mode, + List> params) throws CloudRuntimeException { + String command = VsmCommand.getUpdatePortProfile(name, mode, params); + if (command != null) { + command = command.concat(SSH_NETCONF_TERMINATOR); + send(command); + // parse the rpc reply and the return success or failure. + parseReply(receive()); + } else { + throw new CloudRuntimeException("Error generating rpc request for updating port profile."); + } } public void deletePortProfile(String name) throws CloudRuntimeException { - String command = VsmCommand.getDeletePortProfile(name) + SSH_NETCONF_TERMINATOR; - send(command); - // parse the rpc reply and the return success or failure. - parseReply(receive()); + String command = VsmCommand.getDeletePortProfile(name); + if (command != null) { + command = command.concat(SSH_NETCONF_TERMINATOR); + send(command); + // parse the rpc reply and the return success or failure. + parseReply(receive()); + } else { + throw new CloudRuntimeException("Error generating rpc request for deleting port profile."); + } } private void exchangeHello() { diff --git a/utils/src/com/cloud/utils/cisco/n1kv/vsm/VsmCommand.java b/utils/src/com/cloud/utils/cisco/n1kv/vsm/VsmCommand.java index 064762f8528..783e650ca10 100644 --- a/utils/src/com/cloud/utils/cisco/n1kv/vsm/VsmCommand.java +++ b/utils/src/com/cloud/utils/cisco/n1kv/vsm/VsmCommand.java @@ -1,5 +1,6 @@ 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; @@ -9,9 +10,12 @@ 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); @@ -42,8 +46,14 @@ public class VsmCommand { privatevlanpromiscuous } + public enum OperationType { + addvlanid, + removevlanid, + setrate + } + public static String getAddPortProfile(String name, PortProfileType type, - BindingType binding, SwitchPortMode mode, int vlanid) { + BindingType binding, SwitchPortMode mode, int vlanid, int networkRate) { try { // Create the document and root element. DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); @@ -76,6 +86,40 @@ public class VsmCommand { } } + public static String getUpdatePortProfile(String name, SwitchPortMode mode, + List> 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 message : " + e.getMessage()); + return null; + } catch (DOMException e) { + s_logger.error("Error while creating update message : " + e.getMessage()); + return null; + } + } + public static String getDeletePortProfile(String portName) { try { // Create the document and root element. @@ -193,7 +237,7 @@ public class VsmCommand { // Switchport mode. portProf.appendChild(getSwitchPortMode(doc, mode)); // Adding vlan details. - portProf.appendChild(getVlanDetails(doc, mode, vlanid)); + portProf.appendChild(getAddVlanDetails(doc, mode, Integer.toString(vlanid))); } // Command "vmware port-group". @@ -220,6 +264,48 @@ public class VsmCommand { return configure; } + private static Element configPortProfileDetails(Document doc, String name, SwitchPortMode mode, + List> 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 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); @@ -256,10 +342,16 @@ public class VsmCommand { return copy; } - private static Element getVlanDetails(Document doc, SwitchPortMode mode, int vlanid) { + private static Element getAddVlanDetails(Document doc, SwitchPortMode mode, String vlanid) { Element switchport = doc.createElement("switchport"); - // Handling is there only for 'access' mode command. + // 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); @@ -267,17 +359,68 @@ public class VsmCommand { Element vlan = doc.createElement("vlan"); access.appendChild(vlan); - Element vlancreate = doc.createElement("vlan-id-create-delete"); vlan.appendChild(vlancreate); + } else if (mode == SwitchPortMode.trunk) { + Element trunk = doc.createElement("trunk"); + switchport.appendChild(trunk); - Element value = doc.createElement(s_paramvalue); - value.setTextContent(Integer.toString(vlanid)); - vlancreate.appendChild(value); + 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");