Fixes cloudpipe extension to work with keystone

* Removes deprecated auth from cloudpipe extension
 * Fixes pipelib to not use ec2_api
 * Changes vpn_image_id to be a uuid
 * Uses network api to retrieve information
 * Simplifies cloudpipe tests
 * Removes nova-manage cloudpipe launching
 * Removes related unused db methods
 * Fixes bug 940744

Change-Id: I5fd1fb49a9e11b89062aa754501fed29874cb6ee
This commit is contained in:
Vishvananda Ishaya
2012-02-24 18:29:34 -08:00
parent e60398ba2c
commit 8da178d7f7
10 changed files with 149 additions and 271 deletions

View File

@@ -16,6 +16,7 @@
import os
from nova.api.openstack import common
from nova.api.openstack import wsgi
from nova.api.openstack import xmlutil
from nova.api.openstack import extensions
@@ -27,6 +28,7 @@ from nova import db
from nova import exception
from nova import flags
from nova import log as logging
from nova import network
from nova import utils
@@ -54,6 +56,7 @@ class CloudpipeController(object):
def __init__(self):
self.compute_api = compute.API()
self.network_api = network.API()
self.auth_manager = manager.AuthManager()
self.cloudpipe = pipelib.CloudPipe()
self.setup()
@@ -66,58 +69,76 @@ class CloudpipeController(object):
if not os.path.exists(FLAGS.keys_path):
os.makedirs(FLAGS.keys_path)
def _get_all_cloudpipes(self, context):
"""Get all cloudpipes"""
return [instance for instance in self.compute_api.get_all(context)
if instance['image_ref'] == str(FLAGS.vpn_image_id)
and instance['vm_state'] != vm_states.DELETED]
def _get_cloudpipe_for_project(self, context, project_id):
"""Get the cloudpipe instance for a project ID."""
# NOTE(todd): this should probably change to compute_api.get_all
# or db.instance_get_project_vpn
for instance in db.instance_get_all_by_project(context, project_id):
if (instance['image_id'] == str(FLAGS.vpn_image_id)
and instance['vm_state'] != vm_states.DELETED):
return instance
cloudpipes = self._get_all_cloudpipes(context) or [None]
return cloudpipes[0]
def _vpn_dict(self, project, vpn_instance):
rv = {'project_id': project.id,
'public_ip': project.vpn_ip,
'public_port': project.vpn_port}
if vpn_instance:
rv['instance_id'] = vpn_instance['uuid']
rv['created_at'] = utils.isotime(vpn_instance['created_at'])
address = vpn_instance.get('fixed_ip', None)
if address:
rv['internal_ip'] = address['address']
if project.vpn_ip and project.vpn_port:
if utils.vpn_ping(project.vpn_ip, project.vpn_port):
def _get_ip_and_port(self, instance):
pass
def _vpn_dict(self, context, project_id, instance):
elevated = context.elevated()
rv = {'project_id': project_id}
if not instance:
rv['state'] = 'pending'
return rv
rv['instance_id'] = instance['uuid']
rv['created_at'] = utils.isotime(instance['created_at'])
nw_info = common.get_nw_info_for_instance(elevated, instance)
if not nw_info:
return rv
vif = nw_info[0]
ips = [ip for ip in vif.fixed_ips() if ip['version'] == 4]
if ips:
rv['internal_ip'] = ips[0]['address']
network = self.network_api.get(elevated, vif['network']['id'])
if network:
vpn_ip = network['vpn_public_address']
vpn_port = network['vpn_public_port']
rv['public_ip'] = vpn_ip
rv['public_port'] = vpn_port
if vpn_ip and vpn_port:
if utils.vpn_ping(vpn_ip, vpn_port):
rv['state'] = 'running'
else:
rv['state'] = 'down'
else:
rv['state'] = 'invalid'
else:
rv['state'] = 'pending'
return rv
@wsgi.serializers(xml=CloudpipeTemplate)
def create(self, req, body):
"""Create a new cloudpipe instance, if none exists.
Parameters: {cloudpipe: {project_id: XYZ}}
Parameters: {cloudpipe: {'project_id': ''}}
"""
ctxt = req.environ['nova.context']
authorize(ctxt)
context = req.environ['nova.context']
authorize(context)
params = body.get('cloudpipe', {})
project_id = params.get('project_id', ctxt.project_id)
instance = self._get_cloudpipe_for_project(ctxt, project_id)
project_id = params.get('project_id', context.project_id)
# NOTE(vish): downgrade to project context. Note that we keep
# the same token so we can still talk to glance
context.project_id = project_id
context.user_id = 'project-vpn'
context.is_admin = False
context.roles = []
instance = self._get_cloudpipe_for_project(context, project_id)
if not instance:
proj = self.auth_manager.get_project(project_id)
user_id = proj.project_manager_id
try:
self.cloudpipe.launch_vpn_instance(project_id, user_id)
result = self.cloudpipe.launch_vpn_instance(context)
instance = result[0][0]
except db.NoMoreNetworks:
msg = _("Unable to claim IP for VPN instances, ensure it "
"isn't running, and try again in a few minutes")
raise exception.HTTPBadRequest(explanation=msg)
instance = self._get_cloudpipe_for_project(ctxt, proj)
return {'instance_id': instance['uuid']}
@wsgi.serializers(xml=CloudpipesTemplate)
@@ -125,11 +146,8 @@ class CloudpipeController(object):
"""List running cloudpipe instances."""
context = req.environ['nova.context']
authorize(context)
vpns = []
# TODO(todd): could use compute_api.get_all with admin context?
for project in self.auth_manager.get_projects():
instance = self._get_cloudpipe_for_project(context, project.id)
vpns.append(self._vpn_dict(project, instance))
vpns = [self._vpn_dict(context, x['project_id'], x)
for x in self._get_all_cloudpipes(context)]
return {'cloudpipes': vpns}