finish up group api

- add add/remove host to Group
- add add/remove service to Group
- update cli to use new apis
- normalized some capitalization in api error messages
- add validation methods for group and service names

Jira-Issue: OSTACKDEV-17
This commit is contained in:
Steve Noyes 2016-03-24 11:22:32 -04:00
parent ee80b1b5f2
commit 4b229c6ea4
8 changed files with 164 additions and 73 deletions

View File

@ -53,7 +53,7 @@ class HostsSshCheckError(ClientException):
for hostname in hostnames:
failed_hosts = ''.join([failed_hosts, comma, hostname])
comma = ','
message = (u._('host(s) ssh check failed: {hosts}')
message = (u._('Host(s) ssh check failed: {hosts}')
.format(hosts=failed_hosts))
super(HostsSshCheckError, self).__init__(message, *args)
@ -75,6 +75,6 @@ class FailedOperation(ClientException):
class MissingArgument(ClientException):
"""Missing argument"""
def __init__(self, argname, *args):
message = (u._('argument is missing: {name}')
message = (u._('Argument is missing: {name}')
.format(name=argname))
super(MissingArgument, self).__init__(message, *args)

View File

@ -11,6 +11,7 @@
# 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 copy import copy
import kollacli.i18n as u
from kollacli.api.exceptions import MissingArgument
@ -23,8 +24,8 @@ class GroupApi(object):
class Group(object):
def __init__(self, groupname, servicenames, hostnames):
self.name = groupname
self.servicenames = servicenames
self.hostnames = hostnames
self._servicenames = servicenames
self._hostnames = hostnames
def get_name(self):
"""Get name
@ -34,21 +35,93 @@ class GroupApi(object):
"""
return self.name
def get_servicenames(self):
"""Get service names associated with this group.
def get_services(self):
"""Get names of services associated with this group.
:return: service names
:rtype: list of strings
"""
return self.servicenames
return copy(self._servicenames)
def get_hostnames(self):
"""Get host names associated with this group.
def add_service(self, servicename):
"""Add service to group
:param servicename: name of the service to add to the group
:type servicename: string
"""
servicename = safe_decode(servicename)
inventory = Inventory.load()
inventory.validate_servicenames([servicename])
group_services = inventory.get_group_services()
self._servicenames = group_services[self.name]
if servicename not in self._servicenames:
# service not associated with group, add it
inventory.add_group_to_service(self.name, servicename)
Inventory.save(inventory)
def remove_service(self, servicename):
"""Remove service from group
:param servicename: name of the service to remove from the group
:type servicename: string
"""
servicename = safe_decode(servicename)
inventory = Inventory.load()
inventory.validate_servicenames([servicename])
group_services = inventory.get_group_services()
self._servicenames = group_services[self.name]
if servicename in self._servicenames:
# service is associated with group, remove it
inventory.remove_group_from_service(self.name, servicename)
Inventory.save(inventory)
def get_hosts(self):
"""Get names of hosts associated with this group.
:return: host names
:rtype: list of strings
"""
return self.hostnames
return copy(self._hostnames)
def add_host(self, hostname):
"""Add host to group
:param hostname: name of the host to add to the group
:type hostname: string
"""
hostname = safe_decode(hostname)
inventory = Inventory.load()
inventory.validate_hostnames([hostname])
group = inventory.get_group(self.name)
self._hostnames = group.get_hostnames()
if hostname not in self._hostnames:
# host not associated with group, add it
inventory.add_host(hostname, self.name)
Inventory.save(inventory)
def remove_host(self, hostname):
"""Remove host from group
:param hostname: name of the host to remove from the group
:type hostname: string
"""
hostname = safe_decode(hostname)
inventory = Inventory.load()
inventory.validate_hostnames([hostname])
group = inventory.get_group(self.name)
self._hostnames = group.get_hostnames()
if hostname in self._hostnames:
# host is associated with group, remove it
inventory.remove_host(hostname, self.name)
Inventory.save(inventory)
def group_add(self, groupname):
"""Add a group to the inventory
@ -58,7 +131,7 @@ class GroupApi(object):
"""
if not groupname:
raise MissingArgument('Group name')
raise MissingArgument(u._('Group name'))
groupname = safe_decode(groupname)
inventory = Inventory.load()
@ -73,7 +146,7 @@ class GroupApi(object):
"""
if not groupname:
raise MissingArgument('Group name')
raise MissingArgument(u._('Group name'))
inventory = Inventory.load()
groupname = safe_decode(groupname)
@ -97,13 +170,16 @@ class GroupApi(object):
:rtype: list of Group objects
"""
if groupnames is None:
raise(MissingArgument(u._('Group names')))
raise MissingArgument(u._('Group names'))
groupnames = safe_decode(groupnames)
return self._get_groups(groupnames)
def _get_groups(self, groupnames, get_all=False):
groups = []
inventory = Inventory.load()
if groupnames:
inventory.validate_groupnames(groupnames)
group_services = inventory.get_group_services()
inv_groups = inventory.get_groups()
for inv_group in inv_groups:

View File

@ -11,6 +11,8 @@
# 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 kollacli.i18n as u
from kollacli.api.exceptions import MissingArgument
from kollacli.common.inventory import Inventory
from kollacli.common.utils import safe_decode
@ -46,7 +48,7 @@ class HostApi(object):
:param hostnames: list of strings
"""
if not hostnames:
raise MissingArgument('host names')
raise MissingArgument(u._('Host names'))
hostnames = safe_decode(hostnames)
inventory = Inventory.load()
@ -66,7 +68,7 @@ class HostApi(object):
inventory = Inventory.load()
if not hostnames:
raise MissingArgument('host name')
raise MissingArgument(u._('Host names'))
hostnames = safe_decode(hostnames)
any_changed = False
@ -97,7 +99,12 @@ class HostApi(object):
:return: hosts
:rtype: Host
"""
if hostnames is None:
raise MissingArgument(u._('Host names'))
hostnames = safe_decode(hostnames)
inventory = Inventory.load()
inventory.validate_hostnames(hostnames)
hosts = []
host_groups = inventory.get_host_groups()
for hostname in hostnames:

View File

@ -11,6 +11,7 @@
# 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 copy import copy
import kollacli.i18n as u
from kollacli.api.exceptions import MissingArgument
@ -42,8 +43,8 @@ class ServiceApi(object):
childnames=[], groupnames=[]):
self.name = servicename
self.parentname = parentname
self.childnames = childnames
self.groupnames = groupnames
self._childnames = childnames
self._groupnames = groupnames
def get_name(self):
"""Get name
@ -67,7 +68,7 @@ class ServiceApi(object):
:return: child names
:rtype: list of strings
"""
return self.childnames
return copy(self._childnames)
def get_groupnames(self):
"""Get names of the groups associated with this service
@ -75,7 +76,7 @@ class ServiceApi(object):
:return: group names
:rtype: list of strings
"""
return self.groupnames
return copy(self._groupnames)
def service_get_all(self):
"""Get all services in the inventory
@ -94,13 +95,16 @@ class ServiceApi(object):
:rtype: list of Service objects
"""
if servicenames is None:
raise(MissingArgument(u._('Service names')))
raise MissingArgument(u._('Service names'))
servicenames = safe_decode(servicenames)
return self._get_services(servicenames)
def _get_services(self, servicenames, get_all=False):
services = []
inventory = Inventory.load()
if servicenames:
inventory.validate_servicenames(servicenames)
inv_services = inventory.get_services()
inv_subservices = inventory.get_sub_services()

View File

@ -18,8 +18,6 @@ import kollacli.i18n as u
from kollacli.api.client import ClientApi
from kollacli.api.exceptions import ClientException
from kollacli.commands.exceptions import CommandError
from kollacli.common.inventory import Inventory
from kollacli.common.utils import convert_to_unicode
from cliff.command import Command
from cliff.lister import Lister
@ -79,14 +77,13 @@ class GroupAddhost(Command):
def take_action(self, parsed_args):
try:
groupname = parsed_args.groupname.strip()
groupname = convert_to_unicode(groupname)
hostname = parsed_args.hostname.strip()
hostname = convert_to_unicode(hostname)
inventory = Inventory.load()
inventory.add_host(hostname, groupname)
Inventory.save(inventory)
except CommandError as e:
raise e
group = CLIENT.group_get([groupname])[0]
group.add_host(hostname)
except ClientException as e:
raise CommandError(str(e))
except Exception as e:
raise Exception(traceback.format_exc())
@ -105,15 +102,13 @@ class GroupRemovehost(Command):
def take_action(self, parsed_args):
try:
groupname = parsed_args.groupname.strip()
groupname = convert_to_unicode(groupname)
hostname = parsed_args.hostname.strip()
hostname = convert_to_unicode(hostname)
inventory = Inventory.load()
inventory.remove_host(hostname, groupname)
Inventory.save(inventory)
except CommandError as e:
raise e
group = CLIENT.group_get([groupname])[0]
group.remove_host(hostname)
except ClientException as e:
raise CommandError(str(e))
except Exception as e:
raise Exception(traceback.format_exc())
@ -129,7 +124,7 @@ class GroupListhosts(Lister):
data = []
for group in groups:
data.append((group.get_name(),
sorted(group.get_hostnames())))
sorted(group.get_hosts())))
return ((u._('Group'), u._('Hosts')), sorted(data))
except ClientException as e:
raise CommandError(str(e))
@ -150,15 +145,13 @@ class GroupAddservice(Command):
def take_action(self, parsed_args):
try:
groupname = parsed_args.groupname.strip()
groupname = convert_to_unicode(groupname)
servicename = parsed_args.servicename.strip()
servicename = convert_to_unicode(servicename)
inventory = Inventory.load()
inventory.add_group_to_service(groupname, servicename)
Inventory.save(inventory)
except CommandError as e:
raise e
group = CLIENT.group_get([groupname])[0]
group.add_service(servicename)
except ClientException as e:
raise CommandError(str(e))
except Exception as e:
raise Exception(traceback.format_exc())
@ -177,15 +170,13 @@ class GroupRemoveservice(Command):
def take_action(self, parsed_args):
try:
groupname = parsed_args.groupname.strip()
groupname = convert_to_unicode(groupname)
servicename = parsed_args.servicename.strip()
servicename = convert_to_unicode(servicename)
inventory = Inventory.load()
inventory.remove_group_from_service(groupname, servicename)
Inventory.save(inventory)
except CommandError as e:
raise e
group = CLIENT.group_get([groupname])[0]
group.remove_service(servicename)
except ClientException as e:
raise CommandError(str(e))
except Exception as e:
raise Exception(traceback.format_exc())
@ -201,7 +192,7 @@ class GroupListservices(Lister):
data = []
for group in groups:
data.append((group.get_name(),
sorted(group.get_servicenames())))
sorted(group.get_services())))
return ((u._('Group'), u._('Services')), sorted(data))
except ClientException as e:
raise CommandError(str(e))

View File

@ -18,8 +18,6 @@ import kollacli.i18n as u
from kollacli.api.client import ClientApi
from kollacli.api.exceptions import ClientException
from kollacli.commands.exceptions import CommandError
from kollacli.common.inventory import Inventory
from kollacli.common.utils import convert_to_unicode
from cliff.command import Command
from cliff.lister import Lister
@ -45,17 +43,13 @@ class ServiceAddGroup(Command):
def take_action(self, parsed_args):
try:
groupname = parsed_args.groupname.strip()
groupname = convert_to_unicode(groupname)
servicename = parsed_args.servicename.strip()
servicename = convert_to_unicode(servicename)
inventory = Inventory.load()
group = CLIENT.group_get([groupname])[0]
group.add_service(servicename)
inventory.add_group_to_service(groupname, servicename)
Inventory.save(inventory)
except CommandError as e:
raise e
except ClientException as e:
raise CommandError(str(e))
except Exception as e:
raise Exception(traceback.format_exc())
@ -74,17 +68,13 @@ class ServiceRemoveGroup(Command):
def take_action(self, parsed_args):
try:
groupname = parsed_args.groupname.strip()
groupname = convert_to_unicode(groupname)
servicename = parsed_args.servicename.strip()
servicename = convert_to_unicode(servicename)
inventory = Inventory.load()
group = CLIENT.group_get([groupname])[0]
group.remove_service(servicename)
inventory.remove_group_from_service(groupname, servicename)
Inventory.save(inventory)
except CommandError as e:
raise e
except ClientException as e:
raise CommandError(str(e))
except Exception as e:
raise Exception(traceback.format_exc())

View File

@ -11,7 +11,6 @@
# 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 fcntl
import json
import logging
@ -20,6 +19,8 @@ import subprocess # nosec
import tempfile
import time
import kollacli.i18n as u
from kollacli.common.inventory import remove_temp_inventory
from kollacli.common.utils import get_admin_uids
from kollacli.common.utils import safe_decode
@ -176,7 +177,8 @@ class AnsibleJob(object):
elif action == ACTION_TASK_START:
return self._format_task_start(packet)
else:
raise Exception('Invalid action [%s] from callback' % action)
raise Exception(u._('Invalid action [{action}] from callback')
.format(action=action))
def _format_include_file(self, packet):
return 'included: %s' % packet['filename']

View File

@ -885,10 +885,31 @@ class Inventory(object):
def validate_hostnames(self, hostnames):
if not hostnames:
raise MissingArgument(u._('host name(s)'))
raise MissingArgument(u._('Host name(s)'))
invalid_hosts = []
for hostname in hostnames:
if hostname not in self._hosts:
invalid_hosts.append(hostname)
if invalid_hosts:
raise NotInInventory(u._('Host'), invalid_hosts)
def validate_groupnames(self, groupnames):
if not groupnames:
raise MissingArgument(u._('Group name(s)'))
invalid_groups = []
for groupname in groupnames:
if groupname not in self._groups:
invalid_groups.append(groupname)
if invalid_groups:
raise NotInInventory(u._('Group'), invalid_groups)
def validate_servicenames(self, servicenames):
if not servicenames:
raise MissingArgument(u._('Service name(s)'))
invalid_services = []
for servicename in servicenames:
if (servicename not in self._services and
servicename not in self._sub_services):
invalid_services.append(servicename)
if invalid_services:
raise NotInInventory(u._('Service'), invalid_services)