From e37085aba5026262780418c8cb69acadb7631ebc Mon Sep 17 00:00:00 2001 From: Bart Wensley Date: Thu, 22 Nov 2018 16:03:53 -0600 Subject: [PATCH] Enable communication from nova-api-proxy to VIM Prior to kubernetes integration, the nova-api-proxy communicated with the VIM using port 30003 on the loopback address. This worked fine when both the nova-api-proxy and the VIM were running on bare metal. When nova-api-proxy is running in a pod, it cannot use the loopback address to communicate with the VIM, since the loopback address is local to the pod. The nova-api-proxy pod will instead use the floating management address (which is present on all systems) to communicate with the VIM. The problem is that on AIO simplex systems, the floating management address is also in the loopback subnet. The fix for this is to use a non-loopback address for management on AIO simplex systems. This required changes to configuration scripts/utilities to allow the user to specify the management subnet on AIO simplex systems, instead of hardcoding it to a loopback address. Change-Id: I26c15657471f8214e628c6d43eaab07eb8e744ec Story: 2003910 Task: 28061 Depends-on: Ib7c08bfc1c661a9fb347308e55cc806b4dd129ad Signed-off-by: Bart Wensley --- .../configutilities/common/configobjects.py | 15 +- .../configutilities/common/validator.py | 57 +++- .../configutilities/configfiletool.py | 251 ++++++++++-------- .../controllerconfig/common/constants.py | 2 +- .../controllerconfig/configassistant.py | 57 +++- .../tests/files/system_config.simplex_mgmt | 25 ++ .../tests/test_system_config.py | 56 ++++ .../src/modules/platform/manifests/network.pp | 12 +- sysinv/sysinv/sysinv/sysinv/puppet/nfv.py | 7 + 9 files changed, 349 insertions(+), 133 deletions(-) create mode 100644 controllerconfig/controllerconfig/controllerconfig/tests/files/system_config.simplex_mgmt diff --git a/configutilities/configutilities/configutilities/common/configobjects.py b/configutilities/configutilities/configutilities/common/configobjects.py index 7f9a0d99f7..91406c6656 100755 --- a/configutilities/configutilities/configutilities/common/configobjects.py +++ b/configutilities/configutilities/configutilities/common/configobjects.py @@ -133,7 +133,8 @@ class Network(object): def parse_config(self, system_config, config_type, network_type, min_addresses=0, multicast_addresses=0, optional=False, - naming_type=DEFAULT_NAMES): + naming_type=DEFAULT_NAMES, + logical_interface_required=True): network_prefix = NETWORK_PREFIX_NAMES[naming_type][network_type] network_name = network_prefix + '_NETWORK' @@ -375,8 +376,10 @@ class Network(object): gateway_address_str, network_name, e)) # Parse/validate the logical interface - logical_interface_name = system_config.get( - network_name, attr_prefix + 'LOGICAL_INTERFACE') - self.logical_interface = LogicalInterface() - self.logical_interface.parse_config(system_config, - logical_interface_name) + if logical_interface_required or system_config.has_option( + network_name, attr_prefix + 'LOGICAL_INTERFACE'): + logical_interface_name = system_config.get( + network_name, attr_prefix + 'LOGICAL_INTERFACE') + self.logical_interface = LogicalInterface() + self.logical_interface.parse_config(system_config, + logical_interface_name) diff --git a/configutilities/configutilities/configutilities/common/validator.py b/configutilities/configutilities/configutilities/common/validator.py index 072742e355..088a9e767d 100755 --- a/configutilities/configutilities/configutilities/common/validator.py +++ b/configutilities/configutilities/configutilities/common/validator.py @@ -69,6 +69,7 @@ class ConfigValidator(object): self.glance_region = None self.system_mode = None self.system_type = None + self.system_dc_role = None def is_simplex_cpe(self): return self.system_mode == SYSTEM_MODE_SIMPLEX @@ -79,6 +80,9 @@ class ConfigValidator(object): def set_system_mode(self, mode): self.system_mode = mode + def set_system_dc_role(self, dc_role): + self.system_dc_role = dc_role + def set_oam_config(self, use_lag, external_oam_interface_name): if self.cgcs_conf is not None: self.cgcs_conf.add_section('cEXT_OAM') @@ -165,6 +169,45 @@ class ConfigValidator(object): except Exception as e: raise ConfigFail("Error parsing configuration file: %s" % e) + def validate_aio_simplex_mgmt(self): + # AIO simplex management network configuration + mgmt_prefix = NETWORK_PREFIX_NAMES[self.naming_type][MGMT_TYPE] + self.mgmt_network = Network() + + min_addresses = 16 + + try: + self.mgmt_network.parse_config(self.conf, self.config_type, + MGMT_TYPE, + min_addresses=min_addresses, + multicast_addresses=0, + naming_type=self.naming_type, + logical_interface_required=False) + + except ConfigFail: + raise + except Exception as e: + raise ConfigFail("Error parsing configuration file: %s" % e) + + if self.mgmt_network.vlan or self.mgmt_network.multicast_cidr or \ + self.mgmt_network.start_end_in_config or \ + self.mgmt_network.floating_address or \ + self.mgmt_network.address_0 or self.mgmt_network.address_1 or \ + self.mgmt_network.dynamic_allocation or \ + self.mgmt_network.gateway_address or \ + self.mgmt_network.logical_interface: + raise ConfigFail("For AIO simplex, only the %s network CIDR can " + "be specified" % mgmt_prefix) + + if self.mgmt_network.cidr.version == 6: + raise ConfigFail("IPv6 management network not supported on " + "simplex configuration.") + + if self.cgcs_conf is not None: + self.cgcs_conf.add_section('cMGMT') + self.cgcs_conf.set('cMGMT', 'MANAGEMENT_SUBNET', + self.mgmt_network.cidr) + def validate_aio_network(self, subcloud=False): if not subcloud: # AIO-SX subcloud supports MGMT_NETWORK & PXEBOOT_NETWORK @@ -172,8 +215,7 @@ class ConfigValidator(object): raise ConfigFail("PXEBoot Network configuration is not " "supported.") if self.conf.has_section('MGMT_NETWORK'): - raise ConfigFail("Management Network configuration is not " - "supported.") + self.validate_aio_simplex_mgmt() if self.conf.has_section('INFRA_NETWORK'): raise ConfigFail("Infrastructure Network configuration is not " "supported.") @@ -192,6 +234,17 @@ class ConfigValidator(object): "No gateway specified - %s_GATEWAY must be specified" % oam_prefix) + # Check overlap with management network + if self.mgmt_network is not None: + try: + self.configured_networks.append(self.mgmt_network.cidr) + check_network_overlap(self.oam_network.cidr, + self.configured_networks) + except ValidateFail: + raise ConfigFail("%s CIDR %s overlaps with another configured " + "network" % + (oam_prefix, str(self.mgmt_network.cidr))) + self.set_oam_config(use_lag, external_oam_interface_name) def validate_version(self): diff --git a/configutilities/configutilities/configutilities/configfiletool.py b/configutilities/configutilities/configutilities/configfiletool.py index ef9589309a..5b875a528a 100755 --- a/configutilities/configutilities/configutilities/configfiletool.py +++ b/configutilities/configutilities/configutilities/configfiletool.py @@ -288,6 +288,10 @@ class ConfigPage(WizardPage): if mode: validator.set_system_mode(mode) + dc_role = get_opt('SYSTEM', 'DISTRIBUTED_CLOUD_ROLE') + if dc_role: + validator.set_system_dc_role(dc_role) + for method in self.validator_methods: getattr(validator, method)() @@ -808,14 +812,12 @@ class SYSTEMPage(ConfigPage): event.Skip() def skip_not_required_pages(self, skip): - # Skip PXEBOOT, MGMT, BMC and INFRA pages + # Skip PXEBOOT, BMC and INFRA pages self.parent.skip_page(PXEBootPage, skip) - self.parent.skip_page(MGMTPage, skip) self.parent.skip_page(INFRAPage, skip) # Remove the sections that are not required config.remove_section("PXEBOOT_NETWORK") - config.remove_section("MGMT_NETWORK") config.remove_section("BOARD_MANAGEMENT_NETWORK") config.remove_section("INFRA_NETWORK") @@ -894,117 +896,134 @@ class MGMTPage(ConfigPage): LINK_SPEED_10G, LINK_SPEED_25G] self.section = "MGMT_NETWORK" - self.validator_methods = ["validate_pxeboot", "validate_mgmt"] + if get_opt('SYSTEM', 'SYSTEM_MODE') != 'simplex': + self.validator_methods = ["validate_pxeboot", "validate_mgmt"] + self.help_text = ( + "The management network is used for internal communication " + "between platform components. IP addresses on this network " + "are reachable only within the data center.") + else: + self.validator_methods = ["validate_aio_simplex_mgmt"] + self.help_text = ( + "The management network is used for internal communication " + "between platform components. IP addresses on this network " + "are reachable only within the host.") self.title = "Management Network" - self.help_text = ( - "The management network is used for internal communication " - "between platform components. IP addresses on this network " - "are reachable only within the data center.") self.set_fields() self.do_setup() self.bind_events() def set_fields(self): - self.fields['mgmt_port1'] = Field( - text="Management interface", - type=TYPES.string, - initial="enp0s8", - transient=True - ) - self.fields['lag_help'] = Field( - text="A management bond interface provides redundant " - "connections for the management network. When selected, the " - "field above specifies the first member of the bond.", - type=TYPES.help, - ) - self.fields['LAG_INTERFACE'] = Field( - text="Use management interface link aggregation", - type=TYPES.checkbox, - shows=["LAG_MODE", "mgmt_port2"], - transient=True - ) - self.fields['LAG_MODE'] = Field( - text="Management interface bonding policy", - type=TYPES.choice, - choices=self.lag_choices.keys(), - transient=True - ) - self.fields['mgmt_port2'] = Field( - text="Second management interface member", - type=TYPES.string, - initial="", - transient=True - ) - self.fields['INTERFACE_MTU'] = Field( - text="Management interface MTU", - type=TYPES.int, - initial="1500", - transient=True - ) - self.fields['INTERFACE_LINK_CAPACITY'] = Field( - text="Management interface link capacity Mbps", - type=TYPES.choice, - choices=self.mgmt_speed_choices, - initial=self.mgmt_speed_choices[0], - transient=True - ) - if config.has_option('PXEBOOT_NETWORK', 'PXEBOOT_CIDR') or \ - config.has_option('REGION2_PXEBOOT_NETWORK', 'PXEBOOT_CIDR'): - self.fields['vlan_help'] = Field( - text=("A management VLAN is required because a separate " - "PXEBoot network was configured on the management " - "interface."), - type=TYPES.help + if get_opt('SYSTEM', 'SYSTEM_MODE') != 'simplex': + self.fields['mgmt_port1'] = Field( + text="Management interface", + type=TYPES.string, + initial="enp0s8", + transient=True ) - self.fields['VLAN'] = Field( - text="Management VLAN Identifier", - type=TYPES.int, + self.fields['lag_help'] = Field( + text="A management bond interface provides redundant " + "connections for the management network. When selected, " + "the field above specifies the first member of the bond.", + type=TYPES.help, + ) + self.fields['LAG_INTERFACE'] = Field( + text="Use management interface link aggregation", + type=TYPES.checkbox, + shows=["LAG_MODE", "mgmt_port2"], + transient=True + ) + self.fields['LAG_MODE'] = Field( + text="Management interface bonding policy", + type=TYPES.choice, + choices=self.lag_choices.keys(), + transient=True + ) + self.fields['mgmt_port2'] = Field( + text="Second management interface member", + type=TYPES.string, initial="", + transient=True ) - self.fields['CIDR'] = Field( - text="Management subnet", - type=TYPES.string, - initial="192.168.204.0/24", - ) - self.fields['MULTICAST_CIDR'] = Field( - text="Management multicast subnet", - type=TYPES.string, - initial='239.1.1.0/28' - ) + self.fields['INTERFACE_MTU'] = Field( + text="Management interface MTU", + type=TYPES.int, + initial="1500", + transient=True + ) + self.fields['INTERFACE_LINK_CAPACITY'] = Field( + text="Management interface link capacity Mbps", + type=TYPES.choice, + choices=self.mgmt_speed_choices, + initial=self.mgmt_speed_choices[0], + transient=True + ) + if config.has_option('PXEBOOT_NETWORK', 'PXEBOOT_CIDR') or \ + config.has_option('REGION2_PXEBOOT_NETWORK', + 'PXEBOOT_CIDR'): + self.fields['vlan_help'] = Field( + text=("A management VLAN is required because a separate " + "PXEBoot network was configured on the management " + "interface."), + type=TYPES.help + ) + self.fields['VLAN'] = Field( + text="Management VLAN Identifier", + type=TYPES.int, + initial="", + ) - # Start/end ranges - self.fields['use_entire_subnet'] = Field( - text="Restrict management subnet address range", - type=TYPES.checkbox, - shows=["IP_START_ADDRESS", "IP_END_ADDRESS"], - transient=True - ) - self.fields['IP_START_ADDRESS'] = Field( - text="Management network start address", - type=TYPES.string, - initial="192.168.204.2", - ) - self.fields['IP_END_ADDRESS'] = Field( - text="Management network end address", - type=TYPES.string, - initial="192.168.204.254", - ) + self.fields['CIDR'] = Field( + text="Management subnet", + type=TYPES.string, + initial="192.168.204.0/24", + ) - # Dynamic addressing - self.fields['dynamic_help'] = Field( - text=( - "IP addresses can be assigned to hosts dynamically or " - "a static IP address can be specified for each host. " - "Note: This choice applies to both the management network " - "and infrastructure network."), - type=TYPES.help, - ) - self.fields['DYNAMIC_ALLOCATION'] = Field( - text="Use dynamic IP address allocation", - type=TYPES.checkbox, - initial='Y' - ) + self.fields['MULTICAST_CIDR'] = Field( + text="Management multicast subnet", + type=TYPES.string, + initial='239.1.1.0/28' + ) + + # Start/end ranges + self.fields['use_entire_subnet'] = Field( + text="Restrict management subnet address range", + type=TYPES.checkbox, + shows=["IP_START_ADDRESS", "IP_END_ADDRESS"], + transient=True + ) + self.fields['IP_START_ADDRESS'] = Field( + text="Management network start address", + type=TYPES.string, + initial="192.168.204.2", + ) + self.fields['IP_END_ADDRESS'] = Field( + text="Management network end address", + type=TYPES.string, + initial="192.168.204.254", + ) + + # Dynamic addressing + self.fields['dynamic_help'] = Field( + text=( + "IP addresses can be assigned to hosts dynamically or " + "a static IP address can be specified for each host. " + "Note: This choice applies to both the management network " + "and infrastructure network."), + type=TYPES.help, + ) + self.fields['DYNAMIC_ALLOCATION'] = Field( + text="Use dynamic IP address allocation", + type=TYPES.checkbox, + initial='Y' + ) + else: + self.fields['CIDR'] = Field( + text="Management subnet", + type=TYPES.string, + initial="192.168.204.0/28", + ) def validate_page(self): super(MGMTPage, self).validate_page() @@ -1013,19 +1032,21 @@ class MGMTPage(ConfigPage): def get_config(self): super(MGMTPage, self).get_config() - # Add logical interface - ports = self.fields['mgmt_port1'].get_value() - if self.fields['mgmt_port2'].get_value(): - ports += "," + self.fields['mgmt_port2'].get_value() - li = create_li( - lag=self.fields['LAG_INTERFACE'].get_value(), - mode=self.lag_choices.get(self.fields['LAG_MODE'].get_value()), - mtu=self.fields['INTERFACE_MTU'].get_value(), - link_capacity=self.fields['INTERFACE_LINK_CAPACITY'].get_value(), - ports=ports - ) - config.set(self.section, 'LOGICAL_INTERFACE', li) - clean_lis() + if get_opt('SYSTEM', 'SYSTEM_MODE') != 'simplex': + # Add logical interface + ports = self.fields['mgmt_port1'].get_value() + if self.fields['mgmt_port2'].get_value(): + ports += "," + self.fields['mgmt_port2'].get_value() + li = create_li( + lag=self.fields['LAG_INTERFACE'].get_value(), + mode=self.lag_choices.get(self.fields['LAG_MODE'].get_value()), + mtu=self.fields['INTERFACE_MTU'].get_value(), + link_capacity=self.fields[ + 'INTERFACE_LINK_CAPACITY'].get_value(), + ports=ports + ) + config.set(self.section, 'LOGICAL_INTERFACE', li) + clean_lis() class INFRAPage(ConfigPage): diff --git a/controllerconfig/controllerconfig/controllerconfig/common/constants.py b/controllerconfig/controllerconfig/controllerconfig/common/constants.py index 5a218a580e..54dba506d8 100644 --- a/controllerconfig/controllerconfig/controllerconfig/common/constants.py +++ b/controllerconfig/controllerconfig/controllerconfig/common/constants.py @@ -87,7 +87,7 @@ LOOPBACK_IFNAME = 'lo' DEFAULT_MULTICAST_SUBNET_IPV4 = '239.1.1.0/28' DEFAULT_MULTICAST_SUBNET_IPV6 = 'ff08::1:1:0/124' -DEFAULT_MGMT_ON_LOOPBACK_SUBNET_IPV4 = '127.168.204.0/24' +DEFAULT_MGMT_ON_LOOPBACK_SUBNET_IPV4 = '192.168.204.0/28' DEFAULT_REGION_NAME = "RegionOne" DEFAULT_SERVICE_PROJECT_NAME = "services" diff --git a/controllerconfig/controllerconfig/controllerconfig/configassistant.py b/controllerconfig/controllerconfig/controllerconfig/configassistant.py index 55486527b1..b29eaa1564 100644 --- a/controllerconfig/controllerconfig/controllerconfig/configassistant.py +++ b/controllerconfig/controllerconfig/controllerconfig/configassistant.py @@ -1322,13 +1322,47 @@ class ConfigAssistant(): """ Management interface configuration complete""" self.management_interface_configured = True - def populate_aio_management_config(self): - """Populate management on aio interface config.""" + def input_aio_simplex_management_config(self, management_subnet=None): + """Allow user to input AIO simplex management config and perform + validation.""" + + if management_subnet is not None: + self.management_subnet = management_subnet + else: + print "\nManagement Network:" + print "-------------------\n" + + print textwrap.fill( + "The management network is used for internal communication " + "between platform components. IP addresses on this network " + "are reachable only within the host.", 80) + print + + self.management_subnet = IPNetwork( + constants.DEFAULT_MGMT_ON_LOOPBACK_SUBNET_IPV4) + min_addresses = 16 + while True: + user_input = input("Management subnet [" + + str(self.management_subnet) + "]: ") + if user_input.lower() == 'q': + raise UserQuit + elif user_input == "": + user_input = self.management_subnet + + try: + tmp_management_subnet = validate_network_str(user_input, + min_addresses) + if tmp_management_subnet.version == 6: + print ("IPv6 management network not supported on " + + "simplex configuration") + continue + self.management_subnet = tmp_management_subnet + break + except ValidateFail as e: + print "{}".format(e) self.management_interface = constants.LOOPBACK_IFNAME self.management_interface_name = constants.LOOPBACK_IFNAME - self.management_subnet = IPNetwork( - constants.DEFAULT_MGMT_ON_LOOPBACK_SUBNET_IPV4) self.management_start_address = self.management_subnet[2] self.management_end_address = self.management_subnet[-2] self.controller_floating_address = self.management_start_address @@ -2307,7 +2341,7 @@ class ConfigAssistant(): self.check_storage_config() if self.system_mode == sysinv_constants.SYSTEM_MODE_SIMPLEX: self.default_pxeboot_config() - self.populate_aio_management_config() + self.input_aio_simplex_management_config() else: # An AIO system cannot function as a Distributed Cloud System # Controller @@ -2425,9 +2459,16 @@ class ConfigAssistant(): # Management network configuration if self.system_mode == sysinv_constants.SYSTEM_MODE_SIMPLEX and \ not self.subcloud_config(): - # For AIO-SX subcloud, mgmt n/w will be on a separate - # physical interface instead of the loopback interface. - self.populate_aio_management_config() + # For AIO-SX, only the management subnet is configurable + # (unless this is a subcloud). + if config.has_option('cMGMT', 'MANAGEMENT_SUBNET'): + management_subnet = IPNetwork(config.get( + 'cMGMT', 'MANAGEMENT_SUBNET')) + else: + management_subnet = IPNetwork( + constants.DEFAULT_MGMT_ON_LOOPBACK_SUBNET_IPV4) + self.input_aio_simplex_management_config( + management_subnet=management_subnet) else: self.management_interface_name = config.get( 'cMGMT', 'MANAGEMENT_INTERFACE_NAME') diff --git a/controllerconfig/controllerconfig/controllerconfig/tests/files/system_config.simplex_mgmt b/controllerconfig/controllerconfig/controllerconfig/tests/files/system_config.simplex_mgmt new file mode 100644 index 0000000000..c8c204d8d7 --- /dev/null +++ b/controllerconfig/controllerconfig/controllerconfig/tests/files/system_config.simplex_mgmt @@ -0,0 +1,25 @@ +[LOGICAL_INTERFACE_1] +LAG_INTERFACE=N +;LAG_MODE= +INTERFACE_MTU=1500 +;INTERFACE_LINK_CAPACITY= +INTERFACE_PORTS=eth0 + +[MGMT_NETWORK] +CIDR=192.168.42.0/28 + +[OAM_NETWORK] +IP_ADDRESS=10.10.10.20 +CIDR=10.10.10.0/24 +GATEWAY=10.10.10.1 +LOGICAL_INTERFACE=LOGICAL_INTERFACE_1 + +[AUTHENTICATION] +ADMIN_PASSWORD=Li69nux* + +[VERSION] +RELEASE = TEST.SW.VERSION + +[SYSTEM] +SYSTEM_TYPE=All-in-one +SYSTEM_MODE=simplex diff --git a/controllerconfig/controllerconfig/controllerconfig/tests/test_system_config.py b/controllerconfig/controllerconfig/controllerconfig/tests/test_system_config.py index c179e7f1f9..c0a9b8fbee 100644 --- a/controllerconfig/controllerconfig/controllerconfig/tests/test_system_config.py +++ b/controllerconfig/controllerconfig/controllerconfig/tests/test_system_config.py @@ -107,6 +107,62 @@ def test_system_config_simplex(): _test_system_config(systemfile) +def test_system_config_simplex_mgmt(): + """ Test import of system_config file for AIO-simplex with management + configuration""" + + # Create the path to the system_config file + systemfile = os.path.join( + os.getcwd(), "controllerconfig/tests/files/", + "system_config.simplex_mgmt") + + _test_system_config(systemfile) + + # Test MGMT_NETWORK parameters that are not allowed + system_config = cr.parse_system_config(systemfile) + system_config.set('MGMT_NETWORK', 'GATEWAY', '192.168.42.1') + with pytest.raises(exceptions.ConfigFail): + cr.create_cgcs_config_file(None, system_config, None, None, None, 0, + validate_only=True) + with pytest.raises(exceptions.ConfigFail): + validate(system_config, DEFAULT_CONFIG, None, False) + system_config = cr.parse_system_config(systemfile) + system_config.set('MGMT_NETWORK', 'LOGICAL_INTERFACE', + 'LOGICAL_INTERFACE_1') + with pytest.raises(exceptions.ConfigFail): + cr.create_cgcs_config_file(None, system_config, None, None, None, 0, + validate_only=True) + with pytest.raises(exceptions.ConfigFail): + validate(system_config, DEFAULT_CONFIG, None, False) + + # Test overlap with OAM network + system_config = cr.parse_system_config(systemfile) + system_config.set('MGMT_NETWORK', 'CIDR', '10.10.10.0/24') + with pytest.raises(exceptions.ConfigFail): + cr.create_cgcs_config_file(None, system_config, None, None, None, 0, + validate_only=True) + with pytest.raises(exceptions.ConfigFail): + validate(system_config, DEFAULT_CONFIG, None, False) + + # Test IPv6 management CIDR (not supported) + system_config = cr.parse_system_config(systemfile) + system_config.set('MGMT_NETWORK', 'CIDR', 'FD01::0000/64') + with pytest.raises(exceptions.ConfigFail): + cr.create_cgcs_config_file(None, system_config, None, None, None, 0, + validate_only=True) + with pytest.raises(exceptions.ConfigFail): + validate(system_config, DEFAULT_CONFIG, None, False) + + # Test management CIDR that is too small + system_config = cr.parse_system_config(systemfile) + system_config.set('MGMT_NETWORK', 'CIDR', '192.168.42.0/29') + with pytest.raises(exceptions.ConfigFail): + cr.create_cgcs_config_file(None, system_config, None, None, None, 0, + validate_only=True) + with pytest.raises(exceptions.ConfigFail): + validate(system_config, DEFAULT_CONFIG, None, False) + + def test_system_config_validation(): """ Test detection of various errors in system_config file """ diff --git a/puppet-manifests/src/modules/platform/manifests/network.pp b/puppet-manifests/src/modules/platform/manifests/network.pp index e1f9c56840..9c164ed94e 100644 --- a/puppet-manifests/src/modules/platform/manifests/network.pp +++ b/puppet-manifests/src/modules/platform/manifests/network.pp @@ -86,10 +86,20 @@ define network_address ( $address, $ifname, ) { + # In AIO simplex configurations, the management addresses are assigned to the + # loopback interface. These addresses must be assigned using the host scope + # or assignment is prevented (can't have multiple global scope addresses on + # the loopback interface). + if $ifname == 'lo' { + $options = 'scope host' + } else { + $options = '' + } + # addresses should only be configured if running in simplex, otherwise SM # will configure them on the active controller. exec { "Configuring ${name} IP address": - command => "ip addr replace ${address} dev ${ifname}", + command => "ip addr replace ${address} dev ${ifname} ${options}", onlyif => "test -f /etc/platform/simplex", } } diff --git a/sysinv/sysinv/sysinv/sysinv/puppet/nfv.py b/sysinv/sysinv/sysinv/sysinv/puppet/nfv.py index e4740e1811..49592314d6 100644 --- a/sysinv/sysinv/sysinv/sysinv/puppet/nfv.py +++ b/sysinv/sysinv/sysinv/sysinv/puppet/nfv.py @@ -181,6 +181,13 @@ class NfvPuppet(openstack.OpenstackBasePuppet): nova_oslo_messaging_data['password'], } config.update(rabbit_config) + + # Listen to nova api proxy on management address + nova_api_proxy_config = { + 'nfv::nfvi::compute_rest_api_host': + self._get_management_address(), + } + config.update(nova_api_proxy_config) else: # The openstack auth info is still required as the VIM will # audit some keystone entities (e.g. tenants). Point it to