brooklyn.networking.subnet.PortForwarderAsyncImpl.java Source code

Java tutorial

Introduction

Here is the source code for brooklyn.networking.subnet.PortForwarderAsyncImpl.java

Source

/*
 * Copyright 2013-2014 by Cloudsoft Corporation Limited
 *
 * 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 brooklyn.networking.subnet;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import brooklyn.entity.Entity;
import brooklyn.entity.basic.EntityAndAttribute;
import brooklyn.entity.basic.EntityLocal;
import brooklyn.event.AttributeSensor;
import brooklyn.event.SensorEvent;
import brooklyn.event.SensorEventListener;
import brooklyn.location.MachineLocation;
import brooklyn.location.PortRange;
import brooklyn.location.basic.PortRanges;
import brooklyn.networking.AttributeMunger;
import brooklyn.util.net.Cidr;
import brooklyn.util.net.Protocol;

import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.Iterables;
import com.google.common.net.HostAndPort;

public class PortForwarderAsyncImpl implements PortForwarderAsync {

    private static final Logger log = LoggerFactory.getLogger(PortForwarderAsyncImpl.class);

    private final EntityLocal adjunctEntity;
    private final PortForwarder portForwarder;

    public PortForwarderAsyncImpl(EntityLocal adjunctEntity, PortForwarder portForwarder) {
        this.adjunctEntity = adjunctEntity;
        this.portForwarder = portForwarder;
    }

    @Override
    public void openGatewayAsync(EntityAndAttribute<String> whereToAdvertiseHostname) {
        // IP of port-forwarder already exists; can call synchronously
        String gateway = portForwarder.openGateway();
        AttributeMunger.setAttributeIfChanged(whereToAdvertiseHostname, gateway);
    }

    @Override
    public void openStaticNatAsync(Entity serviceToOpen, EntityAndAttribute<String> whereToAdvertiseHostname) {
        // FIXME Do in deferred block; what do we wait for?
        String staticNat = portForwarder.openStaticNat(serviceToOpen);
        whereToAdvertiseHostname.setValue(staticNat);
    }

    @Override
    public void openFirewallPortAsync(EntityAndAttribute<String> publicIp, int port, Protocol protocol,
            Cidr accessingCidr) {
        openFirewallPortRangeAsync(publicIp, PortRanges.fromInteger(port), protocol, accessingCidr);
    }

    @Override
    public void openFirewallPortRangeAsync(final EntityAndAttribute<String> publicIp, final PortRange portRange,
            final Protocol protocol, final Cidr accessingCidr) {
        DeferredExecutor<String> updater = new DeferredExecutor<String>("open-firewall", publicIp,
                Predicates.notNull(), new Runnable() {
                    public void run() {
                        portForwarder.openFirewallPortRange(publicIp.getEntity(), portRange, protocol,
                                accessingCidr);
                    }
                });
        subscribe(publicIp.getEntity(), publicIp.getAttribute(), updater);
        updater.apply(publicIp.getEntity(), publicIp.getValue());
    }

    @Override
    public void openPortForwardingAndAdvertise(final EntityAndAttribute<Integer> privatePort,
            final Optional<Integer> optionalPublicPort, final Protocol protocol, final Cidr accessingCidr,
            final EntityAndAttribute<String> whereToAdvertiseEndpoint) {
        DeferredExecutor<Integer> updater = new DeferredExecutor<Integer>("open-port-forwarding", privatePort,
                Predicates.notNull(), new Runnable() {
                    public void run() {
                        Entity entity = privatePort.getEntity();
                        MachineLocation machine = (MachineLocation) Iterables.getOnlyElement(entity.getLocations(),
                                null);
                        HostAndPort publicEndpoint = portForwarder.openPortForwarding(machine,
                                privatePort.getValue(), optionalPublicPort, protocol, accessingCidr);
                        whereToAdvertiseEndpoint
                                .setValue(publicEndpoint.getHostText() + ":" + publicEndpoint.getPort());
                    }
                });
        subscribe(privatePort.getEntity(), privatePort.getAttribute(), updater);
        updater.apply(privatePort.getEntity(), privatePort.getValue());
    }

    protected <T> void subscribe(Entity entity, AttributeSensor<T> attribute,
            SensorEventListener<? super T> listener) {
        adjunctEntity.subscribe(entity, attribute, listener);
    }

    protected class DeferredExecutor<T> implements SensorEventListener<Object> {
        private final EntityAndAttribute<T> attribute;
        private final Predicate<? super T> readiness;
        private final Runnable task;
        private final String description;

        public DeferredExecutor(String description, EntityAndAttribute<T> attribute, Runnable task) {
            this(description, attribute, Predicates.notNull(), task);
        }

        public DeferredExecutor(String description, EntityAndAttribute<T> attribute, Predicate<? super T> readiness,
                Runnable task) {
            this.description = description;
            this.attribute = attribute;
            this.readiness = readiness;
            this.task = task;
        }

        @Override
        public void onEvent(SensorEvent<Object> event) {
            apply(event.getSource(), event.getValue());
        }

        public void apply(Entity source, Object valueIgnored) {
            T val = (T) attribute.getValue();
            if (!readiness.apply(val)) {
                log.warn("Skipping {} for {} because attribute {} not ready",
                        new Object[] { description, attribute.getEntity(), attribute.getAttribute() });
                return;
            }

            task.run();
        }
    }
}