/***************************************************************************** * Copyright (c) 2012-2015 VMware, Inc. All Rights Reserved. * 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 com.vmware.bdd.cli.commands; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedHashMap; import java.util.List; import java.util.Set; import java.util.TreeSet; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.shell.core.CommandMarker; import org.springframework.shell.core.annotation.CliCommand; import org.springframework.shell.core.annotation.CliOption; import org.springframework.stereotype.Component; import com.vmware.bdd.apitypes.RackInfo; import com.vmware.bdd.cli.rest.TopologyRestClient; @Component public class TopologyCommands implements CommandMarker { @Autowired private TopologyRestClient topologyRestClient; @CliCommand(value = "topology upload", help = "Upload a rack-->hosts mapping topology file") public void upload( @CliOption(key = { "fileName" }, mandatory = true, help = "The topology file name") final String fileName, @CliOption(key = { "yes" }, mandatory = false, unspecifiedDefaultValue = "false", specifiedDefaultValue = "true", help = "Answer 'yes' to all Y/N questions. ") final boolean alwaysAnswerYes) { List<String> warningMsgList = new ArrayList<String>(); try { List<RackInfo> racks = readRackInfoFromFile(fileName); if (!duplicatedNameCheck(racks)) { RackInfo[] existingRackInfo = topologyRestClient.list(); if ((existingRackInfo != null) && (existingRackInfo.length > 0)) { warningMsgList.add(Constants.OVERWRITE_TOPOLOGY); } if (CommandsUtils.showWarningMsg(null, Constants.OUTPUT_OBJECT_TOPOLOGY, Constants.OUTPUT_OP_UPLOAD, warningMsgList, alwaysAnswerYes, null)) { topologyRestClient.upload(racks); CommandsUtils.printCmdSuccess(Constants.OUTPUT_OBJECT_TOPOLOGY, Constants.OUTPUT_OP_RESULT_UPLOAD); } } } catch (Exception e) { CommandsUtils.printCmdFailure(Constants.OUTPUT_OBJECT_TOPOLOGY, Constants.OUTPUT_OP_UPLOAD, Constants.OUTPUT_OP_RESULT_FAIL, e.getMessage()); return; } } private boolean duplicatedNameCheck(List<RackInfo> racks) { Set<String> checkRack = new TreeSet<String>(); Set<String> checkHosts = new TreeSet<String>(); for (RackInfo rack: racks) { if (checkRack.contains(rack.getName())) { CommandsUtils.printCmdFailure(Constants.OUTPUT_OBJECT_TOPOLOGY, Constants.OUTPUT_OP_UPLOAD, Constants.OUTPUT_OP_RESULT_FAIL, "Racks cannot be duplicated."); return true; } checkRack.add(rack.getName()); for (String hostName: rack.getHosts()) { if (checkHosts.contains(hostName)) { CommandsUtils.printCmdFailure(Constants.OUTPUT_OBJECT_TOPOLOGY, Constants.OUTPUT_OP_UPLOAD, Constants.OUTPUT_OP_RESULT_FAIL, "Remove duplicated hosts."); return true; } checkHosts.add(hostName); } } return false; } /* * The rack format is: rack_name: hostname1, hostname2,... */ private List<RackInfo> readRackInfoFromFile(String filePath) throws IOException, FileNotFoundException, CliException { FileInputStream fis = null; InputStreamReader inputStreamReader = null; BufferedReader bufferedReader = null; List<RackInfo> racksInfo = new ArrayList<RackInfo>(); try { fis = new FileInputStream(filePath); inputStreamReader = new InputStreamReader(fis, "UTF-8"); bufferedReader = new BufferedReader(inputStreamReader); String line = ""; int lineNum = 1; while ((line = bufferedReader.readLine()) != null) { int idx = line.indexOf("#"); if ( idx >= 0 ) { line = line.substring(0, idx); } line = line.trim(); if (line.isEmpty()) { lineNum++; continue; } else { String formatErrMsg = "wrong topology format at line " + lineNum + ".\n" + Constants.TOPLOGY_FORMAT; String[] rackHosts = line.split(":"); if (rackHosts.length < 2 || rackHosts[0].trim().isEmpty()) { throw new CliException(formatErrMsg); } String hostsInfo = line.substring(line.indexOf(":") + 1).trim(); if (hostsInfo.isEmpty()) { throw new CliException(formatErrMsg); } String[] hosts = hostsInfo.split(","); int numOfNonEmptyHosts = 0; for (int i = 0; i < hosts.length; i++) { hosts[i] = hosts[i].trim(); if (!hosts[i].isEmpty()) { hosts[numOfNonEmptyHosts++] = hosts[i]; } } if (numOfNonEmptyHosts == 0) { throw new CliException(formatErrMsg); } lineNum++; RackInfo rackInfo = new RackInfo(); rackInfo.setName(rackHosts[0].trim()); rackInfo.setHosts(Arrays.asList(hosts).subList(0, numOfNonEmptyHosts)); racksInfo.add(rackInfo); } } } finally { if (fis != null) { fis.close(); } if (inputStreamReader != null) { inputStreamReader.close(); } if (bufferedReader != null) { bufferedReader.close(); } } return racksInfo; } @CliCommand(value = "topology list", help = "List a rack-->hosts mapping topology") public void list() { try { RackInfo[] racksInfo = topologyRestClient.list(); prettyOutputRackInfo(racksInfo); } catch (Exception e) { CommandsUtils.printCmdFailure(Constants.OUTPUT_OBJECT_TOPOLOGY, Constants.OUTPUT_OP_LIST, Constants.OUTPUT_OP_RESULT_FAIL, e.getMessage()); } } private void prettyOutputRackInfo(RackInfo[] racks) throws Exception { if (racks != null) { LinkedHashMap<String, List<String>> rackInfoColumnNamesWithGetMethodNames = new LinkedHashMap<String, List<String>>(); rackInfoColumnNamesWithGetMethodNames.put( Constants.FORMAT_TABLE_COLUMN_RACK, Arrays.asList("getName")); rackInfoColumnNamesWithGetMethodNames.put( Constants.FORMAT_TABLE_COLUMN_HOSTS, Arrays.asList("getHosts")); CommandsUtils.printInTableFormat( rackInfoColumnNamesWithGetMethodNames, racks, Constants.OUTPUT_INDENT); } } }