This patch makes the classad plugin use the REST API. This introduces
a requirement on librest so you will now have to have rest-devel,
glib2-devel, libsoup-devel, and libxml2-devel installed to build.
Signed-off-by: Ian Main <imain(a)redhat.com>
---
configure.ac | 6 +
deltacloud-aggregator.spec.in | 8 ++
src/app/util/condormatic.rb | 11 +-
src/classad_plugin/Makefile.am | 12 +-
src/classad_plugin/classad_plugin.rb | 79 -------------
src/classad_plugin/deltacloud_classad_plugin.cpp | 128 +++++++++++----------
6 files changed, 92 insertions(+), 152 deletions(-)
delete mode 100644 src/classad_plugin/classad_plugin.rb
diff --git a/configure.ac b/configure.ac
index 9598925..c597a74 100644
--- a/configure.ac
+++ b/configure.ac
@@ -33,6 +33,12 @@ elif test "x$with_classads" = "x"; then
fi
fi
+PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.18)
+PKG_CHECK_MODULES(SOUP, libsoup-2.4)
+PKG_CHECK_MODULES(XML, libxml-2.0)
+PKG_CHECK_MODULES(GTHREAD, gthread-2.0)
+PKG_CHECK_MODULES(REST, rest-0.6)
+
# If using gcc and default CFLAGS, enable some warnings.
test x"$ac_ct_CC:$CFLAGS" = 'xgcc:-g -O2' \
&& CFLAGS="$CFLAGS -Wshadow -Wall -Werror"
diff --git a/deltacloud-aggregator.spec.in b/deltacloud-aggregator.spec.in
index 0632f79..c7d6a7b 100644
--- a/deltacloud-aggregator.spec.in
+++ b/deltacloud-aggregator.spec.in
@@ -38,6 +38,10 @@ Requires: postgresql-server
Requires: ruby-postgres
Requires: ruby-RMagick
Requires: classads >= 1.0
+Requires: libsoup >= 2.0
+Requires: glib2 >= 2.0
+Requires: libxml2 >= 2.6
+Requires: rest >= 0.6
Requires: condor >= 7.5.5-10dcloud
Requires: iwhd
Requires: deltacloud-configure
@@ -45,6 +49,10 @@ Requires: deltacloud-configure
BuildRequires: ruby
BuildRequires: ruby-devel
BuildRequires: classads-devel >= 1.0
+BuildRequires: libsoup-devel >= 2.0
+BuildRequires: glib2-devel >= 2.0
+BuildRequires: libxml2-devel >= 2.6
+BuildRequires: rest-devel >= 0.6
%package daemons
Summary: Deltacloud Aggregator daemons config
diff --git a/src/app/util/condormatic.rb b/src/app/util/condormatic.rb
index 8b4e224..1d52d21 100644
--- a/src/app/util/condormatic.rb
+++ b/src/app/util/condormatic.rb
@@ -57,13 +57,10 @@ def condormatic_instance_create(task)
requirements = "requirements = hardwareprofile ==
\"#{instance.hardware_profile.id}\" && image ==
\"#{instance.template.id}\""
requirements += " && realm == \"#{realm.id}\"" if realm
!= nil
- # We may need to add some stuff to the provider classads like pool id, provider id
etc. This is mostly just
- # to test and make sure this works for now.
- #
- # This is currently broken as the condor plugin loads models without initializing
rails.
- # However, recent changes have required that rails be initialized in order to load
the
- # pool and quota models.
- #requirements += " && deltacloud_quota_check(\"#{job_name}\",
other.cloud_account_id)"
+ # Call into the deltacloud quota plugin. This uses a REST API to call back into the
+ # conductor to check quotas as the last thing in the logical AND to match a provider
+ # account.
+ requirements += " && deltacloud_quota_check(#{instance.id},
other.cloud_account_id)"
requirements += "\n"
pipe.puts requirements
diff --git a/src/classad_plugin/Makefile.am b/src/classad_plugin/Makefile.am
index 9334f5f..5d40240 100644
--- a/src/classad_plugin/Makefile.am
+++ b/src/classad_plugin/Makefile.am
@@ -1,12 +1,14 @@
-AM_CPPFLAGS=-I`ruby -e "require 'rbconfig' ; puts
Config::CONFIG['archdir']"` \
- -DDELTACLOUD_INSTALL_DIR=\"$(DELTACLOUD_INSTALL_DIR)\"
-DLOGFILE=\"/var/log/condor/deltacloud_condor_plugin.log\"
+AM_CPPFLAGS= $(GLIB_CFLAGS) $(GTHREAD_CFLAGS) \
+ $(SOUP_CFLAGS) $(SOUP_GNOME_CFLAGS) \
+ $(XML_CFLAGS) $(REST_CFLAGS) \
+ -DLOGFILE=\"/var/log/condor/deltacloud_condor_plugin.log\"
classadplugindir=$(pkgdatadir)/classad_plugin
classadplugin_LTLIBRARIES = deltacloud_classad_plugin.la
deltacloud_classad_plugin_la_SOURCES = deltacloud_classad_plugin.cpp
-deltacloud_classad_plugin_la_LIBADD = -lclassad -lruby
+deltacloud_classad_plugin_la_LIBADD = $(GLIB_LIBS) $(GTHREAD_LIBS) \
+ $(SOUP_LIBS) $(SOUP_GNOME_LIBS) $(XML_LIBS) $(REST_LIBS)\
+ -lclassad
deltacloud_classad_plugin_la_LDFLAGS = -module -avoid-version -shared
-
-classadplugin_DATA = classad_plugin.rb
diff --git a/src/classad_plugin/classad_plugin.rb b/src/classad_plugin/classad_plugin.rb
deleted file mode 100644
index 2aabfb9..0000000
--- a/src/classad_plugin/classad_plugin.rb
+++ /dev/null
@@ -1,79 +0,0 @@
-require 'rubygems'
-require 'active_record'
-require 'search_filter'
-require 'permissioned_object'
-require 'authlogic'
-require 'user'
-require 'instance'
-require 'cloud_account'
-require 'pool'
-require 'quota'
-
-class BashParser
- def initialize(filename)
- @config = {}
-
- f = File.open(filename, 'r')
- while (line = f.gets)
- strip = line.strip.gsub(/#.*/, '').gsub(/^export /, '')
- if strip.length == 0
- next
- end
-
- x = strip.split('=')
- if x.length != 2
- next
- end
-
- @config[x[0]] = x[1]
- end
-
- f.close
- end
-
- def get_value(name)
- @config[name]
- end
-end
-
-def classad_plugin(logf, conf_path, instance_key, account_id)
- rails_env = "development"
-
- begin
- config = BashParser.new('/etc/sysconfig/deltacloud-rails')
- env = config.get_value('RAILS_ENV')
- if not env.nil?
- rails_env = env
- end
- rescue
- # if any of this failed, then just assume the development database and
- # hope for the best
- end
-
- logf.puts "loading db config from #{conf_path}, using environment
#{rails_env}"
- conf = YAML::load(File.open(conf_path))
- ActiveRecord::Base.establish_connection(conf[rails_env])
-
- # I left the puts in here because you can run condor_negotiator -f from the
- # command line and it will print this stuff out. Very nice for debugging.
- logf.puts "getting instance from key #{instance_key}"
- instance = Instance.find(:first,
- :conditions => [ "condor_job_id = ?",
instance_key ])
- logf.puts "getting cloud account from id #{account_id}"
- cloud_account = CloudAccount.find(:first,
- :conditions => [ "id = ?", account_id
])
-
- logf.puts "instance is: #{instance}, cloud account is #{cloud_account}"
-
- return false if instance.nil?
- return false if cloud_account.nil?
-
- logf.puts "checking quota.."
- ret = Quota.can_start_instance?(instance, cloud_account)
- logf.puts "After checking quota, ret is #{ret}"
-
- logf.puts "Disconnecting from the database"
- ActiveRecord::Base.connection.disconnect!
-
- return ret
-end
diff --git a/src/classad_plugin/deltacloud_classad_plugin.cpp
b/src/classad_plugin/deltacloud_classad_plugin.cpp
index 74d6023..cfd52c8 100644
--- a/src/classad_plugin/deltacloud_classad_plugin.cpp
+++ b/src/classad_plugin/deltacloud_classad_plugin.cpp
@@ -1,4 +1,3 @@
-#include <ruby.h>
#include <stdio.h>
#include <iostream>
@@ -7,6 +6,9 @@
#include "classad/classad_distribution.h"
#include "classad/fnCall.h"
+#include <rest/rest-proxy.h>
+#include <rest/rest-xml-parser.h>
+
using namespace std;
#ifdef WANT_CLASSAD_NAMESPACE
using namespace classad;
@@ -70,6 +72,26 @@ static void _print_value(FILE *fp, Value val, const char *name)
fprintf(fp, "%s\n", sstr.str().c_str());
}
+static RestXmlNode *
+get_xml (RestProxyCall *call)
+{
+ RestXmlParser *parser;
+ RestXmlNode *root;
+ GError *error = NULL;
+
+ parser = rest_xml_parser_new ();
+
+ root = rest_xml_parser_parse_from_data (parser,
+ rest_proxy_call_get_payload (call),
+ rest_proxy_call_get_payload_length (call));
+
+ g_object_unref (call);
+ g_object_unref (parser);
+
+ return root;
+}
+
+
/*
* Perform our quota check against the deltacloud aggregator database.
* This function expects:
@@ -87,14 +109,18 @@ bool
deltacloud_quota_check(const char *name, const ArgumentList &arglist,
EvalState &state, Value &result)
{
- Value instance_key;
+ Value instance_id;
Value account_id;
FILE *fp;
- VALUE res;
bool val = false;
- char *ruby_string;
- std::stringstream method_args;
- int rc;
+ RestProxy *proxy;
+ RestProxyCall *call;
+ RestXmlNode *root;
+ std::stringstream rest_call;
+ GError *err = NULL;
+
+ g_thread_init (NULL);
+ g_type_init ();
result.SetBooleanValue(false);
@@ -106,22 +132,22 @@ deltacloud_quota_check(const char *name, const ArgumentList
&arglist,
goto do_ret;
}
- if (!arglist[0]->Evaluate(state, instance_key)) {
+ if (!arglist[0]->Evaluate(state, instance_id)) {
result.SetErrorValue();
- fprintf(fp, "Could not evaluate argument 0 to instance key\n");
+ fprintf(fp, "Could not evaluate argument 0 to instance id\n");
goto do_ret;
}
if (!arglist[1]->Evaluate(state, account_id)) {
result.SetErrorValue();
- fprintf(fp, "Could not evaluate argument 1 to account_id\n");
+ fprintf(fp, "Could not evaluate argument 1 to account id\n");
goto do_ret;
}
- print_type(fp, instance_key);
- print_value(fp, instance_key);
- if (instance_key.GetType() != Value::STRING_VALUE) {
+ print_type(fp, instance_id);
+ print_value(fp, instance_id);
+ if (instance_id.GetType() != Value::INTEGER_VALUE) {
result.SetErrorValue();
- fprintf(fp, "Instance type was not a string\n");
+ fprintf(fp, "Instance id type was not an integer\n");
goto do_ret;
}
@@ -133,56 +159,36 @@ deltacloud_quota_check(const char *name, const ArgumentList
&arglist,
goto do_ret;
}
- ruby_init();
- ruby_init_loadpath();
-
- method_args << "'" << DELTACLOUD_INSTALL_DIR <<
"/config/database.yml', '"
- << instance_key << "', " << account_id;
-
- rc = asprintf(&ruby_string,
- "$: << '%s/classad_plugin'\n"
- "$: << '%s/app/models'\n"
- "logf = File.new('%s', 'a')\n"
- "logf.puts \"Loading ruby support file from
%s/classad_plugin\"\n"
- "begin\n"
- " require 'classad_plugin.rb'\n"
- " ret = classad_plugin(logf, %s)\n"
- "rescue Exception => ex\n"
- " logf.puts \"Error running classad plugin: #{ex.message}\"\n"
- " logf.puts ex.backtrace\n"
- " ret = false\n"
- "end\n"
- "logf.close\n"
- "ret",
- DELTACLOUD_INSTALL_DIR,
- DELTACLOUD_INSTALL_DIR,
- LOGFILE,
- DELTACLOUD_INSTALL_DIR,
- method_args.str().c_str());
-
- if (rc < 0) {
- fprintf(fp, "Failed to allocate memory for asprintf\n");
- goto do_ret;
+ rest_call << "resources/instances/" << instance_id <<
"/can_start/" << account_id;
+
+ // Call rest API to get answer on quota..
+ proxy = rest_proxy_new ("http://localhost:3000/deltacloud", FALSE);
+ call = rest_proxy_new_call (proxy);
+ rest_proxy_call_set_function (call, rest_call.str().c_str());
+
+ fprintf(fp, "Calling REST API with %s\n", rest_call.str().c_str());
+ rest_proxy_call_sync (call, &err);
+
+ if (err != NULL) {
+ fprintf (fp, "Error calling REST API: %s\n", err->message);
+ } else {
+ root = get_xml (call);
+ if (root) {
+ RestXmlNode *node;
+ gchar *value;
+
+ node = rest_xml_node_find (root, "value");
+ value = node->content;
+
+ fprintf (fp, "return value is %s\n", value);
+ if (strncmp(value, "true", 4) == 0) {
+ result.SetBooleanValue(true);
+ val = true;
+ }
+ }
}
- fprintf(fp, "ruby string is %s\n", ruby_string);
- fflush(fp);
-
- res = rb_eval_string(ruby_string);
- free(ruby_string);
-
- /* FIXME: I'd like to call ruby_finalize here, but it spews weird errors:
- *
- * Error running classad plugin: wrong argument type Mutex (expected Data)
- */
- //ruby_finalize();
-
- fprintf(fp, "Returned result from ruby code was %s\n", (res == Qtrue) ?
"true" : "false");
-
- if (res == Qtrue) {
- result.SetBooleanValue(true);
- val = true;
- }
+ g_object_unref (proxy);
do_ret:
fclose(fp);
--
1.7.4