Support all metadata api functional
This commit is contained in:
parent
a44cb523b9
commit
e68f0c28e8
0
metadataclient/openstack/__init__.py
Normal file
0
metadataclient/openstack/__init__.py
Normal file
0
metadataclient/openstack/common/__init__.py
Normal file
0
metadataclient/openstack/common/__init__.py
Normal file
50
metadataclient/openstack/common/gettextutils.py
Normal file
50
metadataclient/openstack/common/gettextutils.py
Normal file
@ -0,0 +1,50 @@
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
# Copyright 2012 Red Hat, Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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.
|
||||
|
||||
"""
|
||||
gettext for openstack-common modules.
|
||||
|
||||
Usual usage in an openstack.common module:
|
||||
|
||||
from glanceclient.openstack.common.gettextutils import _
|
||||
"""
|
||||
|
||||
import gettext
|
||||
import os
|
||||
|
||||
_localedir = os.environ.get('glanceclient'.upper() + '_LOCALEDIR')
|
||||
_t = gettext.translation('glanceclient', localedir=_localedir, fallback=True)
|
||||
|
||||
|
||||
def _(msg):
|
||||
return _t.ugettext(msg)
|
||||
|
||||
|
||||
def install(domain):
|
||||
"""Install a _() function using the given translation domain.
|
||||
|
||||
Given a translation domain, install a _() function using gettext's
|
||||
install() function.
|
||||
|
||||
The main difference from gettext.install() is that we allow
|
||||
overriding the default localedir (e.g. /usr/share/locale) using
|
||||
a translation-domain-specific environment variable (e.g.
|
||||
NOVA_LOCALEDIR).
|
||||
"""
|
||||
gettext.install(domain,
|
||||
localedir=os.environ.get(domain.upper() + '_LOCALEDIR'),
|
||||
unicode=True)
|
67
metadataclient/openstack/common/importutils.py
Normal file
67
metadataclient/openstack/common/importutils.py
Normal file
@ -0,0 +1,67 @@
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
# Copyright 2011 OpenStack Foundation.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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.
|
||||
|
||||
"""
|
||||
Import related utilities and helper functions.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import traceback
|
||||
|
||||
|
||||
def import_class(import_str):
|
||||
"""Returns a class from a string including module and class."""
|
||||
mod_str, _sep, class_str = import_str.rpartition('.')
|
||||
try:
|
||||
__import__(mod_str)
|
||||
return getattr(sys.modules[mod_str], class_str)
|
||||
except (ValueError, AttributeError):
|
||||
raise ImportError('Class %s cannot be found (%s)' %
|
||||
(class_str,
|
||||
traceback.format_exception(*sys.exc_info())))
|
||||
|
||||
|
||||
def import_object(import_str, *args, **kwargs):
|
||||
"""Import a class and return an instance of it."""
|
||||
return import_class(import_str)(*args, **kwargs)
|
||||
|
||||
|
||||
def import_object_ns(name_space, import_str, *args, **kwargs):
|
||||
"""
|
||||
Import a class and return an instance of it, first by trying
|
||||
to find the class in a default namespace, then failing back to
|
||||
a full path if not found in the default namespace.
|
||||
"""
|
||||
import_value = "%s.%s" % (name_space, import_str)
|
||||
try:
|
||||
return import_class(import_value)(*args, **kwargs)
|
||||
except ImportError:
|
||||
return import_class(import_str)(*args, **kwargs)
|
||||
|
||||
|
||||
def import_module(import_str):
|
||||
"""Import a module."""
|
||||
__import__(import_str)
|
||||
return sys.modules[import_str]
|
||||
|
||||
|
||||
def try_import(import_str, default=None):
|
||||
"""Try to import a module and if it fails return default."""
|
||||
try:
|
||||
return import_module(import_str)
|
||||
except ImportError:
|
||||
return default
|
150
metadataclient/openstack/common/strutils.py
Normal file
150
metadataclient/openstack/common/strutils.py
Normal file
@ -0,0 +1,150 @@
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
# Copyright 2011 OpenStack Foundation.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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.
|
||||
|
||||
"""
|
||||
System-level utilities and helper functions.
|
||||
"""
|
||||
|
||||
import sys
|
||||
|
||||
from metadataclient.openstack.common.gettextutils import _
|
||||
|
||||
|
||||
TRUE_STRINGS = ('1', 't', 'true', 'on', 'y', 'yes')
|
||||
FALSE_STRINGS = ('0', 'f', 'false', 'off', 'n', 'no')
|
||||
|
||||
|
||||
def int_from_bool_as_string(subject):
|
||||
"""
|
||||
Interpret a string as a boolean and return either 1 or 0.
|
||||
|
||||
Any string value in:
|
||||
|
||||
('True', 'true', 'On', 'on', '1')
|
||||
|
||||
is interpreted as a boolean True.
|
||||
|
||||
Useful for JSON-decoded stuff and config file parsing
|
||||
"""
|
||||
return bool_from_string(subject) and 1 or 0
|
||||
|
||||
|
||||
def bool_from_string(subject, strict=False):
|
||||
"""
|
||||
Interpret a string as a boolean.
|
||||
|
||||
A case-insensitive match is performed such that strings matching 't',
|
||||
'true', 'on', 'y', 'yes', or '1' are considered True and, when
|
||||
`strict=False`, anything else is considered False.
|
||||
|
||||
Useful for JSON-decoded stuff and config file parsing.
|
||||
|
||||
If `strict=True`, unrecognized values, including None, will raise a
|
||||
ValueError which is useful when parsing values passed in from an API call.
|
||||
Strings yielding False are 'f', 'false', 'off', 'n', 'no', or '0'.
|
||||
"""
|
||||
if not isinstance(subject, basestring):
|
||||
subject = str(subject)
|
||||
|
||||
lowered = subject.strip().lower()
|
||||
|
||||
if lowered in TRUE_STRINGS:
|
||||
return True
|
||||
elif lowered in FALSE_STRINGS:
|
||||
return False
|
||||
elif strict:
|
||||
acceptable = ', '.join(
|
||||
"'%s'" % s for s in sorted(TRUE_STRINGS + FALSE_STRINGS))
|
||||
msg = _("Unrecognized value '%(val)s', acceptable values are:"
|
||||
" %(acceptable)s") % {'val': subject,
|
||||
'acceptable': acceptable}
|
||||
raise ValueError(msg)
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
def safe_decode(text, incoming=None, errors='strict'):
|
||||
"""
|
||||
Decodes incoming str using `incoming` if they're
|
||||
not already unicode.
|
||||
|
||||
:param incoming: Text's current encoding
|
||||
:param errors: Errors handling policy. See here for valid
|
||||
values http://docs.python.org/2/library/codecs.html
|
||||
:returns: text or a unicode `incoming` encoded
|
||||
representation of it.
|
||||
:raises TypeError: If text is not an isntance of basestring
|
||||
"""
|
||||
if not isinstance(text, basestring):
|
||||
raise TypeError("%s can't be decoded" % type(text))
|
||||
|
||||
if isinstance(text, unicode):
|
||||
return text
|
||||
|
||||
if not incoming:
|
||||
incoming = (sys.stdin.encoding or
|
||||
sys.getdefaultencoding())
|
||||
|
||||
try:
|
||||
return text.decode(incoming, errors)
|
||||
except UnicodeDecodeError:
|
||||
# Note(flaper87) If we get here, it means that
|
||||
# sys.stdin.encoding / sys.getdefaultencoding
|
||||
# didn't return a suitable encoding to decode
|
||||
# text. This happens mostly when global LANG
|
||||
# var is not set correctly and there's no
|
||||
# default encoding. In this case, most likely
|
||||
# python will use ASCII or ANSI encoders as
|
||||
# default encodings but they won't be capable
|
||||
# of decoding non-ASCII characters.
|
||||
#
|
||||
# Also, UTF-8 is being used since it's an ASCII
|
||||
# extension.
|
||||
return text.decode('utf-8', errors)
|
||||
|
||||
|
||||
def safe_encode(text, incoming=None,
|
||||
encoding='utf-8', errors='strict'):
|
||||
"""
|
||||
Encodes incoming str/unicode using `encoding`. If
|
||||
incoming is not specified, text is expected to
|
||||
be encoded with current python's default encoding.
|
||||
(`sys.getdefaultencoding`)
|
||||
|
||||
:param incoming: Text's current encoding
|
||||
:param encoding: Expected encoding for text (Default UTF-8)
|
||||
:param errors: Errors handling policy. See here for valid
|
||||
values http://docs.python.org/2/library/codecs.html
|
||||
:returns: text or a bytestring `encoding` encoded
|
||||
representation of it.
|
||||
:raises TypeError: If text is not an isntance of basestring
|
||||
"""
|
||||
if not isinstance(text, basestring):
|
||||
raise TypeError("%s can't be encoded" % type(text))
|
||||
|
||||
if not incoming:
|
||||
incoming = (sys.stdin.encoding or
|
||||
sys.getdefaultencoding())
|
||||
|
||||
if isinstance(text, unicode):
|
||||
return text.encode(encoding, errors)
|
||||
elif text and encoding != incoming:
|
||||
# Decode text before encoding it with `encoding`
|
||||
text = safe_decode(text, incoming, errors)
|
||||
return text.encode(encoding, errors)
|
||||
|
||||
return text
|
@ -1,13 +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.
|
@ -1,5 +1,4 @@
|
||||
# Copyright 2012 OpenStack LLC.
|
||||
# All Rights Reserved.
|
||||
# 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
|
||||
@ -13,6 +12,7 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
|
||||
from metadataclient.common import http
|
||||
from metadataclient.v1 import metadata_client
|
||||
from metadataclient.v1 import metadata_admin
|
||||
@ -31,5 +31,6 @@ class Client(http.HTTPClient):
|
||||
def __init__(self, *args, **kwargs):
|
||||
"""Initialize a new client for the Murano Metadata Client v1 API."""
|
||||
super(Client, self).__init__(*args, **kwargs)
|
||||
self.metadata_client = metadata_client.MetadataClientManager(self)
|
||||
# self.metadata_admin = metadata_admin.MetadataAdminManager(self)
|
||||
self.http_client = http.HTTPClient(*args, **kwargs)
|
||||
self.metadata_client = metadata_client.Controller(self)
|
||||
self.metadata_admin = metadata_admin.Controller(self)
|
||||
|
@ -11,48 +11,85 @@
|
||||
# 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 muranoclient.common import base
|
||||
import StringIO
|
||||
|
||||
|
||||
class MetadataAdmin(base.Resource):
|
||||
def __repr__(self):
|
||||
return "<Metadata Client %s>" % self._info
|
||||
|
||||
|
||||
class MetadataAdminManager(base.Manager):
|
||||
resource_class = MetadataAdmin
|
||||
class Controller(object):
|
||||
def __init__(self, http_client):
|
||||
self.http_client = http_client
|
||||
|
||||
def list_ui(self, path=None):
|
||||
if path:
|
||||
return self._list('/v1/admin/ui/{path}'.format(path=path))
|
||||
url = '/v1/admin/ui/{path}'.format(path=path)
|
||||
else:
|
||||
return self._list('/v1/admin/ui')
|
||||
url = '/v1/admin/ui'
|
||||
resp, body = self.http_client.json_request('GET', url)
|
||||
return body
|
||||
|
||||
def list_agent(self, path=None):
|
||||
if path:
|
||||
return self._list('/v1/admin/agent/{path}'.format(path=path))
|
||||
url = '/v1/admin/agent/{path}'.format(path=path)
|
||||
else:
|
||||
return self._list('/v1/admin/agent')
|
||||
|
||||
def list_heat(self, path=None):
|
||||
if path:
|
||||
return self._list('/v1/admin/heat/{path}'.format(path=path))
|
||||
else:
|
||||
return self._list('/v1/admin/heat')
|
||||
|
||||
def list_workflows(self, path=None):
|
||||
if path:
|
||||
return self._list('/v1/admin/workflows/{path}'.format(path=path))
|
||||
else:
|
||||
return self._list('/v1/admin/workflows')
|
||||
url = '/v1/admin/agent'
|
||||
resp, body = self.http_client.json_request('GET', url)
|
||||
return body
|
||||
|
||||
def list_scripts(self, path=None):
|
||||
if path:
|
||||
return self._list('/v1/admin/scripts/{path}'.format(path=path))
|
||||
url = '/v1/admin/scripts/{path}'.format(path=path)
|
||||
else:
|
||||
return self._list('/v1/admin/scripts')
|
||||
url = '/v1/admin/scripts'
|
||||
resp, body = self.http_client.json_request('GET', url)
|
||||
return body
|
||||
|
||||
def get_file(self):
|
||||
#application/octet
|
||||
pass
|
||||
def list_workflows(self, path=None):
|
||||
if path:
|
||||
url = '/v1/admin/workflows/{path}'.format(path=path)
|
||||
else:
|
||||
url = '/v1/admin/workflows'
|
||||
resp, body = self.http_client.json_request('GET', url)
|
||||
return body
|
||||
|
||||
def list_heat(self, path=None):
|
||||
if path:
|
||||
url = '/v1/admin/heat/{path}'.format(path=path)
|
||||
else:
|
||||
url = '/v1/admin/heat'
|
||||
resp, body = self.http_client.json_request('GET', url)
|
||||
return body
|
||||
|
||||
def list_manifests(self, path=None):
|
||||
if path:
|
||||
url = '/v1/admin/manifests/{path}'.format(path=path)
|
||||
else:
|
||||
url = '/v1/admin/manifests'
|
||||
resp, body = self.http_client.json_request('GET', url)
|
||||
return body
|
||||
|
||||
def upload_file(self, data_type, file_data):
|
||||
url = '/v1/admin/{0}'.format(data_type)
|
||||
hdrs = {'Content-Type': 'application/octet-stream'}
|
||||
self.http_client.raw_request('POST', url,
|
||||
headers=hdrs,
|
||||
body=file_data)
|
||||
|
||||
def upload_file_to_dir(self, data_type, path, file_data):
|
||||
url = '/v1/admin/{0}/{1}'.format(data_type, path)
|
||||
hdrs = {'Content-Type': 'application/octet-stream'}
|
||||
self.http_client.raw_request('POST', url,
|
||||
headers=hdrs,
|
||||
body=file_data)
|
||||
|
||||
def get_file(self, data_type, file_path):
|
||||
url = '/v1/admin/{0}/{1}'.format(data_type, file_path)
|
||||
resp, body = self.http_client.raw_request('GET', url)
|
||||
body_str = ''.join([chunk for chunk in body])
|
||||
return StringIO.StringIO(body_str)
|
||||
|
||||
def create_directory(self, data_type, dir_name):
|
||||
url = '/v1/admin/{0}/{1}'.format(data_type, dir_name)
|
||||
self.http_client.json_request('PUT', url)
|
||||
|
||||
def delete_dir(self, data_type, path):
|
||||
url = '/v1/admin/{0}/{1}'.format(data_type, path)
|
||||
self.http_client.json_request('DELETE', url)
|
@ -15,16 +15,38 @@
|
||||
from muranoclient.common import base
|
||||
|
||||
|
||||
class MetadataClient(base.Resource):
|
||||
def __repr__(self):
|
||||
return "<Metadata Client %s>" % self._info
|
||||
# class MetadataClient(base.Resource):
|
||||
# def __repr__(self):
|
||||
# return "<Metadata Client %s>" % self._info
|
||||
#
|
||||
#
|
||||
# class MetadataClientManager(base.Manager):
|
||||
# resource_class = MetadataClient
|
||||
#
|
||||
# def get_ui_archive(self):
|
||||
# return self._get('/v1/client/ui')
|
||||
#
|
||||
# def conductor(self):
|
||||
# return self._get('/v1/client/conductor')
|
||||
|
||||
class Controller(object):
|
||||
def __init__(self, http_client):
|
||||
self.http_client = http_client
|
||||
|
||||
class MetadataClientManager(base.Manager):
|
||||
resource_class = MetadataClient
|
||||
def get_ui_data(self):
|
||||
"""
|
||||
Download tar.gz with
|
||||
|
||||
def get_ui_archive(self):
|
||||
return self._get('/v1/client/ui')
|
||||
"""
|
||||
url = '/v1/client/ui'
|
||||
resp, body = self.http_client.archive_request('GET', url)
|
||||
return body
|
||||
|
||||
def conductor(self):
|
||||
return self._get('/v1/client/conductor')
|
||||
def get_conductor_data(self):
|
||||
"""
|
||||
Download tar.gz with
|
||||
|
||||
"""
|
||||
url = '/v1/client/conductor'
|
||||
resp, body = self.http_client.archive_request('GET', url)
|
||||
return body
|
Loading…
x
Reference in New Issue
Block a user