mirror of https://github.com/apache/cloudstack.git
CS-9919: Support for Nexus Swiches (Cisco Vswitches)
Description: Adding a netconf helper class for adding and deleting port profiles. These functions need to be further parameterized and error handling needs to be taken care of.
This commit is contained in:
parent
7380f52f12
commit
1198a62453
|
|
@ -49,8 +49,6 @@ public class CiscoNexusVSM {
|
|||
private String vsmPassword;
|
||||
private String vsmSubsystem;
|
||||
com.trilead.ssh2.Connection sshConnection;
|
||||
private String _helloClientCmd = "<?xml version=\"1.0\"?><nc:hello xmlns:nc=\"urn:ietf:params:xml:ns:netconf:base:1.0\"><nc:capabilities><nc:capability>urn:ietf:params:xml:ns:netconf:base:1.0</nc:capability></nc:capabilities></nc:hello>]]>]]>";
|
||||
private String _clientCmd1 = "<?xml version=\"1.0\"?><nc:rpc message-id=\"1\" xmlns:nc=\"urn:ietf:params:xml:ns:netconf:base:1.0\"xmlns=\"http://www.cisco.com/nxos:1.0:xml\"><nc:get><nc:filter type=\"subtree\"><show><xml><server><status/></server></xml></show></nc:filter></nc:get></nc:rpc>]]>]]>";
|
||||
|
||||
private static final Logger s_logger = Logger.getLogger(CiscoNexusVSM.class);
|
||||
|
||||
|
|
@ -58,7 +56,6 @@ public class CiscoNexusVSM {
|
|||
CiscoNexusVSMService _vsmService;
|
||||
|
||||
Long _timeout = new Long(100000);
|
||||
//base_response apiCallResult;
|
||||
|
||||
// We need to store the result of the XML-RPC command sent to
|
||||
// the VSM. For now it's a string. We should make this the appropriate XSD object.
|
||||
|
|
@ -88,15 +85,15 @@ public class CiscoNexusVSM {
|
|||
return vsmIpaddr;
|
||||
}
|
||||
|
||||
public String getvsmUsername() {
|
||||
public String getVsmUsername() {
|
||||
return vsmUsername;
|
||||
}
|
||||
|
||||
public String getvsmPassword() {
|
||||
public String getVsmPassword() {
|
||||
return vsmPassword;
|
||||
}
|
||||
|
||||
public String getvsmSubsystem() {
|
||||
public String getVsmSubsystem() {
|
||||
return vsmSubsystem;
|
||||
}
|
||||
|
||||
|
|
@ -111,5 +108,4 @@ public class CiscoNexusVSM {
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,216 @@
|
|||
package com.cloud.utils.cisco.n1kv.vsm;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import com.cloud.utils.ssh.*;
|
||||
import com.trilead.ssh2.Session;
|
||||
import com.trilead.ssh2.Connection;
|
||||
import com.trilead.ssh2.ChannelCondition;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
|
||||
public class NetconfHelper {
|
||||
private static final Logger s_logger = Logger.getLogger(NetconfHelper.class);
|
||||
|
||||
private static final String SSH_NETCONF_TERMINATOR = "]]>]]>";
|
||||
|
||||
private Connection _connection;
|
||||
|
||||
private Session _session;
|
||||
|
||||
public NetconfHelper (String ip, String username, String password) throws CloudRuntimeException {
|
||||
_connection = SSHCmdHelper.acquireAuthorizedConnection(ip, username, password);
|
||||
if (_connection == null) {
|
||||
throw new CloudRuntimeException("Error opening ssh connection.");
|
||||
}
|
||||
|
||||
try {
|
||||
_session = _connection.openSession();
|
||||
_session.startSubSystem("xmlagent");
|
||||
exchangeHello();
|
||||
} catch (final Exception e) {
|
||||
disconnect();
|
||||
s_logger.error("Failed to connect to device SSH server: " + e.getMessage());
|
||||
throw new CloudRuntimeException("Failed to connect to SSH server: " + _connection.getHostname());
|
||||
}
|
||||
}
|
||||
|
||||
public void disconnect() {
|
||||
if (_session != null) {
|
||||
_session.close();
|
||||
}
|
||||
SSHCmdHelper.releaseSshConnection(_connection);
|
||||
}
|
||||
|
||||
public void queryStatus() {
|
||||
// FIXME: Use an xml parser to generate this request.
|
||||
String status = "<?xml version=\"1.0\"?>" +
|
||||
"<nc:rpc message-id=\"1\" xmlns:nc=\"urn:ietf:params:xml:ns:netconf:base:1.0" +
|
||||
"\"xmlns=\"http://www.cisco.com/nxos:1.0:xml\">" +
|
||||
" <nc:get>" +
|
||||
" <nc:filter type=\"subtree\">" +
|
||||
" <show>" +
|
||||
" <xml>" +
|
||||
" <server>" +
|
||||
" <status/>" +
|
||||
" </server>" +
|
||||
" </xml>" +
|
||||
" </show>" +
|
||||
" </nc:filter>" +
|
||||
" </nc:get>" +
|
||||
"</nc:rpc>" +
|
||||
SSH_NETCONF_TERMINATOR;
|
||||
send(status);
|
||||
String reply = receive();
|
||||
}
|
||||
|
||||
public boolean addPortProfile(String name, int vlan) {
|
||||
// FIXME: Use an xml parser to generate this request.
|
||||
String command = "<?xml version=\"1.0\"?>" +
|
||||
"<nf:rpc xmlns=\"http://www.cisco.com/nxos:1.0:ppm\" " +
|
||||
"xmlns:nf=\"urn:ietf:params:xml:ns:netconf:base:1.0\" message-id=\"110\">" +
|
||||
" <nf:edit-config>" +
|
||||
" <nf:target>" +
|
||||
" <nf:running/>" +
|
||||
" </nf:target>" +
|
||||
" <nf:config>" +
|
||||
" <nxos:configure xmlns:nxos=\"http://www.cisco.com/nxos:1.0:ppm\">" +
|
||||
" <nxos:__XML__MODE__exec_configure>" +
|
||||
" <port-profile>" +
|
||||
" <type>" +
|
||||
" <vethernet>" +
|
||||
" <name>" +
|
||||
" <__XML__PARAM_value isKey=\"true\">@name</__XML__PARAM_value>" +
|
||||
" <__XML__MODE_port-prof>" +
|
||||
" <switchport>" +
|
||||
" <mode>" +
|
||||
" <access/>" +
|
||||
" </mode>" +
|
||||
" </switchport>" +
|
||||
" <switchport>" +
|
||||
" <access>" +
|
||||
" <vlan>" +
|
||||
" <vlan-id-create-delete>" +
|
||||
" <__XML__PARAM_value>@vlan</__XML__PARAM_value>" +
|
||||
" </vlan-id-create-delete>" +
|
||||
" </vlan>" +
|
||||
" </access>" +
|
||||
" </switchport>" +
|
||||
" <vmware>" +
|
||||
" <port-group/>" +
|
||||
" </vmware>" +
|
||||
" <state>" +
|
||||
" <enabled/>" +
|
||||
" </state>" +
|
||||
" <no>" +
|
||||
" <shutdown/>" +
|
||||
" </no>" +
|
||||
" </__XML__MODE_port-prof>" +
|
||||
" </name>" +
|
||||
" </vethernet>" +
|
||||
" </type>" +
|
||||
" </port-profile>" +
|
||||
" </nxos:__XML__MODE__exec_configure>" +
|
||||
" </nxos:configure>" +
|
||||
" </nf:config>" +
|
||||
" </nf:edit-config>" +
|
||||
"</nf:rpc>" +
|
||||
SSH_NETCONF_TERMINATOR;
|
||||
command = command.replace("@name", name);
|
||||
command = command.replace("@vlan", Integer.toString(vlan));
|
||||
send(command);
|
||||
// parse the rpc reply and the return success or failure.
|
||||
String reply = receive();
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean deletePortProfile(String name) {
|
||||
// FIXME: Use an xml parser to generate this request.
|
||||
String command = "<?xml version=\"1.0\"?>" +
|
||||
"<nf:rpc xmlns=\"http://www.cisco.com/nxos:1.0:ppm\" " +
|
||||
"xmlns:nf=\"urn:ietf:params:xml:ns:netconf:base:1.0\" message-id=\"110\">" +
|
||||
" <nf:edit-config>" +
|
||||
" <nf:target>" +
|
||||
" <nf:running/>" +
|
||||
" </nf:target>" +
|
||||
" <nf:config>" +
|
||||
" <nxos:configure xmlns:nxos=\"http://www.cisco.com/nxos:1.0:ppm\">" +
|
||||
" <nxos:__XML__MODE__exec_configure>" +
|
||||
" <no>" +
|
||||
" <port-profile>" +
|
||||
" <name>" +
|
||||
" <__XML__PARAM_value isKey=\"true\">@name</__XML__PARAM_value>" +
|
||||
" </name>" +
|
||||
" </port-profile>" +
|
||||
" </no>" +
|
||||
" </nxos:__XML__MODE__exec_configure>" +
|
||||
" </nxos:configure>" +
|
||||
" </nf:config>" +
|
||||
" </nf:edit-config>" +
|
||||
"</nf:rpc>" +
|
||||
SSH_NETCONF_TERMINATOR;
|
||||
command = command.replace("@name", name);
|
||||
send(command);
|
||||
// parse the rpc reply and the return success or failure.
|
||||
String reply = receive();
|
||||
return true;
|
||||
}
|
||||
|
||||
private void exchangeHello() {
|
||||
String ack = receive();
|
||||
String hello = "<?xml version=\"1.0\"?>" +
|
||||
"<nc:hello xmlns:nc=\"urn:ietf:params:xml:ns:netconf:base:1.0\">" +
|
||||
" <nc:capabilities>" +
|
||||
" <nc:capability>urn:ietf:params:xml:ns:netconf:base:1.0</nc:capability>" +
|
||||
" </nc:capabilities>" +
|
||||
"</nc:hello>" +
|
||||
SSH_NETCONF_TERMINATOR;
|
||||
send(hello);
|
||||
}
|
||||
|
||||
private void send(String message) {
|
||||
try {
|
||||
OutputStream outputStream = _session.getStdin();
|
||||
outputStream.write(message.getBytes());
|
||||
outputStream.flush();
|
||||
} catch(Exception e) {
|
||||
s_logger.error("Failed to send message: " + e.getMessage());
|
||||
throw new CloudRuntimeException("Failed to send message: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private String receive() {
|
||||
byte[] buffer = new byte[8192];
|
||||
InputStream inputStream = _session.getStdout();
|
||||
try {
|
||||
while (true) {
|
||||
if (inputStream.available() == 0) {
|
||||
int conditions = _session.waitForCondition(ChannelCondition.STDOUT_DATA |
|
||||
ChannelCondition.STDERR_DATA | ChannelCondition.EOF, 500);
|
||||
|
||||
if ((conditions & ChannelCondition.TIMEOUT) != 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
if ((conditions & ChannelCondition.EOF) != 0) {
|
||||
if ((conditions & (ChannelCondition.STDOUT_DATA |
|
||||
ChannelCondition.STDERR_DATA)) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while (inputStream.available() > 0) {
|
||||
inputStream.read(buffer);
|
||||
}
|
||||
}
|
||||
} catch(Exception e) {
|
||||
s_logger.error("Failed to receive message: " + e.getMessage());
|
||||
throw new CloudRuntimeException("Failed to receives message: " + e.getMessage());
|
||||
}
|
||||
|
||||
return new String(buffer);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue