/* * Copyright 2010-2012 Amazon.com, Inc. or its affiliates. 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. * A copy of the License is located at * * http://aws.amazon.com/apache2.0 * * or in the "license" file accompanying this file. This file 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.amazonaws.eclipse.elasticbeanstalk.jobs; import static com.amazonaws.eclipse.elasticbeanstalk.ElasticBeanstalkPlugin.trace; import java.util.List; import java.util.Random; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.ui.progress.IProgressConstants; import org.eclipse.ui.statushandlers.StatusManager; import org.eclipse.wst.server.core.IServer; import org.eclipse.wst.server.core.IServerWorkingCopy; import org.eclipse.wst.server.core.ServerCore; import com.amazonaws.AmazonClientException; import com.amazonaws.eclipse.core.AwsToolkitCore; import com.amazonaws.eclipse.elasticbeanstalk.ElasticBeanstalkPlugin; import com.amazonaws.eclipse.elasticbeanstalk.Environment; import com.amazonaws.eclipse.elasticbeanstalk.EnvironmentBehavior; import com.amazonaws.eclipse.elasticbeanstalk.util.ElasticBeanstalkClientExtensions; import com.amazonaws.services.elasticbeanstalk.AWSElasticBeanstalk; import com.amazonaws.services.elasticbeanstalk.model.ConfigurationSettingsDescription; import com.amazonaws.services.elasticbeanstalk.model.DescribeEnvironmentsRequest; import com.amazonaws.services.elasticbeanstalk.model.EnvironmentDescription; import com.amazonaws.services.elasticbeanstalk.model.EnvironmentStatus; public class SyncEnvironmentsJob extends Job { private static final int SHORT_DELAY = 1000 * 30; private static final int LONG_DELAY = 1000 * 60 * 4; private static final Random RANDOM = new Random(); private String previousErrorMessage; public SyncEnvironmentsJob() { super("Synchronizing AWS Elastic Beanstalk environments"); setProperty(IProgressConstants.ICON_PROPERTY, AwsToolkitCore.getDefault().getImageRegistry().getDescriptor(AwsToolkitCore.IMAGE_AWS_ICON)); setSystem(true); setPriority(LONG); setUser(false); } @Override protected IStatus run(IProgressMonitor monitor) { monitor.beginTask("Syncing", IProgressMonitor.UNKNOWN); trace("Syncing environment statuses"); boolean transitioningEnvironment = false; Exception syncingError = null; for (IServer server : ServerCore.getServers()) { if (server.getServerType() == null) continue; String id = server.getServerType().getId(); if (ElasticBeanstalkPlugin.SERVER_TYPE_IDS.contains(id)) { convertLegacyServer(server, monitor); Environment environment = (Environment)server.loadAdapter(Environment.class, monitor); EnvironmentBehavior behavior = (EnvironmentBehavior)server.loadAdapter(EnvironmentBehavior.class, monitor); monitor.setTaskName("Syncing environment " + environment.getEnvironmentName()); try { trace("Syncing server: " + server.getName() + ", " + "environment: " + environment.getEnvironmentName()); transitioningEnvironment |= syncEnvironment(environment, behavior); previousErrorMessage = null; } catch (AmazonClientException ace) { syncingError = ace; } } } if ( syncingError != null ) { schedule(LONG_DELAY); // Don't keep complaining about being unable to synchronize if ( previousErrorMessage != null && previousErrorMessage.equals(syncingError.getMessage()) ) { return Status.OK_STATUS; } previousErrorMessage = syncingError.getMessage(); return new Status(Status.WARNING, ElasticBeanstalkPlugin.PLUGIN_ID, "Unable to synchronize an environment", syncingError); } if (transitioningEnvironment) schedule(SHORT_DELAY + RANDOM.nextInt(5 * 1000)); else schedule(LONG_DELAY + RANDOM.nextInt(5 * 1000)); return Status.OK_STATUS; } /** * Synchronizes the environment given with its AWS Elastic Beanstalk state and returns whether * it should be considered in a "transitioning" state. */ private boolean syncEnvironment(Environment environment, EnvironmentBehavior behavior) { ElasticBeanstalkClientExtensions clientExt = new ElasticBeanstalkClientExtensions(environment); EnvironmentDescription environmentDescription = clientExt.getEnvironmentDescription(environment.getEnvironmentName()); List<ConfigurationSettingsDescription> settings = environment.getCurrentSettings(); behavior.updateServer(environmentDescription, settings); if (environmentDescription == null) return false; EnvironmentStatus environmentStatus = null; try { environmentStatus = EnvironmentStatus.fromValue(environmentDescription.getStatus()); } catch (IllegalArgumentException e) { Status status = new Status(Status.INFO, ElasticBeanstalkPlugin.PLUGIN_ID, "Unknown environment status: " + environmentDescription.getStatus()); StatusManager.getManager().handle(status, StatusManager.LOG); } return (environmentStatus == EnvironmentStatus.Launching || environmentStatus == EnvironmentStatus.Updating || environmentStatus == EnvironmentStatus.Terminating); } /** * We change the data model to save the server environment information. This * function is used to convert the old data format to the new one. */ private void convertLegacyServer(IServer server, IProgressMonitor monitor) { IServerWorkingCopy serverWorkingCopy = server.createWorkingCopy(); Environment env = (Environment) serverWorkingCopy.loadAdapter(Environment.class, monitor); env.convertLegacyServer(); try { serverWorkingCopy.save(true, monitor); } catch (CoreException e) { throw new AmazonClientException("Unable to synchronize with the beanstalk", e); } } }