Allow CIDR instead of iterface name
This patch implements translation from CIDR to interface name, which should allow deployments to heretogenous infrastructure. Package openstack-packstack-puppet will need new require, which is rubygem-ippaddress. Workaround for rhbz#1200604 Change-Id: Id27881f616781e5a24a1bdb1e169915b7619eebd
This commit is contained in:
parent
29b18bc93b
commit
d14f898ed2
|
@ -101,6 +101,9 @@ Global Options
|
|||
**CONFIG_UNSUPPORTED**
|
||||
Specify 'y' if you want to use unsupported parameters. This should be used only if you know what you are doing. Issues caused by using unsupported options will not be fixed before the next major release. ['y', 'n']
|
||||
|
||||
**CONFIG_USE_SUBNETS**
|
||||
Specify 'y' if you want to use subnet addresses (in CIDR format) instead of interface names in following options: CONFIG_NOVA_COMPUTE_PRIVIF, CONFIG_NOVA_NETWORK_PRIVIF, CONFIG_NOVA_NETWORK_PUBIF, CONFIG_NEUTRON_OVS_BRIDGE_IFACES, CONFIG_NEUTRON_LB_INTERFACE_MAPPINGS, CONFIG_NEUTRON_OVS_TUNNEL_IF. This is useful for cases when interface names are not same on all installation hosts.
|
||||
|
||||
vCenter Config Parameters
|
||||
-------------------------
|
||||
|
||||
|
|
|
@ -68,7 +68,10 @@ HIERADATA_FILE_RELATIVE = "hieradata"
|
|||
HIERADATA_DIR = os.path.join(VAR_DIR, HIERADATA_FILE_RELATIVE)
|
||||
|
||||
PUPPET_DEPENDENCIES = ['puppet', 'hiera', 'openssh-clients', 'tar', 'nc']
|
||||
PUPPET_MODULES_PKG = 'openstack-puppet-modules'
|
||||
PUPPET_MODULES_PKGS = [
|
||||
'openstack-puppet-modules',
|
||||
'openstack-packstack-puppet'
|
||||
]
|
||||
|
||||
FILE_INSTALLER_LOG = "setup.log"
|
||||
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import netaddr
|
||||
|
||||
from ..installer import utils
|
||||
|
||||
|
||||
|
@ -49,3 +51,37 @@ def is_all_in_one(config):
|
|||
# with them when checking all-in-one. MariaDB host should however be
|
||||
# omitted if we are not installing MariaDB.
|
||||
return len(filtered_hosts(config, exclude=False, dbhost=True)) == 1
|
||||
|
||||
|
||||
def cidr_to_ifname(cidr, host, config):
|
||||
"""
|
||||
Returns appropriate host's interface name from given CIDR subnet. Passed
|
||||
config dict has to contain discovered hosts details.
|
||||
"""
|
||||
if not config or not config['HOST_DETAILS'] or '/' not in cidr:
|
||||
raise ValueError(
|
||||
'Cannot translate CIDR to interface, invalid parameters '
|
||||
'were given.'
|
||||
)
|
||||
info = config['HOST_DETAILS'][host]
|
||||
|
||||
result = []
|
||||
for item in cidr.split(','):
|
||||
translated = []
|
||||
for fragment in item.split(':'):
|
||||
try:
|
||||
subnet_a = netaddr.IPNetwork(fragment)
|
||||
except netaddr.AddrFormatError:
|
||||
translated.append(fragment)
|
||||
continue
|
||||
|
||||
for interface in info['interfaces'].split(','):
|
||||
interface = interface.strip()
|
||||
ipaddr = info['ipaddress_{}'.format(interface)]
|
||||
netmask = info['netmask_{}'.format(interface)]
|
||||
subnet_b = netaddr.IPNetwork('{ipaddr}/{netmask}'.format(**locals()))
|
||||
if subnet_a == subnet_b:
|
||||
translated.append(interface)
|
||||
break
|
||||
result.append(':'.join(translated))
|
||||
return ','.join(result)
|
||||
|
|
|
@ -24,28 +24,6 @@ PUPPET_TEMPLATE_DIR = os.path.join(PUPPET_DIR, "templates")
|
|||
HIERA_DEFAULTS_YAML = os.path.join(basedefs.HIERADATA_DIR, "defaults.yaml")
|
||||
|
||||
|
||||
class NovaConfig(object):
|
||||
"""
|
||||
Helper class to create puppet manifest entries for nova_config
|
||||
"""
|
||||
def __init__(self):
|
||||
self.options = {}
|
||||
|
||||
def addOption(self, n, v):
|
||||
self.options[n] = v
|
||||
|
||||
def getManifestEntry(self):
|
||||
entry = ""
|
||||
if not self.options:
|
||||
return entry
|
||||
|
||||
entry += "nova_config{\n"
|
||||
for k, v in self.options.items():
|
||||
entry += ' "%s": value => "%s";\n' % (k, v)
|
||||
entry += "}"
|
||||
return entry
|
||||
|
||||
|
||||
class ManifestFiles(object):
|
||||
def __init__(self):
|
||||
self.filelist = []
|
||||
|
|
|
@ -23,7 +23,7 @@ from packstack.installer import processors
|
|||
from packstack.installer import output_messages
|
||||
from packstack.installer.utils import split_hosts
|
||||
|
||||
from packstack.modules.common import filtered_hosts
|
||||
from packstack.modules import common
|
||||
from packstack.modules.documentation import update_params_usage
|
||||
from packstack.modules.shortcuts import get_mq
|
||||
from packstack.modules.ospluginutils import appendManifestFile
|
||||
|
@ -739,6 +739,10 @@ def create_l2_agent_manifests(config, messages):
|
|||
(host in network_hosts and tunnel_types)
|
||||
or 'vlan' in ovs_type)
|
||||
):
|
||||
if config['CONFIG_USE_SUBNETS'] == 'y':
|
||||
iface_arr = [
|
||||
common.cidr_to_ifname(i, host, config) for i in iface_arr
|
||||
]
|
||||
config["CONFIG_NEUTRON_OVS_BRIDGE_IFACES"] = iface_arr
|
||||
manifestdata += getManifestTemplate(template_name)
|
||||
appendManifestFile(manifestfile, manifestdata + "\n")
|
||||
|
@ -761,7 +765,7 @@ def create_metadata_manifests(config, messages):
|
|||
|
||||
def check_nm_status(config, messages):
|
||||
hosts_with_nm = []
|
||||
for host in filtered_hosts(config):
|
||||
for host in common.filtered_hosts(config):
|
||||
server = utils.ScriptRunner(host)
|
||||
server.append("systemctl")
|
||||
rc, out = server.execute(can_fail=False)
|
||||
|
|
|
@ -26,13 +26,13 @@ from packstack.installer import utils
|
|||
from packstack.installer import validators
|
||||
from packstack.installer.exceptions import ScriptRuntimeError
|
||||
|
||||
from packstack.modules import common
|
||||
from packstack.modules.documentation import update_params_usage
|
||||
from packstack.modules.shortcuts import get_mq
|
||||
from packstack.modules.ospluginutils import appendManifestFile
|
||||
from packstack.modules.ospluginutils import createFirewallResources
|
||||
from packstack.modules.ospluginutils import getManifestTemplate
|
||||
from packstack.modules.ospluginutils import manifestfiles
|
||||
from packstack.modules.ospluginutils import NovaConfig
|
||||
|
||||
# ------------- Nova Packstack Plugin Initialization --------------
|
||||
|
||||
|
@ -532,16 +532,19 @@ def create_compute_manifest(config, messages):
|
|||
manifestdata += getManifestTemplate("nova_nfs")
|
||||
manifestfile = "%s_nova.pp" % host
|
||||
|
||||
nova_config_options = NovaConfig()
|
||||
if config['CONFIG_NEUTRON_INSTALL'] != 'y':
|
||||
if host not in network_hosts:
|
||||
nova_config_options.addOption(
|
||||
"DEFAULT/flat_interface",
|
||||
config['CONFIG_NOVA_COMPUTE_PRIVIF']
|
||||
manifestdata += getManifestTemplate('nova_compute_flat')
|
||||
|
||||
if config['CONFIG_USE_SUBNETS'] == 'y':
|
||||
netface = common.cidr_to_ifname(
|
||||
config['CONFIG_NOVA_COMPUTE_PRIVIF'], host, config
|
||||
)
|
||||
check_ifcfg(host, config['CONFIG_NOVA_COMPUTE_PRIVIF'])
|
||||
else:
|
||||
netface = config['CONFIG_NOVA_COMPUTE_PRIVIF']
|
||||
check_ifcfg(host, netface)
|
||||
try:
|
||||
bring_up_ifcfg(host, config['CONFIG_NOVA_COMPUTE_PRIVIF'])
|
||||
bring_up_ifcfg(host, netface)
|
||||
except ScriptRuntimeError as ex:
|
||||
# just warn user to do it by himself
|
||||
messages.append(str(ex))
|
||||
|
@ -564,7 +567,6 @@ def create_compute_manifest(config, messages):
|
|||
manifestdata += "\n" + createFirewallResources(
|
||||
'FIREWALL_NOVA_COMPUTE_RULES'
|
||||
)
|
||||
manifestdata += "\n" + nova_config_options.getManifestEntry()
|
||||
manifestdata += "\n" + ssh_hostkeys
|
||||
appendManifestFile(manifestfile, manifestdata)
|
||||
|
||||
|
@ -585,9 +587,12 @@ def create_network_manifest(config, messages):
|
|||
config['CONFIG_NOVA_NETWORK_MULTIHOST'] = multihost and 'true' or 'false'
|
||||
for host in network_hosts:
|
||||
for i in ('CONFIG_NOVA_NETWORK_PRIVIF', 'CONFIG_NOVA_NETWORK_PUBIF'):
|
||||
check_ifcfg(host, config[i])
|
||||
netface = config[i]
|
||||
if config['CONFIG_USE_SUBNETS'] == 'y':
|
||||
netface = common.cidr_to_ifname(netface, host, config)
|
||||
check_ifcfg(host, netface)
|
||||
try:
|
||||
bring_up_ifcfg(host, config[i])
|
||||
bring_up_ifcfg(host, netface)
|
||||
except ScriptRuntimeError as ex:
|
||||
# just warn user to do it by himself
|
||||
messages.append(str(ex))
|
||||
|
|
|
@ -43,7 +43,7 @@ PLUGIN_NAME_COLORED = utils.color_text(PLUGIN_NAME, 'blue')
|
|||
|
||||
|
||||
def initConfig(controller):
|
||||
default_ssh_key = os.path.join(os.environ["HOME"], ".ssh/*.pub")
|
||||
default_ssh_key = os.path.expanduser('~/.ssh/*.pub')
|
||||
default_ssh_key = (glob.glob(default_ssh_key) + [""])[0]
|
||||
params = {
|
||||
"GLOBAL": [
|
||||
|
@ -437,6 +437,19 @@ def initConfig(controller):
|
|||
"USE_DEFAULT": False,
|
||||
"NEED_CONFIRM": False,
|
||||
"CONDITION": False},
|
||||
|
||||
{"CMD_OPTION": "use-subnets",
|
||||
"PROMPT": ("Should interface names be automatically recognized "
|
||||
"based on subnet CIDR"),
|
||||
"OPTION_LIST": ['y', 'n'],
|
||||
"VALIDATORS": [validators.validate_options],
|
||||
"DEFAULT_VALUE": "n",
|
||||
"MASK_INPUT": False,
|
||||
"LOOSE_VALIDATION": False,
|
||||
"CONF_NAME": "CONFIG_USE_SUBNETS",
|
||||
"USE_DEFAULT": False,
|
||||
"NEED_CONFIRM": False,
|
||||
"CONDITION": False},
|
||||
],
|
||||
|
||||
"VMWARE": [
|
||||
|
@ -884,7 +897,12 @@ def is_rhel():
|
|||
|
||||
def detect_os_and_version(host):
|
||||
server = utils.ScriptRunner(host)
|
||||
server.append('python -c "import platform; print platform.linux_distribution(full_distribution_name=0)[0]+\',\'+platform.linux_distribution()[1]"')
|
||||
server.append(
|
||||
'python -c "import platform; '
|
||||
'print platform.linux_distribution(full_distribution_name=0)[0]'
|
||||
'+\',\'+'
|
||||
'platform.linux_distribution()[1]"'
|
||||
)
|
||||
try:
|
||||
rc, out = server.execute()
|
||||
out = out.split(",")
|
||||
|
@ -1169,20 +1187,25 @@ def preinstall_and_discover(config, messages):
|
|||
"""
|
||||
config['HOST_LIST'] = list(filtered_hosts(config))
|
||||
|
||||
local = utils.ScriptRunner()
|
||||
local.append('rpm -q --requires %s | egrep -v "^(rpmlib|\/|perl)"'
|
||||
% basedefs.PUPPET_MODULES_PKG)
|
||||
# this can fail if there are no dependencies other than those
|
||||
# filtered out by the egrep expression.
|
||||
rc, modules_deps = local.execute(can_fail=False)
|
||||
all_deps = ''
|
||||
for pkg in basedefs.PUPPET_MODULES_PKGS:
|
||||
local = utils.ScriptRunner()
|
||||
local.append(
|
||||
'rpm -q --requires %s | egrep -v "^(rpmlib|\/|perl)"' % pkg
|
||||
)
|
||||
# this can fail if there are no dependencies other than those
|
||||
# filtered out by the egrep expression.
|
||||
rc, pkg_deps = local.execute(can_fail=False)
|
||||
errmsg = '%s is not installed' % pkg
|
||||
if errmsg in pkg_deps:
|
||||
# modules package might not be installed if we are running
|
||||
# from source; in this case we assume user knows what (s)he's
|
||||
# doing and we don't install modules dependencies
|
||||
continue
|
||||
all_deps += ' ' + pkg_deps.strip()
|
||||
|
||||
# modules package might not be installed if we are running from source;
|
||||
# in this case we assume user knows what (s)he's doing and we don't
|
||||
# install modules dependencies
|
||||
errmsg = '%s is not installed' % basedefs.PUPPET_MODULES_PKG
|
||||
deps = list(basedefs.PUPPET_DEPENDENCIES)
|
||||
if errmsg not in modules_deps:
|
||||
deps.extend([i.strip() for i in modules_deps.split() if i.strip()])
|
||||
deps.extend([i.strip() for i in all_deps.split() if i.strip()])
|
||||
|
||||
details = {}
|
||||
for hostname in config['HOST_LIST']:
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
|
||||
require 'ipaddress'
|
||||
|
||||
# Returns value
|
||||
module Puppet::Parser::Functions
|
||||
newfunction(:force_interface, :type => :rvalue) do |args|
|
||||
|
||||
if args.size < 2
|
||||
raise(
|
||||
Puppet::ParseError,
|
||||
"force_interface(): Wrong number of arguments given (#{args.size} for 2)"
|
||||
)
|
||||
end
|
||||
|
||||
value = args[0]
|
||||
allow = args[1]
|
||||
|
||||
was_array = value.kind_of?(Array)
|
||||
if not was_array
|
||||
value = [value]
|
||||
end
|
||||
|
||||
result = []
|
||||
if allow
|
||||
value.each do |val|
|
||||
translated = []
|
||||
val.split(':').each do |fragment|
|
||||
if fragment.include?('/') # this is CIDR, so translate it
|
||||
cidr = IPAddress fragment
|
||||
lookupvar('interfaces').split(',').each do |interface|
|
||||
interface.strip!
|
||||
ifaddr = lookupvar("ipaddress_#{interface}")
|
||||
ifmask = lookupvar("netmask_#{interface}")
|
||||
ifcidr = IPAddress "#{ifaddr}/#{ifmask}"
|
||||
if cidr.network == ifcidr.network
|
||||
translated.push(interface)
|
||||
end
|
||||
end
|
||||
else
|
||||
translated.push(fragment)
|
||||
end
|
||||
end
|
||||
result.push(translated.join(':'))
|
||||
end
|
||||
else
|
||||
result = value
|
||||
end
|
||||
if not was_array
|
||||
result = result[0]
|
||||
end
|
||||
result
|
||||
end
|
||||
end
|
|
@ -1 +1,8 @@
|
|||
|
||||
$use_subnets_value = hiera('CONFIG_USE_SUBNETS')
|
||||
$use_subnets = $use_subnets_value ? {
|
||||
'y' => true,
|
||||
default => false,
|
||||
}
|
||||
|
||||
Exec { timeout => hiera('DEFAULT_EXEC_TIMEOUT') }
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
|
||||
$neutron_lb_interface_mappings = hiera('CONFIG_NEUTRON_LB_INTERFACE_MAPPINGS')
|
||||
class { '::neutron::agents::linuxbridge':
|
||||
physical_interface_mappings => hiera('CONFIG_NEUTRON_LB_INTERFACE_MAPPINGS'),
|
||||
physical_interface_mappings => force_interface($neutron_lb_interface_mappings, $use_subnets),
|
||||
}
|
||||
|
|
|
@ -1,4 +1,10 @@
|
|||
$ovs_agent_vxlan_cfg_neut_ovs_tun_if = hiera('CONFIG_NEUTRON_OVS_TUNNEL_IF',undef)
|
||||
|
||||
$neutron_ovs_tunnel_if = hiera('CONFIG_NEUTRON_OVS_TUNNEL_IF', undef)
|
||||
if $neutron_ovs_tunnel_if {
|
||||
$ovs_agent_vxlan_cfg_neut_ovs_tun_if = force_interface($neutron_ovs_tunnel_if, $use_subnets)
|
||||
} else {
|
||||
$ovs_agent_vxlan_cfg_neut_ovs_tun_if = undef
|
||||
}
|
||||
|
||||
if $ovs_agent_vxlan_cfg_neut_ovs_tun_if != '' {
|
||||
$iface = regsubst($ovs_agent_vxlan_cfg_neut_ovs_tun_if, '[\.\-\:]', '_', 'G')
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
|
||||
$nova_compute_privif = hiera('CONFIG_NOVA_COMPUTE_PRIVIF')
|
||||
|
||||
nova_config {
|
||||
'DEFAULT/flat_interface': value => force_interface($nova_compute_privif, $use_subnets);
|
||||
}
|
|
@ -35,13 +35,16 @@ if $manager == 'nova.network.manager.VlanManager' {
|
|||
$net_num = 1
|
||||
}
|
||||
|
||||
$nova_network_privif = hiera('CONFIG_NOVA_NETWORK_PRIVIF')
|
||||
$nova_network_pubif = hiera('CONFIG_NOVA_NETWORK_PUBIF')
|
||||
|
||||
class { '::nova::network':
|
||||
enabled => true,
|
||||
network_manager => $manager,
|
||||
num_networks => $net_num ,
|
||||
network_size => $net_size,
|
||||
private_interface => hiera('CONFIG_NOVA_NETWORK_PRIVIF'),
|
||||
public_interface => hiera('CONFIG_NOVA_NETWORK_PUBIF'),
|
||||
private_interface => force_interface($nova_network_privif, $use_subnets),
|
||||
public_interface => force_interface($nova_network_pubif, $use_subnets),
|
||||
fixed_range => hiera('CONFIG_NOVA_NETWORK_FIXEDRANGE'),
|
||||
floating_range => hiera('CONFIG_NOVA_NETWORK_FLOATRANGE'),
|
||||
config_overrides => $overrides,
|
||||
|
@ -50,4 +53,3 @@ class { '::nova::network':
|
|||
package { 'dnsmasq':
|
||||
ensure => present,
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue