diff --git a/core/src/com/cloud/network/resource/CiscoNexusVSM.java b/core/src/com/cloud/network/resource/CiscoNexusVSM.java new file mode 100644 index 00000000000..51d4a377f34 --- /dev/null +++ b/core/src/com/cloud/network/resource/CiscoNexusVSM.java @@ -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 = "urn:ietf:params:xml:ns:netconf:base:1.0]]>]]>"; + private String _clientCmd1 = "]]>]]>"; + + 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; + } + +} \ No newline at end of file diff --git a/core/src/com/cloud/network/resource/CiscoNexusVSMResource.java b/core/src/com/cloud/network/resource/CiscoNexusVSMResource.java deleted file mode 100644 index 09111d059b1..00000000000 --- a/core/src/com/cloud/network/resource/CiscoNexusVSMResource.java +++ /dev/null @@ -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 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; - } - -} \ No newline at end of file diff --git a/server/src/com/cloud/api/commands/AddCiscoNexusVSMCmd.java b/server/src/com/cloud/api/commands/AddCiscoNexusVSMCmd.java index c136dccc5a5..1b275df3e36 100644 --- a/server/src/com/cloud/api/commands/AddCiscoNexusVSMCmd.java +++ b/server/src/com/cloud/api/commands/AddCiscoNexusVSMCmd.java @@ -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 { diff --git a/server/src/com/cloud/network/CiscoNexusVSMDeviceManagerImpl.java b/server/src/com/cloud/network/CiscoNexusVSMDeviceManagerImpl.java index cf4bc5445d1..a1c90132c3f 100644 --- a/server/src/com/cloud/network/CiscoNexusVSMDeviceManagerImpl.java +++ b/server/src/com/cloud/network/CiscoNexusVSMDeviceManagerImpl.java @@ -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()); diff --git a/server/src/com/cloud/network/element/CiscoNexusVSMElement.java b/server/src/com/cloud/network/element/CiscoNexusVSMElement.java index 29a6303c8f1..f4bd8eb8260 100644 --- a/server/src/com/cloud/network/element/CiscoNexusVSMElement.java +++ b/server/src/com/cloud/network/element/CiscoNexusVSMElement.java @@ -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; }