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(), 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',

View File

@@ -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']

View File

@@ -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)

View File

@@ -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

View File

@@ -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):