org.dasein.cloud.aws.network.Route53 Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of dasein-cloud-aws Show documentation
Show all versions of dasein-cloud-aws Show documentation
Implementation of the Dasein Cloud API for AWS.
/**
* Copyright (C) 2009-2015 Dell, Inc.
* See annotations for authorship information
*
* ====================================================================
* Licensed 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 org.dasein.cloud.aws.network;
import org.dasein.cloud.CloudException;
import org.dasein.cloud.InternalException;
import org.dasein.cloud.ProviderContext;
import org.dasein.cloud.ResourceStatus;
import org.dasein.cloud.aws.AWSCloud;
import org.dasein.cloud.aws.compute.EC2Exception;
import org.dasein.cloud.identity.ServiceAction;
import org.dasein.cloud.network.DNSRecord;
import org.dasein.cloud.network.DNSRecordType;
import org.dasein.cloud.network.DNSSupport;
import org.dasein.cloud.network.DNSZone;
import org.dasein.cloud.util.APITrace;
import org.dasein.util.Jiterator;
import org.dasein.util.JiteratorPopulator;
import org.dasein.util.PopulatorThread;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import javax.annotation.Nonnegative;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.Locale;
import java.util.TreeSet;
import java.util.UUID;
public class Route53 implements DNSSupport {
private AWSCloud provider;
Route53(AWSCloud provider) { this.provider = provider; }
private @Nonnull String generateCallerReference() {
return UUID.randomUUID().toString();
}
@Override
public @Nonnull DNSRecord addDnsRecord(@Nonnull String providerDnsZoneId, @Nonnull DNSRecordType recordType, @Nonnull String name, @Nonnegative int ttl, @Nonnull String... values) throws CloudException, InternalException {
APITrace.begin(provider, "DNS.addDnsRecord");
try {
DNSZone zone = getDnsZone(providerDnsZoneId);
if( zone == null ) {
throw new CloudException("Invalid DNS zone: " + providerDnsZoneId);
}
Route53Method method;
if( !name.endsWith(".") && (recordType.equals(DNSRecordType.A) || recordType.equals(DNSRecordType.AAAA)) ) {
name = name + zone.getDomainName();
}
for( DNSRecord record : listDnsRecords(providerDnsZoneId, recordType, null) ) {
if( record != null && record.getType().equals(recordType) && record.getName().equals(name) ) {
deleteDnsRecords(record);
}
}
method = new Route53Method(Route53Method.CHANGE_RESOURCE_RECORD_SETS, provider, getResourceUrl(providerDnsZoneId));
StringBuilder xml = new StringBuilder();
xml.append("\r\n");
xml.append("");
xml.append("");
xml.append("");
xml.append("");
xml.append("CREATE ");
xml.append("");
xml.append("");
xml.append(name);
xml.append(" ");
xml.append("");
xml.append(recordType.toString());
xml.append(" ");
xml.append("");
xml.append(String.valueOf(ttl));
xml.append(" ");
xml.append("");
if( values.length > 0 ) {
for( String value : values ) {
xml.append("");
xml.append("");
xml.append(AWSCloud.escapeXml(value));
xml.append(" ");
xml.append(" ");
}
}
xml.append(" ");
xml.append(" ");
xml.append(" ");
xml.append(" ");
xml.append(" ");
xml.append(" ");
try {
method.invoke(xml.toString());
}
catch( EC2Exception e ) {
throw new CloudException(e);
}
for( DNSRecord record : listDnsRecords(providerDnsZoneId, recordType, null) ) {
if( record != null && record.getType().equals(recordType) && record.getName().equals(name) ) {
return record;
}
}
throw new CloudException("Unable to identified newly added record");
}
finally {
APITrace.end();
}
}
@Override
public @Nonnull String createDnsZone(@Nonnull String domainName, @Nonnull String name, @Nonnull String description) throws CloudException, InternalException {
APITrace.begin(provider, "DNS.createDnsZone");
try {
ProviderContext ctx = provider.getContext();
if( ctx == null ) {
throw new CloudException("No context was configured for this request");
}
Route53Method method;
NodeList blocks;
Document doc;
method = new Route53Method(Route53Method.CREATE_HOSTED_ZONE, provider, getHostedZoneUrl(null));
StringBuilder xml = new StringBuilder();
xml.append("\r\n");
xml.append("");
xml.append("");
xml.append(domainName);
xml.append(" ");
xml.append("");
xml.append(generateCallerReference());
xml.append(" ");
xml.append("");
xml.append(AWSCloud.escapeXml(description));
xml.append(" ");
xml.append(" ");
try {
doc = method.invoke(xml.toString());
}
catch( EC2Exception e ) {
throw new CloudException(e);
}
ArrayList ns = new ArrayList();
blocks = doc.getElementsByTagName("NameServer");
for( int i=0; i zones = new TreeSet();
for( DNSRecord record : dnsRecords ) {
zones.add(record.getProviderZoneId());
}
for( String zoneId : zones ) {
Route53Method method = new Route53Method(Route53Method.CHANGE_RESOURCE_RECORD_SETS, provider, getResourceUrl(zoneId));
StringBuilder xml = new StringBuilder();
xml.append("\r\n");
xml.append("");
xml.append("");
xml.append("");
for( DNSRecord record : dnsRecords ) {
if( record.getProviderZoneId().equals(zoneId) ) {
xml.append("");
xml.append("DELETE ");
xml.append("");
xml.append("");
xml.append(record.getName());
xml.append(" ");
xml.append("");
xml.append(record.getType().toString());
xml.append(" ");
xml.append("");
xml.append(String.valueOf(record.getTtl()));
xml.append(" ");
xml.append("");
String[] values = record.getValues();
if( values != null && values.length > 0 ) {
for( String value : values ) {
xml.append("");
xml.append("");
xml.append(AWSCloud.escapeXml(value));
xml.append(" ");
xml.append(" ");
}
}
xml.append(" ");
xml.append(" ");
xml.append(" ");
}
}
xml.append(" ");
xml.append(" ");
xml.append(" ");
try {
method.invoke(xml.toString());
}
catch( EC2Exception e ) {
throw new CloudException(e);
}
}
}
finally {
APITrace.end();
}
}
@Override
public void deleteDnsZone(@Nonnull String providerDnsZoneId) throws CloudException, InternalException {
APITrace.begin(provider, "DNS.deleteDnsZone");
try {
Route53Method method;
method = new Route53Method(Route53Method.DELETE_HOSTED_ZONE, provider, getHostedZoneUrl(providerDnsZoneId));
try {
method.invoke();
}
catch( EC2Exception e ) {
throw new CloudException(e);
}
}
finally {
APITrace.end();
}
}
@Override
public @Nullable DNSZone getDnsZone(@Nonnull String providerDnsZoneId) throws CloudException, InternalException {
APITrace.begin(provider, "DNS.getDnsZone");
try {
ProviderContext ctx = provider.getContext();
if( ctx == null ) {
throw new CloudException("No context was configured for this request");
}
Route53Method method;
NodeList blocks;
Document doc;
method = new Route53Method(Route53Method.GET_HOSTED_ZONE, provider, getHostedZoneUrl(providerDnsZoneId));
try {
doc = method.invoke();
}
catch( EC2Exception e ) {
String code = e.getCode();
if( code != null && ( code.equals("AccessDenied") || code.equals("InvalidInput") ) ) {
for( DNSZone zone : listDnsZones() ) {
if( zone.getProviderDnsZoneId().equals(providerDnsZoneId) ) {
return zone;
}
}
return null;
}
else if( code != null && code.equals("NoSuchHostedZone") ) {
return null;
}
throw new CloudException(e);
}
ArrayList ns = new ArrayList();
blocks = doc.getElementsByTagName("NameServer");
for( int i=0; i listDnsRecords(@Nonnull String providerDnsZoneId, @Nullable DNSRecordType forType, @Nullable String name) throws CloudException, InternalException {
final ProviderContext ctx = provider.getContext();
if( ctx == null ) {
throw new CloudException("No context was configured for this request");
}
PopulatorThread populator;
final String zoneId = providerDnsZoneId;
final DNSRecordType type = forType;
final String nom = name;
provider.hold();
populator = new PopulatorThread(new JiteratorPopulator() {
public void populate(@Nonnull Jiterator iterator) throws CloudException, InternalException {
try {
populateRecords(iterator, zoneId, type, nom);
}
finally {
provider.release();
}
}
});
populator.populate();
return populator.getResult();
}
private void populateRecords(@Nonnull Jiterator iterator, @Nonnull String providerDnsZoneId, @Nullable DNSRecordType forType, @Nullable String name) throws CloudException, InternalException {
APITrace.begin(provider, "DNS.listDnsRecords");
try {
DNSZone zone = getDnsZone(providerDnsZoneId);
if( zone == null ) {
return;
}
String url = getResourceUrl(providerDnsZoneId);
Route53Method method;
NodeList blocks;
Document doc;
if( name == null ) {
name = zone.getDomainName();
}
if( forType == null ) {
url += "?name=" + AWSCloud.encode(name, false);
}
else {
url += "?type=" + AWSCloud.encode(forType.toString(), false) + "&name=" + AWSCloud.encode(name, false);
}
method = new Route53Method(Route53Method.LIST_RESOURCE_RECORD_SETS, provider, url);
try {
doc = method.invoke();
}
catch( EC2Exception e ) {
throw new CloudException(e);
}
blocks = doc.getElementsByTagName("ResourceRecordSet");
for( int i=0; i listDnsZoneStatus() throws CloudException, InternalException {
final ProviderContext ctx = provider.getContext();
if( ctx == null ) {
throw new CloudException("No context was configured for this request");
}
PopulatorThread populator;
provider.hold();
populator = new PopulatorThread(new JiteratorPopulator() {
public void populate(@Nonnull Jiterator iterator) throws CloudException, InternalException {
try {
populateZoneStatus(iterator, null);
}
finally {
provider.release();
}
}
});
populator.populate();
return populator.getResult();
}
@Override
public @Nonnull Iterable listDnsZones() throws CloudException, InternalException {
final ProviderContext ctx = provider.getContext();
if( ctx == null ) {
throw new CloudException("No context was configured for this request");
}
PopulatorThread populator;
provider.hold();
populator = new PopulatorThread(new JiteratorPopulator() {
public void populate(@Nonnull Jiterator iterator) throws CloudException, InternalException {
populateZones(ctx, iterator, null);
provider.release();
}
});
populator.populate();
return populator.getResult();
}
@Override
public @Nonnull String[] mapServiceAction(@Nonnull ServiceAction action) {
if( action.equals(DNSSupport.ANY) ) {
return new String[] { Route53Method.R53_PREFIX + "*" };
}
else if( action.equals(DNSSupport.ADD_RECORD) ) {
return new String[] { Route53Method.R53_PREFIX + Route53Method.CHANGE_RESOURCE_RECORD_SETS };
}
else if( action.equals(DNSSupport.CREATE_ZONE) ) {
return new String[] { Route53Method.R53_PREFIX + Route53Method.CREATE_HOSTED_ZONE };
}
else if( action.equals(DNSSupport.GET_ZONE) ) {
return new String[] { Route53Method.R53_PREFIX + Route53Method.GET_HOSTED_ZONE};
}
else if( action.equals(DNSSupport.LIST_ZONE) ) {
return new String[] { Route53Method.R53_PREFIX + Route53Method.LIST_HOSTED_ZONES };
}
else if( action.equals(DNSSupport.LIST_RECORD) ) {
return new String[] { Route53Method.R53_PREFIX + Route53Method.LIST_RESOURCE_RECORD_SETS };
}
else if( action.equals(DNSSupport.REMOVE_RECORD) ) {
return new String[] { Route53Method.R53_PREFIX + Route53Method.CHANGE_RESOURCE_RECORD_SETS };
}
else if( action.equals(DNSSupport.REMOVE_ZONE) ) {
return new String[] { Route53Method.R53_PREFIX + Route53Method.DELETE_HOSTED_ZONE };
}
return new String[0];
}
private void populateZoneStatus(@Nonnull Jiterator iterator, @Nullable String marker) throws CloudException, InternalException {
APITrace.begin(provider, "DNS.listDnsZoneStatus");
try {
String url = getHostedZoneUrl(null);
Route53Method method;
NodeList blocks;
Document doc;
if( marker != null ) {
url = url + "?marker=" + marker;
}
method = new Route53Method(Route53Method.LIST_HOSTED_ZONES, provider, url);
try {
doc = method.invoke();
}
catch( EC2Exception e ) {
throw new CloudException(e);
}
blocks = doc.getElementsByTagName("HostedZone");
for( int i=0; i iterator, @Nullable String marker) throws CloudException, InternalException {
APITrace.begin(provider, "DNS.listDnsZones");
try {
String url = getHostedZoneUrl(null);
Route53Method method;
NodeList blocks;
Document doc;
if( marker != null ) {
url = url + "?marker=" + marker;
}
method = new Route53Method(Route53Method.LIST_HOSTED_ZONES, provider, url);
try {
doc = method.invoke();
}
catch( EC2Exception e ) {
throw new CloudException(e);
}
blocks = doc.getElementsByTagName("HostedZone");
for( int i=0; i data = new ArrayList();
NodeList configs = attr.getChildNodes();
for( int j=0; j