org.apache.brooklyn.entity.nosql.redis.RedisClusterImpl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of brooklyn-software-nosql Show documentation
Show all versions of brooklyn-software-nosql Show documentation
Brooklyn entities for NoSQL data store software entities
/*
* 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.nosql.redis;
import java.util.Collection;
import java.util.List;
import org.apache.brooklyn.api.entity.EntitySpec;
import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.api.mgmt.Task;
import org.apache.brooklyn.api.sensor.AttributeSensor;
import org.apache.brooklyn.core.entity.AbstractEntity;
import org.apache.brooklyn.core.entity.Attributes;
import org.apache.brooklyn.core.entity.lifecycle.Lifecycle;
import org.apache.brooklyn.core.entity.lifecycle.ServiceStateLogic;
import org.apache.brooklyn.core.entity.lifecycle.ServiceStateLogic.ComputeServiceIndicatorsFromChildrenAndMembers;
import org.apache.brooklyn.core.entity.lifecycle.ServiceStateLogic.ServiceProblemsLogic;
import org.apache.brooklyn.core.sensor.DependentConfiguration;
import org.apache.brooklyn.core.sensor.Sensors;
import org.apache.brooklyn.enricher.stock.Enrichers;
import org.apache.brooklyn.entity.group.DynamicCluster;
import org.apache.brooklyn.entity.software.base.SoftwareProcess;
import org.apache.brooklyn.util.collections.QuorumCheck.QuorumChecks;
import org.apache.brooklyn.util.exceptions.CompoundRuntimeException;
import org.apache.brooklyn.util.exceptions.Exceptions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
public class RedisClusterImpl extends AbstractEntity implements RedisCluster {
private static final AttributeSensor MASTER = Sensors.newSensor(RedisStore.class, "redis.master");
private static final AttributeSensor SLAVES = Sensors.newSensor(DynamicCluster.class, "redis.slaves");
public RedisClusterImpl() {
}
@Override
public RedisStore getMaster() {
return getAttribute(MASTER);
}
@Override
public DynamicCluster getSlaves() {
return getAttribute(SLAVES);
}
@Override
public void init() {
super.init();
RedisStore master = addChild(EntitySpec.create(RedisStore.class));
sensors().set(MASTER, master);
DynamicCluster slaves = addChild(EntitySpec.create(DynamicCluster.class)
.configure(DynamicCluster.MEMBER_SPEC, EntitySpec.create(RedisSlave.class).configure(RedisSlave.MASTER, master)
.configure(SoftwareProcess.CUSTOMIZE_LATCH, DependentConfiguration.attributeWhenReady(master, Attributes.SERVICE_UP))));
sensors().set(SLAVES, slaves);
enrichers().add(Enrichers.builder()
.propagating(RedisStore.HOSTNAME, RedisStore.ADDRESS, RedisStore.SUBNET_HOSTNAME, RedisStore.SUBNET_ADDRESS, RedisStore.REDIS_PORT)
.from(master)
.build());
}
@Override
protected void initEnrichers() {
super.initEnrichers();
ServiceStateLogic.newEnricherFromChildrenUp().
checkChildrenOnly().
requireUpChildren(QuorumChecks.all()).
configure(ComputeServiceIndicatorsFromChildrenAndMembers.IGNORE_ENTITIES_WITH_THESE_SERVICE_STATES, ImmutableSet.of()).
addTo(this);
}
@Override
public void start(Collection extends Location> locations) {
ServiceStateLogic.setExpectedState(this, Lifecycle.STARTING);
ServiceProblemsLogic.clearProblemsIndicator(this, START);
try {
doStart(locations);
ServiceStateLogic.setExpectedState(this, Lifecycle.RUNNING);
} catch (Exception e) {
ServiceProblemsLogic.updateProblemsIndicator(this, START, "Start failed with error: "+e);
ServiceStateLogic.setExpectedState(this, Lifecycle.ON_FIRE);
throw Exceptions.propagate(e);
}
}
private void doStart(Collection extends Location> locations) {
// Start the master and slaves asynchronously (the slave has a LAUNCH_LATCH on master to ensure it is available before the slaves are launched)
Task masterStartTask = getMaster().invoke(RedisStore.START, ImmutableMap.of("locations", ImmutableList.copyOf(locations)));
Task slaveStartTask = getSlaves().invoke(DynamicCluster.START, ImmutableMap.of("locations", ImmutableList.copyOf(locations)));
// Wait for both master and slave to start before returning
masterStartTask.getUnchecked();
slaveStartTask.getUnchecked();
}
@Override
public void stop() {
ServiceStateLogic.setExpectedState(this, Lifecycle.STOPPING);
try {
doStop();
ServiceStateLogic.setExpectedState(this, Lifecycle.STOPPED);
} catch (Exception e) {
ServiceProblemsLogic.updateProblemsIndicator(this, STOP, "Stop failed with error: "+e);
ServiceStateLogic.setExpectedState(this, Lifecycle.ON_FIRE);
throw Exceptions.propagate(e);
}
}
private void doStop() {
StringBuilder message = new StringBuilder();
List exceptions = Lists.newLinkedList();
try {
getSlaves().invoke(DynamicCluster.STOP, ImmutableMap.of()).getUnchecked();
} catch (Exception e) {
message.append("Failed to stop Redis slaves");
exceptions.add(e);
}
try {
getMaster().invoke(RedisStore.STOP, ImmutableMap.of()).getUnchecked();
} catch (Exception e) {
message.append((message.length() == 0) ? "Failed to stop Redis master" : " and master");
exceptions.add(e);
}
if (!exceptions.isEmpty()) {
throw new CompoundRuntimeException(message.toString(), exceptions);
}
}
@Override
public void restart() {
throw new UnsupportedOperationException();
}
}