/* * Copyright 2000-2014 JetBrains s.r.o. * * 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 jetbrains.buildServer.clouds.vmware.vmrun.local; import java.io.File; import java.io.IOException; import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.concurrent.TimeUnit; import jetbrains.buildServer.clouds.CloudInstanceUserData; import jetbrains.buildServer.clouds.vmware.VMWareConstants; import jetbrains.buildServer.clouds.vmware.settings.VMImageInfo; import jetbrains.buildServer.clouds.vmware.vmrun.VMRunParameters; import jetbrains.buildServer.util.PropertiesUtil; import org.apache.log4j.Logger; import org.jetbrains.annotations.NotNull; /** * @author Eugene Petrenko * Created: 20.03.2010 14:49:08 */ public class WMMachineInjection { private static final Logger LOG = Logger.getLogger(WMMachineInjection.class); private final VMRunSettings mySettings; public WMMachineInjection(final VMRunSettings settings) { mySettings = settings; } public void injectSettings(final VMImageInfo info, final VMRunParameters params, final CloudInstanceUserData data, final File file) { waitInstanceToStart(info, params); //We have no chance to wait for WMWareTools loaded in the VM //Thus the only chance is to try patching files several times //with big timeout. //http://communities.vmware.com/message/895012 try { getAgentPropertiesFile(info, file); setupProperties(params, data, file); pushAgentPropertiesFile(info, file); } catch (Throwable t) { LOG.warn("Failed to update build agent properties. " + info + ". Machine will be stopped."); throw new VMRunException("Failed to start machine. " + info + ", " + t.getMessage(), t); } } private void waitInstanceToStart(@NotNull final VMImageInfo info, @NotNull final VMRunParameters params) { sleep(30, TimeUnit.SECONDS); for (int _ = 15; _-- > 0;) { final ListVMCommand cmd = new ListVMCommand(mySettings, Collections.singletonList(params.getImageInfo())); cmd.startVMRun(); if (!cmd.getInfos().isEmpty()) { return; } LOG.info("Instance " + params.getImageInfo().getId() + " is not started. Waiting... " + info); sleep(30, TimeUnit.SECONDS); } throw new VMRunException("Timout waiting for " + info + " to start"); } private void sleep(long time, TimeUnit unit) { try { Thread.sleep(unit.toMillis(time)); } catch (InterruptedException e) { //NOP } } private void getAgentPropertiesFile(final VMImageInfo info, final File file) { VMRunException getError = null; for (int _ = 10; _-- > 0;) { try { new GetFileCommand(mySettings, info, info.getImageAgentConfigLocation(), file).startVMRun(); return; } catch (VMRunException e) { LOG.debug("Get command failed for machine " + info.getImagePath() + ". Will try again after timeout..."); getError = e; sleep(15, TimeUnit.SECONDS); } } if (getError != null) { LOG.warn("Failed to download " + info.getImageAgentConfigLocation() + " file from machine: " + info.getImagePath() + ". " + "Check latest VMWare Tools installed on the machine and started. " + getError.getMessage(), getError); throw new VMRunException("Failed to download buildAgent.proprties file. " + getError.getMessage()); } } private void pushAgentPropertiesFile(final VMImageInfo info, final File file) { //TODO: Should we retry here too? try { new PushFileCommand(mySettings, info, info.getImageAgentConfigLocation(), file).startVMRun(); } catch (VMRunException e) { LOG.warn("Failed to upload file to " + info.getImageAgentConfigLocation() + " for machine: " + info.getImagePath() + ". " + e.getMessage(), e); throw new VMRunException("Failed to update patched buildAgent.properties file. " + e.getMessage()); } } private void setupProperties(final VMRunParameters params, final CloudInstanceUserData data, final File file) { Map props = new HashMap(); props.putAll(data.getCustomAgentConfigurationParameters()); props.put("name", data.getAgentName()); props.put("authorizationToken", ""); props.put("serverUrl", data.getServerAddress()); props.put(VMWareConstants.WM_IMAGE_ID, params.getImageId()); props.put(VMWareConstants.WM_INSTANCE_ID, params.getInstanceId()); props.put(VMWareConstants.WM_LOCATION_ID, params.getLocationId()); try { PropertiesUtil.updatePropertiesFromFile(file, props, Collections.emptySet()); } catch (IOException e) { throw new VMRunException("Failed to update properties file locally.", e); } } }