Merge "Add 'public' attribute to 'networks' entry"

This commit is contained in:
Jenkins 2016-01-05 21:41:38 +00:00 committed by Gerrit Code Review
commit 761e56061c
8 changed files with 164 additions and 31 deletions

View File

@ -288,8 +288,8 @@ provider, the Nodepool image types are also defined (see
image-type: qcow2
ipv6-preferred: False
networks:
- net-id: 'some-uuid'
- net-label: 'some-network-name'
- name: 'some-network-name'
public: True
images:
- name: trusty
base-image: 'Trusty'
@ -393,11 +393,10 @@ provider, the Nodepool image types are also defined (see
Default None
``networks`` (dict)
Specify custom Neutron networks that get attached to each node. You can
specify Neutron networks using either the ``net-id`` or ``net-label``. If
only the ``net-label`` is specified the network UUID is automatically
queried via the Nova os-tenant-networks API extension (this requires that
the cloud provider has deployed this extension).
Specify custom Neutron networks that get attached to each
node. Specify the ``name`` of the network (a string) and if the
network routes to the Internet, set the boolean ``public`` to
true.
``ipv6_preferred``
If it is set to True, nodepool will try to find ipv6 in public net first

View File

@ -43,6 +43,16 @@ class ConfigValidator:
'config-drive': bool,
}
old_network = {
'net-id': str,
'net-label': str,
}
network = {
'name': v.Required(str),
'public': bool,
}
providers = {
'name': str,
'region-name': str,
@ -59,10 +69,7 @@ class ConfigValidator:
'max-servers': int,
'pool': str,
'image-type': str,
'networks': [{
'net-id': str,
'net-label': str,
}],
'networks': [v.Any(old_network, network)],
'boot-timeout': int,
'api-timeout': int,
'rate': float,

View File

@ -190,6 +190,19 @@ class FakeGlanceClient(object):
self.images = images
class FakeNeutronClient(object):
def __init__(self, networks=None):
if networks is None:
networks = [dict(id='fake-public-network-uuid',
name='fake-public-network-name'),
dict(id='fake-private-network-uuid',
name='fake-private-network-name')]
self.networks = networks
def list_networks(self):
return dict(networks=self.networks)
class FakeOpenStackCloud(object):
def __init__(self, images=None):
if images is None:
@ -200,6 +213,7 @@ class FakeOpenStackCloud(object):
metadata={})])
self.nova_client = FakeClient(images)
self._glance_client = FakeGlanceClient(images)
self.neutron_client = FakeNeutronClient()
def create_image(self, **kwargs):
image = self._glance_client.images.create(**kwargs)

View File

@ -1227,7 +1227,11 @@ class SnapshotImageUpdater(ImageUpdater):
class ConfigValue(object):
pass
def __eq__(self, other):
if isinstance(other, ConfigValue):
if other.__dict__ == self.__dict__:
return True
return False
class Config(ConfigValue):
@ -1270,6 +1274,10 @@ class DiskImage(ConfigValue):
pass
class Network(ConfigValue):
pass
class NodePool(threading.Thread):
log = logging.getLogger("nodepool.NodePool")
@ -1372,7 +1380,20 @@ class NodePool(threading.Thread):
p.boot_timeout = provider.get('boot-timeout', 60)
p.launch_timeout = provider.get('launch-timeout', 3600)
p.use_neutron = bool(provider.get('networks', ()))
p.networks = provider.get('networks')
p.networks = []
for network in provider.get('networks', []):
n = Network()
p.networks.append(n)
if 'net-id' in network:
n.id = network['net-id']
n.name = None
elif 'net-label' in network:
n.name = network['net-label']
n.id = None
else:
n.name = network.get('name')
n.id = None
n.public = network.get('public', False)
p.ipv6_preferred = provider.get('ipv6-preferred')
p.azs = provider.get('availability-zones')
p.template_hostname = provider.get(

View File

@ -36,7 +36,7 @@ SERVER_LIST_AGE = 5 # How long to keep a cached copy of the server list
IPS_LIST_AGE = 5 # How long to keep a cached copy of the ip list
def get_public_ip(server, version=4):
def get_public_ip(server, provider, version=4):
for addr in server.addresses.get('public', []):
if type(addr) == type(u''): # Rackspace/openstack 1.0
return addr
@ -56,6 +56,12 @@ def get_public_ip(server, version=4):
for addr in server.addresses.get('Ext-Net', []):
if addr['version'] == version: # OVH
return addr['addr']
if provider.use_neutron: # Internap
for network in provider.networks:
if network.public and network.name:
for addr in server.addresses.get(network.name, []):
if addr['version'] == version:
return addr['addr']
return None
@ -83,7 +89,7 @@ def get_private_ip(server):
return ret[0]
def make_server_dict(server):
def make_server_dict(server, provider):
d = dict(id=str(server.id),
name=server.name,
status=server.status,
@ -96,9 +102,9 @@ def make_server_dict(server):
d['progress'] = server.progress
if hasattr(server, 'metadata'):
d['metadata'] = server.metadata
d['public_v4'] = get_public_ip(server)
d['public_v4'] = get_public_ip(server, provider)
d['private_v4'] = get_private_ip(server)
d['public_v6'] = get_public_ip(server, version=6)
d['public_v6'] = get_public_ip(server, provider, version=6)
return d
@ -122,11 +128,12 @@ class CreateServerTask(Task):
class GetServerTask(Task):
def main(self, client):
provider = self.args.pop('_nodepool_provider')
try:
server = client.nova_client.servers.get(self.args['server_id'])
except novaclient.exceptions.NotFound:
raise NotFound()
return make_server_dict(server)
return make_server_dict(server, provider)
class DeleteServerTask(Task):
@ -136,8 +143,10 @@ class DeleteServerTask(Task):
class ListServersTask(Task):
def main(self, client):
provider = self.args.pop('_nodepool_provider')
servers = client.nova_client.servers.list()
return [make_server_dict(server) for server in servers]
return [make_server_dict(server, provider)
for server in servers]
class AddKeypairTask(Task):
@ -247,7 +256,7 @@ class DeleteImageTask(Task):
class FindNetworkTask(Task):
def main(self, client):
for network in client.neutron_client.list_networks()['networks']:
if self.args['label'] == network['name']:
if self.args['name'] == network['name']:
return dict(id=str(network['id']))
@ -340,11 +349,11 @@ class ProviderManager(TaskManager):
self._images[name] = image
return image
def findNetwork(self, label):
if label in self._networks:
return self._networks[label]
network = self.submitTask(FindNetworkTask(label=label))
self._networks[label] = network
def findNetwork(self, name):
if name in self._networks:
return self._networks[name]
network = self.submitTask(FindNetworkTask(name=name))
self._networks[name] = network
return network
def deleteImage(self, name):
@ -381,10 +390,10 @@ class ProviderManager(TaskManager):
if self.provider.use_neutron:
nics = []
for network in self.provider.networks:
if 'net-id' in network:
nics.append({'net-id': network['net-id']})
elif 'net-label' in network:
net_id = self.findNetwork(network['net-label'])['id']
if network.id:
nics.append({'net-id': network.id})
elif network.name:
net_id = self.findNetwork(network.name)['id']
nics.append({'net-id': net_id})
else:
raise Exception("Invalid 'networks' configuration.")
@ -412,7 +421,8 @@ class ProviderManager(TaskManager):
return self.submitTask(CreateServerTask(**create_args))
def getServer(self, server_id):
return self.submitTask(GetServerTask(server_id=server_id))
return self.submitTask(GetServerTask(server_id=server_id,
_nodepool_provider=self.provider))
def getFloatingIP(self, ip_id):
return self.submitTask(GetFloatingIPTask(ip_id=ip_id))
@ -571,7 +581,8 @@ class ProviderManager(TaskManager):
# data until it succeeds.
if self._servers_lock.acquire(False):
try:
self._servers = self.submitTask(ListServersTask())
self._servers = self.submitTask(ListServersTask(
_nodepool_provider=self.provider))
self._servers_time = time.time()
finally:
self._servers_lock.release()

View File

@ -883,6 +883,23 @@ providers:
diskimage: devstack-fedora21-dib
username: jenkins
private-key: /home/nodepool/.ssh/id_rsa
- name: internap-nyj01
region-name: 'nyj01'
cloud: internap
api-timeout: 60
boot-timeout: 120
max-servers: 0
rate: 0.001
networks:
- name: inap-17304-WAN2342
public: True
images:
- name: centos-6
min-ram: 8000
name-filter: 'A1.8'
diskimage: centos-6
username: jenkins
private-key: /home/nodepool/.ssh/id_rsa
- name: tripleo-test-cloud-hp1
service-type: 'compute'
service-name: 'nova'

View File

@ -0,0 +1,49 @@
script-dir: .
images-dir: '{images_dir}'
cron:
check: '*/15 * * * *'
cleanup: '*/1 * * * *'
image-update: '14 2 * * *'
zmq-publishers:
- tcp://localhost:8881
gearman-servers:
- host: localhost
port: {gearman_port}
labels:
- name: fake-label
image: fake-image
min-ready: 1
providers:
- name: fake-provider
providers:
- name: fake-provider
region-name: fake-region
keypair: 'if-present-use-this-keypair'
username: 'fake'
password: 'fake'
auth-url: 'fake'
project-id: 'fake'
max-servers: 96
pool: 'fake'
networks:
- name: 'fake-public-network-name'
public: true
- name: 'fake-private-network-name'
rate: 0.0001
images:
- name: fake-image
base-image: 'Fake Precise'
min-ram: 8192
name-filter: 'Fake'
meta:
key: value
key2: value
setup: prepare_node_devstack.sh
targets:
- name: fake-target

View File

@ -49,6 +49,21 @@ class TestNodepool(tests.DBTestCase):
state=nodedb.READY)
self.assertEqual(len(nodes), 1)
def test_node_net_name(self):
"""Test that a node is created with a net name"""
configfile = self.setup_config('node_net_name.yaml')
pool = self.useNodepool(configfile, watermark_sleep=1)
pool.start()
self.waitForImage(pool, 'fake-provider', 'fake-image')
self.waitForNodes(pool)
with pool.getDB().getSession() as session:
nodes = session.getNodes(provider_name='fake-provider',
label_name='fake-label',
target_name='fake-target',
state=nodedb.READY)
self.assertEqual(len(nodes), 1)
def test_dib_node(self):
"""Test that a dib image and node are created"""
configfile = self.setup_config('node_dib.yaml')