com.vmware.vchs.publicapi.samples.GatewayRuleSample.java Source code

Java tutorial

Introduction

Here is the source code for com.vmware.vchs.publicapi.samples.GatewayRuleSample.java

Source

/*
 * Copyright (c) 2013 VMware, Inc. All Rights Reserved.
 *
 * 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 com.vmware.vchs.publicapi.samples;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.List;
import java.util.concurrent.TimeUnit;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;

import org.apache.commons.cli.CommandLine;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;

import com.vmware.ares.pub.api.ComputeType;
import com.vmware.ares.pub.api.LinkType;
import com.vmware.ares.pub.api.ServiceListType;
import com.vmware.ares.pub.api.ServiceType;
import com.vmware.ares.pub.api.VCloudSessionType;
import com.vmware.ares.pub.api.VdcLinkType;
import com.vmware.ares.pub.api.VdcReferenceType;
import com.vmware.vcloud.api.rest.schema.FirewallRuleProtocols;
import com.vmware.vcloud.api.rest.schema.FirewallRuleType;
import com.vmware.vcloud.api.rest.schema.FirewallServiceType;
import com.vmware.vcloud.api.rest.schema.GatewayConfigurationType;
import com.vmware.vcloud.api.rest.schema.GatewayFeaturesType;
import com.vmware.vcloud.api.rest.schema.GatewayInterfaceType;
import com.vmware.vcloud.api.rest.schema.GatewayInterfacesType;
import com.vmware.vcloud.api.rest.schema.GatewayNatRuleType;
import com.vmware.vcloud.api.rest.schema.GatewayType;
import com.vmware.vcloud.api.rest.schema.IpRangeType;
import com.vmware.vcloud.api.rest.schema.IpRangesType;
import com.vmware.vcloud.api.rest.schema.NatRuleType;
import com.vmware.vcloud.api.rest.schema.NatServiceType;
import com.vmware.vcloud.api.rest.schema.NetworkServiceType;
import com.vmware.vcloud.api.rest.schema.ObjectFactory;
import com.vmware.vcloud.api.rest.schema.QueryResultEdgeGatewayRecordType;
import com.vmware.vcloud.api.rest.schema.QueryResultRecordType;
import com.vmware.vcloud.api.rest.schema.QueryResultRecordsType;
import com.vmware.vcloud.api.rest.schema.ReferenceType;
import com.vmware.vcloud.api.rest.schema.TaskType;
import com.vmware.vcloud.api.rest.schema.VdcType;

/**
 * GatewayRuleSample
 * 
 * This sample will add a NAT rule and a Firewall Rule to the EdgeGateway of the VDC where this
 * vApp is deployed.
 * 
 * The command line option --vdcname is used to specify the VDC where the gateway resides.
 * 
 * The command line option --internalip is the IP address assigned to an existing vApp
 * VM instance.
 * 
 * The command line option --externalip is the external IP address of the EdgeGateway of the VDC 
 * where the vApp resides.
 * 
 * The command line option --edgegateway is the name of the gateway that the vApp connects to in
 * the VDC where the vApp resides.
 * 
 * Steps:
 *   1) Log in to vCHS
 *   2) Get the list of the compute services
 *   3) Find the VDC within the compute services
 *   4) Get the VDC's session link from vCHS
 *   5) Get a vCloud session for the VDC
 *   6) Get a VCD instance from the vCloud session Href
 *   7) Get the VDC EdgeGateway Href
 *   8) Add the gateway rules to the VDC
 *   
 * Parameters:
 * url              [required] : url of the vCHS web service.
 * username         [required] : username for the vCHS authentication.
 * password         [required] : password for the  vCHS authentication.
 * vchsversion      [required] : version of vCHS API.
 * vcloudversion    [required] : version of vCloud API.
 * vdcname          [required] : name of the VDC.
 * internalip       [required] : the internal IP address of the deployed vApp
 * externalip       [required] : the external public IP assigned to the vApp gateway
 * edgegateway      [required] : the Org gateway from which the vApp network is connected to
 * 
 * Argument Line:
 * 
 * Creates a vApp from a vApp template, deploys it and powers it on, and displays its internal
 * IP address.
 * 
 * --url [vchs webservice url] --username [vchs username] --password [vchs password]
 * --vchsversion [vchs version] --vappname [vapp name] --vdcname [vdc name]
 * --vcloudversion [vcloud version] --internalip [vApp assigned ip] 
 * --externalip [vApp gateway] --edgegateway [vApp gateway]
 */
public class GatewayRuleSample {
    private Vchs vchs = null;
    private Vcd vcd = null;
    private GatewayRuleCommandLineOptions options = null;

    /**
     * @param args
     *            any arguments passed by the command line, if none, defaults are used where
     *            applicable.
     */
    public static void main(String[] args) {
        // Creating an instance of this sample
        GatewayRuleSample sample = new GatewayRuleSample();
        sample.run(args);
    }

    /**
     * Called by the static main method on the instance of this class with the
     * command line args array.
     * 
     * @param args the arguments passed on the command line
     */
    private void run(String[] args) {
        // Create instance of CommandLineOptions for use in this sample
        options = new GatewayRuleCommandLineOptions();
        options.parseOptions(args);

        System.out.print("\nConnecting to vCHS...");

        // Instance of Vchs for this sample
        vchs = new Vchs();

        // Log in to vCHS, passing the command line arguments
        if (vchs.login(options)) {
            System.out.println("Success\n");

            // Retrieve a vcloudSession for the VDC specified on the command line.
            // options.vdcName contains the name of a VDC corresponding to the retrieved vCloud 
            // session
            String vcdSessionHref = vchs.getVCloudDSessionHref(options);

            // Retrieve the vCloud API EndPoint for the VDC.
            vcd = HttpUtils.getVCDEndPoint(vchs, options, vcdSessionHref);

            // Retrieve the Link to Edge Gateways i.e, the list of Edge Gateway that is to be
            // used to add NAT and firewall Rules
            System.out.print("Retrieving the href for the EdgeGateway...");
            String edgeGatewaysHref = getEdgeGatewaysHref(vcd.vdcHref);
            System.out.println("Success\n");

            // Find the details regarding the network on which nat rules are to be applied, the link
            // to action to be performed to update gateways and then add nat and firewall rules to
            // gateway
            System.out.print("Adding NAT and Firewall rules...");
            addRules(edgeGatewaysHref);
        }
    }

    /**
     * This method is to get Href for EdgeGateways, the list of EdgeGateway
     * 
     * @param vdcHref
     *            the href to the VDC
     * 
     * @return the href to the EdgeGateways for VDC
     */
    private String getEdgeGatewaysHref(String vdcHref) {
        HttpResponse response = HttpUtils.httpInvoke(vcd.get(vdcHref, options));
        VdcType vdc = HttpUtils.unmarshal(response.getEntity(), VdcType.class);
        List<com.vmware.vcloud.api.rest.schema.LinkType> linklist = vdc.getLink();

        String edgegatewaysHref = null;

        // Iterating through the links associated with VDC and getting one for EdgeGateways
        for (com.vmware.vcloud.api.rest.schema.LinkType link : linklist) {
            if (link.getRel() != null && link.getRel().equals("edgeGateways")) {
                edgegatewaysHref = link.getHref();
                break;
            }
        }

        if (null == edgegatewaysHref) {
            throw new RuntimeException("Could not find edge gateways for VDC Href: " + vdcHref);
        }

        return edgegatewaysHref;
    }

    /**
     * This method will retrieve information to configure gateways and use the details to add Nat
     * and Firewall Rules. It will use the gateway specified by name.
     * 
     * @param edgeGatewaysHref
     *            the Href to the edgegateways
     */
    private void addRules(String edgeGatewaysHref) {
        // invoking API for EdgeGateways
        HttpResponse response = HttpUtils.httpInvoke(vcd.get(edgeGatewaysHref, options));
        QueryResultRecordsType queryRecords = HttpUtils.unmarshal(response.getEntity(),
                QueryResultRecordsType.class);
        List<JAXBElement<? extends QueryResultRecordType>> Records = queryRecords.getRecord();
        String gatewayHref = null;

        // Iterating through the EdgeGateway to find href for the gateway to be used to add rules
        for (JAXBElement<? extends QueryResultRecordType> qResult : Records) {
            QueryResultEdgeGatewayRecordType rslt = new QueryResultEdgeGatewayRecordType();
            rslt = (QueryResultEdgeGatewayRecordType) qResult.getValue();

            if (rslt.getName().equalsIgnoreCase(options.edgeGateway)) {
                gatewayHref = rslt.getHref();
                // Found, break from loop
                break;
            }
        }

        // Make sure returned gatewayHref is not null
        if (null != gatewayHref) {
            // Before configuring the gateway rules need to find the url to perform the service
            // configuration action
            String serviceConfHref = getServiceConfHref(gatewayHref);

            // Retrieving the Href for the network,on which nat rules to be applied on
            String networkHref = getNetworkHref(gatewayHref);
            if (networkHref != null) {
                // Performing the main action of sample that is adding nat and firewall rules
                configureRules(networkHref, serviceConfHref);
            } else {
                throw new RuntimeException("\nFailed to find network to be used to apply rules.");
            }
        } else {
            throw new RuntimeException("Could not find gateway Href for edge gateways: " + edgeGatewaysHref);
        }
    }

    /**
     * This method is to get Href for the Gateway Service Configuration action i.e, Link to update
     * gateway
     * 
     * @param gatewayHref
     *            the href to the gateway to be used
     * @return the href of the service configuration action for the gateway.
     */
    private String getServiceConfHref(String gatewayHref) {
        HttpResponse response = HttpUtils.httpInvoke(vcd.get(gatewayHref, options));
        GatewayType gateway = HttpUtils.unmarshal(response.getEntity(), GatewayType.class);
        List<com.vmware.vcloud.api.rest.schema.LinkType> links = gateway.getLink();

        String serviceConfHref = null;

        // Iterating through the Links associated with Gateway's action to retrieve one that is to
        // perform edgeGatewayServiceConfiguration
        for (com.vmware.vcloud.api.rest.schema.LinkType link : links) {
            if (link.getType() != null && link.getType().contains("edgeGatewayServiceConfiguration")) {
                serviceConfHref = link.getHref();
                break;
            }
        }

        if (null == serviceConfHref) {
            throw new RuntimeException("Could not find service configuration for gateway Href: " + gatewayHref);
        }

        return serviceConfHref;
    }

    /**
     * This method is to get Href for network on which the Nat rules need to be Applied.
     * 
     * @param gatewayHref
     *            the href to the gateway to be used
     * @return href the interface on which the rules need to be applied
     */
    private String getNetworkHref(String gatewayHref) {
        // Represents the Gateway
        HttpResponse response = HttpUtils.httpInvoke(vcd.get(gatewayHref, options));
        GatewayType gateway = HttpUtils.unmarshal(response.getEntity(), GatewayType.class);

        // Retrieving the configuration for the Gateway
        GatewayConfigurationType gatewayConfig = gateway.getConfiguration();

        // Retrieving the Gateway Interfaces
        GatewayInterfacesType gatewayInterfaces = gatewayConfig.getGatewayInterfaces();
        List<GatewayInterfaceType> gatewayInterfaceList = gatewayInterfaces.getGatewayInterface();
        String networkHref = null;

        // Iterating through Gateway Interface list to select a Gateway Interface to which the
        // externalIp provided belongs
        for (GatewayInterfaceType gatewayInterface : gatewayInterfaceList) {
            if (gatewayInterface.getInterfaceType().equals("uplink")) {
                for (int i = 0; i < gatewayInterface.getSubnetParticipation().size(); i++) {
                    IpRangesType ipRanges = gatewayInterface.getSubnetParticipation().get(i).getIpRanges();
                    List<IpRangeType> ipRange = ipRanges.getIpRange();

                    for (IpRangeType ipR : ipRange) {
                        long startAddress = 0l;
                        long endAddresss = 0l;
                        long ipToTest = 0l;

                        try {
                            startAddress = ipToLong(InetAddress.getByName(ipR.getStartAddress()));
                            endAddresss = ipToLong(InetAddress.getByName(ipR.getEndAddress()));
                            ipToTest = ipToLong(InetAddress.getByName(options.externalIp));
                        } catch (UnknownHostException e) {
                            e.printStackTrace();
                        }

                        if (ipToTest >= startAddress && ipToTest <= endAddresss) {
                            // The Network that is to be used to apply NAT Rules
                            networkHref = gatewayInterface.getNetwork().getHref();
                            break;
                        }
                    }
                }
            }
        }

        if (null == networkHref) {
            throw new RuntimeException("Could not find network for gateway Href: " + gatewayHref);
        }

        return networkHref;
    }

    /**
     * This method converts ip to long which is later used to find the ip within iprange
     * 
     * @param ip
     *            ip address
     * @return result
     */
    private static final long ipToLong(InetAddress ip) {
        byte[] octets = ip.getAddress();
        long result = 0;
        for (byte octet : octets) {
            result <<= 8;
            result |= octet & 0xff;
        }

        return result;
    }

    /**
     * This method is to configure NAT and Firewall Rules to the EdgeGateway
     * 
     * @param networkHref
     *            the href to the network on which nat rules to be applied
     * @param serviceConfHref
     *            the href to the service configure action of gateway
     * @return
     */
    private void configureRules(String networkHref, String serviceConfHref) {
        // NAT Rules
        NatServiceType natService = new NatServiceType();

        // To Enable the service using this flag
        natService.setIsEnabled(Boolean.TRUE);

        // Configuring Destination nat
        NatRuleType dnatRule = new NatRuleType();

        // Setting Rule type Destination Nat DNAT
        dnatRule.setRuleType("DNAT");
        dnatRule.setIsEnabled(Boolean.TRUE);
        GatewayNatRuleType dgatewayNat = new GatewayNatRuleType();
        ReferenceType refd = new ReferenceType();
        refd.setHref(networkHref);

        // Network on which nat rules to be applied
        dgatewayNat.setInterface(refd);

        // Setting Original IP
        dgatewayNat.setOriginalIp(options.externalIp);
        dgatewayNat.setOriginalPort("any");

        dgatewayNat.setTranslatedIp(options.internalIp);

        // To allow all ports and all protocols
        // dgatewayNat.setTranslatedPort("any");
        // dgatewayNat.setProtocol("Any");

        // To allow only https use Port 443 and TCP protocol
        dgatewayNat.setTranslatedPort("any");
        dgatewayNat.setProtocol("TCP");

        // To allow only ssh use Port 22 and TCP protocol
        // dgatewayNat.setTranslatedPort("22");
        // dgatewayNat.setProtocol("TCP");
        // Setting Destination IP
        dnatRule.setGatewayNatRule(dgatewayNat);
        natService.getNatRule().add(dnatRule);

        // Configuring Source nat
        NatRuleType snatRule = new NatRuleType();

        // Setting Rule type Source Nat SNAT
        snatRule.setRuleType("SNAT");
        snatRule.setIsEnabled(Boolean.TRUE);
        GatewayNatRuleType sgatewayNat = new GatewayNatRuleType();
        //ReferenceType refd = new ReferenceType();
        //refd.setHref(networkHref);

        // Network on which nat rules to be applied
        sgatewayNat.setInterface(refd);

        // Setting Original IP
        sgatewayNat.setOriginalIp(options.internalIp);
        //sgatewayNat.setOriginalPort("any");

        sgatewayNat.setTranslatedIp(options.externalIp);

        // Setting Source IP
        snatRule.setGatewayNatRule(sgatewayNat);
        natService.getNatRule().add(snatRule);

        // Firewall Rules
        FirewallServiceType firewallService = new FirewallServiceType();

        // Enable or disable the service using this flag
        firewallService.setIsEnabled(Boolean.TRUE);

        // Default action of the firewall set to drop
        firewallService.setDefaultAction("drop");

        // Flag to enable logging for default action
        firewallService.setLogDefaultAction(Boolean.FALSE);

        // Firewall Rule settings
        FirewallRuleType firewallInRule = new FirewallRuleType();
        firewallInRule.setIsEnabled(Boolean.TRUE);
        firewallInRule.setMatchOnTranslate(Boolean.FALSE);
        firewallInRule.setDescription("Allow incoming https access");
        firewallInRule.setPolicy("allow");
        FirewallRuleProtocols firewallProtocol = new FirewallRuleProtocols();
        firewallProtocol.setAny(Boolean.TRUE);
        firewallInRule.setProtocols(firewallProtocol);
        firewallInRule.setDestinationPortRange("any");
        firewallInRule.setDestinationIp(options.externalIp);
        firewallInRule.setSourcePortRange("Any");
        firewallInRule.setSourceIp("external");
        firewallInRule.setEnableLogging(Boolean.FALSE);
        firewallService.getFirewallRule().add(firewallInRule);

        // To create the HttpPost request Body
        ObjectFactory objectFactory = new ObjectFactory();
        GatewayFeaturesType gatewayFeatures = new GatewayFeaturesType();
        JAXBElement<NetworkServiceType> serviceType = objectFactory.createNetworkService(natService);
        JAXBElement<NetworkServiceType> firewallserviceType = objectFactory.createNetworkService(firewallService);
        gatewayFeatures.getNetworkService().add(serviceType);
        gatewayFeatures.getNetworkService().add(firewallserviceType);
        JAXBContext jaxbContexts = null;

        try {
            jaxbContexts = JAXBContext.newInstance(GatewayFeaturesType.class);
        } catch (JAXBException ex) {
            ex.printStackTrace();
        }

        OutputStream os = null;
        JAXBElement<GatewayFeaturesType> gateway_Features = objectFactory
                .createEdgeGatewayServiceConfiguration(gatewayFeatures);

        try {
            javax.xml.bind.Marshaller marshaller = jaxbContexts.createMarshaller();
            marshaller.setProperty(javax.xml.bind.Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
            os = new ByteArrayOutputStream();

            // Marshal the JAXB class to XML
            marshaller.marshal(gateway_Features, os);
        } catch (JAXBException e) {
            e.printStackTrace();
        }

        HttpPost httpPost = vcd.post(serviceConfHref, options);
        ContentType contentType = ContentType.create(SampleConstants.CONTENT_TYPE_EDGE_GATEWAY, "ISO-8859-1");
        StringEntity rules = new StringEntity(os.toString(), contentType);
        httpPost.setEntity(rules);
        InputStream is = null;

        // Invoking api to add rules to gateway
        HttpResponse response = HttpUtils.httpInvoke(httpPost);

        // Make sure the response code is 202 ACCEPTED
        if (response.getStatusLine().getStatusCode() == HttpStatus.SC_ACCEPTED) {
            // System.out.println("ResponseCode : " + response.getStatusLine().getStatusCode());
            System.out.println("\nRequest To update Gateway initiated sucessfully");
            System.out.print("\nUpdating EdgeGateways to add NAT and Firewall Rules...");
            taskStatus(response);
        }
    }

    /**
     * This method is to get the status of Configure NAT and Fire-wall Rules
     * 
     * @param response
     *            the response of gateway configure action
     */
    private void taskStatus(HttpResponse response) {
        // Represents the task configuring NAT and Firewall Rules
        TaskType task = HttpUtils.unmarshal(response.getEntity(), TaskType.class);
        String taskHref = task.getHref();
        HttpGet httpGet = vcd.get(taskHref, options);
        HttpResponse resp = null;

        // Check task status until it shows either success or error.
        while (!(task.getStatus()).equals("success") && !(task.getStatus()).equals("error")) {
            try {
                // Wait 10 seconds before requesting the status again
                TimeUnit.SECONDS.sleep(10);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }

            resp = HttpUtils.httpInvoke(httpGet);
            System.out.print(".");
            task = HttpUtils.unmarshal(resp.getEntity(), TaskType.class);
        }

        if ((task.getStatus()).equals("success")) {
            System.out.println("Success");
        } else {
            throw new RuntimeException(task.getStatus());
        }
    }
}