mirror of https://github.com/apache/cloudstack.git
WIP: XML control of VNMC
Signed-off-by: Chiradeep Vittal <chiradeep@apache.org>
This commit is contained in:
parent
a69e7f9bf6
commit
11b804a894
|
|
@ -0,0 +1,129 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
|
||||
|
||||
<project name="Cloud Stack VNMC network element" default="help" basedir=".">
|
||||
<description>
|
||||
Cloud Stack ant build file
|
||||
</description>
|
||||
|
||||
<dirname property="vnmc.base.dir" file="${ant.file.Cloud Stack VNMC network element}/"/>
|
||||
<!-- This directory must be set -->
|
||||
<property name="top.dir" location="${vnmc.base.dir}/../../.."/>
|
||||
<property name="build.dir" location="${top.dir}/build"/>
|
||||
|
||||
<echo message="build.dir=${build.dir}; top.dir=${top.dir}; vnmc.base.dir=${vnmc.base.dir}"/>
|
||||
|
||||
<!-- Import anything that the user wants to set-->
|
||||
<!-- Import properties files and environment variables here -->
|
||||
|
||||
<property environment="env" />
|
||||
|
||||
<condition property="build-cloud.properties.file" value="${build.dir}/override/build-cloud.properties" else="${build.dir}/build-cloud.properties">
|
||||
<available file="${build.dir}/override/build-cloud.properties" />
|
||||
</condition>
|
||||
|
||||
<condition property="cloud.properties.file" value="${build.dir}/override/cloud.properties" else="${build.dir}/cloud.properties">
|
||||
<available file="${build.dir}/override/cloud.properties" />
|
||||
</condition>
|
||||
|
||||
<condition property="override.file" value="${build.dir}/override/replace.properties" else="${build.dir}/replace.properties">
|
||||
<available file="${build.dir}/override/replace.properties" />
|
||||
</condition>
|
||||
|
||||
<echo message="Using build parameters from ${build-cloud.properties.file}" />
|
||||
<property file="${build-cloud.properties.file}" />
|
||||
|
||||
<echo message="Using company info from ${cloud.properties.file}" />
|
||||
<property file="${cloud.properties.file}" />
|
||||
|
||||
<echo message="Using override file from ${override.file}" />
|
||||
<property file="${override.file}" />
|
||||
|
||||
<property file="${build.dir}/build.number" />
|
||||
|
||||
<!-- In case these didn't get defined in the build-cloud.properties -->
|
||||
<property name="branding.name" value="default" />
|
||||
<property name="deprecation" value="off" />
|
||||
<property name="target.compat.version" value="1.6" />
|
||||
<property name="source.compat.version" value="1.6" />
|
||||
<property name="debug" value="true" />
|
||||
<property name="debuglevel" value="lines,source"/>
|
||||
|
||||
<echo message="target.dir=${target.dir}; top.dir=${top.dir}"/>
|
||||
<!-- directories for build and distribution -->
|
||||
<property name="target.dir" location="${top.dir}/target" />
|
||||
<property name="classes.dir" location="${target.dir}/classes" />
|
||||
<property name="jar.dir" location="${target.dir}/jar" />
|
||||
<property name="dep.cache.dir" location="${target.dir}/dep-cache" />
|
||||
<property name="build.log" location="${target.dir}/ant_verbose.txt" />
|
||||
|
||||
<property name="deps.dir" location="${top.dir}/deps" />
|
||||
|
||||
<property name="cloud-plugin-vnmc.jar" value="cloud-plugin-vnmc.jar" />
|
||||
|
||||
<import file="${build.dir}/build-common.xml"/>
|
||||
|
||||
<echo message="target.dir=${target.dir}; top.dir=${top.dir}"/>
|
||||
|
||||
<!-- This section needs to be replaced by some kind of dependency library-->
|
||||
<path id="deps.classpath">
|
||||
<!--filelist files="${deps.classpath}" /-->
|
||||
<fileset dir="${deps.dir}" erroronmissingdir="false">
|
||||
<include name="*.jar" />
|
||||
</fileset>
|
||||
</path>
|
||||
|
||||
<path id="cloudstack.classpath">
|
||||
<fileset dir="${jar.dir}">
|
||||
<include name="*.jar"/>
|
||||
</fileset>
|
||||
</path>
|
||||
|
||||
<path id="vnmc.classpath">
|
||||
<path refid="deps.classpath"/>
|
||||
<path refid="cloudstack.classpath"/>
|
||||
</path>
|
||||
|
||||
<!-- This section needs to be replaced by some kind of dependency library-->
|
||||
|
||||
<target name="deploy-vnmc" >
|
||||
</target>
|
||||
|
||||
<target name="init" description="Initialize binaries directory">
|
||||
<mkdir dir="${classes.dir}/${cloud-plugin-vnmc.jar}"/>
|
||||
<mkdir dir="${jar.dir}"/>
|
||||
</target>
|
||||
|
||||
<target name="compile-vnmc" depends="init" description="Compile Cisco VNMC">
|
||||
<compile-java jar.name="${cloud-plugin-vnmc.jar}" top.dir="${vnmc.base.dir}" classpath="vnmc.classpath" />
|
||||
</target>
|
||||
|
||||
<target name="clean-vnmc">
|
||||
<delete dir="${classes.dir}/${cloud-plugin-vnmc.jar}"/>
|
||||
</target>
|
||||
|
||||
<target name="build" depends="compile-vnmc"/>
|
||||
<target name="clean" depends="clean-vnmc"/>
|
||||
|
||||
<target name="help" description="help">
|
||||
<echo level="info" message="This is the build file for Cisco VNMC element plugin"/>
|
||||
<echo level="info" message="You can do a build by doing ant build or clean by doing ant clean" />
|
||||
</target>
|
||||
|
||||
</project>
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
<!--
|
||||
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.
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>cloud-plugin-network-cisco-vnmc</artifactId>
|
||||
<name>Apache CloudStack Plugin - Cisco VNMC</name>
|
||||
<parent>
|
||||
<groupId>org.apache.cloudstack</groupId>
|
||||
<artifactId>cloudstack-plugins</artifactId>
|
||||
<version>4.0.0-SNAPSHOT</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<dependencies>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
<configConfMo
|
||||
cookie="%cookie%"
|
||||
inHierarchical="false">
|
||||
<inConfig>
|
||||
<policyEdgeDeviceServiceProfile
|
||||
addrTranslationTimeout="10800"
|
||||
descr="%descr%"
|
||||
dn="%dn%"
|
||||
name="%name%"
|
||||
status="created"
|
||||
vpn=""/>
|
||||
</inConfig>
|
||||
</configConfMo>
|
||||
<!--dn="org-root/org-TestTenant3/org-Tenant3-VDC/edsp-Tenant3-Edge-Device-Profile" -->
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
<configConfMo
|
||||
dn=""
|
||||
cookie="%cookie%"
|
||||
inHierarchical="false">
|
||||
<inConfig>
|
||||
<routeRoutingPolicy
|
||||
descr="%descr%"
|
||||
dn="%routepolicydn%"
|
||||
name="%name%"
|
||||
status="created"/>
|
||||
</inConfig>
|
||||
</configConfMo>
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
<configConfMos
|
||||
cookie="%cookie%"
|
||||
inHierarchical="false">
|
||||
<inConfigs>
|
||||
<pair key="%routedn%" >
|
||||
<routeStaticRoute
|
||||
dn="%routedn%"
|
||||
id="%id%"
|
||||
ipAddress="%destination%"
|
||||
ipSubnet="%netmask%"
|
||||
nextHopGWIp="%nexthop%"
|
||||
nextHopIntf="%nexthopintf%"
|
||||
routeMetric="1"
|
||||
status="created"/>
|
||||
</pair>
|
||||
</inConfigs>
|
||||
</configConfMos>
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
<configConfMo cookie="%cookie%" inHierarchical="false">
|
||||
<inConfig>
|
||||
<orgTenant
|
||||
descr="%descr%"
|
||||
dn="%dn%"
|
||||
name="%name%"
|
||||
status="created"/>
|
||||
</inConfig>
|
||||
</configConfMo>
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
<configConfMo
|
||||
dn=""
|
||||
cookie="%cookie%"
|
||||
inHierarchical="false">
|
||||
<inConfig>
|
||||
<orgDatacenter
|
||||
descr="%descr%"
|
||||
dn="%dn%"
|
||||
name="%name%"
|
||||
status="created"/>
|
||||
</inConfig>
|
||||
</configConfMo>
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
<configResolveChildren
|
||||
cookie="%cookie%"
|
||||
classId="orgTenant"
|
||||
inDn="org-root"
|
||||
inHierarchical="false">
|
||||
<inFilter>
|
||||
</inFilter>
|
||||
</configResolveChildren>
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
<?xml version="1.0" encoding="us-ascii"?>
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
<aaaLogin inName="%username%" inPassword="%password%" />
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
<configResolveChildren cookie="1349183392/5c1d1ceb-9a5d-433b-aab2-0760b90f31f8" commCookie="2/12/0/eab" srcExtSys="10.223.56.5" destExtSys="10.223.56.5" srcSvc="sam_extXMLApi" destSvc="service-reg_dme" response="yes" classId="orgTenant">
|
||||
<outConfigs>
|
||||
<orgTenant descr="Test Tenant 2" dn="org-root/org-TestTenant2" fltAggr="0" level="1" name="TestTenant2"/>
|
||||
<orgTenant descr="First test" dn="org-root/org-TestTenant1" fltAggr="0" level="1" name="TestTenant1"/>
|
||||
</outConfigs>
|
||||
</configResolveChildren>
|
||||
|
||||
|
|
@ -0,0 +1 @@
|
|||
<aaaLogin cookie="testCookie" commCookie="" srcExtSys="0.0.0.0" destExtSys="0.0.0.0" srcSvc="" destSvc="" response="yes" errorCode="539" invocationResult="unidentified-fail" errorDescr="Authentication failed"/>
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
<aaaLogin cookie="testCookie" commCookie="" srcExtSys="0.0.0.0" destExtSys="0.0.0.0" srcSvc="" destSvc="" response="yes" outCookie="1349183392/5c1d1ceb-9a5d-433b-aab2-0760b90f31f8" outRefreshPeriod="600" outPriv="admin,read-only" outDomains="" outChannel="fullssl" outEvtChannel="fullssl" outSessionId="web_36667" outVersion="2.0(3f)"/>
|
||||
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -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<String, Object> 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<String, String> 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<String, String> 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<String, String> 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<String, String> 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<String, String> 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<String, String> 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<String, String> checkResponse(String xmlResponse, String... keys) throws ExecutionException {
|
||||
Document xmlDoc = getDocument(xmlResponse);
|
||||
Map<String, String> result = new HashMap<String, String>();
|
||||
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 = "</" + marker + ">";
|
||||
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("<?xml version=\"1.0\"?> \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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
* <http://www.apache.org/>.
|
||||
*
|
||||
*/
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* EasySSLProtocolSocketFactory can be used to creats SSL {@link Socket}s
|
||||
* that accept self-signed certificates.
|
||||
* </p>
|
||||
* <p>
|
||||
* 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
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* Example of using custom protocol socket factory for a specific host:
|
||||
* <pre>
|
||||
* 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);
|
||||
* </pre>
|
||||
* </p>
|
||||
* <p>
|
||||
* Example of using custom protocol socket factory per default instead of the standard one:
|
||||
* <pre>
|
||||
* 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);
|
||||
* </pre>
|
||||
* </p>
|
||||
*
|
||||
* @author <a href="mailto:oleg -at- ural.ru">Oleg Kalnichevski</a>
|
||||
*
|
||||
* <p>
|
||||
* 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.
|
||||
* </p>
|
||||
*/
|
||||
|
||||
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.
|
||||
* <p>
|
||||
* 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}
|
||||
* </p>
|
||||
*
|
||||
* @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();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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
|
||||
* <http://www.apache.org/>.
|
||||
*
|
||||
*/
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* EasyX509TrustManager unlike default {@link X509TrustManager} accepts
|
||||
* self-signed certificates.
|
||||
* </p>
|
||||
* <p>
|
||||
* 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
|
||||
* </p>
|
||||
*
|
||||
* @author <a href="mailto:adrian.sutton@ephox.com">Adrian Sutton</a>
|
||||
* @author <a href="mailto:oleg@ural.ru">Oleg Kalnichevski</a>
|
||||
*
|
||||
* <p>
|
||||
* 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.
|
||||
* </p>
|
||||
*/
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue