Mgmt instances.
This commit is contained in:
parent
af66968890
commit
7cd37cb0d3
@ -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',
|
||||
|
@ -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']
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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):
|
||||
|
Loading…
Reference in New Issue
Block a user