Пример #1
0
    def put(self, ticket_id):
        # TODO
        # - reject invalid or expired ticket
        # - start expire timer
        if not ticket_id:
            raise HTTPBadRequest("Ticket id is required")
        try:
            ticket = self.request.json
        except ValueError as e:
            raise HTTPBadRequest("Invalid ticket: %s" % e)
        try:
            timeout = ticket["timeout"]
        except KeyError:
            raise HTTPBadRequest("Missing timeout key")
        try:
            timeout = int(timeout)
        except ValueError as e:
            raise HTTPBadRequest("Invalid timeout value: %s" % e)
        try:
            url_str = ticket["url"]
        except KeyError:
            raise HTTPBadRequest("Missing url key in ticket")
        try:
            ticket["url"] = urllib_parse.urlparse(url_str)
        except (ValueError, AttributeError, TypeError):
            raise HTTPBadRequest("Invalid url string %r" % url_str)

        if ticket["url"].scheme not in supported_schemes:
            raise HTTPBadRequest("url scheme is not supported "
                                 "for url: %s" % ticket["url"].scheme)

        ticket["expires"] = int(util.monotonic_time()) + timeout
        tickets.add(ticket_id, ticket)
        return response()
Пример #2
0
    def __init__(self, ticket_dict):
        if not isinstance(ticket_dict, dict):
            raise errors.InvalidTicket(
                "Invalid ticket: %r, expecting a dict" % ticket_dict)

        self._uuid = _required(ticket_dict, "uuid", six.string_types)
        self._size = _required(ticket_dict, "size", six.integer_types)
        self._ops = _required(ticket_dict, "ops", list)

        self._timeout = _required(ticket_dict, "timeout", six.integer_types)
        now = int(util.monotonic_time())
        self._expires = now + self._timeout
        self._access_time = now

        url_str = _required(ticket_dict, "url", six.string_types)
        try:
            self._url = urllib_parse.urlparse(url_str)
        except (ValueError, AttributeError, TypeError) as e:
            raise errors.InvalidTicketParameter("url", url_str, e)
        if self._url.scheme not in supported_schemes:
            raise errors.InvalidTicketParameter(
                "url", url_str,
                "Unsupported url scheme: %s" % self._url.scheme)

        self._filename = _optional(ticket_dict, "filename", six.string_types)
        self._sparse = _optional(ticket_dict, "sparse", bool, default=False)
        self._operations = []
        self._lock = threading.Lock()

        # Set holding ongoing operations.
        self._ongoing = set()

        # Ranges transferred by completed operations.
        self._completed = []
Пример #3
0
    def __init__(self, ticket_dict):
        if not isinstance(ticket_dict, dict):
            raise errors.InvalidTicket(
                "Invalid ticket: %r, expecting a dict" % ticket_dict)

        self._uuid = _required(ticket_dict, "uuid")
        self._size = _required(ticket_dict, "size")
        self._ops = _required(ticket_dict, "ops")

        timeout = _required(ticket_dict, "timeout")
        try:
            timeout = int(timeout)
        except ValueError as e:
            raise errors.InvalidTicketParameter("timeout", timeout, e)

        now = int(util.monotonic_time())
        self._expires = now + timeout
        self._access_time = now

        url_str = _required(ticket_dict, "url")
        try:
            self._url = urllib_parse.urlparse(url_str)
        except (ValueError, AttributeError, TypeError) as e:
            raise errors.InvalidTicketParameter("url", url_str, e)
        if self._url.scheme not in supported_schemes:
            raise errors.InvalidTicketParameter(
                "url", url_str,
                "Unsupported url scheme: %s" % self._url.scheme)

        self._filename = ticket_dict.get("filename")
        self._operations = []
        self._lock = threading.Lock()
Пример #4
0
def add_ticket(ticket):
    # Simulate adding a ticket to the server, without modifying the source
    # ticket.
    ticket = json.loads(json.dumps(ticket))
    ticket["expires"] = int(util.monotonic_time()) + ticket["timeout"]
    ticket["url"] = urllib_parse.urlparse(ticket["url"])
    tickets.add(ticket["uuid"], ticket)
Пример #5
0
 def idle_time(self):
     """
     Return the time in which the ticket became inactive.
     """
     if self.active():
         return 0
     return int(util.monotonic_time()) - self._access_time
Пример #6
0
 def idle_time(self):
     """
     Return the time in which the ticket became inactive.
     """
     if self.active():
         return 0
     return int(util.monotonic_time()) - self._access_time
Пример #7
0
    def touch(self):
        """
        Extend the ticket and update the last access time.

        Must be called when an operation is completed.
        """
        now = int(util.monotonic_time())
        self._expires = now + self._timeout
        self._access_time = now
Пример #8
0
    def touch(self):
        """
        Extend the ticket and update the last access time.

        Must be called when an operation is completed.
        """
        now = int(util.monotonic_time())
        self._expires = now + self._timeout
        self._access_time = now
Пример #9
0
def test_tickets_put(fake_time):
    ticket = testutils.create_ticket()
    body = json.dumps(ticket)
    res = unix_request("PUT", "/tickets/%(uuid)s" % ticket, body)
    # Server adds expires key
    ticket["expires"] = int(util.monotonic_time()) + ticket["timeout"]
    ticket["active"] = False
    server_ticket = get_ticket(ticket["uuid"])
    assert res.status == 200
    assert server_ticket == ticket
Пример #10
0
def test_tickets_put(monkeypatch):
    monkeypatch.setattr(util, "monotonic_time", lambda: 123456789)
    ticket = create_ticket()
    body = json.dumps(ticket)
    res = unix_request("PUT", "/tickets/%(uuid)s" % ticket, body)
    # Server adds expires key
    ticket["expires"] = int(util.monotonic_time()) + ticket["timeout"]
    server_ticket = get_ticket(ticket["uuid"])
    assert res.status == 200
    assert server_ticket == ticket
Пример #11
0
def test_tickets_put(fake_time):
    ticket = testutils.create_ticket(sparse=False)
    body = json.dumps(ticket)
    res = http.unix_request(
        config.tickets.socket, "PUT", "/tickets/%(uuid)s" % ticket, body)
    # Server adds expires key
    ticket["expires"] = int(util.monotonic_time()) + ticket["timeout"]
    ticket["active"] = False
    ticket["idle_time"] = 0
    server_ticket = auth.get(ticket["uuid"]).info()
    assert res.status == 200
    assert res.getheader("content-length") == "0"
    assert server_ticket == ticket
Пример #12
0
def test_tickets_put(fake_time):
    ticket = testutils.create_ticket(sparse=False)
    body = json.dumps(ticket)
    res = http.unix_request(
        config.tickets.socket, "PUT", "/tickets/%(uuid)s" % ticket, body)
    # Server adds expires key
    ticket["expires"] = int(util.monotonic_time()) + ticket["timeout"]
    ticket["active"] = False
    ticket["idle_time"] = 0
    server_ticket = auth.get(ticket["uuid"]).info()
    assert res.status == 200
    assert res.getheader("content-length") == "0"
    assert server_ticket == ticket
Пример #13
0
 def info(self):
     info = {
         "active": self.active(),
         "expires": self._expires,
         "ops": list(self._ops),
         "size": self._size,
         "timeout": self.expires - int(util.monotonic_time()),
         "url": urllib_parse.urlunparse(self._url),
         "uuid": self._uuid,
     }
     if self.filename:
         info["filename"] = self.filename
     transferred = self.transferred()
     if transferred is not None:
         info["transferred"] = transferred
     return info
Пример #14
0
def authorize(ticket_id, op, size):
    """
    Authorizing a ticket operation
    """
    log.debug("Authorizing %r to offset %d for ticket %s", op, size, ticket_id)
    try:
        ticket = _tickets[ticket_id]
    except KeyError:
        raise HTTPForbidden("No such ticket %r" % ticket_id)
    if ticket["expires"] <= util.monotonic_time():
        raise HTTPForbidden("Ticket %r expired" % ticket_id)
    if op not in ticket["ops"]:
        raise HTTPForbidden("Ticket %r forbids %r" % (ticket_id, op))
    if size > ticket["size"]:
        raise HTTPForbidden("Content-Length out of allowed range")
    return ticket
Пример #15
0
def authorize(ticket_id, op, offset, size):
    """
    Authorizing a ticket operation
    """
    log.debug("Authorizing op=%r, offset=%r, size=%r, for ticket %s",
              op, offset, size, ticket_id)
    try:
        ticket = _tickets[ticket_id]
    except KeyError:
        raise HTTPForbidden("No such ticket %r" % ticket_id)
    if ticket.expires <= util.monotonic_time():
        raise HTTPForbidden("Ticket %r expired" % ticket_id)
    if not ticket.may(op):
        raise HTTPForbidden("Ticket %r forbids %r" % (ticket_id, op))
    end = (offset + size) if size else offset
    if end > ticket.size:
        raise HTTPForbidden("Requested range out of allowed range")
    return ticket
Пример #16
0
def authorize(ticket_id, op):
    """
    Authorizing a ticket operation
    """
    log.debug("AUTH op=%s ticket=%s", op, ticket_id)
    try:
        ticket = _tickets[ticket_id]
    except KeyError:
        raise errors.AuthorizationError("No such ticket {}".format(ticket_id))

    if ticket.expires <= util.monotonic_time():
        raise errors.AuthorizationError("Ticket {} expired".format(ticket_id))

    if not ticket.may(op):
        raise errors.AuthorizationError("Ticket {} forbids {}".format(
            ticket_id, op))

    return ticket
Пример #17
0
def authorize(ticket_id, op, offset, size):
    """
    Authorizing a ticket operation
    """
    log.debug("AUTH op=%s offset=%s size=%s ticket=%s",
              op, offset, size, ticket_id)
    try:
        ticket = _tickets[ticket_id]
    except KeyError:
        raise errors.AuthorizationError("No such ticket {}".format(ticket_id))

    if ticket.expires <= util.monotonic_time():
        raise errors.AuthorizationError("Ticket {} expired".format(ticket_id))

    if not ticket.may(op):
        raise errors.AuthorizationError(
            "Ticket {} forbids {}".format(ticket_id, op))

    end = (offset + size) if size else offset
    if end > ticket.size:
        raise errors.AuthorizationError("Requested range out of allowed range")

    return ticket
Пример #18
0
    def __init__(self, ticket_dict):
        if not isinstance(ticket_dict, dict):
            raise errors.InvalidTicket(
                "Invalid ticket: %r, expecting a dict" % ticket_dict)

        self._uuid = _required(ticket_dict, "uuid", six.string_types)
        self._size = _required(ticket_dict, "size", six.integer_types)
        self._ops = _required(ticket_dict, "ops", list)

        self._timeout = _required(ticket_dict, "timeout", six.integer_types)
        now = int(util.monotonic_time())
        self._expires = now + self._timeout
        self._access_time = now

        url_str = _required(ticket_dict, "url", six.string_types)
        try:
            self._url = urllib_parse.urlparse(url_str)
        except (ValueError, AttributeError, TypeError) as e:
            raise errors.InvalidTicketParameter("url", url_str, e)
        if not backends.supports(self._url.scheme):
            raise errors.InvalidTicketParameter(
                "url", url_str,
                "Unsupported url scheme: %s" % self._url.scheme)

        self._transfer_id = _optional(
            ticket_dict, "transfer_id", six.string_types)
        self._filename = _optional(ticket_dict, "filename", six.string_types)
        self._sparse = _optional(ticket_dict, "sparse", bool, default=False)

        self._operations = []
        self._lock = threading.Lock()

        # Set holding ongoing operations.
        self._ongoing = set()

        # Ranges transferred by completed operations.
        self._completed = []
Пример #19
0
 def patch(self, ticket_id):
     # TODO: restart expire timer
     if not ticket_id:
         raise HTTPBadRequest("Ticket id is required")
     try:
         patch = self.request.json
     except ValueError as e:
         raise HTTPBadRequest("Invalid patch: %s" % e)
     try:
         timeout = patch["timeout"]
     except KeyError:
         raise HTTPBadRequest("Missing timeout key")
     try:
         timeout = int(timeout)
     except ValueError as e:
         raise HTTPBadRequest("Invalid timeout value: %s" % e)
     try:
         ticket = tickets.get(ticket_id)
     except KeyError:
         raise HTTPNotFound("No such ticket: %s" % ticket_id)
     ticket["expires"] = int(util.monotonic_time()) + timeout
     self.log.info("Extending ticket %s, new expiration in %d", ticket_id,
                   ticket["expires"])
     return response()
Пример #20
0
def test_monotonic_time():
    t1 = util.monotonic_time()
    time.sleep(0.01)
    t2 = util.monotonic_time()
    assert t1 <= t2
Пример #21
0
def test_monotonic_time():
    t1 = util.monotonic_time()
    time.sleep(0.01)
    t2 = util.monotonic_time()
    assert t1 <= t2
Пример #22
0
 def extend(self, timeout):
     expires = int(util.monotonic_time()) + timeout
     self._expires = expires
Пример #23
0
 def extend(self, timeout):
     expires = int(util.monotonic_time()) + timeout
     log.info("Extending ticket %s, new expiration in %d",
              self._uuid, expires)
     self._expires = expires
Пример #24
0
 def touch(self):
     """
     Update the ticket access time. Must be called when an operation is
     completed.
     """
     self._access_time = int(util.monotonic_time())
Пример #25
0
 def extend(self, timeout):
     expires = int(util.monotonic_time()) + timeout
     self._expires = expires