Delete network VIPs on stack delete
Update the tripleo_overcloud_network_vip_provision module to remove obsolete network vip ports for a stack by keeping a list of managed vip ports in 'managed_ports', then run a cleanup to delete any port with the apropriate tags that are not in the 'managed_ports' list to keep the provisioned resources state matching the VIPs defined in the vip_data. On stack delete, call the module without specifying any vip_data, so that the remove_obsolete_ports method will delete any network VIP port resources associated with the stack. Also add cli-overcloud-network-vip-unprovision.yaml. Related-Blueprint: blueprint network-data-v2-ports Change-Id: Idcfd47dcfe6d635da4cc6bb6f18cbaa2a3bc4a6e
This commit is contained in:
parent
8011f82f1c
commit
260cdbf00c
@ -56,6 +56,7 @@ options:
|
||||
description:
|
||||
- Dictionary of network Virtual IP definitions
|
||||
type: list
|
||||
default: []
|
||||
elements: dict
|
||||
suboptions:
|
||||
name:
|
||||
@ -146,13 +147,13 @@ def create_port_def(vip_spec, net_maps):
|
||||
else:
|
||||
raise Exception(
|
||||
'Network {} has multiple subnets, please add a subnet or an '
|
||||
'ip_address for the vip on whit network.'.format(
|
||||
'ip_address for the vip on this network.'.format(
|
||||
vip_spec['network']))
|
||||
|
||||
return port_def
|
||||
|
||||
|
||||
def provision_vip_port(conn, stack, net_maps, vip_spec):
|
||||
def provision_vip_port(conn, stack, net_maps, vip_spec, managed_ports):
|
||||
port_def = create_port_def(vip_spec, net_maps)
|
||||
|
||||
tags = ['tripleo_stack_name={}'.format(stack),
|
||||
@ -164,6 +165,7 @@ def provision_vip_port(conn, stack, net_maps, vip_spec):
|
||||
|
||||
try:
|
||||
port = next(ports)
|
||||
managed_ports.append(port.id)
|
||||
del port_def['network_id']
|
||||
for k, v in port_def.items():
|
||||
if port.get(k) != v:
|
||||
@ -172,6 +174,7 @@ def provision_vip_port(conn, stack, net_maps, vip_spec):
|
||||
except StopIteration:
|
||||
port = conn.network.create_port(**port_def)
|
||||
conn.network.set_tags(port, tags)
|
||||
managed_ports.append(port.id)
|
||||
|
||||
|
||||
def validate_vip_nets_in_net_map(vip_data, net_maps):
|
||||
@ -187,6 +190,15 @@ def validate_vip_nets_in_net_map(vip_data, net_maps):
|
||||
vip['subnet'], vip['network']))
|
||||
|
||||
|
||||
def remove_obsolete_ports(conn, stack, managed_ports):
|
||||
ports = conn.network.ports(tags=['tripleo_stack_name={}'.format(stack)])
|
||||
ports = [p for p in ports if any("tripleo_vip_net" in t for t in p.tags)]
|
||||
|
||||
for port in ports:
|
||||
if port.id not in managed_ports:
|
||||
conn.network.delete_port(port.id)
|
||||
|
||||
|
||||
def run_module():
|
||||
result = dict(
|
||||
success=False,
|
||||
@ -205,8 +217,8 @@ def run_module():
|
||||
)
|
||||
|
||||
concurrency = module.params['concurrency']
|
||||
stack = module.params['stack_name']
|
||||
vip_data = module.params['vip_data']
|
||||
stack = module.params.get('stack_name')
|
||||
vip_data = module.params.get('vip_data')
|
||||
|
||||
try:
|
||||
_, conn = openstack_cloud_from_module(module)
|
||||
@ -215,14 +227,16 @@ def run_module():
|
||||
|
||||
# no limit on concurrency, create a worker for every vip
|
||||
if concurrency < 1:
|
||||
concurrency = len(vip_data)
|
||||
concurrency = len(vip_data) if len(vip_data) > 0 else 1
|
||||
|
||||
exceptions = list()
|
||||
provision_jobs = list()
|
||||
managed_ports = list()
|
||||
with futures.ThreadPoolExecutor(max_workers=concurrency) as p:
|
||||
for vip_spec in vip_data:
|
||||
provision_jobs.append(p.submit(
|
||||
provision_vip_port, conn, stack, net_maps, vip_spec))
|
||||
provision_vip_port, conn, stack, net_maps, vip_spec,
|
||||
managed_ports))
|
||||
|
||||
for job in futures.as_completed(provision_jobs):
|
||||
e = job.exception()
|
||||
@ -232,6 +246,8 @@ def run_module():
|
||||
if exceptions:
|
||||
raise exceptions[0]
|
||||
|
||||
remove_obsolete_ports(conn, stack, managed_ports)
|
||||
|
||||
result['success'] = True
|
||||
module.exit_json(**result)
|
||||
except Exception as err:
|
||||
|
@ -45,6 +45,9 @@
|
||||
until: stack_delete is success
|
||||
delay: 4
|
||||
retries: 16
|
||||
- name: Delete overcloud network Virtual IPs
|
||||
tripleo_overcloud_network_vip_provision:
|
||||
stack_name: "{{ stack_name }}"
|
||||
post_tasks:
|
||||
- name: Workflow notice
|
||||
debug:
|
||||
|
@ -0,0 +1,35 @@
|
||||
---
|
||||
# Copyright 2021 Red Hat, Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
- name: Overcloud Virtual IPs Unprovision
|
||||
connection: "{{ (tripleo_target_host is defined) | ternary('ssh', 'local') }}"
|
||||
hosts: "{{ tripleo_target_host | default('localhost') }}"
|
||||
remote_user: "{{ tripleo_target_user | default(lookup('env', 'USER')) }}"
|
||||
gather_facts: "{{ (tripleo_target_host is defined) | ternary(true, false) }}"
|
||||
any_errors_fatal: true
|
||||
vars:
|
||||
overwrite: false
|
||||
pre_tasks:
|
||||
- fail:
|
||||
msg: stack_name is a required input
|
||||
when:
|
||||
- stack_name is undefined
|
||||
|
||||
tasks:
|
||||
|
||||
- name: Delete Overcloud Virtual IPs
|
||||
tripleo_overcloud_network_vip_provision:
|
||||
stack_name: "{{ stack_name | default('overcloud') }}"
|
@ -109,7 +109,7 @@ class TestTripleoOvercloudVipProvision(tests_base.TestCase):
|
||||
vip_spec = {'network': 'network1'}
|
||||
msg = (
|
||||
'Network {} has multiple subnets, please add a subnet or an '
|
||||
'ip_address for the vip on whit network.'.format(
|
||||
'ip_address for the vip on this network.'.format(
|
||||
vip_spec['network']))
|
||||
self.assertRaisesRegex(Exception, msg,
|
||||
plugin.create_port_def, vip_spec, NET_MAPS)
|
||||
@ -120,7 +120,9 @@ class TestTripleoOvercloudVipProvision(tests_base.TestCase):
|
||||
'ip_address': '1.2.3.4',
|
||||
'dns_name': 'overcloud'}
|
||||
mock_conn.network.ports.return_value = self.a2g([])
|
||||
plugin.provision_vip_port(mock_conn, 'stack', NET_MAPS, vip_spec)
|
||||
managed_ports = list()
|
||||
plugin.provision_vip_port(mock_conn, 'stack', NET_MAPS, vip_spec,
|
||||
managed_ports)
|
||||
mock_conn.network.create_port.assert_called_with(
|
||||
dns_name='overcloud',
|
||||
fixed_ips=[{'ip_address': '1.2.3.4'}],
|
||||
@ -142,7 +144,10 @@ class TestTripleoOvercloudVipProvision(tests_base.TestCase):
|
||||
tags=['tripleo_stack_name=stack', 'tripleo_vip_net=network1']
|
||||
)
|
||||
mock_conn.network.ports.return_value = self.a2g([fake_port])
|
||||
plugin.provision_vip_port(mock_conn, 'stack', NET_MAPS, vip_spec)
|
||||
managed_ports = list()
|
||||
plugin.provision_vip_port(mock_conn, 'stack', NET_MAPS, vip_spec,
|
||||
managed_ports)
|
||||
self.assertEqual([fake_port.id], managed_ports)
|
||||
mock_conn.network.create_port.assert_not_called()
|
||||
mock_conn.network.update_port.assert_not_called()
|
||||
mock_conn.network.set_tags.assert_not_called()
|
||||
@ -164,8 +169,37 @@ class TestTripleoOvercloudVipProvision(tests_base.TestCase):
|
||||
'fixed_ips': [{'ip_address': '11.22.33.44'}],
|
||||
'name': 'network1_virtual_ip'}
|
||||
mock_conn.network.ports.return_value = self.a2g([fake_port])
|
||||
plugin.provision_vip_port(mock_conn, 'stack', NET_MAPS, vip_spec)
|
||||
managed_ports = list()
|
||||
plugin.provision_vip_port(mock_conn, 'stack', NET_MAPS, vip_spec,
|
||||
managed_ports)
|
||||
self.assertEqual([fake_port.id], managed_ports)
|
||||
mock_conn.network.create_port.assert_not_called()
|
||||
mock_conn.network.update_port.assert_called_with(fake_port.id,
|
||||
**port_def)
|
||||
mock_conn.network.set_tags.assert_not_called()
|
||||
|
||||
def test_remove_obsolete_ports_deletes_port(self, mock_conn):
|
||||
fake_port = stubs.FakeNeutronPort(
|
||||
id='port_id',
|
||||
name='network1_virtual_ip',
|
||||
network_id='network1_id',
|
||||
fixed_ips=[{'ip_address': '1.2.3.4'}],
|
||||
dns_name='overcloud',
|
||||
tags=['tripleo_stack_name=stack', 'tripleo_vip_net=network1']
|
||||
)
|
||||
mock_conn.network.ports.return_value = self.a2g([fake_port])
|
||||
plugin.remove_obsolete_ports(mock_conn, 'stack', [])
|
||||
mock_conn.network.delete_port.assert_called_once_with(fake_port.id)
|
||||
|
||||
def test_remove_obsolete_ports_does_not_delete_managed(self, mock_conn):
|
||||
fake_port = stubs.FakeNeutronPort(
|
||||
id='port_id',
|
||||
name='network1_virtual_ip',
|
||||
network_id='network1_id',
|
||||
fixed_ips=[{'ip_address': '1.2.3.4'}],
|
||||
dns_name='overcloud',
|
||||
tags=['tripleo_stack_name=stack', 'tripleo_vip_net=network1']
|
||||
)
|
||||
mock_conn.network.ports.return_value = self.a2g([fake_port])
|
||||
plugin.remove_obsolete_ports(mock_conn, 'stack', [fake_port.id])
|
||||
mock_conn.network.delete_port.assert_not_called()
|
||||
|
Loading…
Reference in New Issue
Block a user