--- /dev/null
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+/*
+ * convert RGW commands to file commands
+ *
+ * Copyright (C) 2011 New Dream Network
+ *
+ * This is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software
+ * Foundation. See file COPYING.
+ *
+ */
+#ifndef RGW_FILE_H
+#define RGW_FILE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * dynamic allocated handle to support nfs handle
+ * Currently we support only one instance of librgw.
+ * In order to support several instance we will need to include an
+ * instance id (16bit)
+ */
+struct nfs_handle
+{
+ uint64_t handle;
+};
+
+/*
+ get entity handle
+*/
+int rgw_get_handle(const char *uri, struct nfs_handle *handle);
+
+/*
+ check handle
+*/
+int rgw_check_handle(const struct nfs_handle *handle);
+
+ int rgw_mount(const char *uid, const char *key, const char *secret,
+ const struct nfs_handle *handle);
+
+/*
+ create a new dirctory
+*/
+int rgw_create_directory(const struct nfs_handle *parent_handle, const char *name);
+
+/*
+ create a new file
+*/
+ int rgw_create_file(const struct nfs_handle *parent_handle, const char* name);
+
+ int rgw_rename(const struct nfs_handle *parent_handle, const char* old_name, const char* new_name);
+
+/*
+ remove file or directory
+*/
+int rgw_unlink(const struct nfs_handle *parent_handle, const char* path);
+
+/*
+ lookup a directory or file
+*/
+int rgw_lookup(const struct nfs_handle *parent_handle, const char *path, uint64_t *handle);
+
+/*
+ read directory content
+*/
+int rgw_readdir(const struct nfs_handle *parent_handle, const char *path);
+
+int rgw_set_attributes(const struct nfs_handle *handle);
+
+int rgw_get_attributes(const struct nfs_handle *handle);
+
+int rgw_open(const struct nfs_handle *handle);
+
+int rgw_close(const struct nfs_handle *handle);
+
+int read(const struct nfs_handle *handle);
+
+int write(const struct nfs_handle *handle);
+
+int set_user_permissions(cosnt char *uid);
+
+int get_user_permissions(const char *uid);
+
+int set_dir_permissions(const struct nfs_handle *handle);
+
+int get_dir_permissions(const struct nfs_handle *handle);
+
+int set_file_permissions(const struct nfs_handle *handle);
+
+int get_file_permissions(const struct nfs_handle *handle);
+
+int acl2perm();
+
+int perm2acl();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
* Foundation. See file COPYING.
*
*/
+#include <sys/types.h>
+#include <string.h>
#include "include/types.h"
#include "include/rados/librgw.h"
#include "rgw/rgw_acl_s3.h"
#include "rgw_acl.h"
+
+#include "include/str_list.h"
+#include "global/global_init.h"
+#include "common/config.h"
+#include "common/errno.h"
+#include "common/Timer.h"
+#include "common/Throttle.h"
+#include "common/WorkQueue.h"
#include "common/ceph_argparse.h"
#include "common/ceph_context.h"
#include "common/common_init.h"
#include "common/dout.h"
+#include "rgw_rados.h"
+#include "rgw_resolve.h"
+#include "rgw_op.h"
+#include "rgw_rest.h"
+#include "rgw_frontend.h"
+#include "rgw_request.h"
+#include "rgw_process.h"
+#include "rgw_rest_user.h"
+#include "rgw_rest_s3.h"
+#include "rgw_rest_lib.h"
+#include "rgw_auth_s3.h"
+#include "rgw_lib.h"
+
#include <errno.h>
#include <sstream>
#include <string.h>
{
rgw->put();
}
+
+class C_InitTimeout : public Context {
+public:
+ C_InitTimeout() {}
+ void finish(int r) {
+ derr << "Initialization timeout, failed to initialize" << dendl;
+ exit(1);
+ }
+};
+
+struct RGWLibRequest : public RGWRequest {
+ string method;
+ string resource;
+ int content_length;
+ atomic_t *fail_flag;
+
+ RGWLibRequest(uint64_t req_id, const string& _m, const string& _r, int _cl, bool user_command,
+ atomic_t *_ff) : RGWRequest(req_id), method(_m), resource(_r), content_length(_cl), fail_flag(_ff)
+ {
+ s->librgw_user_command = user_command;
+ }
+};
+
+void RGWLibRequestEnv::set_date(utime_t& tm)
+{
+ stringstream s;
+ tm.asctime(s);
+ date_str = s.str();
+}
+
+int RGWLibRequestEnv::sign(RGWAccessKey& access_key)
+{
+ map<string, string> meta_map;
+ map<string, string> sub_resources;
+
+ string canonical_header;
+ string digest;
+
+ rgw_create_s3_canonical_header(request_method.c_str(),
+ NULL, /* const char *content_md5 */
+ content_type.c_str(),
+ date_str.c_str(),
+ meta_map,
+ uri.c_str(),
+ sub_resources,
+ canonical_header);
+
+ int ret = rgw_get_s3_header_digest(canonical_header, access_key.key, digest);
+ if (ret < 0) {
+ return ret;
+ }
+
+};
+
+class RGWLibFrontend : public RGWProcessFrontend {
+public:
+ RGWLibFrontend(RGWProcessEnv& pe, RGWFrontendConfig *_conf) : RGWProcessFrontend(pe, _conf) {}
+ int init();
+ void gen_request(const string& method, const string& resource, int content_length, bool user_command,
+ atomic_t *fail_flag);
+};
+
+class RGWLibProcess : public RGWProcess {
+ RGWAccessKey access_key;
+public:
+ RGWLibProcess(CephContext *cct, RGWProcessEnv *pe, int num_threads, RGWFrontendConfig *_conf) :
+ RGWProcess(cct, pe, num_threads, _conf) {}
+ void run();
+ void checkpoint();
+ void handle_request(RGWRequest *req);
+ void gen_request(const string& method, const string& resource, int content_length, bool user_command,
+ atomic_t *fail_flag);
+ void set_access_key(RGWAccessKey& key) { access_key = key; }
+};
+
+
+void RGWLibProcess::checkpoint()
+{
+ m_tp.drain(&req_wq);
+}
+
+void RGWLibProcess::run()
+{
+}
+
+void RGWLibProcess::gen_request(const string& method, const string& resource, int content_length,
+ bool user_command, atomic_t *fail_flag)
+{
+ RGWLibRequest *req = new RGWLibRequest(store->get_new_req_id(), method, resource,
+ content_length, user_command, fail_flag);
+ dout(10) << "allocated request req=" << hex << req << dec << dendl;
+ req_throttle.get(1);
+ req_wq.queue(req);
+}
+
+void RGWLibProcess::handle_request(RGWRequest *r)
+{
+ RGWLibRequest *req = static_cast<RGWLibRequest *>(r);
+
+ RGWLibRequestEnv env;
+
+ utime_t tm = ceph_clock_now(NULL);
+
+ env.port = 80;
+ env.content_length = req->content_length;
+ env.content_type = "binary/octet-stream"; /* TBD */
+ env.request_method = req->method;
+ env.uri = req->resource;
+ env.set_date(tm);
+ env.sign(access_key);
+
+ RGWLibIO client_io(&env);
+
+ int ret = process_request(store, rest, req, &client_io, olog);
+ if (ret < 0) {
+ /* we don't really care about return code */
+ dout(20) << "process_request() returned " << ret << dendl;
+
+ }
+ delete req;
+}
+
+void RGWLibFrontend::gen_request(const string& method, const string& resource, int content_length,
+ bool user_command, atomic_t *fail_flag)
+{
+ RGWLibProcess *lib_process = static_cast<RGWLibProcess *>(pprocess);
+ lib_process->gen_request(method, resource, content_length, user_command, fail_flag);
+}
+
+int RGWLib::init()
+{
+ int r = 0;
+ /* alternative default for module */
+ vector<const char *> def_args;
+ def_args.push_back("--debug-rgw=1/5");
+ def_args.push_back("--keyring=$rgw_data/keyring");
+ def_args.push_back("--log-file=/var/log/radosgw/$cluster-$name.log");
+
+ vector<const char*> args;
+ global_init(&def_args, args, CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_DAEMON,
+ CINIT_FLAG_UNPRIVILEGED_DAEMON_DEFAULTS);
+
+ Mutex mutex("main");
+ SafeTimer init_timer(g_ceph_context, mutex);
+ init_timer.init();
+ mutex.Lock();
+ init_timer.add_event_after(g_conf->rgw_init_timeout, new C_InitTimeout);
+ mutex.Unlock();
+
+ common_init_finish(g_ceph_context);
+
+ rgw_tools_init(g_ceph_context);
+
+ rgw_init_resolver();
+
+ store = RGWStoreManager::get_storage(g_ceph_context,
+ g_conf->rgw_enable_gc_threads, g_conf->rgw_enable_quota_threads);
+
+ if (!store) {
+ mutex.Lock();
+ init_timer.cancel_all_events();
+ init_timer.shutdown();
+ mutex.Unlock();
+
+ derr << "Couldn't init storage provider (RADOS)" << dendl;
+ return EIO;
+ }
+
+ r = rgw_perf_start(g_ceph_context);
+
+ rgw_rest_init(g_ceph_context, store->region);
+
+ mutex.Lock();
+ init_timer.cancel_all_events();
+ init_timer.shutdown();
+ mutex.Unlock();
+
+ if (r)
+ return 1;
+
+ rgw_user_init(store);
+ rgw_bucket_init(store->meta_mgr);
+ rgw_log_usage_init(g_ceph_context, store);
+
+
+ mgr = new RGWRESTMgr_Lib();
+ mgr->set_logging(true);
+ rest.register_default_mgr(mgr);
+
+ if (!g_conf->rgw_ops_log_socket_path.empty()) {
+ olog = new OpsLogSocket(g_ceph_context, g_conf->rgw_ops_log_data_backlog);
+ olog->init(g_conf->rgw_ops_log_socket_path);
+ }
+
+ int port = 80;
+ RGWProcessEnv env = { store, &rest, olog, port };
+
+ fec = new RGWFrontendConfig("librgw");
+ fe = new RGWLibFrontend(env, fec);
+
+ fe->init();
+ if (r < 0) {
+ derr << "ERROR: failed initializing frontend" << dendl;
+ return -r;
+ }
+
+ fe->run();
+
+ return 0;
+
+}
+
+int RGWLib::stop()
+{
+ derr << "shutting down" << dendl;
+
+ fe->stop();
+
+ fe->join();
+
+ delete fe;
+
+ rgw_log_usage_finalize();
+
+ delete olog;
+
+ RGWStoreManager::close_storage(store);
+
+ rgw_tools_cleanup();
+ rgw_shutdown_resolver();
+
+ rgw_perf_stop(g_ceph_context);
+
+ dout(1) << "final shutdown" << dendl;
+ g_ceph_context->put();
+
+ ceph::crypto::shutdown();
+
+ return 0;
+}
+
+int RGWLib::get_uri(const uint64_t handle, string &uri)
+{
+ ceph::unordered_map<uint64_t, string>::iterator i = handles_map.find(handle);
+ if (i != handles_map.end()) {
+ uri = i->second;
+ return 0;
+ }
+ return -1;
+}
+
+uint64_t RGWLib::get_new_handle(const string& uri)
+{
+ ceph::unordered_map<string, uint64_t>::iterator i = allocated_objects_handles.find(uri);
+ if (i != allocated_objects_handles.end()) {
+ return i->second;
+ }
+
+ allocated_objects_handles[uri] = last_allocated_handle.inc();
+ handles_map[last_allocated_handle.read()] = uri;
+
+ return last_allocated_handle.read();
+}
+
+int RGWLibIO::set_uid(RGWRados *store, const rgw_user& uid)
+{
+ int ret = rgw_get_user_info_by_uid(store, uid, user_info, NULL);
+ if (ret < 0) {
+ derr << "ERROR: failed reading user info: uid=" << uid << " ret="
+ << ret << dendl;
+ }
+ return ret;
+}
+
+int RGWLibIO::write_data(const char *buf, int len)
+{
+ return len;
+}
+
+int RGWLibIO::read_data(char *buf, int len)
+{
+ int read_len = MIN(left_to_read, (uint64_t)len);
+ left_to_read -= read_len;
+ return read_len;
+}
+
+void RGWLibIO::flush()
+{
+}
+
+int RGWLibIO::complete_request()
+{
+ return 0;
+}
+
+void RGWLibIO::init_env(CephContext *cct)
+{
+ env.init(cct);
+
+ left_to_read = re->content_length;
+
+ char buf[32];
+ snprintf(buf, sizeof(buf), "%lld", (long long)re->content_length);
+ env.set("CONTENT_LENGTH", buf);
+
+ env.set("CONTENT_TYPE", re->content_type.c_str());
+ env.set("HTTP_DATE", re->date_str.c_str());
+
+ for (map<string, string>::iterator iter = re->headers.begin(); iter != re->headers.end(); ++iter) {
+ env.set(iter->first.c_str(), iter->second.c_str());
+ }
+
+ env.set("REQUEST_METHOD", re->request_method.c_str());
+ env.set("REQUEST_URI", re->uri.c_str());
+ env.set("QUERY_STRING", re->query_string.c_str());
+ env.set("SCRIPT_URI", re->uri.c_str());
+
+ char port_buf[16];
+ snprintf(port_buf, sizeof(port_buf), "%d", re->port);
+ env.set("SERVER_PORT", port_buf);
+}
+
+int RGWLibIO::send_status(int status, const char *status_name)
+{
+ return 0;
+}
+
+int RGWLibIO::send_100_continue()
+{
+ return 0;
+}
+
+int RGWLibIO::complete_header()
+{
+ return 0;
+}
+
+int RGWLibIO::send_content_length(uint64_t len)
+{
+ return 0;
+}
+
+int RGWLib::get_userinfo_by_uid(const string& uid, RGWUserInfo &info)
+{
+ atomic_t failed;
+
+ fe->gen_request("GET", uid, 4096, true, &failed);
+ return failed.read();
+}
+
+int RGWLib::get_user_acl()
+{
+}
+
+int RGWLib::set_user_permissions()
+{
+}
+
+int RGWLib::set_user_quota()
+{
+}
+
+int RGWLib::get_user_quota()
+{
+}
+
+int RGWLib::get_user_buckets_list()
+{
+ /* need to authanitcate first */
+ atomic_t failed;
+ fe->gen_request("GET", "", 4096, false, &failed);
+ return failed.read();
+
+}
+
+int RGWLib::get_bucket_objects_list()
+{
+}
+
+int RGWLib::create_bucket()
+{
+}
+
+int RGWLib::delete_bucket()
+{
+}
+
+int RGWLib::get_bucket_attributes()
+{
+}
+
+int RGWLib::set_bucket_attributes()
+{
+}
+
+int RGWLib::create_object ()
+{
+}
+
+int RGWLib::delete_object()
+{
+}
+
+int RGWLib::write()
+{
+}
+
+int RGWLib::read()
+{
+}
+
+int RGWLib::get_object_attributes()
+{
+}
+
+int RGWLib::set_object_attributes()
+{
+}
+
+/* global RGW library object */
+static RGWLib rgwlib;
+
+int librgw_init()
+{
+ return rgwlib.init();
+}
+
+int librgw_stop()
+{
+ return rgwlib.stop();
+}
--- /dev/null
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+#include "rgw_file.h"
+
+extern RGWLib librgw;
+
+
+bool is_root(const string& uri)
+{
+ return uri.equals("");
+}
+
+bool is_bucket(const string& uri)
+{
+ int pos = req.find('/');
+ return (pos < 0);
+}
+
+/*
+ get generate nfs_handle
+*/
+int rgw_get_handle(const char *uri, struct nfs_handle *handle)
+{
+ handle->handle = librgw.get_handle(uri);
+ return 0;
+}
+
+/*
+ check nfs_handle
+*/
+int rgw_check_handle(const struct nfs_handle *handle)
+{
+ return librgw.check_handle(handle);
+}
+
+int rgw_mount(const char *uid, const char *key, const char *secret,
+ const struct nfs_handle *handle)
+{
+ int rc;
+ string uri = uid + "\";
+ string auth_hdr;
+ map<string, string> meta_map;
+ map<string, string> sub_resources;
+
+ rgw_create_s3_canonical_header('GET',
+ NULL, /* const char *content_md5 */
+ 'text/html',
+ "",
+ meta_map,
+ urti.c_str(),
+ sub_resources,
+ auth_hdr);
+
+ /* check key */
+ rc = rgw_get_s3_header_digest(auth_hdr, key, secret);
+ if (rc < 0 ) {
+ return rc;
+ }
+
+ return rgw_get_handle(uri);
+}
+
+/*
+ create a new dirctory
+*/
+int rgw_create_directory(const struct nfs_handle *parent_handle, const char *name)
+{
+ return 0;
+}
+
+/*
+ create a new file
+*/
+int rgw_create_file(const struct nfs_handle *parent_handle, const char* name)
+{
+ return 0;
+}
+
+int rgw_rename(const struct nfs_handle *parent_handle, const char* old_name, const char* new_name)
+{
+ return 0;
+}
+/*
+ remove file or directory
+*/
+int rgw_unlink(const struct nfs_handle *parent_handle, const char* path)
+{
+ return 0;
+}
+
+/*
+ lookup a directory or file
+*/
+int rgw_lookup(const struct nfs_handle *parent_handle, const struct nfs_handle *parent_handle,
+ const char *path, uint64_t *handle)
+{
+ string uri;
+ int rc;
+
+ rc = get_uri(parent_handle, uri);
+ if (rc < 0 ) { /* invalid parent */
+ return rc;
+ }
+
+ if (is_root(uri)) {
+ librgw.get_bucket(uri);
+ } else if (is_bucket(uri)) {
+ /* get the object */
+ } else { /* parent cannot be an object */
+ return -1;
+ }
+
+ uri += "/" + path;
+ /* find or create an handle for the object or bucket */
+ *handle = librgw.get_new_handle(uri);
+ return 0;
+}
+
+/*
+ read directory content
+*/
+int rgw_readdir(const struct nfs_handle *parent_handle, const char *path)
+{
+ string uri;
+ int rc;
+
+ rc = get_uri(parent_handle, uri);
+ if (rc < 0 ) { /* invalid parent */
+ return rc;
+ }
+
+ if (librgw.is_root(uri)) {
+ /* get the bucket list */
+ return librgw.get_user_buckets_list();
+ } else if (librgw.is_bucket(uri)) {
+ /* get the object list */
+ return librgw.get_buckets_object_list();
+ } else { /* parent cannot be an object */
+ return -1;
+ }
+
+ return 0;
+}
+
+
--- /dev/null
+#ifndef RGW_LIB_H
+#define RGW_LIB_H
+
+#include "include/unordered_map.h"
+#include "rgw_common.h"
+#include "rgw_client_io.h"
+#include "rgw_rest.h"
+#include "rgw_request.h"
+#include "rgw_process.h"
+
+
+class RGWLibFrontendConfig;
+class RGWLibFrontend;
+class OpsLogSocket;
+class RGWREST;
+class RGWRESTMgr;
+
+class RGWLib {
+ RGWFrontendConfig *fec;
+ RGWLibFrontend *fe;
+ OpsLogSocket *olog;
+ RGWREST rest;
+ RGWProcessEnv env;
+ RGWRados *store;
+ RGWRESTMgr *mgr;
+ ceph::unordered_map<string, uint64_t> allocated_objects_handles;
+ ceph::unordered_map<uint64_t, string> handles_map;
+ atomic64_t last_allocated_handle;
+public:
+ RGWLib() {}
+ ~RGWLib() {}
+
+ int init();
+ int stop();
+
+ /* generate dynamic handle currently unique per librgw object
+ */
+ uint64_t get_new_handle(const string& url);
+
+ int get_uri(const uint64_t handle, string &uri);
+
+ /* User interface */
+ int get_userinfo_by_uid(const string& uid, RGWUserInfo &info);
+ int get_user_acl();
+ int set_user_permissions();
+ int set_user_quota();
+ int get_user_quota();
+
+ /* buckets */
+ int get_user_buckets_list();
+ int get_bucket_objects_list();
+ int create_bucket();
+ int delete_bucket();
+ int get_bucket_attributes();
+ int set_bucket_attributes();
+
+ /* objects */
+ int create_object ();
+ int delete_object();
+ int write();
+ int read();
+ int get_object_attributes();
+ int set_object_attributes();
+};
+
+/* request interface */
+
+struct RGWLibRequestEnv {
+ int port;
+ uint64_t content_length;
+ string content_type;
+ string request_method;
+ string uri;
+ string query_string;
+ string date_str;
+
+ map<string, string> headers;
+
+ RGWLibRequestEnv() : port(0), content_length(0) {}
+
+ void set_date(utime_t& tm);
+ int sign(RGWAccessKey& access_key);
+};
+
+class RGWLibIO : public RGWClientIO
+{
+ uint64_t left_to_read;
+ RGWLibRequestEnv *re;
+ RGWUserInfo user_info;
+public:
+ RGWLibIO(RGWLibRequestEnv *_re): re(_re) {}
+ RGWLibIO(RGWLibRequestEnv *_re, const RGWUserInfo &_user_info)
+ : re(_re), user_info(_user_info) {}
+
+ void init_env(CephContext *cct);
+
+ int set_uid(RGWRados* store, const rgw_user& uid);
+ const RGWUserInfo &get_user() { return user_info; }
+ int write_data(const char *buf, int len);
+ int read_data(char *buf, int len);
+
+ int send_status(int status, const char *status_name);
+ int send_100_continue();
+ int complete_header();
+ int complete_request();
+ int send_content_length(uint64_t len);
+
+ void flush();
+};
+
+#endif