/*
* Copyright 2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.xd.yarn;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Properties;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;
import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
import org.springframework.boot.cli.command.AbstractCommand;
import org.springframework.boot.cli.command.status.ExitStatus;
import org.springframework.boot.cli.util.Log;
import org.springframework.core.io.FileSystemResource;
/**
* A custom command for listing the http ports used by admin servers.
*
* @author Thomas Risberg
*/
@SuppressWarnings("unchecked")
public class XdYarnAdminInfoCommand extends AbstractCommand {
private static final String XD_YARN_ADMIN_INFO_COMMAND_NAME = "admininfo";
private static final String XD_YARN_ADMIN_INFO_COMMAND_DESC = "List http host and port info for the admin servers";
public static final String ZK_NAMESPACE = "zk.namespace";
public static final String ZK_CLIENT_CONNECT = "zk.client.connect";
public static final String XD_ADMINS = "admins";
private String zkNamespace = "xd";
private String zkClientConnect = "localhost:2181";
private ZooKeeper zk;
/**
* Call super constructor for new {@link org.springframework.boot.cli.command.AbstractCommand} instance.
*/
public XdYarnAdminInfoCommand() {
super(XD_YARN_ADMIN_INFO_COMMAND_NAME, XD_YARN_ADMIN_INFO_COMMAND_DESC);
}
@Override
public ExitStatus run(String... args) throws InterruptedException {
try {
init();
Log.info("Admins: " + getAdmins());
}
catch (IOException e) {
Log.error("IOException accessing admin info: " + e.getMessage());
}
catch (KeeperException e) {
Log.error("KeeperException accessing admin info: " + e.getMessage());
}
finally {
close();
}
return ExitStatus.OK;
}
private void init() throws IOException {
YamlPropertiesFactoryBean ypfb = new YamlPropertiesFactoryBean();
ypfb.setResources(new FileSystemResource(System.getProperty("spring.config.location")));
Properties conf = ypfb.getObject();
if (conf.containsKey(ZK_NAMESPACE)) {
zkNamespace = (String) conf.get(ZK_NAMESPACE);
}
if (conf.containsKey(ZK_CLIENT_CONNECT)) {
zkClientConnect = (String) conf.get(ZK_CLIENT_CONNECT);
}
zk = new ZooKeeper(zkClientConnect, 5000,
new Watcher() {
@Override
public void process(WatchedEvent event) {
}
});
}
private void close() throws InterruptedException {
if (zk != null) {
zk.close();
}
}
private List<String> getAdmins() throws KeeperException {
String adminsPath = "/" + zkNamespace + "/" + XD_ADMINS;
List<String> results = new ArrayList<String>();
try {
Stat stat = zk.exists(adminsPath, false);
if (stat != null) {
List<String> admins = zk.getChildren(adminsPath, false);
for (String admin : admins) {
byte[] data = zk.getData(adminsPath + "/" + admin, false, null);
try {
HashMap<String,Object> dataValues =
new ObjectMapper().readValue(new String(data), HashMap.class);
results.add("http://" + dataValues.get("host") + ":" + dataValues.get("port"));
} catch (IOException e) {
Log.error("IOException while retrieving data for " + admin + ": " + e.getMessage());
}
}
}
} catch (InterruptedException ignore) {}
return results;
}
}