# Service status description when status == -1.
self.status_desc = None
+ def to_json(self):
+ out = {
+ 'nodename': self.nodename,
+ 'container_id': self.container_id,
+ 'daemon_name': self.daemon_name,
+ 'service_type': self.service_type,
+ 'version': self.version,
+ 'rados_config_location': self.rados_config_location,
+ 'service_url': self.service_url,
+ 'status': self.status,
+ 'status_desc': self.status_desc,
+ }
+ return {k:v for (k,v) in out.items() if v is not None}
+
class DriveGroupSpec(object):
"""
# how much space is available.
self.metadata_space_free = None
+ def to_json(self):
+ return dict(type=self.type, blank=self.blank, id=self.id, size=self.size, **self.extended)
+
class InventoryNode(object):
+ """
+ When fetching inventory, all Devices are groups inside of an
+ InventoryNode.
+ """
def __init__(self, name, devices):
assert isinstance(devices, list)
self.name = name # unique within cluster. For example a hostname.
- self.devices = devices # list of InventoryDevice
+ self.devices = devices # type: List[InventoryDevice]
+
+ def to_json(self):
+ return {'name': self.name, 'devices': [d.to_json() for d in self.devices]}
import errno
+import json
import time
from mgr_module import MgrModule, HandleCommandResult
COMMANDS = [
{
'cmd': "orchestrator device ls "
- "name=node,type=CephString,req=false",
+ "name=host,type=CephString,req=false"
+ "name=format,type=CephChoices,strings=json|plain,req=false ",
"desc": "List devices on a node",
"perm": "r"
},
{
'cmd': "orchestrator service ls "
"name=host,type=CephString,req=false "
- "name=type,type=CephString,req=false ",
+ "name=svc_type,type=CephString,req=false "
+ "name=svc_id,type=CephString,req=false "
+ "name=format,type=CephChoices,strings=json|plain,req=false ",
"desc": "List services known to orchestrator" ,
"perm": "r"
},
{
'cmd': "orchestrator service status "
+ "name=host,type=CephString,req=false "
"name=svc_type,type=CephString "
- "name=svc_id,type=CephString ",
+ "name=svc_id,type=CephString "
+ "name=format,type=CephChoices,strings=json|plain,req=false ",
"desc": "Get orchestrator state for Ceph service",
"perm": "r"
},
date hardware inventory is fine as long as hardware ultimately appears
in the output of this command.
"""
- node = cmd.get('node', None)
+ host = cmd.get('host', None)
- if node:
+ if host:
nf = orchestrator.InventoryFilter()
- nf.nodes = [node]
+ nf.nodes = [host]
else:
nf = None
self._wait([completion])
- # Spit out a human readable version
- result = ""
-
- for inventory_node in completion.result:
- result += "{0}:\n".format(inventory_node.name)
- for d in inventory_node.devices:
- result += " {0} ({1}, {2}b)\n".format(
- d.id, d.type, d.size)
- result += "\n"
+ if cmd.get('format', 'plain') == 'json':
+ data = [n.to_json() for n in completion.result]
+ return HandleCommandResult(odata=json.dumps(data))
+ else:
+ # Return a human readable version
+ result = ""
+ for inventory_node in completion.result:
+ result += "{0}:\n".format(inventory_node.name)
+ for d in inventory_node.devices:
+ result += " {0} ({1}, {2}b)\n".format(
+ d.id, d.type, d.size)
+ result += "\n"
- return HandleCommandResult(odata=result)
+ return HandleCommandResult(odata=result)
def _list_services(self, cmd):
hostname = cmd.get('host', None)
- service_type = cmd.get('type', None)
+ svc_id = cmd.get('svc_id', None)
+ svc_type = cmd.get('svc_type', None)
+ # XXX this is kind of confusing for people because in the orchestrator
+ # context the service ID for MDS is the filesystem ID, not the daemon ID
+
+ completion = self._oremote("describe_service", svc_type, svc_id, hostname)
- completion = self._oremote("describe_service", service_type, None, hostname)
self._wait([completion])
+
services = completion.result
+ # Sort the list for display
+ services.sort(key=lambda s: (s.service_type, s.nodename, s.daemon_name))
+
if len(services) == 0:
return HandleCommandResult(rs="No services reported")
+ elif cmd.get('format', 'plain') == 'json':
+ data = [s.to_json() for s in services]
+ return HandleCommandResult(odata=json.dumps(data))
else:
- # Sort the list for display
- services.sort(key = lambda s: (s.service_type, s.nodename, s.daemon_name))
lines = []
for s in services:
lines.append("{0}.{1} {2} {3} {4} {5}".format(
return HandleCommandResult(odata="\n".join(lines))
- def _service_status(self, cmd):
- svc_type = cmd['svc_type']
- svc_id = cmd['svc_id']
-
- # XXX this is kind of confusing for people because in the orchestrator
- # context the service ID for MDS is the filesystem ID, not the daemon ID
-
- completion = self._oremote("describe_service", svc_type, svc_id, None)
-
- self._wait([completion])
-
- service_list = completion.result
-
- if len(service_list) == 0:
- return HandleCommandResult(rs="No locations reported")
- else:
- lines = []
- for l in service_list:
- lines.append("{0}.{1} {2} {3}".format(
- svc_type,
- l.daemon_name,
- l.nodename,
- l.container_id))
-
- return HandleCommandResult(odata="\n".join(lines))
-
def _service_add(self, cmd):
svc_type = cmd['svc_type']
if svc_type == "osd":
enabled = module['name'] in mgr_map['modules']
if not enabled:
return HandleCommandResult(-errno.EINVAL,
- rs="Module '{0}' is not enabled".format(module_name))
+ rs="Module '{module_name}' is not enabled. \n Run `ceph "
+ "mgr module enable {module_name}` "
+ "to enable.".format(module_name=module_name))
try:
is_orchestrator = self.remote(module_name,
elif cmd['prefix'] == "orchestrator service ls":
return self._list_services(cmd)
elif cmd['prefix'] == "orchestrator service status":
- return self._service_status(cmd)
+ return self._list_services(cmd) # TODO: create more detailed output
elif cmd['prefix'] == "orchestrator service add":
return self._service_add(cmd)
elif cmd['prefix'] == "orchestrator service rm":
return self._status()
else:
raise NotImplementedError()
+