org.opendaylight.neutron.spi.NeutronSubnet.java Source code

Java tutorial

Introduction

Here is the source code for org.opendaylight.neutron.spi.NeutronSubnet.java

Source

/*
 * Copyright (c) 2013, 2015 IBM Corporation and others.  All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
 * and is available at http://www.eclipse.org/legal/epl-v10.html
 */

package org.opendaylight.neutron.spi;

import java.io.Serializable;
import java.math.BigInteger;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import org.apache.commons.net.util.SubnetUtils;
import org.apache.commons.net.util.SubnetUtils.SubnetInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@XmlRootElement
@XmlAccessorType(XmlAccessType.NONE)
public final class NeutronSubnet extends NeutronBaseAttributes<NeutronSubnet> implements Serializable {
    private static final Logger LOGGER = LoggerFactory.getLogger(NeutronCRUDInterfaces.class);

    private static final long serialVersionUID = 1L;
    private static final int IPV4_VERSION = 4;
    private static final int IPV6_VERSION = 6;
    private static final int IPV6_LENGTH = 128;
    private static final int IPV6_LENGTH_BYTES = 8;
    private static final long IPV6_LSB_MASK = 0x000000FF;
    private static final int IPV6_BYTE_OFFSET = 7;

    // See OpenStack Network API v2.0 Reference for description of
    // annotated attributes

    @XmlElement(name = "network_id")
    String networkUUID;

    @XmlElement(defaultValue = "4", name = "ip_version")
    Integer ipVersion;

    @XmlElement(name = "cidr")
    String cidr;

    @XmlElement(name = "gateway_ip")
    String gatewayIp;

    @XmlElement(name = "dns_nameservers")
    List<String> dnsNameservers;

    @XmlElement(name = "allocation_pools")
    List<NeutronSubnetIpAllocationPool> allocationPools;

    @XmlElement(name = "host_routes")
    List<NeutronRoute> hostRoutes;

    @XmlElement(defaultValue = "true", name = "enable_dhcp")
    Boolean enableDHCP;

    @XmlElement(name = "ipv6_address_mode", nillable = true)
    String ipV6AddressMode;

    @XmlElement(name = "ipv6_ra_mode", nillable = true)
    String ipV6RaMode;

    public String getNetworkUUID() {
        return networkUUID;
    }

    public void setNetworkUUID(String networkUUID) {
        this.networkUUID = networkUUID;
    }

    public Integer getIpVersion() {
        return ipVersion;
    }

    public void setIpVersion(Integer ipVersion) {
        this.ipVersion = ipVersion;
    }

    public String getCidr() {
        return cidr;
    }

    public void setCidr(String cidr) {
        this.cidr = cidr;
    }

    public String getGatewayIp() {
        return gatewayIp;
    }

    public void setGatewayIp(String gatewayIp) {
        this.gatewayIp = gatewayIp;
    }

    public List<String> getDnsNameservers() {
        return dnsNameservers;
    }

    public void setDnsNameservers(List<String> dnsNameservers) {
        this.dnsNameservers = dnsNameservers;
    }

    public List<NeutronSubnetIpAllocationPool> getAllocationPools() {
        return allocationPools;
    }

    public void setAllocationPools(List<NeutronSubnetIpAllocationPool> allocationPools) {
        this.allocationPools = allocationPools;
    }

    public List<NeutronRoute> getHostRoutes() {
        return hostRoutes;
    }

    public void setHostRoutes(List<NeutronRoute> hostRoutes) {
        this.hostRoutes = hostRoutes;
    }

    public boolean isEnableDHCP() {
        if (enableDHCP == null) {
            return true;
        }
        return enableDHCP;
    }

    public Boolean getEnableDHCP() {
        return enableDHCP;
    }

    public void setEnableDHCP(Boolean newValue) {
        enableDHCP = newValue;
    }

    public String getIpV6AddressMode() {
        return ipV6AddressMode;
    }

    public void setIpV6AddressMode(String ipV6AddressMode) {
        this.ipV6AddressMode = ipV6AddressMode;
    }

    public String getIpV6RaMode() {
        return ipV6RaMode;
    }

    public void setIpV6RaMode(String ipV6RaMode) {
        this.ipV6RaMode = ipV6RaMode;
    }

    /**
     * This method copies selected fields from the object and returns them
     * as a new object, suitable for marshaling.
     *
     * @param fields
     *            List of attributes to be extracted
     * @return an OpenStackSubnets object with only the selected fields
     *             populated
     */

    public NeutronSubnet extractFields(List<String> fields) {
        NeutronSubnet ans = new NeutronSubnet();
        for (String s : fields) {
            extractField(s, ans);
            if (s.equals("network_id")) {
                ans.setNetworkUUID(this.getNetworkUUID());
            }
            if (s.equals("ip_version")) {
                ans.setIpVersion(this.getIpVersion());
            }
            if (s.equals("cidr")) {
                ans.setCidr(this.getCidr());
            }
            if (s.equals("gateway_ip")) {
                ans.setGatewayIp(this.getGatewayIp());
            }
            if (s.equals("dns_nameservers")) {
                List<String> nsList = new ArrayList<String>();
                nsList.addAll(this.getDnsNameservers());
                ans.setDnsNameservers(nsList);
            }
            if (s.equals("allocation_pools")) {
                List<NeutronSubnetIpAllocationPool> pools = new ArrayList<NeutronSubnetIpAllocationPool>();
                pools.addAll(this.getAllocationPools());
                ans.setAllocationPools(pools);
            }
            if (s.equals("host_routes")) {
                List<NeutronRoute> hostRoutes = new ArrayList<NeutronRoute>();
                hostRoutes.addAll(this.getHostRoutes());
                ans.setHostRoutes(hostRoutes);
            }
            if (s.equals("enable_dhcp")) {
                ans.setEnableDHCP(this.getEnableDHCP());
            }
            if (s.equals("ipv6_address_mode")) {
                ans.setIpV6AddressMode(this.getIpV6AddressMode());
            }
            if (s.equals("ipv6_ra_mode")) {
                ans.setIpV6RaMode(this.getIpV6RaMode());
            }
        }
        return ans;
    }

    /* test to see if the cidr address used to define this subnet
     * is a valid network address (an necessary condition when creating
     * a new subnet)
     */
    public boolean isValidCIDR() {
        // fix for Bug 2290 - need to wrap the existing test as
        // IPv4 because SubnetUtils doesn't support IPv6
        if (ipVersion == IPV4_VERSION) {
            try {
                SubnetUtils util = new SubnetUtils(cidr);
                SubnetInfo info = util.getInfo();
                if (!info.getNetworkAddress().equals(info.getAddress())) {
                    return false;
                }
            } catch (IllegalArgumentException e) {
                LOGGER.warn("Failure in isValidCIDR()", e);
                return false;
            }
            return true;
        }
        if (ipVersion == IPV6_VERSION) {
            // fix for Bug2290 - this is custom code because no classes
            // with ODL-friendly licenses have been found
            // extract address (in front of /) and length (after /)
            String[] parts = cidr.split("/");
            if (parts.length != 2) {
                return false;
            }
            try {
                int length = Integer.parseInt(parts[1]);
                //TODO?: limit check on length
                // convert to byte array
                byte[] addrBytes = ((Inet6Address) InetAddress.getByName(parts[0])).getAddress();
                for (int index = length; index < IPV6_LENGTH; index++) {
                    if (((((int) addrBytes[index / IPV6_LENGTH_BYTES]) & IPV6_LSB_MASK)
                            & (1 << (IPV6_BYTE_OFFSET - (index % IPV6_LENGTH_BYTES)))) != 0) {
                        return (false);
                    }
                }
                return (true);
            } catch (UnknownHostException e) {
                LOGGER.warn("Failure in isValidCIDR()", e);
                return (false);
            }
        }
        return false;
    }

    /* test to see if the gateway IP specified overlaps with specified
     * allocation pools (an error condition when creating a new subnet
     * or assigning a gateway IP)
     */
    public boolean gatewayIp_Pool_overlap() {
        for (NeutronSubnetIpAllocationPool pool : allocationPools) {
            if (ipVersion == IPV4_VERSION && pool.contains(gatewayIp)) {
                return true;
            }
            if (ipVersion == IPV6_VERSION && pool.containsV6(gatewayIp)) {
                return true;
            }
        }
        return false;
    }

    @Override
    public void initDefaults() {
        if (enableDHCP == null) {
            enableDHCP = true;
        }
        if (ipVersion == null) {
            ipVersion = IPV4_VERSION;
        }
        if (dnsNameservers == null) {
            dnsNameservers = new ArrayList<String>();
        }
        if (hostRoutes == null) {
            hostRoutes = new ArrayList<NeutronRoute>();
        }
        if (allocationPools == null) {
            allocationPools = new ArrayList<NeutronSubnetIpAllocationPool>();
            if (ipVersion == IPV4_VERSION) {
                try {
                    SubnetUtils util = new SubnetUtils(cidr);
                    SubnetInfo info = util.getInfo();
                    if (gatewayIp == null || ("").equals(gatewayIp)) {
                        gatewayIp = info.getLowAddress();
                    }
                    if (allocationPools.size() < 1) {
                        NeutronSubnetIpAllocationPool source = new NeutronSubnetIpAllocationPool(
                                info.getLowAddress(), info.getHighAddress());
                        allocationPools = source.splitPool(gatewayIp);
                    }
                } catch (IllegalArgumentException e) {
                    LOGGER.warn("Failure in initDefault()", e);
                    return;
                }
            }
            if (ipVersion == IPV6_VERSION) {
                String[] parts = cidr.split("/");
                if (parts.length != 2) {
                    return;
                }

                int length = Integer.parseInt(parts[1]);
                BigInteger lowAddressBi = NeutronSubnetIpAllocationPool.convertV6(parts[0]);
                String lowAddress = NeutronSubnetIpAllocationPool.bigIntegerToIp(lowAddressBi.add(BigInteger.ONE));
                BigInteger mask = BigInteger.ONE.shiftLeft(length).subtract(BigInteger.ONE);
                String highAddress = NeutronSubnetIpAllocationPool
                        .bigIntegerToIp(lowAddressBi.add(mask).subtract(BigInteger.ONE));
                if (gatewayIp == null || ("").equals(gatewayIp)) {
                    gatewayIp = lowAddress;
                }
                if (allocationPools.size() < 1) {
                    NeutronSubnetIpAllocationPool source = new NeutronSubnetIpAllocationPool(lowAddress,
                            highAddress);
                    allocationPools = source.splitPoolV6(gatewayIp);
                }
            }
        }
    }

    /* this method tests to see if the supplied IPv4 address
     * is valid for this subnet or not
     */
    public boolean isValidIp(String ipAddress) {
        if (ipVersion == IPV4_VERSION) {
            try {
                SubnetUtils util = new SubnetUtils(cidr);
                SubnetInfo info = util.getInfo();
                return info.isInRange(ipAddress);
            } catch (IllegalArgumentException e) {
                LOGGER.warn("Failure in isValidIp()", e);
                return false;
            }
        }

        if (ipVersion == IPV6_VERSION) {
            String[] parts = cidr.split("/");
            try {
                int length = Integer.parseInt(parts[1]);
                byte[] cidrBytes = ((Inet6Address) InetAddress.getByName(parts[0])).getAddress();
                byte[] ipBytes = ((Inet6Address) InetAddress.getByName(ipAddress)).getAddress();
                for (int index = 0; index < length; index++) {
                    if (((((int) cidrBytes[index / IPV6_LENGTH_BYTES]) & IPV6_LSB_MASK) & (1 << (IPV6_BYTE_OFFSET
                            - (index % IPV6_LENGTH_BYTES)))) != ((((int) ipBytes[index / IPV6_LENGTH_BYTES])
                                    & IPV6_LSB_MASK) & (1 << (IPV6_BYTE_OFFSET - (index % IPV6_LENGTH_BYTES))))) {
                        return (false);
                    }
                }
                return (true);
            } catch (UnknownHostException e) {
                LOGGER.warn("Failure in isValidIp()", e);
                return (false);
            }
        }
        return false;
    }

    /* method to get the lowest available address of the subnet.
     * go through all the allocation pools and keep the lowest of their
     * low addresses.
     */
    public String getLowAddr() {
        String ans = null;
        for (NeutronSubnetIpAllocationPool pool : allocationPools) {
            if (ans == null) {
                ans = pool.getPoolStart();
            } else {
                if (ipVersion == IPV4_VERSION && NeutronSubnetIpAllocationPool
                        .convert(pool.getPoolStart()) < NeutronSubnetIpAllocationPool.convert(ans)) {
                    ans = pool.getPoolStart();
                }
                if (ipVersion == IPV6_VERSION && NeutronSubnetIpAllocationPool.convertV6(pool.getPoolStart())
                        .compareTo(NeutronSubnetIpAllocationPool.convertV6(ans)) < 0) {
                    ans = pool.getPoolStart();
                }
            }
        }
        return ans;
    }

    @Override
    public String toString() {
        return "NeutronSubnet [subnetUUID=" + uuid + ", networkUUID=" + networkUUID + ", name=" + name
                + ", ipVersion=" + ipVersion + ", cidr=" + cidr + ", gatewayIp=" + gatewayIp + ", dnsNameservers="
                + dnsNameservers + ", allocationPools=" + allocationPools + ", hostRoutes=" + hostRoutes
                + ", enableDHCP=" + enableDHCP + ", tenantID=" + tenantID + ", ipv6AddressMode=" + ipV6AddressMode
                + ", ipv6RaMode=" + ipV6RaMode + "]";
    }
}