Ejemplo n.º 1
0
  def _validateAutostackResults(self, metricID, instanceIDs, metricName):
    """Validate that AutoStack data is correct based on the metrics data.

    This method ensures that there is at least twelve records and validates
    that the most recent five are computed correctly. By skipping at least the
    first few, we ensure that the data is still available in Cloudwatch. The
    number five is arbitrary, we just need some records to validate.

    @param metricID the ID of the AutoStack metric to check
    @param instanceIDs a sequence of the IDs for the metrics that make up the
        AutoStack
    @param metricName the metric name to validate
    """
    # Get the AutoStack data
    response = requests.get("https://localhost/_models/%s/data" % metricID,
                            auth=(self.apiKey, ""), verify=False)
    self.assertSetEqual(set(response.json().keys()), set(["names", "data"]))
    names = response.json()["names"]
    self.assertSetEqual(
        set(["timestamp", "value", "anomaly_score", "rowid"]), set(names))
    data = response.json()["data"]

    # Make sure that we have enough data to validate
    self.assertGreaterEqual(len(data), 12)
    recordsToValidate = dict((r[0], r[1]) for r in data[:12])

    # Get the start and end dates to pull Cloudwatch data for
    start = datetime.datetime.strptime(min(recordsToValidate.keys()),
                                       "%Y-%m-%d %H:%M:%S")
    end = datetime.datetime.strptime(max(recordsToValidate.keys()),
                                     "%Y-%m-%d %H:%M:%S")

    # Collect the Cloudwatch data for the timestamp range for all instances
    dataByTimestamp = collections.defaultdict(list)
    conn = boto.ec2.cloudwatch.connect_to_region(
            _REGION,
            aws_access_key_id=config.get("aws", "aws_access_key_id"),
            aws_secret_access_key=config.get("aws", "aws_secret_access_key"))
    for instanceID in instanceIDs:
      data = conn.get_metric_statistics(
          period=_PERIOD, start_time=start, end_time=end,
          metric_name=metricName, namespace="AWS/EC2", statistics=("Average",),
          dimensions={"InstanceId": instanceID})
      for record in data:
        dataByTimestamp[record["Timestamp"]].append(record["Average"])

    # Check that the manually averaged values match the AutoStack value
    numRecordsValidated = 0
    for timestamp, records in dataByTimestamp.iteritems():
      expectedAverage = sum(records) / len(records)
      actualAverage = recordsToValidate[timestamp.strftime("%Y-%m-%d %H:%M:%S")]
      self.assertAlmostEqual(
          expectedAverage, actualAverage, 4,
          "AutoStack value of %f differs from average from CloudWatch of %f "
          "at time %s" % (actualAverage, expectedAverage, timestamp))
      if len(records) >= 2:
        numRecordsValidated += 1
    # Make sure we checked enough records that had multiple instances
    self.assertGreaterEqual(numRecordsValidated, 5)
Ejemplo n.º 2
0
def getBaseConnectionArgsDict():
    """Return a dictonary of common database connection arguments."""
    return {
        "host": config.get("repository", "host"),
        "port": config.getint("repository", "port"),
        "user": config.get("repository", "user"),
        "passwd": config.get("repository", "passwd"),
        "charset": "utf8",
        "use_unicode": True,
    }
Ejemplo n.º 3
0
def getBaseConnectionArgsDict():
  """Return a dictonary of common database connection arguments."""
  return {
    "host": config.get("repository", "host"),
    "port": config.getint("repository", "port"),
    "user": config.get("repository", "user"),
    "passwd": config.get("repository", "passwd"),
    "charset": "utf8",
    "use_unicode": True,
  }
Ejemplo n.º 4
0
def sendWelcomeEmail(toAddress):
    subject = config.get("registration", "subject")
    body = open(resource_filename(YOMP.__name__, os.path.join("../conf", config.get("registration", "body")))).read()
    body = body.replace("\n", "\r\n")  # Ensure windows newlines

    serverUrl = web.ctx.env["HTTP_HOST"]
    templated = dict(apiKey=config.get("security", "apikey"), serverUrl=serverUrl)

    try:
        ses_utils.sendEmail(subject=subject.format(**templated), body=body.format(**templated), toAddresses=[toAddress])
    except BotoServerError:
        raise web.badrequest("Invalid email address.")
Ejemplo n.º 5
0
def getRDSInstances(region):
  """Simple generator for getting RDS instances.

  :param region: the region to get instances for
  :returns: a generator of :class:`boto.rds.dbinstance.DBInstance` instances
  """
  awsAccessKeyId = config.get("aws", "aws_access_key_id")
  awsSecretAccessKey = config.get("aws", "aws_secret_access_key")
  conn = boto.rds.connect_to_region(region_name=region,
                                    aws_access_key_id=awsAccessKeyId,
                                    aws_secret_access_key=awsSecretAccessKey)
  for instance in conn.get_all_dbinstances():
    yield instance
Ejemplo n.º 6
0
def getRDSInstances(region):
    """Simple generator for getting RDS instances.

  :param region: the region to get instances for
  :returns: a generator of :class:`boto.rds.dbinstance.DBInstance` instances
  """
    awsAccessKeyId = config.get("aws", "aws_access_key_id")
    awsSecretAccessKey = config.get("aws", "aws_secret_access_key")
    conn = boto.rds.connect_to_region(region_name=region,
                                      aws_access_key_id=awsAccessKeyId,
                                      aws_secret_access_key=awsSecretAccessKey)
    for instance in conn.get_all_dbinstances():
        yield instance
Ejemplo n.º 7
0
def getELBInstances(region):
  """Simple generator for getting ELB instances.

  :param region: the region to get instances for
  :returns: a generator of :class:`boto.ec2.elb.load_balancer.LoadBalancer`
      instances
  """
  awsAccessKeyId = config.get("aws", "aws_access_key_id")
  awsSecretAccessKey = config.get("aws", "aws_secret_access_key")
  conn = boto.ec2.elb.connect_to_region(
      region_name=region,
      aws_access_key_id=awsAccessKeyId,
      aws_secret_access_key=awsSecretAccessKey)
  for loadBalancer in conn.get_all_load_balancers():
    yield loadBalancer
Ejemplo n.º 8
0
def reset(offline=False):
    """
  Reset the YOMP database; upon successful completion, the necessary schema are
  created, but the tables are not populated

  :param offline: False to execute SQL commands; True to just dump SQL commands
    to stdout for offline mode or debugging
  """
    # Make sure we have the latest version of configuration
    config.loadConfig()
    dbName = config.get('repository', 'db')

    resetDatabaseSQL = ("DROP DATABASE IF EXISTS %(database)s; "
                        "CREATE DATABASE %(database)s;" % {
                            "database": dbName
                        })
    statements = resetDatabaseSQL.split(";")

    engine = getUnaffiliatedEngine()
    with engine.connect() as connection:
        for s in statements:
            if s.strip():
                connection.execute(s)

    migrate(offline=offline)
Ejemplo n.º 9
0
def getEC2Instances(region, filters=None):
    """Simple generator for getting EC2 instances.

  :param region: the region to get instances for
  :param filters: Dictionary of filters
    See http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_Filtering.html
  :returns: a generator of :class:`boto.ec2.instance.Instance` instances
  """
    awsAccessKeyId = config.get("aws", "aws_access_key_id")
    awsSecretAccessKey = config.get("aws", "aws_secret_access_key")
    conn = boto.ec2.connect_to_region(region_name=region,
                                      aws_access_key_id=awsAccessKeyId,
                                      aws_secret_access_key=awsSecretAccessKey)
    for reservation in conn.get_all_reservations(filters=filters):
        for instance in reservation.instances:
            yield instance
Ejemplo n.º 10
0
def getEC2Instances(region, filters=None):
  """Simple generator for getting EC2 instances.

  :param region: the region to get instances for
  :param filters: Dictionary of filters
    See http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_Filtering.html
  :returns: a generator of :class:`boto.ec2.instance.Instance` instances
  """
  awsAccessKeyId = config.get("aws", "aws_access_key_id")
  awsSecretAccessKey = config.get("aws", "aws_secret_access_key")
  conn = boto.ec2.connect_to_region(region_name=region,
                                    aws_access_key_id=awsAccessKeyId,
                                    aws_secret_access_key=awsSecretAccessKey)
  for reservation in conn.get_all_reservations(filters=filters):
    for instance in reservation.instances:
      yield instance
Ejemplo n.º 11
0
  def setUpClass(cls):
    cls.autostacksApp = TestApp(autostacks_api.app.wsgifunc())
    cls.cloudwatchApp = TestApp(cloudwatch_api.app.wsgifunc())
    cls.customApp = TestApp(custom_api.app.wsgifunc())
    cls.instancesApp = TestApp(instances_api.app.wsgifunc())
    cls.modelApp = TestApp(models_api.app.wsgifunc())
    cls.headers = getDefaultHTTPHeaders(YOMP.app.config)

    cls.plaintextPort = config.getint("metric_listener", "plaintext_port")
    cls.apiKey = config.get("security", "apikey")
Ejemplo n.º 12
0
def sendWelcomeEmail(toAddress):
    subject = config.get("registration", "subject")
    body = open(
        resource_filename(
            YOMP.__name__,
            os.path.join("../conf", config.get("registration",
                                               "body")))).read()
    body = body.replace("\n", "\r\n")  # Ensure windows newlines

    serverUrl = web.ctx.env['HTTP_HOST']
    templated = dict(apiKey=config.get("security", "apikey"),
                     serverUrl=serverUrl)

    try:
        ses_utils.sendEmail(subject=subject.format(**templated),
                            body=body.format(**templated),
                            toAddresses=[toAddress])
    except BotoServerError:
        raise web.badrequest("Invalid email address.")
Ejemplo n.º 13
0
    def POST(self):

        url = config.get("usertrack", "wufoo_url")
        user = config.get("usertrack", "wufoo_user")

        fields = {
            'name': 'Field6',
            'company': 'Field3',
            'email': 'Field4',
            'edition': 'Field8',
            'version': 'Field10',
            'build': 'Field12',
            'accountId': 'Field14',
            'uniqueServerId': 'Field16',
            'instanceId': 'Field18',
            'region': 'Field19',
            'instanceType': 'Field21'
        }
        payload = {}

        instanceData = instance_utils.getInstanceData() or {}
        for datum in instanceData:
            if datum in fields:
                payload[fields[datum]] = instanceData[datum]

        data = json.loads(web.data())

        if 'email' in data and len(data['email']):
            sendWelcomeEmail(data['email'])

        for datum in data:
            payload[fields[datum]] = data[datum]

        payload[fields["uniqueServerId"]] = config.get("usertrack", "YOMP_id")

        if config.getboolean("usertrack", "send_to_wufoo"):
            requests.post(url=url, data=payload, auth=(user, ''))

        for (fieldName, field) in fields.iteritems():
            log.info("{TAG:WUFOO.CUST.REG} %s=%s" %
                     (fieldName, payload.get(field)))

        return web.HTTPError(status="204", data="No Content")
Ejemplo n.º 14
0
    def setUpClass(cls):
        cls.autostacksApp = TestApp(autostacks_api.app.wsgifunc())
        cls.cloudwatchApp = TestApp(cloudwatch_api.app.wsgifunc())
        cls.customApp = TestApp(custom_api.app.wsgifunc())
        cls.instancesApp = TestApp(instances_api.app.wsgifunc())
        cls.modelApp = TestApp(models_api.app.wsgifunc())
        cls.headers = getDefaultHTTPHeaders(YOMP.app.config)

        cls.plaintextPort = config.getint("metric_listener", "plaintext_port")
        cls.apiKey = config.get("security", "apikey")
Ejemplo n.º 15
0
    def POST(self):

        url = config.get("usertrack", "wufoo_url")
        user = config.get("usertrack", "wufoo_user")

        fields = {
            "name": "Field6",
            "company": "Field3",
            "email": "Field4",
            "edition": "Field8",
            "version": "Field10",
            "build": "Field12",
            "accountId": "Field14",
            "uniqueServerId": "Field16",
            "instanceId": "Field18",
            "region": "Field19",
            "instanceType": "Field21",
        }
        payload = {}

        instanceData = instance_utils.getInstanceData() or {}
        for datum in instanceData:
            if datum in fields:
                payload[fields[datum]] = instanceData[datum]

        data = json.loads(web.data())

        if "email" in data and len(data["email"]):
            sendWelcomeEmail(data["email"])

        for datum in data:
            payload[fields[datum]] = data[datum]

        payload[fields["uniqueServerId"]] = config.get("usertrack", "YOMP_id")

        if config.getboolean("usertrack", "send_to_wufoo"):
            requests.post(url=url, data=payload, auth=(user, ""))

        for (fieldName, field) in fields.iteritems():
            log.info("{TAG:WUFOO.CUST.REG} %s=%s" % (fieldName, payload.get(field)))

        return web.HTTPError(status="204", data="No Content")
Ejemplo n.º 16
0
def getAutoScalingGroups(region, filters=None):
  """Simple generator for getting AutoScaling groups.

  :param region: the region to get groups for
  :param filters: Dictionary of filters
    See http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_Filtering.html
  :returns: a generator of :class:`boto.ec2.autoscale.group.AutoScalingGroup`
      instances
  """
  awsAccessKeyId = config.get("aws", "aws_access_key_id")
  awsSecretAccessKey = config.get("aws", "aws_secret_access_key")
  conn = boto.ec2.autoscale.connect_to_region(
      region_name=region,
      aws_access_key_id=awsAccessKeyId,
      aws_secret_access_key=awsSecretAccessKey)
  names = None
  if filters:
    names = filters.get("tag:Name", None)
  for group in conn.get_all_groups(names=names):
    yield group
Ejemplo n.º 17
0
def sendEmail(subject, body, toAddresses, region=None, sender=None):
    """Send an email with AWS SES.

  :param subject: Email subject header
  :param body: Email body
  :param toAddresses: Email recipient(s)
  :param region: AWS Region
  :param sender: Email sender
  :returns: SES Message ID or None
  """
    if region is None:
        region = config.get("aws", "default_region")

    if sender is None:
        sender = config.get("notifications", "sender")

    if region not in _SES_ENDPOINTS:
        raise ValueError(
            "Region '%s' provided does not exist in known SES region "
            "endpoints set." % region)

    regionInfo = RegionInfo(None, region, _SES_ENDPOINTS[region])

    awsAccessKeyId = config.get("notifications", "aws_access_key_id")
    awsSecretAccessKey = config.get("notifications", "aws_secret_access_key")
    if awsAccessKeyId == "" or awsSecretAccessKey == "":
        awsAccessKeyId = config.get("aws", "aws_access_key_id")
        awsSecretAccessKey = config.get("aws", "aws_secret_access_key")

    conn = boto.ses.SESConnection(region=regionInfo,
                                  aws_access_key_id=awsAccessKeyId,
                                  aws_secret_access_key=awsSecretAccessKey)

    # Send the email
    result = conn.send_email(source=sender,
                             subject=subject,
                             body=body,
                             to_addresses=toAddresses)

    # Return the SES message ID, or None if there is no message ID in the response
    if "SendEmailResponse" in result:
        if "SendEmailResult" in result["SendEmailResponse"]:
            if "MessageId" in result["SendEmailResponse"]["SendEmailResult"]:
                return result["SendEmailResponse"]["SendEmailResult"][
                    "MessageId"]
    return None
Ejemplo n.º 18
0
def sendEmail(subject, body, toAddresses, region=None, sender=None):
  """Send an email with AWS SES.

  :param subject: Email subject header
  :param body: Email body
  :param toAddresses: Email recipient(s)
  :param region: AWS Region
  :param sender: Email sender
  :returns: SES Message ID or None
  """
  if region is None:
    region = config.get("aws", "default_region")

  if sender is None:
    sender = config.get("notifications", "sender")

  if region not in _SES_ENDPOINTS:
    raise ValueError("Region '%s' provided does not exist in known SES region "
                     "endpoints set." % region)

  regionInfo = RegionInfo(None, region, _SES_ENDPOINTS[region])

  awsAccessKeyId = config.get("notifications", "aws_access_key_id")
  awsSecretAccessKey = config.get("notifications", "aws_secret_access_key")
  if awsAccessKeyId == "" or awsSecretAccessKey == "":
    awsAccessKeyId = config.get("aws", "aws_access_key_id")
    awsSecretAccessKey = config.get("aws", "aws_secret_access_key")

  conn = boto.ses.SESConnection(region=regionInfo,
                                aws_access_key_id=awsAccessKeyId,
                                aws_secret_access_key=awsSecretAccessKey)

  # Send the email
  result = conn.send_email(source=sender,
                           subject=subject,
                           body=body,
                           to_addresses=toAddresses)

  # Return the SES message ID, or None if there is no message ID in the response
  if "SendEmailResponse" in result:
    if "SendEmailResult" in result["SendEmailResponse"]:
      if "MessageId" in result["SendEmailResponse"]["SendEmailResult"]:
        return result["SendEmailResponse"]["SendEmailResult"]["MessageId"]
  return None
Ejemplo n.º 19
0
def reset(offline=False):
  """
  Reset the YOMP database; upon successful completion, the necessary schema are
  created, but the tables are not populated

  :param offline: False to execute SQL commands; True to just dump SQL commands
    to stdout for offline mode or debugging
  """
  # Make sure we have the latest version of configuration
  config.loadConfig()
  dbName = config.get('repository', 'db')

  resetDatabaseSQL = (
      "DROP DATABASE IF EXISTS %(database)s; "
      "CREATE DATABASE %(database)s;" % {"database": dbName})
  statements = resetDatabaseSQL.split(";")

  engine = getUnaffiliatedEngine()
  with engine.connect() as connection:
    for s in statements:
      if s.strip():
        connection.execute(s)

  migrate(offline=offline)
Ejemplo n.º 20
0
    def GET(self, region=None):  # pylint: disable=R0201
        """
    Get quick selection instance suggestions to monitor

    ::

        GET /_instances/suggestions

    Sample Output:

    ::

        {
            "suggested": [
              {
                  "region": "us-west-2",
                  "namespace": "AWS/EC2",
                  "id": "i-12345678"
              },
              ... (up to 8 total suggested) ...
          ],
          "alternates": [
              {
                  "region": "us-west-2",
                  "namespace": "AWS/ELB",
                  "id": "YOMP-docs-elb"
              },
              ... (up to 22 total alternatives) ...
          ]
      }
      """
        if region is None:
            region = config.get("aws", "default_region")

        ec2Queue = Queue.Queue()
        ec2Thread = threading.Thread(target=ec2_utils.getSuggestedInstances,
                                     args=(region, ec2Queue,
                                           _AWS_INSTANCE_FETCHING_TIME_LIMIT))
        ec2Thread.start()

        rdsQueue = Queue.Queue()
        rdsThread = threading.Thread(target=rds_utils.getSuggestedInstances,
                                     args=(region, rdsQueue,
                                           _AWS_INSTANCE_FETCHING_TIME_LIMIT))
        rdsThread.start()

        elbQueue = Queue.Queue()
        elbThread = threading.Thread(target=elb_utils.getSuggestedInstances,
                                     args=(region, elbQueue,
                                           _AWS_INSTANCE_FETCHING_TIME_LIMIT))
        elbThread.start()

        asgQueue = Queue.Queue()
        asgThread = threading.Thread(target=asg_utils.getSuggestedInstances,
                                     args=(region, asgQueue,
                                           _AWS_INSTANCE_FETCHING_TIME_LIMIT))
        asgThread.start()

        response = {
            "suggested": [],
            "alternates": [],
        }

        # Wait for the threads to finish
        ec2Thread.join()
        rdsThread.join()
        elbThread.join()
        asgThread.join()

        n = 0
        done = False
        while n < _MAX_SUGGESTED_INSTANCES_TOTAL and not done:
            done = True

            # EC2 Instances
            try:
                instance = ec2Queue.get(block=False)
                if n < _NUM_SUGGESTED_INSTANCES:
                    response["suggested"].append(instance)
                else:
                    response["alternates"].append(instance)
                done = False
                n += 1
                if n >= _MAX_SUGGESTED_INSTANCES_TOTAL:
                    break
            except Queue.Empty:
                pass

            # RDS Instances
            try:
                instance = rdsQueue.get(block=False)
                if n < _NUM_SUGGESTED_INSTANCES:
                    response["suggested"].append(instance)
                else:
                    response["alternates"].append(instance)
                done = False
                n += 1
                if n >= _MAX_SUGGESTED_INSTANCES_TOTAL:
                    break
            except Queue.Empty:
                pass

            # Load Balancers
            try:
                instance = elbQueue.get(block=False)
                if n < _NUM_SUGGESTED_INSTANCES:
                    response["suggested"].append(instance)
                else:
                    response["alternates"].append(instance)
                done = False
                n += 1
                if n >= _MAX_SUGGESTED_INSTANCES_TOTAL:
                    break
            except Queue.Empty:
                pass

            # AutoScaling groups
            try:
                instance = asgQueue.get(block=False)
                if n < _NUM_SUGGESTED_INSTANCES:
                    response["suggested"].append(instance)
                else:
                    response["alternates"].append(instance)
                done = False
                n += 1
                if n >= _MAX_SUGGESTED_INSTANCES_TOTAL:
                    break
            except Queue.Empty:
                pass

        return encodeJson(response)
Ejemplo n.º 21
0
 def getDatabaseNameFromConfig(cls):
   return config.get(cls.REPO_SECTION_NAME,
                              cls.REPO_DATABASE_ATTR_NAME)
Ejemplo n.º 22
0
import YOMP
import YOMP.app
from YOMP.app import config, repository
from htmengine import utils
from YOMP.app.repository import schema
from YOMP.app.aws import s3_utils
from YOMP import YOMP_logging

from nta.utils.file_lock import ExclusiveFileLock


# Path format for writing Android logs.
_LOG_FORMAT_ANDROID = os.path.join(os.path.dirname(YOMP.__file__), "..", "logs", "android.log")
_LOGGER = YOMP_logging.getExtendedLogger(__name__)

_AWS_ACCESS_KEY = config.get("aws", "aws_access_key_id")
_AWS_SECRET_KEY = config.get("aws", "aws_secret_access_key")
_BUCKET = "YOMP.logs"
_MACHINE_ID = uuid.getnode()
_KEY_PREFIX = "metric_dumps/%s-" % _MACHINE_ID
_UPLOAD_ATTEMPTS = 3

urls = (
    # /_logging/android
    "/android",
    "AndroidHandler",
    # /_logging/feedback
    "/feedback",
    "FeedbackHandler",
)
Ejemplo n.º 23
0
 def setUp(self):
   self.apiKey = config.get("security", "apikey")
Ejemplo n.º 24
0
 def setUp(self):
     self.apiKey = config.get("security", "apikey")
Ejemplo n.º 25
0
    def _validateAutostackResults(self, metricID, instanceIDs, metricName):
        """Validate that AutoStack data is correct based on the metrics data.

    This method ensures that there is at least twelve records and validates
    that the most recent five are computed correctly. By skipping at least the
    first few, we ensure that the data is still available in Cloudwatch. The
    number five is arbitrary, we just need some records to validate.

    @param metricID the ID of the AutoStack metric to check
    @param instanceIDs a sequence of the IDs for the metrics that make up the
        AutoStack
    @param metricName the metric name to validate
    """
        # Get the AutoStack data
        response = requests.get("https://localhost/_models/%s/data" % metricID,
                                auth=(self.apiKey, ""),
                                verify=False)
        self.assertSetEqual(set(response.json().keys()), set(["names",
                                                              "data"]))
        names = response.json()["names"]
        self.assertSetEqual(
            set(["timestamp", "value", "anomaly_score", "rowid"]), set(names))
        data = response.json()["data"]

        # Make sure that we have enough data to validate
        self.assertGreaterEqual(len(data), 12)
        recordsToValidate = dict((r[0], r[1]) for r in data[:12])

        # Get the start and end dates to pull Cloudwatch data for
        start = datetime.datetime.strptime(min(recordsToValidate.keys()),
                                           "%Y-%m-%d %H:%M:%S")
        end = datetime.datetime.strptime(max(recordsToValidate.keys()),
                                         "%Y-%m-%d %H:%M:%S")

        # Collect the Cloudwatch data for the timestamp range for all instances
        dataByTimestamp = collections.defaultdict(list)
        conn = boto.ec2.cloudwatch.connect_to_region(
            _REGION,
            aws_access_key_id=config.get("aws", "aws_access_key_id"),
            aws_secret_access_key=config.get("aws", "aws_secret_access_key"))
        for instanceID in instanceIDs:
            data = conn.get_metric_statistics(
                period=_PERIOD,
                start_time=start,
                end_time=end,
                metric_name=metricName,
                namespace="AWS/EC2",
                statistics=("Average", ),
                dimensions={"InstanceId": instanceID})
            for record in data:
                dataByTimestamp[record["Timestamp"]].append(record["Average"])

        # Check that the manually averaged values match the AutoStack value
        numRecordsValidated = 0
        for timestamp, records in dataByTimestamp.iteritems():
            expectedAverage = sum(records) / len(records)
            actualAverage = recordsToValidate[timestamp.strftime(
                "%Y-%m-%d %H:%M:%S")]
            self.assertAlmostEqual(
                expectedAverage, actualAverage, 4,
                "AutoStack value of %f differs from average from CloudWatch of %f "
                "at time %s" % (actualAverage, expectedAverage, timestamp))
            if len(records) >= 2:
                numRecordsValidated += 1
        # Make sure we checked enough records that had multiple instances
        self.assertGreaterEqual(numRecordsValidated, 5)
Ejemplo n.º 26
0
  def GET(self, region=None): # pylint: disable=R0201
    """
    Get quick selection instance suggestions to monitor

    ::

        GET /_instances/suggestions

    Sample Output:

    ::

        {
            "suggested": [
              {
                  "region": "us-west-2",
                  "namespace": "AWS/EC2",
                  "id": "i-12345678"
              },
              ... (up to 8 total suggested) ...
          ],
          "alternates": [
              {
                  "region": "us-west-2",
                  "namespace": "AWS/ELB",
                  "id": "YOMP-docs-elb"
              },
              ... (up to 22 total alternatives) ...
          ]
      }
      """
    if region is None:
      region = config.get("aws", "default_region")

    ec2Queue = Queue.Queue()
    ec2Thread = threading.Thread(
        target=ec2_utils.getSuggestedInstances,
        args=(region, ec2Queue, _AWS_INSTANCE_FETCHING_TIME_LIMIT))
    ec2Thread.start()

    rdsQueue = Queue.Queue()
    rdsThread = threading.Thread(
        target=rds_utils.getSuggestedInstances,
        args=(region, rdsQueue, _AWS_INSTANCE_FETCHING_TIME_LIMIT))
    rdsThread.start()

    elbQueue = Queue.Queue()
    elbThread = threading.Thread(
        target=elb_utils.getSuggestedInstances,
        args=(region, elbQueue, _AWS_INSTANCE_FETCHING_TIME_LIMIT))
    elbThread.start()

    asgQueue = Queue.Queue()
    asgThread = threading.Thread(
        target=asg_utils.getSuggestedInstances,
        args=(region, asgQueue, _AWS_INSTANCE_FETCHING_TIME_LIMIT))
    asgThread.start()

    response = {
        "suggested": [],
        "alternates": [],
    }

    # Wait for the threads to finish
    ec2Thread.join()
    rdsThread.join()
    elbThread.join()
    asgThread.join()

    n = 0
    done = False
    while n < _MAX_SUGGESTED_INSTANCES_TOTAL and not done:
      done = True

      # EC2 Instances
      try:
        instance = ec2Queue.get(block=False)
        if n < _NUM_SUGGESTED_INSTANCES:
          response["suggested"].append(instance)
        else:
          response["alternates"].append(instance)
        done = False
        n += 1
        if n >= _MAX_SUGGESTED_INSTANCES_TOTAL:
          break
      except Queue.Empty:
        pass

      # RDS Instances
      try:
        instance = rdsQueue.get(block=False)
        if n < _NUM_SUGGESTED_INSTANCES:
          response["suggested"].append(instance)
        else:
          response["alternates"].append(instance)
        done = False
        n += 1
        if n >= _MAX_SUGGESTED_INSTANCES_TOTAL:
          break
      except Queue.Empty:
        pass

      # Load Balancers
      try:
        instance = elbQueue.get(block=False)
        if n < _NUM_SUGGESTED_INSTANCES:
          response["suggested"].append(instance)
        else:
          response["alternates"].append(instance)
        done = False
        n += 1
        if n >= _MAX_SUGGESTED_INSTANCES_TOTAL:
          break
      except Queue.Empty:
        pass

      # AutoScaling groups
      try:
        instance = asgQueue.get(block=False)
        if n < _NUM_SUGGESTED_INSTANCES:
          response["suggested"].append(instance)
        else:
          response["alternates"].append(instance)
        done = False
        n += 1
        if n >= _MAX_SUGGESTED_INSTANCES_TOTAL:
          break
      except Queue.Empty:
        pass

    return encodeJson(response)
Ejemplo n.º 27
0
import YOMP
import YOMP.app
from YOMP.app import config, repository
from htmengine import utils
from YOMP.app.repository import schema
from YOMP.app.aws import s3_utils
from YOMP import YOMP_logging

from nta.utils.file_lock import ExclusiveFileLock

# Path format for writing Android logs.
_LOG_FORMAT_ANDROID = os.path.join(os.path.dirname(YOMP.__file__), "..",
                                   "logs", "android.log")
_LOGGER = YOMP_logging.getExtendedLogger(__name__)

_AWS_ACCESS_KEY = config.get("aws", "aws_access_key_id")
_AWS_SECRET_KEY = config.get("aws", "aws_secret_access_key")
_BUCKET = "YOMP.logs"
_MACHINE_ID = uuid.getnode()
_KEY_PREFIX = "metric_dumps/%s-" % _MACHINE_ID
_UPLOAD_ATTEMPTS = 3

urls = (
    # /_logging/android
    "/android",
    "AndroidHandler",
    # /_logging/feedback
    "/feedback",
    "FeedbackHandler",
)