예제 #1
0
 def fake_send_request(request_type, **kwargs):
     for arg in ["uid", "gid"]:
         assert arg in kwargs.keys()
     assert request_type == HttpFsRequest.OP_READDIR
     assert kwargs["path"] == fake_path
     resp = HttpFsResponse()
     resp._response_data["dir_listing"] = list()
     return resp
예제 #2
0
 def fake_send_request(request_type, **kwargs):
     assert request_type == HttpFsRequest.OP_CREATE
     for required_key in ["uid", "gid"]:
         assert required_key in kwargs.keys()
     assert kwargs["path"] == fake_path
     assert kwargs["mode"] == fake_mode
     resp = HttpFsResponse()
     resp._response_data["file_descriptor"] = 0
     return resp
예제 #3
0
 def fake_send_request(request_type, **kwargs):
     for arg in ["uid", "gid"]:
         assert arg in kwargs.keys()
     assert request_type == HttpFsRequest.OP_WRITE
     assert kwargs["file_descriptor"] == fake_fd
     assert kwargs["data"] == base64.standard_b64encode(fake_data).decode("utf-8")
     assert kwargs["offset"] == fake_offset
     resp = HttpFsResponse()
     resp._response_data["bytes_written"] = 10
     return resp
예제 #4
0
 def on_invalid_request(self, err_msg):
     """
     Called when invalid JSON has been sent as a request from a client
     :param err_msg: The error message
     """
     logging.debug("Invalid request received from {}: '{}'".format(
         self.client_address[0], err_msg))
     response_obj = HttpFsResponse(errno.EIO, {"message": err_msg})
     self.send_json_response(http.HTTPStatus.BAD_REQUEST,
                             response_obj.as_dict())
예제 #5
0
 def fake_send_request(request_type, **kwargs):
     for arg in ["uid", "gid"]:
         assert arg in kwargs.keys()
     assert request_type == HttpFsRequest.OP_READ
     assert kwargs["file_descriptor"] == fake_fd
     assert kwargs["size"] == fake_size
     assert kwargs["offset"] == fake_offset
     resp = HttpFsResponse()
     resp._response_data["bytes_read"] = bytes()
     return resp
예제 #6
0
    def on_readdir(self, httpfs_request_args):
        """
        Called when HttpFsRequest.OP_READDIR is requested
        :param httpfs_request_args: The client request args dict
        """
        path = self.get_abs_path(httpfs_request_args["path"])
        uid = httpfs_request_args["uid"]
        gid = httpfs_request_args["gid"]

        file_stats = os.stat(path)
        is_owner = file_stats.st_uid == uid
        is_group = file_stats.st_gid == gid

        response_obj = HttpFsResponse()

        if uid == 0:
            access_ok = True
        elif is_owner:
            access_ok = file_stats.st_mode & stat.S_IRUSR
        elif is_group:
            access_ok = file_stats.st_mode & stat.S_IRGRP
        else:
            access_ok = file_stats.st_mode & stat.S_IROTH

        if access_ok:
            dir_listing = os.listdir(path)
            dir_listing = [".", ".."] + dir_listing
            response_obj.set_data({"dir_listing": dir_listing})
        else:
            logging.warning("Error during readdir request: Access denied")
            response_obj.set_err_no(errno.EACCES)
            response_obj.set_data({"message": "Access denied"})

        self.send_json_response(200, response_obj.as_dict())
예제 #7
0
    def on_statfs(self, httpfs_request_args):
        """
        Called when HttpFsRequest.OP_STAT_FS is received from the client
        :param httpfs_request_args: The client request arg dict
        """
        fs_path = self.get_abs_path(httpfs_request_args["path"])
        statfs_os_result = os.statvfs(fs_path)
        statfs_result = dict()

        for k in _HttpFsRequestHandler.STAT_FS_KEYS:
            statfs_result[k] = getattr(statfs_os_result, k)

        response_obj = HttpFsResponse(response_data=statfs_result)
        self.send_json_response(200, response_obj.as_dict())
예제 #8
0
    def on_release(self, httpfs_request_args):
        """
        Called when HttpFsRequest.OP_RELEASE is requested
        :param httpfs_request_args: The client request args dict
        """
        response_obj = HttpFsResponse()

        try:
            os.close(httpfs_request_args["file_descriptor"])
        except Exception as e:
            logging.error("Error during release request: {}".format(e))
            response_obj.set_err_no(errno.EIO)

        self.send_json_response(200, response_obj.as_dict())
예제 #9
0
 def fake_send_request(request_type, **kwargs):
     for arg in ["uid", "gid"]:
         assert arg in kwargs.keys()
     assert request_type == HttpFsRequest.OP_RENAME
     assert kwargs["old_path"] == fake_old_path
     assert kwargs["new_path"] == fake_new_path
     return HttpFsResponse()
예제 #10
0
    def on_symlink(self, httpfs_request_args):
        """
        Called when HttpFsRequest.OP_SYMLINK is received from the client
        :param httpfs_request_args: The client request arg dict
        """
        response_obj = HttpFsResponse()
        source = self.get_abs_path(httpfs_request_args["source"])
        target = self.get_abs_path(httpfs_request_args["target"])

        try:
            os.symlink(source, target)
        except Exception as e:
            logging.error("Error during symlink request: {}".format(e))
            response_obj.set_err_no(errno.EIO)

        self.send_json_response(200, response_obj.as_dict())
예제 #11
0
 def fake_send_request(request_type, **kwargs):
     for arg in ["uid", "gid"]:
         assert arg in kwargs.keys()
     assert request_type == HttpFsRequest.OP_UTIMENS
     assert kwargs["path"] == fake_path
     assert kwargs["times"] == fake_times
     return HttpFsResponse()
예제 #12
0
 def fake_send_request(request_type, **kwargs):
     for arg in ["uid", "gid"]:
         assert arg in kwargs.keys()
     assert request_type == HttpFsRequest.OP_OPEN
     assert kwargs["path"] == fake_path
     assert kwargs["flags"] == fake_flags
     return HttpFsResponse()
예제 #13
0
 def fake_send_request(request_type, **kwargs):
     assert request_type == HttpFsRequest.OP_CHMOD
     for required_key in ["uid", "gid"]:
         assert required_key in kwargs.keys()
     assert kwargs["path"] == fake_path
     assert kwargs["mode"] == fake_mode
     return HttpFsResponse()
예제 #14
0
    def on_rmdir(self, httpfs_request_args):
        """
        Called when HttpFsRequest.OP_RMDIR is requested
        :param httpfs_request_args: The client request args dict
        """
        response_obj = HttpFsResponse()
        path = self.get_abs_path(httpfs_request_args["path"])
        _error = None
        _err = None
        try:
            os.rmdir(path)

        except FileNotFoundError as e:
            logging.error("{} not found".format(path))
            err = errno.ENOENT
            _error = e
        except OSError as e:
            err = e.errno
            _error = e
        except Exception as e:
            err = errno.EIO
            _error = e

        if _error != None:
            logging.error("Error during rmdir request: {}".format(_error))
            response_obj.set_err_no(_err)
            response_obj.set_data({"message": str(_error)})

        self.send_json_response(200, response_obj.as_dict())
예제 #15
0
    def on_valid_request(self, request_dict):
        """
        Called when a valid JSON request has been sent from a client
        :param request_dict: JSON request converted to dict object
        """
        cred_store = self.server.get_cred_store()
        auth_enabled = cred_store is not None
        has_auth_header = auth_enabled and "Authorization" in self.headers
        is_authorized = not auth_enabled or (
            has_auth_header
            and cred_store.has_cred(self.headers["Authorization"]))

        if "User-Agent" not in self.headers or not self.headers[
                "User-Agent"].startswith("HttpFsClient"):
            raise RuntimeError(
                "Invalid User-Agent header: Client is not an HttpFsClient")
        if not is_authorized:
            logging.error("{} is not authorized".format(
                self.client_address[0]))
            response = HttpFsResponse(errno.EACCES,
                                      {"message": "Invalid API key"})
            self.send_json_response(http.HTTPStatus.UNAUTHORIZED,
                                    response.as_dict())
        else:
            try:
                request = HttpFsRequest.from_dict(request_dict)
                self._delegate_request(request)
            except Exception as e:
                response = HttpFsResponse(errno.EIO, {"message": str(e)})
                self.send_json_response(http.HTTPStatus.BAD_REQUEST,
                                        response.as_dict())
예제 #16
0
    def on_flush(self, httpfs_request_args):
        """
        Called when HttpFsRequest.OP_FLUSH is received from the client
        :param httpfs_request_args: The client request arg dict
        """
        response_obj = HttpFsResponse()

        try:
            os.fsync(httpfs_request_args["file_descriptor"])
        except Exception as e:
            logging.error("Error during flush request: {}".format(e))
            response_obj.set_err_no(errno.EIO)
            response_obj.set_data({"message": str(e)})

        self.send_json_response(http.HTTPStatus.OK, response_obj.as_dict())
예제 #17
0
    def on_mkdir(self, httpfs_request_args):
        """
        Called when HttpFsRequest.OP_MKDIR is requested
        :param httpfs_request_args: The client request args dict
        """
        response_obj = HttpFsResponse()
        path = self.get_abs_path(httpfs_request_args["path"])

        try:
            os.mkdir(path, mode=httpfs_request_args["mode"])
        except Exception as e:
            logging.error("Error during mkdir request: {}".format(e))
            response_obj.set_err_no(errno.EIO)
            response_obj.set_data({"message": str(e)})

        self.send_json_response(http.HTTPStatus.OK, response_obj.as_dict())
예제 #18
0
    def on_truncate(self, httpfs_request_args):
        """
        Called when HttpFsRequest.OP_TRUNCATE is received from the client
        :param httpfs_request_args: The client request arg dict
        """
        response_obj = HttpFsResponse()
        path = self.get_abs_path(httpfs_request_args["path"])
        length = httpfs_request_args["length"]

        try:
            with open(path, 'r+') as f:
                f.truncate(length)
        except Exception as e:
            logging.error("Error during truncate request: {}".format(e))
            response_obj.set_err_no(errno.EIO)
            response_obj.set_data({"message": str(e)})

        self.send_json_response(200, response_obj.as_dict())
예제 #19
0
    def on_link(self, httpfs_request_args):
        """
        Called when HttpFsRequest.OP_LINK is requested
        :param httpfs_request_args: The client request args dict
        """
        target_path = self.get_abs_path(httpfs_request_args["target"])
        source_path = self.get_abs_path(httpfs_request_args["source"])

        response_obj = HttpFsResponse()

        try:
            os.link(source_path, target_path)
        except Exception as e:
            logging.error("Error during link request: {}".format(e))
            response_obj.set_err_no(errno.EIO)
            response_obj.set_data({"message": str(e)})

        self.send_json_response(http.HTTPStatus.OK, response_obj.as_dict())
예제 #20
0
    def _send_request(self, request_type, **kwargs):
        """
        Sends an HttpFsRequest of the given type with the given kwargs
        :param request_type: The request type to send
        :param kwargs: The arguments for the request
        :return: The HttpFsResponse
        """
        request = HttpFsRequest(request_type, kwargs)

        try:
            headers = dict()
            if self._api_key is not None:
                headers["Authorization"] = self._api_key

            response = self._http_keepalive_session.post(
                self._server_url,
                json=request.as_dict(),
                allow_redirects=False,
                timeout=10,
                headers=headers,
                stream=True)

            response.raise_for_status()

            # Minimal server response validation
            is_json = response.headers.get("Content-Type").startswith(
                "application/json")
            is_httpfs_server = response.headers.get("Server").startswith(
                "HttpFs")
            if not is_json or not is_httpfs_server:
                logging.error("Server response didn't come from HttpFs")
                raise FuseOSError(errno.EIO)

            return HttpFsResponse.from_dict(response.json())

        except requests.exceptions.HTTPError as http_error:
            logging.error(http_error)
            raise FuseOSError(errno.EACCES)
        except Exception as exception:
            logging.error(exception)
            raise FuseOSError(errno.EIO)
예제 #21
0
    def on_readlink(self, httpfs_request_args):
        # TODO: This doesn't work
        """
        Called when HttpFsRequest.OP_RELEASE is requested
        :param httpfs_request_args: The client request args dict
        """
        response_obj = HttpFsResponse()
        link_path = self.get_abs_path(httpfs_request_args["link_path"])

        try:
            target = os.readlink(link_path)
            if target.startswith("/"):
                target = os.path.relpath(target, self.server.get_fs_root())
            response_obj.set_data({"target": target})
        except Exception as e:
            logging.error("Error during readlink request: {}".format(e))
            response_obj.set_err_no(errno.EIO)

        self.send_json_response(200, response_obj.as_dict())
예제 #22
0
    def on_getattr(self, httpfs_request_args):
        """
        Called when HttpFsRequest.OP_GET_ATTR is requested
        :param httpfs_request_args: The client request args dict
        """
        response_obj = HttpFsResponse()
        path = self.get_abs_path(httpfs_request_args["path"])

        try:
            os_attrs = os.lstat(path)
            attrs = dict()

            for k in _HttpFsRequestHandler.GETATTR_KEYS:
                attrs[k] = getattr(os_attrs, k)

            response_obj.set_data(attrs)

        except FileNotFoundError:
            logging.warning("{} not found".format(path))
            response_obj.set_err_no(errno.ENOENT)

        self.send_json_response(200, response_obj.as_dict())
예제 #23
0
 def fake_send_request(request_type, **kwargs):
     assert request_type == HttpFsRequest.OP_FSYNC
     assert kwargs["file_descriptor"] == fake_fd
     assert kwargs["datasync"] == fake_ds
     return HttpFsResponse()
예제 #24
0
 def fake_send_request(request_type, **kwargs):
     assert request_type == HttpFsRequest.OP_TRUNCATE
     assert kwargs["path"] == fake_path
     assert kwargs["length"] == fake_len
     return HttpFsResponse()
예제 #25
0
 def fake_send_request(request_type, **kwargs):
     assert request_type == HttpFsRequest.OP_SYMLINK
     assert kwargs["target"] == fake_target
     assert kwargs["source"] == fake_source
     return HttpFsResponse()
예제 #26
0
 def fake_send_request(request_type, **kwargs):
     assert request_type == HttpFsRequest.OP_STAT_FS
     assert kwargs["path"] == fake_path
     return HttpFsResponse()
예제 #27
0
 def fake_send_request(request_type, **kwargs):
     assert request_type == HttpFsRequest.OP_RELEASE
     assert kwargs["file_descriptor"] == fake_fd
     return HttpFsResponse()
예제 #28
0
 def fake_send_request(request_type, **kwargs):
     assert request_type == HttpFsRequest.OP_READLINK
     assert kwargs["link_path"] == fake_path
     resp = HttpFsResponse()
     resp._response_data["target"] = ""
     return resp
예제 #29
0
 def fake_send_request(request_type, **kwargs):
     assert request_type == HttpFsRequest.OP_CHOWN
     assert kwargs["path"] == fake_path
     assert kwargs["uid"] == 2222
     assert kwargs["gid"] == 0
     return HttpFsResponse()
예제 #30
0
 def fake_send_request(request_type, **kwargs):
     assert request_type == HttpFsRequest.OP_MKNOD
     assert kwargs["path"] == fake_path
     assert kwargs["mode"] == fake_mode
     assert kwargs["dev"] == fake_dev
     return HttpFsResponse()