Beispiel #1
0
    def __call__(self, req):
        """
        Determine period start and stop, ask db api, and return JSON report.
        """
        arg_dict = req.environ['wsgiorg.routing_args'][1]

        STATISTICS_NONE = 0
        STATISTICS_SHORT = 1
        STATISTICS_LONG = 2

        queried_tenant_id = arg_dict.get("project_id", None)
        roles = [r.strip()
                 for r in req.headers.get('X_ROLE', '').split(',')]
        is_admin = "Admin" in roles
        if not is_admin:
            if queried_tenant_id:
                if req.headers.get('X_TENANT_ID', '') != queried_tenant_id:
                    raise webob.exc.HTTPUnauthorized()
            else:
                queried_tenant_id = req.headers.get('X_TENANT_ID', '-1')

        auth_token = req.headers.get('X_AUTH_TOKEN', '')

        period_start, period_end = self.get_period(req)
        statistics = {"instances": STATISTICS_NONE,
                      "images": STATISTICS_NONE}
        try:
            include = req.GET["include"]
        except KeyError:
            statistics["instances"] = (STATISTICS_LONG
                if period_end - period_start <= datetime.timedelta(days=31)
                    and queried_tenant_id
                else STATISTICS_SHORT)
        else:
            include = include.strip(",")
            for key in "images", "instances":
                if (key + "-long") in include:
                    statistics[key] = STATISTICS_LONG
                elif key in include:
                    statistics[key] = STATISTICS_SHORT

        if is_admin:
            tenants = keystone_utils.KeystoneTenants().\
                    get_tenants(auth_token)
            reported_projects = set([tenant.id for tenant in tenants])
            if queried_tenant_id:
                if queried_tenant_id in reported_projects:
                    reported_projects = set([queried_tenant_id])
                else:
                    raise webob.exc.HTTPNotFound()
        else:
            reported_projects = set([queried_tenant_id])

        projects = {}
        for project_id in reported_projects:
            projects[project_id] = {
                "id": str(project_id),
                "url": "http://%s:%s/projects/%s" %
                       (req.environ["SERVER_NAME"],
                        req.environ["SERVER_PORT"],
                        project_id),
            }
        now = utils.now()
        for statistics_key in "images", "instances":
            if not statistics[statistics_key]:
                continue
            show_items = statistics[statistics_key] == STATISTICS_LONG
            if statistics_key == "images":
                total_statistics = glance_utils.images_on_interval(
                    period_start, period_end,
                    auth_token, queried_tenant_id)
            else:
                total_statistics = db_api.instances_on_interval(
                    period_start, period_end, queried_tenant_id)
            for project_id in projects:
                project_statistics = total_statistics.get(project_id, {})
                project_dict = {
                    "count": len(project_statistics),
                }
                project_usage = {}
                items = []
                for item_id, item_statistics in project_statistics.items():
                    utils.dict_add(project_usage, item_statistics["usage"])
                    if show_items:
                        lifetime = utils.total_seconds(
                            min(item_statistics["destroyed_at"] or now, period_end) -
                            max(item_statistics["created_at"], period_start))
                        item_dict = {
                            "id": item_id,
                            "lifetime_sec": lifetime,
                            "usage": utils.usage_to_hours(item_statistics["usage"]),
                            "name": item_statistics.get("name", None),
                        }
                        for key in "created_at", "destroyed_at":
                            item_dict[key] = utils.datetime_to_str(item_statistics[key])
                        items.append(item_dict)

                if show_items:
                    project_dict["items"] = items
                project_dict["usage"] = utils.usage_to_hours(project_usage)
                projects[project_id][statistics_key] = project_dict

        ans_dict = {
            "period_start": utils.datetime_to_str(period_start),
            "period_end": utils.datetime_to_str(period_end),
            "projects": projects.values(),
        }
        return webob.Response(json.dumps(ans_dict),
                              content_type='application/json')
Beispiel #2
0
 def test_total_seconds(self):
     begin_at = datetime.datetime(2011, 1, 12, 0, 0)
     end_at = datetime.datetime(2011, 1, 12, 0, 1)
     seconds = utils.total_seconds(end_at - begin_at)
     self.assertEquals(seconds, 60)
Beispiel #3
0
def images_on_interval(period_start, period_stop, auth_tok, tenant_id=None):
    """
    Retrieve images statistics for the given interval [``period_start``, ``period_stop``]. 
    ``tenant_id=None`` means all projects.

    Example of the returned value:

    .. code-block:: python

        {
            "1": {
                12: {
                    "created_at": datetime.datetime(2011, 1, 1),
                    "destroyed_at": datetime.datetime(2011, 1, 2),
                    "name": "Gentoo initrd",
                    "usage": {"local_gb": 0.1},
                },
                14: {
                    "created_at": datetime.datetime(2011, 1, 4),
                    "destroyed_at": datetime.datetime(2011, 2, 1),
                    "name": "Ubuntu vmlinuz",
                    "usage": {"local_gb": 2.5},
                },
            },
            "2": {
                24: {
                    "created_at": datetime.datetime(2011, 1, 1),
                    "destroyed_at": datetime.datetime(2011, 1, 2),
                    "name": "RHEL vmlinuz",
                    "usage": {"local_gb": 6.1},
                },
            }
        }

    :returns: a dictionary where keys are project ids and values are project statistics.
    """

    glance_host, glance_port = pick_glance_api_server()
    client = glance_client.Client(glance_host, glance_port, auth_tok=auth_tok)
    images = client.get_images_detailed(filters={"is_public": "none"})
    if tenant_id:
        images = [image for image in images if image["owner"] == tenant_id]
    else:
        images = [image for image in images if image["owner"] is not None]
    report_by_id = {}
    now = utils.now()
    for image in images:
        created_at = utils.str_to_datetime(image["created_at"])
        if created_at >= period_stop:
            continue
        deleted_at = utils.str_to_datetime(image["deleted_at"])
        if deleted_at and deleted_at <= period_start:
            continue
        lifetime = utils.total_seconds(
            min(deleted_at or now, period_stop) -
            max(created_at, period_start))
        if lifetime < 0:
            lifetime = 0
        try:
            tenant_statistics = report_by_id[image["owner"]]
        except KeyError:
            tenant_statistics = {}
            report_by_id[image["owner"]] = tenant_statistics
        tenant_statistics[image["id"]] = {
            "name": image["name"],
            "created_at": created_at,
            "destroyed_at": deleted_at,
            "usage": {"local_gb": image["size"] * lifetime / 2 ** 30}
        }

    return report_by_id