summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore4
-rw-r--r--AUTHORS7
-rw-r--r--CMakeLists.txt46
-rw-r--r--README36
-rw-r--r--cmake/FindGearman.cmake17
-rw-r--r--src/client/main.cpp139
-rw-r--r--src/version.h2
-rw-r--r--src/worker/main.cpp166
8 files changed, 417 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..5d94cf1
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+*.o
+bin
+build
+~*
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..db95e97
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,7 @@
+Initial design and first versions:
+Johann Latocha <johann@latocha.de>
+
+Project management, supervision:
+Dirk von Suchodoletz <dvs@openslx.com>
+Sebastian Schmelzer <sebastian@schmelzer.ws>
+Johann Latocha <johann@latocha.de> \ No newline at end of file
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..04a2be4
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,46 @@
+################################################################################
+# General
+################################################################################
+
+# set project's name
+PROJECT( nbd-broker )
+
+# cmake min version
+CMAKE_MINIMUM_REQUIRED( VERSION 2.8.0 )
+
+# set compiler optimizations for debug and release
+SET(CMAKE_BUILD_TYPE Debug)
+SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g -Wall")
+SET(CMAKE_CXX_FLAGS_RELEASE "-O2 -march=native")
+
+# local cmake modules
+SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
+
+# this command finds libraries and sets all required variables
+FIND_PACKAGE(Gearman REQUIRED)
+
+# some includes
+INCLUDE_DIRECTORIES( ${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR} )
+
+################################################################################
+# Variables
+################################################################################
+
+FILE( GLOB_RECURSE NBDBROKERWORKER_SRCS "src/worker/*.cpp" )
+FILE( GLOB_RECURSE NBDBROKERCLIENT_SRCS "src/client/*.cpp" )
+
+
+################################################################################
+# Build
+################################################################################
+
+# build
+ADD_EXECUTABLE( nbd-broker-worker ${NBDBROKERWORKER_SRCS} )
+ADD_EXECUTABLE( nbd-broker-client ${NBDBROKERCLIENT_SRCS} )
+
+# link
+TARGET_LINK_LIBRARIES( nbd-broker-worker ${GEARMAN_LIBRARIES} )
+TARGET_LINK_LIBRARIES( nbd-broker-client ${GEARMAN_LIBRARIES} )
+
+# install
+INSTALL(TARGETS nbd-broker-worker nbd-broker-client RUNTIME DESTINATION bin)
diff --git a/README b/README
new file mode 100644
index 0000000..2a6c07e
--- /dev/null
+++ b/README
@@ -0,0 +1,36 @@
+**** Installation Guide (Debian/Ubuntu/Suse) ****
+
+*** Prerequisites ***
+
+The following packages are required:
+
+Client:
+ gearman-tools
+ libgearman4
+ libgearman-dev
+ nbd-client
+ cmake
+
+Server additionally:
+ gearman-job-server
+ nbd-server
+
+
+*** Installation ***
+
+Change to the root folder nbd-broker and enter:
+ mkdir -p build
+ cd build/
+ cmake ..
+ make
+
+If you succeed, all binaries are located at build/
+So change the current directory with:
+ cd build/
+
+As superuser (root) you can install the application on your system:
+ make install
+
+
+If you have any feedback please consult http://feedback.openslx.org/ and
+send your suggestions, praise, or complaints to feedback@openslx.org \ No newline at end of file
diff --git a/cmake/FindGearman.cmake b/cmake/FindGearman.cmake
new file mode 100644
index 0000000..757d5b7
--- /dev/null
+++ b/cmake/FindGearman.cmake
@@ -0,0 +1,17 @@
+FIND_PATH(GEARMAN_INCLUDES gearman.h /usr/include/libgearman /usr/local/include/libgearman)
+
+FIND_LIBRARY(GEARMAN_LIBRARIES NAMES libgearman.so PATH /usr/lib /usr/local/lib)
+
+IF (GEARMAN_INCLUDES AND GEARMAN_LIBRARIES)
+ SET(GEARMAN_FOUND TRUE)
+ENDIF (GEARMAN_INCLUDES AND GEARMAN_LIBRARIES)
+
+IF (GEARMAN_FOUND)
+ IF (NOT GEARMAN_FIND_QUIETLY)
+ MESSAGE(STATUS "Found Gearman: ${GEARMAN_LIBRARIES}")
+ ENDIF (NOT GEARMAN_FIND_QUIETLY)
+ELSE (GEARMAN_FOUND)
+ IF (GEARMAN_FIND_REQUIRED)
+ MESSAGE(FATAL_ERROR "Could not find Gearman")
+ ENDIF (GEARMAN_FIND_REQUIRED)
+ENDIF (GEARMAN_FOUND) \ No newline at end of file
diff --git a/src/client/main.cpp b/src/client/main.cpp
new file mode 100644
index 0000000..dfec059
--- /dev/null
+++ b/src/client/main.cpp
@@ -0,0 +1,139 @@
+/*
+ # Copyright (c) 2011 - OpenSLX Project, Computer Center University of Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://gpl.openslx.org/
+ #
+ # If you have any feedback please consult http://feedback.openslx.org/ and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ */
+
+#include <sstream>
+#include <iostream>
+#include <stdio.h>
+#include <libgearman/gearman.h>
+
+#include "../version.h"
+
+using namespace std;
+
+static void usage(char *name)
+{
+ printf("usage: %s -h <host> [-p <port>] -i <image> -d <device>\n", name);
+ printf("\t-h <host>\t gearman job server host\n");
+ printf("\t-p <port>\t gearman job server port\n");
+ printf("\t-i <image>\t remote image file to load\n");
+ printf("\t-d <device>\t local nbd-device to use\n");
+ printf("\t-v\t\t print version and exit\n");
+}
+
+int main(int argc, char* argv[])
+{
+ string host("");
+ in_port_t port = 0;
+ string image("");
+ string device("");
+
+ gearman_return_t ret;
+ gearman_client_st client;
+
+ // parse command line arguments
+ int c;
+ while ((c = getopt(argc, argv, "h:p:i:d:v")) != -1)
+ {
+ switch (c)
+ {
+ case 'h':
+ host = optarg;
+ break;
+ case 'p':
+ port = (in_port_t) atoi(optarg);
+ break;
+ case 'i':
+ image = optarg;
+ break;
+ case 'd':
+ device = optarg;
+ break;
+ case 'v':
+ printf("Version: %s\n", VERSION_STRING);
+ exit(0);
+ default:
+ usage(argv[0]);
+ exit(1);
+ }
+ }
+
+ if (host == "" || image == "" || device == "")
+ {
+ usage(argv[0]);
+ exit(1);
+ }
+
+ // initialize gearman client
+ if (gearman_client_create(&client) == NULL)
+ {
+ cerr << "[ERROR] Memory allocation failure on client creation" << endl;
+ exit(1);
+ }
+ ret = gearman_client_add_server(&client, host.c_str(), port);
+ if (ret != GEARMAN_SUCCESS)
+ {
+ cerr << "[ERROR] " << gearman_client_error(&client) << endl;
+ exit(1);
+ }
+
+ // main loop
+ char *result;
+ size_t result_size;
+ string msg;
+ while (1)
+ {
+ // send request to gearman job server
+ result = (char *) gearman_client_do(&client, "start_nbd_server", NULL,
+ (void*) image.c_str(), (size_t) image.length(), &result_size,
+ &ret);
+
+ if (ret == GEARMAN_WORK_DATA)
+ {
+ msg = result;
+ free(result);
+ continue;
+ }
+ else if (ret == GEARMAN_WORK_STATUS)
+ {
+ uint32_t m, n;
+ gearman_client_do_status(&client, &n, &m);
+ printf("[INFO] Status: %u/%u\n", n, m);
+ continue;
+ }
+ else if (ret == GEARMAN_SUCCESS)
+ {
+ // start nbd-client
+ stringstream command;
+ command << "nbd-client " << host << " " << msg << " " << device;
+ cout << "[DEBUG] " << "Running command: " << command.str() << endl;
+ system(command.str().c_str());
+ free(result);
+ }
+ else if (ret == GEARMAN_WORK_FAIL)
+ {
+ cerr << "[ERROR] " << msg << endl;
+ cerr << "[ERROR] Work failed" << endl;
+ free(result);
+ }
+ else
+ {
+ cerr << "[ERROR] " << gearman_client_error(&client) << endl;
+ free(result);
+ }
+
+ break;
+ }
+
+ // cleanup
+ gearman_client_free(&client);
+ return 0;
+}
diff --git a/src/version.h b/src/version.h
new file mode 100644
index 0000000..43331a7
--- /dev/null
+++ b/src/version.h
@@ -0,0 +1,2 @@
+#define VERSION_STRING "0.1.0"
+#define VERSION_NUMBER 010
diff --git a/src/worker/main.cpp b/src/worker/main.cpp
new file mode 100644
index 0000000..ff97041
--- /dev/null
+++ b/src/worker/main.cpp
@@ -0,0 +1,166 @@
+/*
+ # Copyright (c) 2011 - OpenSLX Project, Computer Center University of Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://gpl.openslx.org/
+ #
+ # If you have any feedback please consult http://feedback.openslx.org/ and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ */
+
+#include <map>
+#include <unistd.h>
+#include <iostream>
+#include <sstream>
+#include <stdio.h>
+#include <string.h>
+#include <libgearman/gearman.h>
+
+#include "../version.h"
+
+using namespace std;
+
+int _nbd_server_port;
+map<string, int> _map; // map running nbd-servers: <exported image, port number>
+
+static void *start_nbd_server(gearman_job_st *job, void *context,
+ size_t *result_size, gearman_return_t *ret_ptr)
+{
+ cout << "[DEBUG] Received request from " << gearman_job_handle(job) << endl;
+
+ if (gearman_job_workload_size(job) <= 0)
+ {
+ cerr << "[ERROR] No image given, aborting!" << endl;
+ return NULL;
+ }
+
+ // prepare data
+ char* req = (char*) gearman_job_workload(job);
+ size_t req_size = gearman_job_workload_size(job);
+ string *image = new string(req, req_size);
+ int current_port = 0;
+ cout << "[DEBUG] Requested image: " << *image << endl;
+
+ // test if requested image exists
+ int test = access(image->c_str(), 0);
+ if (test != 0)
+ {
+ cerr << "[ERROR] Requested image not found, aborting!" << endl;
+ char msg[] = "Requested image not found";
+ gearman_job_send_data(job, msg, sizeof(msg));
+ *ret_ptr = GEARMAN_WORK_FAIL;
+ return NULL;
+ }
+
+ if (_map[*image] != 0)
+ {
+ // nbd-server already running
+ cout << "[DEBUG] Requested nbd-server is already running on port "
+ << _map[*image] << endl;
+ current_port = _map[*image];
+ }
+ else
+ {
+ // start new nbd-server
+ cout << "[DEBUG] Starting new nbd-server on port " << _nbd_server_port
+ << endl;
+
+ stringstream command;
+ command << "nbd-server " << _nbd_server_port << " " << *image;
+ cout << "[DEBUG] " << "Running command: " << command.str() << endl;
+ system(command.str().c_str());
+
+ current_port = _nbd_server_port;
+ _map[*image] = _nbd_server_port;
+ _nbd_server_port++;
+ }
+
+ // send port number to client
+ cout << "[DEBUG] " << "Response with port number " << current_port << endl;
+ char buf[32];
+ snprintf(buf, sizeof(buf), "%d", current_port);
+ gearman_job_send_data(job, buf, strlen(buf));
+
+ *ret_ptr = GEARMAN_SUCCESS;
+ return NULL;
+}
+
+static void usage(char *name)
+{
+ printf("usage: %s [-p] [-d] [-v]\n", name);
+ printf("\t-p\t first port number for nbd-servers (default: 5001)\n");
+ printf("\t-d\t start as daemon\n");
+ printf("\t-v\t print version and exit\n");
+}
+
+int main(int argc, char* argv[])
+{
+ gearman_return_t result;
+ gearman_worker_st worker;
+ _nbd_server_port = 5001;
+ bool as_daemon = false;
+
+ // parse command line arguments
+ int c;
+ while ((c = getopt(argc, argv, "p:dv")) != -1)
+ {
+ switch (c)
+ {
+ case 'p':
+ _nbd_server_port = atoi(optarg);
+ break;
+ case 'd':
+ as_daemon = true;
+ break;
+ case 'v':
+ printf("Version: %s\n", VERSION_STRING);
+ exit(0);
+ default:
+ usage(argv[0]);
+ exit(1);
+ }
+ }
+
+ // initialize gearman worker
+ if (gearman_worker_create(&worker) == NULL)
+ {
+ cerr << "[ERROR] Memory allocation failure on worker creation" << endl;
+ exit(1);
+ }
+ result = gearman_worker_add_server(&worker, "127.0.0.1", 0);
+ if (result != GEARMAN_SUCCESS)
+ {
+ cerr << "[ERROR] " << gearman_worker_error(&worker) << endl;
+ exit(1);
+ }
+ result = gearman_worker_add_function(&worker, "start_nbd_server", 0,
+ start_nbd_server, NULL);
+ if (result != GEARMAN_SUCCESS)
+ {
+ cerr << "[ERROR] " << gearman_worker_error(&worker) << endl;
+ exit(1);
+ }
+ cout << "[DEBUG] Worker is ready." << endl;
+ if (as_daemon)
+ {
+ cout << "[DEBUG] Daemonize..." << endl;
+ daemon(0, 0);
+ }
+
+ // main loop
+ while (1)
+ {
+ result = gearman_worker_work(&worker);
+ if (result != GEARMAN_SUCCESS)
+ {
+ cerr << "[ERROR] " << gearman_worker_error(&worker) << endl;
+ break;
+ }
+ }
+
+ // cleanup
+ gearman_worker_free(&worker);
+ cout << "[DEBUG] Worker has been freed." << endl;
+}