Ejemplo n.º 1
0
def test_tickets_extend_no_ticket_id(fake_time):
    ticket = testutils.create_ticket()
    tickets.add(ticket)
    prev_ticket = tickets.get(ticket["uuid"]).info()
    body = json.dumps({"timeout": 300})
    res = http.unix_request(config.tickets.socket, "PATCH", "/tickets/", body)
    cur_ticket = tickets.get(ticket["uuid"]).info()
    assert res.status == 400
    assert cur_ticket == prev_ticket
Ejemplo n.º 2
0
def test_tickets_extend_invalid_json(fake_time):
    ticket = testutils.create_ticket()
    tickets.add(ticket)
    prev_ticket = tickets.get(ticket["uuid"]).info()
    res = http.unix_request(config.tickets.socket, "PATCH",
                            "/tickets/%(uuid)s" % ticket, "{invalid}")
    cur_ticket = tickets.get(ticket["uuid"]).info()
    assert res.status == 400
    assert cur_ticket == prev_ticket
Ejemplo n.º 3
0
def test_tickets_idle_time_inactive(fake_time):
    ticket = testutils.create_ticket()
    tickets.add(ticket)

    # Ticket idle time starts with ticket is added.
    assert tickets.get(ticket["uuid"]).idle_time == 0

    # Simulate time passing without any request.
    fake_time.now += 200
    assert tickets.get(ticket["uuid"]).idle_time == 200
Ejemplo n.º 4
0
def test_tickets_extend_expired_ticket(fake_time):
    ticket = testutils.create_ticket()
    tickets.add(ticket)
    # Make the ticket expire.
    fake_time.now += 500
    server_ticket = tickets.get(ticket["uuid"]).info()
    # Extend the expired ticket.
    body = json.dumps({"timeout": 300})
    res = http.unix_request(config.tickets.socket, "PATCH",
                            "/tickets/%(uuid)s" % ticket, body)
    assert res.status == 200
    server_ticket = tickets.get(ticket["uuid"]).info()
    assert server_ticket["expires"] == 800
Ejemplo n.º 5
0
def test_images_options_ticket_expired(fake_time):
    ticket = testutils.create_ticket(timeout=300)
    tickets.add(ticket)
    server_ticket = tickets.get(ticket["uuid"]).info()
    assert server_ticket["expires"] == 300

    # Make the ticket expire
    fake_time.now += 300
    res = http.options("/images/" + ticket["uuid"])
    assert res.status == 403

    server_ticket = tickets.get(ticket["uuid"]).info()
    assert server_ticket["expires"] == 300
Ejemplo n.º 6
0
def test_images_options_extends_ticket(fake_time):
    ticket = testutils.create_ticket()
    tickets.add(ticket)
    server_ticket = tickets.get(ticket["uuid"]).info()
    assert server_ticket["expires"] == 300

    fake_time.now += 200
    res = http.options("/images/" + ticket["uuid"])
    assert res.status == 200

    res.read()
    server_ticket = tickets.get(ticket["uuid"]).info()
    assert server_ticket["expires"] == 500
Ejemplo n.º 7
0
def test_images_upload_extends_ticket(tmpdir, fake_time):
    image = testutils.create_tempfile(tmpdir, "image", "before")
    ticket = testutils.create_ticket(url="file://" + str(image))
    tickets.add(ticket)
    server_ticket = tickets.get(ticket["uuid"]).info()
    assert server_ticket["expires"] == 300

    fake_time.now += 200
    res = http.put("/images/" + ticket["uuid"], "")
    assert res.status == 200

    res.read()
    server_ticket = tickets.get(ticket["uuid"]).info()
    assert server_ticket["expires"] == 500
Ejemplo n.º 8
0
def test_images_download_extends_ticket(tmpdir, fake_time):
    size = 1024
    image = testutils.create_tempfile(tmpdir, "image", size=size)
    ticket = testutils.create_ticket(url="file://" + str(image), size=size)
    tickets.add(ticket)
    server_ticket = tickets.get(ticket["uuid"]).info()
    assert server_ticket["expires"] == 300

    fake_time.now += 200
    res = http.get("/images/" + ticket["uuid"])
    assert res.status == 200

    res.read()
    server_ticket = tickets.get(ticket["uuid"]).info()
    assert server_ticket["expires"] == 500
Ejemplo n.º 9
0
def test_download_progress(tmpdir):
    size = 1024**2 * 50
    filename = tmpdir.join("image")
    with open(str(filename), 'wb') as image:
        image.truncate(size)
    ticket = testutils.create_ticket(url="file://" + str(filename),
                                     ops=["read"],
                                     size=size)
    add_ticket(ticket)
    ticket = tickets.get(ticket["uuid"])

    # No operations
    assert not ticket.active()
    assert ticket.transferred() == 0

    res = download(ticket.uuid)

    res.read(1024**2)
    # The server has sent some chunks
    assert ticket.active()
    assert 0 < ticket.transferred() < size

    res.read()
    # The server has sent all the chunks - download completed
    assert not ticket.active()
    assert ticket.transferred() == size
Ejemplo n.º 10
0
def test_download_progress(tmpdir):
    size = 1024**2 * 10
    filename = tmpdir.join("image")
    with open(str(filename), 'wb') as image:
        image.truncate(size)
    ticket = testutils.create_ticket(url="file://" + str(filename),
                                     ops=["read"],
                                     size=size)
    tickets.add(ticket)
    ticket = tickets.get(ticket["uuid"])

    # No operations
    assert not ticket.active()
    assert ticket.transferred() == 0

    res = http.get("/images/" + ticket.uuid)
    res.read(1024**2)
    # The server has sent some chunks
    assert ticket.active()
    assert 0 < ticket.transferred() < size

    res.read()

    # The server has sent all the chunks but we need to give it time to
    # touch the ticket.
    time.sleep(0.2)

    assert not ticket.active()
    assert ticket.transferred() == size
Ejemplo n.º 11
0
def test_images_flush_extends_ticket(tmpdir, fake_time):
    data = "x" * 512
    image = testutils.create_tempfile(tmpdir, "image", data)
    ticket = testutils.create_ticket(url="file://" + str(image))
    tickets.add(ticket)
    server_ticket = tickets.get(ticket["uuid"]).info()
    assert server_ticket["expires"] == 300

    fake_time.now += 200
    body = json.dumps({"op": "flush"}).encode("ascii")
    res = http.patch("/images/" + ticket["uuid"], body)
    assert res.status == 200

    res.read()
    server_ticket = tickets.get(ticket["uuid"]).info()
    assert server_ticket["expires"] == 500
Ejemplo n.º 12
0
def test_tickets_idle_time_options(fake_time):
    ticket = testutils.create_ticket(url="file:///no/such/file")
    tickets.add(ticket)

    # Request must reset idle time.
    fake_time.now += 200
    http.options("/images/" + ticket["uuid"])
    assert tickets.get(ticket["uuid"]).idle_time == 0
Ejemplo n.º 13
0
def test_tickets_idle_time_get(fake_time, tmpdir):
    image = testutils.create_tempfile(tmpdir, "image", "a" * 8192)
    ticket = testutils.create_ticket(url="file://" + str(image))
    tickets.add(ticket)

    # Request must reset idle time.
    fake_time.now += 200
    http.get("/images/" + ticket["uuid"])
    assert tickets.get(ticket["uuid"]).idle_time == 0
Ejemplo n.º 14
0
def test_tickets_idle_time_patch(fake_time, tmpdir, msg):
    image = testutils.create_tempfile(tmpdir, "image", "a" * 8192)
    ticket = testutils.create_ticket(url="file://" + str(image))
    tickets.add(ticket)

    # Request must reset idle time.
    fake_time.now += 200
    body = json.dumps(msg).encode('ascii')
    http.patch("/images/" + ticket["uuid"],
               body,
               headers={"content-type": "application/json"})
    assert tickets.get(ticket["uuid"]).idle_time == 0
Ejemplo n.º 15
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 = tickets.get(ticket["uuid"]).info()
    assert res.status == 200
    assert res.getheader("content-length") == "0"
    assert server_ticket == ticket
Ejemplo n.º 16
0
def test_tickets_extend(fake_time):
    ticket = testutils.create_ticket(sparse=False)
    tickets.add(ticket)
    patch = {"timeout": 300}
    body = json.dumps(patch)
    fake_time.now += 240
    res = http.unix_request(config.tickets.socket, "PATCH",
                            "/tickets/%(uuid)s" % ticket, body)
    ticket["expires"] = int(fake_time.now + ticket["timeout"])
    ticket["active"] = False
    ticket["idle_time"] = 240
    server_ticket = tickets.get(ticket["uuid"]).info()
    assert res.status == 200
    assert res.getheader("content-length") == "0"
    assert server_ticket == ticket
Ejemplo n.º 17
0
def test_tickets_idle_time_active(fake_time, tmpdir):
    filename = tmpdir.join("image")
    # Note: must be big enough so the request remain active.
    size = 1024**2 * 10
    with open(str(filename), 'wb') as image:
        image.truncate(size)
    ticket = testutils.create_ticket(url="file://" + str(filename),
                                     ops=["read"],
                                     size=size)
    tickets.add(ticket)

    # Start a download, but read only 1 byte to make sure the operation becomes
    # active but do not complete.
    res = http.get("/images/" + ticket["uuid"])
    res.read(1)

    # Active ticket idle time is always 0.
    fake_time.now += 200
    assert tickets.get(ticket["uuid"]).idle_time == 0
Ejemplo n.º 18
0
def get_ticket(uuid):
    # Get a copy of the current server ticket, simulating a get request
    ticket = tickets.get(uuid)
    ticket = json.loads(json.dumps(ticket))
    ticket["url"] = urllib_parse.urlunparse(ticket["url"])
    return ticket
Ejemplo n.º 19
0
    def post(self, ticket_id):
        if not ticket_id:
            raise HTTPBadRequest("Ticket id is required")

        body = self.request.body
        methodargs = json.loads(body)
        if not 'backup_path' in methodargs:
            raise HTTPBadRequest(
                "Malformed request. Requires backup_path in the body")

        destdir = os.path.split(methodargs['backup_path'])[0]
        if not os.path.exists(destdir):
            raise HTTPBadRequest("Backup_path does not exists")

        with open(os.path.join(CONF_DIR, "daemon.conf")) as f:
            sample_config = f.read()
        config = ConfigParser.RawConfigParser(allow_no_value=True)
        config.readfp(io.BytesIO(sample_config))

        nfsshare = config.get('nfs_config', 'nfs_share')
        mountpath = config.get('nfs_config', 'mount_path')
        if not nfs_mount.is_mounted(nfsshare, mountpath):
            if not nfs_mount.mount_backup_target(nfsshare, mountpath):
                raise HTTPBadRequest("Backup target not mounted.")

        # TODO: cancel copy if ticket expired or revoked
        if methodargs['method'] == 'backup':
            offset = 0
            size = None
            if self.request.range:
                offset = self.request.range.start
                if self.request.range.end is not None:
                    size = self.request.range.end - offset

            ticket = tickets.authorize(ticket_id, "read", 0, size)

            self.log.debug("disk %s to %s for ticket %s", body,
                           ticket.url.path, ticket_id)
            try:
                ctask = celery_tasks.backup.apply_async(
                    (ticket_id, ticket.url.path, methodargs['backup_path'],
                     tickets.get(ticket_id).size, methodargs['type'],
                     self.config.daemon.buffer_size,
                     methodargs['recent_snap_id']),
                    #queue='backup_tasks',
                    retry=True,
                    retry_policy={
                        'max_retries': 3,
                        'interval_start': 3,
                        'interval_step': 0.5,
                        'interval_max': 0.5,
                    })
            except celery_tasks.backup.OperationalError as exc:
                self.log.info("Submitting celery task raised: %r", exc)
            print "Submitted backup"
        elif methodargs['method'] == 'restore':
            size = self.request.content_length
            if size is None:
                raise HTTPBadRequest("Content-Length header is required")
            if size < 0:
                raise HTTPBadRequest("Invalid Content-Length header: %r" %
                                     size)
            content_range = web.content_range(self.request)
            offset = content_range.start or 0

            ticket = tickets.authorize(ticket_id, "write", offset, size)
            self.log.debug("disk %s to %s for ticket %s", body,
                           ticket.url.path, ticket_id)
            try:
                ctask = celery_tasks.restore.apply_async(
                    (ticket_id, ticket.url.path, methodargs['backup_path'],
                     tickets.get(ticket_id).size,
                     self.config.daemon.buffer_size),
                    #queue='restore_tasks',
                    retry=True,
                    retry_policy={
                        'max_retries': 3,
                        'interval_start': 3,
                        'interval_step': 0.5,
                        'interval_max': 0.5,
                    })
            except celery_tasks.backup.OperationalError as exc:
                self.log.info("Submitting celery task raised: %r", exc)
            print "Submitted restore"
        else:
            raise HTTPBadRequest("Invalid method")

        r = response(status=206)
        r.headers["Location"] = "/tasks/%s" % ctask.id
        return r
Ejemplo n.º 20
0
def get_ticket(uuid):
    return tickets.get(uuid).info()