Merge "Refactor server password metadata to avoid direct db usage"

This commit is contained in:
Jenkins 2013-02-06 01:00:30 +00:00 committed by Gerrit Code Review
commit bfd295daed
6 changed files with 39 additions and 16 deletions
nova
api
metadata
openstack/compute/contrib
tests
api/openstack/compute/contrib
test_metadata.py
virt/xenapi

@ -15,8 +15,9 @@
from webob import exc from webob import exc
from nova import conductor
from nova import context from nova import context
from nova import db from nova import utils
CHUNKS = 4 CHUNKS = 4
@ -33,7 +34,7 @@ def extract_password(instance):
return result or None return result or None
def set_password(context, instance_uuid, password): def convert_password(context, password):
"""Stores password as system_metadata items. """Stores password as system_metadata items.
Password is stored with the keys 'password_0' -> 'password_3'. Password is stored with the keys 'password_0' -> 'password_3'.
@ -43,10 +44,7 @@ def set_password(context, instance_uuid, password):
for i in xrange(CHUNKS): for i in xrange(CHUNKS):
meta['password_%d' % i] = password[:CHUNK_LENGTH] meta['password_%d' % i] = password[:CHUNK_LENGTH]
password = password[CHUNK_LENGTH:] password = password[CHUNK_LENGTH:]
db.instance_system_metadata_update(context, return meta
instance_uuid,
meta,
False)
def handle_password(req, meta_data): def handle_password(req, meta_data):
@ -63,6 +61,12 @@ def handle_password(req, meta_data):
if (req.content_length > MAX_SIZE or len(req.body) > MAX_SIZE): if (req.content_length > MAX_SIZE or len(req.body) > MAX_SIZE):
msg = _("Request is too large.") msg = _("Request is too large.")
raise exc.HTTPBadRequest(explanation=msg) raise exc.HTTPBadRequest(explanation=msg)
set_password(ctxt, meta_data.uuid, req.body)
conductor_api = conductor.API()
instance = conductor_api.instance_get_by_uuid(ctxt, meta_data.uuid)
sys_meta = utils.metadata_to_dict(instance['system_metadata'])
sys_meta.update(convert_password(ctxt, req.body))
conductor_api.instance_update(ctxt, meta_data.uuid,
system_metadata=sys_meta)
else: else:
raise exc.HTTPBadRequest() raise exc.HTTPBadRequest()

@ -24,6 +24,7 @@ from nova.api.openstack import extensions
from nova.api.openstack import wsgi from nova.api.openstack import wsgi
from nova.api.openstack import xmlutil from nova.api.openstack import xmlutil
from nova import compute from nova import compute
from nova import db
from nova import exception from nova import exception
@ -62,7 +63,9 @@ class ServerPasswordController(object):
context = req.environ['nova.context'] context = req.environ['nova.context']
authorize(context) authorize(context)
instance = self._get_instance(context, server_id) instance = self._get_instance(context, server_id)
password.set_password(context, instance['uuid'], None) meta = password.convert_password(context, None)
db.instance_system_metadata_update(context, instance['uuid'],
meta, False)
class Server_password(extensions.ExtensionDescriptor): class Server_password(extensions.ExtensionDescriptor):

@ -40,11 +40,12 @@ class ServerPasswordTest(test.TestCase):
def fake_extract_password(instance): def fake_extract_password(instance):
return self.password return self.password
def fake_set_password(context, instance_uuid, password): def fake_convert_password(context, password):
self.password = password self.password = password
return {}
self.stubs.Set(password, 'extract_password', fake_extract_password) self.stubs.Set(password, 'extract_password', fake_extract_password)
self.stubs.Set(password, 'set_password', fake_set_password) self.stubs.Set(password, 'convert_password', fake_convert_password)
self.flags( self.flags(
osapi_compute_extension=[ osapi_compute_extension=[
'nova.api.openstack.compute.contrib.select_extensions'], 'nova.api.openstack.compute.contrib.select_extensions'],

@ -549,6 +549,7 @@ class MetadataPasswordTestCase(test.TestCase):
self.instance = copy.copy(INSTANCES[0]) self.instance = copy.copy(INSTANCES[0])
self.mdinst = fake_InstanceMetadata(self.stubs, self.instance, self.mdinst = fake_InstanceMetadata(self.stubs, self.instance,
address=None, sgroups=None) address=None, sgroups=None)
self.flags(use_local=True, group='conductor')
def test_get_password(self): def test_get_password(self):
request = webob.Request.blank('') request = webob.Request.blank('')
@ -566,8 +567,16 @@ class MetadataPasswordTestCase(test.TestCase):
request = webob.Request.blank('') request = webob.Request.blank('')
request.method = 'POST' request.method = 'POST'
request.body = val request.body = val
self.stubs.Set(db, 'instance_system_metadata_update', self.stubs.Set(db, 'instance_get_by_uuid',
lambda *a, **kw: None) lambda *a, **kw: {'system_metadata': []})
def fake_instance_update(context, uuid, updates):
self.assertIn('system_metadata', updates)
self.assertIn('password_0', updates['system_metadata'])
return self.instance, self.instance
self.stubs.Set(db, 'instance_update_and_get_original',
fake_instance_update)
password.handle_password(request, self.mdinst) password.handle_password(request, self.mdinst)
def test_set_password(self): def test_set_password(self):

@ -123,8 +123,9 @@ def _get_agent_version(session, instance, vm_ref):
class XenAPIBasedAgent(object): class XenAPIBasedAgent(object):
def __init__(self, session, instance, vm_ref): def __init__(self, session, virtapi, instance, vm_ref):
self.session = session self.session = session
self.virtapi = virtapi
self.instance = instance self.instance = instance
self.vm_ref = vm_ref self.vm_ref = vm_ref
@ -212,9 +213,13 @@ class XenAPIBasedAgent(object):
sshkey = self.instance.get('key_data') sshkey = self.instance.get('key_data')
if sshkey: if sshkey:
ctxt = context.get_admin_context()
enc = crypto.ssh_encrypt_text(sshkey, new_pass) enc = crypto.ssh_encrypt_text(sshkey, new_pass)
password.set_password(context.get_admin_context(), sys_meta = utils.metadata_to_dict(self.instance['system_metadata'])
self.instance['uuid'], base64.b64encode(enc)) sys_meta.update(password.convert_password(ctxt,
base64.b64encode(enc)))
self.virtapi.instance_update(ctxt, self.instance['uuid'],
{'system_metadata': sys_meta})
return resp['message'] return resp['message']

@ -176,7 +176,8 @@ class VMOps(object):
def _get_agent(self, instance, vm_ref): def _get_agent(self, instance, vm_ref):
if self.agent_enabled: if self.agent_enabled:
return xapi_agent.XenAPIBasedAgent(self._session, instance, vm_ref) return xapi_agent.XenAPIBasedAgent(self._session, self._virtapi,
instance, vm_ref)
raise exception.NovaException(_("Error: Agent is disabled")) raise exception.NovaException(_("Error: Agent is disabled"))
def list_instances(self): def list_instances(self):