packaging aeolus components
by Mo Morsi
Inorder to assist with the Aeolus packaging process, we are looking to
split the end-of-development-cycle packaging tasks up among engineers
working on the various components. The tentative list of lead packagers
can be found below as well as on the wiki [1].
These packagers are responsible for making sure their component is
tested against the supported Fedora versions at the time (currently F15,
F16, and rawhide), and their component is pushed into Fedora with all of
its dependencies (both new and updated ones). They may ask delegate some
of this responsobility off to other team members as appropriate on a
case by case basis.
audrey - JoeVLcek
conductor - sseago
configure - mmorsi
deltacloud - mfojtik
imagefactory - sloranz
iwhd - jmeyering
oz - clalance
If anyone feels that there are a better fits, feel free to suggest.
-Mo
[1] https://www.aeolusproject.org/redmine/projects/aeolus/wiki/Packaging
11 years, 4 months
[PATCH] Use a thread to do instance creates V4.
by Ian Main
From: Chris Lalancette <clalance(a)redhat.com>
I modified Chris' patch to use a thread instead of fork. This pushes
the communications with deltacloud into a thread which can take as long
as it needs to complete the start.
In the future we may want to put a retry in here too.
You will notice in V2 we now set allow_concurrency = true in the
postgres config. I'm a little worried that this means it may not work
with other DB providers.
V4: Fix whitespace errors
Signed-off-by: Ian Main <imain(a)redhat.com>
---
src/app/util/taskomatic.rb | 81 ++++++++++++++++++++++++++++++-------------
src/config/database.pg | 3 ++
2 files changed, 59 insertions(+), 25 deletions(-)
diff --git a/src/app/util/taskomatic.rb b/src/app/util/taskomatic.rb
index 84dabd0..2f08daa 100644
--- a/src/app/util/taskomatic.rb
+++ b/src/app/util/taskomatic.rb
@@ -26,27 +26,15 @@ module Taskomatic
task.state = Task::STATE_PENDING
task.save!
- task.instance.provider_account = match.provider_account
- task.instance.create_auth_key unless task.instance.instance_key
-
- dcloud_instance = create_dcloud_instance(task.instance, match)
-
- handle_dcloud_error(dcloud_instance)
+ create_dcloud_instance(task.instance, match)
task.state = Task::STATE_RUNNING
- task.save!
-
- Rails.logger.info "Task instance create completed with key #{dcloud_instance.id} and state #{dcloud_instance.state}"
- task.instance.external_key = dcloud_instance.id
- task.instance.state = dcloud_to_instance_state(dcloud_instance.state)
- task.instance.save!
rescue HttpException => ex
task.failure_code = Task::FAILURE_PROVIDER_CONTACT_FAILED
handle_create_instance_error(task, ex)
rescue Exception => ex
handle_create_instance_error(task, ex)
ensure
- task.instance.save!
task.save!
end
end
@@ -146,18 +134,61 @@ module Taskomatic
end
def self.create_dcloud_instance(instance, match)
- client = match.provider_account.connect
-
- overrides = HardwareProfile.generate_override_property_values(instance.hardware_profile, match.hwp)
-
- client.create_instance(:image_id => match.provider_image.target_identifier,
- :name => instance.name.tr("/", "-"),
- :hwp_id => match.hwp.external_key,
- :hwp_memory => overrides[:memory],
- :hwp_cpu => overrides[:cpu],
- :hwp_storage => overrides[:storage],
- :realm_id => (match.realm.external_key rescue nil),
- :keyname => (instance.instance_key.name))
+ # because creating an instance can take a potentially long time (and
+ # creating multiple of them just prolongs this), we start a new thread
+ # that does this work. The new thread continues to run in the background
+ # and communicates the status back to the main UI via the database
+
+ # This cleans up old DB connections. AR creates a new connection for each
+ # thread. This can leak FDs if you don't clean them up. Basically this
+ # ensures the previously used FD is cleaned up.
+ ActiveRecord::Base.connection_pool.clear_stale_cached_connections!
+
+ Thread.new do
+ begin
+ # These all need to be reloaded because when you create a new thread
+ # AR creates a new connection and these objects become stale.
+ #
+ # Everything used here must be reloaded.
+ instance.reload
+ match.provider_account.reload
+ match.hwp.reload
+ match.realm.reload if match.realm
+
+ instance.provider_account = match.provider_account
+ instance.create_auth_key unless instance.instance_key
+
+ client = match.provider_account.connect
+
+ overrides = HardwareProfile.generate_override_property_values(instance.hardware_profile, match.hwp)
+
+ dcloud_instance = client.create_instance(:image_id => match.provider_image.target_identifier,
+ :name => instance.name.tr("/", "-"),
+ :hwp_id => match.hwp.external_key,
+ :hwp_memory => overrides[:memory],
+ :hwp_cpu => overrides[:cpu],
+ :hwp_storage => overrides[:storage],
+ :realm_id => (match.realm.external_key rescue nil),
+ :keyname => (instance.instance_key.name))
+
+ handle_dcloud_error(dcloud_instance)
+
+ Rails.logger.info "Task instance create completed with key #{dcloud_instance.id} and state #{dcloud_instance.state}"
+ instance.external_key = dcloud_instance.id
+ instance.state = dcloud_to_instance_state(dcloud_instance.state)
+ rescue Exception => ex
+ # any sort of exception causes us to put the instance in CREATE_FAILED
+ # FIXME: if the exception is raised *after* the create_instance, this
+ # isn't true and will result in a rogue instance
+ Rails.logger.error ex.message
+ Rails.logger.error ex.backtrace.join("\n")
+ instance.state = Instance::STATE_CREATE_FAILED
+ raise ex
+ ensure
+ instance.save!
+ Thread.exit
+ end
+ end
end
def self.matches(instance)
diff --git a/src/config/database.pg b/src/config/database.pg
index 19fe4e6..72a3895 100644
--- a/src/config/database.pg
+++ b/src/config/database.pg
@@ -45,6 +45,7 @@ development:
username: aeolus
password: v23zj59an
host: localhost
+ allow_concurrency: true
min_messages: warning
# Warning: The database defined as 'test' will be erased and
@@ -56,6 +57,7 @@ test: &TEST
username: aeolus
password: v23zj59an
host: localhost
+ allow_concurrency: true
min_messages: warning
production:
@@ -63,6 +65,7 @@ production:
database: conductor
username: aeolus
password: v23zj59an
+ allow_concurrency: true
host: localhost
cucumber:
--
1.7.6.2
11 years, 7 months
[PATCH 1/3] Document undocumented hard-coded 300 second timeout and default timout value.
by Steven Dake
Signed-off-by: Steven Dake <sdake(a)redhat.com>
---
man/oz-install.1 | 11 ++++++++---
1 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/man/oz-install.1 b/man/oz-install.1
index b497813..7cf0077 100644
--- a/man/oz-install.1
+++ b/man/oz-install.1
@@ -70,9 +70,14 @@ will undefine the libvirt guest with the same name or UUID and delete
the diskimage, so it should be used with caution.
.TP
.B "\-t"
-Use a timeout value of \fBtimeout\fR for installation, rather than the
-oz default. This can be useful if you know you have slower storage
-and want to wait longer for the installation to timeout.
+Terminate the installation of the guest image in \fBtimeout\fR seconds
+rather then the default of 1200 seconds. This value can be increased in the
+case of slow storage or multiple oz-install operations on the same machine
+consuming the disk bandwidth.
+
+Please note there is a separate termination action that occurs if 300 seconds
+elapses before any data is written to the VM image. This timer value is not
+configurable.
.TP
.B "\-u"
Customize the image after installation. This generally installs
--
1.7.4.4
11 years, 7 months
Let's switch to GitHub
by Matt Wagner
Hi all,
I'd like to propose that we move Conductor and aeolus-configure over to
GitHub. (Bear with me for one second, please.)
"But wait," you're thinking. "Didn't we just have that discussion the
other week?" Not like this.
What I'd like to propose is that we keep our workflow exactly the same
as it is today, but move the repository from FedoraHosted to GitHub.
We'll still send patches to the list, have someone test them and send an
ACK to the list, and then push the code. It'll just be to the git repo
on GitHub instead of the repo on FedoraHosted.
Why do this? Two reasons, really:
a.) Most of the other Aeolus projects are already on GitHub. This way,
everything will be in one place.
b.) GitHub is a lot more widely-known than FedoraHosted. If we link
people in the community to the GitHub page for Conductor, most will
instinctively know how to clone the source and how to start
contributing. As it is today, I have to cat .git/config to have any idea
where our repo lives.
I think that we should probably do this at the end of this sprint before
starting the next one, since I imagine moving it mid-sprint would be too
disruptive. Does anyone object to this change?
I think the change will look something like this:
1.) Create the Conductor and aeolus-configure repos on GitHub, and give
existing developers commit rights there
2.) Change our .git/config files to point there
3.) Update the aeolusproject.org site which has documentation pointing
to the FH repos
4.) Update Redmine's repo browser to use the new location
5.) Modify Jenkins to use the GitHub repo
6.) Send out an email explaining the change and telling everyone what
they need to do
7.) Add a logo to the main Aeolus Project organization to replace the
default octocat
Again, I'm happy to take the lead on making this happen, but I want to
make sure there's consensus. (Plus, I don't have rights to the project
right now.)
What do you think?
Best,
Matt
11 years, 8 months
OAuth in iwhd preview patch
by Pete Zaitcev
Guys:
Below is what I have now for 2-legged OAuth in iwhd. It actually works,
with oauthtest2 from liboauth.
The patch is only a small piece, since it has no client, which we need
to run the tests, has no documentation, and no user list. However, it
retires most of the risk. We know that it can be done, this way.
The biggest risk left is interoperability with Aeolus.
BTW, the OAuth header looks like this:
Authorization: OAuth realm="http://example.org/", oauth_consumer_key="chiaki",
oauth_nonce="mitPzrhrCMHABJiYava_", oauth_signature_method="HMAC-SHA1",
oauth_timestamp="1317182031", oauth_version="1.0",
oauth_signature="Ya36%2FkXTG5YATRx%2BWAXK9NXzZCg%3D"
-- Pete
diff --git a/configure.ac b/configure.ac
index e23d1fa..8b115cb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -70,6 +70,9 @@ AC_CHECK_LIB([uuid], [uuid_generate_random],
[AC_MSG_ERROR([Missing required uuid lib])])
AC_SUBST([UUID_LIB])
+dnl How to check properly?
+LIBS="$LIBS -loauth"
+
PKG_CHECK_MODULES([HAIL],[libhail >= 0.8])
AC_SUBST([HAIL_LIBS])
AC_SUBST([HAIL_CFLAGS])
@@ -97,6 +100,9 @@ AC_CACHE_CHECK([whether json_load_file takes 3 arguments],
AC_DEFINE_UNQUOTED([JANSSON_LOAD_FLAG], $iw_cv_func_jansson_flag,
[Define to "0," if json_load_file and json_loads require a flags arguments.])
+AC_CHECK_HEADER([oauth.h], ,
+ [AC_MSG_ERROR([Missing OAuth development library: liboauth-devel])])
+
# from http://www.gnu.org/software/autoconf-archive/
AX_BOOST_BASE
AX_BOOST_SYSTEM
diff --git a/rest.c b/rest.c
index 92f36cb..fec602c 100644
--- a/rest.c
+++ b/rest.c
@@ -15,12 +15,14 @@
#include <config.h>
+#include <ctype.h>
#include <error.h>
#include <fcntl.h>
#include <getopt.h>
#include <poll.h>
#include <pthread.h>
#include <semaphore.h>
+#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
@@ -33,6 +35,7 @@
#include <microhttpd.h>
#include <hstor.h> /* only for ARRAY_SIZE at this point */
#include <curl/curl.h>
+#include <oauth.h>
#include "configmake.h" /* for LOCALEDIR */
#include "dirname.h"
@@ -113,6 +116,9 @@ static unsigned short my_port = MY_PORT;
static LIST_HEAD(gc_list, _my_state) my_states; /* this keeps GC informed */
static pthread_mutex_t my_lock = PTHREAD_MUTEX_INITIALIZER;
static const char *log_name;
+static char my_hostname[HOST_NAME_MAX+1];
+static bool oauth = false;
+static const char *username, *userpass;
static const char *const (reserved_name[]) = {"_default", "_new", "_policy", "_query", NULL};
static const char *const (reserved_attr[]) = {"_attrs", "_bucket", "_date", "_etag", "_key", "_loc", "_size", NULL};
@@ -2091,6 +2097,454 @@ parse_url (const char *url, my_state *ms)
return eindex;
}
+/* TBD: evict this to "user.h" once -U is gone. */
+#define USERNAME_MAX 64
+#define USERPASS_MAX 64
+struct user {
+ char name[USERNAME_MAX+1];
+ char pass[USERPASS_MAX+1];
+};
+
+static struct user *
+user_lookup (const char *user)
+{
+ struct user *ret;
+
+ /*
+ * We do not have a real user table yet, so just compare with -U.
+ */
+ if (username == NULL || strcmp(user, username) != 0)
+ return NULL;
+
+ ret = malloc(sizeof(struct user));
+ if (!ret)
+ return NULL;
+ memset(ret,0,sizeof(struct user));
+ strcpy(ret->name, username);
+ strcpy(ret->pass, userpass);
+ return ret;
+}
+
+static char *
+rebuild_url(bool is_ssl, struct MHD_Connection *conn, const char *path)
+{
+ const char *val;
+ char *ret;
+ int rc;
+
+ /*
+ * Luckily for us, this header includes the colon-port.
+ * It really should be called "Netloc", not "Host".
+ */
+ val = MHD_lookup_connection_value(conn,MHD_HEADER_KIND,"Host");
+ if (!val) {
+ if (my_hostname[0] == 0) {
+ if (gethostname(my_hostname, HOST_NAME_MAX) != 0) {
+ /* TBD: This may flood - user-driven. */
+ error (0, errno, _("gethostname"));
+ return NULL;
+ }
+ my_hostname[HOST_NAME_MAX] = 0;
+ }
+ /* TBD: And port? But this is a fall-back anyway. */
+ val = my_hostname;
+ }
+
+ rc = asprintf(&ret, "%s://%s%s", is_ssl? "https": "http", val, path);
+ if (rc < 0) {
+ DPRINTF("No core");
+ return NULL;
+ }
+ return ret;
+}
+
+static const char *
+auth_type_check (const char *val, const char *type)
+{
+ const char *p;
+ size_t tlen = strlen(type);
+
+ p = val;
+ while (*p == ' ') {
+ if (*p == 0) {
+ return false;
+ }
+ p++;
+ }
+ if (strncmp(p, type, tlen) != 0)
+ return false;
+ p += tlen;
+ if (*p != ' ')
+ return false;
+ p++;
+ while (*p == ' ') {
+ if (*p == 0) {
+ return false;
+ }
+ p++;
+ }
+ return p;
+}
+
+/*
+ * Split up an Authorization header.
+ * Note that this decodes the strings.
+ */
+static bool
+auth_hdr_split (int *pargc, char ***pargv, const char *val)
+{
+ enum { ARGC_MAX = 20 }; /* better than 2-pass */
+ enum { VAL_MAX = 512 }; /* a constant is not great, but... */
+ enum {
+ ST_NONE, ST_ERR, ST_KEY, ST_EQ, ST_VAL, ST_Q2, ST_COM,
+ ST_PCENT1, ST_PCENT2
+ } state;
+ int argc;
+ char **argv;
+ const char *p;
+ const char *key;
+ size_t klen = 0;
+ size_t vlen = 0;
+ char vbuf[VAL_MAX+1];
+ unsigned int acc = 0, n;
+ char *arg;
+
+ if (!(val = auth_type_check(val, "OAuth")))
+ return false;
+
+ argv = malloc((ARGC_MAX+1) * sizeof(char*));
+ if (!argv) {
+ return false;
+ }
+ argc = 0;
+
+ arg = NULL;
+ state = ST_NONE;
+ key = NULL;
+ for (p = val; *p != 0; p++) {
+ switch (state) {
+ case ST_NONE:
+ if (*p == ' ') {
+ ;
+ }
+ else if (!isascii(*p) || !isalpha(*p)) {
+ state = ST_ERR;
+ }
+ else {
+ state = ST_KEY;
+ key = p;
+ }
+ break;
+ case ST_KEY:
+ if (*p == '=') {
+ state = ST_EQ;
+ klen = p-key;
+ }
+ break;
+ case ST_EQ:
+ if (*p == '"') {
+ state = ST_VAL;
+ vlen = 0;
+ }
+ else {
+ /*
+ * A compiler writer would've had an ulcer
+ * from this, because obviously we are going
+ * to recover in a dirty way. But whatever,
+ * all we want is an error indication.
+ */
+ state = ST_ERR;
+ }
+ break;
+ case ST_VAL:
+ if (*p == '"') {
+ vbuf[vlen] = 0;
+ state = ST_Q2;
+ }
+ else if (*p == '%') {
+ state = ST_PCENT1;
+ acc = 0;
+ }
+ else {
+ vbuf[vlen++] = *p;
+ }
+ break;
+ case ST_PCENT1:
+ if (isxdigit(*p)) {
+ if (*p <= '9') {
+ n = toupper(*p) - '0';
+ } else {
+ n = toupper(*p) - 'A' + 10;
+ }
+ acc = (acc << 4) | (n & 0x0f);
+ state = ST_PCENT2;
+ } else {
+ state = ST_ERR;
+ }
+ break;
+ case ST_PCENT2:
+ if (isxdigit(*p)) {
+ if (*p <= '9') {
+ n = toupper(*p) - '0';
+ } else {
+ n = toupper(*p) - 'A' + 10;
+ }
+ acc = (acc << 4) | (n & 0x0f);
+ if (iscntrl(acc))
+ acc = '?';
+ if (vlen >= VAL_MAX) {
+ state = ST_ERR;
+ break;
+ }
+ vbuf[vlen++] = acc;
+ state = ST_VAL;
+ }
+ else {
+ state = ST_ERR;
+ }
+ break;
+ case ST_Q2:
+ if (*p == ',') {
+ arg = malloc(klen+1+vlen+1);
+ if (!arg) {
+ state = ST_ERR;
+ break;
+ }
+ memcpy(arg, key, klen);
+ arg[klen] = '=';
+ memcpy(arg+klen+1, vbuf, vlen);
+ arg[klen+1+vlen] = 0;
+
+ state = ST_COM;
+ key = NULL;
+ }
+ else {
+ state = ST_ERR;
+ }
+ break;
+ case ST_COM:
+ if (*p == ' ') {
+ if (!arg) {
+ state = ST_NONE;
+ key = NULL;
+ break;
+ }
+ if (argc >= ARGC_MAX) {
+ /* TBD: error out immediately */
+ state = ST_ERR;
+ break;
+ }
+ argv[argc++] = arg;
+ arg = NULL;
+ state = ST_NONE;
+ key = NULL;
+ }
+ else {
+ state = ST_ERR;
+ }
+ default: // ST_ERR
+ if (*p == ',') {
+ state = ST_COM;
+ }
+ }
+ }
+
+ if (arg) {
+ DPRINTF("auth_hdr_split ended with arg %s\n", arg);
+ free (arg);
+ }
+
+ if (state == ST_Q2) {
+ if (key) {
+ arg = malloc(klen+1+vlen+1);
+ if (arg && argc < ARGC_MAX) {
+ memcpy(arg, key, klen);
+ arg[klen] = '=';
+ memcpy(arg+klen+1, vbuf, vlen);
+ arg[klen+1+vlen] = 0;
+ argv[argc++] = arg;
+ }
+ }
+ }
+ argv[argc] = NULL;
+
+ *pargc = argc;
+ *pargv = argv;
+ return true;
+}
+
+/* Extract the value from key="val". */
+static char *
+oauth_param_val(const char *arg) {
+ char *val;
+
+ val = strchr(arg, '=');
+ if (!val)
+ return NULL;
+ val++;
+ if (*val == 0)
+ return NULL;
+ return strdup(val);
+}
+
+/* clone of oauth_param_exists with minimal changes */
+static int
+oauth_param_find(char **argv, int argc, const char *key) {
+ int i;
+ size_t l= strlen(key);
+ for (i=0;i<argc;i++)
+ if (strlen(argv[i])>l && !strncmp(argv[i],key,l) && argv[i][l] == '=') return i;
+ return -1;
+}
+
+static int
+do_oauth (struct MHD_Connection *conn, my_state *ms,
+ const char *url, const char *method)
+{
+ const char *val;
+ struct MHD_Response *resp;
+ int argc;
+ char **argv;
+ int oargc;
+ char **oargv;
+ int x;
+ struct user *u;
+ char *sig_supplied, *sig_calculated;
+
+ val = MHD_lookup_connection_value(conn,MHD_HEADER_KIND,"Authorization");
+ if (!val) {
+ resp = MHD_create_response_from_data(0,NULL,MHD_NO,MHD_NO);
+ if (!resp) {
+ return -1;
+ }
+ MHD_add_response_header(resp,"WWW-Authenticate","OAuth");
+ MHD_queue_response(conn,MHD_HTTP_UNAUTHORIZED,resp);
+ MHD_destroy_response(resp);
+ return 1;
+ }
+
+ if (!auth_hdr_split(&argc, &argv, val)) {
+ do_resp(conn,NULL,MHD_HTTP_BAD_REQUEST,NULL,"400\r\n");
+ return -1;
+ }
+ if (verbose >= 2) {
+ int i;
+ printf("OAuth supplied [%d]\n", argc);
+ for (i = 0; i < argc; i++) {
+ printf(" %s\n", argv[i]);
+ }
+ }
+
+ x = oauth_param_find(argv,argc,"oauth_consumer_key");
+ if (x == -1) {
+ do_resp(conn,NULL,MHD_HTTP_BAD_REQUEST,NULL,"400 no user\r\n");
+ return -1;
+ }
+
+ u = user_lookup(oauth_param_val(argv[x]));
+ if (!u) {
+ do_resp(conn,NULL,MHD_HTTP_FORBIDDEN,NULL,"403 bad user\r\n");
+ return -1;
+ }
+
+ /*
+ * Putting marshalling arguments for and extracting results from
+ * oauth_sign_array2_process makes you dirty, but this way offloads
+ * some tricks to liboauth, so there.
+ * XXX - verify HMAC or other type
+ */
+ oargc = 1+argc; /* add a slot for URL */
+
+ /*
+ * If we just call malloc() here, we actually involve a function
+ * intercepted by GC. Then, glibc will abort inside liboauth
+ * oauth_sign_array2_process->xrealloc->free() => "invalid pointer".
+ * Solution: use a random liboauth function which allocates
+ * the memory we need. The result can be safely passed to liboauth.
+ */
+ oargv = malloc((oargc+1)*sizeof(char*));
+
+ memset((void*)oargv, '0', (oargc+1)*sizeof(char*));
+ ((char *)oargv)[(oargc+1)*sizeof(char*) - 1] = 0;
+ oargv = (char **) oauth_url_escape((char *)oargv);
+
+ if (!oargv) {
+ do_resp(conn,NULL,MHD_HTTP_INTERNAL_SERVER_ERROR,NULL,
+ "500\r\n");
+ return -1;
+ }
+ oargv[0] = rebuild_url(false, conn, url); /* TBD: SSL */
+ if (!oargv[0]) {
+ do_resp(conn,NULL,MHD_HTTP_INTERNAL_SERVER_ERROR,NULL,
+ "500\r\n");
+ return -1;
+ }
+
+ // no good, must filter
+ // memcpy(&oargv[1], argv, (argc+1)*sizeof(char*));
+
+ oargc = 1;
+
+ x = oauth_param_find(argv,argc,"oauth_nonce");
+ if (x == -1) {
+ do_resp(conn,NULL,MHD_HTTP_BAD_REQUEST,NULL,"400 no nonce\r\n");
+ return -1;
+ }
+ oargv[oargc++] = argv[x];
+
+ x = oauth_param_find(argv,argc,"oauth_timestamp");
+ if (x == -1) {
+ do_resp(conn,NULL,MHD_HTTP_BAD_REQUEST,NULL,
+ "400 no timestamp\r\n");
+ return -1;
+ }
+ oargv[oargc++] = argv[x];
+
+ oauth_sign_array2_process(&oargc, &oargv, NULL, OA_HMAC, method,
+ u->name, u->pass, NULL, NULL);
+ if (verbose >= 2) {
+ int i;
+ printf("OAuth calculated\n");
+ for (i = 0; i < oargc; i++) {
+ printf(" %s\n", oargv[i]);
+ }
+ }
+
+ /*
+ * We've got the signature, now verify.
+ */
+ x = oauth_param_find(argv,argc,"oauth_signature");
+ if (x == -1) {
+ do_resp(conn,NULL,MHD_HTTP_BAD_REQUEST,NULL,
+ "400 no signature\r\n");
+ return -1;
+ }
+ sig_supplied = oauth_param_val(argv[x]);
+
+ x = oauth_param_find(oargv,oargc,"oauth_signature");
+ if (x == -1) {
+ do_resp(conn,NULL,MHD_HTTP_INTERNAL_SERVER_ERROR,NULL,
+ "500 no signature\r\n");
+ return -1;
+ }
+ sig_calculated = oauth_param_val(oargv[x]);
+
+ if (strcmp(sig_supplied, sig_calculated) != 0) {
+ DPRINTF("OAuth signature mismatch");
+ return -1;
+ }
+ return 0;
+}
+
+static int kv_iter_dump(void *cls, enum MHD_ValueKind kind,
+ const char *key, const char *value)
+{
+ /* ok to use printf when MHD_USE_THREAD_PER_CONNECTION maybe? */
+ printf("%s: %s\n", key, value);
+
+ return MHD_YES;
+}
+
static int
access_handler_0 (void *cctx, struct MHD_Connection *conn, const char *url,
const char *method, const char *version, const char *data,
@@ -2099,10 +2553,24 @@ access_handler_0 (void *cctx, struct MHD_Connection *conn, const char *url,
unsigned int i;
url_type utype;
my_state *ms = *rctx;
+ int rc;
log_check();
+ if (verbose >= 2) {
+ printf(">> HTTP\n");
+ rc = MHD_get_connection_values(conn, MHD_HEADER_KIND,
+ kv_iter_dump, NULL);
+ printf(">> headers: %d\n", rc);
+ }
if (ms) {
+ if (oauth) {
+ rc = do_oauth(conn,ms,url,method);
+ if (rc < 0)
+ return MHD_NO;
+ if (rc > 0)
+ return MHD_YES;
+ }
return ms->handler(cctx,conn,url,method,version,
data,data_size,rctx);
}
@@ -2131,12 +2599,20 @@ access_handler_0 (void *cctx, struct MHD_Connection *conn, const char *url,
ms->conn = conn;
*rctx = ms;
pthread_mutex_lock(&my_lock);
- LIST_INSERT_HEAD(&my_states, ms, gc_link);
+ LIST_INSERT_HEAD(&my_states,ms,gc_link);
pthread_mutex_unlock(&my_lock);
+ if (oauth) {
+ rc = do_oauth(conn,ms,url,method);
+ if (rc < 0)
+ return MHD_NO;
+ if (rc > 0)
+ return MHD_YES;
+ }
return ms->handler(cctx,conn,url,method,version,
data,data_size,rctx);
}
+ /* This is *unauthenticated*. Remove altogether? TBD */
if (!strcmp(method,"QUIT")) {
(void)sem_post((sem_t *)cctx);
return MHD_NO;
@@ -2194,7 +2670,9 @@ static const struct option my_options[] = {
{ "db", required_argument, NULL, 'd' },
{ "logfile", required_argument, NULL, 'l' },
{ "master", required_argument, NULL, 'm' },
+ { "oauth", no_argument, NULL, 'o' },
{ "port", required_argument, NULL, 'p' },
+ { "usercred", required_argument, NULL, 'U' },
{ "verbose", no_argument, NULL, 'v' },
{ "version", no_argument, NULL, GETOPT_VERSION_CHAR },
{ "help", no_argument, NULL, GETOPT_HELP_CHAR },
@@ -2222,7 +2700,9 @@ A configuration file must be specified.\n\
-d, --db=HOST_PORT database server as ip[:port]\n\
-l, --logfile=FILE logfile (default stdout/stderr)\n\
-m, --master=HOST_PORT master (upstream) server as ip[:port]\n\
+ -o, --oauth enable OAuth\n\
-p, --port=PORT alternate listen port (default 9090)\n\
+ -U, --usercred=U:P singleton pair of username:password\n\
-v, --verbose verbose/debug output\n\
\n\
--help display this help and exit\n\
@@ -2275,6 +2755,7 @@ main (int argc, char **argv)
sem_t the_sem;
bool autostart = false;
char *cfg_file = NULL;
+ char *usercred = NULL;
set_program_name (argv[0]);
setlocale (LC_ALL, "");
@@ -2287,7 +2768,8 @@ main (int argc, char **argv)
db_host = xstrdup ("localhost");
for (;;)
- switch (getopt_long(argc,argv,"ac:d:l:m:p:v",my_options,NULL)) {
+ switch (getopt_long(argc,argv,"ac:d:l:m:op:U:v",my_options,NULL))
+ {
case 'a':
autostart = true;
break;
@@ -2308,10 +2790,16 @@ main (int argc, char **argv)
free (master_host); master_host = NULL;
extract_host_port (optarg, &master_host, &master_port);
break;
+ case 'o':
+ oauth = true;
+ break;
case 'p':
assert (optarg);
my_port = get_port (optarg);
break;
+ case 'U': /* Uppercase because very temporary until -u appears. */
+ usercred = optarg;
+ break;
case 'v':
++verbose;
break;
@@ -2366,6 +2854,30 @@ args_done:
usage (EXIT_FAILURE);
}
+ if (usercred) {
+ const char *p = strchr(usercred,':');
+ if (!p) {
+ error (0, 0, _("The -U argument must contain a colon"));
+ usage (EXIT_FAILURE);
+ }
+ if (p == usercred) {
+ error (0, 0,
+ _("The user part of -U argument is empty"));
+ usage (EXIT_FAILURE);
+ }
+ username = strndup(usercred,p-usercred);
+ userpass = strdup(p+1);
+ if (!username || !userpass) {
+ error (EXIT_FAILURE, 0, _("No core"));
+ }
+ if (strlen(username) > USERNAME_MAX) {
+ error (EXIT_FAILURE, 0, _("User name too long"));
+ }
+ if (strlen(userpass) > USERPASS_MAX) {
+ error (EXIT_FAILURE, 0, _("User password too long"));
+ }
+ }
+
char *t;
char const *tmpdir = ((t = getenv ("TMPDIR")) ? t : "/tmp");
tmpfile_template = xasprintf ("%s/iwhd.XXXXXX", tmpdir);
@@ -2382,6 +2894,9 @@ args_done:
printf("db is at %s:%u\n",db_host,db_port);
printf("will listen on port %u\n",my_port);
printf("my location is \"%s\"\n",me);
+ if (oauth) {
+ printf("autheticated with OAuth\n");
+ }
if (fflush(stdout) || ferror(stdout))
error(EXIT_FAILURE, 0, _("write failed"));
}
11 years, 8 months
[PATCH conductor] Implement User card automatic filling with the form information
by jzigmund@redhat.com
From: Jozef Zigmund <jzigmund(a)redhat.com>
---
src/app/stylesheets/custom.scss | 11 +++++++++++
src/app/views/users/_form.haml | 28 +++++++++++++++++++++++-----
src/app/views/users/edit.haml | 7 ++++---
src/app/views/users/new.haml | 7 ++++---
4 files changed, 42 insertions(+), 11 deletions(-)
diff --git a/src/app/stylesheets/custom.scss b/src/app/stylesheets/custom.scss
index d019798..967137b 100644
--- a/src/app/stylesheets/custom.scss
+++ b/src/app/stylesheets/custom.scss
@@ -47,3 +47,14 @@
ul.deployment-array.small li.deployment {
height: 90px;
}
+
+div#user_card header.user-card-header h2#first_name {
+ color: white;
+ padding: 15px 10px 10px 60px;
+ background: transparent url('../../images/user_card_icon.png') no-repeat 12px 10px;
+}
+
+div#user_card header.user-card-header h2#first_name + h2#last_name {
+ padding: 0px;
+ background: transparent;
+}
\ No newline at end of file
diff --git a/src/app/views/users/_form.haml b/src/app/views/users/_form.haml
index 43f49f8..0289025 100644
--- a/src/app/views/users/_form.haml
+++ b/src/app/views/users/_form.haml
@@ -1,20 +1,20 @@
- if @user.errors.any?
= render 'layouts/error_messages', :object => @user
-%fieldset
+%fieldset.kokot
%p
= form.label :first_name, t(:first_name)
- = form.text_field :first_name
+ = form.text_field :first_name, :class =>"check_change"
%p
= form.label :last_name, t(:last_name)
- = form.text_field :last_name
+ = form.text_field :last_name, :class =>"check_change"
%p
= form.label :email, t(:email)
- = form.text_field :email
+ = form.text_field :email, :class =>"check_change"
%fieldset
%p
= form.label :login, t(:choose_name)
- = form.text_field :login, :class => "em"
+ = form.text_field :login, :class => "em check_change"
%p
= form.label :password, form.object.new_record? ? t(:choose_password) : t(:change_password)
= form.password_field :password
@@ -48,3 +48,21 @@
%fieldset.options
= form.submit "Save User", :class => "submit button pill"
+
+:javascript
+ $('.check_change').change(function(){
+ switch(this.id){
+ case 'user_last_name':
+ $('h2#last_name').text(this.value);
+ break;
+ case 'user_first_name':
+ $('h2#first_name').text(this.value);
+ break;
+ case 'user_email':
+ $('dd#email').text(this.value);
+ break;
+ case 'user_login':
+ $('dd#login').text(this.value);
+ break;
+ }
+ });
diff --git a/src/app/views/users/edit.haml b/src/app/views/users/edit.haml
index ddbb891..aebcfd7 100644
--- a/src/app/views/users/edit.haml
+++ b/src/app/views/users/edit.haml
@@ -12,12 +12,13 @@
.content
#user_card.user_form_card
%header.user-card-header
- %h2= @user.name
+ %h2#first_name= @user.first_name
+ %h2#last_name= @user.last_name
.user-card-content
%dl
%dt E-mail Address
- %dd= @user.email
+ %dd#email= @user.email
%dt Username
- %dd= @user.login
+ %dd#login= @user.login
= form_for @user, :url => user_path(@user), :html => { :method => :put, :class => 'generic' } do |f|
= render :partial => "form", :locals => { :form => f, :cancel_path => users_path }
diff --git a/src/app/views/users/new.haml b/src/app/views/users/new.haml
index d5d76d9..ca41a1b 100644
--- a/src/app/views/users/new.haml
+++ b/src/app/views/users/new.haml
@@ -14,13 +14,14 @@
%br
#user_card.user_form_card
%header.user-card-header
- %h2 Kenneth Keiter
+ %h2 Kenneth
+ %h2#last_name Keiter
.user-card-content
%dl
%dt E-mail Address
- %dd kkeiter(a)redhat.com
+ %dd#email kkeiter(a)redhat.com
%dt Username
- %dd kkeiter
+ %dd#login kkeiter
= form_for @user, :url => users_path, :html => {:class => 'generic'} do |f|
-if current_user
= render :partial => "form", :locals => { :form => f }
--
1.7.6.2
11 years, 8 months
RFC: proposal for upcoming release of aeolus project components
by steve linabery
Hello aeolus community,
I think it's high time we did a community release of aeolus components.
To quote an aeolus thought leader:
"we have good reasons for doing it now -- we've got most stuff working end to end again on rails 3, we've pulled Condor, we have an admin UI, we have a (not perfect but adequate) permissions management UI, etc."
And I agree; we're overdue and the time is right. There is an 0.4.0 branch in conductor git repo which needs to be brought up current with master, and then I say we tag a RC early next week and pick over commits through end of sprint.
Steve|eggs
11 years, 8 months
[PATCH conductor] Fix delete button on deployment#show
by jzigmund@redhat.com
From: Jozef Zigmund <jzigmund(a)redhat.com>
---
src/app/views/deployments/_header_show.haml | 2 +-
src/features/deployment.feature | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/app/views/deployments/_header_show.haml b/src/app/views/deployments/_header_show.haml
index 8d03753..a1ea557 100644
--- a/src/app/views/deployments/_header_show.haml
+++ b/src/app/views/deployments/_header_show.haml
@@ -3,5 +3,5 @@
= [@deployment.name, "Deployment"].join(' ')
#obj_actions.button-container
.button-group
- = button_to 'Delete', deployment_path(@deployment), :method => :delete, :confirm => t("deployments.confirm_delete"), :class => "button pill danger", :id => 'delete_button'
+ = button_to 'Delete', deployment_path(@deployment), :method => :delete, :confirm => t("deployments.confirm_delete"), :class => "button pill danger", :id => 'delete'
.corner
diff --git a/src/features/deployment.feature b/src/features/deployment.feature
index e246c1a..aab0c5c 100644
--- a/src/features/deployment.feature
+++ b/src/features/deployment.feature
@@ -175,7 +175,7 @@ Feature: Manage Deployments
Given there is a deployment named "testdeployment" belonging to "testdeployable" owned by "testuser"
And I am on the pools page
When I follow "testdeployment"
- And I press "delete_button"
+ And I press "delete"
Then I should see "The deployment testdeployment was scheduled for deletion"
Scenario: Delete multiple deployments
@@ -195,7 +195,7 @@ Feature: Manage Deployments
And the instance "myinstance" is in the running state
And I am on the pools page
When I follow "mockdeployment"
- And I press "delete_button"
+ And I press "delete"
Then I should see "The deployment mockdeployment was scheduled for deletion"
Scenario: Launch a deployment which is not launchable
--
1.7.6.2
11 years, 8 months
[PATCH conductor] Fix flash messages for multi_stop action in deployments_controller
by jzigmund@redhat.com
From: Jozef Zigmund <jzigmund(a)redhat.com>
---
src/app/controllers/deployments_controller.rb | 8 ++++----
src/app/views/layouts/_new_notification.haml | 16 ++++++++++++++--
2 files changed, 18 insertions(+), 6 deletions(-)
diff --git a/src/app/controllers/deployments_controller.rb b/src/app/controllers/deployments_controller.rb
index 98171a9..b74bebb 100644
--- a/src/app/controllers/deployments_controller.rb
+++ b/src/app/controllers/deployments_controller.rb
@@ -234,8 +234,8 @@ class DeploymentsController < ApplicationController
end
def multi_stop
- notices = ""
- errors = ""
+ notices = []
+ errors = []
Deployment.find(params[:deployments_selected] || []).each do |deployment|
deployment.instances.each do |instance|
begin
@@ -250,9 +250,9 @@ class DeploymentsController < ApplicationController
raise ActionError.new("stop cannot be performed on this instance.")
end
Taskomatic.stop_instance(@task)
- notices << "Deployment: #{instance.deployment.name}, Instance: #{instance.name}: stop action was successfully queued.<br/>"
+ notices << "Deployment: #{instance.deployment.name}, Instance: #{instance.name}: stop action was successfully queued."
rescue Exception => err
- errors << "Deployment: #{instance.deployment.name}, Instance: #{instance.name}: " + err + "<br/>"
+ errors << "Deployment: #{instance.deployment.name}, Instance: #{instance.name}: " + err
end
end
end
diff --git a/src/app/views/layouts/_new_notification.haml b/src/app/views/layouts/_new_notification.haml
index 33a654c..e248684 100644
--- a/src/app/views/layouts/_new_notification.haml
+++ b/src/app/views/layouts/_new_notification.haml
@@ -14,7 +14,11 @@
%div.heading
=image_tag 'flash_notice_icon.png', :alt => 'Notices'
%ul.flashes
- %li= flash[:notice]
+ -if flash[:notice].kind_of?(Array)
+ -flash[:notice].each do |msg|
+ %li= msg
+ -else flash[:notice]
+ %li= flash[:notice]
-if flash[:warning]
.warning.flash-group
@@ -30,7 +34,7 @@
%div.heading
=image_tag 'flash_error_icon.png', :alt => 'Errors'
=flash[:error]
- -else
+ -elsif flash[:error].kind_of?(Hash)
-unless flash[:error][:successes].blank?
.notice.flash-group
.flash-subset
@@ -55,3 +59,11 @@
-else
-flash[:error].each do |e|
%li= e
+ -elsif flash[:error].kind_of?(Array)
+ .error.flash-group
+ .flash-subset
+ %div.heading
+ =image_tag 'flash_error_icon.png', :alt => 'Errors'
+ %ul.flashes
+ -flash[:error].each do |msg|
+ %li= msg
--
1.7.6.2
11 years, 8 months