Create independent sm-api client

1. use sm-api.conf for sm-api configuration
2. create sm-api client code and command line entry
3. add keystone authentication for accessing sm-api
4. removed dead sm-api client code

Story: 2002827
Task: 22744

Depends-On: I743f6b0f09c06325d3c9dc6e11902420882e7931
Change-Id: I861a6fa144494e135f6eb67d96e874d25f4db5d4
Signed-off-by: Bin Qian <bin.qian@windriver.com>
This commit is contained in:
Bin Qian 2018-06-29 14:09:55 -04:00
parent e7d2713327
commit 045a37c672
40 changed files with 546 additions and 751 deletions

View File

@ -1,4 +1,4 @@
SRC_DIR=sm-api
TAR_NAME=sm-api
VERSION=1.0
TIS_PATCH_VER=2
TIS_PATCH_VER=4

View File

@ -36,11 +36,13 @@ Requires: cgts-mtce-common-pmon
install -d %{buildroot}/etc/sm
install -d %{buildroot}/etc/init.d
install -d %{buildroot}/etc/pmon.d
install -d %{buildroot}/etc/sm-api
install -d %{buildroot}%{_unitdir}
install -m 644 %{_buildsubdir}/scripts/sm_api.ini %{buildroot}/etc/sm
install -m 755 %{_buildsubdir}/scripts/sm-api %{buildroot}/etc/init.d
install -m 644 %{_buildsubdir}/scripts/sm-api.service %{buildroot}%{_unitdir}
install -m 644 %{_buildsubdir}/scripts/sm-api.conf %{buildroot}/etc/pmon.d
install -m 644 %{_buildsubdir}/etc/sm-api/policy.json %{buildroot}/etc/sm-api
%description
Service Management API
@ -72,6 +74,7 @@ Service Management API
%dir "/etc/sm"
"/etc/init.d/sm-api"
"/etc/pmon.d/sm-api.conf"
"/etc/sm-api/policy.json"
"/etc/sm/sm_api.ini"
%{_unitdir}/*

View File

@ -0,0 +1,5 @@
{
"admin": "role:admin or role:administrator",
"admin_api": "is_admin:True",
"default": "rule:admin_api"
}

View File

@ -1,6 +1,6 @@
#! /bin/sh
#
# Copyright (c) 2014 Wind River Systems, Inc.
# Copyright (c) 2014-2018 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
@ -32,6 +32,7 @@ LSB_NOT_RUNNING=7
SM_API_NAME="sm-api"
SM_API="/usr/bin/${SM_API_NAME}"
SM_API_CONFIG_FILE="/etc/sm-api/sm-api.conf"
daemon_pidfile="/var/run/${SM_API_NAME}.pid"
@ -51,7 +52,7 @@ case "$1" in
echo -n "is already running "
RETVAL=0
else
/bin/sh -c "${SM_API} --debug --verbose --use-syslog --syslog-log-facility local1"' >> /dev/null 2>&1 & echo $!' > ${daemon_pidfile}
/bin/sh -c "${SM_API} --config-file=${SM_API_CONFIG_FILE} --verbose --use-syslog --syslog-log-facility local1"' >> /dev/null 2>&1 & echo $!' > ${daemon_pidfile}
RETVAL=$?
fi
if [ ${RETVAL} -eq 0 ] ; then

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2014 Wind River Systems, Inc.
# Copyright (c) 2014-2018 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
@ -11,16 +11,16 @@ Application
from oslo_config import cfg
import pecan
from sm_api.api import acl
from sm_api.api import config
from sm_api.api import hooks
from sm_api.api import acl
from sm_api.api import middleware
from sm_api.common import policy
auth_opts = [
cfg.StrOpt('auth_strategy',
default='noauth',
default='keystone',
help='Method to use for auth: noauth or keystone.'),
]
@ -52,6 +52,8 @@ def create_app():
def setup_app(pecan_config=None, extra_hooks=None):
policy.init()
app_hooks = [hooks.ConfigHook(),
hooks.DatabaseHook(),
hooks.ContextHook(pecan_config.app.acl_public_routes),

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2014 Wind River Systems, Inc.
# Copyright (c) 2014-2018 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
@ -12,6 +12,6 @@ app = {'root': 'sm_api.api.controllers.root.RootController',
'modules': ['sm_api'],
'static_root': '',
'debug': False,
'enable_acl': False,
'enable_acl': True,
'acl_public_routes': ['/', '/v1']
}

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2014 Wind River Systems, Inc.
# Copyright (c) 2014-2018 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
@ -28,14 +28,20 @@ class Version1(wsme_types.Base):
links = [link.Link]
"Links that point to a specific URL for this version and documentation"
service_group = [link.Link]
nodes = [link.Link]
"Links to the SM node resource"
service_groups = [link.Link]
"Links to the SM service-group resource"
services = [link.Link]
"Links to the SM service resource"
servicenode = [link.Link]
"Links to the SM service node resource"
"Links to the SM node operation resource"
sm_sda = [link.Link]
"Links to the SM service domain assignments resource "
"Links to the SM service domain assignement resource"
@classmethod
def convert(cls):
@ -43,6 +49,14 @@ class Version1(wsme_types.Base):
v1.id = "v1"
v1.links = [link.Link.make_link('self', pecan.request.host_url,
'v1', '', bookmark=True)]
v1.nodes = [link.Link.make_link('self',
pecan.request.host_url,
'nodes', ''),
link.Link.make_link('bookmark',
pecan.request.host_url,
'nodes', '',
bookmark=True)]
v1.service_groups = [link.Link.make_link('self',
pecan.request.host_url,
'service_groups', ''),
@ -65,7 +79,6 @@ class Version1(wsme_types.Base):
pecan.request.host_url,
'servicenode', '',
bookmark=True)]
v1.sm_sda = [link.Link.make_link('self',
pecan.request.host_url,
'sm_sda', ''),
@ -74,14 +87,6 @@ class Version1(wsme_types.Base):
'sm_sda', '',
bookmark=True)]
v1.nodes = [link.Link.make_link('self',
pecan.request.host_url,
'nodes', ''),
link.Link.make_link('bookmark',
pecan.request.host_url,
'nodes', '',
bookmark=True)]
return v1

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2014 Wind River Systems, Inc.
# Copyright (c) 2014-2018 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
@ -15,7 +15,7 @@ from sm_api.api.controllers.v1 import base
from sm_api.api.controllers.v1 import collection
from sm_api.api.controllers.v1 import link
from sm_api.api.controllers.v1 import utils
from sm_api.common import exception
from sm_api.common import log
from sm_api import objects
@ -112,7 +112,10 @@ class NodesController(rest.RestController):
@wsme_pecan.wsexpose(Nodes, unicode)
def get_one(self, uuid):
try:
rpc_sg = objects.sm_node.get_by_uuid(pecan.request.context, uuid)
except exception.ServerNotFound:
return None
return Nodes.convert_with_links(rpc_sg)

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2014 Wind River Systems, Inc.
# Copyright (c) 2014-2018 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
@ -15,7 +15,7 @@ from sm_api.api.controllers.v1 import base
from sm_api.api.controllers.v1 import collection
from sm_api.api.controllers.v1 import link
from sm_api.api.controllers.v1 import utils
from sm_api.common import exception
from sm_api.common import log
from sm_api import objects
@ -43,27 +43,32 @@ class ServiceGroupCommandResult(wsme_types.Base):
class ServiceGroup(base.APIBase):
name = wsme_types.text
state = wsme_types.text
status = wsme_types.text
# JKUNG new
uuid = wsme_types.text
"The UUID of the service_groups"
id = int
uuid = wsme_types.text
"The UUID of the sm_sda"
name = wsme_types.text
node_name = wsme_types.text
service_group_name = wsme_types.text
state = wsme_types.text
desired_state = wsme_types.text
status = wsme_types.text
condition = wsme_types.text
links = [link.Link]
"A list containing a self link and associated service_groups links"
"A list containing a self link and associated sm_sda links"
def __init__(self, **kwargs):
self.fields = objects.service_groups.fields.keys()
self.fields = objects.sm_sda.fields.keys()
for k in self.fields:
setattr(self, k, kwargs.get(k))
@classmethod
def convert_with_links(cls, rpc_service_groups, expand=True):
minimum_fields = ['id', 'name', 'state', 'status']
minimum_fields = ['id', 'uuid', 'name', 'node_name',
'service_group_name', 'desired_state',
'state', 'status', 'condition']
fields = minimum_fields if not expand else None
service_groups = ServiceGroup.from_rpc_object(
rpc_service_groups, fields)
@ -104,18 +109,27 @@ class ServiceGroupController(rest.RestController):
sort_dir = utils.validate_sort_dir(sort_dir)
marker_obj = None
if marker:
marker_obj = objects.service_groups.get_by_uuid(
pecan.request.context, marker)
marker_obj = objects.sm_sda.get_by_uuid(pecan.request.context,
marker)
service_groups = pecan.request.dbapi.iservicegroup_get_list(limit,
sm_sdas = pecan.request.dbapi.sm_sda_get_list(limit,
marker_obj,
sort_key=sort_key,
sort_dir=sort_dir)
return service_groups
# Remap OpenStack_Services to Cloud_Services
for sm_sda in sm_sdas:
if sm_sda.service_group_name.lower() == "openstack_services":
sm_sda.service_group_name = "Cloud_Services"
return sm_sdas
@wsme_pecan.wsexpose(ServiceGroup, unicode)
def get_one(self, uuid):
rpc_sg = objects.service_groups.get_by_uuid(pecan.request.context, uuid)
try:
rpc_sg = objects.sm_sda.get_by_uuid(pecan.request.context, uuid)
except exception.ServerNotFound:
return None
return ServiceGroup.convert_with_links(rpc_sg)
@ -134,23 +148,6 @@ class ServiceGroupController(rest.RestController):
sort_key=sort_key,
sort_dir=sort_dir)
# cursor = pecan.request.database.cursor()
# cursor.execute("SELECT name, state from service_groups")
# data = cursor.fetchall()
# if data is not None:
# service_groups = []
# for row in data:
# service_groups.append({'name': row[0], 'state': row[1]})
# return ServiceGroups(service_groups=json.dumps(service_groups))
#return wsme.api.Response(ServiceGroups(service_groups=json.dumps([])),
# status_code=404)
@wsme_pecan.wsexpose(ServiceGroupCommandResult, unicode,
body=ServiceGroupCommand)
def put(self, hostname, command):

View File

@ -118,8 +118,6 @@ LOCAL_HOST_NAME = socket.gethostname()
def rest_api_request(token, method, api_cmd, api_cmd_headers=None,
api_cmd_payload=None, timeout=10):
"""
Make a rest-api request
Returns: response as a dictionary
@ -133,7 +131,7 @@ def rest_api_request(token, method, api_cmd, api_cmd_headers=None,
request_info = urllib2.Request(api_cmd)
request_info.get_method = lambda: method
if token:
request_info.add_header("X-Auth-Token", token.get_id())
request_info.add_header("X-Auth-Token", token)
request_info.add_header("Accept", "application/json")
if api_cmd_headers is not None:
@ -155,9 +153,6 @@ def rest_api_request(token, method, api_cmd, api_cmd_headers=None,
LOG.info("Response=%s" % response)
except urllib2.HTTPError as e:
if 401 == e.code:
if token:
token.set_expired()
LOG.warn("HTTP Error e.code=%s e=%s" % (e.code, e))
if hasattr(e, 'msg') and e.msg:
response = json.loads(e.msg)
@ -438,8 +433,12 @@ class ServiceNodeController(rest.RestController):
api_cmd_headers['Content-type'] = "application/json"
api_cmd_headers['Accept'] = "application/json"
api_cmd_headers['User-Agent'] = "sm/1.0"
response = rest_api_request(None, "GET", api_cmd, api_cmd_headers, None)
auth_token = pecan.request.context.auth_token
response = rest_api_request(auth_token,
"GET",
api_cmd,
api_cmd_headers,
None)
return response

View File

@ -15,11 +15,10 @@ from sm_api.api.controllers.v1 import base
from sm_api.api.controllers.v1 import collection
from sm_api.api.controllers.v1 import link
from sm_api.api.controllers.v1 import utils
from sm_api.common import exception
from sm_api.common import log
from sm_api import objects
LOG = log.get_logger(__name__)
@ -112,12 +111,19 @@ class ServicesController(rest.RestController):
@wsme_pecan.wsexpose(Services, unicode)
def get_one(self, uuid):
try:
rpc_sg = objects.service.get_by_uuid(pecan.request.context, uuid)
except exception.ServerNotFound:
return None
return Services.convert_with_links(rpc_sg)
@wsme_pecan.wsexpose(Services, unicode)
def get_service(self, name):
try:
rpc_sg = objects.service.get_by_name(pecan.request.context, name)
except exception.ServerNotFound:
return None
return Services.convert_with_links(rpc_sg)
@wsme_pecan.wsexpose(ServicesCollection, unicode, int,

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2014 Wind River Systems, Inc.
# Copyright (c) 2014-2018 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
@ -15,7 +15,7 @@ from sm_api.api.controllers.v1 import base
from sm_api.api.controllers.v1 import collection
from sm_api.api.controllers.v1 import link
from sm_api.api.controllers.v1 import utils
from sm_api.common import exception
from sm_api.common import log
from sm_api import objects
@ -125,12 +125,10 @@ class SmSdaController(rest.RestController):
@wsme_pecan.wsexpose(SmSda, unicode)
def get_one(self, uuid):
try:
rpc_sda = objects.sm_sda.get_by_uuid(pecan.request.context, uuid)
# temp: remap OpenStack_Services to Cloud_Services
if rpc_sda.service_group_name.lower() == "openstack_services":
rpc_sda.service_group_name = "Cloud_Services"
except exception.ServerNotFound:
return None
return SmSda.convert_with_links(rpc_sda)

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2014 Wind River Systems, Inc.
# Copyright (c) 2014-2018 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
@ -19,8 +19,6 @@ from sm_api.db import api as dbapi
from sm_api.openstack.common import policy
class ConfigHook(hooks.PecanHook):
def __init__(self):
super(ConfigHook, self).__init__()
@ -76,7 +74,7 @@ class ContextHook(hooks.PecanHook):
auth_token = state.request.headers.get('X-Auth-Token', None)
creds = {'roles': state.request.headers.get('X-Roles', '').split(',')}
is_admin = policy.check('is_admin', state.request.headers, creds)
is_admin = policy.check('admin', state.request.headers, creds)
path = utils.safe_rstrip(state.request.path, '/')
is_public_api = path in self.public_api_routes

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2013-2014 Wind River Systems, Inc.
# Copyright (c) 2013-2018 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
@ -21,6 +21,7 @@ class AuthTokenMiddleware(auth_token.AuthProtocol):
"""
def __init__(self, app, conf, public_api_routes=[]):
self.smapi_app = app
self.public_api_routes = set(public_api_routes)
super(AuthTokenMiddleware, self).__init__(app, conf)
@ -29,6 +30,6 @@ class AuthTokenMiddleware(auth_token.AuthProtocol):
path = utils.safe_rstrip(env.get('PATH_INFO'), '/')
if path in self.public_api_routes:
return self.app(env, start_response)
return self.smapi_app(env, start_response)
return super(AuthTokenMiddleware, self).__call__(env, start_response)

View File

@ -66,14 +66,13 @@ def main():
# Parse config file and command line options, then start logging
# Periodically check every minute for want_sm_config
while os.path.exists("/etc/sm/.not_want_sm_config"):
time.sleep(60)
LOG = log.getLogger(__name__)
sm_api_service.prepare_service(sys.argv)
# Build and start the WSGI app
host = socket.gethostname()
port = 7777
host = CONF.sm_api_bind_ip or socket.gethostname()
port = CONF.sm_api_port
addrinfo_list = socket.getaddrinfo(host, port)
addrinfo = addrinfo_list[0]
@ -88,7 +87,6 @@ def main():
server_class=server_cls,
handler_class=get_handler_cls())
LOG = log.getLogger(__name__)
LOG.info("Serving on http://%(host)s:%(port)s" %
{'host': host, 'port': port})
LOG.info("Configuration:")

View File

@ -76,7 +76,7 @@ def model_query(model, *args, **kwargs):
return query
def add_identity_filter(query, value, use_name=False):
def add_identity_filter(query, value, model, use_name=False):
"""Adds an identity filter to a query.
Filters results by ID, if supplied value is a valid integer.
@ -86,9 +86,9 @@ def add_identity_filter(query, value, use_name=False):
:param value: Value for filtering results by.
:return: Modified query.
"""
if utils.is_int_like(value):
if utils.is_int_like(value) and hasattr(model, "id"):
return query.filter_by(id=value)
elif uuidutils.is_uuid_like(value):
elif uuidutils.is_uuid_like(value) and hasattr(model, "uuid"):
return query.filter_by(uuid=value)
else:
if use_name:
@ -129,7 +129,8 @@ class Connection(api.Connection):
@objects.objectify(objects.service_groups)
def iservicegroup_get(self, server):
query = model_query(models.iservicegroup)
query = add_identity_filter(query, server, use_name=True)
query = add_identity_filter(
query, server, models.iservicegroup, use_name=True)
try:
result = query.one()
@ -149,7 +150,8 @@ class Connection(api.Connection):
# server may be passed as a string. It may be uuid or Int.
# server = int(server)
query = model_query(models.service)
query = add_identity_filter(query, server, use_name=True)
query = add_identity_filter(
query, server, models.service, use_name=True)
try:
result = query.one()
@ -191,7 +193,8 @@ class Connection(api.Connection):
@objects.objectify(objects.sm_sda)
def sm_sda_get(self, server):
query = model_query(models.sm_sda)
query = add_identity_filter(query, server, use_name=True)
query = add_identity_filter(
query, server, models.sm_sda, use_name=True)
try:
result = query.one()
@ -215,7 +218,8 @@ class Connection(api.Connection):
@objects.objectify(objects.sm_node)
def sm_node_get(self, server):
query = model_query(models.sm_node)
query = add_identity_filter(query, server, use_name=True)
query = add_identity_filter(
query, server, models.sm_node, use_name=True)
try:
result = query.one()
@ -240,7 +244,8 @@ class Connection(api.Connection):
# server may be passed as a string. It may be uuid or Int.
# server = int(server)
query = model_query(models.service)
query = add_identity_filter(query, server, use_name=True)
query = add_identity_filter(
query, server, models.service, use_name=True)
try:
result = query.one()

View File

@ -1,4 +1,4 @@
SRC_DIR=sm-client
TAR_NAME=sm-client
VERSION=1.0
TIS_PATCH_VER=1
TIS_PATCH_VER=2

View File

@ -23,6 +23,8 @@ Requires: python-libs
%install
%global _buildsubdir %{_builddir}/%{name}-%{version}
%{__python2} setup.py install -O1 --skip-build --root %{buildroot}
install -d %{buildroot}/usr/bin
install -m 755 %{_buildsubdir}/usr/bin/smc %{buildroot}/usr/bin
%description
Service Management Client and CLI
@ -46,6 +48,7 @@ Service Management Client and CLI
%defattr(-,root,root,-)
%dir "/usr/lib/python2.7/site-packages/sm_client"
/usr/lib/python2.7/site-packages/sm_client/*
"/usr/bin/smc"
%dir "/usr/lib/python2.7/site-packages/sm_client-1.0.0-py2.7.egg-info"
/usr/lib/python2.7/site-packages/sm_client-1.0.0-py2.7.egg-info/*

View File

@ -1,13 +1,12 @@
#
# Copyright (c) 2013-2014 Wind River Systems, Inc.
# Copyright (c) 2013-2018 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
from sm_client.common import utils
from keystoneclient.v2_0 import client as ksclient
from keystoneclient.v3 import client as ksclient
def _get_ksclient(**kwargs):
"""Get an endpoint and auth token from Keystone.
@ -21,17 +20,19 @@ def _get_ksclient(**kwargs):
"""
return ksclient.Client(username=kwargs.get('username'),
password=kwargs.get('password'),
tenant_id=kwargs.get('tenant_id'),
tenant_name=kwargs.get('tenant_name'),
user_domain_name=kwargs.get('user_domain_name'),
project_domain_name=kwargs.get('project_domain_name'),
project_name=kwargs.get('project_name'),
auth_url=kwargs.get('auth_url'),
cacert=kwargs.get('os_cacert'),
insecure=kwargs.get('insecure'))
def _get_endpoint(client, **kwargs):
"""Get an endpoint using the provided keystone client."""
return client.service_catalog.url_for(
service_type=kwargs.get('service_type') or 'baremetal',
endpoint_type=kwargs.get('endpoint_type') or 'publicURL',
service_type=kwargs.get('service_name') or 'smapi',
endpoint_type=kwargs.get('endpoint_type') or 'public',
region_name=kwargs.get('os_region_name') or 'RegionOne')
@ -54,31 +55,30 @@ def get_client(api_version, **kwargs):
if kwargs.get('os_auth_token') and kwargs.get('smc_url'):
token = kwargs.get('os_auth_token')
endpoint = kwargs.get('smc_url')
auth_ref = None
elif (kwargs.get('os_username') and
kwargs.get('os_password') and
kwargs.get('os_auth_url') and
(kwargs.get('os_tenant_id') or kwargs.get('os_tenant_name'))):
kwargs.get('os_auth_url')):
ks_kwargs = {
'username': kwargs.get('os_username'),
'password': kwargs.get('os_password'),
'tenant_id': kwargs.get('os_tenant_id'),
'tenant_name': kwargs.get('os_tenant_name'),
'auth_url': kwargs.get('os_auth_url'),
'project_id': kwargs.get('os_project_id'),
'project_name': kwargs.get('os_project_name'),
'user_domain_id': kwargs.get('os_user_domain_id'),
'user_domain_name': kwargs.get('os_user_domain_name'),
'project_domain_id': kwargs.get('os_project_domain_id'),
'project_domain_name': kwargs.get('os_project_domain_name'),
'service_type': kwargs.get('os_service_type'),
'endpoint_type': kwargs.get('os_endpoint_type'),
'insecure': kwargs.get('insecure'),
}
_ksclient = _get_ksclient(**ks_kwargs)
token = ((lambda: kwargs.get('os_auth_token'))
if kwargs.get('os_auth_token')
else (lambda: _ksclient.auth_token))
token = kwargs.get('os_auth_token') if kwargs.get('os_auth_token') else _ksclient.auth_ref.auth_token
ep_kwargs = {
'username': kwargs.get('os_username'),
'password': kwargs.get('os_password'),
'tenant_id': kwargs.get('os_tenant_id'),
'tenant_name': kwargs.get('os_tenant_name'),
'auth_url': kwargs.get('os_auth_url'),
'service_type': kwargs.get('os_service_type'),
'endpoint_type': kwargs.get('os_endpoint_type'),
@ -89,8 +89,7 @@ def get_client(api_version, **kwargs):
endpoint = kwargs.get('smc_url') or \
_get_endpoint(_ksclient, **ep_kwargs)
#region_name=kwargs.get('os_region_name') or 'RegionOne'
# neutron_endpoint = _get_endpoint(_ksclient, service_type='network', endpoint_type='internalURL', region_name=region_name )
auth_ref = _ksclient.auth_ref
cli_kwargs = {
'token': token,
@ -99,7 +98,8 @@ def get_client(api_version, **kwargs):
'ca_file': kwargs.get('ca_file'),
'cert_file': kwargs.get('cert_file'),
'key_file': kwargs.get('key_file'),
# 'neutron_endpoint': neutron_endpoint,
'auth_ref': auth_ref,
'auth_url': kwargs.get('os_auth_url'),
}
return Client(api_version, endpoint, **cli_kwargs)

View File

@ -13,7 +13,7 @@
# License for the specific language governing permissions and limitations
# under the License.
#
# Copyright (c) 2013-2014 Wind River Systems, Inc.
# Copyright (c) 2013-2018 Wind River Systems, Inc.
#
@ -118,11 +118,42 @@ def print_tuple_list(tuples, tuple_labels=[]):
print pt.get_string()
def print_dict(d, dict_property="Property", wrap=0):
def print_mapping(data, fields, dict_property="Property", wrap=0):
pt = prettytable.PrettyTable([dict_property, 'Value'],
caching=False, print_empty=False)
pt.align = 'l'
for k, v in d.iteritems():
for k in fields:
if hasattr(data, k):
v = getattr(data, k, '')
else:
v = ''
# convert dict to str to check length
if isinstance(v, dict):
v = str(v)
if wrap > 0:
v = textwrap.fill(str(v), wrap)
# if value has a newline, add in multiple rows
# e.g. fault with stacktrace
if v and isinstance(v, basestring) and r'\n' in v:
lines = v.strip().split(r'\n')
col1 = k
for line in lines:
pt.add_row([col1, line])
col1 = ''
else:
pt.add_row([k, v])
print pt.get_string()
def print_dict(d, fields, dict_property="Property", wrap=0):
pt = prettytable.PrettyTable([dict_property, 'Value'],
caching=False, print_empty=False)
pt.align = 'l'
for k in fields:
if k in d:
v = d[k]
else:
v = ''
# convert dict to str to check length
if isinstance(v, dict):
v = str(v)

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2013-2014 Wind River Systems, Inc.
# Copyright (c) 2013-2018 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
@ -14,7 +14,7 @@ class BaseException(Exception):
self.message = message
def __str__(self):
return self.message or self.__class__.__doc__
return str(self.message) or self.__class__.__doc__
class CommandError(BaseException):
@ -41,7 +41,7 @@ class HTTPException(ClientException):
self.details = details
def __str__(self):
return self.details or "%s (HTTP %s)" % (self.__class__.__name__,
return str(self.details) or "%s (HTTP %s)" % (self.__class__.__name__,
self.code)
@ -143,10 +143,11 @@ for obj_name in dir(sys.modules[__name__]):
_code_map[obj.code] = obj
def from_response(response, error=None):
def from_response(response, message=None, traceback=None,
method=None, url=None):
"""Return an instance of an HTTPException based on httplib response."""
cls = _code_map.get(response.status, HTTPException)
return cls(error)
return cls(message)
class NoTokenLookupException(Exception):
@ -159,8 +160,18 @@ class EndpointNotFound(Exception):
pass
class AmbiguousAuthSystem(ClientException):
"""Could not obtain token and endpoint using provided credentials."""
pass
# Alias for backwards compatibility
AmbigiousAuthSystem = AmbiguousAuthSystem
class InvalidAttribute(ClientException):
pass
class InvalidAttributeValue(ClientException):
pass
#

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2013-2015 Wind River Systems, Inc.
# Copyright (c) 2014-2018 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
@ -12,6 +12,7 @@ Command-line interface for Service Manager (SM)
import argparse
import httplib2
import logging
import socket
import sys
import sm_client
@ -97,20 +98,6 @@ class SmcShell(object):
parser.add_argument('--os_password',
help=argparse.SUPPRESS)
parser.add_argument('--os-tenant-id',
default=utils.env('OS_TENANT_ID'),
help='Defaults to env[OS_TENANT_ID]')
parser.add_argument('--os_tenant_id',
help=argparse.SUPPRESS)
parser.add_argument('--os-tenant-name',
default=utils.env('OS_TENANT_NAME'),
help='Defaults to env[OS_TENANT_NAME]')
parser.add_argument('--os_tenant_name',
help=argparse.SUPPRESS)
parser.add_argument('--os-auth-url',
default=utils.env('OS_AUTH_URL'),
help='Defaults to env[OS_AUTH_URL]')
@ -132,9 +119,11 @@ class SmcShell(object):
parser.add_argument('--os_auth_token',
help=argparse.SUPPRESS)
smc_url = "http://{host}:{port}".format(
host=socket.gethostname(), port=7777)
parser.add_argument('--smc-url',
# default=utils.env('SMC_URL'),
default="http://localhost:7777",
default=smc_url,
help='Defaults to env[SMC_URL]')
parser.add_argument('--smc_url',
@ -163,6 +152,36 @@ class SmcShell(object):
parser.add_argument('--os_endpoint_type',
help=argparse.SUPPRESS)
parser.add_argument('--os-user-domain-id',
default=utils.env('OS_USER_DOMAIN_ID'),
help='Defaults to env[OS_USER_DOMAIN_ID].')
parser.add_argument('--os-user-domain-name',
default=utils.env('OS_USER_DOMAIN_NAME'),
help='Defaults to env[OS_USER_DOMAIN_NAME].')
parser.add_argument('--os-project-id',
default=utils.env('OS_PROJECT_ID'),
help='Another way to specify tenant ID. '
'This option is mutually exclusive with '
' --os-tenant-id. '
'Defaults to env[OS_PROJECT_ID].')
parser.add_argument('--os-project-name',
default=utils.env('OS_PROJECT_NAME'),
help='Another way to specify tenant name. '
'This option is mutually exclusive with '
' --os-tenant-name. '
'Defaults to env[OS_PROJECT_NAME].')
parser.add_argument('--os-project-domain-id',
default=utils.env('OS_PROJECT_DOMAIN_ID'),
help='Defaults to env[OS_PROJECT_DOMAIN_ID].')
parser.add_argument('--os-project-domain-name',
default=utils.env('OS_PROJECT_DOMAIN_NAME'),
help='Defaults to env[OS_PROJECT_DOMAIN_NAME].')
return parser
def get_subcommand_parser(self, version):
@ -223,11 +242,6 @@ class SmcShell(object):
"either --os-password or via "
"env[OS_PASSWORD]")
if not (args.os_tenant_id or args.os_tenant_name):
raise exc.CommandError("You must provide a tenant_id via "
"either --os-tenant-id or via "
"env[OS_TENANT_ID]")
if not args.os_auth_url:
raise exc.CommandError("You must provide an auth url via "
"either --os-auth-url or via "

View File

@ -13,16 +13,16 @@
# License for the specific language governing permissions and limitations
# under the License.
#
# Copyright (c) 2013-2014 Wind River Systems, Inc.
# Copyright (c) 2013-2018 Wind River Systems, Inc.
#
from sm_client.common import http
from sm_client.v1 import iservice
from sm_client.v1 import iservicegroup
from sm_client.v1 import sm_sda
from sm_client.v1 import smservicenode
from sm_client.v1 import sm_nodes
from sm_client.v1 import smc_service
from sm_client.v1 import smc_service_node
from sm_client.v1 import smc_servicegroup
class Client(http.HTTPClient):
@ -38,8 +38,8 @@ class Client(http.HTTPClient):
def __init__(self, *args, **kwargs):
"""Initialize a new client for the Smc v1 API."""
super(Client, self).__init__(*args, **kwargs)
self.iservice = iservice.iServiceManager(self)
self.iservicegroup = iservicegroup.iServiceGroupManager(self)
self.sm_sda = sm_sda.Sm_SdaManager(self)
self.sm_nodes = sm_nodes.Sm_NodesManager(self)
self.smservicenode = smservicenode.smServiceNodeManager(self)
self.smc_service = smc_service.SmcServiceManager(self)
self.smc_service_node = smc_service_node.SmcNodeManager(self)
self.smc_servicegroup = smc_servicegroup.SmcServiceGroupManager(self)

View File

@ -1,63 +0,0 @@
# -*- encoding: utf-8 -*-
#
# Copyright © 2013 Red Hat, 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.
#
# Copyright (c) 2013-2014 Wind River Systems, Inc.
#
from sm_client.common import base
from sm_client import exc
CREATION_ATTRIBUTES = ['name', 'hostname', 'state', 'activity', 'reason']
# missing forihostid
class iService(base.Resource):
def __repr__(self):
return "<iService %s>" % self._info
class iServiceManager(base.Manager):
resource_class = iService
@staticmethod
def _path(id=None):
return '/v1/services/%s' % id if id else '/v1/services'
def list(self):
return self._list(self._path(), "services")
def get(self, iservice_id):
try:
return self._list(self._path(iservice_id))[0]
except IndexError:
return None
def create(self, **kwargs):
new = {}
for (key, value) in kwargs.items():
if key in CREATION_ATTRIBUTES:
new[key] = value
else:
raise exc.InvalidAttribute()
return self._create(self._path(), new)
def delete(self, iservice_id):
return self._delete(self._path(iservice_id))
def update(self, iservice_id, patch):
return self._update(self._path(iservice_id), patch)

View File

@ -1,116 +0,0 @@
#!/usr/bin/env python
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2013 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.
#
# Copyright (c) 2013-2014 Wind River Systems, Inc.
#
from sm_client.common import utils
from sm_client import exc
def _print_iservice_show(iservice):
fields = ['id', 'name', 'desired_state', 'state', 'status']
data = dict([(f, getattr(iservice, f, '')) for f in fields])
utils.print_dict(data, wrap=72)
# These are now part of the "system" command
def donot_service_list(cc, args):
"""List services."""
iservice = cc.iservice.list()
fields = ['id', 'name', 'desired_state', 'state', 'status']
field_labels = ['id', 'name', 'desired_state', 'state', 'status']
utils.print_list(iservice, fields, field_labels, sortby=1)
@utils.arg('iservice', metavar='<iservice id>', help="ID of iservice")
def donot_service_show(cc, args):
"""Show a service."""
try:
iservice = cc.iservice.get(args.iservice)
except exc.HTTPNotFound:
raise exc.CommandError('service not found: %s' % args.iservice)
else:
_print_iservice_show(iservice)
@utils.arg('-c', '--servicename',
metavar='<servicename>',
help='servicename of the service [REQUIRED]')
@utils.arg('-n', '--hostname',
metavar='<hostname>',
help='hostname of the service [REQUIRED]')
@utils.arg('-s', '--state',
metavar='<state>',
help='state of the service [REQUIRED]')
@utils.arg('-a', '--activity',
metavar="<key=value>",
action='append',
help="Record activity key/value metadata. ")
@utils.arg('-r', '--reason',
metavar="<key=value>",
action='append',
help="Record reason key/value metadata. ")
def donot_service_create(cc, args):
"""Create a new service."""
field_list = ['servicename', 'hostname', 'state', 'activity', 'reason']
fields = dict((k, v) for (k, v) in vars(args).items()
if k in field_list and not (v is None))
# fields = utils.args_array_to_dict(fields, 'activity')
fields = utils.args_array_to_dict(fields, 'reason')
iservice = cc.iservice.create(**fields)
field_list.append('uuid')
data = dict([(f, getattr(iservice, f, '')) for f in field_list])
utils.print_dict(data, wrap=72)
@utils.arg('iservice',
metavar='<iservice id>',
nargs='+',
help="ID of iservice")
def donot_service_delete(cc, args):
"""Delete a iservice."""
for c in args.iservice:
try:
cc.iservice.delete(c)
except exc.HTTPNotFound:
raise exc.CommandError('Service not found: %s' % c)
print 'Deleted service %s' % c
@utils.arg('iservice',
metavar='<iservice id>',
help="ID of iservice")
@utils.arg('attributes',
metavar='<path=value>',
nargs='+',
action='append',
default=[],
help="Attributes to add/replace or remove ")
def donot_service_modify_lab(cc, args):
"""LAB ONLY Update a service. """
# JKUNG comment this out prior to delivery
patch = utils.args_array_to_patch("replace", args.attributes[0])
try:
iservice = cc.iservice.update(args.iservice, patch)
except exc.HTTPNotFound:
raise exc.CommandError('Service not found: %s' % args.iservice)
_print_iservice_show(iservice)

View File

@ -1,62 +0,0 @@
# -*- encoding: utf-8 -*-
#
# Copyright © 2013 Red Hat, 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.
#
# Copyright (c) 2013-2014 Wind River Systems, Inc.
#
from sm_client.common import base
from sm_client import exc
CREATION_ATTRIBUTES = ['servicename', 'state']
class iService(base.Resource):
def __repr__(self):
return "<iService %s>" % self._info
class iServiceGroupManager(base.Manager):
resource_class = iService
@staticmethod
def _path(id=None):
return '/v1/service_groups/%s' % id if id else '/v1/service_groups'
def list(self):
return self._list(self._path(), "service_groups")
def get(self, iservicegroup_id):
try:
return self._list(self._path(iservicegroup_id))[0]
except IndexError:
return None
def create(self, **kwargs):
new = {}
for (key, value) in kwargs.items():
if key in CREATION_ATTRIBUTES:
new[key] = value
else:
raise exc.InvalidAttribute()
return self._create(self._path(), new)
def delete(self, iservicegroup_id):
return self._delete(self._path(iservicegroup_id))
def update(self, iservicegroup_id, patch):
return self._update(self._path(iservicegroup_id), patch)

View File

@ -1,105 +0,0 @@
#!/usr/bin/env python
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2013 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.
#
# Copyright (c) 2013-2014 Wind River Systems, Inc.
#
from sm_client.common import utils
from sm_client import exc
def _print_iservicegroup_show(iservicegroup):
fields = ['id', 'name', 'state', 'status']
data = dict([(f, getattr(iservicegroup, f, '')) for f in fields])
utils.print_dict(data, wrap=72)
def do_servicegroup_list(cc, args):
"""List Service Groups."""
iservicegroup = cc.iservicegroup.list()
fields = ['id', 'name', 'state', 'status']
field_labels = ['id', 'name', 'state', 'status']
utils.print_list(iservicegroup, fields, field_labels, sortby=1)
@utils.arg('servicegroup', metavar='<servicegroup id>',
help="ID of iservicegroup")
def do_servicegroup_show(cc, args):
"""Show a Service Group."""
try:
servicegroup = cc.iservicegroup.get(args.servicegroup)
except exc.HTTPNotFound:
raise exc.CommandError(
'Service Group not found: %s' % args.servicegroup)
else:
_print_iservicegroup_show(servicegroup)
@utils.arg('-n', '--name',
metavar='<name>',
help='name of the service group [REQUIRED]')
@utils.arg('-s', '--state',
metavar='<state>',
help='state of the servicegroup [REQUIRED]')
def donot_servicegroup_create(cc, args):
"""Create a new servicegroup."""
field_list = ['name', 'state']
fields = dict((k, v) for (k, v) in vars(args).items()
if k in field_list and not (v is None))
# fields = utils.args_array_to_dict(fields, 'activity')
iservicegroup = cc.iservicegroup.create(**fields)
field_list.append('uuid')
data = dict([(f, getattr(iservicegroup, f, '')) for f in field_list])
utils.print_dict(data, wrap=72)
@utils.arg('iservicegroup',
metavar='<iservicegroup id>',
nargs='+',
help="ID of iservicegroup")
def donot_servicegroup_delete(cc, args):
"""Delete a servicegroup."""
for c in args.iservicegroup:
try:
cc.iservicegroup.delete(c)
except exc.HTTPNotFound:
raise exc.CommandError('Service not found: %s' % c)
print 'Deleted servicegroup %s' % c
@utils.arg('iservicegroup',
metavar='<iservicegroup id>',
help="ID of iservicegroup")
@utils.arg('attributes',
metavar='<path=value>',
nargs='+',
action='append',
default=[],
help="Attributes to add/replace or remove ")
def donot_servicegroup_modify_labonly(cc, args):
"""LAB ONLY Update a servicegroup. """
# JKUNG comment this out prior to delivery
patch = utils.args_array_to_patch("replace", args.attributes[0])
try:
iservicegroup = cc.iservicegroup.update(args.iservicegroup, patch)
except exc.HTTPNotFound:
raise exc.CommandError(
'Service Group not found: %s' % args.iservicegroup)
_print_iservicegroup_show(iservicegroup)

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2013-2014 Wind River Systems, Inc.
# Copyright (c) 2013-2018 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
@ -8,18 +8,14 @@
from sm_client.common import utils
from sm_client.v1 import iservicegroup_shell
from sm_client.v1 import iservice_shell
from sm_client.v1 import smservicenode_shell
from sm_client.v1 import sm_sda_shell
from sm_client.v1 import sm_nodes_shell
from sm_client.v1 import smc_service_shell
from sm_client.v1 import smc_service_node_shell
from sm_client.v1 import smc_servicegroup_shell
COMMAND_MODULES = [
iservicegroup_shell,
iservice_shell,
smservicenode_shell,
sm_sda_shell,
sm_nodes_shell
smc_service_shell,
smc_service_node_shell,
smc_servicegroup_shell,
]

View File

@ -1,51 +0,0 @@
#!/usr/bin/env python
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2013 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.
#
# Copyright (c) 2013-2014 Wind River Systems, Inc.
#
from sm_client.common import utils
from sm_client import exc
def _print_sm_node_show(node):
fields = ['id', 'name', 'state', 'online']
data = dict([(f, getattr(node, f, '')) for f in fields])
utils.print_dict(data, wrap=72)
def do_node_list(cc, args):
"""List Node(s)."""
node = cc.sm_nodes.list()
fields = ['id', 'name', 'state', 'online']
field_labels = ['id', 'name', 'state', 'online']
utils.print_list(node, fields, field_labels, sortby=1)
@utils.arg('node', metavar='<node uuid>',
help="uuid of a Service Domain Assignment")
def do_node_show(cc, args):
"""Show a Node."""
try:
node = cc.sm_nodes.get(args.node)
except exc.HTTPNotFound:
raise exc.CommandError(
'Service Domain Assignment not found: %s' % args.node)
else:
_print_sm_node_show(node)

View File

@ -1,54 +0,0 @@
#!/usr/bin/env python
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2013 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.
#
# Copyright (c) 2013-2014 Wind River Systems, Inc.
#
from sm_client.common import utils
from sm_client import exc
def _print_sm_sda_show(sm_sda):
fields = ['id', 'uuid', 'name', 'node_name', 'service_group_name',
'desired_state', 'state', 'status', 'condition']
data = dict([(f, getattr(sm_sda, f, '')) for f in fields])
utils.print_dict(data, wrap=72)
def do_sda_list(cc, args):
"""List Service Domain Assignments."""
sm_sda = cc.sm_sda.list()
fields = ['uuid', 'service_group_name', 'node_name', 'state', 'status',
'condition']
field_labels = ['uuid', 'service_group_name', 'node_name',
'state', 'status', 'condition']
utils.print_list(sm_sda, fields, field_labels, sortby=1)
@utils.arg('sm_sda', metavar='<sm_sda uuid>',
help="uuid of a Service Domain Assignment")
def do_sda_show(cc, args):
"""Show a Service Domain Assignment."""
try:
sm_sda = cc.sm_sda.get(args.sm_sda)
except exc.HTTPNotFound:
raise exc.CommandError(
'Service Domain Assignment not found: %s' % args.sm_sda)
else:
_print_sm_sda_show(sm_sda)

View File

@ -0,0 +1,33 @@
#!/usr/bin/env python
# vim: tabstop=4 shiftwidth=4 softtabstop=4
#
# Copyright (c) 2018 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
#
from sm_client import exc
from sm_client.common import base
class SmcService(base.Resource):
def __repr__(self):
return "<SmcService %s>" % self._info
class SmcServiceManager(base.Manager):
resource_class = SmcService
@staticmethod
def _path(id=None):
return '/v1/services/%s' % id if id else '/v1/services'
def list(self):
return self._list(self._path(), "services")
def get(self, iservice_id):
result = self._list(self._path(iservice_id))
if len(result) == 0:
return None
else:
return result[0]

View File

@ -0,0 +1,33 @@
#!/usr/bin/env python
# vim: tabstop=4 shiftwidth=4 softtabstop=4
#
#
# Copyright (c) 2018 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
#
from sm_client import exc
from sm_client.common import base
class SmcNode(base.Resource):
def __repr__(self):
return "<SmcNode %s>" % self._info
class SmcNodeManager(base.Manager):
resource_class = SmcNode
@staticmethod
def _path(id=None):
return '/v1/nodes/%s' % id if id else '/v1/nodes'
def list(self):
return self._list(self._path(), "nodes")
def get(self, nodes_id):
result = self._list(self._path(nodes_id))
if len(result) > 0:
return result[0]
else:
return None

View File

@ -0,0 +1,49 @@
#!/usr/bin/env python
# vim: tabstop=4 shiftwidth=4 softtabstop=4
#
#
# Copyright (c) 2018 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
#
from sm_client import exc
from sm_client.common import utils
def _print_sm_service_node_show(node):
fields = ['id', 'name', 'administrative_state', 'operational_state',
'availability_status', 'ready_state']
utils.print_mapping(node, fields, wrap=72)
def do_servicenode_list(cc, args):
"""List Service Nodes."""
try:
node = cc.smc_service_node.list()
except exc.Forbidden:
raise exc.CommandError("Not authorized. The requested action "
"requires 'admin' level")
else:
fields = ['id', 'name', 'administrative_state', 'operational_state',
'availability_status', 'ready_state']
field_labels = ['id', 'name', 'administrative', 'operational',
'availability', 'ready_state']
utils.print_list(node, fields, field_labels, sortby=1)
@utils.arg('node', metavar='<node uuid>',
help="uuid of a Service Node")
def do_servicenode_show(cc, args):
"""Show a Service Node's attributes."""
try:
node = cc.smc_service_node.get(args.node)
except exc.HTTPNotFound:
raise exc.CommandError('Service Node not found: %s' % args.node)
except exc.Forbidden:
raise exc.CommandError("Not authorized. The requested action "
"requires 'admin' level")
else:
if node is None:
print "Service node %s could not be found" % args.node
return
_print_sm_service_node_show(node)

View File

@ -0,0 +1,65 @@
#!/usr/bin/env python
# vim: tabstop=4 shiftwidth=4 softtabstop=4
#
#
# Copyright (c) 2018 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
#
import socket
from sm_client.common import utils
from sm_client import exc
def _print_service_show(service):
fields = ['id', 'service_name', 'hostname', 'state']
data = dict([(f, getattr(service, f, '')) for f in fields])
data['hostname'] = getattr(service, 'node_name', '')
utils.print_dict(data, fields, wrap=72)
def do_service_list(cc, args):
"""List Services."""
try:
service = cc.smc_service.list()
except exc.Forbidden:
raise exc.CommandError("Not authorized. The requested action "
"requires 'admin' level")
else:
fields = ['id', 'name', 'node_name', 'state']
field_labels = ['id', 'service_name', 'hostname', 'state']
# remove the entry in the initial state
clean_list = filter(lambda x: x.state != 'initial', service)
for s in clean_list:
if s.status:
setattr(s, 'state', s.state + '-' + s.status)
if getattr(s, 'node_name', None) is None:
setattr(s, 'node_name', socket.gethostname())
utils.print_list(clean_list, fields, field_labels, sortby=1)
@utils.arg('service', metavar='<service id>', help="ID of service")
def do_service_show(cc, args):
"""Show a Service."""
try:
service = cc.smc_service.get(args.service)
except exc.HTTPNotFound:
raise exc.CommandError('service not found: %s' % args.service)
except exc.Forbidden:
raise exc.CommandError("Not authorized. The requested action "
"requires 'admin' level")
else:
if service is None:
print "Service %s could not be found" % args.service
return
if service.status:
setattr(service, 'state', service.state + '-' + service.status)
setattr(service, 'service_name', service.name)
if getattr(service, 'node_name', None) is None:
setattr(service, 'hostname', socket.gethostname())
_print_service_show(service)

View File

@ -0,0 +1,38 @@
#!/usr/bin/env python
# vim: tabstop=4 shiftwidth=4 softtabstop=4
#
#
# Copyright (c) 2018 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
#
from sm_client import exc
from sm_client.common import base
class smc_Servicegroup(base.Resource):
def __repr__(self):
return "<smc_Servicegroup %s>" % self._info
class SmcServiceGroupManager(base.Manager):
resource_class = smc_Servicegroup
@staticmethod
def _path(id=None):
return '/v1/service_groups/%s' % id if id else '/v1/service_groups'
def list(self):
return self._list(self._path(), "service_groups")
def get(self, sm_servicegroup_id):
try:
result = self._list(self._path(sm_servicegroup_id))
except IndexError:
return None
if len(result) > 0:
return result[0]
else:
return None

View File

@ -0,0 +1,54 @@
#!/usr/bin/env python
# vim: tabstop=4 shiftwidth=4 softtabstop=4
#
#
# Copyright (c) 2018 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
#
from sm_client.common import utils
from sm_client import exc
def _print_servicegroup_show(servicegroup):
fields = ['uuid', 'name', 'hostname', 'service_group_name', 'state']
utils.print_mapping(servicegroup, fields, wrap=72)
def do_servicegroup_list(cc, args):
"""List Service Groups."""
try:
servicegroup = cc.smc_servicegroup.list()
except exc.Forbidden:
raise exc.CommandError("Not authorized. The requested action "
"requires 'admin' level")
else:
fields = ['uuid', 'service_group_name', 'node_name', 'state']
field_labels = ['uuid', 'service_group_name', 'hostname', 'state']
for s in servicegroup:
if s.status:
setattr(s, 'state', s.state + '-' + s.status)
utils.print_list(servicegroup, fields, field_labels, sortby=1)
@utils.arg('servicegroup', metavar='<servicegroup uuid>',
help="UUID of servicegroup")
def do_servicegroup_show(cc, args):
"""Show a Service Group."""
try:
servicegroup = cc.smc_servicegroup.get(args.servicegroup)
except exc.HTTPNotFound:
raise exc.CommandError('Service Group not found: %s' % args.servicegroup)
except exc.Forbidden:
raise exc.CommandError("Not authorized. The requested action "
"requires 'admin' level")
else:
if servicegroup is None:
print "Service group %s could not be found" % args.servicegroup
return
if servicegroup.status:
setattr(servicegroup, 'state', servicegroup.state + '-' +
servicegroup.status)
setattr(servicegroup, 'hostname', servicegroup.node_name)
_print_servicegroup_show(servicegroup)

View File

@ -1,62 +0,0 @@
# -*- encoding: utf-8 -*-
#
# Copyright © 2013 Red Hat, 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.
#
# Copyright (c) 2013-2014 Wind River Systems, Inc.
#
from sm_client.common import base
from sm_client import exc
CREATION_ATTRIBUTES = ['servicename', 'state']
class smService(base.Resource):
def __repr__(self):
return "<smService %s>" % self._info
class smServiceNodeManager(base.Manager):
resource_class = smService
@staticmethod
def _path(id=None):
return '/v1/servicenode/%s' % id if id else '/v1/servicenode'
def list(self, hostname):
return self._list(self._path(hostname), "servicenode")
def get(self, smservicenode_id):
try:
return self._list(self._path(smservicenode_id))[0]
except IndexError:
return None
def create(self, **kwargs):
new = {}
for (key, value) in kwargs.items():
if key in CREATION_ATTRIBUTES:
new[key] = value
else:
raise exc.InvalidAttribute()
return self._create(self._path(), new)
def delete(self, smservicenode_id):
return self._delete(self._path(smservicenode_id))
def update(self, smservicenode_id, patch):
return self._update(self._path(smservicenode_id), patch)

View File

@ -1,56 +0,0 @@
#!/usr/bin/env python
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2013 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.
#
# Copyright (c) 2013-2014 Wind River Systems, Inc.
#
from sm_client.common import utils
from sm_client import exc
def _print_smservicenode_show(smservicenode):
fields = ['id', 'uuid', 'name', 'node_name', 'service_group_name',
'desired_state', 'state', 'status']
data = dict([(f, getattr(smservicenode, f, '')) for f in fields])
utils.print_dict(data, wrap=72)
@utils.arg('hostname', metavar='<hostname>',
help="hostname of servicenode")
def donot_servicenode_list(cc, args):
"""List sm servicenodes by hostname."""
smservicenode = cc.smservicenode.list(args.hostname)
fields = ['uuid', 'name', 'node_name', 'service_group_name',
'state', 'status']
field_labels = ['uuid', 'name', 'node_name', 'service_group_name',
'state', 'status']
utils.print_list(smservicenode, fields, field_labels, sortby=1)
@utils.arg('smservicenode', metavar='<smservicenode uuid>',
help="uuid of smservicenode")
def donot_servicenode_show(cc, args):
"""Show an smservicenode."""
try:
smservicenode = cc.smservicenode.get(args.smservicenode)
except exc.HTTPNotFound:
raise exc.CommandError(
'servicenode not found: %s' % args.smservicenode)
else:
_print_smservicenode_show(smservicenode)

View File

@ -0,0 +1,16 @@
#!/usr/bin/env python
# vim: tabstop=4 shiftwidth=4 softtabstop=4
#
#
# Copyright (c) 2018 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
#
import sys
from sm_client.shell import main
if __name__ == "__main__":
sys.exit(main())