def createAutostack(self, stackSpec):
    """ Create an "autostack"

    :param stackSpec: specification for an Autostack
    :type stackSpec: dict

    ::

        {
          "name": "all_web_servers",  # Autostack name
          "aggSpec": {  # aggregation spec
            "datasource": "cloudwatch",
            "region": "us-west-2",
            "resourceType": "AWS::EC2::Instance"
            "filters": {  # resourceType-specific filter
              "tag:Name":["*test*", "*grok*"], "tag:Description":["Blah", "foo"]
            },
          }
        }

    :returns: "autostack"
    """
    if "name" not in stackSpec or stackSpec["name"].strip() == "":
      raise ValueError("Must provide a valid name for the Autostack.")

    aggSpec = stackSpec["aggSpec"]
    filters = aggSpec["filters"]
    self._validateFilters(filters)

    region = aggSpec["region"]

    # Enforce the instances per AutoStack limit
    adapter = htm.it.app.adapters.datasource.createDatasourceAdapter(
      aggSpec["datasource"])
    instances = adapter.getMatchingResources(aggSpec)
    if len(instances) > MAX_INSTANCES_PER_AUTOSTACK:
      raise htm.it.app.exceptions.TooManyInstancesError(
        "The filters specified match %i instances but the limit per "
        "AutoStack is %i." % (len(instances), MAX_INSTANCES_PER_AUTOSTACK))

    name = stackSpec["name"]

    with self.connectionFactory() as conn:
      autostackDict = repository.addAutostack(
                        conn,
                        name=name,
                        region=region,
                        filters=htmengine.utils.jsonEncode(filters))
      autostackObj = repository.getAutostack(conn, autostackDict["uid"])

    return autostackObj
        def _createAutostackMetric(conn, name, region, filters):
            autostackDict = repository.addAutostack(
                conn, name=name, region=region, filters=json.dumps(filters))

            modelSpec = {
                "modelParams": {},
                "datasource": "autostack",
                "metricSpec": {
                    "slaveDatasource": "cloudwatch",
                    "slaveMetric": {
                        "metric": "CPUUtilization",
                        "namespace": "AWS/EC2"
                    },
                    "autostackId": autostackDict["uid"]
                }
            }

            metricDict = repository.addMetric(
                conn,
                datasource="autostack",
                name="CPUUtilization",
                description=(
                    "CPUUtilization on HTM-IT Autostack {0} in us-west-2 "
                    "region").format(name),
                server="Autostacks/{0}".format(autostackDict["uid"]),
                location=region,
                tag_name=name,
                parameters=htmengine.utils.jsonEncode(modelSpec),
                poll_interval=300,
                status=MetricStatus.UNMONITORED)

            repository.addMetricToAutostack(conn, autostackDict["uid"],
                                            metricDict["uid"])

            autostackObj = type("MutableAutostack", (object, ),
                                autostackDict)()
            autostackObj.filters = json.loads(autostackObj.filters)

            metricObj = type("MutableMetric", (object, ), metricDict)()

            return autostackObj, metricObj
    def _createAutostackMetric(conn, name, region, filters):
      autostackDict = repository.addAutostack(conn,
                                              name=name,
                                              region=region,
                                              filters=json.dumps(filters))

      modelSpec = {"modelParams": {},
                   "datasource": "autostack",
                   "metricSpec": {"slaveDatasource": "cloudwatch",
                                  "slaveMetric": {"metric": "CPUUtilization",
                                                  "namespace": "AWS/EC2"},
                                  "autostackId": autostackDict["uid"]}}

      metricDict = repository.addMetric(
          conn,
          datasource="autostack",
          name="CPUUtilization",
          description=("CPUUtilization on HTM-IT Autostack {0} in us-west-2 "
                       "region").format(name),
          server="Autostacks/{0}".format(autostackDict["uid"]),
          location=region,
          tag_name=name,
          parameters=htmengine.utils.jsonEncode(modelSpec),
          poll_interval=300,
          status=MetricStatus.UNMONITORED)

      repository.addMetricToAutostack(conn,
                                      autostackDict["uid"],
                                      metricDict["uid"])

      autostackObj = type("MutableAutostack", (object,), autostackDict)()
      autostackObj.filters = json.loads(autostackObj.filters)

      metricObj = type("MutableMetric", (object,), metricDict)()

      return autostackObj, metricObj