Bug CS-9919: Support for Nexus Swiches (Cisco Vswitches)

Description:

	This is work in progress. This set of changes will not
	compile. Checking in for team wide code sync up.

	Changes are underway to test if VMWareResource can be
	leveraged to talk to the VSM, instead of creating a
	new resource for the VSM, like we've been doing up
	until now.
This commit is contained in:
Vijayendra Bhamidipati 2012-04-27 16:06:51 -07:00
parent b0facd16e4
commit 28568e694b
5 changed files with 169 additions and 185 deletions

View File

@ -0,0 +1,115 @@
// Copyright 2012 Citrix Systems, Inc. Licensed under the
// Apache License, Version 2.0 (the "License"); you may not use this
// file except in compliance with the License. Citrix Systems, Inc.
// reserves all rights not expressly granted by 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.network.resource;
import java.util.Map;
import javax.naming.ConfigurationException;
import com.cloud.agent.IAgentControl;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.Command;
import com.cloud.agent.api.PingCommand;
import com.cloud.agent.api.StartupCommand;
import com.cloud.agent.api.StartupExternalLoadBalancerCommand;
import com.cloud.api.ApiConstants;
import com.cloud.host.Host;
import com.cloud.host.Host.Type;
import com.cloud.resource.ServerResource;
import com.cloud.serializer.GsonHelper;
import com.cloud.utils.NumbersUtil;
import com.google.gson.Gson;
import com.cloud.utils.ssh.*;
import com.cloud.utils.cisco.n1kv.vsm.CiscoNexusVSMService;
import com.cloud.utils.exception.CloudRuntimeException;
import org.apache.log4j.Logger;
class VSMError {
static final int VSM_RESOURCE_EXISTS = 89901;
static final int VSM_RESOURCE_NOT_EXISTS= 89902;
static final int VSM_NO_SERIVCE = 89903;
static final int VSM_OPERATION_NOT_PERMITTED = 89904;
}
public class CiscoNexusVSM {
// deployment configuration
private String vsmIpaddr;
private String vsmUsername;
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);
// interface to interact with Cisco Nexus VSM devices
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.
String xml_rpc_response;
public void setVsmIpaddr(String ipaddr) {
this.vsmIpaddr = ipaddr;
}
public void setVsmUsername(String username) {
this.vsmUsername = username;
}
public void setVsmPassword(String password) {
this.vsmPassword = password;
}
public void setVsmSubsystem(String subsystem) {
this.vsmSubsystem = subsystem;
}
public CiscoNexusVSM() {
this.vsmSubsystem = "xmlagent";
}
public String getVsmIpaddr() {
return vsmIpaddr;
}
public String getvsmUsername() {
return vsmUsername;
}
public String getvsmPassword() {
return vsmPassword;
}
public String getvsmSubsystem() {
return vsmSubsystem;
}
public CiscoNexusVSM(String username, String ipaddr, String password) {
}
public boolean connectToVSM() {
sshConnection = SSHCmdHelper.acquireAuthorizedConnection(this.vsmIpaddr, this.vsmUsername, this.vsmPassword);
if (sshConnection == null) {
return false;
}
return true;
}
}

View File

@ -1,173 +0,0 @@
// Copyright 2012 Citrix Systems, Inc. Licensed under the
// Apache License, Version 2.0 (the "License"); you may not use this
// file except in compliance with the License. Citrix Systems, Inc.
// reserves all rights not expressly granted by 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.network.resource;
import java.util.Map;
import javax.naming.ConfigurationException;
import com.cloud.agent.IAgentControl;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.Command;
import com.cloud.agent.api.PingCommand;
import com.cloud.agent.api.StartupCommand;
import com.cloud.agent.api.StartupExternalLoadBalancerCommand;
import com.cloud.api.ApiConstants;
import com.cloud.host.Host;
import com.cloud.host.Host.Type;
import com.cloud.resource.ServerResource;
import com.cloud.serializer.GsonHelper;
import com.cloud.utils.NumbersUtil;
import com.google.gson.Gson;
import com.cloud.utils.cisco.n1kv.vsm.CiscoNexusVSMService;
import org.apache.log4j.Logger;
class VSMError {
static final int VSM_RESOURCE_EXISTS = 89901;
static final int VSM_RESOURCE_NOT_EXISTS= 89902;
static final int VSM_NO_SERIVCE = 89903;
static final int VSM_OPERATION_NOT_PERMITTED = 89904;
}
public class CiscoNexusVSMResource implements ServerResource {
// deployment configuration
private String _name;
//private String _zoneId;
private String _ip;
private String _username;
private String _password;
private Integer _numRetries;
private static final Logger s_logger = Logger.getLogger(CiscoNexusVSMResource.class);
protected Gson _gson;
// interface to interact with Cisco Nexus VSM devices
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.
String xml_rpc_response;
public CiscoNexusVSMResource() {
_gson = GsonHelper.getGsonLogger();
}
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
try {
// What is this name?! Is it a name for the VSM device? What do we set this to??
// Can't understand why the "Manager" interface needs a String name parameter for
// configure().
// Do we need this zone id???? We may need to add other info also, like a/c id etc.
/**
_zoneId = (String) params.get("zoneId");
if (_zoneId == null) {
throw new ConfigurationException("Unable to find zone Id in the configuration parameters");
} **/
_ip = (String) params.get(ApiConstants.IP_ADDRESS);
if (_ip == null) {
throw new ConfigurationException("Unable to find IP address in the configuration parameters");
}
_username = (String) params.get(ApiConstants.USERNAME);
if (_username == null) {
throw new ConfigurationException("Unable to find username in the configuration parameters");
}
_password = (String) params.get(ApiConstants.PASSWORD);
if (_password == null) {
throw new ConfigurationException("Unable to find password in the configuration parameters");
}
_numRetries = NumbersUtil.parseInt((String) params.get("numretries"), 2);
// we may want to validate whether the username/password is right.. so we may want to
// issue a login to the VSM. However note that the VSM has a max limit of 8 concurrent
// sessions. We don't want a situation where we are opening concurrent sessions at all.
return true;
} catch (Exception e) {
throw new ConfigurationException(e.getMessage());
}
}
@Override
public IAgentControl getAgentControl() {
return null;
}
@Override
public void setAgentControl(IAgentControl agentControl) {
return;
}
@Override
public void disconnected() {
return;
}
@Override
public Type getType() {
return Host.Type.ExternalVirtualSwitchSupervisor;
}
@Override
public PingCommand getCurrentStatus(long id) {
return new PingCommand(Host.Type.ExternalVirtualSwitchSupervisor, id);
}
@Override
public StartupCommand[] initialize() {
StartupExternalLoadBalancerCommand cmd = new StartupExternalLoadBalancerCommand();
cmd.setName(_name);
//cmd.setDataCenter(_zoneId);
cmd.setPod("");
cmd.setPrivateIpAddress(_ip);
cmd.setStorageIpAddress("");
cmd.setVersion("");
return new StartupCommand[]{cmd};
}
@Override
public Answer executeRequest(Command cmd) {
return executeRequest(cmd, _numRetries);
}
// We will need to change this executeRequest() function.
private Answer executeRequest(Command cmd, int numRetries) {
return Answer.createUnsupportedCommandAnswer(cmd);
}
@Override
public String getName() {
return _name;
}
@Override
public boolean start() {
return true;
}
@Override
public boolean stop() {
return true;
}
}

View File

@ -54,8 +54,8 @@ public class AddCiscoNexusVSMCmd extends BaseAsyncCmd {
@Parameter(name=ApiConstants.IP_ADDRESS, type=CommandType.STRING, required = true, description="IP Address of the Cisco Nexus 1000v VSM appliance.")
private String ipaddr;
@Parameter(name=ApiConstants.ZONE_ID, type=CommandType.STRING, required = true, description="Id of the zone in which the Cisco Nexus 1000v VSM appliance.")
private long zoneId;
@Parameter(name=ApiConstants.ZONE_ID, type=CommandType.LONG, required = true, description="Id of the CloudStack cluster in which the Cisco Nexus 1000v VSM appliance.")
private long clusterId;
@Parameter(name=ApiConstants.USERNAME, type=CommandType.STRING, required = true, description="username to reach the Cisco Nexus 1000v VSM device")
private String username;
@ -86,14 +86,17 @@ public class AddCiscoNexusVSMCmd extends BaseAsyncCmd {
return vsmName;
}
public long getZoneId() {
return zoneId;
public long getClusterId() {
return clusterId;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
// NOTE- The uuid that is sent in during the invocation of the API AddCiscoNexusVSM()
// automagically gets translated to the corresponding db id before this execute() method
// is invoked. That's the reason why we don't have any uuid-dbid translation code here.
@Override
public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException {
try {

View File

@ -26,12 +26,14 @@ import com.cloud.agent.api.StartupCommand;
import com.cloud.api.ApiConstants;
import com.cloud.configuration.Config;
import com.cloud.configuration.dao.ConfigurationDao;
import com.cloud.dc.ClusterVO;
import com.cloud.dc.DataCenter;
import com.cloud.dc.DataCenterIpAddressVO;
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.Pod;
import com.cloud.dc.Vlan.VlanType;
import com.cloud.dc.VlanVO;
import com.cloud.dc.dao.ClusterDao;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.dc.dao.HostPodDao;
import com.cloud.dc.dao.VlanDao;
@ -44,6 +46,7 @@ import com.cloud.host.Host;
import com.cloud.host.HostVO;
import com.cloud.host.dao.HostDao;
import com.cloud.host.dao.HostDetailsDao;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.network.ExternalNetworkDeviceManager.NetworkDevice;
import com.cloud.network.Network.Service;
import com.cloud.network.Networks.TrafficType;
@ -75,6 +78,7 @@ import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.vm.dao.DomainRouterDao;
import com.cloud.vm.dao.NicDao;
import com.cloud.network.dao.CiscoNexusVSMDeviceDao;
import com.cloud.network.resource.CiscoNexusVSM;
//public abstract class CiscoNexusVSMDeviceManagerImpl extends AdapterBase implements CiscoNexusVSMDeviceManager, ResourceStateAdapter {
public abstract class CiscoNexusVSMDeviceManagerImpl extends AdapterBase {
@ -125,12 +129,49 @@ public abstract class CiscoNexusVSMDeviceManagerImpl extends AdapterBase {
NetworkServiceMapDao _ntwkSrvcProviderDao;
@Inject
protected HostPodDao _podDao = null;
@Inject
ClusterDao _clusterDao;
private static final org.apache.log4j.Logger s_logger = Logger.getLogger(ExternalLoadBalancerDeviceManagerImpl.class);
// dummy func, will remove later.
private boolean vsmIsReachable(String ipaddress, String username, String password) {
return true; // dummy true for now.
}
@DB
public CiscoNexusVSMDeviceVO addCiscoNexusVSM(long zoneId, String ipaddress, String username, String password, ServerResource resource, String vsmName) {
//public CiscoNexusVSMDeviceVO addCiscoNexusVSM(long clusterId, String ipaddress, String username, String password, ServerResource resource, String vsmName) {
public CiscoNexusVSMDeviceVO addCiscoNexusVSM(long clusterId, String ipaddress, String username, String password, String vsmName) {
// In this function, we associate this VSM with the vCenter
// that is associated with the provided clusterId.
ClusterVO cluster = _clusterDao.findById(clusterId);
// Check if the ClusterVO's hypervisor type is "vmware". If not,
// throw an exception.
if (cluster.getHypervisorType() != HypervisorType.VMware) {
InvalidParameterValueException ex = new InvalidParameterValueException("Cluster with specified id is not a VMWare hypervisor cluster");
throw ex;
}
// Now we need a reference to the vmWareResource for this cluster.
DataCenterVO zone = _dcDao.findById(cluster.getDataCenterId());
// Else, check if this VSM is reachable. Use the XML-RPC VSM API Java bindings to talk to
// the VSM.
// Create a new VSM object.
CiscoNexusVSM vsmObj = new CiscoNexusVSM(ipaddress, username, password);
if (!vsmObj.connectToVSM()) {
throw new CloudRuntimeException("Couldn't login to the specified VSM");
}
// Since we can reached the VSM, and are logged into it, let's add it to the vCenter.
// In this function, we create a record for this Cisco Nexus VSM, in the database.
// We also hand off interaction with the actual Cisco Nexus VSM via XML-RPC, to the
// Resource Manager. The resource manager invokes the CiscoNexusVSMResource class's
@ -144,10 +185,7 @@ public abstract class CiscoNexusVSMDeviceManagerImpl extends AdapterBase {
// Q1) Do we need a zoneUuid to dbzoneId translation? How will the user send in the zoneId?
// We get the zoneId as a uuid, so we need to look up the db zoneId.
// Ask Frank how to do this lookup.
long dbZoneId = zoneId;
// Q2) Do we need to have the user send in a "DedicatedUse" parameter? What is it's use
// for Netscaler?
long dbZoneId = clusterId;
hostDetails.put(ApiConstants.ZONE_ID, dbZoneId);
hostDetails.put(ApiConstants.GUID, UUID.randomUUID().toString());

View File

@ -174,12 +174,13 @@ public class CiscoNexusVSMElement extends CiscoNexusVSMDeviceManagerImpl impleme
String vsmusername = cmd.getUsername();
String vsmpassword = cmd.getPassword();
String vsmName = cmd.getVSMName();
long zoneId = cmd.getZoneId();
long clusterId = cmd.getClusterId();
// Invoke the addCiscoNexusVSM() function defined in the upper layer (DeviceMgrImpl).
// The upper layer function will create a resource of type "host" to represent this VSM.
// It will add this VSM to the db.
CiscoNexusVSMDeviceVO vsmDeviceVO = addCiscoNexusVSM(zoneId, vsmipaddress, vsmusername, vsmpassword, (ServerResource) new CiscoNexusVSMResource(), vsmName);
//CiscoNexusVSMDeviceVO vsmDeviceVO = addCiscoNexusVSM(clusterId, vsmipaddress, vsmusername, vsmpassword, (ServerResource) new CiscoNexusVSMResource(), vsmName);
CiscoNexusVSMDeviceVO vsmDeviceVO = addCiscoNexusVSM(clusterId, vsmipaddress, vsmusername, vsmpassword, vsmName);
return vsmDeviceVO;
}