Mgmt instances.

This commit is contained in:
Sudarshan Acharya 2012-06-18 13:26:46 -05:00 committed by Tim Simpson
parent af66968890
commit 7cd37cb0d3
5 changed files with 143 additions and 48 deletions

View File

@ -52,7 +52,8 @@ class Mgmt(extensions.ExtensionsDescriptor):
service.MgmtInstanceController(),
deserializer=wsgi.ReddwarfRequestDeserializer(),
serializer=serializer,
member_actions={'root': 'GET'},
member_actions={'root': 'GET',
'diagnostics': 'GET'},
)
resources.append(instances)
hosts = extensions.ResourceExtension('{tenant_id}/mgmt/hosts',

View File

@ -15,35 +15,58 @@
import logging
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.models import load_instance
from reddwarf.instance import models as instance_models
CONFIG = config.Config
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)
self.server = kwargs['server']
def load_mgmt_instances(context):
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
def host(self):
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):
def __init__(self, *args, **kwargs):
super(MgmtInstances, self).__init__(*args, **kwargs)
@staticmethod
def load_status_from_existing(context, db_infos, servers):
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:
raise TypeError("Argument context not defined.")
@ -69,3 +92,7 @@ class Server(object):
self.status = server['status']
self.name = server['name']
self.host = server['host']
if 'deleted' in server:
self.deleted = server['deleted']
if 'deleted_at' in server:
self.deleted_at = server['deleted_at']

View File

@ -18,12 +18,17 @@
import logging
import webob.exc
from novaclient import exceptions as nova_exceptions
from reddwarf.common import exception
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.extensions.mgmt import views
from reddwarf.extensions.mysql import models as mysql_models
from reddwarf.instance.service import InstanceController
from reddwarf.common.remote import create_nova_client
LOG = logging.getLogger(__name__)
@ -35,13 +40,17 @@ class MgmtInstanceController(InstanceController):
"""Return all instances."""
LOG.info(_("req : '%s'\n\n") % req)
LOG.info(_("Indexing a database instance for tenant '%s'") % tenant_id)
# TODO(sacharya): Load all servers from nova?
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
return wsgi.Result(view_cls(servers,
add_addresses=self.add_addresses).data(), 200)
view_cls = views.MgmtInstancesView
return wsgi.Result(view_cls(instances, req=req,
add_addresses=self.add_addresses,
add_volumes=self.add_volumes).data(), 200)
def show(self, req, tenant_id, id):
"""Return a single instance."""
@ -51,12 +60,16 @@ class MgmtInstanceController(InstanceController):
context = req.environ[wsgi.CONTEXT_KEY]
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:
LOG.error(e)
return wsgi.Result(str(e), 404)
return wsgi.Result(views.InstanceView(server,
add_addresses=self.add_addresses).data(), 200)
return wsgi.Result(views.MgmtInstanceDetailView(server, req=req,
add_addresses=self.add_addresses,
add_volumes=self.add_volumes,
root_history=root_history).data(), 200)
def root(self, req, tenant_id, id):
"""Return the date and time root was enabled on an instance,
@ -78,3 +91,18 @@ class MgmtInstanceController(InstanceController):
else:
rhv = views.RootHistoryView(id)
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)

View File

@ -16,47 +16,66 @@
# under the License.
from collections import defaultdict
from reddwarf.instance.views import InstanceDetailView
def tree():
return defaultdict(tree)
def get_ip_address(addresses):
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']]
class MgmtInstanceView(InstanceDetailView):
class InstanceView(object):
def __init__(self, instance, add_addresses=False):
self.instance = instance
self.add_addresses = add_addresses
def __init__(self, instance, req=None, add_addresses=False,
add_volumes=False):
super(MgmtInstanceView, self).__init__(instance, req,
add_addresses,
add_volumes)
def data(self):
ip = get_ip_address(self.instance.addresses)
instance_dict = {
"tenant_id": self.instance.server.tenant_id,
"id": self.instance.id,
"name": self.instance.name,
"status": self.instance.status,
"links": self.instance.links,
"created": self.instance.created,
"flavor": self.instance.flavor,
"updated": self.instance.updated
result = super(MgmtInstanceView, self).data()
result['instance']['server_id'] = self.instance.server_id
result['instance']['host'] = self.instance.host
result['instance']['tenant_id'] = self.instance.tenant_id
result['instance']['deleted'] = self.instance.deleted
result['instance']['deleted_at'] = self.instance.deleted_at
return result
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:
instance_dict['ip'] = ip
return {"instance": instance_dict}
result['instance']['guest_status'] = {
"state_description": self.instance.service_status.status.description
}
return result
class MgmtInstancesView(object):
"""Shows a list of MgmtInstance objects."""
class InstancesView(InstanceView):
def __init__(self, instances, add_addresses=False):
def __init__(self, instances, req=None, add_addresses= False, add_volumes=False):
self.instances = instances
self.req = req
self.add_addresses = add_addresses
self.add_volumes = add_volumes
def data(self):
data = []
@ -66,8 +85,10 @@ class InstancesView(InstanceView):
return {'instances': data}
def data_for_instance(self, instance):
return InstanceView(instance,
self.add_addresses).data()['instance']
view = MgmtInstanceView(instance, req=self.req,
add_addresses=self.add_addresses,
add_volumes=self.add_volumes)
return view.data()['instance']
class RootHistoryView(object):
@ -83,3 +104,20 @@ class RootHistoryView(object):
res['root_history']['enabled'] = self.enabled
res['root_history']['user'] = self.user
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

View File

@ -114,7 +114,8 @@ class SimpleInstance(object):
@property
def addresses(self):
#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
def created(self):