/*
* 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.mongodb.sharding;
import static org.apache.brooklyn.core.sensor.DependentConfiguration.attributeWhenReady;
import java.util.Collection;
import java.util.List;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.EntitySpec;
import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.api.policy.PolicySpec;
import org.apache.brooklyn.core.entity.AbstractEntity;
import org.apache.brooklyn.core.entity.Attributes;
import org.apache.brooklyn.core.entity.Entities;
import org.apache.brooklyn.core.entity.lifecycle.Lifecycle;
import org.apache.brooklyn.core.entity.lifecycle.ServiceStateLogic;
import org.apache.brooklyn.core.entity.lifecycle.ServiceStateLogic.ServiceNotUpLogic;
import org.apache.brooklyn.core.entity.trait.Startable;
import org.apache.brooklyn.enricher.stock.Enrichers;
import org.apache.brooklyn.entity.group.AbstractMembershipTrackingPolicy;
import org.apache.brooklyn.entity.group.DynamicCluster;
import org.apache.brooklyn.util.exceptions.Exceptions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.brooklyn.entity.nosql.mongodb.MongoDBAuthenticationMixins;
import org.apache.brooklyn.entity.nosql.mongodb.MongoDBAuthenticationUtils;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
public class MongoDBShardedDeploymentImpl extends AbstractEntity implements MongoDBShardedDeployment, MongoDBAuthenticationMixins {
@SuppressWarnings("unused")
private static final Logger LOG = LoggerFactory.getLogger(MongoDBShardedDeploymentImpl.class);
@Override
public void init() {
super.init();
EntitySpec<MongoDBConfigServerCluster> configServerClusterSpec = EntitySpec.create(MongoDBConfigServerCluster.class)
.configure(MongoDBConfigServerCluster.MEMBER_SPEC, getConfig(MONGODB_CONFIG_SERVER_SPEC))
.configure(DynamicCluster.INITIAL_SIZE, getConfig(CONFIG_CLUSTER_SIZE));
MongoDBAuthenticationUtils.setAuthenticationConfig(configServerClusterSpec, this);
sensors().set(CONFIG_SERVER_CLUSTER, addChild(configServerClusterSpec));
EntitySpec<MongoDBRouterCluster> routerClusterSpec = EntitySpec.create(MongoDBRouterCluster.class)
.configure(MongoDBRouterCluster.MEMBER_SPEC, getConfig(MONGODB_ROUTER_SPEC))
.configure(DynamicCluster.INITIAL_SIZE, getConfig(INITIAL_ROUTER_CLUSTER_SIZE))
.configure(MongoDBRouter.CONFIG_SERVERS, attributeWhenReady(getAttribute(CONFIG_SERVER_CLUSTER), MongoDBConfigServerCluster.CONFIG_SERVER_ADDRESSES));
MongoDBAuthenticationUtils.setAuthenticationConfig(routerClusterSpec, this);
sensors().set(ROUTER_CLUSTER, addChild(routerClusterSpec));
EntitySpec<MongoDBShardCluster> shardClusterSpec = EntitySpec.create(MongoDBShardCluster.class)
.configure(MongoDBShardCluster.MEMBER_SPEC, getConfig(MONGODB_REPLICA_SET_SPEC))
.configure(DynamicCluster.INITIAL_SIZE, getConfig(INITIAL_SHARD_CLUSTER_SIZE));
MongoDBAuthenticationUtils.setAuthenticationConfig(shardClusterSpec, this);
sensors().set(SHARD_CLUSTER, addChild(shardClusterSpec));
enrichers().add(Enrichers.builder()
.propagating(MongoDBConfigServerCluster.CONFIG_SERVER_ADDRESSES)
.from(getAttribute(CONFIG_SERVER_CLUSTER))
.build());
// Advertise even if default are used (root password is set in MongoDBAuthenticationUtils)
sensors().set(MongoDBAuthenticationMixins.AUTHENTICATION_DATABASE, config().get(MongoDBAuthenticationMixins.AUTHENTICATION_DATABASE));
sensors().set(MongoDBAuthenticationMixins.ROOT_USERNAME, config().get(MongoDBAuthenticationMixins.ROOT_USERNAME));
ServiceNotUpLogic.updateNotUpIndicator(this, Attributes.SERVICE_STATE_ACTUAL, "stopped");
}
@Override
public void start(Collection<? extends Location> locations) {
ServiceStateLogic.setExpectedState(this, Lifecycle.STARTING);
try {
final MongoDBRouterCluster routers = getAttribute(ROUTER_CLUSTER);
final MongoDBShardCluster shards = getAttribute(SHARD_CLUSTER);
List<DynamicCluster> clusters = ImmutableList.of(getAttribute(CONFIG_SERVER_CLUSTER), routers, shards);
Entities.invokeEffectorList(this, clusters, Startable.START, ImmutableMap.of("locations", locations))
.get();
if (getConfigRaw(MongoDBShardedDeployment.CO_LOCATED_ROUTER_GROUP, true).isPresent()) {
policies().add(PolicySpec.create(ColocatedRouterTrackingPolicy.class)
.displayName("Co-located router tracker")
.configure("group", getConfig(MongoDBShardedDeployment.CO_LOCATED_ROUTER_GROUP)));
}
ServiceNotUpLogic.clearNotUpIndicator(this, Attributes.SERVICE_STATE_ACTUAL);
ServiceStateLogic.setExpectedState(this, Lifecycle.RUNNING);
} catch (Exception e) {
ServiceStateLogic.setExpectedState(this, Lifecycle.ON_FIRE);
// no need to log here; the effector invocation should do that
throw Exceptions.propagate(e);
}
}
public static class ColocatedRouterTrackingPolicy extends AbstractMembershipTrackingPolicy {
@Override
protected void onEntityAdded(Entity member) {
MongoDBAuthenticationUtils.setAuthenticationConfig(member, entity);
MongoDBRouterCluster cluster = entity.getAttribute(ROUTER_CLUSTER);
cluster.addMember(member.getAttribute(CoLocatedMongoDBRouter.ROUTER));
}
@Override
protected void onEntityRemoved(Entity member) {
MongoDBRouterCluster cluster = entity.getAttribute(ROUTER_CLUSTER);
cluster.removeMember(member.getAttribute(CoLocatedMongoDBRouter.ROUTER));
}
}
@Override
public void stop() {
ServiceStateLogic.setExpectedState(this, Lifecycle.STOPPING);
try {
Entities.invokeEffectorList(this, ImmutableList.of(getAttribute(CONFIG_SERVER_CLUSTER), getAttribute(ROUTER_CLUSTER),
getAttribute(SHARD_CLUSTER)), Startable.STOP).get();
} catch (Exception e) {
ServiceStateLogic.setExpectedState(this, Lifecycle.ON_FIRE);
throw Exceptions.propagate(e);
}
ServiceStateLogic.setExpectedState(this, Lifecycle.STOPPED);
ServiceNotUpLogic.updateNotUpIndicator(this, Attributes.SERVICE_STATE_ACTUAL, "stopped");
}
@Override
public void restart() {
throw new UnsupportedOperationException();
}
@Override
public MongoDBConfigServerCluster getConfigCluster() {
return getAttribute(CONFIG_SERVER_CLUSTER);
}
@Override
public MongoDBRouterCluster getRouterCluster() {
return getAttribute(ROUTER_CLUSTER);
}
@Override
public MongoDBShardCluster getShardCluster() {
return getAttribute(SHARD_CLUSTER);
}
}