blob: bd22da3467bf16f4e0ed37b0faefd682b074ce85 [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):
Clark Boylan24620182017-04-24 10:11:51 -070031 super(TestNodepoolIntegration, self).setUp()
James E. Blairf88b8172017-01-24 13:37:21 -080032
David Shrewsbury5e898282018-02-05 14:44:16 -050033 self.statsd = None
James E. Blairf88b8172017-01-24 13:37:21 -080034 self.zk = zuul.zk.ZooKeeper()
Clark Boylanffe8f8b2017-04-24 17:36:11 -070035 self.addCleanup(self.zk.disconnect)
Paul Belanger9790c6a2017-03-20 16:48:11 -040036 self.zk.connect('localhost:2181')
Paul Belanger97e807b2017-03-21 15:06:35 -040037 self.hostname = socket.gethostname()
James E. Blairf88b8172017-01-24 13:37:21 -080038
39 self.provisioned_requests = []
40 # This class implements the scheduler methods zuul.nodepool
41 # needs, so we pass 'self' as the scheduler.
42 self.nodepool = zuul.nodepool.Nodepool(self)
43
44 def waitForRequests(self):
45 # Wait until all requests are complete.
46 while self.nodepool.requests:
47 time.sleep(0.1)
48
49 def onNodesProvisioned(self, request):
50 # This is a scheduler method that the nodepool class calls
51 # back when a request is provisioned.
52 self.provisioned_requests.append(request)
53
54 def test_node_request(self):
55 # Test a simple node request
56
57 nodeset = model.NodeSet()
David Shrewsbury349b23b2017-02-09 14:12:41 -050058 nodeset.addNode(model.Node('controller', 'fake-label'))
James E. Blairf88b8172017-01-24 13:37:21 -080059 job = model.Job('testjob')
60 job.nodeset = nodeset
61 request = self.nodepool.requestNodes(None, job)
62 self.waitForRequests()
63 self.assertEqual(len(self.provisioned_requests), 1)
David Shrewsburye054b902017-01-26 08:22:25 -050064 self.assertEqual(request.state, model.STATE_FULFILLED)
James E. Blairf88b8172017-01-24 13:37:21 -080065
66 # Accept the nodes
67 self.nodepool.acceptNodes(request)
68 nodeset = request.nodeset
69
70 for node in nodeset.getNodes():
71 self.assertIsNotNone(node.lock)
David Shrewsburye054b902017-01-26 08:22:25 -050072 self.assertEqual(node.state, model.STATE_READY)
James E. Blairf88b8172017-01-24 13:37:21 -080073
74 # Mark the nodes in use
75 self.nodepool.useNodeSet(nodeset)
76 for node in nodeset.getNodes():
David Shrewsburye054b902017-01-26 08:22:25 -050077 self.assertEqual(node.state, model.STATE_IN_USE)
James E. Blairf88b8172017-01-24 13:37:21 -080078
79 # Return the nodes
80 self.nodepool.returnNodeSet(nodeset)
81 for node in nodeset.getNodes():
82 self.assertIsNone(node.lock)
David Shrewsburye054b902017-01-26 08:22:25 -050083 self.assertEqual(node.state, model.STATE_USED)
84
85 def test_invalid_node_request(self):
86 # Test requests with an invalid node type fail
87 nodeset = model.NodeSet()
88 nodeset.addNode(model.Node('controller', 'invalid-label'))
89 job = model.Job('testjob')
90 job.nodeset = nodeset
91 request = self.nodepool.requestNodes(None, job)
92 self.waitForRequests()
93 self.assertEqual(len(self.provisioned_requests), 1)
94 self.assertEqual(request.state, model.STATE_FAILED)
James E. Blairf88b8172017-01-24 13:37:21 -080095
96 @skip("Disabled until nodepool is ready")
97 def test_node_request_disconnect(self):
98 # Test that node requests are re-submitted after disconnect
99
100 nodeset = model.NodeSet()
101 nodeset.addNode(model.Node('controller', 'ubuntu-xenial'))
102 nodeset.addNode(model.Node('compute', 'ubuntu-xenial'))
103 job = model.Job('testjob')
104 job.nodeset = nodeset
105 self.fake_nodepool.paused = True
106 request = self.nodepool.requestNodes(None, job)
107 self.zk.client.stop()
108 self.zk.client.start()
109 self.fake_nodepool.paused = False
110 self.waitForRequests()
111 self.assertEqual(len(self.provisioned_requests), 1)
David Shrewsburye054b902017-01-26 08:22:25 -0500112 self.assertEqual(request.state, model.STATE_FULFILLED)
James E. Blairf88b8172017-01-24 13:37:21 -0800113
114 @skip("Disabled until nodepool is ready")
115 def test_node_request_canceled(self):
116 # Test that node requests can be canceled
117
118 nodeset = model.NodeSet()
119 nodeset.addNode(model.Node('controller', 'ubuntu-xenial'))
120 nodeset.addNode(model.Node('compute', 'ubuntu-xenial'))
121 job = model.Job('testjob')
122 job.nodeset = nodeset
123 self.fake_nodepool.paused = True
124 request = self.nodepool.requestNodes(None, job)
125 self.nodepool.cancelRequest(request)
126
127 self.waitForRequests()
128 self.assertEqual(len(self.provisioned_requests), 0)