All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.dasein.cloud.aws.network.Route53 Maven / Gradle / Ivy

There is a newer version: 2015.10.9
Show newest version
/**
 * 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




© 2015 - 2024 Weber Informatics LLC | Privacy Policy