summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--savannaclient/api/base.py25
-rw-r--r--savannaclient/api/client.py10
-rw-r--r--savannaclient/api/cluster_templates.py8
-rw-r--r--savannaclient/api/clusters.py14
-rw-r--r--savannaclient/api/data_sources.py26
-rw-r--r--savannaclient/api/job_binaries.py25
-rw-r--r--savannaclient/api/job_binary_internals.py22
-rw-r--r--savannaclient/api/job_executions.py29
-rw-r--r--savannaclient/api/job_origins.py43
-rw-r--r--savannaclient/api/jobs.py32
-rw-r--r--savannaclient/api/node_group_templates.py15
-rw-r--r--savannaclient/api/plugins.py13
-rw-r--r--setup.cfg12
-rw-r--r--tox.ini4
14 files changed, 134 insertions, 144 deletions
diff --git a/savannaclient/api/base.py b/savannaclient/api/base.py
index 9b475db..fa584f0 100644
--- a/savannaclient/api/base.py
+++ b/savannaclient/api/base.py
@@ -56,7 +56,6 @@ def _check_items(obj, searches):
return False
-#TODO(nkonovalov) handle response body in case of error
class ResourceManager(object):
resource_class = None
@@ -78,9 +77,9 @@ class ResourceManager(object):
self._raise_api_exception(resp)
if response_key is not None:
- data = resp.json()[response_key]
+ data = get_json(resp)[response_key]
else:
- data = resp.json()
+ data = get_json(resp)
return self.resource_class(self, data)
def _update(self, url, data):
@@ -91,7 +90,7 @@ class ResourceManager(object):
def _list(self, url, response_key):
resp = self.api.client.get(url)
if resp.status_code == 200:
- data = resp.json()[response_key]
+ data = get_json(resp)[response_key]
return [self.resource_class(self, res)
for res in data]
@@ -103,9 +102,9 @@ class ResourceManager(object):
if resp.status_code == 200:
if response_key is not None:
- data = resp.json()[response_key]
+ data = get_json(resp)[response_key]
else:
- data = resp.json()
+ data = get_json(resp)
return self.resource_class(self, data)
else:
self._raise_api_exception(resp)
@@ -120,9 +119,21 @@ class ResourceManager(object):
return self.resource_class.resource_name + 's'
def _raise_api_exception(self, resp):
- error_data = resp.json()
+ error_data = get_json(resp)
raise APIException(error_data["error_message"])
+def get_json(response):
+ """This method provided backward compatibility with old versions
+ of requests library
+
+ """
+ json_field_or_function = getattr(response, 'json', None)
+ if callable(json_field_or_function):
+ return response.json()
+ else:
+ return json.loads(response.content)
+
+
class APIException(Exception):
pass
diff --git a/savannaclient/api/client.py b/savannaclient/api/client.py
index 284b08b..8eb120b 100644
--- a/savannaclient/api/client.py
+++ b/savannaclient/api/client.py
@@ -29,7 +29,6 @@ from savannaclient.api import images
from savannaclient.api import job_binaries
from savannaclient.api import job_binary_internals
from savannaclient.api import job_executions
-from savannaclient.api import job_origins
from savannaclient.api import jobs
from savannaclient.api import node_group_templates
from savannaclient.api import plugins
@@ -38,10 +37,10 @@ LOG = logging.getLogger(__name__)
class Client(object):
- def __init__(self, username, api_key, project_id=None, project_name=None,
- auth_url=None, savanna_url=None, timeout=None,
- endpoint_type='publicURL', service_type='mapreduce',
- input_auth_token=None):
+ def __init__(self, username=None, api_key=None, project_id=None,
+ project_name=None, auth_url=None, savanna_url=None,
+ timeout=None, endpoint_type='publicURL',
+ service_type='mapreduce', input_auth_token=None):
if savanna_url and not isinstance(savanna_url, six.string_types):
raise RuntimeError('Savanna url should be string')
if (isinstance(project_name, six.string_types) or
@@ -93,7 +92,6 @@ class Client(object):
self.data_sources = data_sources.DataSourceManager(self)
self.jobs = jobs.JobsManager(self)
- self.job_origins = job_origins.JobOriginsManager(self)
self.job_executions = job_executions.JobExecutionsManager(self)
self.job_binaries = job_binaries.JobBinariesManager(self)
self.job_binary_internals =\
diff --git a/savannaclient/api/cluster_templates.py b/savannaclient/api/cluster_templates.py
index fef2cc9..c18de32 100644
--- a/savannaclient/api/cluster_templates.py
+++ b/savannaclient/api/cluster_templates.py
@@ -26,18 +26,20 @@ class ClusterTemplateManager(base.ResourceManager):
resource_class = ClusterTemplate
def create(self, name, plugin_name, hadoop_version, description,
- cluster_configs, node_groups, anti_affinity):
- # expecting node groups to be array of dictionaries
+ cluster_configs, node_groups, anti_affinity, net_id=None):
data = {
'name': name,
'plugin_name': plugin_name,
'hadoop_version': hadoop_version,
'description': description,
'cluster_configs': cluster_configs,
- 'node_groups': node_groups,
+ 'node_groups': [ng.as_dict() for ng in node_groups],
'anti_affinity': anti_affinity
}
+ if net_id:
+ data.update({'neutron_management_network': net_id})
+
return self._create('/cluster-templates', data, 'cluster_template')
def list(self):
diff --git a/savannaclient/api/clusters.py b/savannaclient/api/clusters.py
index aa2b1ca..0245560 100644
--- a/savannaclient/api/clusters.py
+++ b/savannaclient/api/clusters.py
@@ -31,12 +31,19 @@ class ClusterManager(base.ResourceManager):
raise base.APIException('Cluster is missing field "%s"' %
var_name)
+ def _copy_if_defined(self, data, **kwargs):
+ for var_name, var_value in kwargs.iteritems():
+ if var_value is not None:
+ data[var_name] = var_value
+
def create(self, name, plugin_name, hadoop_version,
cluster_template_id=None, default_image_id=None,
description=None, cluster_configs=None, node_groups=None,
- user_keypair_id=None, anti_affinity=None):
+ user_keypair_id=None, anti_affinity=None, net_id=None):
+
+ if node_groups is not None:
+ node_groups = [ng.as_dict() for ng in node_groups]
- # expecting node groups to be array of dictionaries
data = {
'name': name,
'plugin_name': plugin_name,
@@ -55,7 +62,8 @@ class ClusterManager(base.ResourceManager):
cluster_configs=cluster_configs,
node_groups=node_groups,
user_keypair_id=user_keypair_id,
- anti_affinity=anti_affinity)
+ anti_affinity=anti_affinity,
+ neutron_management_network=net_id)
return self._create('/clusters', data, 'cluster')
diff --git a/savannaclient/api/data_sources.py b/savannaclient/api/data_sources.py
index d2a35c3..64c309c 100644
--- a/savannaclient/api/data_sources.py
+++ b/savannaclient/api/data_sources.py
@@ -23,23 +23,23 @@ class DataSources(base.Resource):
class DataSourceManager(base.ResourceManager):
resource_class = DataSources
- def list(self):
- return self._list('/data-sources', "data_sources")
-
- def delete(self, data_source_id):
- return self._delete('/data-sources/%s' % data_source_id)
-
- def get(self, data_source_id):
- return self._get('/data-sources/%s' % data_source_id,
- 'resource')
-
- def create(self, name, description, data_source_type, url, credentials):
+ def create(self, name, description, data_source_type,
+ url, credential_user, credential_pass):
data = {
'name': name,
'description': description,
'type': data_source_type,
'url': url,
- 'credentials': credentials
+ 'credentials': {'user': credential_user,
+ 'password': credential_pass}
}
-
return self._create('/data-sources', data, 'data_source')
+
+ def list(self):
+ return self._list('/data-sources', 'data_sources')
+
+ def get(self, data_source_id):
+ return self._get('/data-sources/%s' % data_source_id, 'data_source')
+
+ def delete(self, data_source_id):
+ self._delete('/data-sources/%s' % data_source_id)
diff --git a/savannaclient/api/job_binaries.py b/savannaclient/api/job_binaries.py
index ca44861..673af73 100644
--- a/savannaclient/api/job_binaries.py
+++ b/savannaclient/api/job_binaries.py
@@ -23,18 +23,21 @@ class JobBinaries(base.Resource):
class JobBinariesManager(base.ResourceManager):
resource_class = JobBinaries
- def list(self):
- return self._list('/job-binaries', "binaries")
-
- def delete(self, job_binary_id):
- return self._delete('/job-binaries/%s' % job_binary_id)
-
- def create(self, name, url, description=None):
+ def create(self, name, url, description, extra):
data = {
- 'name': name,
- 'url': url,
+ "name": name,
+ "url": url,
+ "description": description,
+ "extra": extra
}
- self._copy_if_defined(data, description=description)
+ return self._create('/job-binaries', data, 'job_binary')
- return self._create("/job-binaries", data, "job_binary")
+ def list(self):
+ return self._list('/job-binaries', 'binaries')
+
+ def get(self, job_binary_id):
+ return self._get('/job-binaries/%s' % job_binary_id, 'job_binary')
+
+ def delete(self, job_binary_id):
+ self._delete('/job-binaries/%s' % job_binary_id)
diff --git a/savannaclient/api/job_binary_internals.py b/savannaclient/api/job_binary_internals.py
index 1ac3177..2a6248c 100644
--- a/savannaclient/api/job_binary_internals.py
+++ b/savannaclient/api/job_binary_internals.py
@@ -23,18 +23,16 @@ class JobBinaryInternal(base.Resource):
class JobBinaryInternalsManager(base.ResourceManager):
resource_class = JobBinaryInternal
- def list(self):
- return self._list('/job-binary-internals', "binaries")
-
- def delete(self, job_binary_id):
- return self._delete('/job-binary-internals/%s' % job_binary_id)
-
def create(self, name, data):
- url = '/job-binary-internals/%s' % name
- resp = self.api.client.put(url, data)
+ return self._create('/job-binary-internals/%s' % name, data,
+ 'job_binary_internal')
- if resp.status_code != 202:
- self._raise_api_exception(resp)
+ def list(self):
+ return self._list('/job-binary-internals', 'binaries')
+
+ def get(self, job_binary_id):
+ return self._get('/job-binary-internals/%s' % job_binary_id,
+ 'job_binary_internal')
- data = resp.json()["job_binary_internal"]
- return self.resource_class(self, data)
+ def delete(self, job_binary_id):
+ self._delete('/job-binary-internals/%s' % job_binary_id)
diff --git a/savannaclient/api/job_executions.py b/savannaclient/api/job_executions.py
index f09595f..80436e6 100644
--- a/savannaclient/api/job_executions.py
+++ b/savannaclient/api/job_executions.py
@@ -16,30 +16,29 @@
from savannaclient.api import base
-class JobExecutions(base.Resource):
+class JobExecution(base.Resource):
resource_name = 'JobExecution'
class JobExecutionsManager(base.ResourceManager):
- resource_class = JobExecutions
+ resource_class = JobExecution
def list(self):
- return self._list('/job-executions', "job_executions")
+ return self._list('/job-executions', 'job_executions')
- def get(self, job_execution_id):
- return self._get('/job-executions/%s' % job_execution_id)
+ def get(self, obj_id):
+ return self._get('/job-executions/%s' % obj_id, 'job_execution')
- def cancel(self, job_execution_id):
- return self._get('/job-executions/%s/cancel' % job_execution_id)
+ def delete(self, obj_id):
+ self._delete('/job-executions/%s' % obj_id)
- def delete(self, job_execution_id):
- return self._delete('/job-executions/%s' % job_execution_id)
-
- def execute(self, job_id, input_id, output_id, cluster_id):
+ def create(self, job_id, cluster_id, input_id, output_id, configs):
+ url = "/jobs/%s/execute" % job_id
data = {
- 'input_id': input_id,
- 'output_id': output_id,
- 'cluster_id': cluster_id,
+ "input_id": input_id,
+ "output_id": output_id,
+ "cluster_id": cluster_id,
+ "job_configs": configs
}
- return self._create('/jobs/%s/execute' % job_id, data, "job_execution")
+ return self._create(url, data, 'job_execution')
diff --git a/savannaclient/api/job_origins.py b/savannaclient/api/job_origins.py
deleted file mode 100644
index 2c3d546..0000000
--- a/savannaclient/api/job_origins.py
+++ /dev/null
@@ -1,43 +0,0 @@
-# Copyright (c) 2013 Mirantis Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-# implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from savannaclient.api import base
-
-
-class JobOrigins(base.Resource):
- resource_name = 'JobOrigin'
-
-
-class JobOriginsManager(base.ResourceManager):
- resource_class = JobOrigins
-
- def list(self):
- return self._list('/job-origins', "job_origins")
-
- def delete(self, job_origin_id):
- return self._delete('/job-origins/%s' % job_origin_id)
-
- def get(self, job_origin_id):
- return self._get('/job-origins/%s' % job_origin_id)
-
- def create(self, name, description, mains, libs=[]):
- data = {
- 'name': name,
- 'description': description,
- 'mains': mains,
- 'libs': libs,
- }
-
- return self._create('/job-origins', data, "job_origin")
diff --git a/savannaclient/api/jobs.py b/savannaclient/api/jobs.py
index b5e63d0..1b5d8ad 100644
--- a/savannaclient/api/jobs.py
+++ b/savannaclient/api/jobs.py
@@ -16,31 +16,29 @@
from savannaclient.api import base
-class Jobs(base.Resource):
+class Job(base.Resource):
resource_name = 'Job'
class JobsManager(base.ResourceManager):
- resource_class = Jobs
+ resource_class = Job
- def list(self):
- return self._list('/jobs', "jobs")
-
- def delete(self, job_id):
- return self._delete('/jobs/%s' % job_id)
-
- def get(self, job_id):
- return self._get('/jobs/%s' % job_id)
-
- def create(self, name, description, job_origin_id,
- job_type, input_type, output_type):
+ def create(self, name, type, mains, libs, description):
data = {
'name': name,
+ 'type': type,
'description': description,
- 'type': job_type,
- 'job_origin_id': job_origin_id,
- 'input_type': input_type,
- 'output_type': output_type
+ 'mains': mains,
+ 'libs': libs
}
return self._create('/jobs', data, 'job')
+
+ def list(self):
+ return self._list('/jobs', 'jobs')
+
+ def get(self, job_id):
+ return self._get('/jobs/%s' % job_id, 'job')
+
+ def delete(self, job_id):
+ self._delete('/jobs/%s' % job_id)
diff --git a/savannaclient/api/node_group_templates.py b/savannaclient/api/node_group_templates.py
index 2131665..f3c1036 100644
--- a/savannaclient/api/node_group_templates.py
+++ b/savannaclient/api/node_group_templates.py
@@ -27,7 +27,7 @@ class NodeGroupTemplateManager(base.ResourceManager):
def create(self, name, plugin_name, hadoop_version, flavor_id,
description=None, volumes_per_node=None, volumes_size=None,
- node_processes=None, node_configs=None):
+ node_processes=None, node_configs=None, floating_ip_pool=None):
data = {
'name': name,
@@ -35,16 +35,21 @@ class NodeGroupTemplateManager(base.ResourceManager):
'hadoop_version': hadoop_version,
'description': description,
'flavor_id': flavor_id,
- 'node_processes': node_processes,
- 'node_configs': node_configs
+ 'node_processes': node_processes
}
+ if not node_configs:
+ data["node_configs"] = dict()
+
+ if floating_ip_pool:
+ data.update({"floating_ip_pool": floating_ip_pool})
+
if volumes_per_node:
data.update({"volumes_per_node": volumes_per_node,
"volumes_size": volumes_size})
- return self._create(
- '/node-group-templates', data, 'node_group_template')
+ return self._create('/node-group-templates', data,
+ 'node_group_template')
def list(self):
return self._list('/node-group-templates', 'node_group_templates')
diff --git a/savannaclient/api/plugins.py b/savannaclient/api/plugins.py
index b9c93ef..5f27f8d 100644
--- a/savannaclient/api/plugins.py
+++ b/savannaclient/api/plugins.py
@@ -15,6 +15,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+import urllib
+
from savannaclient.api import base
@@ -36,10 +38,15 @@ class PluginManager(base.ResourceManager):
'plugin')
def convert_to_cluster_template(self, plugin_name, hadoop_version,
- filecontent):
- resp = self.api.client.post('/plugins/%s/%s/convert-config' %
- (plugin_name, hadoop_version), filecontent)
+ template_name, filecontent):
+ resp = self.api.client.post('/plugins/%s/%s/convert-config/%s' %
+ (plugin_name,
+ hadoop_version,
+ urllib.quote(template_name)),
+ filecontent)
if resp.status_code != 202:
raise RuntimeError('Failed to upload template file for plugin "%s"'
' and version "%s"' %
(plugin_name, hadoop_version))
+ else:
+ return base.get_json(resp)['cluster_template']
diff --git a/setup.cfg b/setup.cfg
index 06c4dc7..352886a 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,5 +1,6 @@
[metadata]
name = python-savannaclient
+version = 0.3
summary = Client library for Savanna API
description-file =
README.rst
@@ -18,11 +19,10 @@ classifier =
Programming Language :: Python :: 2.7
Programming Language :: Python :: 2.6
-[files]
-packages =
- savannaclient
-
[global]
-setup-hooks =
- pbr.hooks.setup_hook
+setup-hooks = pbr.hooks.setup_hook
+
+
+[files]
+packages = savannaclient
diff --git a/tox.ini b/tox.ini
index 1b2b244..94d4324 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,7 +1,11 @@
[tox]
envlist = py26,py27,pep8
+minversion = 1.6
+skipsdist = True
[testenv]
+usedevelop = True
+install_command = pip install -U {opts} {packages}
sitepackages = True
setenv =
VIRTUAL_ENV={envdir}