Apply floating ip for node according to configuration

When we deploy nodepool and zuul instances in virtual machine of
cloud provider, the provisioned nodes may be in the same internal
network with nodepool and zuul instances, in that case we don't
have to allocate floating ip for nodes, zuul can talk with nodes
via fixed ip of virtual machines. So if we can customize the behavior,
save the quota of floating ip, it's awesome.

Note: Although option "floating_ip_source: None" in clouds.yaml can
decide to apply floating ip or not for specified cloud, but that impact
all the SDKs and tools that use the clouds.yaml, we should control
nodepool behavior flexibly and independently.

This patch add a bool option "auto-floating-ip" into each pool of
"provider" section in nodepool.conf

Change-Id: Ia9a1bed6dd4f6e39015bde660f52e4cd6addb26e
This commit is contained in:
Rui Chen
2017-11-10 17:30:29 +08:00
parent 73e5d8bdd4
commit 32e1e0b616
9 changed files with 144 additions and 4 deletions

View File

@@ -380,6 +380,7 @@ Example::
- az1
networks:
- some-network-name
auto-floating-ip: False
labels:
- name: trusty
min-ram: 8192
@@ -417,6 +418,12 @@ Example::
Specify custom Neutron networks that get attached to each
node. Specify the name or id of the network as a string.
``auto-floating-ip`` (bool)
Specify custom behavior of allocating floating ip for each node.
When set to False, nodepool-launcher will not apply floating ip
for nodes. When zuul instances and nodes are deployed in the same
internal private network, set the option to False to save floating ip
for cloud provider. The default value is True.
.. _provider_diskimages:

View File

@@ -52,6 +52,7 @@ class ConfigValidator:
pool = {
'name': str,
'networks': [str],
'auto-floating-ip': bool,
'max-servers': int,
'labels': [pool_label],
'availability-zones': [str],

View File

@@ -278,6 +278,7 @@ def loadConfig(config_path):
pp.max_servers = pool['max-servers']
pp.azs = pool.get('availability-zones')
pp.networks = pool.get('networks', [])
pp.auto_floating_ip = bool(pool.get('auto-floating-ip', True))
pp.labels = {}
for label in pool.get('labels', []):
pl = ProviderLabel()

View File

@@ -218,9 +218,18 @@ class FakeOpenStackCloud(object):
result = self._get(name_or_id, self._server_list)
return result
def _clean_floating_ip(self, server):
server.public_v4 = ''
server.public_v6 = ''
server.interface_ip = server.private_v4
return server
def wait_for_server(self, server, **kwargs):
while server.status == 'BUILD':
time.sleep(0.1)
auto_ip = kwargs.get('auto_ip')
if not auto_ip:
server = self._clean_floating_ip(server)
return server
def list_servers(self):

View File

@@ -158,7 +158,8 @@ class NodeLauncher(threading.Thread, stats.StatsReporter):
self.log.debug("Waiting for server %s for node id: %s" %
(server.id, self._node.id))
server = self._manager.waitForServer(
server, self._provider.launch_timeout)
server, self._provider.launch_timeout,
auto_ip=self._pool.auto_floating_ip)
if server.status != 'ACTIVE':
raise exceptions.LaunchStatusException("Server %s for node id: %s "

View File

@@ -214,11 +214,11 @@ class OpenStackProvider(Provider):
except shade.OpenStackCloudException:
return None
def waitForServer(self, server, timeout=3600):
def waitForServer(self, server, timeout=3600, auto_ip=True):
with shade_inner_exceptions():
return self._client.wait_for_server(
server=server, auto_ip=True, reuse=False,
timeout=timeout)
server=server, auto_ip=auto_ip,
reuse=False, timeout=timeout)
def waitForNodeCleanup(self, server_id, timeout=600):
for count in iterate_timeout(

View File

@@ -33,6 +33,7 @@ providers:
pools:
- name: main
max-servers: 184
auto-floating-ip: True
labels:
- name: trusty
diskimage: trusty
@@ -59,6 +60,7 @@ providers:
pools:
- name: main
max-servers: 184
auto-floating-ip: False
labels:
- name: trusty
diskimage: trusty

View File

@@ -0,0 +1,84 @@
elements-dir: .
images-dir: '{images_dir}'
zookeeper-servers:
- host: {zookeeper_host}
port: {zookeeper_port}
chroot: {zookeeper_chroot}
labels:
- name: fake-label1
min-ready: 1
- name: fake-label2
min-ready: 1
- name: fake-label3
min-ready: 1
providers:
- name: fake-provider1
cloud: fake
driver: fake
region-name: fake-region
rate: 0.0001
diskimages:
- name: fake-image
pools:
- name: main
max-servers: 96
networks:
- 'some-name'
auto-floating-ip: False
labels:
- name: fake-label1
diskimage: fake-image
min-ram: 8192
- name: fake-provider2
cloud: fake
driver: fake
region-name: fake-region
rate: 0.0001
diskimages:
- name: fake-image
pools:
- name: main
max-servers: 96
networks:
- 'some-name'
auto-floating-ip: True
labels:
- name: fake-label2
diskimage: fake-image
min-ram: 8192
- name: fake-provider3
cloud: fake
driver: fake
region-name: fake-region
rate: 0.0001
diskimages:
- name: fake-image
pools:
- name: main
max-servers: 96
networks:
- 'some-name'
# Test default value of auto-floating-ip is True
labels:
- name: fake-label3
diskimage: fake-image
min-ram: 8192
diskimages:
- name: fake-image
elements:
- fedora
- vm
release: 21
env-vars:
TMPDIR: /opt/dib_tmp
DIB_IMAGE_CACHE: /opt/dib_cache
DIB_CLOUD_IMAGES: http://download.fedoraproject.org/pub/fedora/linux/releases/test/21-Beta/Cloud/Images/x86_64/
BASE_IMAGE_FILE: Fedora-Cloud-Base-20141029-21_Beta.x86_64.qcow2

View File

@@ -683,3 +683,38 @@ class TestLauncher(tests.DBTestCase):
# max-servers, req2 should get declined now, and transition to FAILED
req2 = self.waitForNodeRequest(req2, (zk.FAILED,))
self.assertNotEqual(req2.declined_by, [])
def test_node_auto_floating_ip(self):
"""Test that auto-floating-ip option works fine."""
configfile = self.setup_config('node_auto_floating_ip.yaml')
pool = self.useNodepool(configfile, watermark_sleep=1)
self._useBuilder(configfile)
pool.start()
self.waitForImage('fake-provider1', 'fake-image')
self.waitForImage('fake-provider2', 'fake-image')
self.waitForImage('fake-provider3', 'fake-image')
label1_nodes = self.waitForNodes('fake-label1')
label2_nodes = self.waitForNodes('fake-label2')
label3_nodes = self.waitForNodes('fake-label3')
self.assertEqual(1, len(label1_nodes))
self.assertEqual(1, len(label2_nodes))
self.assertEqual(1, len(label3_nodes))
# auto-floating-ip: False
self.assertEqual('fake-provider1', label1_nodes[0].provider)
self.assertEqual('', label1_nodes[0].public_ipv4)
self.assertEqual('', label1_nodes[0].public_ipv6)
self.assertEqual('fake', label1_nodes[0].interface_ip)
# auto-floating-ip: True
self.assertEqual('fake-provider2', label2_nodes[0].provider)
self.assertEqual('fake', label2_nodes[0].public_ipv4)
self.assertEqual('', label2_nodes[0].public_ipv6)
self.assertEqual('fake', label2_nodes[0].interface_ip)
# auto-floating-ip: default value
self.assertEqual('fake-provider3', label3_nodes[0].provider)
self.assertEqual('fake', label3_nodes[0].public_ipv4)
self.assertEqual('', label3_nodes[0].public_ipv6)
self.assertEqual('fake', label3_nodes[0].interface_ip)