Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 49 additions & 22 deletions blazarclient/command.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
HEX_ELEM + '{4}', HEX_ELEM + '{4}',
HEX_ELEM + '{12}'])

import logging
LOG = logging.getLogger(__name__)

class OpenStackCommand(command.Command):
"""Base class for OpenStack commands."""
Expand Down Expand Up @@ -88,6 +90,31 @@ def get_client(self):
else:
return self.app.client

def get_manager_and_args(
self, parsed_args, args, add_to_body=False, blazar_client=None
):
if not blazar_client:
blazar_client = self.get_client()

if hasattr(parsed_args, "resource"): # Passed in via --resource flag
if hasattr(blazar_client, parsed_args.resource): # A built-in type
resource_manager = getattr(blazar_client, parsed_args.resource)
if add_to_body:
args["resource_type"] = parsed_args.resource
else:
args.insert(0, parsed_args.resource)
else: # A built-in resource type
resource_manager = blazar_client.resource
if add_to_body:
args["resource_type"] = self.resource
else:
args.insert(0, parsed_args.resource)
else: # Else, no --resource, normal usage
resource_manager = getattr(blazar_client, self.resource)
# Update resource type depending on calling method
return resource_manager, args


def get_parser(self, prog_name):
parser = super(BlazarCommand, self).get_parser(prog_name)
return parser
Expand Down Expand Up @@ -135,7 +162,7 @@ def get_data(self, parsed_args):
self.log.debug('get_data(%s)' % parsed_args)
blazar_client = self.get_client()
body = self.args2body(parsed_args)
resource_manager = getattr(blazar_client, self.resource)
resource_manager, body = self.get_manager_and_args(parsed_args, body, add_to_body=True, blazar_client=blazar_client)
data = resource_manager.create(**body)
self.format_output_data(data)

Expand Down Expand Up @@ -178,8 +205,8 @@ def run(self, parsed_args):
self.id_pattern)
else:
res_id = parsed_args.id
resource_manager = getattr(blazar_client, self.resource)
resource_manager.update(res_id, **body)
resource_manager, args = self.get_manager_and_args(parsed_args, [res_id], add_to_body=False, blazar_client=blazar_client)
resource_manager.update(*args, **body)
print('Updated %s: %s' % (self.resource, parsed_args.id),
file=self.app.stdout)
return
Expand All @@ -189,7 +216,7 @@ class DeleteCommand(BlazarCommand):
"""Delete a given resource."""

api = 'reservation'
resource = None
resource = "resource"
log = None

def get_parser(self, prog_name):
Expand All @@ -206,7 +233,6 @@ def get_parser(self, prog_name):
def run(self, parsed_args):
self.log.debug('run(%s)' % parsed_args)
blazar_client = self.get_client()
resource_manager = getattr(blazar_client, self.resource)
if self.allow_names:
res_id = utils.find_resource_id_by_name_or_id(blazar_client,
self.resource,
Expand All @@ -215,7 +241,8 @@ def run(self, parsed_args):
self.id_pattern)
else:
res_id = parsed_args.id
resource_manager.delete(res_id)
resource_manager, args = self.get_manager_and_args(parsed_args, [res_id], add_to_body=False, blazar_client=blazar_client)
resource_manager.delete(*args)
print('Deleted %s: %s' % (self.resource, parsed_args.id),
file=self.app.stdout)
return
Expand All @@ -231,6 +258,8 @@ class ListCommand(BlazarCommand, lister.Lister):
list_columns = []
unknown_parts_flag = True

list_fn_name = "list"

def args2body(self, parsed_args):
params = {}
if parsed_args.sort_by:
Expand All @@ -249,8 +278,8 @@ def retrieve_list(self, parsed_args):
"""Retrieve a list of resources from Blazar server."""
blazar_client = self.get_client()
body = self.args2body(parsed_args)
resource_manager = getattr(blazar_client, self.resource)
data = resource_manager.list(**body)
resource_manager, body = self.get_manager_and_args(parsed_args, body, add_to_body=True, blazar_client=blazar_client)
data = getattr(resource_manager, self.list_fn_name)(**body)
return data

def setup_columns(self, info, parsed_args):
Expand Down Expand Up @@ -292,7 +321,7 @@ def retrieve_list(self, parsed_args):
"""Retrieve a list of resources from Blazar server."""
blazar_client = self.get_client()
body = self.args2body(parsed_args)
resource_manager = getattr(blazar_client, self.resource)
resource_manager, body = self.get_manager_and_args(parsed_args, body, add_to_body=True, blazar_client=blazar_client)
data = resource_manager.list_allocations(**body)
return data

Expand All @@ -317,18 +346,15 @@ def get_parser(self, prog_name):
def get_data(self, parsed_args):
self.log.debug('get_data(%s)' % parsed_args)
blazar_client = self.get_client()

res_id = parsed_args.id
if self.allow_names:
res_id = utils.find_resource_id_by_name_or_id(blazar_client,
self.resource,
parsed_args.id,
self.name_key,
self.id_pattern)
else:
res_id = parsed_args.id

resource_manager = getattr(blazar_client, self.resource)
data = resource_manager.get(res_id)
resource_manager, args = self.get_manager_and_args(parsed_args, [res_id], add_to_body=False, blazar_client=blazar_client)
data = resource_manager.get(*args)
self.format_output_data(data)
return list(zip(*sorted(data.items())))

Expand All @@ -339,8 +365,8 @@ class ShowAllocationCommand(ShowCommand, show.ShowOne):
def get_data(self, parsed_args):
self.log.debug('get_data(%s)' % parsed_args)
blazar_client = self.get_client()
resource_manager = getattr(blazar_client, self.resource)
data = resource_manager.get_allocation(parsed_args.id)
resource_manager, args = self.get_manager_and_args(parsed_args, [parsed_args.id], add_to_body=False, blazar_client=blazar_client)
data = resource_manager.get_allocation(*args)
self.format_output_data(data)
return list(zip(*sorted(data.items())))

Expand Down Expand Up @@ -377,8 +403,8 @@ def run(self, parsed_args):
self.id_pattern)
else:
res_id = parsed_args.id
resource_manager = getattr(blazar_client, self.resource)
resource_manager.reallocate(res_id, body)
resource_manager, args = self.get_manager_and_args(parsed_args, [res_id, body], add_to_body=False, blazar_client=blazar_client)
resource_manager.reallocate(*args)
print('Reallocated %s: %s' % (self.resource, parsed_args.id),
file=self.app.stdout)
return
Expand All @@ -400,8 +426,9 @@ def get_parser(self, prog_name):
def get_data(self, parsed_args):
self.log.debug('get_data(%s)' % parsed_args)
blazar_client = self.get_client()
resource_manager = getattr(blazar_client, self.resource)
data = resource_manager.get_capability(parsed_args.capability_name)
resource_manager, args = self.get_manager_and_args(parsed_args, [parsed_args.capability_name], add_to_body=False, blazar_client=blazar_client)
LOG.info(args)
data = resource_manager.get_capability(*args)
self.format_output_data(data)
return list(zip(*sorted(data.items())))

Expand All @@ -415,7 +442,7 @@ def run(self, parsed_args):
self.log.debug('run(%s)' % parsed_args)
blazar_client = self.get_client()
body = self.args2body(parsed_args)
resource_manager = getattr(blazar_client, self.resource)
resource_manager, body = self.get_manager_and_args(parsed_args, body, add_to_body=True, blazar_client=blazar_client)
resource_manager.set_capability(**body)
print(
'Updated %s extra capability: %s' % (
Expand Down
8 changes: 6 additions & 2 deletions blazarclient/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,12 @@ def find_resource_id_by_name_or_id(client, resource_type, name_or_id,


def _find_resource_id_by_name(client, resource_type, name, name_key):
resource_manager = getattr(client, resource_type)
resources = resource_manager.list()
if hasattr(client, resource_type):
resource_manager = getattr(client, resource_type)
resources = resource_manager.list()
else: # If third party resource
resource_manager = client.resource
resources = resource_manager.list(resource_type)

named_resources = []
key = name_key if name_key else 'name'
Expand Down
7 changes: 7 additions & 0 deletions blazarclient/v1/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
from blazarclient.v1 import hosts
from blazarclient.v1 import leases
from blazarclient.v1 import networks
from blazarclient.v1 import resources


class Client(object):
Expand Down Expand Up @@ -76,3 +77,9 @@ def __init__(self, blazar_url=None, auth_token=None, session=None,
session=self.session,
version=self.version,
**kwargs)
self.resource = resources.ResourceClientManager(
blazar_url=self.blazar_url,
auth_token=self.auth_token,
session=self.session,
version=self.version,
**kwargs)
2 changes: 1 addition & 1 deletion blazarclient/v1/hosts.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ def update(self, host_id, values):

def delete(self, host_id):
"""Delete host with specified ID."""
resp, body = self.request_manager.delete('/os-hosts/%s' % host_id)
self.request_manager.delete('/os-hosts/%s' % host_id)

def list(self, sort_by=None):
"""List all hosts."""
Expand Down
109 changes: 109 additions & 0 deletions blazarclient/v1/resources.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
# Copyright (c) 2019 StackHPC Ltd.
#
# 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 blazarclient import base
from blazarclient.i18n import _

import logging
LOG = logging.getLogger(__name__)

class ResourceClientManager(base.BaseClientManager):

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Most of the dict lookups in this class assume that the server will also have plugins installed. Is this assumption safe to make?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is fine, as blazar already assumes you have oshosts/network/fip running. There is a /resources endpoint in 3rd party plugins patch which shows enabled resources we could check, but that would require an extra API call for each command.

def list_resources(self, sort_by=None):
resp, body = self.request_manager.get('/resources')
if sort_by:
body = sorted(body, key=lambda l: l[sort_by])
return body

def create(self, resource_type, data, **kwargs):
values = {'data': data}
values.update(**kwargs)
resp, body = self.request_manager.post(f'/{resource_type}', body=values)
return body['resource']

def get(self, resource_type, resource_id):
resp, body = self.request_manager.get(
f'/{resource_type}/{resource_id}')
return body['resource']

def update(self, resource_type, res_id, data, extras):
if not data and not extras:
return _('No information to update passed.')
body = {"data": data, "extras": extras}
resp, body = self.request_manager.put(
f'/{resource_type}/{res_id}', body=body
)
return body['resource']

def delete(self, resource_type, resource_id):
resp, body = self.request_manager.delete(

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These variables are unused

f'/{resource_type}/{resource_id}')

def list(self, resource_type, sort_by=None):
resp, body = self.request_manager.get(f'/{resource_type}')
resources = body['resources']
if sort_by:
resources = sorted(resources, key=lambda l: l[sort_by])
return resources

def get_allocation(self, resource_type, resource_id):
resp, body = self.request_manager.get(
f'/{resource_type}/{resource_id}/allocation')
return body['allocation']

def list_allocations(self, resource_type, sort_by=None):
resp, body = self.request_manager.get(f'/{resource_type}/allocations')
allocations = body['allocations']
if sort_by:
allocations = sorted(allocations, key=lambda l: l[sort_by])
return allocations

def reallocate(self, resource_type, resource_id, values):
resp, body = self.request_manager.put(
f'/{resource_type}/{resource_id}/allocation', body=values)
return body['allocation']

def list_capabilities(self, resource_type, detail=False, sort_by=None):
url = f'/{resource_type}/properties'

if detail:
url += '?detail=True'

resp, body = self.request_manager.get(url)
resource_properties = body['resource_properties']

# Values is a reserved word in cliff so need to rename values column.
if detail:
for p in resource_properties:
p['capability_values'] = p['values']
del p['values']

if sort_by:
resource_properties = sorted(resource_properties,
key=lambda l: l[sort_by])
return resource_properties

def get_capability(self, resource_type, capability_name):
resource_property = [
x for x in self.list_capabilities(resource_type, detail=True)
if x['property'] == capability_name]

return {} if not resource_property else resource_property[0]

def set_capability(self, resource_type, capability_name, private):
data = {'private': private}
resp, body = self.request_manager.patch(
f'/{resource_type}/properties/{capability_name}', body=data)

return body['resource_property']
7 changes: 6 additions & 1 deletion blazarclient/v1/shell_commands/leases.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,10 @@
"resource_type": 'device'
},
"others": {
".*": None
"min": "",
"max": "",
"resource_properties": {},
"resource_type": "",
}
}

Expand Down Expand Up @@ -280,6 +283,8 @@ def _parse_params(self, str_params, default, err_msg):
prog = re.compile('^(?:(.*),)?(%s)=(.*)$'
% "|".join(default.keys()))

self.log.info("%s", str_params)
self.log.info("%s", default)
while str_params != "":
match = prog.search(str_params)

Expand Down
Loading