From 11b804a8940c17e105b25ac7f9dfd87651e4c55a Mon Sep 17 00:00:00 2001 From: Chiradeep Vittal Date: Wed, 16 Jan 2013 15:29:54 -0800 Subject: [PATCH] WIP: XML control of VNMC Signed-off-by: Chiradeep Vittal --- plugins/network-elements/cisco-vnmc/build.xml | 129 ++++ plugins/network-elements/cisco-vnmc/pom.xml | 32 + .../cisco/create-edge-device-profile.xml | 14 + .../cisco/create-edge-device-route-policy.xml | 12 + .../cisco/create-edge-device-route.xml | 17 + .../scripts/network/cisco/create-tenant.xml | 9 + .../scripts/network/cisco/create-vdc.xml | 12 + .../scripts/network/cisco/list-tenants.xml | 8 + .../scripts/network/cisco/login.xml | 20 + .../cisco/responses/list-tenants-response.xml | 7 + .../network/cisco/responses/login-error.xml | 1 + .../network/cisco/responses/login-success.xml | 2 + .../cisco-vnmc/src/CiscoVnmcResourceTest.java | 96 +++ .../api/commands/AddExternalFirewallCmd.java | 109 +++ .../network/resource/CiscoVnmcResource.java | 647 ++++++++++++++++++ .../src/com/cloud/network/resource/x | 2 + .../ssl/EasySSLProtocolSocketFactory.java | 232 +++++++ .../contrib/ssl/EasyX509TrustManager.java | 114 +++ 18 files changed, 1463 insertions(+) create mode 100755 plugins/network-elements/cisco-vnmc/build.xml create mode 100644 plugins/network-elements/cisco-vnmc/pom.xml create mode 100644 plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-edge-device-profile.xml create mode 100644 plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-edge-device-route-policy.xml create mode 100644 plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-edge-device-route.xml create mode 100644 plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-tenant.xml create mode 100644 plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-vdc.xml create mode 100644 plugins/network-elements/cisco-vnmc/scripts/network/cisco/list-tenants.xml create mode 100644 plugins/network-elements/cisco-vnmc/scripts/network/cisco/login.xml create mode 100644 plugins/network-elements/cisco-vnmc/scripts/network/cisco/responses/list-tenants-response.xml create mode 100644 plugins/network-elements/cisco-vnmc/scripts/network/cisco/responses/login-error.xml create mode 100644 plugins/network-elements/cisco-vnmc/scripts/network/cisco/responses/login-success.xml create mode 100644 plugins/network-elements/cisco-vnmc/src/CiscoVnmcResourceTest.java create mode 100644 plugins/network-elements/cisco-vnmc/src/com/cloud/api/commands/AddExternalFirewallCmd.java create mode 100644 plugins/network-elements/cisco-vnmc/src/com/cloud/network/resource/CiscoVnmcResource.java create mode 100644 plugins/network-elements/cisco-vnmc/src/com/cloud/network/resource/x create mode 100644 plugins/network-elements/cisco-vnmc/src/org/apache/commons/httpclient/contrib/ssl/EasySSLProtocolSocketFactory.java create mode 100644 plugins/network-elements/cisco-vnmc/src/org/apache/commons/httpclient/contrib/ssl/EasyX509TrustManager.java diff --git a/plugins/network-elements/cisco-vnmc/build.xml b/plugins/network-elements/cisco-vnmc/build.xml new file mode 100755 index 00000000000..c9eca5d108b --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/build.xml @@ -0,0 +1,129 @@ + + + + + + + Cloud Stack ant build file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/network-elements/cisco-vnmc/pom.xml b/plugins/network-elements/cisco-vnmc/pom.xml new file mode 100644 index 00000000000..d69cd64f5e6 --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/pom.xml @@ -0,0 +1,32 @@ + + + 4.0.0 + cloud-plugin-network-cisco-vnmc + Apache CloudStack Plugin - Cisco VNMC + + org.apache.cloudstack + cloudstack-plugins + 4.0.0-SNAPSHOT + ../../pom.xml + + + + diff --git a/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-edge-device-profile.xml b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-edge-device-profile.xml new file mode 100644 index 00000000000..2baec16b321 --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-edge-device-profile.xml @@ -0,0 +1,14 @@ + + + + + + diff --git a/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-edge-device-route-policy.xml b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-edge-device-route-policy.xml new file mode 100644 index 00000000000..3b760de3a64 --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-edge-device-route-policy.xml @@ -0,0 +1,12 @@ + + + + + diff --git a/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-edge-device-route.xml b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-edge-device-route.xml new file mode 100644 index 00000000000..24b55e5d02f --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-edge-device-route.xml @@ -0,0 +1,17 @@ + + + + + + + diff --git a/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-tenant.xml b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-tenant.xml new file mode 100644 index 00000000000..1dd8f2098ee --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-tenant.xml @@ -0,0 +1,9 @@ + + + + + diff --git a/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-vdc.xml b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-vdc.xml new file mode 100644 index 00000000000..a303ee42499 --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-vdc.xml @@ -0,0 +1,12 @@ + + + + + diff --git a/plugins/network-elements/cisco-vnmc/scripts/network/cisco/list-tenants.xml b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/list-tenants.xml new file mode 100644 index 00000000000..6f912ea3a93 --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/list-tenants.xml @@ -0,0 +1,8 @@ + + + + diff --git a/plugins/network-elements/cisco-vnmc/scripts/network/cisco/login.xml b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/login.xml new file mode 100644 index 00000000000..8e1c435ea15 --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/login.xml @@ -0,0 +1,20 @@ + + + diff --git a/plugins/network-elements/cisco-vnmc/scripts/network/cisco/responses/list-tenants-response.xml b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/responses/list-tenants-response.xml new file mode 100644 index 00000000000..00d5f9642dd --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/responses/list-tenants-response.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/plugins/network-elements/cisco-vnmc/scripts/network/cisco/responses/login-error.xml b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/responses/login-error.xml new file mode 100644 index 00000000000..ae94fb16176 --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/responses/login-error.xml @@ -0,0 +1 @@ + diff --git a/plugins/network-elements/cisco-vnmc/scripts/network/cisco/responses/login-success.xml b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/responses/login-success.xml new file mode 100644 index 00000000000..ce7c3098313 --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/responses/login-success.xml @@ -0,0 +1,2 @@ + + diff --git a/plugins/network-elements/cisco-vnmc/src/CiscoVnmcResourceTest.java b/plugins/network-elements/cisco-vnmc/src/CiscoVnmcResourceTest.java new file mode 100644 index 00000000000..0ea67aab7ca --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/src/CiscoVnmcResourceTest.java @@ -0,0 +1,96 @@ +import static org.junit.Assert.*; + +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.cloud.network.resource.CiscoVnmcResource; +import com.cloud.utils.exception.ExecutionException; + + +public class CiscoVnmcResourceTest { + static CiscoVnmcResource resource; + @BeforeClass + public static void setUpClass() throws Exception { + resource = new CiscoVnmcResource("10.223.56.5", "admin", "C1sco123"); + try { + boolean response = resource.login(); + assertTrue(response); + } catch (ExecutionException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + @Test + public void testLogin() { + //fail("Not yet implemented"); + try { + boolean response = resource.login(); + assertTrue(response); + } catch (ExecutionException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + @Test + public void testCreateTenant() { + //fail("Not yet implemented"); + try { + boolean response = resource.createTenant("TenantA"); + assertTrue(response); + } catch (ExecutionException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + @Test + public void testCreateTenantVDC() { + //fail("Not yet implemented"); + try { + boolean response = resource.createTenantVDC("TenantA"); + assertTrue(response); + } catch (ExecutionException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + + @Test + public void testCreateTenantVDCEdgeDeviceProfile() { + //fail("Not yet implemented"); + try { + boolean response = resource.createTenantVDCEdgeDeviceProfile("TenantA"); + assertTrue(response); + } catch (ExecutionException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + @Test + public void testCreateTenantVDCEdgeDeviceRoutePolicy() { + try { + boolean response = resource.createTenantVDCEdgeStaticRoutePolicy("TenantA"); + assertTrue(response); + } catch (ExecutionException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + @Test + public void testCreateTenantVDCEdgeDeviceRoute() { + try { + boolean response = resource.createTenantVDCEdgeStaticRoute("TenantA", + "10.223.136.1", "Edge_Outside", "0.0.0.0", "0.0.0.0"); + assertTrue(response); + } catch (ExecutionException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } +} diff --git a/plugins/network-elements/cisco-vnmc/src/com/cloud/api/commands/AddExternalFirewallCmd.java b/plugins/network-elements/cisco-vnmc/src/com/cloud/api/commands/AddExternalFirewallCmd.java new file mode 100644 index 00000000000..1abe6b2804d --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/src/com/cloud/api/commands/AddExternalFirewallCmd.java @@ -0,0 +1,109 @@ +// 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.api.commands; + +import org.apache.log4j.Logger; + +import com.cloud.api.ApiConstants; +import com.cloud.api.BaseCmd; +import com.cloud.api.IdentityMapper; +import com.cloud.api.Implementation; +import com.cloud.api.Parameter; +import com.cloud.api.PlugService; +import com.cloud.api.ServerApiException; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.host.Host; +import com.cloud.server.api.response.ExternalFirewallResponse; +import com.cloud.user.Account; +import com.cloud.utils.exception.CloudRuntimeException; + +@Implementation(description="Adds an external firewall appliance", responseObject = ExternalFirewallResponse.class) +public class AddExternalFirewallCmd extends BaseCmd { + public static final Logger s_logger = Logger.getLogger(AddExternalFirewallCmd.class.getName()); + private static final String s_name = "addexternalfirewallresponse"; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @IdentityMapper(entityTableName="data_center") + @Parameter(name=ApiConstants.ZONE_ID, type=CommandType.LONG, required = true, description="Zone in which to add the external firewall appliance.") + private Long zoneId; + + @Parameter(name=ApiConstants.URL, type=CommandType.STRING, required = true, description="URL of the external firewall appliance.") + private String url; + + @Parameter(name=ApiConstants.USERNAME, type=CommandType.STRING, required = true, description="Username of the external firewall appliance.") + private String username; + + @Parameter(name=ApiConstants.PASSWORD, type=CommandType.STRING, required = true, description="Password of the external firewall appliance.") + private String password; + + /////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public Long getZoneId() { + return zoneId; + } + + public String getUrl() { + return url; + } + + public String getUsername() { + return username; + } + + public String getPassword() { + return password; + } + + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + //@PlugService JuniperSRXFirewallElementService _srxElementService; + + @Override + public String getCommandName() { + return s_name; + } + + @Override + public long getEntityOwnerId() { + return Account.ACCOUNT_ID_SYSTEM; + } + + @SuppressWarnings("deprecation") + @Override + public void execute(){ + try { +// Host externalFirewall = _srxElementService.addExternalFirewall(this); +// ExternalFirewallResponse response = _srxElementService.createExternalFirewallResponse(externalFirewall); +// response.setObjectName("externalfirewall"); +// response.setResponseName(getCommandName()); + // this.setResponseObject(response); + } catch (InvalidParameterValueException ipve) { + throw new ServerApiException(BaseCmd.PARAM_ERROR, ipve.getMessage()); + } catch (CloudRuntimeException cre) { + throw new ServerApiException(BaseCmd.INTERNAL_ERROR, cre.getMessage()); + } + } +} + diff --git a/plugins/network-elements/cisco-vnmc/src/com/cloud/network/resource/CiscoVnmcResource.java b/plugins/network-elements/cisco-vnmc/src/com/cloud/network/resource/CiscoVnmcResource.java new file mode 100644 index 00000000000..180b665a490 --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/src/com/cloud/network/resource/CiscoVnmcResource.java @@ -0,0 +1,647 @@ +// 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.network.resource; + +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.StringReader; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.naming.ConfigurationException; +import javax.xml.parsers.DocumentBuilderFactory; + +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.HttpStatus; +import org.apache.commons.httpclient.contrib.ssl.EasySSLProtocolSocketFactory; +import org.apache.commons.httpclient.methods.PostMethod; +import org.apache.log4j.Logger; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.xml.sax.InputSource; + +import com.cloud.agent.IAgentControl; +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.Command; +import com.cloud.agent.api.ExternalNetworkResourceUsageAnswer; +import com.cloud.agent.api.ExternalNetworkResourceUsageCommand; +import com.cloud.agent.api.MaintainAnswer; +import com.cloud.agent.api.MaintainCommand; +import com.cloud.agent.api.PingCommand; +import com.cloud.agent.api.ReadyAnswer; +import com.cloud.agent.api.ReadyCommand; +import com.cloud.agent.api.StartupCommand; +import com.cloud.agent.api.StartupExternalFirewallCommand; +import com.cloud.agent.api.routing.IpAssocAnswer; +import com.cloud.agent.api.routing.IpAssocCommand; +import com.cloud.agent.api.routing.NetworkElementCommand; +import com.cloud.agent.api.routing.SetPortForwardingRulesCommand; +import com.cloud.agent.api.routing.SetStaticNatRulesCommand; +import com.cloud.agent.api.to.IpAddressTO; +import com.cloud.host.Host; +import com.cloud.resource.ServerResource; +import com.cloud.utils.NumbersUtil; +import com.cloud.utils.exception.ExecutionException; +import com.cloud.utils.net.NetUtils; +import com.cloud.utils.script.Script; + +public class CiscoVnmcResource implements ServerResource { + + private String _name; + private String _zoneId; + private String _physicalNetworkId; + private String _ip; + private String _username; + private String _password; + private String _guid; + private String _objectNameWordSep; + private Integer _numRetries; + private String _publicZone; + private String _privateZone; + private String _publicInterface; + private String _privateInterface; + private String _cookie; + + + private String _primaryDnsAddress; + + + private final Logger s_logger = Logger.getLogger(CiscoVnmcResource.class); + + private enum VnmcXml { + LOGIN("login.xml", "mgmt-controller"), + CREATE_TENANT("create-tenant.xml", "service-reg"), + CREATE_VDC("create-vdc.xml", "service-reg"), + CREATE_EDGE_DEVICE_PROFILE("create-edge-device-profile.xml", "policy-mgr"), + CREATE_EDGE_ROUTE_POLICY("create-edge-device-route-policy.xml", "policy-mgr"), + CREATE_EDGE_ROUTE("create-edge-device-route.xml", "policy-mgr"); + + + private String scriptsDir = "scripts/network/cisco"; + private String xml; + private String service; + private final Logger s_logger = Logger.getLogger(CiscoVnmcResource.class); + + private VnmcXml(String filename, String service) { + this.xml = getXml(filename); + this.service = service; + } + + public String getXml() { + return xml; + } + + private String getXml(String filename) { + try { + String xmlFilePath = Script.findScript(scriptsDir, filename); + + if (xmlFilePath == null) { + throw new Exception("Failed to find Cisco VNMC XML file: " + filename); + } + + FileReader fr = new FileReader(xmlFilePath); + BufferedReader br = new BufferedReader(fr); + + String xml = ""; + String line; + while ((line = br.readLine()) != null) { + xml += line.replaceAll("\n"," "); + } + + return xml; + } catch (Exception e) { + s_logger.debug(e); + return null; + } + } + + public String getService() { + return service; + } + } + + + + public CiscoVnmcResource(String ip, String username, String password) { + _ip = ip; + _username = username; + _password = password; + } + + public Answer executeRequest(Command cmd) { + if (cmd instanceof ReadyCommand) { + return execute((ReadyCommand) cmd); + } else if (cmd instanceof MaintainCommand) { + return execute((MaintainCommand) cmd); + } else if (cmd instanceof IpAssocCommand) { + return execute((IpAssocCommand) cmd); + } else if (cmd instanceof SetStaticNatRulesCommand) { + return execute((SetStaticNatRulesCommand) cmd); + } else if (cmd instanceof SetPortForwardingRulesCommand) { + return execute((SetPortForwardingRulesCommand) cmd); + } else if (cmd instanceof ExternalNetworkResourceUsageCommand) { + return execute((ExternalNetworkResourceUsageCommand) cmd); + } else { + return Answer.createUnsupportedCommandAnswer(cmd); + } + } + + public boolean configure(String name, Map params) throws ConfigurationException { + try { + _name = (String) params.get("name"); + if (_name == null) { + throw new ConfigurationException("Unable to find name"); + } + + _zoneId = (String) params.get("zoneId"); + if (_zoneId == null) { + throw new ConfigurationException("Unable to find zone"); + } + + _physicalNetworkId = (String) params.get("physicalNetworkId"); + if (_physicalNetworkId == null) { + throw new ConfigurationException("Unable to find physical network id in the configuration parameters"); + } + + _ip = (String) params.get("ip"); + if (_ip == null) { + throw new ConfigurationException("Unable to find IP"); + } + + _username = (String) params.get("username"); + if (_username == null) { + throw new ConfigurationException("Unable to find username"); + } + + _password = (String) params.get("password"); + if (_password == null) { + throw new ConfigurationException("Unable to find password"); + } + + _publicInterface = (String) params.get("publicinterface"); + if (_publicInterface == null) { + throw new ConfigurationException("Unable to find public interface."); + } + + + _privateInterface = (String) params.get("privateinterface"); + if (_privateInterface == null) { + throw new ConfigurationException("Unable to find private interface."); + } + + _publicZone = (String) params.get("publiczone"); + if (_publicZone == null) { + _publicZone = "untrust"; + } + + _privateZone = (String) params.get("privatezone"); + if (_privateZone == null) { + _privateZone = "trust"; + } + + _guid = (String)params.get("guid"); + if (_guid == null) { + throw new ConfigurationException("Unable to find the guid"); + } + + _numRetries = NumbersUtil.parseInt((String) params.get("numretries"), 1); + + NumbersUtil.parseInt((String) params.get("timeout"), 300); + + _objectNameWordSep = "-"; + + _primaryDnsAddress = "4.2.2.2"; + + // Open a socket and login + if (!refreshVnmcConnection()) { + throw new ConfigurationException("Unable to open a connection to the VNMC."); + } + + return true; + } catch (Exception e) { + throw new ConfigurationException(e.getMessage()); + } + + } + + public StartupCommand[] initialize() { + StartupExternalFirewallCommand cmd = new StartupExternalFirewallCommand(); + cmd.setName(_name); + cmd.setDataCenter(_zoneId); + cmd.setPod(""); + cmd.setPrivateIpAddress(_ip); + cmd.setStorageIpAddress(""); + cmd.setVersion(""); + cmd.setGuid(_guid); + return new StartupCommand[]{cmd}; + } + + public Host.Type getType() { + return Host.Type.ExternalFirewall; + } + + @Override + public String getName() { + return _name; + } + + @Override + public boolean start() { + return true; + } + + @Override + public boolean stop() { + return true; + } + + @Override + public PingCommand getCurrentStatus(final long id) { + return new PingCommand(Host.Type.ExternalFirewall, id); + } + + @Override + public void disconnected() { + } + + public IAgentControl getAgentControl() { + return null; + } + + public void setAgentControl(IAgentControl agentControl) { + return; + } + + private Answer execute(ReadyCommand cmd) { + return new ReadyAnswer(cmd); + } + + private Answer execute(MaintainCommand cmd) { + return new MaintainAnswer(cmd); + } + + private ExternalNetworkResourceUsageAnswer execute(ExternalNetworkResourceUsageCommand cmd) { + + return new ExternalNetworkResourceUsageAnswer(cmd); + + } + + /* + * Login + */ + + private boolean refreshVnmcConnection() { + return true; + } + + public boolean login() throws ExecutionException { + String xml = VnmcXml.LOGIN.getXml(); + String service = VnmcXml.LOGIN.getService(); + xml = replaceXmlValue(xml, "username", _username); + xml = replaceXmlValue(xml, "password", _password); + String response = sendRequest(service, xml); + Map checked = checkResponse(response, "outCookie", "errorCode", "response"); + + if (checked.get("errorCode") != null) + return false; + _cookie = checked.get("outCookie"); + if (_cookie == null) { + return false; + } + return true; + } + + private String getDnForTenant(String tenantName) { + return "org-root/org-" + tenantName; + } + + private String getDnForTenantVDC(String tenantName) { + return getDnForTenant(tenantName) + "/org-VDC-" + tenantName; + } + + private String getDnForTenantVDCEdgeDeviceProfile(String tenantName) { + return getDnForTenantVDC(tenantName) + "/edsp-" + tenantName + "-Edge-Device-Profile"; + } + + private String getDnForEdgeDeviceRoutingPolicy(String tenantName) { + return getDnForTenantVDC(tenantName) + "/routing-policy-EDSP-" + tenantName + "-Routes"; + //FIXME: any other construct is unreliable. why? + } + + private String getDnForEdgeDeviceRoute(String tenantName, int id) { + return getDnForEdgeDeviceRoutingPolicy(tenantName) + "/sroute-" + id ; + } + + + public boolean createTenant(String tenantName) throws ExecutionException { + String xml = VnmcXml.CREATE_TENANT.getXml(); + String service = VnmcXml.CREATE_TENANT.getService(); + xml = replaceXmlValue(xml, "cookie", _cookie); + xml = replaceXmlValue(xml, "descr", "Tenant for account " + tenantName); + xml = replaceXmlValue(xml, "name", tenantName); + xml = replaceXmlValue(xml, "dn", getDnForTenant(tenantName)); + + String response = sendRequest(service, xml); + Map checked = checkResponse(response, "errorCode", "response"); + + if (checked.get("errorCode") != null) { + String errorCode = checked.get("errorCode"); + if (errorCode.equals("103")) { + //tenant already exists + return true; + } + return false; + } + return true; + } + + public boolean createTenantVDC(String tenantName) throws ExecutionException { + String xml = VnmcXml.CREATE_VDC.getXml(); + String service = VnmcXml.CREATE_VDC.getService(); + xml = replaceXmlValue(xml, "cookie", _cookie); + xml = replaceXmlValue(xml, "descr", "VDC for Tenant" + tenantName); + xml = replaceXmlValue(xml, "name", "VDC-" + tenantName); + xml = replaceXmlValue(xml, "dn", getDnForTenantVDC(tenantName)); + + String response = sendRequest(service, xml); + Map checked = checkResponse(response, "errorCode", "response"); + + if (checked.get("errorCode") != null) { + String errorCode = checked.get("errorCode"); + if (errorCode.equals("103")) { + //tenant already exists + return true; + } + return false; + } + return true; + } + + public boolean createTenantVDCEdgeDeviceProfile(String tenantName) throws ExecutionException { + String xml = VnmcXml.CREATE_EDGE_DEVICE_PROFILE.getXml(); + String service = VnmcXml.CREATE_EDGE_DEVICE_PROFILE.getService(); + xml = replaceXmlValue(xml, "cookie", _cookie); + xml = replaceXmlValue(xml, "descr", "Edge Device Profile for Tenant VDC" + tenantName); + xml = replaceXmlValue(xml, "name", "EDSP-" + tenantName); + xml = replaceXmlValue(xml, "dn", getDnForTenantVDCEdgeDeviceProfile(tenantName)); + + String response = sendRequest(service, xml); + Map checked = checkResponse(response, "errorCode", "response"); + + if (checked.get("errorCode") != null) { + String errorCode = checked.get("errorCode"); + if (errorCode.equals("103")) { + //tenant already exists + return true; + } + return false; + } + return true; + } + + public boolean createTenantVDCEdgeStaticRoutePolicy(String tenantName) throws ExecutionException { + String xml = VnmcXml.CREATE_EDGE_ROUTE_POLICY.getXml(); + String service = VnmcXml.CREATE_EDGE_ROUTE_POLICY.getService(); + xml = replaceXmlValue(xml, "cookie", _cookie); + xml = replaceXmlValue(xml, "name", "EDSP-" + tenantName + "-Routes");//FIXME: this has to match DN somehow? + xml = replaceXmlValue(xml, "routepolicydn", getDnForEdgeDeviceRoutingPolicy(tenantName)); + xml = replaceXmlValue(xml, "descr", "Routing Policy for Edge Device for Tenant " + tenantName); + + + String response = sendRequest(service, xml); + Map checked = checkResponse(response, "errorCode", "response"); + + if (checked.get("errorCode") != null) { + String errorCode = checked.get("errorCode"); + if (errorCode.equals("103")) { + //already exists + return true; + } + return false; + } + return true; + } + + public boolean createTenantVDCEdgeStaticRoute(String tenantName, + String nextHopIp, String outsideIntf, + String destination, String netmask) throws ExecutionException { + String xml = VnmcXml.CREATE_EDGE_ROUTE.getXml(); + String service = VnmcXml.CREATE_EDGE_ROUTE.getService(); + xml = replaceXmlValue(xml, "cookie", _cookie); + xml = replaceXmlValue(xml, "routedn", getDnForEdgeDeviceRoute(tenantName, 2));//TODO: why 2? + xml = replaceXmlValue(xml, "id", "2"); // TODO:2? + xml = replaceXmlValue(xml, "nexthop", nextHopIp); + xml = replaceXmlValue(xml, "nexthopintf", outsideIntf); + xml = replaceXmlValue(xml, "destination", destination); + xml = replaceXmlValue(xml, "netmask", netmask); + + //TODO: this adds default route, make it more generic + + String response = sendRequest(service, xml); + Map checked = checkResponse(response, "errorCode", "response"); + + if (checked.get("errorCode") != null) { + String errorCode = checked.get("errorCode"); + if (errorCode.equals("103")) { + //tenant already exists + return true; + } + return false; + } + return true; + } + private String sendRequest(String service, String xmlRequest) throws ExecutionException { + org.apache.commons.httpclient.protocol.Protocol myhttps = + new org.apache.commons.httpclient.protocol.Protocol("https", new EasySSLProtocolSocketFactory(), 443); + HttpClient client = new HttpClient(); + client.getHostConfiguration().setHost(_ip, 443, myhttps); + byte[] response = null; + PostMethod method = new PostMethod("/xmlIM/" + service); + + method.setRequestBody(xmlRequest); + + try{ + int statusCode = client.executeMethod(method); + + if (statusCode != HttpStatus.SC_OK) { + throw new Exception("Error code : " + statusCode); + } + response = method.getResponseBody(); + }catch(Exception e){ + System.out.println(e.getMessage()); + } + System.out.println(new String(response)); + return new String(response); + } + + + + + private synchronized Answer execute(IpAssocCommand cmd) { + refreshVnmcConnection(); + return execute(cmd, _numRetries); + } + + private Answer execute(IpAssocCommand cmd, int numRetries) { + String[] results = new String[cmd.getIpAddresses().length]; + + + return new IpAssocAnswer(cmd, results); + } + + + /* + * Static NAT + */ + + private synchronized Answer execute(SetStaticNatRulesCommand cmd) { + refreshVnmcConnection(); + return execute(cmd, _numRetries); + } + + private Answer execute(SetStaticNatRulesCommand cmd, int numRetries) { + + return new Answer(cmd); + + } + + + + + + + /* + * Destination NAT + */ + + private synchronized Answer execute (SetPortForwardingRulesCommand cmd) { + refreshVnmcConnection(); + return execute(cmd, _numRetries); + } + + private Answer execute(SetPortForwardingRulesCommand cmd, int numRetries) { + + return new Answer(cmd); + + } + + /* + * XML API commands + */ + + private Map checkResponse(String xmlResponse, String... keys) throws ExecutionException { + Document xmlDoc = getDocument(xmlResponse); + Map result = new HashMap(); + Node topElement = xmlDoc.getChildNodes().item(0); + if (topElement != null) { + for (String key: keys){ + Node valueNode = topElement.getAttributes().getNamedItem(key); + result.put(key, valueNode==null?null:valueNode.getNodeValue()); + } + } + return result; + } + + + + + /* + * XML utils + */ + + private String replaceXmlTag(String xml, String oldTag, String newTag) { + return xml.replaceAll(oldTag, newTag); + } + + private String replaceXmlValue(String xml, String marker, String value) { + marker = "\\s*%" + marker + "%\\s*"; + + if (value == null) { + value = ""; + } + + return xml.replaceAll(marker, value); + } + + private String extractXml(String xml, String marker) { + String startMarker = "<" + marker + ">"; + String endMarker = ""; + if (xml.contains(startMarker) && xml.contains(endMarker)) { + return xml.substring(xml.indexOf(startMarker) + startMarker.length(), xml.indexOf(endMarker)); + } else { + return null; + } + + } + + + + /* + * Misc + */ + + private Long getVlanTag(String vlan) throws ExecutionException { + Long publicVlanTag = null; + if (!vlan.equals("untagged")) { + try { + publicVlanTag = Long.parseLong(vlan); + } catch (Exception e) { + throw new ExecutionException("Unable to parse VLAN tag: " + vlan); + } + } + + return publicVlanTag; + } + + private String genObjectName(String... args) { + String objectName = ""; + + for (int i = 0; i < args.length; i++) { + objectName += args[i]; + if (i != args.length -1) { + objectName += _objectNameWordSep; + } + } + + return objectName; + } + + + + + private Document getDocument(String xml) throws ExecutionException { + StringReader xmlReader = new StringReader(" \n" + xml.trim()); + InputSource xmlSource = new InputSource(xmlReader); + Document doc = null; + + try { + doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(xmlSource); + + } catch (Exception e) { + s_logger.error(e); + throw new ExecutionException(e.getMessage()); + } + + if (doc == null) { + throw new ExecutionException("Failed to parse xml " + xml); + } else { + return doc; + } + } + +} diff --git a/plugins/network-elements/cisco-vnmc/src/com/cloud/network/resource/x b/plugins/network-elements/cisco-vnmc/src/com/cloud/network/resource/x new file mode 100644 index 00000000000..8a4ae9bd9bd --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/src/com/cloud/network/resource/x @@ -0,0 +1,2 @@ +org-root/org-TenantA/org-VDC-TenantA/routing-policy-EDSP-TenantA-Routes/sroute-2 +org-root/org-TenantA/org-VDC-TenantA/routing-policy-EDSP-TenantA-Routes/sroute-2 diff --git a/plugins/network-elements/cisco-vnmc/src/org/apache/commons/httpclient/contrib/ssl/EasySSLProtocolSocketFactory.java b/plugins/network-elements/cisco-vnmc/src/org/apache/commons/httpclient/contrib/ssl/EasySSLProtocolSocketFactory.java new file mode 100644 index 00000000000..52f0ea66f50 --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/src/org/apache/commons/httpclient/contrib/ssl/EasySSLProtocolSocketFactory.java @@ -0,0 +1,232 @@ +/* + * $HeadURL$ + * $Revision$ + * $Date$ + * + * ==================================================================== + * + * 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.commons.httpclient.contrib.ssl; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.net.SocketAddress; +import java.net.UnknownHostException; + +import javax.net.SocketFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; + +import org.apache.commons.httpclient.ConnectTimeoutException; +import org.apache.commons.httpclient.HttpClientError; +import org.apache.commons.httpclient.params.HttpConnectionParams; +import org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + *

+ * EasySSLProtocolSocketFactory can be used to creats SSL {@link Socket}s + * that accept self-signed certificates. + *

+ *

+ * This socket factory SHOULD NOT be used for productive systems + * due to security reasons, unless it is a concious decision and + * you are perfectly aware of security implications of accepting + * self-signed certificates + *

+ * + *

+ * Example of using custom protocol socket factory for a specific host: + *

+ *     Protocol easyhttps = new Protocol("https", new EasySSLProtocolSocketFactory(), 443);
+ *
+ *     URI uri = new URI("https://localhost/", true);
+ *     // use relative url only
+ *     GetMethod httpget = new GetMethod(uri.getPathQuery());
+ *     HostConfiguration hc = new HostConfiguration();
+ *     hc.setHost(uri.getHost(), uri.getPort(), easyhttps);
+ *     HttpClient client = new HttpClient();
+ *     client.executeMethod(hc, httpget);
+ *     
+ *

+ *

+ * Example of using custom protocol socket factory per default instead of the standard one: + *

+ *     Protocol easyhttps = new Protocol("https", new EasySSLProtocolSocketFactory(), 443);
+ *     Protocol.registerProtocol("https", easyhttps);
+ *
+ *     HttpClient client = new HttpClient();
+ *     GetMethod httpget = new GetMethod("https://localhost/");
+ *     client.executeMethod(httpget);
+ *     
+ *

+ * + * @author Oleg Kalnichevski + * + *

+ * DISCLAIMER: HttpClient developers DO NOT actively support this component. + * The component is provided as a reference material, which may be inappropriate + * for use without additional customization. + *

+ */ + +public class EasySSLProtocolSocketFactory implements SecureProtocolSocketFactory { + + /** Log object for this class. */ + private static final Log LOG = LogFactory.getLog(EasySSLProtocolSocketFactory.class); + + private SSLContext sslcontext = null; + + /** + * Constructor for EasySSLProtocolSocketFactory. + */ + public EasySSLProtocolSocketFactory() { + super(); + } + + private static SSLContext createEasySSLContext() { + try { + SSLContext context = SSLContext.getInstance("SSL"); + context.init( + null, + new TrustManager[] {new EasyX509TrustManager(null)}, + null); + return context; + } catch (Exception e) { + LOG.error(e.getMessage(), e); + throw new HttpClientError(e.toString()); + } + } + + private SSLContext getSSLContext() { + if (this.sslcontext == null) { + this.sslcontext = createEasySSLContext(); + } + return this.sslcontext; + } + + /** + * @see SecureProtocolSocketFactory#createSocket(java.lang.String,int,java.net.InetAddress,int) + */ + public Socket createSocket( + String host, + int port, + InetAddress clientHost, + int clientPort) + throws IOException, UnknownHostException { + + return getSSLContext().getSocketFactory().createSocket( + host, + port, + clientHost, + clientPort + ); + } + + /** + * Attempts to get a new socket connection to the given host within the given time limit. + *

+ * To circumvent the limitations of older JREs that do not support connect timeout a + * controller thread is executed. The controller thread attempts to create a new socket + * within the given limit of time. If socket constructor does not return until the + * timeout expires, the controller terminates and throws an {@link ConnectTimeoutException} + *

+ * + * @param host the host name/IP + * @param port the port on the host + * @param clientHost the local host name/IP to bind the socket to + * @param clientPort the port on the local machine + * @param params {@link HttpConnectionParams Http connection parameters} + * + * @return Socket a new socket + * + * @throws IOException if an I/O error occurs while creating the socket + * @throws UnknownHostException if the IP address of the host cannot be + * determined + */ + public Socket createSocket( + final String host, + final int port, + final InetAddress localAddress, + final int localPort, + final HttpConnectionParams params + ) throws IOException, UnknownHostException, ConnectTimeoutException { + if (params == null) { + throw new IllegalArgumentException("Parameters may not be null"); + } + int timeout = params.getConnectionTimeout(); + SocketFactory socketfactory = getSSLContext().getSocketFactory(); + if (timeout == 0) { + return socketfactory.createSocket(host, port, localAddress, localPort); + } else { + Socket socket = socketfactory.createSocket(); + SocketAddress localaddr = new InetSocketAddress(localAddress, localPort); + SocketAddress remoteaddr = new InetSocketAddress(host, port); + socket.bind(localaddr); + socket.connect(remoteaddr, timeout); + return socket; + } + } + + /** + * @see SecureProtocolSocketFactory#createSocket(java.lang.String,int) + */ + public Socket createSocket(String host, int port) + throws IOException, UnknownHostException { + return getSSLContext().getSocketFactory().createSocket( + host, + port + ); + } + + /** + * @see SecureProtocolSocketFactory#createSocket(java.net.Socket,java.lang.String,int,boolean) + */ + public Socket createSocket( + Socket socket, + String host, + int port, + boolean autoClose) + throws IOException, UnknownHostException { + return getSSLContext().getSocketFactory().createSocket( + socket, + host, + port, + autoClose + ); + } + + public boolean equals(Object obj) { + return ((obj != null) && obj.getClass().equals(EasySSLProtocolSocketFactory.class)); + } + + public int hashCode() { + return EasySSLProtocolSocketFactory.class.hashCode(); + } + +} diff --git a/plugins/network-elements/cisco-vnmc/src/org/apache/commons/httpclient/contrib/ssl/EasyX509TrustManager.java b/plugins/network-elements/cisco-vnmc/src/org/apache/commons/httpclient/contrib/ssl/EasyX509TrustManager.java new file mode 100644 index 00000000000..ae9f9380b31 --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/src/org/apache/commons/httpclient/contrib/ssl/EasyX509TrustManager.java @@ -0,0 +1,114 @@ +/* + * ==================================================================== + * + * 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.commons.httpclient.contrib.ssl; + +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; + +import javax.net.ssl.TrustManagerFactory; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + *

+ * EasyX509TrustManager unlike default {@link X509TrustManager} accepts + * self-signed certificates. + *

+ *

+ * This trust manager SHOULD NOT be used for productive systems + * due to security reasons, unless it is a concious decision and + * you are perfectly aware of security implications of accepting + * self-signed certificates + *

+ * + * @author Adrian Sutton + * @author Oleg Kalnichevski + * + *

+ * DISCLAIMER: HttpClient developers DO NOT actively support this component. + * The component is provided as a reference material, which may be inappropriate + * for use without additional customization. + *

+ */ + +public class EasyX509TrustManager implements X509TrustManager +{ + private X509TrustManager standardTrustManager = null; + + /** Log object for this class. */ + private static final Log LOG = LogFactory.getLog(EasyX509TrustManager.class); + + /** + * Constructor for EasyX509TrustManager. + */ + public EasyX509TrustManager(KeyStore keystore) throws NoSuchAlgorithmException, KeyStoreException { + super(); + TrustManagerFactory factory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + factory.init(keystore); + TrustManager[] trustmanagers = factory.getTrustManagers(); + if (trustmanagers.length == 0) { + throw new NoSuchAlgorithmException("no trust manager found"); + } + this.standardTrustManager = (X509TrustManager)trustmanagers[0]; + } + + /** + * @see javax.net.ssl.X509TrustManager#checkClientTrusted(X509Certificate[],String authType) + */ + public void checkClientTrusted(X509Certificate[] certificates,String authType) throws CertificateException { + standardTrustManager.checkClientTrusted(certificates,authType); + } + + /** + * @see javax.net.ssl.X509TrustManager#checkServerTrusted(X509Certificate[],String authType) + */ + public void checkServerTrusted(X509Certificate[] certificates,String authType) throws CertificateException { + if ((certificates != null) && LOG.isDebugEnabled()) { + LOG.debug("Server certificate chain:"); + for (int i = 0; i < certificates.length; i++) { + LOG.debug("X509Certificate[" + i + "]=" + certificates[i]); + } + } + if ((certificates != null) && (certificates.length == 1)) { + certificates[0].checkValidity(); + } else { + standardTrustManager.checkServerTrusted(certificates,authType); + } + } + + /** + * @see javax.net.ssl.X509TrustManager#getAcceptedIssuers() + */ + public X509Certificate[] getAcceptedIssuers() { + return this.standardTrustManager.getAcceptedIssuers(); + } +}