http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/77dff880/software/webapp/src/main/java/brooklyn/entity/dns/geoscaling/GeoscalingWebClient.java ---------------------------------------------------------------------- diff --git a/software/webapp/src/main/java/brooklyn/entity/dns/geoscaling/GeoscalingWebClient.java b/software/webapp/src/main/java/brooklyn/entity/dns/geoscaling/GeoscalingWebClient.java deleted file mode 100644 index c712b6a..0000000 --- a/software/webapp/src/main/java/brooklyn/entity/dns/geoscaling/GeoscalingWebClient.java +++ /dev/null @@ -1,459 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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.entity.dns.geoscaling; - -import java.io.IOException; -import java.io.OutputStream; -import java.io.PrintWriter; -import java.text.MessageFormat; -import java.util.ArrayList; -import java.util.LinkedList; -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import org.apache.commons.io.FilenameUtils; -import org.apache.http.HttpEntity; -import org.apache.http.HttpResponse; -import org.apache.http.NameValuePair; -import org.apache.http.client.ClientProtocolException; -import org.apache.http.client.HttpClient; -import org.apache.http.client.entity.UrlEncodedFormEntity; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.client.methods.HttpUriRequest; -import org.apache.http.message.BasicNameValuePair; -import org.apache.http.util.EntityUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; -import org.w3c.tidy.Tidy; - -import brooklyn.util.http.HttpTool; -import brooklyn.util.text.Strings; - -/** - * For interacting with the www.geoscaling.com DNS service. - * - * If you get the SSL error "peer not authenticated", then it means the required certificate is - * not in your trust store. For example, see: - * {@linkplain http://stackoverflow.com/questions/373295/digital-certificate-how-to-import-cer-file-in-to-truststore-file-using}. - * The chain of certificates (as of October 2014, found by viewing in Chrome) is: - * <ol> - * <li> AddTrust External CA root - * <li> COMODO RSA Certification Authority - * <li> COMODO RSA Domain Validation Secure Server CA - * <li> www.geoscaling.com - * </ol> - */ -public class GeoscalingWebClient { - public static final Logger log = LoggerFactory.getLogger(GeoscalingWebClient.class); - - public static final long PROVIDE_NETWORK_INFO = 1 << 0; - public static final long PROVIDE_CITY_INFO = 1 << 1; - public static final long PROVIDE_COUNTRY_INFO = 1 << 2; - public static final long PROVIDE_EXTRA_INFO = 1 << 3; - public static final long PROVIDE_UPTIME_INFO = 1 << 4; - - private static final String HOST ="www.geoscaling.com"; - private static final String PATH ="dns2/index.php"; - private HttpClient httpClient; - private Tidy tidy; - private List<Domain> primaryDomains = null; - - - public class Domain { - public final int id; - public final String name; - private List<SmartSubdomain> smartSubdomains = null; - - public Domain(int id, String name) { - this.id = id; - this.name = name.toLowerCase(); - } - - public List<SmartSubdomain> getSmartSubdomains() { - if (smartSubdomains == null) - smartSubdomains = GeoscalingWebClient.this.fetchSmartSubdomains(this); - return smartSubdomains; - } - - public SmartSubdomain getSmartSubdomain(String name) { - name = name.toLowerCase(); - for (SmartSubdomain s : getSmartSubdomains()) { - if (s.name.equals(name)) return s; - } - return null; - } - - /** e.g. editRecord("foo", "A", "1.2.3.4"), which assuming this domain is "bar.com", will create A record for foo.bar.com. - * <p> - * or editRecord("*.foo", "CNAME", "foo.bar.com") to map everything at *.foo.bar.com to foo.bar.com - */ - public void editRecord(String subdomainPart, String type, String content) { - subdomainPart = Strings.removeFromEnd(subdomainPart, "."+name); - editSubdomainRecord(id, subdomainPart, type, content); - } - - public SmartSubdomain getSmartSubdomain(int id) { - for (SmartSubdomain s : getSmartSubdomains()) { - if (s.id == id) return s; - } - return null; - } - - public void createSmartSubdomain(String name) { - GeoscalingWebClient.this.createSmartSubdomain(id, name); - smartSubdomains = fetchSmartSubdomains(this); - } - - public void delete() { - deletePrimaryDomain(id); - primaryDomains = fetchPrimaryDomains(); - } - - @Override - public String toString() { - return "Domain["+name+" ("+id+")]"; - } - - @Override - public int hashCode() { - return id; - } - } - - - public class SmartSubdomain { - public final Domain parent; - public final int id; - public String name; - - public SmartSubdomain(Domain parent, int id, String name) { - this.parent = parent; - this.id = id; - this.name = name.toLowerCase(); - } - - public void configure(long flags, String phpScript) { - configureSmartSubdomain(parent.id, id, name, flags, phpScript); - } - - public void delete() { - deleteSmartSubdomain(parent.id, id); - parent.smartSubdomains = fetchSmartSubdomains(parent); - } - - @Override - public String toString() { - return "SmartSubdomain["+name+" ("+id+")]"; - } - - @Override - public int hashCode() { - return id; - } - } - - - public GeoscalingWebClient() { - this(HttpTool.httpClientBuilder().build()); - } - - public GeoscalingWebClient(HttpClient httpClient) { - this.httpClient = httpClient; - this.tidy = new Tidy(); - // Silently swallow all HTML errors/warnings. - tidy.setErrout(new PrintWriter(new OutputStream() { - @Override public void write(int b) throws IOException { } - })); - } - - public GeoscalingWebClient(String username, String password) { - this(); - login(username, password); - } - - public void login(String username, String password) { - try { - String url = MessageFormat.format("https://{0}/{1}?module=auth", HOST, PATH); - - HttpPost request = new HttpPost(url); - List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2); - nameValuePairs.add(new BasicNameValuePair("username", username)); - nameValuePairs.add(new BasicNameValuePair("password", password)); - request.setEntity(new UrlEncodedFormEntity(nameValuePairs)); - - sendRequest(request, true); - - } catch (Exception e) { - throw new RuntimeException("Failed to log-in to GeoScaling service: "+e, e); - } - } - - public void logout() { - try { - String url = MessageFormat.format("https://{0}/{1}?module=auth&logout", HOST, PATH); - sendRequest(new HttpGet(url), true); - - } catch (Exception e) { - throw new RuntimeException("Failed to log-out of GeoScaling service: "+e, e); - } - } - - public List<Domain> getPrimaryDomains() { - if (primaryDomains == null) - primaryDomains = fetchPrimaryDomains(); - return primaryDomains; - } - - public Domain getPrimaryDomain(String name) { - name = name.toLowerCase(); - for (Domain d : getPrimaryDomains()) { - if (d.name.equals(name)) return d; - } - return null; - } - - public Domain getPrimaryDomain(int id) { - for (Domain d : getPrimaryDomains()) { - if (d.id == id) return d; - } - return null; - } - - public void createPrimaryDomain(String name) { - try { - name = name.toLowerCase(); - String url = MessageFormat.format("https://{0}/{1}?module=domains", HOST, PATH); - - HttpPost request = new HttpPost(url); - List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2); - nameValuePairs.add(new BasicNameValuePair("MAX_FILE_SIZE", "65536")); - nameValuePairs.add(new BasicNameValuePair("domain", FilenameUtils.removeExtension(name))); - nameValuePairs.add(new BasicNameValuePair("tld", FilenameUtils.getExtension(name))); - request.setEntity(new UrlEncodedFormEntity(nameValuePairs)); - - sendRequest(request, true); - - } catch (Exception e) { - throw new RuntimeException("Failed to create GeoScaling smart subdomain: "+e, e); - } - - primaryDomains = fetchPrimaryDomains(); - } - - private List<Domain> fetchPrimaryDomains() { - try { - List<Domain> domains = new LinkedList<Domain>(); - String url = MessageFormat.format("https://{0}/{1}?module=domains", HOST, PATH); - HttpResponse response = sendRequest(new HttpGet(url), false); - HttpEntity entity = response.getEntity(); - if (entity != null) { - Document document = tidy.parseDOM(entity.getContent(), null); - NodeList links = document.getElementsByTagName("a"); - for (int i = 0; i < links.getLength(); ++i) { - Element link = (Element) links.item(i); - String href = link.getAttribute("href"); - Pattern p = Pattern.compile("module=domain.*&id=(\\d+)"); - Matcher m = p.matcher(href); - if (!m.find(0)) continue; - - int id = Integer.parseInt(m.group(1)); - String name = getTextContent(link).trim(); - if (name.length() == 0) continue; - - domains.add(new Domain(id, name)); - } - - EntityUtils.consume(entity); - } - - return domains; - - } catch (Exception e) { - throw new RuntimeException("Failed to retrieve GeoScaling subdomains: "+e, e); - } - } - - private void deletePrimaryDomain(int primaryDomainId) { - try { - String url = MessageFormat.format( - "https://{0}/{1}?module=domain&id={2,number,#}&delete=1", - HOST, PATH, primaryDomainId); - - sendRequest(new HttpGet(url), true); - - } catch (Exception e) { - throw new RuntimeException("Failed to delete GeoScaling primary domain: "+e, e); - } - } - - private List<SmartSubdomain> fetchSmartSubdomains(Domain parent) { - try { - List<SmartSubdomain> subdomains = new LinkedList<SmartSubdomain>(); - - String url = MessageFormat.format( - "https://{0}/{1}?module=smart_subdomains&id={2,number,#}", - HOST, PATH, parent.id); - - HttpResponse response = sendRequest(new HttpGet(url), false); - HttpEntity entity = response.getEntity(); - if (entity != null) { - Document document = tidy.parseDOM(entity.getContent(), null); - NodeList links = document.getElementsByTagName("a"); - for (int i = 0; i < links.getLength(); ++i) { - Element link = (Element) links.item(i); - String href = link.getAttribute("href"); - Pattern p = Pattern.compile("module=smart_subdomain.*&subdomain_id=(\\d+)"); - Matcher m = p.matcher(href); - if (!m.find(0)) continue; - - int subdomainId = Integer.parseInt(m.group(1)); - String name = getTextContent(link); - if (name.trim().length() == 0) continue; - - name = name.substring(0, name.length() - parent.name.length() - 1); - subdomains.add(new SmartSubdomain(parent, subdomainId, name)); - } - - EntityUtils.consume(entity); - } - - return subdomains; - - } catch (Exception e) { - throw new RuntimeException("Failed to retrieve GeoScaling smart subdomains: "+e, e); - } - } - - private void createSmartSubdomain(int primaryDomainId, String smartSubdomainName) { - try { - smartSubdomainName = smartSubdomainName.toLowerCase(); - String url = MessageFormat.format( - "https://{0}/{1}?module=smart_subdomains&id={2,number,#}", - HOST, PATH, primaryDomainId); - - HttpPost request = new HttpPost(url); - List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2); - nameValuePairs.add(new BasicNameValuePair("MAX_FILE_SIZE", "65536")); - nameValuePairs.add(new BasicNameValuePair("smart_subdomain_name", smartSubdomainName)); - request.setEntity(new UrlEncodedFormEntity(nameValuePairs)); - - sendRequest(request, true); - - } catch (Exception e) { - throw new RuntimeException("Failed to create GeoScaling smart subdomain: "+e, e); - } - } - - private void deleteSmartSubdomain(int primaryDomainId, int smartSubdomainId) { - try { - String url = MessageFormat.format( - "https://{0}/{1}?module=smart_subdomains&id={2,number,#}&delete={3,number,#}", - HOST, PATH, primaryDomainId, smartSubdomainId); - - sendRequest(new HttpGet(url), true); - - } catch (Exception e) { - throw new RuntimeException("Failed to delete GeoScaling smart subdomain: "+e, e); - } - } - - private void configureSmartSubdomain(int primaryDomainId, int smartSubdomainId, String smartSubdomainName, - long flags, String phpScript) { - - try { - smartSubdomainName = smartSubdomainName.toLowerCase(); - String url = MessageFormat.format( - "https://{0}/{1}?module=smart_subdomain&id={2,number,#}&subdomain_id={3,number,#}", - HOST, PATH, primaryDomainId, smartSubdomainId); - - HttpPost request = new HttpPost(url); - List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2); - nameValuePairs.add(new BasicNameValuePair("MAX_FILE_SIZE", "65536")); - nameValuePairs.add(new BasicNameValuePair("name", smartSubdomainName)); - if ((flags & PROVIDE_NETWORK_INFO) != 0) nameValuePairs.add(new BasicNameValuePair("share_as_info", "on")); - if ((flags & PROVIDE_CITY_INFO) != 0) nameValuePairs.add(new BasicNameValuePair("share_city_info", "on")); - if ((flags & PROVIDE_COUNTRY_INFO) != 0) nameValuePairs.add(new BasicNameValuePair("share_country_info", "on")); - if ((flags & PROVIDE_EXTRA_INFO) != 0) nameValuePairs.add(new BasicNameValuePair("share_extra_info", "on")); - if ((flags & PROVIDE_UPTIME_INFO) != 0) nameValuePairs.add(new BasicNameValuePair("share_uptime_info", "on")); - nameValuePairs.add(new BasicNameValuePair("code", phpScript)); - request.setEntity(new UrlEncodedFormEntity(nameValuePairs)); - - sendRequest(request, true); - - } catch (Exception e) { - throw new RuntimeException("Failed to update GeoScaling smart subdomain: "+e, e); - } - } - - private void editSubdomainRecord(int primaryDomainId, String record, String type, String content) { - - try { - String url = MessageFormat.format( - "https://{0}/{1}?", - HOST, "dns2/ajax/add_record.php"); - - HttpPost request = new HttpPost(url); - List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2); - nameValuePairs.add(new BasicNameValuePair("id", ""+primaryDomainId)); - nameValuePairs.add(new BasicNameValuePair("name", record)); - nameValuePairs.add(new BasicNameValuePair("type", type)); - nameValuePairs.add(new BasicNameValuePair("content", content)); - nameValuePairs.add(new BasicNameValuePair("ttl", "300")); - nameValuePairs.add(new BasicNameValuePair("prio", "0")); - - request.setEntity(new UrlEncodedFormEntity(nameValuePairs)); - - sendRequest(request, true); - } catch (Exception e) { - throw new RuntimeException("Failed to update GeoScaling smart subdomain: "+e, e); - } - } - - - protected HttpResponse sendRequest(HttpUriRequest request, boolean consumeResponse) throws ClientProtocolException, IOException { - if (log.isDebugEnabled()) log.debug("Geoscaling request: "+ - request.getURI()+ - (request instanceof HttpPost ? " "+((HttpPost)request).getEntity() : "")); - HttpResponse response = httpClient.execute(request); - if (log.isDebugEnabled()) log.debug("Geoscaling response: "+response); - if (consumeResponse) - EntityUtils.consume(response.getEntity()); - return response; - } - - private static String getTextContent(Node n) { - StringBuffer sb = new StringBuffer(); - NodeList childNodes = n.getChildNodes(); - for (int i = 0; i < childNodes.getLength(); ++i) { - Node child = childNodes.item(i); - if (child.getNodeType() == Node.TEXT_NODE) - sb.append(child.getNodeValue()); - else - sb.append(getTextContent(child)); - } - return sb.toString(); - } - -}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/77dff880/software/webapp/src/main/java/brooklyn/entity/proxy/AbstractController.java ---------------------------------------------------------------------- diff --git a/software/webapp/src/main/java/brooklyn/entity/proxy/AbstractController.java b/software/webapp/src/main/java/brooklyn/entity/proxy/AbstractController.java deleted file mode 100644 index e2ba3a1..0000000 --- a/software/webapp/src/main/java/brooklyn/entity/proxy/AbstractController.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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.entity.proxy; - -import java.util.Set; - -import brooklyn.config.ConfigKey; -import brooklyn.entity.basic.ConfigKeys; -import brooklyn.entity.basic.SoftwareProcess; -import brooklyn.entity.group.Cluster; -import brooklyn.entity.proxying.ImplementedBy; -import brooklyn.event.AttributeSensor; -import brooklyn.event.basic.BasicAttributeSensorAndConfigKey; -import brooklyn.util.flags.SetFromFlag; - -/** - * Represents a controller mechanism for a {@link Cluster}. - */ -@ImplementedBy(AbstractControllerImpl.class) -public interface AbstractController extends SoftwareProcess, LoadBalancer { - - @SetFromFlag("domain") - BasicAttributeSensorAndConfigKey<String> DOMAIN_NAME = new BasicAttributeSensorAndConfigKey<String>( - String.class, "proxy.domainName", "Domain name that this controller responds to, or null if it responds to all domains", null); - - @SetFromFlag("ssl") - ConfigKey<ProxySslConfig> SSL_CONFIG = ConfigKeys.newConfigKey(ProxySslConfig.class, - "proxy.ssl.config", "Configuration (e.g. certificates) for SSL; causes server to run with HTTPS instead of HTTP"); - - - @SetFromFlag("serviceUpUrlPath") - ConfigKey<String> SERVICE_UP_URL_PATH = ConfigKeys.newStringConfigKey( - "controller.config.serviceUpUrlPath", "The path that will be appended to the root URL to determine SERVICE_UP", ""); - - boolean isActive(); - - ProxySslConfig getSslConfig(); - - boolean isSsl(); - - String getProtocol(); - - /** returns primary domain this controller responds to, or null if it responds to all domains */ - String getDomain(); - - Integer getPort(); - - /** primary URL this controller serves, if one can / has been inferred */ - String getUrl(); - - AttributeSensor<Integer> getPortNumberSensor(); - - AttributeSensor<String> getHostnameSensor(); - - AttributeSensor<String> getHostAndPortSensor(); - - Set<String> getServerPoolAddresses(); -} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/77dff880/software/webapp/src/main/java/brooklyn/entity/proxy/AbstractControllerImpl.java ---------------------------------------------------------------------- diff --git a/software/webapp/src/main/java/brooklyn/entity/proxy/AbstractControllerImpl.java b/software/webapp/src/main/java/brooklyn/entity/proxy/AbstractControllerImpl.java deleted file mode 100644 index feff6ef..0000000 --- a/software/webapp/src/main/java/brooklyn/entity/proxy/AbstractControllerImpl.java +++ /dev/null @@ -1,516 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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.entity.proxy; - -import static brooklyn.util.JavaGroovyEquivalents.groovyTruth; -import static com.google.common.base.Preconditions.checkNotNull; -import static com.google.common.base.Preconditions.checkState; - -import java.net.URI; -import java.util.Collection; -import java.util.Map; -import java.util.Set; - -import org.apache.brooklyn.management.Task; -import org.apache.brooklyn.policy.Policy; -import org.apache.brooklyn.policy.PolicySpec; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import brooklyn.entity.Entity; -import brooklyn.entity.Group; -import brooklyn.entity.basic.Entities; -import brooklyn.entity.basic.EntityInternal; -import brooklyn.entity.basic.Lifecycle; -import brooklyn.entity.basic.ServiceStateLogic; -import brooklyn.entity.basic.SoftwareProcessImpl; -import brooklyn.entity.group.AbstractMembershipTrackingPolicy; -import brooklyn.entity.group.Cluster; -import brooklyn.entity.trait.Startable; -import brooklyn.event.AttributeSensor; -import brooklyn.event.feed.ConfigToAttributes; -import brooklyn.location.access.BrooklynAccessUtils; -import brooklyn.location.basic.Machines; -import brooklyn.util.collections.MutableMap; -import brooklyn.util.exceptions.Exceptions; -import brooklyn.util.guava.Maybe; -import brooklyn.util.task.Tasks; -import brooklyn.util.text.Strings; - -import com.google.common.base.Objects; -import com.google.common.base.Predicates; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Iterables; -import com.google.common.collect.Maps; -import com.google.common.collect.Sets; -import com.google.common.net.HostAndPort; - -/** - * Represents a controller mechanism for a {@link Cluster}. - */ -public abstract class AbstractControllerImpl extends SoftwareProcessImpl implements AbstractController { - - // TODO Should review synchronization model. Currently, all changes to the serverPoolTargets - // (and checking for potential changes) is done while synchronized on serverPoolAddresses. That means it - // will also call update/reload while holding the lock. This is "conservative", but means - // sub-classes need to be extremely careful about any additional synchronization and of - // their implementations of update/reconfigureService/reload. - - private static final Logger LOG = LoggerFactory.getLogger(AbstractControllerImpl.class); - - protected volatile boolean isActive; - protected volatile boolean updateNeeded = true; - - protected AbstractMembershipTrackingPolicy serverPoolMemberTrackerPolicy; - // final because this is the synch target - final protected Set<String> serverPoolAddresses = Sets.newLinkedHashSet(); - protected Map<Entity,String> serverPoolTargets = Maps.newLinkedHashMap(); - - public AbstractControllerImpl() { - this(MutableMap.of(), null, null); - } - public AbstractControllerImpl(Map<?, ?> properties) { - this(properties, null, null); - } - public AbstractControllerImpl(Entity parent) { - this(MutableMap.of(), parent, null); - } - public AbstractControllerImpl(Map<?, ?> properties, Entity parent) { - this(properties, parent, null); - } - public AbstractControllerImpl(Entity parent, Cluster cluster) { - this(MutableMap.of(), parent, cluster); - } - public AbstractControllerImpl(Map<?, ?> properties, Entity parent, Cluster cluster) { - super(properties, parent); - } - - @Override - public void init() { - super.init(); - setAttribute(SERVER_POOL_TARGETS, ImmutableMap.<Entity, String>of()); - } - - protected void addServerPoolMemberTrackingPolicy() { - Group serverPool = getServerPool(); - if (serverPool == null) { - return; // no-op - } - if (serverPoolMemberTrackerPolicy != null) { - LOG.debug("Call to addServerPoolMemberTrackingPolicy when serverPoolMemberTrackingPolicy already exists, removing and re-adding, in {}", this); - removeServerPoolMemberTrackingPolicy(); - } - for (Policy p: getPolicies()) { - if (p instanceof ServerPoolMemberTrackerPolicy) { - // TODO want a more elegant idiom for this! - LOG.info(this+" picking up "+p+" as the tracker (already set, often due to rebind)"); - serverPoolMemberTrackerPolicy = (ServerPoolMemberTrackerPolicy) p; - return; - } - } - - AttributeSensor<?> hostAndPortSensor = getConfig(HOST_AND_PORT_SENSOR); - AttributeSensor<?> hostnameSensor = getConfig(HOSTNAME_SENSOR); - AttributeSensor<?> portSensor = getConfig(PORT_NUMBER_SENSOR); - Set<AttributeSensor<?>> sensorsToTrack; - if (hostAndPortSensor != null) { - sensorsToTrack = ImmutableSet.<AttributeSensor<?>>of(hostAndPortSensor); - } else { - sensorsToTrack = ImmutableSet.<AttributeSensor<?>>of(hostnameSensor, portSensor); - } - - serverPoolMemberTrackerPolicy = addPolicy(PolicySpec.create(ServerPoolMemberTrackerPolicy.class) - .displayName("Controller targets tracker") - .configure("group", serverPool) - .configure("sensorsToTrack", sensorsToTrack)); - - LOG.info("Added policy {} to {}", serverPoolMemberTrackerPolicy, this); - - // Initialize ourselves immediately with the latest set of members; don't wait for - // listener notifications because then will be out-of-date for short period (causing - // problems for rebind) - Map<Entity,String> serverPoolTargets = Maps.newLinkedHashMap(); - for (Entity member : getServerPool().getMembers()) { - if (belongsInServerPool(member)) { - if (LOG.isTraceEnabled()) LOG.trace("Done {} checkEntity {}", this, member); - String address = getAddressOfEntity(member); - serverPoolTargets.put(member, address); - } - } - - LOG.info("Resetting {}, server pool targets {}", new Object[] {this, serverPoolTargets}); - setAttribute(SERVER_POOL_TARGETS, serverPoolTargets); - } - - protected void removeServerPoolMemberTrackingPolicy() { - if (serverPoolMemberTrackerPolicy != null) { - removePolicy(serverPoolMemberTrackerPolicy); - } - } - - public static class ServerPoolMemberTrackerPolicy extends AbstractMembershipTrackingPolicy { - @Override - protected void onEntityEvent(EventType type, Entity entity) { - // relies on policy-rebind injecting the implementation rather than the dynamic-proxy - ((AbstractControllerImpl)super.entity).onServerPoolMemberChanged(entity); - } - } - - @Override - public Set<String> getServerPoolAddresses() { - return ImmutableSet.copyOf(Iterables.filter(getAttribute(SERVER_POOL_TARGETS).values(), Predicates.notNull())); - } - - /** - * Opportunity to do late-binding of the cluster that is being controlled. Must be called before start(). - * Can pass in the 'serverPool'. - */ - @Override - public void bind(Map<?,?> flags) { - if (flags.containsKey("serverPool")) { - setConfigEvenIfOwned(SERVER_POOL, (Group) flags.get("serverPool")); - } - } - - @SuppressWarnings("deprecation") - @Override - public void onManagementNoLongerMaster() { - super.onManagementNoLongerMaster(); // TODO remove when deprecated method in parent removed - isActive = false; - removeServerPoolMemberTrackingPolicy(); - } - - private Group getServerPool() { - return getConfig(SERVER_POOL); - } - - @Override - public boolean isActive() { - return isActive; - } - - @Override - public boolean isSsl() { - return getSslConfig() != null; - } - - @Override - public ProxySslConfig getSslConfig() { - return getConfig(SSL_CONFIG); - } - - @Override - public String getProtocol() { - return getAttribute(PROTOCOL); - } - - /** returns primary domain this controller responds to, or null if it responds to all domains */ - @Override - public String getDomain() { - return getAttribute(DOMAIN_NAME); - } - - @Override - public Integer getPort() { - if (isSsl()) - return getAttribute(PROXY_HTTPS_PORT); - else - return getAttribute(PROXY_HTTP_PORT); - } - - /** primary URL this controller serves, if one can / has been inferred */ - @Override - public String getUrl() { - return Strings.toString( getAttribute(MAIN_URI) ); - } - - @Override - public AttributeSensor<Integer> getPortNumberSensor() { - return getAttribute(PORT_NUMBER_SENSOR); - } - - @Override - public AttributeSensor<String> getHostnameSensor() { - return getAttribute(HOSTNAME_SENSOR); - } - - @Override - public AttributeSensor<String> getHostAndPortSensor() { - return getAttribute(HOST_AND_PORT_SENSOR); - } - - @Override - public abstract void reload(); - - protected String inferProtocol() { - return isSsl() ? "https" : "http"; - } - - /** returns URL, if it can be inferred; null otherwise */ - protected String inferUrl(boolean requireManagementAccessible) { - String protocol = checkNotNull(getProtocol(), "no protocol configured"); - String domain = getDomain(); - if (domain != null && domain.startsWith("*.")) { - domain = domain.replace("*.", ""); // Strip wildcard - } - Integer port = checkNotNull(getPort(), "no port configured (the requested port may be in use)"); - if (requireManagementAccessible) { - HostAndPort accessible = BrooklynAccessUtils.getBrooklynAccessibleAddress(this, port); - if (accessible!=null) { - domain = accessible.getHostText(); - port = accessible.getPort(); - } - } - if (domain==null) domain = Machines.findSubnetHostname(this).orNull(); - if (domain==null) return null; - return protocol+"://"+domain+":"+port+"/"+getConfig(SERVICE_UP_URL_PATH); - } - - protected String inferUrl() { - return inferUrl(false); - } - - @Override - protected Collection<Integer> getRequiredOpenPorts() { - Collection<Integer> result = super.getRequiredOpenPorts(); - if (groovyTruth(getAttribute(PROXY_HTTP_PORT))) result.add(getAttribute(PROXY_HTTP_PORT)); - if (groovyTruth(getAttribute(PROXY_HTTPS_PORT))) result.add(getAttribute(PROXY_HTTPS_PORT)); - return result; - } - - @Override - protected void preStart() { - super.preStart(); - computePortsAndUrls(); - } - - protected void computePortsAndUrls() { - AttributeSensor<String> hostAndPortSensor = getConfig(HOST_AND_PORT_SENSOR); - Maybe<Object> hostnameSensor = config().getRaw(HOSTNAME_SENSOR); - Maybe<Object> portSensor = config().getRaw(PORT_NUMBER_SENSOR); - if (hostAndPortSensor != null) { - checkState(!hostnameSensor.isPresent() && !portSensor.isPresent(), - "Must not set %s and either of %s or %s", HOST_AND_PORT_SENSOR, HOSTNAME_SENSOR, PORT_NUMBER_SENSOR); - } - - ConfigToAttributes.apply(this); - - setAttribute(PROTOCOL, inferProtocol()); - setAttribute(MAIN_URI, URI.create(inferUrl())); - setAttribute(ROOT_URL, inferUrl()); - - checkNotNull(getPortNumberSensor(), "no sensor configured to infer port number"); - } - - @Override - protected void connectSensors() { - super.connectSensors(); - // TODO when rebind policies, and rebind calls connectSensors, then this will cause problems. - // Also relying on addServerPoolMemberTrackingPolicy to set the serverPoolAddresses and serverPoolTargets. - - addServerPoolMemberTrackingPolicy(); - } - - @Override - protected void postStart() { - super.postStart(); - isActive = true; - update(); - } - - @Override - protected void postRebind() { - super.postRebind(); - Lifecycle state = getAttribute(SERVICE_STATE_ACTUAL); - if (state != null && state == Lifecycle.RUNNING) { - isActive = true; - updateNeeded(); - } - } - - @Override - protected void preStop() { - super.preStop(); - removeServerPoolMemberTrackingPolicy(); - } - - /** - * Implementations should update the configuration so that 'serverPoolAddresses' are targeted. - * The caller will subsequently call reload to apply the new configuration. - */ - protected abstract void reconfigureService(); - - public void updateNeeded() { - synchronized (serverPoolAddresses) { - if (updateNeeded) return; - updateNeeded = true; - LOG.debug("queueing an update-needed task for "+this+"; update will occur shortly"); - Entities.submit(this, Tasks.builder().name("update-needed").body(new Runnable() { - @Override - public void run() { - if (updateNeeded) - AbstractControllerImpl.this.update(); - } - }).build()); - } - } - - @Override - public void update() { - try { - Task<?> task = updateAsync(); - if (task != null) task.getUnchecked(); - ServiceStateLogic.ServiceProblemsLogic.clearProblemsIndicator(this, "update"); - } catch (Exception e) { - ServiceStateLogic.ServiceProblemsLogic.updateProblemsIndicator(this, "update", "update failed with: "+Exceptions.collapseText(e)); - throw Exceptions.propagate(e); - } - } - - public Task<?> updateAsync() { - synchronized (serverPoolAddresses) { - Task<?> result = null; - if (!isActive()) updateNeeded = true; - else { - updateNeeded = false; - LOG.debug("Updating {} in response to changes", this); - LOG.info("Updating {}, server pool targets {}", new Object[] {this, getAttribute(SERVER_POOL_TARGETS)}); - reconfigureService(); - LOG.debug("Reloading {} in response to changes", this); - // reload should happen synchronously - result = invoke(RELOAD); - } - return result; - } - } - - protected void onServerPoolMemberChanged(Entity member) { - synchronized (serverPoolAddresses) { - if (LOG.isTraceEnabled()) LOG.trace("For {}, considering membership of {} which is in locations {}", - new Object[] {this, member, member.getLocations()}); - if (belongsInServerPool(member)) { - addServerPoolMember(member); - } else { - removeServerPoolMember(member); - } - if (LOG.isTraceEnabled()) LOG.trace("Done {} checkEntity {}", this, member); - } - } - - protected boolean belongsInServerPool(Entity member) { - if (!groovyTruth(member.getAttribute(Startable.SERVICE_UP))) { - if (LOG.isTraceEnabled()) LOG.trace("Members of {}, checking {}, eliminating because not up", this, member); - return false; - } - if (!getServerPool().getMembers().contains(member)) { - if (LOG.isTraceEnabled()) LOG.trace("Members of {}, checking {}, eliminating because not member", this, member); - return false; - } - if (LOG.isTraceEnabled()) LOG.trace("Members of {}, checking {}, approving", this, member); - return true; - } - - protected void addServerPoolMember(Entity member) { - synchronized (serverPoolAddresses) { - String oldAddress = getAttribute(SERVER_POOL_TARGETS).get(member); - String newAddress = getAddressOfEntity(member); - if (Objects.equal(newAddress, oldAddress)) { - if (LOG.isTraceEnabled()) - if (LOG.isTraceEnabled()) LOG.trace("Ignoring unchanged address {}", oldAddress); - return; - } else if (newAddress == null) { - LOG.info("Removing from {}, member {} with old address {}, because inferred address is now null", new Object[] {this, member, oldAddress}); - } else { - if (oldAddress != null) { - LOG.info("Replacing in {}, member {} with old address {}, new address {}", new Object[] {this, member, oldAddress, newAddress}); - } else { - LOG.info("Adding to {}, new member {} with address {}", new Object[] {this, member, newAddress}); - } - } - - if (Objects.equal(oldAddress, newAddress)) { - if (LOG.isTraceEnabled()) LOG.trace("For {}, ignoring change in member {} because address still {}", new Object[] {this, member, newAddress}); - return; - } - - // TODO this does it synchronously; an async method leaning on `updateNeeded` and `update` might - // be more appropriate, especially when this is used in a listener - MapAttribute.put(this, SERVER_POOL_TARGETS, member, newAddress); - updateAsync(); - } - } - - protected void removeServerPoolMember(Entity member) { - synchronized (serverPoolAddresses) { - if (!getAttribute(SERVER_POOL_TARGETS).containsKey(member)) { - if (LOG.isTraceEnabled()) LOG.trace("For {}, not removing as don't have member {}", new Object[] {this, member}); - return; - } - - String address = MapAttribute.remove(this, SERVER_POOL_TARGETS, member); - - LOG.info("Removing from {}, member {} with address {}", new Object[] {this, member, address}); - - updateAsync(); - } - } - - protected String getAddressOfEntity(Entity member) { - AttributeSensor<String> hostAndPortSensor = getHostAndPortSensor(); - if (hostAndPortSensor != null) { - String result = member.getAttribute(hostAndPortSensor); - if (result != null) { - return result; - } else { - LOG.error("No host:port set for {} (using attribute {}); skipping in {}", - new Object[] {member, hostAndPortSensor, this}); - return null; - } - } else { - String ip = member.getAttribute(getHostnameSensor()); - Integer port = member.getAttribute(getPortNumberSensor()); - if (ip!=null && port!=null) { - return ip+":"+port; - } - LOG.error("Unable to construct hostname:port representation for {} ({}:{}); skipping in {}", - new Object[] {member, ip, port, this}); - return null; - } - } - - // Utilities for modifying an AttributeSensor of type map - private static class MapAttribute { - public static <K, V> V put(Entity entity, AttributeSensor<Map<K,V>> attribute, K key, V value) { - Map<K, V> oldMap = entity.getAttribute(attribute); - Map<K, V> newMap = MutableMap.copyOf(oldMap); - V oldVal = newMap.put(key, value); - ((EntityInternal)entity).setAttribute(attribute, newMap); - return oldVal; - } - - public static <K, V> V remove(Entity entity, AttributeSensor<Map<K,V>> attribute, K key) { - Map<K, V> oldMap = entity.getAttribute(attribute); - Map<K, V> newMap = MutableMap.copyOf(oldMap); - V oldVal = newMap.remove(key); - ((EntityInternal)entity).setAttribute(attribute, newMap); - return oldVal; - } - } -} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/77dff880/software/webapp/src/main/java/brooklyn/entity/proxy/AbstractNonProvisionedController.java ---------------------------------------------------------------------- diff --git a/software/webapp/src/main/java/brooklyn/entity/proxy/AbstractNonProvisionedController.java b/software/webapp/src/main/java/brooklyn/entity/proxy/AbstractNonProvisionedController.java deleted file mode 100644 index 47e1f86..0000000 --- a/software/webapp/src/main/java/brooklyn/entity/proxy/AbstractNonProvisionedController.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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.entity.proxy; - -import brooklyn.entity.Entity; -import brooklyn.entity.proxying.ImplementedBy; - -@ImplementedBy(AbstractNonProvisionedControllerImpl.class) -public interface AbstractNonProvisionedController extends LoadBalancer, Entity { - - public boolean isActive(); -} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/77dff880/software/webapp/src/main/java/brooklyn/entity/proxy/AbstractNonProvisionedControllerImpl.java ---------------------------------------------------------------------- diff --git a/software/webapp/src/main/java/brooklyn/entity/proxy/AbstractNonProvisionedControllerImpl.java b/software/webapp/src/main/java/brooklyn/entity/proxy/AbstractNonProvisionedControllerImpl.java deleted file mode 100644 index 590ae32..0000000 --- a/software/webapp/src/main/java/brooklyn/entity/proxy/AbstractNonProvisionedControllerImpl.java +++ /dev/null @@ -1,277 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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.entity.proxy; - -import static brooklyn.util.JavaGroovyEquivalents.groovyTruth; -import static com.google.common.base.Preconditions.checkState; - -import java.util.Collection; -import java.util.Map; -import java.util.Set; - -import org.apache.brooklyn.policy.PolicySpec; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import brooklyn.entity.Entity; -import brooklyn.entity.Group; -import brooklyn.entity.basic.AbstractEntity; -import brooklyn.entity.group.AbstractMembershipTrackingPolicy; -import brooklyn.entity.group.Cluster; -import brooklyn.entity.trait.Startable; -import brooklyn.event.AttributeSensor; -import brooklyn.event.feed.ConfigToAttributes; -import brooklyn.location.Location; -import brooklyn.util.collections.MutableMap; -import brooklyn.util.guava.Maybe; - -import com.google.common.collect.Maps; -import com.google.common.collect.Sets; - -public abstract class AbstractNonProvisionedControllerImpl extends AbstractEntity implements AbstractNonProvisionedController { - - private static final Logger LOG = LoggerFactory.getLogger(AbstractNonProvisionedControllerImpl.class); - - protected volatile boolean isActive; - protected volatile boolean updateNeeded = true; - - protected AbstractMembershipTrackingPolicy serverPoolMemberTrackerPolicy; - protected Set<String> serverPoolAddresses = Sets.newLinkedHashSet(); - protected Map<Entity,String> serverPoolTargets = Maps.newLinkedHashMap(); - - public AbstractNonProvisionedControllerImpl() { - this(MutableMap.of(), null, null); - } - public AbstractNonProvisionedControllerImpl(Map properties) { - this(properties, null, null); - } - public AbstractNonProvisionedControllerImpl(Entity parent) { - this(MutableMap.of(), parent, null); - } - public AbstractNonProvisionedControllerImpl(Map properties, Entity parent) { - this(properties, parent, null); - } - public AbstractNonProvisionedControllerImpl(Entity parent, Cluster cluster) { - this(MutableMap.of(), parent, cluster); - } - public AbstractNonProvisionedControllerImpl(Map properties, Entity parent, Cluster cluster) { - } - - public static class MemberTrackingPolicy extends AbstractMembershipTrackingPolicy { - @Override protected void onEntityEvent(EventType type, Entity member) { - ((AbstractNonProvisionedControllerImpl)super.entity).onServerPoolMemberChanged(member); - } - } - - /** - * Opportunity to do late-binding of the cluster that is being controlled. Must be called before start(). - * Can pass in the 'serverPool'. - */ - @Override - public void bind(Map<?,?> flags) { - if (flags.containsKey("serverPool")) { - setConfigEvenIfOwned(SERVER_POOL, (Group) flags.get("serverPool")); - } - } - - @Override - public boolean isActive() { - return isActive; - } - - @Override - public void start(Collection<? extends Location> locations) { - preStart(); - } - - @Override - public void stop() { - preStop(); - } - - protected void preStart() { - AttributeSensor<?> hostAndPortSensor = getConfig(HOST_AND_PORT_SENSOR); - Maybe<Object> hostnameSensor = getConfigRaw(HOSTNAME_SENSOR, true); - Maybe<Object> portSensor = getConfigRaw(PORT_NUMBER_SENSOR, true); - if (hostAndPortSensor != null) { - checkState(!hostnameSensor.isPresent() && !portSensor.isPresent(), - "Must not set %s and either of %s or %s", HOST_AND_PORT_SENSOR, HOSTNAME_SENSOR, PORT_NUMBER_SENSOR); - } - - ConfigToAttributes.apply(this); - addServerPoolMemberTrackerPolicy(); - } - - protected void preStop() { - removeServerPoolMemberTrackerPolicy(); - } - - protected void addServerPoolMemberTrackerPolicy() { - Group serverPool = getServerPool(); - if (serverPool != null) { - serverPoolMemberTrackerPolicy = addPolicy(PolicySpec.create(MemberTrackingPolicy.class) - .displayName("Controller targets tracker") - .configure("group", serverPool)); - - LOG.info("Added policy {} to {}, during start", serverPoolMemberTrackerPolicy, this); - - serverPoolAddresses.clear(); - serverPoolTargets.clear(); - - // Initialize ourselves immediately with the latest set of members; don't wait for - // listener notifications because then will be out-of-date for short period (causing - // problems for rebind) - for (Entity member : getServerPool().getMembers()) { - if (belongsInServerPool(member)) { - if (LOG.isTraceEnabled()) LOG.trace("Done {} checkEntity {}", this, member); - String address = getAddressOfEntity(member); - serverPoolTargets.put(member, address); - if (address != null) { - serverPoolAddresses.add(address); - } - } - } - - LOG.info("Resetting {}, members {} with addresses {}", new Object[] {this, serverPoolTargets, serverPoolAddresses}); - setAttribute(SERVER_POOL_TARGETS, serverPoolTargets); - } - } - - protected void removeServerPoolMemberTrackerPolicy() { - if (serverPoolMemberTrackerPolicy != null) { - removePolicy(serverPoolMemberTrackerPolicy); - } - } - - /** - * Implementations should update the configuration so that 'serverPoolAddresses' are targeted. - * The caller will subsequently call reload to apply the new configuration. - */ - protected abstract void reconfigureService(); - - @Override - public synchronized void update() { - if (!isActive()) updateNeeded = true; - else { - updateNeeded = false; - LOG.debug("Updating {} in response to changes", this); - reconfigureService(); - LOG.debug("Reloading {} in response to changes", this); - invoke(RELOAD); - } - setAttribute(SERVER_POOL_TARGETS, serverPoolTargets); - } - - protected synchronized void onServerPoolMemberChanged(Entity member) { - if (LOG.isTraceEnabled()) LOG.trace("For {}, considering membership of {} which is in locations {}", - new Object[] {this, member, member.getLocations()}); - if (belongsInServerPool(member)) { - addServerPoolMember(member); - } else { - removeServerPoolMember(member); - } - if (LOG.isTraceEnabled()) LOG.trace("Done {} checkEntity {}", this, member); - } - - protected boolean belongsInServerPool(Entity member) { - if (!groovyTruth(member.getAttribute(Startable.SERVICE_UP))) { - if (LOG.isTraceEnabled()) LOG.trace("Members of {}, checking {}, eliminating because not up", this, member); - return false; - } - if (!getServerPool().getMembers().contains(member)) { - if (LOG.isTraceEnabled()) LOG.trace("Members of {}, checking {}, eliminating because not member", this, member); - return false; - } - if (LOG.isTraceEnabled()) LOG.trace("Members of {}, checking {}, approving", this, member); - return true; - } - - private Group getServerPool() { - return getConfig(SERVER_POOL); - } - - protected AttributeSensor<Integer> getPortNumberSensor() { - return getAttribute(PORT_NUMBER_SENSOR); - } - - protected AttributeSensor<String> getHostnameSensor() { - return getAttribute(HOSTNAME_SENSOR); - } - - protected AttributeSensor<String> getHostAndPortSensor() { - return getAttribute(HOST_AND_PORT_SENSOR); - } - - protected synchronized void addServerPoolMember(Entity member) { - if (serverPoolTargets.containsKey(member)) { - if (LOG.isTraceEnabled()) LOG.trace("For {}, not adding as already have member {}", new Object[] {this, member}); - return; - } - - String address = getAddressOfEntity(member); - if (address != null) { - serverPoolAddresses.add(address); - } - - LOG.info("Adding to {}, new member {} with address {}", new Object[] {this, member, address}); - - update(); - serverPoolTargets.put(member, address); - } - - protected synchronized void removeServerPoolMember(Entity member) { - if (!serverPoolTargets.containsKey(member)) { - if (LOG.isTraceEnabled()) LOG.trace("For {}, not removing as don't have member {}", new Object[] {this, member}); - return; - } - - String address = serverPoolTargets.get(member); - if (address != null) { - serverPoolAddresses.remove(address); - } - - LOG.info("Removing from {}, member {} with address {}", new Object[] {this, member, address}); - - update(); - serverPoolTargets.remove(member); - } - - protected String getAddressOfEntity(Entity member) { - AttributeSensor<String> hostAndPortSensor = getHostAndPortSensor(); - if (hostAndPortSensor != null) { - String result = member.getAttribute(hostAndPortSensor); - if (result != null) { - return result; - } else { - LOG.error("No host:port set for {} (using attribute {}); skipping in {}", - new Object[] {member, hostAndPortSensor, this}); - return null; - } - } else { - String ip = member.getAttribute(getHostnameSensor()); - Integer port = member.getAttribute(getPortNumberSensor()); - if (ip!=null && port!=null) { - return ip+":"+port; - } - LOG.error("Unable to construct hostname:port representation for {} ({}:{}); skipping in {}", - new Object[] {member, ip, port, this}); - return null; - } - } -} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/77dff880/software/webapp/src/main/java/brooklyn/entity/proxy/LoadBalancer.java ---------------------------------------------------------------------- diff --git a/software/webapp/src/main/java/brooklyn/entity/proxy/LoadBalancer.java b/software/webapp/src/main/java/brooklyn/entity/proxy/LoadBalancer.java deleted file mode 100644 index 415dea4..0000000 --- a/software/webapp/src/main/java/brooklyn/entity/proxy/LoadBalancer.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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.entity.proxy; - -import java.net.URI; -import java.util.Map; - -import brooklyn.config.ConfigKey; -import brooklyn.entity.Entity; -import brooklyn.entity.Group; -import brooklyn.entity.annotation.Effector; -import brooklyn.entity.basic.Attributes; -import brooklyn.entity.basic.MethodEffector; -import brooklyn.entity.trait.Startable; -import brooklyn.entity.webapp.WebAppService; -import brooklyn.event.AttributeSensor; -import brooklyn.event.basic.BasicAttributeSensorAndConfigKey; -import brooklyn.event.basic.BasicConfigKey; -import brooklyn.event.basic.PortAttributeSensorAndConfigKey; -import brooklyn.event.basic.Sensors; -import brooklyn.util.flags.SetFromFlag; - -import com.google.common.collect.ImmutableList; -import com.google.common.reflect.TypeToken; - -/** - * A load balancer that routes requests to set(s) of servers. - * - * There is an optional "serverPool" that will have requests routed to it (e.g. as round-robin). - * This is a group whose members are appropriate servers; membership of that group will be tracked - * to automatically update the load balancer's configuration as appropriate. - * - * There is an optional urlMappings group for defining additional mapping rules. Members of this - * group (of type UrlMapping) will be tracked, to automatically update the load balancer's configuration. - * The UrlMappings can give custom routing rules so that specific urls are routed (and potentially re-written) - * to particular sets of servers. - * - * @author aled - */ -public interface LoadBalancer extends Entity, Startable { - - @SetFromFlag("serverPool") - ConfigKey<Group> SERVER_POOL = new BasicConfigKey<Group>( - Group.class, "loadbalancer.serverpool", "The default servers to route messages to"); - - @SetFromFlag("urlMappings") - ConfigKey<Group> URL_MAPPINGS = new BasicConfigKey<Group>( - Group.class, "loadbalancer.urlmappings", "Special mapping rules (e.g. for domain/path matching, rewrite, etc); not supported by all load balancers"); - - /** sensor for port to forward to on target entities */ - @SuppressWarnings("serial") - @SetFromFlag("portNumberSensor") - public static final BasicAttributeSensorAndConfigKey<AttributeSensor<Integer>> PORT_NUMBER_SENSOR = new BasicAttributeSensorAndConfigKey<AttributeSensor<Integer>>( - new TypeToken<AttributeSensor<Integer>>() {}, "member.sensor.portNumber", "Port number sensor on members (defaults to http.port; not supported in all implementations)", Attributes.HTTP_PORT); - - /** sensor for hostname to forward to on target entities */ - @SuppressWarnings("serial") - @SetFromFlag("hostnameSensor") - public static final BasicAttributeSensorAndConfigKey<AttributeSensor<String>> HOSTNAME_SENSOR = new BasicAttributeSensorAndConfigKey<AttributeSensor<String>>( - new TypeToken<AttributeSensor<String>>() {}, "member.sensor.hostname", "Hostname/IP sensor on members (defaults to host.subnet.hostname; not supported in all implementations)", Attributes.SUBNET_HOSTNAME); - - /** sensor for hostname to forward to on target entities */ - @SuppressWarnings("serial") - @SetFromFlag("hostAndPortSensor") - public static final BasicAttributeSensorAndConfigKey<AttributeSensor<String>> HOST_AND_PORT_SENSOR = new BasicAttributeSensorAndConfigKey<AttributeSensor<String>>( - new TypeToken<AttributeSensor<String>>() {}, "member.sensor.hostandport", "host:port sensor on members (invalid to configure this and the portNumber or hostname sensors)", null); - - @SetFromFlag("port") - /** port where this controller should live */ - public static final PortAttributeSensorAndConfigKey PROXY_HTTP_PORT = new PortAttributeSensorAndConfigKey( - "proxy.http.port", "Main port where this proxy listens if using HTTP", ImmutableList.of(8000, "8001+")); - - @SetFromFlag("httpsPort") - /** port where this controller should live */ - public static final PortAttributeSensorAndConfigKey PROXY_HTTPS_PORT = new PortAttributeSensorAndConfigKey( - "proxy.https.port", "Main port where this proxy listens if using HTTPS", ImmutableList.of(8443, "8443+")); - - @SetFromFlag("protocol") - public static final BasicAttributeSensorAndConfigKey<String> PROTOCOL = new BasicAttributeSensorAndConfigKey<String>( - String.class, "proxy.protocol", "Main URL protocol this proxy answers (typically http or https)", null); - - public static final AttributeSensor<String> HOSTNAME = Attributes.HOSTNAME; - - public static final AttributeSensor<URI> MAIN_URI = Attributes.MAIN_URI; - public static final AttributeSensor<String> ROOT_URL = WebAppService.ROOT_URL; - - @SuppressWarnings("serial") - public static final AttributeSensor<Map<Entity, String>> SERVER_POOL_TARGETS = Sensors.newSensor( - new TypeToken<Map<Entity, String>>() {}, - "proxy.serverpool.targets", - "The downstream targets in the server pool"); - - public static final MethodEffector<Void> RELOAD = new MethodEffector<Void>(LoadBalancer.class, "reload"); - - public static final MethodEffector<Void> UPDATE = new MethodEffector<Void>(LoadBalancer.class, "update"); - - @Effector(description="Forces reload of the configuration") - public void reload(); - - @Effector(description="Updates the entities configuration, and then forces reload of that configuration") - public void update(); - - /** - * Opportunity to do late-binding of the cluster that is being controlled. Must be called before start(). - * Can pass in the 'serverPool'. - */ - public void bind(Map<?,?> flags); -} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/77dff880/software/webapp/src/main/java/brooklyn/entity/proxy/LoadBalancerCluster.java ---------------------------------------------------------------------- diff --git a/software/webapp/src/main/java/brooklyn/entity/proxy/LoadBalancerCluster.java b/software/webapp/src/main/java/brooklyn/entity/proxy/LoadBalancerCluster.java deleted file mode 100644 index 1f42827..0000000 --- a/software/webapp/src/main/java/brooklyn/entity/proxy/LoadBalancerCluster.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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.entity.proxy; - -import brooklyn.entity.group.DynamicCluster; -import brooklyn.entity.proxying.ImplementedBy; - -/** - * A cluster of load balancers, where configuring the cluster (through the LoadBalancer interface) - * will configure all load balancers in the cluster. - * - * Config keys (such as LoadBalancer.serverPool and LoadBalancer.urlMappings) are automatically - * inherited by the children of the load balancer cluster. It is through that mechanism that - * configuration changes on the cluster will be applied to all child load balancers (i.e. by - * them all sharing the same serverPool and urlMappings etc). - * - * @author aled - */ -@ImplementedBy(LoadBalancerClusterImpl.class) -public interface LoadBalancerCluster extends DynamicCluster, LoadBalancer { -} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/77dff880/software/webapp/src/main/java/brooklyn/entity/proxy/LoadBalancerClusterImpl.java ---------------------------------------------------------------------- diff --git a/software/webapp/src/main/java/brooklyn/entity/proxy/LoadBalancerClusterImpl.java b/software/webapp/src/main/java/brooklyn/entity/proxy/LoadBalancerClusterImpl.java deleted file mode 100644 index b17049e..0000000 --- a/software/webapp/src/main/java/brooklyn/entity/proxy/LoadBalancerClusterImpl.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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.entity.proxy; - -import java.util.Map; - -import brooklyn.entity.Entity; -import brooklyn.entity.group.DynamicClusterImpl; - -/** - * A cluster of load balancers, where configuring the cluster (through the LoadBalancer interface) - * will configure all load balancers in the cluster. - * - * Config keys (such as LoadBalancer.serverPool and LoadBalancer.urlMappings) are automatically - * inherited by the children of the load balancer cluster. It is through that mechanism that - * configuration changes on the cluster will be applied to all child load balancers (i.e. by - * them all sharing the same serverPool and urlMappings etc). - * - * @author aled - */ -public class LoadBalancerClusterImpl extends DynamicClusterImpl implements LoadBalancerCluster { - - // TODO I suspect there are races with reconfiguring the load-balancers while - // the cluster is growing: there is no synchronization around the calls to reload - // and the resize, so presumably there's a race where a newly added load-balancer - // could miss the most recent reload call? - - public LoadBalancerClusterImpl() { - super(); - } - - /* NOTE The following methods come from {@link LoadBalancer} but are probably safe to ignore */ - - @Override - public void reload() { - for (Entity member : getMembers()) { - if (member instanceof LoadBalancer) { - ((LoadBalancer)member).reload(); - } - } - } - - @Override - public void update() { - for (Entity member : getMembers()) { - if (member instanceof LoadBalancer) { - ((LoadBalancer)member).update(); - } - } - } - - @Override - public void bind(Map<?,?> flags) { - for (Entity member : getMembers()) { - if (member instanceof LoadBalancer) { - ((LoadBalancer)member).bind(flags); - } - } - } -} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/77dff880/software/webapp/src/main/java/brooklyn/entity/proxy/ProxySslConfig.java ---------------------------------------------------------------------- diff --git a/software/webapp/src/main/java/brooklyn/entity/proxy/ProxySslConfig.java b/software/webapp/src/main/java/brooklyn/entity/proxy/ProxySslConfig.java deleted file mode 100644 index 0a61021..0000000 --- a/software/webapp/src/main/java/brooklyn/entity/proxy/ProxySslConfig.java +++ /dev/null @@ -1,219 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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.entity.proxy; - -import java.io.Serializable; -import java.util.Map; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import brooklyn.util.flags.FlagUtils; -import brooklyn.util.flags.SetFromFlag; - -import com.google.common.base.Objects; - -public class ProxySslConfig implements Serializable { - - private static final long serialVersionUID = -2692754611458939617L; - - private static final Logger log = LoggerFactory.getLogger(ProxySslConfig.class); - - public static Builder builder() { - return new Builder(); - } - - public static class Builder { - @SetFromFlag protected String certificateSourceUrl; - @SetFromFlag protected String keySourceUrl; - @SetFromFlag protected String certificateDestination; - @SetFromFlag protected String keyDestination; - @SetFromFlag protected boolean targetIsSsl = false; - @SetFromFlag protected boolean reuseSessions = false; - - public Builder certificateSourceUrl(String val) { - certificateSourceUrl = val; return this; - } - public Builder keySourceUrl(String val) { - keySourceUrl = val; return this; - } - public Builder certificateDestination(String val) { - certificateDestination = val; return this; - } - public Builder keyDestination(String val) { - keyDestination = val; return this; - } - public Builder targetIsSsl(boolean val) { - targetIsSsl = val; return this; - } - public Builder reuseSessions(boolean val) { - reuseSessions = val; return this; - } - public ProxySslConfig build() { - ProxySslConfig result = new ProxySslConfig(this); - return result; - } - } - - public static ProxySslConfig fromMap(Map<?,?> map) { - Builder b = new Builder(); - Map<?, ?> unused = FlagUtils.setFieldsFromFlags(map, b); - if (!unused.isEmpty()) log.warn("Unused flags when populating "+b+" (ignoring): "+unused); - return b.build(); - } - - private String certificateSourceUrl; - private String keySourceUrl; - private String certificateDestination; - private String keyDestination; - private boolean targetIsSsl = false; - private boolean reuseSessions = false; - - public ProxySslConfig() { } - - protected ProxySslConfig(Builder builder) { - certificateSourceUrl = builder.certificateSourceUrl; - keySourceUrl = builder.keySourceUrl; - certificateDestination = builder.certificateDestination; - keyDestination = builder.keyDestination; - targetIsSsl = builder.targetIsSsl; - reuseSessions = builder.reuseSessions; - } - - /** - * URL for the SSL certificates required at the server. - * <p> - * Corresponding nginx settings: - * <pre> - * ssl on; - * ssl_certificate www.example.com.crt; - * ssl_certificate_key www.example.com.key; - * </pre> - * Okay (in nginx) for key to be null if certificate contains both as per setup at - * http://nginx.org/en/docs/http/configuring_https_servers.html - * <p> - * Proxy object can be set on nginx instance to apply site-wide, - * and to put multiple servers in the certificate file - * <p> - * The brooklyn entity will install the certificate/key(s) on the server. - * (however it will not currently merge multiple certificates. - * if conflicting certificates are attempted to be installed nginx will complain.) - */ - public String getCertificateSourceUrl() { - return certificateSourceUrl; - } - - public void setCertificateSourceUrl(String certificateSourceUrl) { - this.certificateSourceUrl = certificateSourceUrl; - } - - /** @see #getCertificateSourceUrl()} */ - public String getKeySourceUrl() { - return keySourceUrl; - } - - public void setKeySourceUrl(String keySourceUrl) { - this.keySourceUrl = keySourceUrl; - } - - /** - * Sets the {@code ssl_certificate_path} to be used within the generated - * {@link LoadBalancer} configuration. - * <p> - * If set to null, Brooklyn will use an auto generated path. - * <p> - * If {@link #getCertificateSourceUrl() certificateSourceUrl} is set * - * then Brooklyn will copy the certificate the destination. - * <p> - * Setting this field is useful if there is a {@code certificate} on the - * nginx machine you want to make use of. - */ - public String getCertificateDestination() { - return certificateDestination; - } - - public void setCertificateDestination(String certificateDestination) { - this.certificateDestination = certificateDestination; - } - - /** - * Sets the {@code ssl_certificate_key} path to be used within the generated - * {@link LoadBalancer} configuration. - * <p> - * If set to null, Brooklyn will use an auto generated path. - * <p> - * If {@link #getKeySourceUrl() keySourceUrl} is set then Brooklyn will copy the - * certificate to the destination. - * <p> - * Setting this field is useful if there is a {@code certificate_key} on the - * nginx machine you want to make use of. - */ - public String getKeyDestination() { - return keyDestination; - } - - public void setKeyDestination(String keyDestination) { - this.keyDestination = keyDestination; - } - - /** - * Whether the downstream server (if mapping) also expects https; default false. - */ - public boolean getTargetIsSsl() { - return targetIsSsl; - } - - public void setTargetIsSsl(boolean targetIsSsl) { - this.targetIsSsl = targetIsSsl; - } - - /** - * Whether to reuse SSL validation in the server (performance). - * <p> - * Corresponds to nginx setting {@code proxy_ssl_session_reuse on|off}. - */ - public boolean getReuseSessions() { - return reuseSessions; - } - - public void setReuseSessions(boolean reuseSessions) { - this.reuseSessions = reuseSessions; - } - - @Override - public int hashCode() { - return Objects.hashCode(certificateSourceUrl, keySourceUrl, certificateDestination, keyDestination, reuseSessions, targetIsSsl); - } - - @Override - public boolean equals(Object obj) { - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - ProxySslConfig other = (ProxySslConfig) obj; - - return Objects.equal(certificateSourceUrl, other.certificateSourceUrl) && - Objects.equal(certificateDestination, other.certificateDestination) && - Objects.equal(keyDestination, other.keyDestination) && - Objects.equal(keySourceUrl, other.keySourceUrl) && - Objects.equal(reuseSessions, other.reuseSessions) && - Objects.equal(targetIsSsl, other.targetIsSsl); - } -} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/77dff880/software/webapp/src/main/java/brooklyn/entity/proxy/nginx/NginxConfigFileGenerator.java ---------------------------------------------------------------------- diff --git a/software/webapp/src/main/java/brooklyn/entity/proxy/nginx/NginxConfigFileGenerator.java b/software/webapp/src/main/java/brooklyn/entity/proxy/nginx/NginxConfigFileGenerator.java deleted file mode 100644 index 1da0ed8..0000000 --- a/software/webapp/src/main/java/brooklyn/entity/proxy/nginx/NginxConfigFileGenerator.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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.entity.proxy.nginx; - -/** - * Generates a {@code server.conf} configuration file for an {@link NginxController}. - */ -public interface NginxConfigFileGenerator { - - /** - * Entry point for the generator. - * - * @return The contents of the {@code server.conf} file - */ - String generateConfigFile(NginxDriver driver, NginxController entity); - -} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/77dff880/software/webapp/src/main/java/brooklyn/entity/proxy/nginx/NginxController.java ---------------------------------------------------------------------- diff --git a/software/webapp/src/main/java/brooklyn/entity/proxy/nginx/NginxController.java b/software/webapp/src/main/java/brooklyn/entity/proxy/nginx/NginxController.java deleted file mode 100644 index 1fdba3e..0000000 --- a/software/webapp/src/main/java/brooklyn/entity/proxy/nginx/NginxController.java +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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.entity.proxy.nginx; - -import java.util.Map; - -import org.apache.brooklyn.catalog.Catalog; -import brooklyn.config.ConfigKey; -import brooklyn.entity.annotation.Effector; -import brooklyn.entity.annotation.EffectorParam; -import brooklyn.entity.basic.ConfigKeys; -import brooklyn.entity.basic.MethodEffector; -import brooklyn.entity.basic.SoftwareProcess; -import brooklyn.entity.proxy.AbstractController; -import brooklyn.entity.proxy.ProxySslConfig; -import brooklyn.entity.proxying.ImplementedBy; -import brooklyn.entity.trait.HasShortName; -import brooklyn.event.AttributeSensor; -import brooklyn.event.basic.BasicAttributeSensorAndConfigKey; -import brooklyn.event.basic.Sensors; -import brooklyn.util.flags.SetFromFlag; - -import com.google.common.collect.ImmutableMap; - -/** - * An entity that represents an Nginx proxy (e.g. for routing requests to servers in a cluster). - * <p> - * The default driver *builds* nginx from source (because binaries are not reliably available, esp not with sticky sessions). - * This requires gcc and other build tools installed. The code attempts to install them but inevitably - * this entity may be more finicky about the OS/image where it runs than others. - * <p> - * Paritcularly on OS X we require Xcode and command-line gcc installed and on the path. - * <p> - * See {@link http://library.linode.com/web-servers/nginx/configuration/basic} for useful info/examples - * of configuring nginx. - * <p> - * https configuration is supported, with the certificates providable on a per-UrlMapping basis or a global basis. - * (not supported to define in both places.) - * per-Url is useful if different certificates are used for different server names, - * or different ports if that is supported. - * see more info on Ssl in {@link ProxySslConfig}. - */ -@Catalog(name="Nginx Server", description="A single Nginx server. Provides HTTP and reverse proxy services", iconUrl="classpath:///nginx-logo.jpeg") -@ImplementedBy(NginxControllerImpl.class) -public interface NginxController extends AbstractController, HasShortName { - - MethodEffector<String> GET_CURRENT_CONFIGURATION = - new MethodEffector<String>(NginxController.class, "getCurrentConfiguration"); - - MethodEffector<Void> DEPLOY = - new MethodEffector<Void>(NginxController.class, "deploy"); - - @SetFromFlag("version") - ConfigKey<String> SUGGESTED_VERSION = - ConfigKeys.newConfigKeyWithDefault(SoftwareProcess.SUGGESTED_VERSION, "1.8.0"); - - @SetFromFlag("stickyVersion") - ConfigKey<String> STICKY_VERSION = ConfigKeys.newStringConfigKey( - "nginx.sticky.version", "Version of ngnix-sticky-module to be installed, if required", "1.2.5"); - - @SetFromFlag("pcreVersion") - ConfigKey<String> PCRE_VERSION = ConfigKeys.newStringConfigKey( - "pcre.version", "Version of PCRE to be installed, if required", "8.37"); - - @SetFromFlag("downloadUrl") - BasicAttributeSensorAndConfigKey<String> DOWNLOAD_URL = new BasicAttributeSensorAndConfigKey<String>( - SoftwareProcess.DOWNLOAD_URL, "http://nginx.org/download/nginx-${version}.tar.gz"); - - @SetFromFlag("downloadAddonUrls") - BasicAttributeSensorAndConfigKey<Map<String,String>> DOWNLOAD_ADDON_URLS = new BasicAttributeSensorAndConfigKey<Map<String,String>>( - SoftwareProcess.DOWNLOAD_ADDON_URLS, ImmutableMap.of( - "stickymodule", "https://bitbucket.org/nginx-goodies/nginx-sticky-module-ng/get/${addonversion}.tar.gz", - "pcre", "ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-${addonversion}.tar.gz")); - - @SetFromFlag("sticky") - ConfigKey<Boolean> STICKY = ConfigKeys.newBooleanConfigKey( - "nginx.sticky", "Whether to use sticky sessions", true); - - @SetFromFlag("httpPollPeriod") - ConfigKey<Long> HTTP_POLL_PERIOD = ConfigKeys.newLongConfigKey( - "nginx.sensorpoll.http", "Poll period (in milliseconds)", 1000L); - - @SetFromFlag("withLdOpt") - ConfigKey<String> WITH_LD_OPT = ConfigKeys.newStringConfigKey( - "nginx.install.withLdOpt", "String to pass in with --with-ld-opt=\"<val>\" (and for OS X has pcre auto-appended to this)", "-L /usr/local/lib"); - - @SetFromFlag("withCcOpt") - ConfigKey<String> WITH_CC_OPT = ConfigKeys.newStringConfigKey( - "nginx.install.withCcOpt", "String to pass in with --with-cc-opt=\"<val>\"", "-I /usr/local/include"); - - @SetFromFlag("configGenerator") - ConfigKey<NginxConfigFileGenerator> SERVER_CONF_GENERATOR = ConfigKeys.newConfigKey(NginxConfigFileGenerator.class, - "nginx.config.generator", "The server.conf generator class", new NginxDefaultConfigGenerator()); - - @SetFromFlag("configTemplate") - ConfigKey<String> SERVER_CONF_TEMPLATE_URL = NginxTemplateConfigGenerator.SERVER_CONF_TEMPLATE_URL; - - @SetFromFlag("staticContentArchive") - ConfigKey<String> STATIC_CONTENT_ARCHIVE_URL = ConfigKeys.newStringConfigKey( - "nginx.config.staticContentArchiveUrl", "The URL of an archive file of static content (To be copied to the server)"); - - BasicAttributeSensorAndConfigKey<String> ACCESS_LOG_LOCATION = new BasicAttributeSensorAndConfigKey<String>(String.class, - "nginx.log.access", "Nginx access log file location", "logs/access.log"); - - BasicAttributeSensorAndConfigKey<String> ERROR_LOG_LOCATION = new BasicAttributeSensorAndConfigKey<String>(String.class, - "nginx.log.error", "Nginx error log file location", "logs/error.log"); - - boolean isSticky(); - - @Effector(description="Gets the current server configuration (by brooklyn recalculating what the config should be); does not affect the server") - String getCurrentConfiguration(); - - @Effector(description="Deploys an archive of static content to the server") - void deploy(@EffectorParam(name="archiveUrl", description="The URL of the static content archive to deploy") String archiveUrl); - - String getConfigFile(); - - Iterable<UrlMapping> getUrlMappings(); - - boolean appendSslConfig(String id, StringBuilder out, String prefix, ProxySslConfig ssl, boolean sslBlock, boolean certificateBlock); - - public static final AttributeSensor<Boolean> NGINX_URL_ANSWERS_NICELY = Sensors.newBooleanSensor( "nginx.url.answers.nicely"); - public static final AttributeSensor<String> PID_FILE = Sensors.newStringSensor( "nginx.pid.file", "PID file"); - - public interface NginxControllerInternal { - public void doExtraConfigurationDuringStart(); - } - -}
