blob: 2c9a9b3f108f9a0661686a3296c6977536e8f268 [file] [log] [blame]
James E. Blairf88b8172017-01-24 13:37:21 -08001# Copyright 2017 Red Hat, Inc.
2#
3# Licensed under the Apache License, Version 2.0 (the "License"); you may
4# not use this file except in compliance with the License. You may obtain
5# a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12# License for the specific language governing permissions and limitations
13# under the License.
14
Paul Belanger97e807b2017-03-21 15:06:35 -040015import socket
James E. Blairf88b8172017-01-24 13:37:21 -080016import time
17from unittest import skip
18
19import zuul.zk
20import zuul.nodepool
21from zuul import model
22
23from tests.base import BaseTestCase
24
25
26class TestNodepoolIntegration(BaseTestCase):
27 # Tests the Nodepool interface class using a *real* nodepool and
28 # fake scheduler.
29
30 def setUp(self):
31 super(BaseTestCase, self).setUp()
32
James E. Blairf88b8172017-01-24 13:37:21 -080033 self.zk = zuul.zk.ZooKeeper()
Paul Belanger9790c6a2017-03-20 16:48:11 -040034 self.zk.connect('localhost:2181')
Paul Belanger97e807b2017-03-21 15:06:35 -040035 self.hostname = socket.gethostname()
James E. Blairf88b8172017-01-24 13:37:21 -080036
37 self.provisioned_requests = []
38 # This class implements the scheduler methods zuul.nodepool
39 # needs, so we pass 'self' as the scheduler.
40 self.nodepool = zuul.nodepool.Nodepool(self)
41
42 def waitForRequests(self):
43 # Wait until all requests are complete.
44 while self.nodepool.requests:
45 time.sleep(0.1)
46
47 def onNodesProvisioned(self, request):
48 # This is a scheduler method that the nodepool class calls
49 # back when a request is provisioned.
50 self.provisioned_requests.append(request)
51
52 def test_node_request(self):
53 # Test a simple node request
54
55 nodeset = model.NodeSet()
David Shrewsbury349b23b2017-02-09 14:12:41 -050056 nodeset.addNode(model.Node('controller', 'fake-label'))
James E. Blairf88b8172017-01-24 13:37:21 -080057 job = model.Job('testjob')
58 job.nodeset = nodeset
59 request = self.nodepool.requestNodes(None, job)
60 self.waitForRequests()
61 self.assertEqual(len(self.provisioned_requests), 1)
David Shrewsburye054b902017-01-26 08:22:25 -050062 self.assertEqual(request.state, model.STATE_FULFILLED)
James E. Blairf88b8172017-01-24 13:37:21 -080063
64 # Accept the nodes
65 self.nodepool.acceptNodes(request)
66 nodeset = request.nodeset
67
68 for node in nodeset.getNodes():
69 self.assertIsNotNone(node.lock)
David Shrewsburye054b902017-01-26 08:22:25 -050070 self.assertEqual(node.state, model.STATE_READY)
James E. Blairf88b8172017-01-24 13:37:21 -080071
72 # Mark the nodes in use
73 self.nodepool.useNodeSet(nodeset)
74 for node in nodeset.getNodes():
David Shrewsburye054b902017-01-26 08:22:25 -050075 self.assertEqual(node.state, model.STATE_IN_USE)
James E. Blairf88b8172017-01-24 13:37:21 -080076
77 # Return the nodes
78 self.nodepool.returnNodeSet(nodeset)
79 for node in nodeset.getNodes():
80 self.assertIsNone(node.lock)
David Shrewsburye054b902017-01-26 08:22:25 -050081 self.assertEqual(node.state, model.STATE_USED)
82
83 def test_invalid_node_request(self):
84 # Test requests with an invalid node type fail
85 nodeset = model.NodeSet()
86 nodeset.addNode(model.Node('controller', 'invalid-label'))
87 job = model.Job('testjob')
88 job.nodeset = nodeset
89 request = self.nodepool.requestNodes(None, job)
90 self.waitForRequests()
91 self.assertEqual(len(self.provisioned_requests), 1)
92 self.assertEqual(request.state, model.STATE_FAILED)
James E. Blairf88b8172017-01-24 13:37:21 -080093
94 @skip("Disabled until nodepool is ready")
95 def test_node_request_disconnect(self):
96 # Test that node requests are re-submitted after disconnect
97
98 nodeset = model.NodeSet()
99 nodeset.addNode(model.Node('controller', 'ubuntu-xenial'))
100 nodeset.addNode(model.Node('compute', 'ubuntu-xenial'))
101 job = model.Job('testjob')
102 job.nodeset = nodeset
103 self.fake_nodepool.paused = True
104 request = self.nodepool.requestNodes(None, job)
105 self.zk.client.stop()
106 self.zk.client.start()
107 self.fake_nodepool.paused = False
108 self.waitForRequests()
109 self.assertEqual(len(self.provisioned_requests), 1)
David Shrewsburye054b902017-01-26 08:22:25 -0500110 self.assertEqual(request.state, model.STATE_FULFILLED)
James E. Blairf88b8172017-01-24 13:37:21 -0800111
112 @skip("Disabled until nodepool is ready")
113 def test_node_request_canceled(self):
114 # Test that node requests can be canceled
115
116 nodeset = model.NodeSet()
117 nodeset.addNode(model.Node('controller', 'ubuntu-xenial'))
118 nodeset.addNode(model.Node('compute', 'ubuntu-xenial'))
119 job = model.Job('testjob')
120 job.nodeset = nodeset
121 self.fake_nodepool.paused = True
122 request = self.nodepool.requestNodes(None, job)
123 self.nodepool.cancelRequest(request)
124
125 self.waitForRequests()
126 self.assertEqual(len(self.provisioned_requests), 0)