Merge trunk and handle flagfiles with kid-gloves in nova-api. Rename some flags for clarity.
This commit is contained in:
commit
038c9c7663
1
Authors
1
Authors
@ -21,6 +21,7 @@ Jesse Andrews <anotherjesse@gmail.com>
|
||||
Joe Heck <heckj@mac.com>
|
||||
Joel Moore <joelbm24@gmail.com>
|
||||
Jonathan Bryce <jbryce@jbryce.com>
|
||||
Josh Durgin <joshd@hq.newdream.net>
|
||||
Josh Kearney <josh.kearney@rackspace.com>
|
||||
Joshua McKenty <jmckenty@gmail.com>
|
||||
Justin Santa Barbara <justin@fathomdb.com>
|
||||
|
57
bin/nova-api
57
bin/nova-api
@ -40,58 +40,47 @@ from nova import flags
|
||||
from nova import log as logging
|
||||
from nova import wsgi
|
||||
|
||||
logging.basicConfig()
|
||||
LOG = logging.getLogger('nova.api')
|
||||
LOG.setLevel(logging.DEBUG)
|
||||
LOG.addHandler(logging.StreamHandler())
|
||||
|
||||
FLAGS = flags.FLAGS
|
||||
|
||||
API_ENDPOINTS = ['ec2', 'openstack']
|
||||
API_ENDPOINTS = ['ec2', 'osapi']
|
||||
|
||||
|
||||
def load_configuration(paste_config):
|
||||
def load_configuration(paste_config, name):
|
||||
"""Load the paste configuration from the config file and return it."""
|
||||
config = None
|
||||
# Try each known name to get the global DEFAULTS, which will give ports
|
||||
for name in API_ENDPOINTS:
|
||||
try:
|
||||
config = deploy.appconfig("config:%s" % paste_config, name=name)
|
||||
except LookupError:
|
||||
pass
|
||||
if config:
|
||||
verbose = config.get('verbose', None)
|
||||
if verbose:
|
||||
FLAGS.verbose = int(verbose) == 1
|
||||
if FLAGS.verbose:
|
||||
logging.getLogger().setLevel(logging.DEBUG)
|
||||
return config
|
||||
LOG.debug(_("Paste config at %s has no secion for known apis"),
|
||||
paste_config)
|
||||
print _("Paste config at %s has no secion for any known apis") % \
|
||||
paste_config
|
||||
os.exit(1)
|
||||
|
||||
|
||||
def launch_api(paste_config_file, section, server, port, host):
|
||||
"""Launch an api server from the specified port and IP."""
|
||||
LOG.debug(_("Launching %s api on %s:%s"), section, host, port)
|
||||
app = deploy.loadapp('config:%s' % paste_config_file, name=section)
|
||||
server.start(app, int(port), host)
|
||||
except LookupError:
|
||||
return None
|
||||
|
||||
|
||||
def run_app(paste_config_file):
|
||||
LOG.debug(_("Using paste.deploy config at: %s"), configfile)
|
||||
config = load_configuration(paste_config_file)
|
||||
LOG.debug(_("Configuration: %r"), config)
|
||||
server = wsgi.Server()
|
||||
ip = config.get('host', '0.0.0.0')
|
||||
apps = []
|
||||
for api in API_ENDPOINTS:
|
||||
port = config.get("%s_port" % api, None)
|
||||
if not port:
|
||||
config = load_configuration(paste_config_file, api)
|
||||
if config is None:
|
||||
continue
|
||||
host = config.get("%s_host" % api, ip)
|
||||
launch_api(configfile, api, server, port, host)
|
||||
LOG.debug(_("All api servers launched, now waiting"))
|
||||
if int(config.get('verbose', 0)) == 1:
|
||||
FLAGS.verbose = True
|
||||
host = config.get("%s_host" % api, config.get('host', '0.0.0.0'))
|
||||
port = config.get("%s_port" % api, getattr(FLAGS, "%s_port" % api))
|
||||
setattr(FLAGS, "%s_host" % api, host)
|
||||
setattr(FLAGS, "%s_port" % api, port)
|
||||
LOG.info(_("Running %s API"), api)
|
||||
app = deploy.loadapp('config:%s' % paste_config_file, name=api)
|
||||
apps.append((app, int(port), host))
|
||||
if len(apps) == 0:
|
||||
LOG.error(_("No known API applications configured in %s."),
|
||||
paste_config_file)
|
||||
else:
|
||||
for app in apps:
|
||||
server.start(*app)
|
||||
server.wait()
|
||||
|
||||
|
||||
|
@ -44,7 +44,6 @@ from nova import wsgi
|
||||
|
||||
|
||||
FLAGS = flags.FLAGS
|
||||
flags.DEFINE_integer('osapi_port', 8774, 'OpenStack API port')
|
||||
flags.DEFINE_string('osapi_host', '0.0.0.0', 'OpenStack API host')
|
||||
flags.DEFINE_integer('ec2api_port', 8773, 'EC2 API port')
|
||||
flags.DEFINE_string('ec2api_host', '0.0.0.0', 'EC2 API host')
|
||||
|
@ -1,9 +1,5 @@
|
||||
[DEFAULT]
|
||||
verbose = 1
|
||||
ec2_port = 8773
|
||||
ec2_address = 0.0.0.0
|
||||
openstack_port = 8774
|
||||
openstack_address = 0.0.0.0
|
||||
|
||||
#######
|
||||
# EC2 #
|
||||
@ -64,13 +60,13 @@ paste.app_factory = nova.api.ec2.metadatarequesthandler:metadata_factory
|
||||
# Openstack #
|
||||
#############
|
||||
|
||||
[composite:openstack]
|
||||
[composite:osapi]
|
||||
use = egg:Paste#urlmap
|
||||
/: osversions
|
||||
/v1.0: openstackapi
|
||||
|
||||
[pipeline:openstackapi]
|
||||
pipeline = faultwrap auth ratelimit osapi
|
||||
pipeline = faultwrap auth ratelimit osapiapp
|
||||
|
||||
[filter:faultwrap]
|
||||
paste.filter_factory = nova.api.openstack:fault_wrapper_factory
|
||||
@ -81,7 +77,7 @@ paste.filter_factory = nova.api.openstack.auth:auth_factory
|
||||
[filter:ratelimit]
|
||||
paste.filter_factory = nova.api.openstack.ratelimiting:ratelimit_factory
|
||||
|
||||
[app:osapi]
|
||||
[app:osapiapp]
|
||||
paste.app_factory = nova.api.openstack:router_factory
|
||||
|
||||
[pipeline:osversions]
|
||||
|
@ -278,8 +278,7 @@ class Authorizer(wsgi.Middleware):
|
||||
return self.application
|
||||
else:
|
||||
LOG.audit(_("Unauthorized request for controller=%s "
|
||||
"and action=%s"), controller_name, action,
|
||||
context=context)
|
||||
"and action=%s"), controller, action, context=context)
|
||||
raise webob.exc.HTTPUnauthorized()
|
||||
|
||||
def _matches_any_role(self, context, roles):
|
||||
|
@ -263,15 +263,15 @@ class CloudController(object):
|
||||
name, _sep, host = region.partition('=')
|
||||
endpoint = '%s://%s:%s%s' % (FLAGS.ec2_prefix,
|
||||
host,
|
||||
FLAGS.cc_port,
|
||||
FLAGS.ec2_port,
|
||||
FLAGS.ec2_suffix)
|
||||
regions.append({'regionName': name,
|
||||
'regionEndpoint': endpoint})
|
||||
else:
|
||||
regions = [{'regionName': 'nova',
|
||||
'regionEndpoint': '%s://%s:%s%s' % (FLAGS.ec2_prefix,
|
||||
FLAGS.cc_host,
|
||||
FLAGS.cc_port,
|
||||
FLAGS.ec2_host,
|
||||
FLAGS.ec2_port,
|
||||
FLAGS.ec2_suffix)}]
|
||||
return {'regionInfo': regions}
|
||||
|
||||
|
@ -682,7 +682,7 @@ class AuthManager(object):
|
||||
region, _sep, region_host = item.partition("=")
|
||||
regions[region] = region_host
|
||||
else:
|
||||
regions = {'nova': FLAGS.cc_host}
|
||||
regions = {'nova': FLAGS.ec2_host}
|
||||
for region, host in regions.iteritems():
|
||||
rc = self.__generate_rc(user,
|
||||
pid,
|
||||
@ -727,28 +727,28 @@ class AuthManager(object):
|
||||
def __generate_rc(user, pid, use_dmz=True, host=None):
|
||||
"""Generate rc file for user"""
|
||||
if use_dmz:
|
||||
cc_host = FLAGS.cc_dmz
|
||||
ec2_host = FLAGS.ec2_dmz_host
|
||||
else:
|
||||
cc_host = FLAGS.cc_host
|
||||
ec2_host = FLAGS.ec2_host
|
||||
# NOTE(vish): Always use the dmz since it is used from inside the
|
||||
# instance
|
||||
s3_host = FLAGS.s3_dmz
|
||||
if host:
|
||||
s3_host = host
|
||||
cc_host = host
|
||||
ec2_host = host
|
||||
rc = open(FLAGS.credentials_template).read()
|
||||
rc = rc % {'access': user.access,
|
||||
'project': pid,
|
||||
'secret': user.secret,
|
||||
'ec2': '%s://%s:%s%s' % (FLAGS.ec2_prefix,
|
||||
cc_host,
|
||||
FLAGS.cc_port,
|
||||
FLAGS.ec2_suffix),
|
||||
'ec2': '%s://%s:%s%s' % (FLAGS.ec2_scheme,
|
||||
ec2_host,
|
||||
FLAGS.ec2_port,
|
||||
FLAGS.ec2_path),
|
||||
's3': 'http://%s:%s' % (s3_host, FLAGS.s3_port),
|
||||
'os': '%s://%s:%s%s' % (FLAGS.os_prefix,
|
||||
cc_host,
|
||||
FLAGS.cc_port,
|
||||
FLAGS.os_suffix),
|
||||
'os': '%s://%s:%s%s' % (FLAGS.osapi_scheme,
|
||||
ec2_host,
|
||||
FLAGS.osapi_port,
|
||||
FLAGS.osapi_path),
|
||||
'user': user.name,
|
||||
'nova': FLAGS.ca_file,
|
||||
'cert': FLAGS.credential_cert_file,
|
||||
|
@ -68,8 +68,8 @@ class CloudPipe(object):
|
||||
shellfile = open(FLAGS.boot_script_template, "r")
|
||||
s = string.Template(shellfile.read())
|
||||
shellfile.close()
|
||||
boot_script = s.substitute(cc_dmz=FLAGS.cc_dmz,
|
||||
cc_port=FLAGS.cc_port,
|
||||
boot_script = s.substitute(cc_dmz=FLAGS.ec2_dmz_host,
|
||||
cc_port=FLAGS.ec2_port,
|
||||
dmz_net=FLAGS.dmz_net,
|
||||
dmz_mask=FLAGS.dmz_mask,
|
||||
num_vpn=FLAGS.cnt_vpn_clients)
|
||||
|
@ -254,13 +254,15 @@ DEFINE_string('rabbit_virtual_host', '/', 'rabbit virtual host')
|
||||
DEFINE_integer('rabbit_retry_interval', 10, 'rabbit connection retry interval')
|
||||
DEFINE_integer('rabbit_max_retries', 12, 'rabbit connection attempts')
|
||||
DEFINE_string('control_exchange', 'nova', 'the main exchange to connect to')
|
||||
DEFINE_string('ec2_prefix', 'http', 'prefix for ec2')
|
||||
DEFINE_string('os_prefix', 'http', 'prefix for openstack')
|
||||
DEFINE_string('cc_host', '$my_ip', 'ip of api server')
|
||||
DEFINE_string('cc_dmz', '$my_ip', 'internal ip of api server')
|
||||
DEFINE_integer('cc_port', 8773, 'cloud controller port')
|
||||
DEFINE_string('ec2_suffix', '/services/Cloud', 'suffix for ec2')
|
||||
DEFINE_string('os_suffix', '/v1.0/', 'suffix for openstack')
|
||||
DEFINE_string('ec2_host', '$my_ip', 'ip of api server')
|
||||
DEFINE_string('ec2_dmz_host', '$my_ip', 'internal ip of api server')
|
||||
DEFINE_integer('ec2_port', 8773, 'cloud controller port')
|
||||
DEFINE_string('ec2_scheme', 'http', 'prefix for ec2')
|
||||
DEFINE_string('ec2_path', '/services/Cloud', 'suffix for ec2')
|
||||
DEFINE_string('osapi_host', '$my_ip', 'ip of api server')
|
||||
DEFINE_string('osapi_scheme', 'http', 'prefix for openstack')
|
||||
DEFINE_integer('osapi_port', 8774, 'OpenStack API port')
|
||||
DEFINE_string('osapi_path', '/v1.0/', 'suffix for openstack')
|
||||
|
||||
DEFINE_string('default_project', 'openstack', 'default project for openstack')
|
||||
DEFINE_string('default_image', 'ami-11111',
|
||||
|
@ -60,7 +60,7 @@ def metadata_forward():
|
||||
"""Create forwarding rule for metadata"""
|
||||
_confirm_rule("PREROUTING", "-t nat -s 0.0.0.0/0 "
|
||||
"-d 169.254.169.254/32 -p tcp -m tcp --dport 80 -j DNAT "
|
||||
"--to-destination %s:%s" % (FLAGS.cc_dmz, FLAGS.cc_port))
|
||||
"--to-destination %s:%s" % (FLAGS.ec2_dmz_host, FLAGS.ec2_port))
|
||||
|
||||
|
||||
def init_host():
|
||||
|
@ -243,11 +243,24 @@ class LibvirtConnection(object):
|
||||
def attach_volume(self, instance_name, device_path, mountpoint):
|
||||
virt_dom = self._conn.lookupByName(instance_name)
|
||||
mount_device = mountpoint.rpartition("/")[2]
|
||||
if device_path.startswith('/dev/'):
|
||||
xml = """<disk type='block'>
|
||||
<driver name='qemu' type='raw'/>
|
||||
<source dev='%s'/>
|
||||
<target dev='%s' bus='virtio'/>
|
||||
</disk>""" % (device_path, mount_device)
|
||||
elif ':' in device_path:
|
||||
(protocol, name) = device_path.split(':')
|
||||
xml = """<disk type='network'>
|
||||
<driver name='qemu' type='raw'/>
|
||||
<source protocol='%s' name='%s'/>
|
||||
<target dev='%s' bus='virtio'/>
|
||||
</disk>""" % (protocol,
|
||||
name,
|
||||
mount_device)
|
||||
else:
|
||||
raise exception.Invalid(_("Invalid device path %s") % device_path)
|
||||
|
||||
virt_dom.attachDevice(xml)
|
||||
|
||||
def _get_disk_xml(self, xml, device):
|
||||
|
@ -49,6 +49,8 @@ flags.DEFINE_string('iscsi_target_prefix', 'iqn.2010-10.org.openstack:',
|
||||
'prefix for iscsi volumes')
|
||||
flags.DEFINE_string('iscsi_ip_prefix', '127.0',
|
||||
'discover volumes on the ip that starts with this prefix')
|
||||
flags.DEFINE_string('rbd_pool', 'rbd',
|
||||
'the rbd pool in which volumes are stored')
|
||||
|
||||
|
||||
class VolumeDriver(object):
|
||||
@ -314,3 +316,58 @@ class FakeISCSIDriver(ISCSIDriver):
|
||||
"""Execute that simply logs the command."""
|
||||
LOG.debug(_("FAKE ISCSI: %s"), cmd)
|
||||
return (None, None)
|
||||
|
||||
|
||||
class RBDDriver(VolumeDriver):
|
||||
"""Implements RADOS block device (RBD) volume commands"""
|
||||
|
||||
def check_for_setup_error(self):
|
||||
"""Returns an error if prerequisites aren't met"""
|
||||
(stdout, stderr) = self._execute("rados lspools")
|
||||
pools = stdout.split("\n")
|
||||
if not FLAGS.rbd_pool in pools:
|
||||
raise exception.Error(_("rbd has no pool %s") %
|
||||
FLAGS.rbd_pool)
|
||||
|
||||
def create_volume(self, volume):
|
||||
"""Creates a logical volume."""
|
||||
if int(volume['size']) == 0:
|
||||
size = 100
|
||||
else:
|
||||
size = int(volume['size']) * 1024
|
||||
self._try_execute("rbd --pool %s --size %d create %s" %
|
||||
(FLAGS.rbd_pool,
|
||||
size,
|
||||
volume['name']))
|
||||
|
||||
def delete_volume(self, volume):
|
||||
"""Deletes a logical volume."""
|
||||
self._try_execute("rbd --pool %s rm %s" %
|
||||
(FLAGS.rbd_pool,
|
||||
volume['name']))
|
||||
|
||||
def local_path(self, volume):
|
||||
"""Returns the path of the rbd volume."""
|
||||
# This is the same as the remote path
|
||||
# since qemu accesses it directly.
|
||||
return self.discover_volume(volume)
|
||||
|
||||
def ensure_export(self, context, volume):
|
||||
"""Synchronously recreates an export for a logical volume."""
|
||||
pass
|
||||
|
||||
def create_export(self, context, volume):
|
||||
"""Exports the volume"""
|
||||
pass
|
||||
|
||||
def remove_export(self, context, volume):
|
||||
"""Removes an export for a logical volume"""
|
||||
pass
|
||||
|
||||
def discover_volume(self, volume):
|
||||
"""Discover volume on a remote host"""
|
||||
return "rbd:%s/%s" % (FLAGS.rbd_pool, volume['name'])
|
||||
|
||||
def undiscover_volume(self, volume):
|
||||
"""Undiscover volume on a remote host"""
|
||||
pass
|
||||
|
Loading…
Reference in New Issue
Block a user