Adds support for multihost nova-network

- Modifies Nova plugin to accept multiple hosts
in CONFIG_NOVA_NETWORK_HOSTS parameter.

- Fixes validate_multi_ip

Change-Id: I16bb63040b5825d4e8f7ed9a95d0ce46680e4074
Fixes: rhbz#1001916
This commit is contained in:
Martin Magr
2013-09-17 13:05:16 +02:00
parent 8bad2a3b0b
commit c7c0b9b8d5
6 changed files with 106 additions and 66 deletions

View File

@@ -121,7 +121,7 @@ Nova Options
**CONFIG_NOVA_COMPUTE_PRIVIF** : Private interface for Flat DHCP on the Nova compute servers **CONFIG_NOVA_COMPUTE_PRIVIF** : Private interface for Flat DHCP on the Nova compute servers
**CONFIG_NOVA_NETWORK_HOST** : The IP address of the server on which to install the Nova Network service **CONFIG_NOVA_NETWORK_HOSTS** : List of IP address of the servers on which to install the Nova Network service
**CONFIG_NOVA_DB_PW** : The password to use for the Nova to access DB **CONFIG_NOVA_DB_PW** : The password to use for the Nova to access DB

View File

@@ -121,7 +121,9 @@ def createmanifest(config):
hosts.add(config.get('CONFIG_NOVA_CONDUCTOR_HOST').strip()) hosts.add(config.get('CONFIG_NOVA_CONDUCTOR_HOST').strip())
hosts.add(config.get('CONFIG_NOVA_SCHED_HOST').strip()) hosts.add(config.get('CONFIG_NOVA_SCHED_HOST').strip())
if config['CONFIG_NEUTRON_INSTALL'] != 'y': if config['CONFIG_NEUTRON_INSTALL'] != 'y':
hosts.add(config.get('CONFIG_NOVA_NETWORK_HOST').strip()) dbhosts = config['CONFIG_NOVA_NETWORK_HOSTS'].split(',')
dbhosts = set([i.strip() for i in dbhosts if i.strip()])
hosts |= dbhosts
for host in config.get('CONFIG_NOVA_COMPUTE_HOSTS').split(','): for host in config.get('CONFIG_NOVA_COMPUTE_HOSTS').split(','):
hosts.add(host.strip()) hosts.add(host.strip())

View File

@@ -24,11 +24,11 @@ def initConfig(controllerObject):
controller = controllerObject controller = controllerObject
if platform.linux_distribution()[0] == "Fedora": if platform.linux_distribution()[0] == "Fedora":
primary_netif = "em1" primary_netif = "em1"
secondary_netif = "em2" secondary_netif = "em2"
else: else:
primary_netif = "eth0" primary_netif = "eth0"
secondary_netif = "eth1" secondary_netif = "eth1"
nova_params = { nova_params = {
"NOVA" : [ "NOVA" : [
@@ -170,15 +170,15 @@ def initConfig(controllerObject):
"USE_DEFAULT" : False, "USE_DEFAULT" : False,
"NEED_CONFIRM" : False, "NEED_CONFIRM" : False,
"CONDITION" : False }, "CONDITION" : False },
{"CMD_OPTION" : "novanetwork-host", {"CMD_OPTION" : "novanetwork-hosts",
"USAGE" : "The IP address of the server on which to install the Nova Network service", "USAGE" : "The list of IP addresses of the server on which to install the Nova Network service",
"PROMPT" : "Enter the IP address of the Nova Network service", "PROMPT" : "Enter list of IP addresses on which to install the Nova Network service",
"OPTION_LIST" : [], "OPTION_LIST" : [],
"VALIDATORS" : [validators.validate_ip, validators.validate_ssh], "VALIDATORS" : [validators.validate_multi_ip, validators.validate_multi_ssh],
"DEFAULT_VALUE" : utils.get_localhost_ip(), "DEFAULT_VALUE" : utils.get_localhost_ip(),
"MASK_INPUT" : False, "MASK_INPUT" : False,
"LOOSE_VALIDATION": True, "LOOSE_VALIDATION": True,
"CONF_NAME" : "CONFIG_NOVA_NETWORK_HOST", "CONF_NAME" : "CONFIG_NOVA_NETWORK_HOSTS",
"USE_DEFAULT" : False, "USE_DEFAULT" : False,
"NEED_CONFIRM" : False, "NEED_CONFIRM" : False,
"CONDITION" : False }, "CONDITION" : False },
@@ -368,6 +368,14 @@ def initSequences(controller):
def createapimanifest(config): def createapimanifest(config):
# Since this step is running first, let's create necesary variables here
# and make them global
global compute_hosts, network_hosts
com_var = config.get("CONFIG_NOVA_COMPUTE_HOSTS", "")
compute_hosts = set([i.strip() for i in com_var.split(",") if i.strip()])
net_var = config.get("CONFIG_NOVA_NETWORK_HOSTS", "")
network_hosts = set([i.strip() for i in net_var.split(",") if i.strip()])
# This is a hack around us needing to generate the neutron metadata # This is a hack around us needing to generate the neutron metadata
# password, but the nova puppet plugin uses the existence of that # password, but the nova puppet plugin uses the existence of that
# password to determine whether or not to configure neutron metadata # password to determine whether or not to configure neutron metadata
@@ -434,29 +442,29 @@ def bring_up_ifcfg(host, device):
def createcomputemanifest(config): def createcomputemanifest(config):
dirty = controller.CONF["CONFIG_NOVA_COMPUTE_HOSTS"].split(",") global compute_hosts, network_hosts
hostlist = [i.strip() for i in dirty if i.strip()] for host in compute_hosts:
for host in hostlist: config["CONFIG_NOVA_COMPUTE_HOST"] = host
controller.CONF["CONFIG_NOVA_COMPUTE_HOST"] = host
manifestdata = getManifestTemplate("nova_compute.pp") manifestdata = getManifestTemplate("nova_compute.pp")
if controller.CONF['CONFIG_CINDER_INSTALL'] == 'y' and controller.CONF['CONFIG_CINDER_BACKEND'] == 'gluster': if config['CONFIG_CINDER_INSTALL'] == 'y' and config['CONFIG_CINDER_BACKEND'] == 'gluster':
manifestdata += getManifestTemplate("nova_gluster.pp") manifestdata += getManifestTemplate("nova_gluster.pp")
if controller.CONF['CONFIG_CINDER_INSTALL'] == 'y' and controller.CONF['CONFIG_CINDER_BACKEND'] == 'nfs': if config['CONFIG_CINDER_INSTALL'] == 'y' and config['CONFIG_CINDER_BACKEND'] == 'nfs':
manifestdata += getManifestTemplate("nova_nfs.pp") manifestdata += getManifestTemplate("nova_nfs.pp")
manifestfile = "%s_nova.pp"%host manifestfile = "%s_nova.pp" % host
nova_config_options = NovaConfig() nova_config_options = NovaConfig()
if controller.CONF['CONFIG_NEUTRON_INSTALL'] != 'y': if config['CONFIG_NEUTRON_INSTALL'] != 'y':
if host != controller.CONF["CONFIG_NOVA_NETWORK_HOST"]: if host not in network_hosts:
nova_config_options.addOption("DEFAULT/flat_interface", controller.CONF['CONFIG_NOVA_COMPUTE_PRIVIF']) nova_config_options.addOption("DEFAULT/flat_interface",
check_ifcfg(host, controller.CONF['CONFIG_NOVA_COMPUTE_PRIVIF']) config['CONFIG_NOVA_COMPUTE_PRIVIF'])
check_ifcfg(host, config['CONFIG_NOVA_COMPUTE_PRIVIF'])
try: try:
bring_up_ifcfg(host, controller.CONF['CONFIG_NOVA_COMPUTE_PRIVIF']) bring_up_ifcfg(host, config['CONFIG_NOVA_COMPUTE_PRIVIF'])
except ScriptRuntimeError as ex: except ScriptRuntimeError as ex:
# just warn user to do it by himself # just warn user to do it by himself
controller.MESSAGES.append(str(ex)) controller.MESSAGES.append(str(ex))
if controller.CONF['CONFIG_CEILOMETER_INSTALL'] == 'y': if config['CONFIG_CEILOMETER_INSTALL'] == 'y':
manifestdata += getManifestTemplate("nova_ceilometer.pp") manifestdata += getManifestTemplate("nova_ceilometer.pp")
# According to the docs the only element that connects directly to nova compute # According to the docs the only element that connects directly to nova compute
@@ -467,43 +475,48 @@ def createcomputemanifest(config):
config['FIREWALL_PORTS'] = "'5900-5999'" config['FIREWALL_PORTS'] = "'5900-5999'"
manifestdata += getManifestTemplate("firewall.pp") manifestdata += getManifestTemplate("firewall.pp")
appendManifestFile(manifestfile, manifestdata + "\n" + nova_config_options.getManifestEntry()) manifestdata += "\n" + nova_config_options.getManifestEntry()
appendManifestFile(manifestfile, manifestdata)
def createnetworkmanifest(config): def createnetworkmanifest(config):
if controller.CONF['CONFIG_NEUTRON_INSTALL'] == "y": global compute_hosts, network_hosts
if config['CONFIG_NEUTRON_INSTALL'] == "y":
return return
host = controller.CONF['CONFIG_NOVA_NETWORK_HOST'] # set default values for VlanManager in case this values are not in config
for i in ('CONFIG_NOVA_NETWORK_PRIVIF', 'CONFIG_NOVA_NETWORK_PUBIF'): for key, value in [('CONFIG_NOVA_NETWORK_VLAN_START', 100),
check_ifcfg(host, controller.CONF[i]) ('CONFIG_NOVA_NETWORK_SIZE', 255),
try: ('CONFIG_NOVA_NETWORK_NUMBER', 1)]:
bring_up_ifcfg(host, controller.CONF[i]) config[key] = config.get(key, value)
except ScriptRuntimeError as ex:
# just warn user to do it by himself
controller.MESSAGES.append(str(ex))
if controller.CONF['CONFIG_NOVA_NETWORK_AUTOASSIGNFLOATINGIP'] == "y": api_host = config['CONFIG_NOVA_API_HOST']
controller.CONF['CONFIG_NOVA_NETWORK_AUTOASSIGNFLOATINGIP'] = True multihost = len(network_hosts) > 1
else: config['CONFIG_NOVA_NETWORK_MULTIHOST'] = multihost and 'true' or 'false'
controller.CONF['CONFIG_NOVA_NETWORK_AUTOASSIGNFLOATINGIP'] = False for host in network_hosts:
for i in ('CONFIG_NOVA_NETWORK_PRIVIF', 'CONFIG_NOVA_NETWORK_PUBIF'):
check_ifcfg(host, config[i])
try:
bring_up_ifcfg(host, config[i])
except ScriptRuntimeError as ex:
# just warn user to do it by himself
controller.MESSAGES.append(str(ex))
# We need to explicitly set the network size key = 'CONFIG_NOVA_NETWORK_AUTOASSIGNFLOATINGIP'
routing_prefix = controller.CONF['CONFIG_NOVA_NETWORK_FIXEDRANGE'].split('/')[1] config[key] = config[key] == "y"
net_size = 2**(32 - int(routing_prefix))
controller.CONF['CONFIG_NOVA_NETWORK_FIXEDSIZE'] = str(net_size)
# Default VLAN parameters to avoid KeyError exceptions in case of VlanManager # We need to explicitly set the network size
# is not used routing_prefix = config['CONFIG_NOVA_NETWORK_FIXEDRANGE'].split('/')[1]
vlan_manager = 'nova.network.manager.VlanManager' net_size = 2**(32 - int(routing_prefix))
if config['CONFIG_NOVA_NETWORK_MANAGER'] != vlan_manager: config['CONFIG_NOVA_NETWORK_FIXEDSIZE'] = str(net_size)
config['CONFIG_NOVA_NETWORK_VLAN_START'] = 100
config['CONFIG_NOVA_NETWORK_SIZE'] = 255
config['CONFIG_NOVA_NETWORK_NUMBER'] = 1
manifestfile = "%s_nova.pp" % host manifestfile = "%s_nova.pp" % host
manifestdata = getManifestTemplate("nova_network.pp") manifestdata = getManifestTemplate("nova_network.pp")
appendManifestFile(manifestfile, manifestdata)
# in multihost mode each compute host runs nova-api-metadata
if multihost and host != api_host and host in compute_hosts:
manifestdata += getManifestTemplate("nova_metadata.pp")
appendManifestFile(manifestfile, manifestdata)
def createschedmanifest(config): def createschedmanifest(config):
@@ -519,30 +532,40 @@ def createvncproxymanifest(config):
def createcommonmanifest(config): def createcommonmanifest(config):
dbhost = config['CONFIG_MYSQL_HOST'] global compute_hosts, network_hosts
dirty = controller.CONF["CONFIG_NOVA_COMPUTE_HOSTS"].split(",") network_type = (config['CONFIG_NEUTRON_INSTALL'] == "y" and
nopass_nodes = [i.strip() for i in dirty if i.strip()] 'neutron' or 'nova')
network_multi = len(network_hosts) > 1
dirty = [config.get('CONFIG_NOVA_CONDUCTOR_HOST'), dirty = [config.get('CONFIG_NOVA_CONDUCTOR_HOST'),
config.get('CONFIG_NOVA_API_HOST'), config.get('CONFIG_NOVA_API_HOST'),
config.get('CONFIG_NOVA_CERT_HOST'), config.get('CONFIG_NOVA_CERT_HOST'),
config.get('CONFIG_NOVA_VNCPROXY_HOST'), config.get('CONFIG_NOVA_VNCPROXY_HOST'),
config.get('CONFIG_NOVA_SCHED_HOST'), config.get('CONFIG_NOVA_SCHED_HOST')]
config.get('CONFIG_NOVA_NETWORK_HOST')] dbacces_hosts = set([i.strip() for i in dirty if i and i.strip()])
dbpass_nodes = [i.strip() for i in dirty if i and i.strip()] dbacces_hosts |= network_hosts
for manifestfile, marker in manifestfiles.getFiles(): for manifestfile, marker in manifestfiles.getFiles():
if manifestfile.endswith("_nova.pp"): if manifestfile.endswith("_nova.pp"):
host, manifest = manifestfile.split('_', 1) host, manifest = manifestfile.split('_', 1)
host = host.strip() host = host.strip()
if host in nopass_nodes and host not in dbpass_nodes: if host in compute_hosts and host not in dbacces_hosts:
# we should omit password in case we are installing only # we should omit password in case we are installing only
# nova-compute to the host # nova-compute to the host
perms = "nova" perms = "nova"
else: else:
perms = "nova:%(CONFIG_NOVA_DB_PW)s" % config perms = "nova:%(CONFIG_NOVA_DB_PW)s"
config['CONFIG_NOVA_SQL_CONN'] = ("mysql://%s@%s/nova" sqlconn = "mysql://%s@%%(CONFIG_MYSQL_HOST)s/nova" % perms
% (perms, dbhost)) config['CONFIG_NOVA_SQL_CONN'] = sqlconn % config
# for nova-network in multihost mode each compute host is metadata
# host otherwise we use api host
if (network_type == 'nova' and network_multi and
host in compute_hosts):
metadata = host
else:
metadata = config['CONFIG_NOVA_API_HOST']
config['CONFIG_NOVA_METADATA_HOST'] = metadata
data = getManifestTemplate("nova_common.pp") data = getManifestTemplate("nova_common.pp")
appendManifestFile(os.path.split(manifestfile)[1], data) appendManifestFile(os.path.split(manifestfile)[1], data)

View File

@@ -4,11 +4,11 @@
Firewall <| |> -> Class['nova'] Firewall <| |> -> Class['nova']
nova_config{ nova_config{
"DEFAULT/metadata_host": value => "%(CONFIG_NOVA_API_HOST)s";
"DEFAULT/sql_connection": value => "%(CONFIG_NOVA_SQL_CONN)s"; "DEFAULT/sql_connection": value => "%(CONFIG_NOVA_SQL_CONN)s";
"DEFAULT/metadata_host": value => "%(CONFIG_NOVA_METADATA_HOST)s";
} }
class {"nova": class { "nova":
glance_api_servers => "%(CONFIG_GLANCE_HOST)s:9292", glance_api_servers => "%(CONFIG_GLANCE_HOST)s:9292",
qpid_hostname => "%(CONFIG_QPID_HOST)s", qpid_hostname => "%(CONFIG_QPID_HOST)s",
rpc_backend => 'nova.openstack.common.rpc.impl_qpid', rpc_backend => 'nova.openstack.common.rpc.impl_qpid',

View File

@@ -0,0 +1,7 @@
nova::generic_service { 'metadata-api':
enabled => true,
ensure_package => 'present',
package_name => 'openstack-nova-api',
service_name => 'openstack-nova-metadata-api',
}

View File

@@ -1,8 +1,16 @@
nova_config{
nova_config {
"DEFAULT/default_floating_pool": value => '%(CONFIG_NOVA_NETWORK_DEFAULTFLOATINGPOOL)s'; "DEFAULT/default_floating_pool": value => '%(CONFIG_NOVA_NETWORK_DEFAULTFLOATINGPOOL)s';
"DEFAULT/auto_assign_floating_ip": value => '%(CONFIG_NOVA_NETWORK_AUTOASSIGNFLOATINGIP)s'; "DEFAULT/auto_assign_floating_ip": value => '%(CONFIG_NOVA_NETWORK_AUTOASSIGNFLOATINGIP)s';
} }
$multihost = %(CONFIG_NOVA_NETWORK_MULTIHOST)s
if $multihost {
nova_config {
"DEFAULT/multi_host": value => true;
"DEFAULT/send_arp_for_ha": value => true;
}
}
$manager = '%(CONFIG_NOVA_NETWORK_MANAGER)s' $manager = '%(CONFIG_NOVA_NETWORK_MANAGER)s'
$overrides = {} $overrides = {}
@@ -17,7 +25,7 @@ if $manager == 'nova.network.manager.VlanManager' {
$net_size = '%(CONFIG_NOVA_NETWORK_FIXEDSIZE)s' $net_size = '%(CONFIG_NOVA_NETWORK_FIXEDSIZE)s'
$net_num = 1 $net_num = 1
} }
class {"nova::network": class { "nova::network":
enabled => true, enabled => true,
network_manager => $manager, network_manager => $manager,
num_networks => $net_num , num_networks => $net_num ,