All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.hadoop.ha.PowerShellFencer Maven / Gradle / Ivy

The newest version!
/**
 * 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.hadoop.ha;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.InetSocketAddress;
import java.nio.charset.StandardCharsets;

import org.apache.hadoop.conf.Configured;
import org.apache.hadoop.util.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Fencer method that uses PowerShell to remotely connect to a machine and kill
 * the required process. This only works in Windows.
 *
 * Fencing method uses PowerShell command. It should be specified
 * in the fencing configuration like:
* powershell(NameNode) * * The argument passed to this fencer should be a unique string in the * "CommandLine" attribute for the "java.exe" process. For example, the full * path for the Namenode: "org.apache.hadoop.hdfs.server.namenode.NameNode". * The administrator can also shorten the name to "Namenode" if it's unique. */ public class PowerShellFencer extends Configured implements FenceMethod { private static final Logger LOG = LoggerFactory.getLogger(PowerShellFencer .class); @Override public void checkArgs(String argStr) throws BadFencingConfigurationException { LOG.info("The parameter for the PowerShell fencer is " + argStr); } @Override public boolean tryFence(HAServiceTarget target, String argsStr) throws BadFencingConfigurationException { String processName = argsStr; InetSocketAddress serviceAddr = target.getAddress(); String hostname = serviceAddr.getHostName(); // Use PowerShell to kill a remote process String ps1script = buildPSScript(processName, hostname); if (ps1script == null) { LOG.error("Cannot build PowerShell script"); return false; } // Execute PowerShell script LOG.info("Executing " + ps1script); ProcessBuilder builder = new ProcessBuilder("powershell.exe", ps1script); Process p = null; try { p = builder.start(); p.getOutputStream().close(); } catch (IOException e) { LOG.warn("Unable to execute " + ps1script, e); return false; } // Pump logs to stderr StreamPumper errPumper = new StreamPumper( LOG, "fencer", p.getErrorStream(), StreamPumper.StreamType.STDERR); errPumper.start(); StreamPumper outPumper = new StreamPumper( LOG, "fencer", p.getInputStream(), StreamPumper.StreamType.STDOUT); outPumper.start(); // Waiting for the process to finish int rc = 0; try { rc = p.waitFor(); errPumper.join(); outPumper.join(); } catch (InterruptedException ie) { LOG.warn("Interrupted while waiting for fencing command: " + ps1script); return false; } return rc == 0; } /** * Build a PowerShell script to kill a java.exe process in a remote machine. * * @param processName Name of the process to kill. This is an attribute in * CommandLine. * @param host Host where the process is. * @return Path of the PowerShell script. */ private String buildPSScript(final String processName, final String host) { LOG.info( "Building PowerShell script to kill " + processName + " at " + host); String ps1script = null; BufferedWriter writer = null; try { File file = File.createTempFile("temp-fence-command", ".ps1"); file.deleteOnExit(); FileOutputStream fos = new FileOutputStream(file, false); OutputStreamWriter osw = new OutputStreamWriter(fos, StandardCharsets.UTF_8); writer = new BufferedWriter(osw); // Filter to identify the Namenode process String filter = StringUtils.join(" and ", new String[] { "Name LIKE '%java.exe%'", "CommandLine LIKE '%" + processName+ "%'"}); // Identify the process String cmd = "Get-WmiObject Win32_Process"; cmd += " -Filter \"" + filter + "\""; // Remote location cmd += " -Computer " + host; // Kill it cmd += " |% { $_.Terminate() }"; LOG.info("PowerShell command: " + cmd); writer.write(cmd); writer.flush(); ps1script = file.getAbsolutePath(); } catch (IOException ioe) { LOG.error("Cannot create PowerShell script", ioe); } finally { if (writer != null) { try { writer.close(); } catch (IOException ioe) { LOG.error("Cannot close PowerShell script", ioe); } } } return ps1script; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy