| // 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.cloudstack.outofbandmanagement.driver.ipmitool; |
| |
| import com.cloud.utils.StringUtils; |
| import com.cloud.utils.exception.CloudRuntimeException; |
| import com.google.common.base.Strings; |
| import com.google.common.collect.ImmutableList; |
| import com.google.common.collect.ImmutableMap; |
| import org.apache.cloudstack.outofbandmanagement.OutOfBandManagement; |
| import org.apache.cloudstack.outofbandmanagement.driver.OutOfBandManagementDriverResponse; |
| import org.apache.cloudstack.utils.process.ProcessResult; |
| import org.apache.cloudstack.utils.process.ProcessRunner; |
| import org.apache.log4j.Logger; |
| import org.joda.time.Duration; |
| |
| import java.util.ArrayList; |
| import java.util.List; |
| import java.util.concurrent.ExecutorService; |
| |
| public final class IpmitoolWrapper { |
| public static final Logger LOG = Logger.getLogger(IpmitoolWrapper.class); |
| |
| private final ProcessRunner RUNNER; |
| |
| public IpmitoolWrapper(ExecutorService executor) { |
| this.RUNNER = new ProcessRunner(executor); |
| } |
| |
| public String parsePowerCommand(OutOfBandManagement.PowerOperation operation) { |
| if (operation == null) { |
| throw new IllegalStateException("Invalid power operation requested"); |
| } |
| switch (operation) { |
| case ON: |
| case OFF: |
| case CYCLE: |
| case RESET: |
| case SOFT: |
| case STATUS: |
| break; |
| default: |
| throw new IllegalStateException("Invalid power operation requested"); |
| } |
| return operation.toString().toLowerCase(); |
| } |
| |
| public OutOfBandManagement.PowerState parsePowerState(final String standardOutput) { |
| if (Strings.isNullOrEmpty(standardOutput)) { |
| return OutOfBandManagement.PowerState.Unknown; |
| } |
| if (standardOutput.equals("Chassis Power is on")) { |
| return OutOfBandManagement.PowerState.On; |
| } else if (standardOutput.equals("Chassis Power is off")) { |
| return OutOfBandManagement.PowerState.Off; |
| } |
| return OutOfBandManagement.PowerState.Unknown; |
| } |
| |
| public List<String> getIpmiToolCommandArgs(final String ipmiToolPath, final String ipmiInterface, final String retries, |
| final ImmutableMap<OutOfBandManagement.Option, String> options, String... commands) { |
| |
| final ImmutableList.Builder<String> ipmiToolCommands = ImmutableList.<String>builder() |
| .add(ipmiToolPath) |
| .add("-I") |
| .add(ipmiInterface) |
| .add("-R") |
| .add(retries) |
| .add("-v"); |
| |
| if (options != null) { |
| for (ImmutableMap.Entry<OutOfBandManagement.Option, String> option : options.entrySet()) { |
| switch (option.getKey()) { |
| case ADDRESS: |
| ipmiToolCommands.add("-H"); |
| break; |
| case PORT: |
| ipmiToolCommands.add("-p"); |
| break; |
| case USERNAME: |
| ipmiToolCommands.add("-U"); |
| break; |
| case PASSWORD: |
| ipmiToolCommands.add("-P"); |
| break; |
| default: |
| continue; |
| } |
| ipmiToolCommands.add(option.getValue()); |
| } |
| } |
| for (String command : commands) { |
| ipmiToolCommands.add(command); |
| } |
| return ipmiToolCommands.build(); |
| } |
| |
| public String findIpmiUser(final String usersList, final String username) { |
| /** |
| * Expected usersList string contains legends on first line and users on rest |
| * ID Name Callin Link Auth IPMI Msg Channel Priv Limit |
| * 1 admin true true true ADMINISTRATOR |
| */ |
| |
| // Assuming user 'ID' index on 1st position |
| int idIndex = 0; |
| |
| // Assuming user 'Name' index on 2nd position |
| int usernameIndex = 1; |
| |
| final String[] lines = usersList.split("\\r?\\n"); |
| if (lines.length < 2) { |
| throw new CloudRuntimeException("Error parsing user ID from ipmi user listing"); |
| } |
| // Find user and name indexes from the 1st line if not on default position |
| final String[] legends = lines[0].split(" +"); |
| for (int idx = 0; idx < legends.length; idx++) { |
| if (legends[idx].equals("ID")) { |
| idIndex = idx; |
| } |
| if (legends[idx].equals("Name")) { |
| usernameIndex = idx; |
| } |
| } |
| // Find user 'ID' based on provided username and ID/Name positions |
| String userId = null; |
| for (int idx = 1; idx < lines.length; idx++) { |
| final String[] words = lines[idx].split(" +"); |
| if (usernameIndex < words.length && idIndex < words.length) { |
| if (words[usernameIndex].equals(username)) { |
| userId = words[idIndex]; |
| } |
| } |
| } |
| return userId; |
| } |
| |
| public OutOfBandManagementDriverResponse executeCommands(final List<String> commands) { |
| return executeCommands(commands, ProcessRunner.DEFAULT_MAX_TIMEOUT); |
| } |
| |
| public OutOfBandManagementDriverResponse executeCommands(final List<String> commands, final Duration timeOut) { |
| final ProcessResult result = RUNNER.executeCommands(commands, timeOut); |
| if (LOG.isTraceEnabled()) { |
| List<String> cleanedCommands = new ArrayList<String>(); |
| int maskNextCommand = 0; |
| for (String command : commands) { |
| if (maskNextCommand > 0) { |
| cleanedCommands.add("**** "); |
| maskNextCommand--; |
| continue; |
| } |
| if (command.equalsIgnoreCase("-P")) { |
| maskNextCommand = 1; |
| } else if (command.toLowerCase().endsWith("password")) { |
| maskNextCommand = 2; |
| } |
| cleanedCommands.add(command); |
| } |
| LOG.trace("Executed ipmitool process with commands: " + StringUtils.join(cleanedCommands, ", ") + |
| "\nIpmitool execution standard output: " + result.getStdOutput() + |
| "\nIpmitool execution error output: " + result.getStdError()); |
| } |
| return new OutOfBandManagementDriverResponse(result.getStdOutput(), result.getStdError(), result.isSuccess()); |
| } |
| } |