Cleaned up how nova is configured.

This commit is contained in:
Joshua Harlow 2012-01-20 17:00:23 -08:00
parent b850a406c1
commit 05677956dd
3 changed files with 228 additions and 169 deletions
conf
devstack/components

@ -27,6 +27,12 @@ type = mysql
[nova]
# Should nova be in verbose mode?
verbose = ${NOVA_VERBOSE:-1}
# Allow the admin api to be accessible?
allow_admin_api = 1
# Nova original used project_id as the *account* that owned resources (servers,
# ip address, ...) With the addition of Keystone we have standardized on the
# term **tenant** as the entity that owns the resources. **novaclient** still
@ -56,7 +62,7 @@ nova_url = ${NOVA_URL:-http://$HOST_IP:5000/v2.0/}
# needs to match the config of your catalog returned by Keystone.
nova_version = ${NOVA_VERSION:-1.1}
scheduler = ${NOVA_SCHEDULER:--nova.scheduler.simple.SimpleScheduler}
scheduler = ${NOVA_SCHEDULER:-nova.scheduler.simple.SimpleScheduler}
fixed_range = ${NOVA_FIXED_RANGE:-10.0.0.0/24}
network_manager = ${NET_MAN:-FlatDHCPManager}
volume_group = ${VOLUME_GROUP:-nova-volumes}

@ -13,27 +13,34 @@
# License for the specific language governing permissions and limitations
# under the License.
from devstack import component as comp
from devstack import constants
from devstack import constants as co
from devstack import log as logging
from devstack import shell as sh
from devstack import utils
from devstack.components import nova_conf as nc
LOG = logging.getLogger("devstack.components.nova")
API_CONF = "nova.conf"
CONFIGS = [API_CONF]
DB_NAME = "nova"
TYPE = constants.NOVA
#what to start
# Does this start nova-compute, nova-volume, nova-network, nova-scheduler
# and optionally nova-wsproxy?
#APP_OPTIONS = {
# 'glance-api': ['--config-file', joinpths('%ROOT%', "etc", API_CONF)],
# 'glance-registry': ['--config-file', joinpths('%ROOT%', "etc", REG_CONF)]
#}
API_CONF = "nova.conf"
PASTE_CONF = 'nova-api-paste.ini'
CONFIGS = [API_CONF]
DB_NAME = "nova"
BIN_DIR = 'bin'
TYPE = co.NOVA
QUANTUM_MANAGER = 'nova.network.quantum.manager.QuantumManager'
NET_MAN_TEMPL = 'nova.network.manager.%s'
IMG_SVC = 'nova.image.glance.GlanceImageService'
QUANTUM_OPENSWITCH_OPS = [
{
'libvirt_vif_type': ['ethernet'],
'libvirt_vif_driver': ['nova.virt.libvirt.vif.LibvirtOpenVswitchDriver'],
'linuxnet_interface_driver': ['nova.network.linux_net.LinuxOVSInterfaceDriver'],
'quantum_use_dhcp': [],
}
]
class NovaUninstaller(comp.PythonUninstallComponent):
@ -41,43 +48,184 @@ class NovaUninstaller(comp.PythonUninstallComponent):
comp.PythonUninstallComponent.__init__(self, TYPE, *args, **kargs)
#self.cfgdir = joinpths(self.appdir, CONFIG_ACTUAL_DIR)
class NovaConfigurator():
def __init__(self, cfg, active_components):
self.cfg = cfg
self.active_components = active_components
def _getbool(self, name):
return self.cfg.getboolean('nova', name)
def _getstr(self, name):
return self.cfg.get('nova', name)
def configure(self, dirs):
#TODO split up into sections??
nova_conf = nc.NovaConf()
hostip = utils.get_host_ip()
#verbose on?
if(self._getbool('verbose')):
nova_conf.add_simple('verbose')
#allow the admin api?
if(self._getbool('allow_admin_api')):
nova_conf.add_simple('allow_admin_api')
#which sheculder do u want
nova_conf.add('scheduler_driver', self._getstr('scheduler'))
#???
nova_conf.add('dhcpbridge_flagfile', utils.joinpths(dirs.get('bin'), API_CONF))
#whats the network fixed range?
nova_conf.add('fixed_range', self._getstr('fixed_range'))
if(co.QUANTUM in self.active_components):
#setup quantum config
nova_conf.add('network_manager', QUANTUM_MANAGER)
nova_conf.add('quantum_connection_host', self.cfg.get('quantum', 'q_host'))
nova_conf.add('quantum_connection_port', self.cfg.get('quantum', 'q_port'))
# TODO
#if ('q-svc' in self.othercomponents and
# self.cfg.get('quantum', 'q_plugin') == 'openvswitch'):
# self.lines.extend(QUANTUM_OPENSWITCH_OPS)
else:
nova_conf.add('network_manager', NET_MAN_TEMPL % (self._getstr('network_manager')))
# TODO
# if ('n-vol' in self.othercomponents):
# self._resolve('--volume_group=', 'nova', 'volume_group')
# self._resolve('--volume_name_template=',
# 'nova', 'volume_name_prefix', '%08x')
# self._add('--iscsi_helper=tgtadm')
nova_conf.add('my_ip', hostip)
# The value for vlan_interface may default to the the current value
# of public_interface. We'll grab the value and keep it handy.
public_interface = self._getstr('public_interface')
vlan_interface = self._getstr('vlan_interface')
if(not vlan_interface):
vlan_interface = public_interface
nova_conf.add('public_interface', public_interface)
nova_conf.add('vlan_interface', vlan_interface)
nova_conf.add('sql_connection', self.cfg.get_dbdsn('nova'))
nova_conf.add('libvirt_type', self._getstr('libvirt_type'))
instance_template = self._getstr('instance_name_prefix') + '%08x';
nova_conf.add('instance_name_template', instance_template)
if(co.OPENSTACK_X in self.active_components):
nova_conf.add('osapi_compute_extension', 'nova.api.openstack.compute.contrib.standard_extensions')
nova_conf.add('osapi_compute_extension', 'extensions.admin.Admin')
# TODO
# if ('n-vnc' in self.othercomponents):
# vncproxy_url = self.cfg.get("nova", "vncproxy_url")
# if (not vncproxy_url):
# vncproxy_url = 'http://' + hostip + ':6080'
# self._add('--vncproxy_url=' + vncproxy_url)
# self._add('vncproxy_wwwroot=' + nova_dir + '/')
#
# TODO is this right?
nova_conf.add('api_paste_config', utils.joinpths(dirs.get('bin'), PASTE_CONF))
nova_conf.add('image_service', IMG_SVC)
ec2_dmz_host = self._getstr('ec2_dmz_host')
if(not ec2_dmz_host):
ec2_dmz_host = utils.get_host_ip()
nova_conf.add('ec2_dmz_host', ec2_dmz_host)
nova_conf.add('rabbit_host', self.cfg.get('default', 'rabbit_host'))
nova_conf.add('rabbit_password', self.cfg.getpw("passwords", "rabbit"))
glance_svr = "%s:9292" % (hostip)
nova_conf.add('glance_api_servers', glance_svr)
nova_conf.add_simple('force_dhcp_release')
instances_path = self._getstr('instances_path')
if(instances_path):
nova_conf.add('instances_path', instances_path)
if(self._getbool('multi_host')):
nova_conf.add_simple('multi_host')
nova_conf.add_simple('send_arp_for_ha')
if(self.cfg.getboolean('default', 'syslog')):
nova_conf.add_simple('use_syslog')
virt_driver = self._getstr('virt_driver')
self._configure_virt_driver(virt_driver, nova_conf)
#now make it
complete_file = nova_conf.generate()
#add any extra flags in?
extra_flags = self._getstr('extra_flags')
if(extra_flags and len(extra_flags)):
full_file = [complete_file, extra_flags]
complete_file = utils.joinlinesep(*full_file)
return complete_file
#configures any virt driver settings
def _configure_virt_driver(self, driver, nova_conf):
if(not driver):
return
drive_canon = driver.lower().strip()
if(drive_canon == 'xenserver'):
nova_conf.add('connection_type', 'xenapi')
nova_conf.add('xenapi_connection_url', 'http://169.254.0.1')
nova_conf.add('xenapi_connection_username', 'root')
# TODO, check that this is the right way to get the password
nova_conf.add('xenapi_connection_password', self.cfg.getpw("passwords", "xenapi"))
nova_conf.add_simple('noflat_injected')
nova_conf.add('flat_interface', 'eth1')
nova_conf.add('flat_network_bridge', 'xapi1')
else:
nova_conf.add('flat_network_bridge', self._getstr('flat_network_bridge'))
nova_conf.add('flat_interface', self._getstr('flat_interface'))
class NovaInstaller(comp.PythonInstallComponent):
def __init__(self, *args, **kargs):
comp.PythonInstallComponent.__init__(self, TYPE, *args, **kargs)
self.gitloc = self.cfg.get("git", "nova_repo")
self.brch = self.cfg.get("git", "nova_branch")
# TBD is this the install location of the conf file?
#self.cfgdir = joinpths(self.appdir, CONFIG_ACTUAL_DIR)
self.git_repo = self.cfg.get("git", "nova_repo")
self.git_branch = self.cfg.get("git", "nova_branch")
self.bindir = utils.joinpths(self.appdir, BIN_DIR)
def _get_download_location(self):
places = comp.PythonInstallComponent._get_download_locations(self)
places.append({
'uri': self.gitloc,
'branch': self.brch,
'uri': self.git_repo,
'branch': self.git_branch,
})
return places
def configure(self):
# FIXME, is this necessary? Is it for the template source?
dirsmade = sh.mkdirslist(self.cfgdir)
self.tracewriter.dir_made(*dirsmade)
nconf = nc.NovaConf(self)
LOG.info("Getting dynamic content for nova.conf")
# Get dynamic content for nova.conf
lines = nconf.generate()
LOG.debug("Got conf lines, %s" % (lines))
# Set up and write lines to the file
fn = API_CONF
tgtfn = self._get_full_config_name(fn)
dirsmade = sh.mkdirslist(os.path.dirname(tgtfn))
self.tracewriter.dir_made(*dirsmade)
LOG.info("Writing configuration file %s" % (tgtfn))
#this trace is used to remove the files configured
sh.write_file(tgtfn, os.linesep.join(lines))
self.tracewriter.cfg_write(tgtfn)
def _generate_nova_conf(self):
LOG.debug("Generating dynamic content for nova.conf")
dirs = dict()
dirs['app'] = self.appdir
dirs['cfg'] = self.cfgdir
dirs['bin'] = self.bindir
conf_gen = NovaConfigurator(self.cfg, self.all_components, dirs)
nova_conf = conf_gen.configure(dirs)
tgtfn = self._get_target_config_name(API_CONF)
sh.write_file(tgtfn, nova_conf)
return 1
def _configure_files(self):
return self._generate_nova_conf()
class NovaRuntime(comp.PythonRuntime):
def __init__(self, *args, **kargs):

@ -20,139 +20,44 @@ from devstack import utils
LOG = logging.getLogger("devstack.components.nova_conf")
QUANTUM_OPENSWITCH_OPS = [
'--libvirt_vif_type=ethernet',
'--libvirt_vif_driver=nova.virt.libvirt.vif.LibvirtOpenVswitchDriver',
'--linuxnet_interface_driver=nova.network.linux_net.LinuxOVSInterfaceDriver',
'--quantum_use_dhcp']
OS_EXTENSIONS = [
'--osapi_compute_extension='
'nova.api.openstack.compute.contrib.standard_extensions',
'--osapi_compute_extension=extensions.admin.Admin']
class NovaConf():
def __init__(self):
self.lines = list()
MULTI_HOST_OPS = ['--multi_host', '--send_arp_for_ha']
def add_list(self, key, *params):
self.lines.append({'key': key, 'options': params})
LOG.debug("Added nova conf key %s with values [%s]" % (key, ",".join(params)))
def add_simple(self, key):
self.lines.append({'key': key, 'options': None})
LOG.debug("Added nova conf key %s" % (key))
class NovaConf:
# Our accumlator for lines that will go into nova.conf
lines = []
def add(self, key, value):
self.lines.append({'key': key, 'options': [value]})
LOG.debug("Added nova conf key %s with value [%s]" % (key, value))
# We should be passed the config object that holds all the values we need
def __init__(self, nova_component):
# Get handles to info from the main Nova component that we'll need
self.nova_component = nova_component
# This is a handy short cut to get to the Nova config data
self.cfg = nova_component.cfg
# This is a handy short cut to get to the Nova othercomponents data
self.othercomponents = nova_component.othercomponents
def _form_key(self, key, has_opts):
key_str = "--" + str(key)
if(has_opts):
key_str += "="
return key_str
# Add a line to the output that contains one value from the config
def _resolve(self, prefix, section, variable, postfix=''):
value = self.cfg.get(section, variable)
self._add(prefix + value + postfix)
# Just a convience method to have the list appending in one place
def _add(self, ldata):
self.lines.append(ldata)
def generate(self):
self.lines = []
self._add('--verbose')
self._add('--allow_admin_api')
self._resolve('--scheduler_driver=', 'nova', 'scheduler')
nova_dir = self.nova_component.appdir # FIXME, is this correct?
self._add('--dhcpbridge_flagfile=' + nova_dir + '/bin/nova.conf')
self._resolve('--fixed_range=', 'nova', 'fixed_range')
# Check if quantum is enabled, and if so, add all the necessary
# config magic that goes with it
if (QUANTUM in self.othercomponents):
# Set network manager to multi lines
self._add(
'--network_manager=nova.network.quantum.manager.QuantumManager')
self._add(
'--network_manager=nova.network.quantum.manager.QuantumManager')
self._resolve('--quantum_connection_host=', 'quantum', 'q_host')
self._resolve('--quantum_connection_port=', 'quantum', 'q_port')
if ('q-svc' in self.othercomponents and
self.cfg.get('quantum', 'q_plugin') == 'openvswitch'):
self.lines.extend(QUANTUM_OPENSWITCH_OPS)
else:
self._resolve('--network_manager=nova.network.manager.',
'nova', 'network_manager')
if ('n-vol' in self.othercomponents):
self._resolve('--volume_group=', 'nova', 'volume_group')
self._resolve('--volume_name_template=',
'nova', 'volume_name_prefix', '%08x')
self._add('--iscsi_helper=tgtadm')
hostip = get_host_ip(self.cfg)
self._add('--my_ip=' + hostip)
# The value for vlan_interface may default to the the current value
# of public_interface. We'll grab the value and keep it handy
public_interface = self.cfg.get("nova", "public_interface")
vlan_interface = self.cfg.get("nova", "vlan_interface")
# If there's no vlan_interface value, use public_interface
if (not vlan_interface):
vlan_interface = public_interface
self._add('--public_interface=' + public_interface)
self._add('--vlan_interface=' + vlan_interface)
self._add('--sql_connection=' + self.cfg.get_dbdsn('nova'))
self._resolve('--libvirt_type=', 'nova', 'libvirt_type')
self._resolve('--instance_name_template=',
'nova', 'instance_name_prefix', '%08x')
if ('openstackx' in self.othercomponents):
self.lines.extend(OS_EXTENSIONS)
if ('n-vnc' in self.othercomponents):
vncproxy_url = self.cfg.get("nova", "vncproxy_url")
if (not vncproxy_url):
vncproxy_url = 'http://' + hostip + ':6080'
self._add('--vncproxy_url=' + vncproxy_url)
self._add('vncproxy_wwwroot=' + nova_dir + '/')
self._add('--api_paste_config=' + nova_dir + '/bin/nova-api-paste.ini')
self._add('--image_service=nova.image.glance.GlanceImageService')
ec2_dmz_host = self.cfg.get("nova", "ec2_dmz_host")
if (not ec2_dmz_host):
ec2_dmz_host = hostip
self._add('--ec2_dmz_host=' + ec2_dmz_host)
self._resolve('--rabbit_host=', 'default', 'rabbit_host')
self._add('--rabbit_password=' + self.cfg.getpw("passwords", "rabbit"))
self._add('--glance_api_servers=' + hostip + ':9292')
self._add('--force_dhcp_release')
instances_path = self.cfg.get("nova", "instances_path")
if (instances_path):
self._add('--instances_path=' + instances_path)
multi_host = self.cfg.getboolean("nova", "multi_host")
if (multi_host == 1):
self.lines.extend(MULTI_HOST_OPS)
if (self.cfg.getboolean("default", "syslog")):
self._add('--use_syslog')
extra_flags = self.cfg.get("nova", "extra_flags")
if (extra_flags):
# FIXME, this is assuming that multiple flags are newline delimited
self._add(extra_flags)
virt_driver = self.cfg.get("nova", "virt_driver")
if (virt_driver == 'xenserver'):
self._add('--connection_type=xenapi')
self._add('--xenapi_connection_url=http://169.254.0.1')
self._add('--xenapi_connection_username=root')
# TBD, check that this is the right way to get the password
self._add('--xenapi_connection_password=' +
self.cfg.getpw("passwords", "xenapi"))
self._add('--noflat_injected')
self._add('--flat_interface=eth1')
self._add('--flat_network_bridge=xapi1')
else:
self._resolve('--flat_network_bridge=',
'nova', 'flat_network_bridge')
self._resolve('--flat_interface=', 'nova', 'flat_interface')
return self.lines
def generate(self, param_dict=None):
gen_lines = list()
for line_entry in self.lines:
key = line_entry.get('key')
opts = line_entry.get('options')
if(not key or len(key) == 0):
continue
if(opts == None):
key_str = self._form_key(key, False)
full_line = key_str
else:
key_str = self._form_key(key, len(opts))
filled_opts = list()
for opt in opts:
filled_opts.append(utils.param_replace(str(opt), param_dict))
full_line = key_str + ",".join(filled_opts)
gen_lines.append(full_line)
return utils.joinlinesep(*gen_lines)