Commit e51c7d5b authored by Stavros Sachtouris's avatar Stavros Sachtouris
Browse files

Complete basic compute v2 implementation

Refs: #4139

Pending: adjust unitests, test against an openstack deployment
parent ef2e6c9f
......@@ -301,13 +301,16 @@ class ComputeClient(ComputeRestClient):
r = self.servers_delete(server_id, key)
return r.headers
def list_flavors(self, detail=False):
def list_flavors(self, detail=False, response_headers=dict(
previous=None, next=None)):
"""
:param detail: (bool) detailed flavor info if set, short if not
:returns: (list) flavor info
"""
r = self.flavors_get(command='detail' if detail else '')
r = self.flavors_get(detail=bool(detail))
for k, v in response_headers.items():
response_headers[k] = r.headers.get(k, v)
return r.json['flavors']
def get_flavor_details(self, flavor_id):
......@@ -319,14 +322,16 @@ class ComputeClient(ComputeRestClient):
r = self.flavors_get(flavor_id)
return r.json['flavor']
def list_images(self, detail=False):
def list_images(self, detail=False, response_headers=dict(
next=None, previous=None)):
"""
:param detail: (bool) detailed info if set, short if not
:returns: dict id,name + full info if detail
"""
detail = 'detail' if detail else ''
r = self.images_get(command=detail)
r = self.images_get(detail=bool(detail))
for k, v in response_headers.items():
response_headers[k] = r.headers.get(k, v)
return r.json['images']
def get_image_details(self, image_id, **kwargs):
......@@ -351,7 +356,8 @@ class ComputeClient(ComputeRestClient):
r = self.images_delete(image_id)
return r.headers
def get_image_metadata(self, image_id, key=''):
def get_image_metadata(self, image_id, key='', response_headers=dict(
previous=None, next=None)):
"""
:param image_id: (str)
......@@ -359,8 +365,9 @@ class ComputeClient(ComputeRestClient):
:returns (dict) metadata if key not set, specific metadatum otherwise
"""
command = path4url('metadata', key)
r = self.images_get(image_id, command)
r = self.images_metadata_get(image_id, key)
for k, v in response_headers.items():
response_headers[k] = r.headers.get(k, v)
return r.json['meta' if key else 'metadata']
def create_image_metadata(self, image_id, key, val):
......@@ -377,7 +384,9 @@ class ComputeClient(ComputeRestClient):
r = self.images_put(image_id, 'metadata/' + key, json_data=req)
return r.json['meta']
def update_image_metadata(self, image_id, **metadata):
def update_image_metadata(
self, image_id,
response_headers=dict(previous=None, next=None), **metadata):
"""
:param image_id: (str)
......@@ -386,7 +395,9 @@ class ComputeClient(ComputeRestClient):
:returns: updated metadata
"""
req = {'metadata': metadata}
r = self.images_post(image_id, 'metadata', json_data=req)
r = self.images_metadata_post(image_id, json_data=req)
for k, v in response_headers.items():
response_headers[k] = r.headers.get(k, v)
return r.json['metadata']
def delete_image_metadata(self, image_id, key):
......
......@@ -101,7 +101,7 @@ class ComputeRestClient(Client):
self.set_param('status', status, iff=status)
self.set_param('host', host, iff=host)
path = path4url('servers', 'detail' if detail else server_id)
path = path4url('servers', 'detail' if detail else (server_id or ''))
return self.get(path, success=success, **kwargs)
def servers_post(
......@@ -263,163 +263,161 @@ class ComputeRestClient(Client):
path = path4url('servers', server_id, 'action')
return self.post(path, data=json_data, success=success, **kwargs)
"""
def servers_actions_post
def servers_ips_get
def servers_get(self, server_id='', command='', success=200, **kwargs):
""GET base_url/servers[/server_id][/command] request
:param server_id: integer (as int or str)
:param command: 'ips', 'stats', or ''
def servers_ips_get(
self, server_id,
network_id=None, changes_since=None, success=(304, 200),
**kwargs):
"""GET base_url/servers/<server_id>/ips[/network_id]
:param success: success code or list or tupple of accepted success
codes. if server response code is not in this list, a ClientError
raises
:param changes_since: time/date stamp in UNIX/epoch time. Checks for
changes since a previous request.
:returns: request response
""
path = path4url('servers', server_id, command)
"""
self.set_param('changes-since', changes_since, iff=changes_since)
path = path4url('servers', server_id, 'ips', network_id or '')
return self.get(path, success=success, **kwargs)
def servers_post(
def images_get(
self,
server_id='',
command='',
json_data=None,
success=202,
image_id='',
detail=False,
changes_since=None,
server_name=None,
name=None,
status=None,
marker=None,
limit=None,
type=None,
success=200,
**kwargs):
""POST base_url/servers[/server_id]/[command] request
:param server_id: integer (as int or str)
"""GET base_url[/image_id][/command]
:param command: 'ips', 'stats', or ''
:param image_id: (str) ignored if detail
:param json_data: a json-formated dict that will be send as data
:param detail: (bool)
:param success: success code or list or tupple of accepted success
codes. if server response code is not in this list, a ClientError
raises
--- Parameters ---
:param changes_since: when the image last changed status
:returns: request response
""
data = json_data
if json_data:
data = json.dumps(json_data)
self.set_header('Content-Type', 'application/json')
self.set_header('Content-Length', len(data))
:param server_name: Name of the server in URL format
path = path4url('servers', server_id, command)
return self.post(path, data=data, success=success, **kwargs)
"""
:param name: Name of the image
def flavors_get(self, flavor_id='', command='', success=200, **kwargs):
"""GET base_url[/flavor_id][/command]
:param status: Status of the image (e.g. filter on "ACTIVE")
:param flavor_id: integer (str or int)
:param marker: UUID of the image at which you want to set a marker
:param command: flavor service command
:param limit: Integer value for the limit of values to return
:param success: success code or list or tupple of accepted success
codes. if server response code is not in this list, a ClientError
raises
:param type: Type of image (e.g. BASE, SERVER, or ALL)
:returns: request response
"""
path = path4url('flavors', flavor_id, command)
return self.get(path, success=success, **kwargs)
if not image_id:
self.set_param('changes-since', changes_since, iff=changes_since)
self.set_param('name', name, iff=name)
self.set_param('status', status, iff=status)
self.set_param('marker', marker, iff=marker)
self.set_param('limit', limit, iff=limit)
self.set_param('type', type, iff=type)
self.set_param('server', server_name, iff=server_name)
def images_get(self, image_id='', command='', success=200, **kwargs):
"""GET base_url[/image_id][/command]
path = path4url('images', 'detail' if detail else (image_id or ''))
return self.get(path, success=success, **kwargs)
:param image_id: string
def images_delete(self, image_id='', success=204, **kwargs):
"""DEL ETE base_url/images/<image_id>
:param command: image server command
:returns: request response
"""
path = path4url('images', image_id)
return self.delete(path, success=success, **kwargs)
:param success: success code or list or tupple of accepted success
codes. if server response code is not in this list, a ClientError
raises
def images_metadata_get(self, image_id, key=None, success=200, **kwargs):
"""GET base_url/<image_id>/metadata[/key]
:returns: request response
"""
path = path4url('images', image_id, command)
path = path4url('images', image_id, 'metadata', key or '')
return self.get(path, success=success, **kwargs)
def images_delete(self, image_id='', command='', success=204, **kwargs):
"""DELETE base_url[/image_id][/command]
:param image_id: string
:param command: image server command
:param success: success code or list or tuple of accepted success
codes. if server response code is not in this list, a ClientError
raises
def images_metadata_post(
self, image_id, json_data=None, success=201, **kwargs):
"""POST base_url/images/<image_id>/metadata
:returns: request response
"""
path = path4url('images', image_id, command)
return self.delete(path, success=success, **kwargs)
def images_post(
self,
image_id='',
command='',
json_data=None,
success=201,
**kwargs):
"""POST base_url/images[/image_id]/[command] request
:param image_id: string
:param command: image server command
if json_data is not None:
json_data = json.dumps(json_data)
self.set_header('Content-Type', 'application/json')
self.set_header('Content-Length', len(json_data))
:param json_data: (dict) will be send as data
path = path4url('images', image_id, 'metadata')
return self.post(path, data=json_data, success=success, **kwargs)
:param success: success code or list or tuple of accepted success
codes. if server response code is not in this list, a ClientError
raises
def images_metadata_put(
self, image_id, key=None, json_data=None, success=201, **kwargs):
"""PUT base_url/images/<image_id>/metadata
:returns: request response
"""
data = json_data
if json_data is not None:
data = json.dumps(json_data)
json_data = json.dumps(json_data)
self.set_header('Content-Type', 'application/json')
self.set_header('Content-Length', len(data))
self.set_header('Content-Length', len(json_data))
path = path4url('images', image_id, 'metadata')
return self.put(path, data=json_data, success=success, **kwargs)
path = path4url('images', image_id, command)
return self.post(path, data=data, success=success, **kwargs)
def images_metadata_delete(self, image_id, key, success=204, **kwargs):
"""DEL ETE base_url/images/<image_id>/metadata/key
def images_put(
:returns: request response
"""
path = path4url('images', image_id, 'metadata', key)
return self.put(path, success=success, **kwargs)
def flavors_get(
self,
image_id='',
command='',
json_data=None,
success=201,
flavor_id='',
detail=False,
changes_since=None,
minDisk=None,
minRam=None,
marker=None,
limit=None,
success=200,
**kwargs):
"""PUT base_url/images[/image_id]/[command] request
"""GET base_url[/flavor_id][/command]
:param image_id: string
:param flavor_id: ignored if detail
:param command: image server command
:param detail: (bool)
:param json_data: (dict) will be send as data
--- Parameters ---
:param success: success code or list or tuple of accepted success
codes. if server response code is not in this list, a ClientError
raises
:param changes_since: when the flavor last changed
:param minDisk: minimum disk space in GB filter
:param minRam: minimum RAM filter
:param marker: UUID of the flavor at which to set a marker
:param limit: limit the number of returned values
:returns: request response
"""
data = json_data
if json_data is not None:
data = json.dumps(json_data)
self.set_header('Content-Type', 'application/json')
self.set_header('Content-Length', len(data))
if not flavor_id:
self.set_param('changes-since', changes_since, iff=changes_since)
self.set_param('minDisk', minDisk, iff=minDisk)
self.set_param('minRam', minRam, iff=minRam)
self.set_param('marker', marker, iff=marker)
self.set_param('limit', limit, iff=limit)
path = path4url('images', image_id, command)
return self.put(path, data=data, success=success, **kwargs)
path = path4url('flavors', 'detail' if detail else (flavor_id or ''))
return self.get(path, success=success, **kwargs)
def floating_ip_pools_get(self, tenant_id, success=200, **kwargs):
path = path4url(tenant_id, 'os-floating-ip-pools')
......
......@@ -151,9 +151,8 @@ class CycladesClient(CycladesRestClient):
:returns: (dict) network interface connections
"""
r = self.servers_get(server_id, 'ips')
r = self.servers_ips_get(server_id)
return r.json['attachments']
#return r.json['addresses']
def get_server_stats(self, server_id):
"""
......@@ -161,7 +160,7 @@ class CycladesClient(CycladesRestClient):
:returns: (dict) auto-generated graphs of statistics (urls)
"""
r = self.servers_get(server_id, 'stats')
r = self.servers_stats_get(server_id)
return r.json['stats']
def list_networks(self, detail=False):
......
......@@ -39,6 +39,11 @@ import json
class CycladesRestClient(ComputeClient):
"""Synnefo Cyclades REST API Client"""
def servers_stats_get(self, server_id, success=200, **kwargs):
"""GET base_url/servers/<server_id>/stats"""
path = path4url('servers', server_id, 'stats')
return self.get(path, success=success, **kwargs)
def networks_get(
self,
network_id='',
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment