Exemplo n.º 1
0
 def __call__(self, req):
     resp = req.get_response(self.application)
     path_info = req.environ.get("PATH_INFO", "/")
     if not path_info.startswith("/images"):
         return resp
     method = req.environ.get("REQUEST_METHOD", "GET")
     if method == "PUT" or method == "POST":
         try:
             resp_json = json.loads(resp.body)
             img_id, img_size = resp_json["image"]["id"], resp_json[
                 "image"]["size"]
         except KeyError:
             return resp
         heart_request = {"name": img_id, "linear": img_size / (1024.0**3)}
     elif method == "DELETE":
         heart_request = {
             "name": path_info[len("/images/"):],
             "fixed": None
         }
     else:
         heart_request = None
     if heart_request is not None:
         heart_request["rtype"] = "glance/image"
         heart_request["account"] = req.headers["X-Tenant-Id"]
         heart_request["datetime"] = utils.datetime_to_str(utils.now())
         try:
             self.billing_heart.event.create(heart_request)
         except:
             LOG.exception("cannot report image info for billing")
     return resp
Exemplo n.º 2
0
 def __call__(self, req):
     resp = req.get_response(self.application)
     path_info = req.environ.get("PATH_INFO", "/")
     if not path_info.startswith("/images"):
         return resp
     method = req.environ.get("REQUEST_METHOD", "GET")
     if method == "PUT" or method == "POST":
         try:
             resp_json = json.loads(resp.body)
             img_id, img_size = resp_json["image"]["id"], resp_json["image"]["size"]
         except KeyError:
             return resp
         heart_request = {"name": img_id,
                          "linear": img_size / (1024.0 ** 3)}
     elif method == "DELETE":
         heart_request = {"name": path_info[len("/images/"):],
                          "fixed": None}
     else:
         heart_request = None
     if heart_request is not None:
         heart_request["rtype"] = "glance/image"
         heart_request["account"] = req.headers["X-Tenant-Id"]
         heart_request["datetime"] = utils.datetime_to_str(utils.now())
         try:
             self.billing_heart.event.create(heart_request)
         except:
             LOG.exception("cannot report image info for billing")
     return resp
Exemplo n.º 3
0
def get_period():
    if not request.args.has_key("time_period"):
        if "period_start" in request.args:
            period_start = utils.str_to_datetime(request.args["period_start"])
            try:
                period_end = utils.str_to_datetime(request.args["period_end"])
            except KeyError:
                raise BadRequest(description="period_end is request.ired")
            if not (period_start and period_end):
                raise BadRequest(
                    description=
                    "date should be in ISO 8601 format of YYYY-MM-DDThh:mm:ssZ"
                )
            if period_start >= period_end:
                raise BadRequest(
                    description="period_start must be less than period_end")
            return period_start, period_end
        else:
            now = utils.now()
            date_args = (now.year, now.month, 1)
            date_incr = 1
    else:
        time_period_splitted = request.args["time_period"].split("-", 2)
        date_args = [1, 1, 1]
        for i in xrange(min(2, len(time_period_splitted))):
            try:
                date_args[i] = int(time_period_splitted[i])
            except ValueError:
                raise BadRequest(description="invalid time_period `%s'" %
                                 request.args["time_period"])
        date_incr = len(time_period_splitted) - 1

    period_start = datetime.datetime(*date_args)
    if date_incr == 2:
        period_end = period_start + datetime.timedelta(days=1)
    else:
        year, month, day = date_args
        if date_incr == 1:
            month += 1
            if month > 12:
                month = 1
                year += 1
        else:
            year += 1
        period_end = datetime.datetime(year=year, month=month, day=day)
    return period_start, period_end
Exemplo n.º 4
0
def get_period():
    if not request.args.has_key("time_period"):
        if "period_start" in request.args:
            period_start = utils.str_to_datetime(request.args["period_start"])
            try:
                period_end = utils.str_to_datetime(request.args["period_end"])
            except KeyError:
                raise BadRequest(description="period_end is request.ired")
            if not (period_start and period_end):
                raise BadRequest(
                    description="date should be in ISO 8601 format of YYYY-MM-DDThh:mm:ssZ")
            if period_start >= period_end:
                raise BadRequest(
                    description="period_start must be less than period_end")
            return period_start, period_end
        else:
            now = utils.now()
            date_args = (now.year, now.month, 1)
            date_incr = 1
    else:
        time_period_splitted = request.args["time_period"].split("-", 2)
        date_args = [1, 1, 1]
        for i in xrange(min(2, len(time_period_splitted))):
            try:
                date_args[i] = int(time_period_splitted[i])
            except ValueError:
                raise BadRequest(
                    description="invalid time_period `%s'" % request.args["time_period"])
        date_incr = len(time_period_splitted) - 1

    period_start = datetime.datetime(*date_args)
    if date_incr == 2:
        period_end = period_start + datetime.timedelta(days=1)
    else:
        year, month, day = date_args
        if date_incr == 1:
            month += 1
            if month > 12:
                month = 1
                year += 1
        else:
            year += 1
        period_end = datetime.datetime(year=year, month=month, day=day)
    return period_start, period_end
Exemplo n.º 5
0
 def get_event_datetime(self, body):
     return utils.now()
Exemplo n.º 6
0
 def get_event_datetime(self, body):
     return utils.now()
Exemplo n.º 7
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')
Exemplo n.º 8
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