ddf5c8fe6a
Fix declaration of ajax_console_proxy_port flag. Change-Id: If949878a81339def2be5dba67ad1415180db4715
477 lines
17 KiB
Python
477 lines
17 KiB
Python
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
|
|
|
# Copyright 2010 United States Government as represented by the
|
|
# Administrator of the National Aeronautics and Space Administration.
|
|
# All Rights Reserved.
|
|
# Copyright 2011 Red Hat, Inc.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
# not use this file except in compliance with the License. You may obtain
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
# under the License.
|
|
|
|
"""Command-line flag library.
|
|
|
|
Emulates gflags by wrapping optparse.
|
|
|
|
The idea is to move to optparse eventually, and this wrapper is a
|
|
stepping stone.
|
|
|
|
"""
|
|
|
|
import optparse
|
|
import os
|
|
import socket
|
|
import string
|
|
import sys
|
|
|
|
import gflags
|
|
|
|
|
|
class FlagValues(object):
|
|
class Flag:
|
|
def __init__(self, name, value, update_default=None):
|
|
self.name = name
|
|
self.value = value
|
|
self._update_default = update_default
|
|
|
|
def SetDefault(self, default):
|
|
if self._update_default:
|
|
self._update_default(self.name, default)
|
|
|
|
class ErrorCatcher:
|
|
def __init__(self, orig_error):
|
|
self.orig_error = orig_error
|
|
self.reset()
|
|
|
|
def reset(self):
|
|
self._error_msg = None
|
|
|
|
def catch(self, msg):
|
|
if ": --" in msg:
|
|
self._error_msg = msg
|
|
else:
|
|
self.orig_error(msg)
|
|
|
|
def get_unknown_arg(self, args):
|
|
if not self._error_msg:
|
|
return None
|
|
# Error message is e.g. "no such option: --runtime_answer"
|
|
a = self._error_msg[self._error_msg.rindex(": --") + 2:]
|
|
return filter(lambda i: i == a or i.startswith(a + "="), args)[0]
|
|
|
|
def __init__(self, extra_context=None):
|
|
self._parser = optparse.OptionParser()
|
|
self._parser.disable_interspersed_args()
|
|
self._extra_context = extra_context
|
|
self.Reset()
|
|
|
|
def _parse(self):
|
|
if not self._values is None:
|
|
return
|
|
|
|
args = gflags.FlagValues().ReadFlagsFromFiles(self._args)
|
|
|
|
values = extra = None
|
|
|
|
#
|
|
# This horrendous hack allows us to stop optparse
|
|
# exiting when it encounters an unknown option
|
|
#
|
|
error_catcher = self.ErrorCatcher(self._parser.error)
|
|
self._parser.error = error_catcher.catch
|
|
try:
|
|
while True:
|
|
error_catcher.reset()
|
|
|
|
(values, extra) = self._parser.parse_args(args)
|
|
|
|
unknown = error_catcher.get_unknown_arg(args)
|
|
if not unknown:
|
|
break
|
|
|
|
args.remove(unknown)
|
|
finally:
|
|
self._parser.error = error_catcher.orig_error
|
|
|
|
(self._values, self._extra) = (values, extra)
|
|
|
|
def __call__(self, argv):
|
|
self._args = argv[1:]
|
|
self._values = None
|
|
self._parse()
|
|
return [argv[0]] + self._extra
|
|
|
|
def __getattr__(self, name):
|
|
self._parse()
|
|
val = getattr(self._values, name)
|
|
if type(val) is str:
|
|
tmpl = string.Template(val)
|
|
context = [self, self._extra_context]
|
|
return tmpl.substitute(StrWrapper(context))
|
|
return val
|
|
|
|
def get(self, name, default):
|
|
value = getattr(self, name)
|
|
if value is not None: # value might be '0' or ""
|
|
return value
|
|
else:
|
|
return default
|
|
|
|
def __contains__(self, name):
|
|
self._parse()
|
|
return hasattr(self._values, name)
|
|
|
|
def _update_default(self, name, default):
|
|
self._parser.set_default(name, default)
|
|
self._values = None
|
|
|
|
def __iter__(self):
|
|
return self.FlagValuesDict().iterkeys()
|
|
|
|
def __getitem__(self, name):
|
|
self._parse()
|
|
if not self.__contains__(name):
|
|
return None
|
|
return self.Flag(name, getattr(self, name), self._update_default)
|
|
|
|
def Reset(self):
|
|
self._args = []
|
|
self._values = None
|
|
self._extra = None
|
|
|
|
def ParseNewFlags(self):
|
|
pass
|
|
|
|
def FlagValuesDict(self):
|
|
ret = {}
|
|
for opt in self._parser.option_list:
|
|
if opt.dest:
|
|
ret[opt.dest] = getattr(self, opt.dest)
|
|
return ret
|
|
|
|
def _add_option(self, name, default, help, prefix='--', **kwargs):
|
|
prefixed_name = prefix + name
|
|
for opt in self._parser.option_list:
|
|
if prefixed_name == opt.get_opt_string():
|
|
return
|
|
self._parser.add_option(prefixed_name, dest=name,
|
|
default=default, help=help, **kwargs)
|
|
self._values = None
|
|
|
|
def define_string(self, name, default, help):
|
|
self._add_option(name, default, help)
|
|
|
|
def define_integer(self, name, default, help):
|
|
self._add_option(name, default, help, type='int')
|
|
|
|
def define_float(self, name, default, help):
|
|
self._add_option(name, default, help, type='float')
|
|
|
|
def define_bool(self, name, default, help):
|
|
#
|
|
# FIXME(markmc): this doesn't support --boolflag=true/false/t/f/1/0
|
|
#
|
|
self._add_option(name, default, help, action='store_true')
|
|
self._add_option(name, default, help,
|
|
prefix="--no", action='store_false')
|
|
|
|
def define_list(self, name, default, help):
|
|
def parse_list(option, opt, value, parser):
|
|
setattr(self._parser.values, name, value.split(','))
|
|
self._add_option(name, default, help, type='string',
|
|
action='callback', callback=parse_list)
|
|
|
|
def define_multistring(self, name, default, help):
|
|
self._add_option(name, default, help, action='append')
|
|
|
|
FLAGS = FlagValues()
|
|
|
|
|
|
class StrWrapper(object):
|
|
"""Wrapper around FlagValues objects.
|
|
|
|
Wraps FlagValues objects for string.Template so that we're
|
|
sure to return strings.
|
|
|
|
"""
|
|
def __init__(self, context_objs):
|
|
self.context_objs = context_objs
|
|
|
|
def __getitem__(self, name):
|
|
for context in self.context_objs:
|
|
val = getattr(context, name, False)
|
|
if val:
|
|
return str(val)
|
|
raise KeyError(name)
|
|
|
|
|
|
def DEFINE_string(name, default, help, flag_values=FLAGS):
|
|
flag_values.define_string(name, default, help)
|
|
|
|
|
|
def DEFINE_integer(name, default, help, lower_bound=None, flag_values=FLAGS):
|
|
# FIXME(markmc): ignoring lower_bound
|
|
flag_values.define_integer(name, default, help)
|
|
|
|
|
|
def DEFINE_bool(name, default, help, flag_values=FLAGS):
|
|
flag_values.define_bool(name, default, help)
|
|
|
|
|
|
def DEFINE_boolean(name, default, help, flag_values=FLAGS):
|
|
DEFINE_bool(name, default, help, flag_values)
|
|
|
|
|
|
def DEFINE_list(name, default, help, flag_values=FLAGS):
|
|
flag_values.define_list(name, default, help)
|
|
|
|
|
|
def DEFINE_float(name, default, help, flag_values=FLAGS):
|
|
flag_values.define_float(name, default, help)
|
|
|
|
|
|
def DEFINE_multistring(name, default, help, flag_values=FLAGS):
|
|
flag_values.define_multistring(name, default, help)
|
|
|
|
|
|
class UnrecognizedFlag(Exception):
|
|
pass
|
|
|
|
|
|
def DECLARE(name, module_string, flag_values=FLAGS):
|
|
if module_string not in sys.modules:
|
|
__import__(module_string, globals(), locals())
|
|
if name not in flag_values:
|
|
raise UnrecognizedFlag('%s not defined by %s' % (name, module_string))
|
|
|
|
|
|
def DEFINE_flag(flag):
|
|
pass
|
|
|
|
|
|
class HelpFlag:
|
|
pass
|
|
|
|
|
|
class HelpshortFlag:
|
|
pass
|
|
|
|
|
|
class HelpXMLFlag:
|
|
pass
|
|
|
|
|
|
def _get_my_ip():
|
|
"""Returns the actual ip of the local machine."""
|
|
try:
|
|
csock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
|
csock.connect(('8.8.8.8', 80))
|
|
(addr, port) = csock.getsockname()
|
|
csock.close()
|
|
return addr
|
|
except socket.error as ex:
|
|
return "127.0.0.1"
|
|
|
|
|
|
# __GLOBAL FLAGS ONLY__
|
|
# Define any app-specific flags in their own files, docs at:
|
|
# http://code.google.com/p/python-gflags/source/browse/trunk/gflags.py#a9
|
|
DEFINE_string('my_ip', _get_my_ip(), 'host ip address')
|
|
DEFINE_list('region_list',
|
|
[],
|
|
'list of region=fqdn pairs separated by commas')
|
|
DEFINE_string('connection_type', 'libvirt', 'libvirt, xenapi or fake')
|
|
DEFINE_string('aws_access_key_id', 'admin', 'AWS Access ID')
|
|
DEFINE_string('aws_secret_access_key', 'admin', 'AWS Access Key')
|
|
# NOTE(sirp): my_ip interpolation doesn't work within nested structures
|
|
DEFINE_string('glance_host', _get_my_ip(), 'default glance host')
|
|
DEFINE_integer('glance_port', 9292, 'default glance port')
|
|
DEFINE_list('glance_api_servers',
|
|
['%s:%d' % (FLAGS.glance_host, FLAGS.glance_port)],
|
|
'list of glance api servers available to nova (host:port)')
|
|
DEFINE_integer('glance_num_retries', 0,
|
|
'The number of times to retry downloading an image from glance')
|
|
DEFINE_integer('s3_port', 3333, 's3 port')
|
|
DEFINE_string('s3_host', '$my_ip', 's3 host (for infrastructure)')
|
|
DEFINE_string('s3_dmz', '$my_ip', 's3 dmz ip (for instances)')
|
|
DEFINE_string('compute_topic', 'compute', 'the topic compute nodes listen on')
|
|
DEFINE_string('console_topic', 'console',
|
|
'the topic console proxy nodes listen on')
|
|
DEFINE_string('scheduler_topic', 'scheduler',
|
|
'the topic scheduler nodes listen on')
|
|
DEFINE_string('volume_topic', 'volume', 'the topic volume nodes listen on')
|
|
DEFINE_string('network_topic', 'network', 'the topic network nodes listen on')
|
|
DEFINE_string('ajax_console_proxy_topic', 'ajax_proxy',
|
|
'the topic ajax proxy nodes listen on')
|
|
DEFINE_string('ajax_console_proxy_url',
|
|
'http://127.0.0.1:8000',
|
|
'location of ajax console proxy, \
|
|
in the form "http://127.0.0.1:8000"')
|
|
DEFINE_integer('ajax_console_proxy_port',
|
|
8000, 'port that ajax_console_proxy binds')
|
|
DEFINE_string('vsa_topic', 'vsa', 'the topic that nova-vsa service listens on')
|
|
DEFINE_bool('verbose', False, 'show debug output')
|
|
DEFINE_boolean('fake_rabbit', False, 'use a fake rabbit')
|
|
DEFINE_bool('fake_network', False,
|
|
'should we use fake network devices and addresses')
|
|
DEFINE_string('rabbit_host', 'localhost', 'rabbit host')
|
|
DEFINE_integer('rabbit_port', 5672, 'rabbit port')
|
|
DEFINE_bool('rabbit_use_ssl', False, 'connect over SSL')
|
|
DEFINE_string('rabbit_userid', 'guest', 'rabbit userid')
|
|
DEFINE_string('rabbit_password', 'guest', 'rabbit password')
|
|
DEFINE_string('rabbit_virtual_host', '/', 'rabbit virtual host')
|
|
DEFINE_integer('rabbit_retry_interval', 1,
|
|
'rabbit connection retry interval to start')
|
|
DEFINE_integer('rabbit_retry_backoff', 2,
|
|
'rabbit connection retry backoff in seconds')
|
|
DEFINE_integer('rabbit_max_retries', 0,
|
|
'maximum rabbit connection attempts (0=try forever)')
|
|
DEFINE_string('control_exchange', 'nova', 'the main exchange to connect to')
|
|
DEFINE_boolean('rabbit_durable_queues', False, 'use durable queues')
|
|
DEFINE_list('enabled_apis', ['ec2', 'osapi'],
|
|
'list of APIs to enable by default')
|
|
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_multistring('osapi_extension',
|
|
['nova.api.openstack.contrib.standard_extensions'],
|
|
'osapi extension to load')
|
|
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.1/', 'suffix for openstack')
|
|
DEFINE_integer('osapi_max_limit', 1000,
|
|
'max number of items returned in a collection response')
|
|
|
|
DEFINE_string('default_project', 'openstack', 'default project for openstack')
|
|
DEFINE_string('default_image', 'ami-11111',
|
|
'default image to use, testing only')
|
|
DEFINE_string('default_instance_type', 'm1.small',
|
|
'default instance type to use, testing only')
|
|
DEFINE_string('null_kernel', 'nokernel',
|
|
'kernel image that indicates not to use a kernel,'
|
|
' but to use a raw disk image instead')
|
|
|
|
DEFINE_string('vpn_image_id', '0', 'image id for cloudpipe vpn server')
|
|
DEFINE_string('vpn_key_suffix',
|
|
'-vpn',
|
|
'Suffix to add to project name for vpn key and secgroups')
|
|
|
|
DEFINE_integer('auth_token_ttl', 3600, 'Seconds for auth tokens to linger')
|
|
|
|
DEFINE_string('state_path', os.path.join(os.path.dirname(__file__), '../'),
|
|
"Top-level directory for maintaining nova's state")
|
|
DEFINE_string('lock_path', os.path.join(os.path.dirname(__file__), '../'),
|
|
'Directory for lock files')
|
|
DEFINE_string('logdir', None, 'output to a per-service log file in named '
|
|
'directory')
|
|
DEFINE_string('logfile_mode', '0644', 'Default file mode of the logs.')
|
|
DEFINE_string('sqlite_db', 'nova.sqlite', 'file name for sqlite')
|
|
DEFINE_bool('sqlite_synchronous', True, 'Synchronous mode for sqlite')
|
|
DEFINE_string('sql_connection',
|
|
'sqlite:///$state_path/$sqlite_db',
|
|
'connection string for sql database')
|
|
DEFINE_integer('sql_idle_timeout',
|
|
3600,
|
|
'timeout for idle sql database connections')
|
|
DEFINE_integer('sql_max_retries', 12, 'sql connection attempts')
|
|
DEFINE_integer('sql_retry_interval', 10, 'sql connection retry interval')
|
|
|
|
DEFINE_string('compute_manager', 'nova.compute.manager.ComputeManager',
|
|
'Manager for compute')
|
|
DEFINE_string('console_manager', 'nova.console.manager.ConsoleProxyManager',
|
|
'Manager for console proxy')
|
|
DEFINE_string('network_manager', 'nova.network.manager.VlanManager',
|
|
'Manager for network')
|
|
DEFINE_string('volume_manager', 'nova.volume.manager.VolumeManager',
|
|
'Manager for volume')
|
|
DEFINE_string('scheduler_manager', 'nova.scheduler.manager.SchedulerManager',
|
|
'Manager for scheduler')
|
|
DEFINE_string('vsa_manager', 'nova.vsa.manager.VsaManager',
|
|
'Manager for vsa')
|
|
DEFINE_string('vc_image_name', 'vc_image',
|
|
'the VC image ID (for a VC image that exists in DB Glance)')
|
|
# VSA constants and enums
|
|
DEFINE_string('default_vsa_instance_type', 'm1.small',
|
|
'default instance type for VSA instances')
|
|
DEFINE_integer('max_vcs_in_vsa', 32,
|
|
'maxinum VCs in a VSA')
|
|
DEFINE_integer('vsa_part_size_gb', 100,
|
|
'default partition size for shared capacity')
|
|
|
|
# The service to use for image search and retrieval
|
|
DEFINE_string('image_service', 'nova.image.glance.GlanceImageService',
|
|
'The service to use for retrieving and searching for images.')
|
|
|
|
DEFINE_string('host', socket.gethostname(),
|
|
'name of this node')
|
|
|
|
DEFINE_string('node_availability_zone', 'nova',
|
|
'availability zone of this node')
|
|
|
|
DEFINE_string('notification_driver',
|
|
'nova.notifier.no_op_notifier',
|
|
'Default driver for sending notifications')
|
|
DEFINE_list('memcached_servers', None,
|
|
'Memcached servers or None for in process cache.')
|
|
|
|
DEFINE_string('zone_name', 'nova', 'name of this zone')
|
|
DEFINE_list('zone_capabilities',
|
|
['hypervisor=xenserver;kvm', 'os=linux;windows'],
|
|
'Key/Multi-value list representng capabilities of this zone')
|
|
DEFINE_string('build_plan_encryption_key', None,
|
|
'128bit (hex) encryption key for scheduler build plans.')
|
|
DEFINE_string('instance_usage_audit_period', 'month',
|
|
'time period to generate instance usages for.')
|
|
DEFINE_integer('bandwith_poll_interval', 600,
|
|
'interval to pull bandwidth usage info')
|
|
|
|
DEFINE_bool('start_guests_on_host_boot', False,
|
|
'Whether to restart guests when the host reboots')
|
|
DEFINE_bool('resume_guests_state_on_host_boot', False,
|
|
'Whether to start guests, that was running before the host reboot')
|
|
|
|
DEFINE_string('root_helper', 'sudo',
|
|
'Command prefix to use for running commands as root')
|
|
|
|
DEFINE_string('network_driver', 'nova.network.linux_net',
|
|
'Driver to use for network creation')
|
|
|
|
DEFINE_bool('use_ipv6', False, 'use ipv6')
|
|
|
|
DEFINE_integer('password_length', 12,
|
|
'Length of generated instance admin passwords')
|
|
|
|
DEFINE_bool('monkey_patch', False,
|
|
'Whether to log monkey patching')
|
|
|
|
DEFINE_list('monkey_patch_modules',
|
|
['nova.api.ec2.cloud:nova.notifier.api.notify_decorator',
|
|
'nova.compute.api:nova.notifier.api.notify_decorator'],
|
|
'Module list representing monkey '
|
|
'patched module and decorator')
|
|
|
|
DEFINE_bool('allow_resize_to_same_host', False,
|
|
'Allow destination machine to match source for resize. Useful'
|
|
' when testing in environments with only one host machine.')
|
|
|
|
DEFINE_string('stub_network', False,
|
|
'Stub network related code')
|
|
|
|
DEFINE_integer('reclaim_instance_interval', 0,
|
|
'Interval in seconds for reclaiming deleted instances')
|
|
|
|
DEFINE_integer('zombie_instance_updated_at_window', 172800,
|
|
'Limit in seconds that a zombie instance can exist before '
|
|
'being cleaned up.')
|