<commit_before>/**
 * Copyright (C) 2009-2013 Dell, Inc.
 * See annotations for authorship information
 *
 * ====================================================================
 * 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 org.dasein.cloud.aws.compute;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.SimpleTimeZone;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.concurrent.Callable;

import javax.annotation.Nonnegative;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.codec.binary.Base64;
import org.apache.log4j.Logger;
import org.dasein.cloud.CloudException;
import org.dasein.cloud.InternalException;
import org.dasein.cloud.OperationNotSupportedException;
import org.dasein.cloud.ProviderContext;
import org.dasein.cloud.Requirement;
import org.dasein.cloud.ResourceStatus;
import org.dasein.cloud.Tag;
import org.dasein.cloud.aws.AWSCloud;
import org.dasein.cloud.compute.*;
import org.dasein.cloud.identity.ServiceAction;
import org.dasein.cloud.network.IPVersion;
import org.dasein.cloud.network.IpAddress;
import org.dasein.cloud.network.IpAddressSupport;
import org.dasein.cloud.network.NetworkServices;
import org.dasein.cloud.network.RawAddress;
import org.dasein.cloud.util.APITrace;
import org.dasein.cloud.util.Cache;
import org.dasein.cloud.util.CacheLevel;
import org.dasein.util.CalendarWrapper;
import org.dasein.util.uom.storage.Gigabyte;
import org.dasein.util.uom.storage.Megabyte;
import org.dasein.util.uom.storage.Storage;
import org.dasein.util.uom.time.Day;
import org.dasein.util.uom.time.TimePeriod;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class EC2Instance extends AbstractVMSupport {
	static private final Logger logger = Logger.getLogger(EC2Instance.class);
	static private final Calendar UTC_CALENDAR = Calendar.getInstance(new SimpleTimeZone(0, "GMT"));

	private AWSCloud provider = null;
	
	EC2Instance(AWSCloud provider) {
        super(provider);
		this.provider = provider;
	}

    @Override
    public VirtualMachine alterVirtualMachine(@Nonnull String vmId, @Nonnull VMScalingOptions options) throws InternalException, CloudException {
        throw new OperationNotSupportedException("AWS does not support vertical scaling of instances");
    }

	@Override
	public void start(@Nonnull String instanceId) throws InternalException, CloudException {
        APITrace.begin(provider, "startVM");
        try {
            VirtualMachine vm = getVirtualMachine(instanceId);

            if( vm == null ) {
                throw new CloudException("No such instance: " + instanceId);
            }
            if( !vm.isPersistent() ) {
                throw new OperationNotSupportedException("Instances backed by ephemeral drives are not start/stop capable");
            }
            Map<String,String> parameters = provider.getStandardParameters(provider.getContext(), EC2Method.START_INSTANCES);
            EC2Method method;

            parameters.put("InstanceId.1", instanceId);
            method = new EC2Method(provider, provider.getEc2Url(), parameters);
            try {
                method.invoke();
            }
            catch( EC2Exception e ) {
                logger.error(e.getSummary());
                throw new CloudException(e);
            }
        }
        finally {
            APITrace.end();
        }
	}

    static private class Metric implements Comparable<Metric> {
        int samples = 0;
        long timestamp = -1L;
        double minimum = -1.0;
        double maximum = 0.0;
        double average = 0.0;
        
        public int compareTo(Metric other) {
            if( other == this ) {
                return 0;
            }
            return (new Long(timestamp)).compareTo(other.timestamp);
        }
	}
	
	private Set<Metric> calculate(String metric, String unit, String instanceId, long startTimestamp, long endTimestamp) throws CloudException, InternalException {
        APITrace.begin(provider, "calculateVMAnalytics");
        try {
            if( !provider.getEC2Provider().isAWS() ) {
                return new TreeSet<Metric>();
            }
            Map<String,String> parameters = provider.getStandardCloudWatchParameters(provider.getContext(), EC2Method.GET_METRIC_STATISTICS);
            SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
            fmt.setCalendar(UTC_CALENDAR);
            EC2Method method;
            NodeList blocks;
            Document doc;

            parameters.put("EndTime", fmt.format(new Date(endTimestamp)));
            parameters.put("StartTime", fmt.format(new Date(startTimestamp)));
            parameters.put("MetricName", metric);
            parameters.put("Namespace", "AWS/EC2");
            parameters.put("Unit", unit);
            parameters.put("Dimensions.member.Name.1", "InstanceId");
            parameters.put("Dimensions.member.Value.1", instanceId);
            parameters.put("Statistics.member.1", "Average");
            parameters.put("Statistics.member.2", "Minimum");
            parameters.put("Statistics.member.3", "Maximum");
            parameters.put("Period", "60");
            method = new EC2Method(provider, getCloudWatchUrl(provider.getContext()), parameters);
            try {
                doc = method.invoke();
            }
            catch( EC2Exception e ) {
                logger.error(e.getSummary());
                throw new CloudException(e);
            }
            TreeSet<Metric> metrics = new TreeSet<Metric>();
            fmt = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
            fmt.setCalendar(UTC_CALENDAR);
            blocks = doc.getElementsByTagName("member");
            for( int i=0; i<blocks.getLength(); i++ ) {
                NodeList items = blocks.item(i).getChildNodes();
                Metric m = new Metric();

                for( int j=0; j<items.getLength(); j++ ) {
                    Node item = items.item(j);

                    if( item.getNodeName().equals("Timestamp") ) {
                        String dateString = item.getFirstChild().getNodeValue();
<commit_msg>Altered call to getCloudWatchURL() to guarantee a nonnull context<commit_after>/**
 * Copyright (C) 2009-2013 Dell, Inc.
 * See annotations for authorship information
 *
 * ====================================================================
 * 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 org.dasein.cloud.aws.compute;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.SimpleTimeZone;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.concurrent.Callable;

import javax.annotation.Nonnegative;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.codec.binary.Base64;
import org.apache.log4j.Logger;
import org.dasein.cloud.CloudException;
import org.dasein.cloud.InternalException;
import org.dasein.cloud.OperationNotSupportedException;
import org.dasein.cloud.ProviderContext;
import org.dasein.cloud.Requirement;
import org.dasein.cloud.ResourceStatus;
import org.dasein.cloud.Tag;
import org.dasein.cloud.aws.AWSCloud;
import org.dasein.cloud.compute.*;
import org.dasein.cloud.identity.ServiceAction;
import org.dasein.cloud.network.IPVersion;
import org.dasein.cloud.network.IpAddress;
import org.dasein.cloud.network.IpAddressSupport;
import org.dasein.cloud.network.NetworkServices;
import org.dasein.cloud.network.RawAddress;
import org.dasein.cloud.util.APITrace;
import org.dasein.cloud.util.Cache;
import org.dasein.cloud.util.CacheLevel;
import org.dasein.util.CalendarWrapper;
import org.dasein.util.uom.storage.Gigabyte;
import org.dasein.util.uom.storage.Megabyte;
import org.dasein.util.uom.storage.Storage;
import org.dasein.util.uom.time.Day;
import org.dasein.util.uom.time.TimePeriod;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class EC2Instance extends AbstractVMSupport {
	static private final Logger logger = Logger.getLogger(EC2Instance.class);
	static private final Calendar UTC_CALENDAR = Calendar.getInstance(new SimpleTimeZone(0, "GMT"));

	private AWSCloud provider = null;
	
	EC2Instance(AWSCloud provider) {
        super(provider);
		this.provider = provider;
	}

    @Override
    public VirtualMachine alterVirtualMachine(@Nonnull String vmId, @Nonnull VMScalingOptions options) throws InternalException, CloudException {
        throw new OperationNotSupportedException("AWS does not support vertical scaling of instances");
    }

	@Override
	public void start(@Nonnull String instanceId) throws InternalException, CloudException {
        APITrace.begin(provider, "startVM");
        try {
            VirtualMachine vm = getVirtualMachine(instanceId);

            if( vm == null ) {
                throw new CloudException("No such instance: " + instanceId);
            }
            if( !vm.isPersistent() ) {
                throw new OperationNotSupportedException("Instances backed by ephemeral drives are not start/stop capable");
            }
            Map<String,String> parameters = provider.getStandardParameters(provider.getContext(), EC2Method.START_INSTANCES);
            EC2Method method;

            parameters.put("InstanceId.1", instanceId);
            method = new EC2Method(provider, provider.getEc2Url(), parameters);
            try {
                method.invoke();
            }
            catch( EC2Exception e ) {
                logger.error(e.getSummary());
                throw new CloudException(e);
            }
        }
        finally {
            APITrace.end();
        }
	}

    static private class Metric implements Comparable<Metric> {
        int samples = 0;
        long timestamp = -1L;
        double minimum = -1.0;
        double maximum = 0.0;
        double average = 0.0;
        
        public int compareTo(Metric other) {
            if( other == this ) {
                return 0;
            }
            return (new Long(timestamp)).compareTo(other.timestamp);
        }
	}
	
	private Set<Metric> calculate(String metric, String unit, String instanceId, long startTimestamp, long endTimestamp) throws CloudException, InternalException {
        APITrace.begin(provider, "calculateVMAnalytics");
        try {
            if( !provider.getEC2Provider().isAWS() ) {
                return new TreeSet<Metric>();
            }
            Map<String,String> parameters = provider.getStandardCloudWatchParameters(provider.getContext(), EC2Method.GET_METRIC_STATISTICS);
            SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
            fmt.setCalendar(UTC_CALENDAR);
            EC2Method method;
            NodeList blocks;
            Document doc;

            parameters.put("EndTime", fmt.format(new Date(endTimestamp)));
            parameters.put("StartTime", fmt.format(new Date(startTimestamp)));
            parameters.put("MetricName", metric);
            parameters.put("Namespace", "AWS/EC2");
            parameters.put("Unit", unit);
            parameters.put("Dimensions.member.Name.1", "InstanceId");
            parameters.put("Dimensions.member.Value.1", instanceId);
            parameters.put("Statistics.member.1", "Average");
            parameters.put("Statistics.member.2", "Minimum");
            parameters.put("Statistics.member.3", "Maximum");
            parameters.put("Period", "60");
            method = new EC2Method(provider, getCloudWatchUrl(getContext()), parameters);
            try {
                doc = method.invoke();
            }
            catch( EC2Exception e ) {
                logger.error(e.getSummary());
                throw new CloudException(e);
            }
            TreeSet<Metric> metrics = new TreeSet<Metric>();
            fmt = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
            fmt.setCalendar(UTC_CALENDAR);
            blocks = doc.getElementsByTagName("member");
            for( int i=0; i<blocks.getLength(); i++ ) {
                NodeList items = blocks.item(i).getChildNodes();
                Metric m = new Metric();

                for( int j=0; j<items.getLength(); j++ ) {
                    Node item = items.item(j);

                    if( item.getNodeName().equals("Timestamp") ) {
                        String dateString = item.getFirstChild().getNodeValue();

{'fraction_non_alphanumeric': 0.12305306452700425, 'fraction_numerical': 0.007012339019621064, 'mean_word_length': 3.012987012987013, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4330942', 'n_tokens_mistral': 4131, 'n_tokens_neox': 4010, 'n_words': 934}