Add nodepool command tests
This commit does a small refactor of the base DB test class so that it can be used by other child classes without duplicating the work in the existing nodepool test cases. With this in place add a new test class to test nodepool commands. Currently only image-update is tested, but it should be easy to add tests for the other commands that nodepool supports. Change-Id: I6ea488a896cc456600da576af6086f95f4938bde
This commit is contained in:
parent
1a5ea47257
commit
74ef962fbe
|
@ -21,11 +21,16 @@ import os
|
|||
import random
|
||||
import string
|
||||
import subprocess
|
||||
import threading
|
||||
import tempfile
|
||||
import time
|
||||
|
||||
import fixtures
|
||||
import testresources
|
||||
import testtools
|
||||
|
||||
from nodepool import allocation
|
||||
|
||||
TRUE_VALUES = ('true', '1', 'yes')
|
||||
|
||||
|
||||
|
@ -72,6 +77,31 @@ class BaseTestCase(testtools.TestCase, testresources.ResourcedTestCase):
|
|||
self.useFixture(fixtures.MonkeyPatch('subprocess.Popen',
|
||||
LoggingPopenFactory))
|
||||
|
||||
def wait_for_threads(self):
|
||||
whitelist = ['APScheduler',
|
||||
'MainThread',
|
||||
'NodePool',
|
||||
'NodeUpdateListener',
|
||||
'Gearman client connect',
|
||||
'Gearman client poll',
|
||||
'fake-provider',
|
||||
'fake-provider1',
|
||||
'fake-provider2',
|
||||
'fake-dib-provider',
|
||||
'fake-jenkins',
|
||||
'fake-target',
|
||||
'DiskImageBuilder queue',
|
||||
]
|
||||
|
||||
while True:
|
||||
done = True
|
||||
for t in threading.enumerate():
|
||||
if t.name not in whitelist:
|
||||
done = False
|
||||
if done:
|
||||
return
|
||||
time.sleep(0.1)
|
||||
|
||||
|
||||
class AllocatorTestCase(object):
|
||||
def setUp(self):
|
||||
|
@ -139,3 +169,42 @@ class DBTestCase(BaseTestCase):
|
|||
f = MySQLSchemaFixture()
|
||||
self.useFixture(f)
|
||||
self.dburi = f.dburi
|
||||
|
||||
def setup_config(self, filename):
|
||||
configfile = os.path.join(os.path.dirname(__file__),
|
||||
'fixtures', filename)
|
||||
config = open(configfile).read()
|
||||
(fd, path) = tempfile.mkstemp()
|
||||
os.write(fd, config.format(dburi=self.dburi))
|
||||
os.close(fd)
|
||||
return path
|
||||
|
||||
def wait_for_config(self, pool):
|
||||
for x in range(300):
|
||||
if pool.config is not None:
|
||||
return
|
||||
time.sleep(0.1)
|
||||
|
||||
def waitForImage(self, pool, provider_name, image_name):
|
||||
self.wait_for_config(pool)
|
||||
while True:
|
||||
self.wait_for_threads()
|
||||
with pool.getDB().getSession() as session:
|
||||
image = session.getCurrentSnapshotImage(provider_name,
|
||||
image_name)
|
||||
if image:
|
||||
break
|
||||
time.sleep(1)
|
||||
self.wait_for_threads()
|
||||
|
||||
def waitForNodes(self, pool):
|
||||
self.wait_for_config(pool)
|
||||
allocation_history = allocation.AllocationHistory()
|
||||
while True:
|
||||
self.wait_for_threads()
|
||||
with pool.getDB().getSession() as session:
|
||||
needed = pool.getNeededNodes(session, allocation_history)
|
||||
if not needed:
|
||||
break
|
||||
time.sleep(1)
|
||||
self.wait_for_threads()
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
script-dir: .
|
||||
dburi: '{dburi}'
|
||||
|
||||
cron:
|
||||
check: '*/15 * * * *'
|
||||
cleanup: '*/1 * * * *'
|
||||
image-update: '14 2 * * *'
|
||||
|
||||
zmq-publishers:
|
||||
- tcp://localhost:8881
|
||||
|
||||
#gearman-servers:
|
||||
# - host: localhost
|
||||
|
||||
labels:
|
||||
- name: fake-label1
|
||||
image: fake-image1
|
||||
min-ready: 1
|
||||
providers:
|
||||
- name: fake-provider1
|
||||
- name: fake-label2
|
||||
image: fake-image2
|
||||
min-ready: 1
|
||||
providers:
|
||||
- name: fake-provider2
|
||||
|
||||
providers:
|
||||
- name: fake-provider1
|
||||
keypair: 'if-present-use-this-keypair'
|
||||
username: 'fake'
|
||||
password: 'fake'
|
||||
auth-url: 'fake'
|
||||
project-id: 'fake'
|
||||
max-servers: 96
|
||||
pool: 'fake'
|
||||
networks:
|
||||
- net-id: 'some-uuid'
|
||||
rate: 0.0001
|
||||
images:
|
||||
- name: fake-image1
|
||||
base-image: 'Fake Precise'
|
||||
min-ram: 8192
|
||||
name-filter: 'Fake'
|
||||
meta:
|
||||
key: value
|
||||
key2: value
|
||||
setup: prepare_node_devstack.sh
|
||||
- name: fake-provider2
|
||||
keypair: 'if-present-use-this-keypair'
|
||||
username: 'fake'
|
||||
password: 'fake'
|
||||
auth-url: 'fake'
|
||||
project-id: 'fake'
|
||||
max-servers: 96
|
||||
pool: 'fake'
|
||||
networks:
|
||||
- net-id: 'some-uuid'
|
||||
rate: 0.0001
|
||||
images:
|
||||
- name: fake-image2
|
||||
base-image: 'Fake Precise'
|
||||
min-ram: 8192
|
||||
name-filter: 'Fake'
|
||||
meta:
|
||||
key: value
|
||||
key2: value
|
||||
setup: prepare_node_devstack.sh
|
||||
|
||||
targets:
|
||||
- name: fake-target
|
||||
jenkins:
|
||||
url: https://jenkins.example.org/
|
||||
user: fake
|
||||
apikey: fake
|
|
@ -0,0 +1,61 @@
|
|||
# Copyright (C) 2015 OpenStack Foundation
|
||||
#
|
||||
# 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.
|
||||
|
||||
import sys # noqa making sure its available for monkey patching
|
||||
|
||||
import fixtures
|
||||
|
||||
from nodepool.cmd import nodepoolcmd
|
||||
from nodepool import tests
|
||||
|
||||
|
||||
class TestNodepoolCMD(tests.DBTestCase):
|
||||
def patch_argv(self, *args):
|
||||
argv = ["nodepool"]
|
||||
argv.extend(args)
|
||||
self.useFixture(fixtures.MonkeyPatch('sys.argv', argv))
|
||||
|
||||
def test_snapshot_image_update(self):
|
||||
configfile = self.setup_config("node.yaml")
|
||||
self.patch_argv("-c", configfile, "image-update",
|
||||
"fake-provider", "fake-image")
|
||||
nodepoolcmd.main()
|
||||
|
||||
def test_dib_image_update(self):
|
||||
configfile = self.setup_config("node_dib.yaml")
|
||||
self.patch_argv("-c", configfile, "image-update",
|
||||
"fake-dib-provider", "fake-dib-image")
|
||||
nodepoolcmd.main()
|
||||
|
||||
def test_dib_snapshot_image_update(self):
|
||||
configfile = self.setup_config("node_dib_and_snap.yaml")
|
||||
self.patch_argv("-c", configfile, "image-update",
|
||||
"fake-provider1", "fake-dib-image")
|
||||
nodepoolcmd.main()
|
||||
self.patch_argv("-c", configfile, "image-update",
|
||||
"fake-provider2", "fake-dib-image")
|
||||
nodepoolcmd.main()
|
||||
|
||||
def test_dib_snapshot_image_update_all(self):
|
||||
configfile = self.setup_config("node_dib_and_snap.yaml")
|
||||
self.patch_argv("-c", configfile, "image-update",
|
||||
"all", "fake-dib-image")
|
||||
nodepoolcmd.main()
|
||||
|
||||
def test_image_update_all(self):
|
||||
configfile = self.setup_config("node_cmd.yaml")
|
||||
self.patch_argv("-c", configfile, "image-update",
|
||||
"all", "fake-image1")
|
||||
nodepoolcmd.main()
|
|
@ -13,87 +13,17 @@
|
|||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import os
|
||||
import tempfile
|
||||
import threading
|
||||
import time
|
||||
|
||||
from nodepool import allocation
|
||||
from nodepool import tests
|
||||
from nodepool import nodedb
|
||||
import nodepool.nodepool
|
||||
|
||||
|
||||
class TestNodepool(tests.DBTestCase):
|
||||
def setup_config(self, filename):
|
||||
configfile = os.path.join(os.path.dirname(tests.__file__),
|
||||
'fixtures', filename)
|
||||
config = open(configfile).read()
|
||||
(fd, path) = tempfile.mkstemp()
|
||||
os.write(fd, config.format(dburi=self.dburi))
|
||||
os.close(fd)
|
||||
return path
|
||||
|
||||
def wait_for_threads(self):
|
||||
whitelist = ['APScheduler',
|
||||
'MainThread',
|
||||
'NodePool',
|
||||
'NodeUpdateListener',
|
||||
'Gearman client connect',
|
||||
'Gearman client poll',
|
||||
'fake-provider',
|
||||
'fake-provider1',
|
||||
'fake-provider2',
|
||||
'fake-dib-provider',
|
||||
'fake-jenkins',
|
||||
'fake-target',
|
||||
'DiskImageBuilder queue'
|
||||
]
|
||||
|
||||
while True:
|
||||
done = True
|
||||
for t in threading.enumerate():
|
||||
if t.name not in whitelist:
|
||||
done = False
|
||||
if done:
|
||||
return
|
||||
time.sleep(0.1)
|
||||
|
||||
def wait_for_config(self, pool):
|
||||
for x in range(300):
|
||||
if pool.config is not None:
|
||||
return
|
||||
time.sleep(0.1)
|
||||
|
||||
def test_db(self):
|
||||
db = nodedb.NodeDatabase(self.dburi)
|
||||
with db.getSession() as session:
|
||||
session.getNodes()
|
||||
|
||||
def waitForImage(self, pool, provider_name, image_name):
|
||||
self.wait_for_config(pool)
|
||||
while True:
|
||||
self.wait_for_threads()
|
||||
with pool.getDB().getSession() as session:
|
||||
image = session.getCurrentSnapshotImage(provider_name,
|
||||
image_name)
|
||||
if image:
|
||||
break
|
||||
time.sleep(1)
|
||||
self.wait_for_threads()
|
||||
|
||||
def waitForNodes(self, pool):
|
||||
self.wait_for_config(pool)
|
||||
allocation_history = allocation.AllocationHistory()
|
||||
while True:
|
||||
self.wait_for_threads()
|
||||
with pool.getDB().getSession() as session:
|
||||
needed = pool.getNeededNodes(session, allocation_history)
|
||||
if not needed:
|
||||
break
|
||||
time.sleep(1)
|
||||
self.wait_for_threads()
|
||||
|
||||
def test_node(self):
|
||||
"""Test that an image and node are created"""
|
||||
configfile = self.setup_config('node.yaml')
|
||||
|
|
Loading…
Reference in New Issue