Mgmt instances.
This commit is contained in:

committed by
Tim Simpson

parent
af66968890
commit
7cd37cb0d3
@@ -52,7 +52,8 @@ class Mgmt(extensions.ExtensionsDescriptor):
|
|||||||
service.MgmtInstanceController(),
|
service.MgmtInstanceController(),
|
||||||
deserializer=wsgi.ReddwarfRequestDeserializer(),
|
deserializer=wsgi.ReddwarfRequestDeserializer(),
|
||||||
serializer=serializer,
|
serializer=serializer,
|
||||||
member_actions={'root': 'GET'},
|
member_actions={'root': 'GET',
|
||||||
|
'diagnostics': 'GET'},
|
||||||
)
|
)
|
||||||
resources.append(instances)
|
resources.append(instances)
|
||||||
hosts = extensions.ResourceExtension('{tenant_id}/mgmt/hosts',
|
hosts = extensions.ResourceExtension('{tenant_id}/mgmt/hosts',
|
||||||
|
@@ -15,35 +15,58 @@
|
|||||||
import logging
|
import logging
|
||||||
|
|
||||||
from reddwarf.common import config
|
from reddwarf.common import config
|
||||||
from reddwarf.common import exception
|
from reddwarf.common.remote import create_nova_client
|
||||||
from reddwarf.instance import models as imodels
|
from reddwarf.instance import models as imodels
|
||||||
|
from reddwarf.instance.models import load_instance
|
||||||
|
from reddwarf.instance import models as instance_models
|
||||||
|
|
||||||
|
|
||||||
CONFIG = config.Config
|
CONFIG = config.Config
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class MgmtInstance(imodels.SimpleInstance):
|
def load_mgmt_instance(cls, context, id):
|
||||||
|
instance = load_instance(cls, context, id, needs_server=True)
|
||||||
|
return instance
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
super(MgmtInstance, self).__init__(*args)
|
def load_mgmt_instances(context):
|
||||||
self.server = kwargs['server']
|
client = create_nova_client(context)
|
||||||
|
mgmt = client.mgmt.get_servers()
|
||||||
|
db_infos = instance_models.DBInstance.find_all()
|
||||||
|
instances = MgmtInstances.load_status_from_existing(context,
|
||||||
|
db_infos, mgmt.servers)
|
||||||
|
return instances
|
||||||
|
|
||||||
|
|
||||||
|
class SimpleMgmtInstance(imodels.BaseInstance):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def host(self):
|
def host(self):
|
||||||
return self.server.host if self.server else ""
|
return self.server.host if self.server else ""
|
||||||
|
|
||||||
|
@property
|
||||||
|
def deleted(self):
|
||||||
|
return self.server.deleted if self.server else ""
|
||||||
|
|
||||||
|
@property
|
||||||
|
def deleted_at(self):
|
||||||
|
return self.server.deleted_at if self.server else ""
|
||||||
|
|
||||||
|
|
||||||
|
class MgmtInstance(imodels.Instance):
|
||||||
|
|
||||||
|
def get_diagnostics(self):
|
||||||
|
return self.get_guest().get_diagnostics()
|
||||||
|
|
||||||
|
|
||||||
class MgmtInstances(imodels.Instances):
|
class MgmtInstances(imodels.Instances):
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
super(MgmtInstances, self).__init__(*args, **kwargs)
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def load_status_from_existing(context, db_infos, servers):
|
def load_status_from_existing(context, db_infos, servers):
|
||||||
|
|
||||||
def load_instance(context, db, status, server=None):
|
def load_instance(context, db, status, server=None):
|
||||||
return MgmtInstance(context, db, status, server=server)
|
return SimpleMgmtInstance(context, db, server, status)
|
||||||
|
|
||||||
if context is None:
|
if context is None:
|
||||||
raise TypeError("Argument context not defined.")
|
raise TypeError("Argument context not defined.")
|
||||||
@@ -69,3 +92,7 @@ class Server(object):
|
|||||||
self.status = server['status']
|
self.status = server['status']
|
||||||
self.name = server['name']
|
self.name = server['name']
|
||||||
self.host = server['host']
|
self.host = server['host']
|
||||||
|
if 'deleted' in server:
|
||||||
|
self.deleted = server['deleted']
|
||||||
|
if 'deleted_at' in server:
|
||||||
|
self.deleted_at = server['deleted_at']
|
||||||
|
@@ -18,12 +18,17 @@
|
|||||||
import logging
|
import logging
|
||||||
import webob.exc
|
import webob.exc
|
||||||
|
|
||||||
|
from novaclient import exceptions as nova_exceptions
|
||||||
|
|
||||||
from reddwarf.common import exception
|
from reddwarf.common import exception
|
||||||
from reddwarf.common import wsgi
|
from reddwarf.common import wsgi
|
||||||
|
from reddwarf.extensions.mgmt import models
|
||||||
|
from reddwarf.extensions.mgmt.views import DiagnosticsView
|
||||||
from reddwarf.instance import models as instance_models
|
from reddwarf.instance import models as instance_models
|
||||||
from reddwarf.extensions.mgmt import views
|
from reddwarf.extensions.mgmt import views
|
||||||
from reddwarf.extensions.mysql import models as mysql_models
|
from reddwarf.extensions.mysql import models as mysql_models
|
||||||
from reddwarf.instance.service import InstanceController
|
from reddwarf.instance.service import InstanceController
|
||||||
|
from reddwarf.common.remote import create_nova_client
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -35,13 +40,17 @@ class MgmtInstanceController(InstanceController):
|
|||||||
"""Return all instances."""
|
"""Return all instances."""
|
||||||
LOG.info(_("req : '%s'\n\n") % req)
|
LOG.info(_("req : '%s'\n\n") % req)
|
||||||
LOG.info(_("Indexing a database instance for tenant '%s'") % tenant_id)
|
LOG.info(_("Indexing a database instance for tenant '%s'") % tenant_id)
|
||||||
# TODO(sacharya): Load all servers from nova?
|
|
||||||
context = req.environ[wsgi.CONTEXT_KEY]
|
context = req.environ[wsgi.CONTEXT_KEY]
|
||||||
servers = instance_models.Instances.load(context)
|
try:
|
||||||
|
instances = models.load_mgmt_instances(context)
|
||||||
|
except nova_exceptions.ClientException, e:
|
||||||
|
LOG.error(e)
|
||||||
|
return wsgi.Result(str(e), 403)
|
||||||
|
|
||||||
view_cls = views.InstancesView
|
view_cls = views.MgmtInstancesView
|
||||||
return wsgi.Result(view_cls(servers,
|
return wsgi.Result(view_cls(instances, req=req,
|
||||||
add_addresses=self.add_addresses).data(), 200)
|
add_addresses=self.add_addresses,
|
||||||
|
add_volumes=self.add_volumes).data(), 200)
|
||||||
|
|
||||||
def show(self, req, tenant_id, id):
|
def show(self, req, tenant_id, id):
|
||||||
"""Return a single instance."""
|
"""Return a single instance."""
|
||||||
@@ -51,12 +60,16 @@ class MgmtInstanceController(InstanceController):
|
|||||||
|
|
||||||
context = req.environ[wsgi.CONTEXT_KEY]
|
context = req.environ[wsgi.CONTEXT_KEY]
|
||||||
try:
|
try:
|
||||||
server = instance_models.Instance.load(context=context, id=id)
|
server = models.load_mgmt_instance(models.SimpleMgmtInstance, context, id)
|
||||||
|
root_history = mysql_models.RootHistory.load(context=context,
|
||||||
|
instance_id=id)
|
||||||
except exception.ReddwarfError, e:
|
except exception.ReddwarfError, e:
|
||||||
LOG.error(e)
|
LOG.error(e)
|
||||||
return wsgi.Result(str(e), 404)
|
return wsgi.Result(str(e), 404)
|
||||||
return wsgi.Result(views.InstanceView(server,
|
return wsgi.Result(views.MgmtInstanceDetailView(server, req=req,
|
||||||
add_addresses=self.add_addresses).data(), 200)
|
add_addresses=self.add_addresses,
|
||||||
|
add_volumes=self.add_volumes,
|
||||||
|
root_history=root_history).data(), 200)
|
||||||
|
|
||||||
def root(self, req, tenant_id, id):
|
def root(self, req, tenant_id, id):
|
||||||
"""Return the date and time root was enabled on an instance,
|
"""Return the date and time root was enabled on an instance,
|
||||||
@@ -78,3 +91,18 @@ class MgmtInstanceController(InstanceController):
|
|||||||
else:
|
else:
|
||||||
rhv = views.RootHistoryView(id)
|
rhv = views.RootHistoryView(id)
|
||||||
return wsgi.Result(rhv.data(), 200)
|
return wsgi.Result(rhv.data(), 200)
|
||||||
|
|
||||||
|
def diagnostics(self, req, tenant_id, id):
|
||||||
|
"""Return a single instance diagnostics."""
|
||||||
|
LOG.info(_("req : '%s'\n\n") % req)
|
||||||
|
LOG.info(_("Showing a instance diagnostics for instance '%s'") % id)
|
||||||
|
LOG.info(_("id : '%s'\n\n") % id)
|
||||||
|
|
||||||
|
context = req.environ[wsgi.CONTEXT_KEY]
|
||||||
|
try:
|
||||||
|
instance = models.MgmtInstance.load(context=context, id=id)
|
||||||
|
diagnostics = instance.get_diagnostics()
|
||||||
|
except exception.ReddwarfError, e:
|
||||||
|
LOG.error(e)
|
||||||
|
return wsgi.Result(str(e), 404)
|
||||||
|
return wsgi.Result(DiagnosticsView(id, diagnostics), 200)
|
||||||
|
@@ -16,47 +16,66 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
|
from reddwarf.instance.views import InstanceDetailView
|
||||||
|
|
||||||
|
|
||||||
def tree():
|
def tree():
|
||||||
return defaultdict(tree)
|
return defaultdict(tree)
|
||||||
|
|
||||||
|
|
||||||
def get_ip_address(addresses):
|
class MgmtInstanceView(InstanceDetailView):
|
||||||
if addresses is not None and \
|
|
||||||
addresses.get('private') is not None and \
|
|
||||||
len(addresses['private']) > 0:
|
|
||||||
return [addr.get('addr') for addr in addresses['private']]
|
|
||||||
|
|
||||||
|
def __init__(self, instance, req=None, add_addresses=False,
|
||||||
class InstanceView(object):
|
add_volumes=False):
|
||||||
|
super(MgmtInstanceView, self).__init__(instance, req,
|
||||||
def __init__(self, instance, add_addresses=False):
|
add_addresses,
|
||||||
self.instance = instance
|
add_volumes)
|
||||||
self.add_addresses = add_addresses
|
|
||||||
|
|
||||||
def data(self):
|
def data(self):
|
||||||
ip = get_ip_address(self.instance.addresses)
|
result = super(MgmtInstanceView, self).data()
|
||||||
instance_dict = {
|
result['instance']['server_id'] = self.instance.server_id
|
||||||
"tenant_id": self.instance.server.tenant_id,
|
result['instance']['host'] = self.instance.host
|
||||||
"id": self.instance.id,
|
result['instance']['tenant_id'] = self.instance.tenant_id
|
||||||
"name": self.instance.name,
|
result['instance']['deleted'] = self.instance.deleted
|
||||||
"status": self.instance.status,
|
result['instance']['deleted_at'] = self.instance.deleted_at
|
||||||
"links": self.instance.links,
|
return result
|
||||||
"created": self.instance.created,
|
|
||||||
"flavor": self.instance.flavor,
|
|
||||||
"updated": self.instance.updated
|
class MgmtInstanceDetailView(InstanceDetailView):
|
||||||
|
"""Works with a full-blown instance."""
|
||||||
|
|
||||||
|
def __init__(self, instance, req, add_addresses=False,
|
||||||
|
add_volumes=False, root_history=None):
|
||||||
|
super(MgmtInstanceDetailView, self).__init__(instance,
|
||||||
|
req=req,
|
||||||
|
add_addresses=add_addresses,
|
||||||
|
add_volumes=add_volumes)
|
||||||
|
self.root_history = root_history
|
||||||
|
|
||||||
|
def data(self):
|
||||||
|
result = super(MgmtInstanceDetailView, self).data()
|
||||||
|
result['instance']['server_id'] = self.instance.server_id
|
||||||
|
result['instance']['tenant_id'] = self.instance.tenant_id
|
||||||
|
if self.root_history:
|
||||||
|
result['instance']['root_enabled'] = self.root_history.created
|
||||||
|
result['instance']['root_enabled_by'] = self.root_history.user
|
||||||
|
result['instance']['volume'] = {
|
||||||
|
"id": self.instance.volume_id,
|
||||||
|
"size": self.instance.volume_size
|
||||||
}
|
}
|
||||||
if self.add_addresses and ip is not None and len(ip) > 0:
|
result['instance']['guest_status'] = {
|
||||||
instance_dict['ip'] = ip
|
"state_description": self.instance.service_status.status.description
|
||||||
return {"instance": instance_dict}
|
}
|
||||||
|
return result
|
||||||
|
|
||||||
|
class MgmtInstancesView(object):
|
||||||
|
"""Shows a list of MgmtInstance objects."""
|
||||||
|
|
||||||
class InstancesView(InstanceView):
|
def __init__(self, instances, req=None, add_addresses= False, add_volumes=False):
|
||||||
|
|
||||||
def __init__(self, instances, add_addresses=False):
|
|
||||||
self.instances = instances
|
self.instances = instances
|
||||||
|
self.req = req
|
||||||
self.add_addresses = add_addresses
|
self.add_addresses = add_addresses
|
||||||
|
self.add_volumes = add_volumes
|
||||||
|
|
||||||
def data(self):
|
def data(self):
|
||||||
data = []
|
data = []
|
||||||
@@ -66,8 +85,10 @@ class InstancesView(InstanceView):
|
|||||||
return {'instances': data}
|
return {'instances': data}
|
||||||
|
|
||||||
def data_for_instance(self, instance):
|
def data_for_instance(self, instance):
|
||||||
return InstanceView(instance,
|
view = MgmtInstanceView(instance, req=self.req,
|
||||||
self.add_addresses).data()['instance']
|
add_addresses=self.add_addresses,
|
||||||
|
add_volumes=self.add_volumes)
|
||||||
|
return view.data()['instance']
|
||||||
|
|
||||||
|
|
||||||
class RootHistoryView(object):
|
class RootHistoryView(object):
|
||||||
@@ -83,3 +104,20 @@ class RootHistoryView(object):
|
|||||||
res['root_history']['enabled'] = self.enabled
|
res['root_history']['enabled'] = self.enabled
|
||||||
res['root_history']['user'] = self.user
|
res['root_history']['user'] = self.user
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
class DiagnosticsView(object):
|
||||||
|
|
||||||
|
def __init__(self, instance_id, diagnostics):
|
||||||
|
self.instance_id = instance_id
|
||||||
|
self.diagnostics = diagnostics
|
||||||
|
|
||||||
|
def data(self):
|
||||||
|
res = tree()
|
||||||
|
res['diagnostics']['version'] = self.diagnostics.version
|
||||||
|
res['diagnostics']['threads'] = self.diagnostics.threads
|
||||||
|
res['diagnostics']['fdSize'] = self.diagnostics.fd_size
|
||||||
|
res['diagnostics']['vmSize'] = self.diagnostics.vm_size
|
||||||
|
res['diagnostics']['vmPeak'] = self.diagnostics.vm_peak
|
||||||
|
res['diagnostics']['vmRss'] = self.diagnostics.vm_rss
|
||||||
|
res['diagnostics']['vmHwm'] = self.diagnostics.vm_hwm
|
||||||
|
return res
|
||||||
|
@@ -114,7 +114,8 @@ class SimpleInstance(object):
|
|||||||
@property
|
@property
|
||||||
def addresses(self):
|
def addresses(self):
|
||||||
#TODO(tim.simpson): Review whether we should keep this... its a mess.
|
#TODO(tim.simpson): Review whether we should keep this... its a mess.
|
||||||
return self.db_info.addresses
|
if hasattr(self.db_info, 'addresses'):
|
||||||
|
return self.db_info.addresses
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def created(self):
|
def created(self):
|
||||||
|
Reference in New Issue
Block a user