/*************************************************************************** * 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.service.sp; import java.util.ArrayList; import java.util.List; import java.util.Map; import com.vmware.aurora.composition.DiskSchema; import com.vmware.bdd.utils.AuAssert; import com.vmware.bdd.utils.Constants; import org.apache.log4j.Logger; import com.vmware.aurora.composition.IPrePostPowerOn; import com.vmware.aurora.composition.NetworkSchema; import com.vmware.aurora.composition.NetworkSchemaUtil; import com.vmware.aurora.vc.VcCache; import com.vmware.aurora.vc.VcVirtualMachine; import com.vmware.aurora.vc.vcservice.VcContext; import com.vmware.aurora.vc.vcservice.VcSession; import com.vmware.bdd.apitypes.Priority; import com.vmware.bdd.utils.VcVmUtil; import com.vmware.vim.binding.impl.vim.vm.ConfigSpecImpl; import com.vmware.vim.binding.vim.option.OptionValue; import com.vmware.vim.binding.vim.vm.ConfigSpec; public class ReplaceVmPrePowerOn implements IPrePostPowerOn { private static final Logger logger = Logger .getLogger(ReplaceVmPrePowerOn.class); private String oldVmId; private String newName; private Priority ioShares; private VcVirtualMachine vm; private NetworkSchema networkSchema; private DiskSchema diskSchema; private boolean ha; private boolean ft; private boolean isMapDistro; public ReplaceVmPrePowerOn(String vmId, String newName, Priority ioShares, NetworkSchema networkSchema, DiskSchema diskSchema, boolean ha, boolean ft, boolean isMapDistro) { this.oldVmId = vmId; this.newName = newName; this.ioShares = ioShares; this.networkSchema = networkSchema; this.diskSchema = diskSchema; this.ha = ha; this.ft = ft; this.isMapDistro = isMapDistro; } private OptionValue[] getVhmExtraConfigs(VcVirtualMachine oldVm) { List<OptionValue> options = new ArrayList<OptionValue>(); for (OptionValue option : oldVm.getConfig().getExtraConfig()) { if (option.getKey().startsWith("vhmInfo")) { options.add(option); } } return options.toArray(new OptionValue[options.size()]); } private void copyNicSettings(VcVirtualMachine oldVm) throws Exception { ConfigSpec configSpec = new ConfigSpecImpl(); NetworkSchemaUtil.copyMacAddresses(configSpec, oldVm, vm, networkSchema); vm.reconfigure(configSpec); } @Override public Void call() throws Exception { final VcVirtualMachine oldVm = VcCache.getIgnoreMissing(oldVmId); if (oldVm == null) { logger.info("vm " + oldVmId + " is not found in VC, ignore this disk fix."); return null; } // delete old vm and rename the replacement VM to its original name VcContext.inVcSessionDo(new VcSession<Void>() { @Override protected Void body() throws Exception { // copy parent vm's mac addresses logger.info("copy mac addresses of parent vm " + newName); copyNicSettings(oldVm); // copy vhm related extra configures logger.info("copy vhm related extra configs from parent vm " + newName); OptionValue[] optionValues = getVhmExtraConfigs(oldVm); if (optionValues.length != 0) { ConfigSpec spec = new ConfigSpecImpl(); spec.setExtraConfig(optionValues); vm.reconfigure(spec); } // copy the io share level from the original vm logger.info("set io share level same with parent vm " + newName); if (!Priority.NORMAL.equals(ioShares)) { VcVmUtil.configIOShares(vm.getId(), ioShares); } // enalbe disk UUID VcVmUtil.enableDiskUUID(vm); // disable ha if (!ha) { logger.info("diable ha for vm " + newName); VcVmUtil.disableHa(vm); } // enable ft if (ft) { logger.info("enable ft for vm " + newName); VcVmUtil.enableFt(vm); } // update disks to machine id Map<String, String> bootupConfigs = vm.getGuestConfigs(); AuAssert.check(bootupConfigs != null); VcVmUtil.addBootupUUID(bootupConfigs); // disk fix support MapR distro bootupConfigs.put(Constants.GUEST_VARIABLE_RESERVE_RAW_DISKS, String.valueOf(isMapDistro)); bootupConfigs.put(Constants.GUEST_VARIABLE_VOLUMES, VcVmUtil.getVolumes(vm.getId(), diskSchema.getDisks())); vm.setGuestConfigs(bootupConfigs); // the following two steps should be in a transaction theoretically // destroy vm logger.info("destroy parent vm " + newName); VcVmUtil.destroyVm(oldVmId, true); // rename vm logger.info("VM " + vm.getName() + " renamed to " + newName); vm.rename(newName); return null; } protected boolean isTaskSession() { return true; } }); return null; } @Override public void setVm(VcVirtualMachine vm) { this.vm = vm; } @Override public VcVirtualMachine getVm() { return this.vm; } }