/*
* 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 org.apache.brooklyn.entity.software.base;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.location.MachineLocation;
import org.apache.brooklyn.api.location.MachineProvisioningLocation;
import org.apache.brooklyn.api.location.PortRange;
import org.apache.brooklyn.api.mgmt.TaskAdaptable;
import org.apache.brooklyn.config.ConfigKey;
import org.apache.brooklyn.core.entity.AbstractEntity;
import org.apache.brooklyn.core.entity.trait.StartableMethods;
import org.apache.brooklyn.core.location.LocationConfigKeys;
import org.apache.brooklyn.entity.software.base.lifecycle.MachineLifecycleEffectorTasks;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.common.reflect.TypeToken;
import org.apache.brooklyn.util.collections.MutableSet;
import org.apache.brooklyn.util.core.flags.TypeCoercions;
import org.apache.brooklyn.util.core.task.DynamicTasks;
import org.apache.brooklyn.util.guava.Maybe;
public class SameServerDriverLifecycleEffectorTasks extends MachineLifecycleEffectorTasks {
private static final Logger LOG = LoggerFactory.getLogger(SameServerDriverLifecycleEffectorTasks.class);
@Override
protected SameServerEntityImpl entity() {
return (SameServerEntityImpl) super.entity();
}
/**
* @return the ports that this entity wants to use, aggregated for all its child entities.
* @see InboundPortsUtils#getRequiredOpenPorts(Entity, Boolean, String)
*/
protected Collection<Integer> getRequiredOpenPorts() {
Set<Integer> result = Sets.newLinkedHashSet();
result.addAll(getRequiredOpenPorts(entity()));
LOG.debug("getRequiredOpenPorts detected aggregated default {} for {}", result, this);
return result;
}
/** @return the ports required for a specific child entity */
protected Collection<Integer> getRequiredOpenPorts(Entity entity) {
Set<Integer> ports = MutableSet.of();
addRequiredOpenPortsRecursively(entity, ports);
return ports;
}
private void addRequiredOpenPortsRecursively(Entity entity, Set<Integer> ports) {
ports.addAll(entity.getConfig(SameServerEntity.REQUIRED_OPEN_LOGIN_PORTS));
Boolean portsAutoInfer = entity.getConfig(SameServerEntity.INBOUND_PORTS_AUTO_INFER);
String portsRegex = entity.getConfig(SameServerEntity.INBOUND_PORTS_CONFIG_REGEX);
ports.addAll(InboundPortsUtils.getRequiredOpenPorts(entity, portsAutoInfer, portsRegex));
LOG.debug("getRequiredOpenPorts detected default {} for {}", ports, entity);
for (Entity child : entity.getChildren()) {
addRequiredOpenPortsRecursively(child, ports);
}
}
@SuppressWarnings("unchecked")
@Override
protected Map<String, Object> obtainProvisioningFlags(MachineProvisioningLocation<?> location) {
Map<String, Object> result = super.obtainProvisioningFlags(location);
result.putAll(obtainProvisioningFlags(entity(), location));
Collection<Integer> ports = getRequiredOpenPorts();
if (result.containsKey("inboundPorts")) {
ports.addAll((Collection<Integer>) result.get("inboundPorts"));
}
if (!ports.isEmpty()) {
result.put("inboundPorts", ports);
}
result.put(LocationConfigKeys.CALLER_CONTEXT.getName(), entity());
return result;
}
/** @return provisioning flags for the given entity */
@SuppressWarnings({ "rawtypes", "unchecked" })
protected Map<String,Object> obtainProvisioningFlags(Entity entity, MachineProvisioningLocation location) {
Map<String,Object> result = Maps.newLinkedHashMap();
result.putAll(Maps.newLinkedHashMap(location.getProvisioningFlags(ImmutableList.of(entity.getEntityType().getName()))));
result.putAll(entity.getConfig(SameServerEntity.PROVISIONING_PROPERTIES));
for (Entity child : entity.getChildren()) {
result.putAll(obtainProvisioningFlags(child, location));
}
return result;
}
@Override
protected String startProcessesAtMachine(Supplier<MachineLocation> machineS) {
DynamicTasks.queueIfPossible(StartableMethods.startingChildren(entity(), machineS.get()))
.orSubmitAsync(entity())
.getTask()
.getUnchecked();
DynamicTasks.waitForLast();
return "children started";
}
// Also see stopProcessesAtMachine in SoftwareProcessDriverLifecycleEffectorTasks.
// Any fixes made there should probably be applied here too.
@Override
protected String stopProcessesAtMachine() {
TaskAdaptable<?> children = StartableMethods.stoppingChildren(entity());
DynamicTasks.queue(children);
Exception childException = null;
try {
DynamicTasks.waitForLast();
} catch (Exception e) {
childException = e;
}
try {
children.asTask().get();
} catch (Exception e) {
childException = e;
LOG.debug("Error stopping children; continuing and will rethrow if no other errors", e);
}
if (childException != null)
throw new IllegalStateException("error stopping child", childException);
return "children stopped";
}
}