blob: 9c87a1036dadb92d7e12cfdc0e02129e48b919ae [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
James E. Blairf88b8172017-01-24 13:37:21 -080033 self.zk = zuul.zk.ZooKeeper()
Clark Boylanffe8f8b2017-04-24 17:36:11 -070034 self.addCleanup(self.zk.disconnect)
Paul Belanger9790c6a2017-03-20 16:48:11 -040035 self.zk.connect('localhost:2181')
Paul Belanger97e807b2017-03-21 15:06:35 -040036 self.hostname = socket.gethostname()
James E. Blairf88b8172017-01-24 13:37:21 -080037
38 self.provisioned_requests = []
39 # This class implements the scheduler methods zuul.nodepool
40 # needs, so we pass 'self' as the scheduler.
41 self.nodepool = zuul.nodepool.Nodepool(self)
42
43 def waitForRequests(self):
44 # Wait until all requests are complete.
45 while self.nodepool.requests:
46 time.sleep(0.1)
47
48 def onNodesProvisioned(self, request):
49 # This is a scheduler method that the nodepool class calls
50 # back when a request is provisioned.
51 self.provisioned_requests.append(request)
52
53 def test_node_request(self):
54 # Test a simple node request
55
56 nodeset = model.NodeSet()
David Shrewsbury349b23b2017-02-09 14:12:41 -050057 nodeset.addNode(model.Node('controller', 'fake-label'))
James E. Blairf88b8172017-01-24 13:37:21 -080058 job = model.Job('testjob')
59 job.nodeset = nodeset
60 request = self.nodepool.requestNodes(None, job)
61 self.waitForRequests()
62 self.assertEqual(len(self.provisioned_requests), 1)
David Shrewsburye054b902017-01-26 08:22:25 -050063 self.assertEqual(request.state, model.STATE_FULFILLED)
James E. Blairf88b8172017-01-24 13:37:21 -080064
65 # Accept the nodes
66 self.nodepool.acceptNodes(request)
67 nodeset = request.nodeset
68
69 for node in nodeset.getNodes():
70 self.assertIsNotNone(node.lock)
David Shrewsburye054b902017-01-26 08:22:25 -050071 self.assertEqual(node.state, model.STATE_READY)
James E. Blairf88b8172017-01-24 13:37:21 -080072
73 # Mark the nodes in use
74 self.nodepool.useNodeSet(nodeset)
75 for node in nodeset.getNodes():
David Shrewsburye054b902017-01-26 08:22:25 -050076 self.assertEqual(node.state, model.STATE_IN_USE)
James E. Blairf88b8172017-01-24 13:37:21 -080077
78 # Return the nodes
79 self.nodepool.returnNodeSet(nodeset)
80 for node in nodeset.getNodes():
81 self.assertIsNone(node.lock)
David Shrewsburye054b902017-01-26 08:22:25 -050082 self.assertEqual(node.state, model.STATE_USED)
83
84 def test_invalid_node_request(self):
85 # Test requests with an invalid node type fail
86 nodeset = model.NodeSet()
87 nodeset.addNode(model.Node('controller', 'invalid-label'))
88 job = model.Job('testjob')
89 job.nodeset = nodeset
90 request = self.nodepool.requestNodes(None, job)
91 self.waitForRequests()
92 self.assertEqual(len(self.provisioned_requests), 1)
93 self.assertEqual(request.state, model.STATE_FAILED)
James E. Blairf88b8172017-01-24 13:37:21 -080094
95 @skip("Disabled until nodepool is ready")
96 def test_node_request_disconnect(self):
97 # Test that node requests are re-submitted after disconnect
98
99 nodeset = model.NodeSet()
100 nodeset.addNode(model.Node('controller', 'ubuntu-xenial'))
101 nodeset.addNode(model.Node('compute', 'ubuntu-xenial'))
102 job = model.Job('testjob')
103 job.nodeset = nodeset
104 self.fake_nodepool.paused = True
105 request = self.nodepool.requestNodes(None, job)
106 self.zk.client.stop()
107 self.zk.client.start()
108 self.fake_nodepool.paused = False
109 self.waitForRequests()
110 self.assertEqual(len(self.provisioned_requests), 1)
David Shrewsburye054b902017-01-26 08:22:25 -0500111 self.assertEqual(request.state, model.STATE_FULFILLED)
James E. Blairf88b8172017-01-24 13:37:21 -0800112
113 @skip("Disabled until nodepool is ready")
114 def test_node_request_canceled(self):
115 # Test that node requests can be canceled
116
117 nodeset = model.NodeSet()
118 nodeset.addNode(model.Node('controller', 'ubuntu-xenial'))
119 nodeset.addNode(model.Node('compute', 'ubuntu-xenial'))
120 job = model.Job('testjob')
121 job.nodeset = nodeset
122 self.fake_nodepool.paused = True
123 request = self.nodepool.requestNodes(None, job)
124 self.nodepool.cancelRequest(request)
125
126 self.waitForRequests()
127 self.assertEqual(len(self.provisioned_requests), 0)