)]}'
{"doc/source/configuration.rst":[{"author":{"_account_id":3099,"name":"David Shrewsbury","email":"dshrewsb@redhat.com","username":"dshrews"},"change_message_id":"428c997c7e226666c43757c2e7260bb7ed4117ce","unresolved":false,"context_lines":[{"line_number":636,"context_line":"  ``ssh-port``"},{"line_number":637,"context_line":"  The ssh port, default to *22*"},{"line_number":638,"context_line":""},{"line_number":639,"context_line":"  ``max-concurrency``"},{"line_number":640,"context_line":"  The number of node to create for the static node, to enable parallel job"},{"line_number":641,"context_line":"  execution. Default to *1*."}],"source_content_type":"text/x-rst","patch_set":22,"id":"9f436f4f_563ff0d5","line":639,"range":{"start_line":639,"start_character":4,"end_line":639,"end_character":19},"updated":"2017-08-08 17:33:01.000000000","message":"I would think that this could get confusing with the identically named providers.max-concurrency config option.","commit_id":"428de241597f8a667868ecf4664ce96dc66b55cf"},{"author":{"_account_id":9311,"name":"Tristan Cacqueray","email":"tdecacqu@redhat.com","username":"tristanC"},"change_message_id":"a196590f147b107f2a7dfe854743c1ef1af9a3e2","unresolved":false,"context_lines":[{"line_number":636,"context_line":"  ``ssh-port``"},{"line_number":637,"context_line":"  The ssh port, default to *22*"},{"line_number":638,"context_line":""},{"line_number":639,"context_line":"  ``max-concurrency``"},{"line_number":640,"context_line":"  The number of node to create for the static node, to enable parallel job"},{"line_number":641,"context_line":"  execution. Default to *1*."}],"source_content_type":"text/x-rst","patch_set":22,"id":"9f436f4f_13ea15ab","line":639,"range":{"start_line":639,"start_character":4,"end_line":639,"end_character":19},"in_reply_to":"9f436f4f_563ff0d5","updated":"2017-08-14 07:18:07.000000000","message":"Good point, I\u0027ve renamed it to \"max-parallel-jobs\"","commit_id":"428de241597f8a667868ecf4664ce96dc66b55cf"},{"author":{"_account_id":1,"name":"James E. Blair","email":"jim@acmegating.com","username":"corvus"},"change_message_id":"b7c27d379142048a34be75a107d433312243fcf8","unresolved":false,"context_lines":[{"line_number":644,"context_line":"  The hostname or ip address of the static node."},{"line_number":645,"context_line":""},{"line_number":646,"context_line":"  ``labels``"},{"line_number":647,"context_line":"  A space separated list of labels associated with the node."},{"line_number":648,"context_line":""},{"line_number":649,"context_line":"  ``host-key``"},{"line_number":650,"context_line":"  The ssh host key of the node."}],"source_content_type":"text/x-rst","patch_set":34,"id":"df87a7cf_3dfe3d37","line":647,"updated":"2017-12-06 17:32:56.000000000","message":"Can this be a yaml list?  We can do the thing we do in zuul -- if it\u0027s a string, automatically transform it into a list of one item (since that\u0027s the most likely use).","commit_id":"3f4fc539781c38a53cedc380d1503f0d2e5393ad"},{"author":{"_account_id":9311,"name":"Tristan Cacqueray","email":"tdecacqu@redhat.com","username":"tristanC"},"change_message_id":"446d70e2f562759aff51dbeb636d5026a7891163","unresolved":false,"context_lines":[{"line_number":644,"context_line":"  The hostname or ip address of the static node."},{"line_number":645,"context_line":""},{"line_number":646,"context_line":"  ``labels``"},{"line_number":647,"context_line":"  A space separated list of labels associated with the node."},{"line_number":648,"context_line":""},{"line_number":649,"context_line":"  ``host-key``"},{"line_number":650,"context_line":"  The ssh host key of the node."}],"source_content_type":"text/x-rst","patch_set":34,"id":"df87a7cf_710ce840","line":647,"in_reply_to":"df87a7cf_3dfe3d37","updated":"2017-12-07 01:37:03.000000000","message":"Done","commit_id":"3f4fc539781c38a53cedc380d1503f0d2e5393ad"},{"author":{"_account_id":1,"name":"James E. Blair","email":"jim@acmegating.com","username":"corvus"},"change_message_id":"b7c27d379142048a34be75a107d433312243fcf8","unresolved":false,"context_lines":[{"line_number":647,"context_line":"  A space separated list of labels associated with the node."},{"line_number":648,"context_line":""},{"line_number":649,"context_line":"  ``host-key``"},{"line_number":650,"context_line":"  The ssh host key of the node."},{"line_number":651,"context_line":""},{"line_number":652,"context_line":"**optional**"},{"line_number":653,"context_line":""}],"source_content_type":"text/x-rst","patch_set":34,"id":"df87a7cf_5df9c14a","line":650,"updated":"2017-12-06 17:32:56.000000000","message":"Is this required?  We could make it optional and if the user supplies it, perform the comparison.  Otherwise, use the retrieved value when we allocate the node.","commit_id":"3f4fc539781c38a53cedc380d1503f0d2e5393ad"},{"author":{"_account_id":9311,"name":"Tristan Cacqueray","email":"tdecacqu@redhat.com","username":"tristanC"},"change_message_id":"446d70e2f562759aff51dbeb636d5026a7891163","unresolved":false,"context_lines":[{"line_number":647,"context_line":"  A space separated list of labels associated with the node."},{"line_number":648,"context_line":""},{"line_number":649,"context_line":"  ``host-key``"},{"line_number":650,"context_line":"  The ssh host key of the node."},{"line_number":651,"context_line":""},{"line_number":652,"context_line":"**optional**"},{"line_number":653,"context_line":""}],"source_content_type":"text/x-rst","patch_set":34,"id":"df87a7cf_54143244","line":650,"in_reply_to":"df87a7cf_5df9c14a","updated":"2017-12-07 01:37:03.000000000","message":"It\u0027s not required, it\u0027s there because it was in the original spec. Next PS will move it to optional.","commit_id":"3f4fc539781c38a53cedc380d1503f0d2e5393ad"}],"nodepool/config.py":[{"author":{"_account_id":4162,"name":"Paul Belanger","email":"pabelanger@redhat.com","username":"pabelanger"},"change_message_id":"5b8af39f9c1f766272f4d52d1f072593187a81cb","unresolved":false,"context_lines":[{"line_number":277,"context_line":"                pp.nodes.append({"},{"line_number":278,"context_line":"                    \u0027name\u0027: node[\u0027name\u0027],"},{"line_number":279,"context_line":"                    \u0027labels\u0027: node[\u0027labels\u0027].split(),"},{"line_number":280,"context_line":"                    \u0027host-key\u0027: node[\u0027host-key\u0027],"},{"line_number":281,"context_line":"                    \u0027timeout\u0027: int(node.get(\u0027timeout\u0027, 5)),"},{"line_number":282,"context_line":"                    \u0027ssh_port\u0027: int(node.get(\u0027ssh_port\u0027, 22)),"},{"line_number":283,"context_line":"                    \u0027username\u0027: node.get(\u0027username\u0027, \u0027root\u0027),"}],"source_content_type":"text/x-python","patch_set":7,"id":"7f231b9d_8eee7a86","line":280,"updated":"2017-06-11 20:09:18.000000000","message":"I _think_ we\u0027ll want to move the host-key validation into zuul (ansible playbook).  I suspect this is something to discuss","commit_id":"fbe241eb917de3daf7c7526fa057454b547738d1"},{"author":{"_account_id":9311,"name":"Tristan Cacqueray","email":"tdecacqu@redhat.com","username":"tristanC"},"change_message_id":"cd06a6358e9645b31f3716793b95108e766f516a","unresolved":false,"context_lines":[{"line_number":277,"context_line":"                pp.nodes.append({"},{"line_number":278,"context_line":"                    \u0027name\u0027: node[\u0027name\u0027],"},{"line_number":279,"context_line":"                    \u0027labels\u0027: node[\u0027labels\u0027].split(),"},{"line_number":280,"context_line":"                    \u0027host-key\u0027: node[\u0027host-key\u0027],"},{"line_number":281,"context_line":"                    \u0027timeout\u0027: int(node.get(\u0027timeout\u0027, 5)),"},{"line_number":282,"context_line":"                    \u0027ssh_port\u0027: int(node.get(\u0027ssh_port\u0027, 22)),"},{"line_number":283,"context_line":"                    \u0027username\u0027: node.get(\u0027username\u0027, \u0027root\u0027),"}],"source_content_type":"text/x-python","patch_set":7,"id":"7f231b9d_41cdd35b","line":280,"in_reply_to":"7f231b9d_8eee7a86","updated":"2017-06-11 23:16:30.000000000","message":"Note that was part of the original spec, see http://specs.openstack.org/openstack-infra/infra-specs/specs/nodepool-drivers.html#proposed-change.\n\nIt makes sense to me that nodepool checks the static node is the correct one, though it makes the configuration file clunky. A similar level of security could be accomplished externally too, using ipsec AH for example.","commit_id":"fbe241eb917de3daf7c7526fa057454b547738d1"},{"author":{"_account_id":16068,"name":"Tobias Henkel","email":"tobias.henkel@bmw.de","username":"tobias.henkel"},"change_message_id":"2eabb18f2807650f77790147f2fc6f53fc6e8a7d","unresolved":false,"context_lines":[{"line_number":278,"context_line":"                    \u0027name\u0027: node[\u0027name\u0027],"},{"line_number":279,"context_line":"                    \u0027labels\u0027: node[\u0027labels\u0027].split(),"},{"line_number":280,"context_line":"                    \u0027host-key\u0027: node[\u0027host-key\u0027],"},{"line_number":281,"context_line":"                    \u0027timeout\u0027: int(node.get(\u0027timeout\u0027, 5)),"},{"line_number":282,"context_line":"                    \u0027ssh_port\u0027: int(node.get(\u0027ssh_port\u0027, 22)),"},{"line_number":283,"context_line":"                    \u0027username\u0027: node.get(\u0027username\u0027, \u0027root\u0027),"},{"line_number":284,"context_line":"                    \u0027max_concurrency\u0027: int(node.get(\u0027max_concurrency\u0027, 1)),"},{"line_number":285,"context_line":"                })"},{"line_number":286,"context_line":"                for label in node[\u0027labels\u0027].split():"},{"line_number":287,"context_line":"                    pl \u003d ProviderLabel()"}],"source_content_type":"text/x-python","patch_set":13,"id":"7f231b9d_19eacfab","line":284,"range":{"start_line":281,"start_character":0,"end_line":284,"end_character":75},"updated":"2017-06-19 18:54:40.000000000","message":"I don\u0027t see these in the validator and good.yaml test fixture.","commit_id":"1af1792ceca7cb0a1ddf323bd26a147869679a28"},{"author":{"_account_id":9311,"name":"Tristan Cacqueray","email":"tdecacqu@redhat.com","username":"tristanC"},"change_message_id":"dc1b9ef277413a9df7e658b6f1f2f5c9a2d64472","unresolved":false,"context_lines":[{"line_number":278,"context_line":"                    \u0027name\u0027: node[\u0027name\u0027],"},{"line_number":279,"context_line":"                    \u0027labels\u0027: node[\u0027labels\u0027].split(),"},{"line_number":280,"context_line":"                    \u0027host-key\u0027: node[\u0027host-key\u0027],"},{"line_number":281,"context_line":"                    \u0027timeout\u0027: int(node.get(\u0027timeout\u0027, 5)),"},{"line_number":282,"context_line":"                    \u0027ssh_port\u0027: int(node.get(\u0027ssh_port\u0027, 22)),"},{"line_number":283,"context_line":"                    \u0027username\u0027: node.get(\u0027username\u0027, \u0027root\u0027),"},{"line_number":284,"context_line":"                    \u0027max_concurrency\u0027: int(node.get(\u0027max_concurrency\u0027, 1)),"},{"line_number":285,"context_line":"                })"},{"line_number":286,"context_line":"                for label in node[\u0027labels\u0027].split():"},{"line_number":287,"context_line":"                    pl \u003d ProviderLabel()"}],"source_content_type":"text/x-python","patch_set":13,"id":"7f231b9d_d172e349","line":284,"range":{"start_line":281,"start_character":0,"end_line":284,"end_character":75},"in_reply_to":"7f231b9d_19eacfab","updated":"2017-06-20 02:45:43.000000000","message":"Done","commit_id":"1af1792ceca7cb0a1ddf323bd26a147869679a28"}],"nodepool/driver/static/handler.py":[{"author":{"_account_id":4146,"name":"Clark Boylan","email":"cboylan@sapwetik.org","username":"cboylan"},"change_message_id":"88ad6209db797fec2e1015f77b2e49582413e991","unresolved":false,"context_lines":[{"line_number":30,"context_line":"        self._setFromPoolWorker()"},{"line_number":31,"context_line":"        static_node \u003d None"},{"line_number":32,"context_line":"        ntype \u003d None"},{"line_number":33,"context_line":"        for pool in self.provider.pools.values():"},{"line_number":34,"context_line":"            for node in pool.nodes:"},{"line_number":35,"context_line":"                for node_type in self.request.node_types:"},{"line_number":36,"context_line":"                    if node_type in node[\"labels\"]:"}],"source_content_type":"text/x-python","patch_set":5,"id":"df140735_c27bddbb","line":33,"updated":"2017-05-31 19:30:41.000000000","message":"self.provider.listNodes()?","commit_id":"14a0a14aca2d6ce13c29aa1b68781644b4110b4a"},{"author":{"_account_id":9311,"name":"Tristan Cacqueray","email":"tdecacqu@redhat.com","username":"tristanC"},"change_message_id":"d69ed3c96a1c2372d257761d11de49fbea5fd021","unresolved":false,"context_lines":[{"line_number":30,"context_line":"        self._setFromPoolWorker()"},{"line_number":31,"context_line":"        static_node \u003d None"},{"line_number":32,"context_line":"        ntype \u003d None"},{"line_number":33,"context_line":"        for pool in self.provider.pools.values():"},{"line_number":34,"context_line":"            for node in pool.nodes:"},{"line_number":35,"context_line":"                for node_type in self.request.node_types:"},{"line_number":36,"context_line":"                    if node_type in node[\"labels\"]:"}],"source_content_type":"text/x-python","patch_set":5,"id":"df140735_d53cabc9","line":33,"in_reply_to":"df140735_c27bddbb","updated":"2017-06-01 08:11:29.000000000","message":"Done","commit_id":"14a0a14aca2d6ce13c29aa1b68781644b4110b4a"},{"author":{"_account_id":4146,"name":"Clark Boylan","email":"cboylan@sapwetik.org","username":"cboylan"},"change_message_id":"88ad6209db797fec2e1015f77b2e49582413e991","unresolved":false,"context_lines":[{"line_number":31,"context_line":"        static_node \u003d None"},{"line_number":32,"context_line":"        ntype \u003d None"},{"line_number":33,"context_line":"        for pool in self.provider.pools.values():"},{"line_number":34,"context_line":"            for node in pool.nodes:"},{"line_number":35,"context_line":"                for node_type in self.request.node_types:"},{"line_number":36,"context_line":"                    if node_type in node[\"labels\"]:"},{"line_number":37,"context_line":"                        static_node \u003d node"}],"source_content_type":"text/x-python","patch_set":5,"id":"df140735_e2ab811a","line":34,"updated":"2017-05-31 19:30:41.000000000","message":"You may want to apply a random sort to this so that you don\u0027t always return the same static node to all jobs. Same with pools? I would expect that distributing the work even under low demand is what most users will want if for no other reason than making sure they have a working set of nodes when demand is high and don\u0027t end up with a lot of failing jobs in that situation.","commit_id":"14a0a14aca2d6ce13c29aa1b68781644b4110b4a"},{"author":{"_account_id":9311,"name":"Tristan Cacqueray","email":"tdecacqu@redhat.com","username":"tristanC"},"change_message_id":"d69ed3c96a1c2372d257761d11de49fbea5fd021","unresolved":false,"context_lines":[{"line_number":31,"context_line":"        static_node \u003d None"},{"line_number":32,"context_line":"        ntype \u003d None"},{"line_number":33,"context_line":"        for pool in self.provider.pools.values():"},{"line_number":34,"context_line":"            for node in pool.nodes:"},{"line_number":35,"context_line":"                for node_type in self.request.node_types:"},{"line_number":36,"context_line":"                    if node_type in node[\"labels\"]:"},{"line_number":37,"context_line":"                        static_node \u003d node"}],"source_content_type":"text/x-python","patch_set":5,"id":"df140735_554e5b6f","line":34,"in_reply_to":"df140735_e2ab811a","updated":"2017-06-01 08:11:29.000000000","message":"Good idea, next PS uses random.shuffle()","commit_id":"14a0a14aca2d6ce13c29aa1b68781644b4110b4a"},{"author":{"_account_id":1,"name":"James E. Blair","email":"jim@acmegating.com","username":"corvus"},"change_message_id":"b7c27d379142048a34be75a107d433312243fcf8","unresolved":false,"context_lines":[{"line_number":20,"context_line":""},{"line_number":21,"context_line":"from nodepool import zk"},{"line_number":22,"context_line":""},{"line_number":23,"context_line":""},{"line_number":24,"context_line":"class StaticNodeRequestHandler(NodeRequestHandler):"},{"line_number":25,"context_line":"    log \u003d logging.getLogger(\"nodepool.driver.static.\""},{"line_number":26,"context_line":"                            \"StaticNodeRequestHandler\")"}],"source_content_type":"text/x-python","patch_set":34,"id":"df87a7cf_ddedd18b","line":23,"updated":"2017-12-06 17:32:56.000000000","message":"I think we have an API problem here -- I\u0027m not sure that we should have per-driver request handlers.  Instead, we should just have a single request handler, and it uses the provider drivers to fulfill the requests.  There\u0027s no reason a user shouldn\u0027t be able to make a request with bost static and dynamic nodes.","commit_id":"3f4fc539781c38a53cedc380d1503f0d2e5393ad"},{"author":{"_account_id":9311,"name":"Tristan Cacqueray","email":"tdecacqu@redhat.com","username":"tristanC"},"change_message_id":"446d70e2f562759aff51dbeb636d5026a7891163","unresolved":false,"context_lines":[{"line_number":20,"context_line":""},{"line_number":21,"context_line":"from nodepool import zk"},{"line_number":22,"context_line":""},{"line_number":23,"context_line":""},{"line_number":24,"context_line":"class StaticNodeRequestHandler(NodeRequestHandler):"},{"line_number":25,"context_line":"    log \u003d logging.getLogger(\"nodepool.driver.static.\""},{"line_number":26,"context_line":"                            \"StaticNodeRequestHandler\")"}],"source_content_type":"text/x-python","patch_set":34,"id":"df87a7cf_3445ee43","line":23,"in_reply_to":"df87a7cf_ddedd18b","updated":"2017-12-07 01:37:03.000000000","message":"I agree this is sub-optimal and we have to copy and adapt this code for any drivers. I\u0027ll work on a refactor in another patch so that we can discuss a better approach.\n\nThough regarding mixing both static and dynamic node, we\u0027ll have to adjust the openstack handler that already ensure requested node are in the same region/az. Not sure how this will play with a generic handler...","commit_id":"3f4fc539781c38a53cedc380d1503f0d2e5393ad"},{"author":{"_account_id":1,"name":"James E. Blair","email":"jim@acmegating.com","username":"corvus"},"change_message_id":"b7c27d379142048a34be75a107d433312243fcf8","unresolved":false,"context_lines":[{"line_number":61,"context_line":""},{"line_number":62,"context_line":"        if len(self.request.node_types) \u003d\u003d 1 and static_node:"},{"line_number":63,"context_line":"            self.log.debug(\"%s: Assigning static_node %s\" % ("},{"line_number":64,"context_line":"                self.request.id, static_node))"},{"line_number":65,"context_line":"            node \u003d zk.Node()"},{"line_number":66,"context_line":"            node.state \u003d zk.READY"},{"line_number":67,"context_line":"            node.external_id \u003d \"static-%s\" % self.request.id"}],"source_content_type":"text/x-python","patch_set":34,"id":"df87a7cf_7d04c54a","line":64,"updated":"2017-12-06 17:32:56.000000000","message":"I note this still uses the dynamic node approach, rather than static.  That may be okay, but we should still discuss this with Monty since it varies from what we talked about a while ago.","commit_id":"3f4fc539781c38a53cedc380d1503f0d2e5393ad"},{"author":{"_account_id":9311,"name":"Tristan Cacqueray","email":"tdecacqu@redhat.com","username":"tristanC"},"change_message_id":"446d70e2f562759aff51dbeb636d5026a7891163","unresolved":false,"context_lines":[{"line_number":61,"context_line":""},{"line_number":62,"context_line":"        if len(self.request.node_types) \u003d\u003d 1 and static_node:"},{"line_number":63,"context_line":"            self.log.debug(\"%s: Assigning static_node %s\" % ("},{"line_number":64,"context_line":"                self.request.id, static_node))"},{"line_number":65,"context_line":"            node \u003d zk.Node()"},{"line_number":66,"context_line":"            node.state \u003d zk.READY"},{"line_number":67,"context_line":"            node.external_id \u003d \"static-%s\" % self.request.id"}],"source_content_type":"text/x-python","patch_set":34,"id":"df87a7cf_34b3ae4f","line":64,"in_reply_to":"df87a7cf_7d04c54a","updated":"2017-12-07 01:37:03.000000000","message":"Well I\u0027ve been waiting since July for that discussion to happen :-)","commit_id":"3f4fc539781c38a53cedc380d1503f0d2e5393ad"},{"author":{"_account_id":1,"name":"James E. Blair","email":"jim@acmegating.com","username":"corvus"},"change_message_id":"fabf7472adb05666e5e29d6539fe72bdc6f0314c","unresolved":false,"context_lines":[{"line_number":78,"context_line":"            self.zk.storeNode(node)"},{"line_number":79,"context_line":"        else:"},{"line_number":80,"context_line":"            if len(self.request.node_types) !\u003d 1:"},{"line_number":81,"context_line":"                reason \u003d \"static provider doesn\u0027t handle nodeset \u003e 1\""},{"line_number":82,"context_line":"            else:"},{"line_number":83,"context_line":"                reason \u003d \"no static nodes available\""},{"line_number":84,"context_line":"            self.log.info(\"%s: Declined because %s\" % (self.request.id, reason))"}],"source_content_type":"text/x-python","patch_set":34,"id":"df87a7cf_426a22ee","line":81,"updated":"2017-12-07 15:28:04.000000000","message":"I think this one is important.  I think the refactor is too big to do right now, so I think we should go ahead and add the for-each loop here, because I do think people are going to expect to be able to get more than one static node.","commit_id":"3f4fc539781c38a53cedc380d1503f0d2e5393ad"},{"author":{"_account_id":1,"name":"James E. Blair","email":"jim@acmegating.com","username":"corvus"},"change_message_id":"b7c27d379142048a34be75a107d433312243fcf8","unresolved":false,"context_lines":[{"line_number":78,"context_line":"            self.zk.storeNode(node)"},{"line_number":79,"context_line":"        else:"},{"line_number":80,"context_line":"            if len(self.request.node_types) !\u003d 1:"},{"line_number":81,"context_line":"                reason \u003d \"static provider doesn\u0027t handle nodeset \u003e 1\""},{"line_number":82,"context_line":"            else:"},{"line_number":83,"context_line":"                reason \u003d \"no static nodes available\""},{"line_number":84,"context_line":"            self.log.info(\"%s: Declined because %s\" % (self.request.id, reason))"}],"source_content_type":"text/x-python","patch_set":34,"id":"df87a7cf_9dff4933","line":81,"updated":"2017-12-06 17:32:56.000000000","message":"Why can\u0027t the static provider handle a nodeset with more than one node?  I think a primary use case is, say, a rack of machines and someone wants to check out 3 of them to deploy openstack.","commit_id":"3f4fc539781c38a53cedc380d1503f0d2e5393ad"},{"author":{"_account_id":9311,"name":"Tristan Cacqueray","email":"tdecacqu@redhat.com","username":"tristanC"},"change_message_id":"446d70e2f562759aff51dbeb636d5026a7891163","unresolved":false,"context_lines":[{"line_number":78,"context_line":"            self.zk.storeNode(node)"},{"line_number":79,"context_line":"        else:"},{"line_number":80,"context_line":"            if len(self.request.node_types) !\u003d 1:"},{"line_number":81,"context_line":"                reason \u003d \"static provider doesn\u0027t handle nodeset \u003e 1\""},{"line_number":82,"context_line":"            else:"},{"line_number":83,"context_line":"                reason \u003d \"no static nodes available\""},{"line_number":84,"context_line":"            self.log.info(\"%s: Declined because %s\" % (self.request.id, reason))"}],"source_content_type":"text/x-python","patch_set":34,"id":"df87a7cf_74961696","line":81,"in_reply_to":"df87a7cf_9dff4933","updated":"2017-12-07 01:37:03.000000000","message":"It was to keep the handler more simple, but if we refactor this code to be generic accros driver, then the static driver would benefit from multi node request for free. Otherwise it\u0027s not that difficult to make the for each request.node_types loop.","commit_id":"3f4fc539781c38a53cedc380d1503f0d2e5393ad"}],"nodepool/driver/static/provider.py":[{"author":{"_account_id":9311,"name":"Tristan Cacqueray","email":"tdecacqu@redhat.com","username":"tristanC"},"change_message_id":"cd06a6358e9645b31f3716793b95108e766f516a","unresolved":false,"context_lines":[{"line_number":28,"context_line":""},{"line_number":29,"context_line":"    def __init__(self, provider):"},{"line_number":30,"context_line":"        self.provider \u003d provider"},{"line_number":31,"context_line":"        self.pools \u003d {}"},{"line_number":32,"context_line":"        self.static_nodes \u003d {}"},{"line_number":33,"context_line":""},{"line_number":34,"context_line":"    def checkHost(self, node):"}],"source_content_type":"text/x-python","patch_set":7,"id":"7f231b9d_c12fa3f4","line":31,"updated":"2017-06-11 23:16:30.000000000","message":"This member isn\u0027t used actually. I\u0027m not sure the \u0027pool\u0027 concepts apply well to static provider...","commit_id":"fbe241eb917de3daf7c7526fa057454b547738d1"},{"author":{"_account_id":4162,"name":"Paul Belanger","email":"pabelanger@redhat.com","username":"pabelanger"},"change_message_id":"5b8af39f9c1f766272f4d52d1f072593187a81cb","unresolved":false,"context_lines":[{"line_number":31,"context_line":"        self.pools \u003d {}"},{"line_number":32,"context_line":"        self.static_nodes \u003d {}"},{"line_number":33,"context_line":""},{"line_number":34,"context_line":"    def checkHost(self, node):"},{"line_number":35,"context_line":"        # Check node is reachable"},{"line_number":36,"context_line":"        try:"},{"line_number":37,"context_line":"            keys \u003d keyscan(socket.gethostbyname(node[\"name\"]),"}],"source_content_type":"text/x-python","patch_set":7,"id":"7f231b9d_4ed742c1","line":34,"updated":"2017-06-11 20:09:18.000000000","message":"We should use the same logic we do today in the openstack driver. I don\u0027t think there is a need to be different between openstack and static.  Keyscan ip, then pass that into zookeeper, raising an exception if we fail to gather host keys.","commit_id":"fbe241eb917de3daf7c7526fa057454b547738d1"},{"author":{"_account_id":9311,"name":"Tristan Cacqueray","email":"tdecacqu@redhat.com","username":"tristanC"},"change_message_id":"cd06a6358e9645b31f3716793b95108e766f516a","unresolved":false,"context_lines":[{"line_number":31,"context_line":"        self.pools \u003d {}"},{"line_number":32,"context_line":"        self.static_nodes \u003d {}"},{"line_number":33,"context_line":""},{"line_number":34,"context_line":"    def checkHost(self, node):"},{"line_number":35,"context_line":"        # Check node is reachable"},{"line_number":36,"context_line":"        try:"},{"line_number":37,"context_line":"            keys \u003d keyscan(socket.gethostbyname(node[\"name\"]),"}],"source_content_type":"text/x-python","patch_set":7,"id":"7f231b9d_a134a74b","line":34,"in_reply_to":"7f231b9d_4ed742c1","updated":"2017-06-11 23:16:30.000000000","message":"The logic is different enough to warrant a custom logic imo.","commit_id":"fbe241eb917de3daf7c7526fa057454b547738d1"},{"author":{"_account_id":4162,"name":"Paul Belanger","email":"pabelanger@redhat.com","username":"pabelanger"},"change_message_id":"5b8af39f9c1f766272f4d52d1f072593187a81cb","unresolved":false,"context_lines":[{"line_number":41,"context_line":"            self.log.error(\"%s: SSHTimeoutException\" % node[\"name\"])"},{"line_number":42,"context_line":"            return False"},{"line_number":43,"context_line":""},{"line_number":44,"context_line":"        # Check node host-key"},{"line_number":45,"context_line":"        if node[\"host-key\"] not in keys:"},{"line_number":46,"context_line":"            self.log.error(\"%s: host key mismatches\" % node[\"name\"])"},{"line_number":47,"context_line":"            self.log.debug(\"%s: Registered key \u0027%s\u0027 not in %s\" % ("}],"source_content_type":"text/x-python","patch_set":7,"id":"7f231b9d_2ee406ac","line":44,"updated":"2017-06-11 20:09:18.000000000","message":"We do this in zuul today, make sense to also handle static nodes like this too.","commit_id":"fbe241eb917de3daf7c7526fa057454b547738d1"},{"author":{"_account_id":9311,"name":"Tristan Cacqueray","email":"tdecacqu@redhat.com","username":"tristanC"},"change_message_id":"cd06a6358e9645b31f3716793b95108e766f516a","unresolved":false,"context_lines":[{"line_number":41,"context_line":"            self.log.error(\"%s: SSHTimeoutException\" % node[\"name\"])"},{"line_number":42,"context_line":"            return False"},{"line_number":43,"context_line":""},{"line_number":44,"context_line":"        # Check node host-key"},{"line_number":45,"context_line":"        if node[\"host-key\"] not in keys:"},{"line_number":46,"context_line":"            self.log.error(\"%s: host key mismatches\" % node[\"name\"])"},{"line_number":47,"context_line":"            self.log.debug(\"%s: Registered key \u0027%s\u0027 not in %s\" % ("}],"source_content_type":"text/x-python","patch_set":7,"id":"7f231b9d_01d7dbef","line":44,"in_reply_to":"7f231b9d_2ee406ac","updated":"2017-06-11 23:16:30.000000000","message":"I _think_ the reasoning is to prevent static node spoofing...","commit_id":"fbe241eb917de3daf7c7526fa057454b547738d1"},{"author":{"_account_id":4162,"name":"Paul Belanger","email":"pabelanger@redhat.com","username":"pabelanger"},"change_message_id":"5b8af39f9c1f766272f4d52d1f072593187a81cb","unresolved":false,"context_lines":[{"line_number":49,"context_line":"            ))"},{"line_number":50,"context_line":"            return False"},{"line_number":51,"context_line":""},{"line_number":52,"context_line":"        # Check node ssh access"},{"line_number":53,"context_line":"        client \u003d paramiko.client.SSHClient()"},{"line_number":54,"context_line":"        try:"},{"line_number":55,"context_line":"            client.set_missing_host_key_policy(paramiko.AutoAddPolicy())"}],"source_content_type":"text/x-python","patch_set":7,"id":"7f231b9d_eec60e17","line":52,"updated":"2017-06-11 20:09:18.000000000","message":"I\u0027m not sure we need this any more. For openstack provider we just keyscan now and pass that information to zuul. It then handles SSH access.","commit_id":"fbe241eb917de3daf7c7526fa057454b547738d1"},{"author":{"_account_id":9311,"name":"Tristan Cacqueray","email":"tdecacqu@redhat.com","username":"tristanC"},"change_message_id":"cd06a6358e9645b31f3716793b95108e766f516a","unresolved":false,"context_lines":[{"line_number":49,"context_line":"            ))"},{"line_number":50,"context_line":"            return False"},{"line_number":51,"context_line":""},{"line_number":52,"context_line":"        # Check node ssh access"},{"line_number":53,"context_line":"        client \u003d paramiko.client.SSHClient()"},{"line_number":54,"context_line":"        try:"},{"line_number":55,"context_line":"            client.set_missing_host_key_policy(paramiko.AutoAddPolicy())"}],"source_content_type":"text/x-python","patch_set":7,"id":"7f231b9d_c10a0389","line":52,"in_reply_to":"7f231b9d_eec60e17","updated":"2017-06-11 23:16:30.000000000","message":"It\u0027s ok to remove that part, though I find it easier to catch potencial problems earlier. Similarly to Jenkins, we could also check if there is enough memory and disk space too.","commit_id":"fbe241eb917de3daf7c7526fa057454b547738d1"},{"author":{"_account_id":2,"name":"Monty Taylor","email":"mordred@inaugust.com","username":"mordred"},"change_message_id":"92e688b70aa1b4f4ec259076708664eafa5e470c","unresolved":false,"context_lines":[{"line_number":49,"context_line":"            ))"},{"line_number":50,"context_line":"            return False"},{"line_number":51,"context_line":""},{"line_number":52,"context_line":"        # Check node ssh access"},{"line_number":53,"context_line":"        client \u003d paramiko.client.SSHClient()"},{"line_number":54,"context_line":"        try:"},{"line_number":55,"context_line":"            client.set_missing_host_key_policy(paramiko.AutoAddPolicy())"}],"source_content_type":"text/x-python","patch_set":9,"id":"7f231b9d_eef41cf3","line":52,"updated":"2017-06-16 14:26:13.000000000","message":"For static nodes we\u0027re going to want their host keys either to be pre-accepted, or listed in the config. (these are pre-existing hosts, so we want to make sure we\u0027re not getting MITM\u0027d) I mention that because one of the static server use-cases is to allow zuul to trigger deployments.\n\nThis is different from cloud nodes where we don\u0027t have that option.","commit_id":"dcddc62e34e76165a10cef0e1c157d5ac12e3ffb"},{"author":{"_account_id":9311,"name":"Tristan Cacqueray","email":"tdecacqu@redhat.com","username":"tristanC"},"change_message_id":"81af058da366c9e6e3432c7b94baf1404e58406a","unresolved":false,"context_lines":[{"line_number":49,"context_line":"            ))"},{"line_number":50,"context_line":"            return False"},{"line_number":51,"context_line":""},{"line_number":52,"context_line":"        # Check node ssh access"},{"line_number":53,"context_line":"        client \u003d paramiko.client.SSHClient()"},{"line_number":54,"context_line":"        try:"},{"line_number":55,"context_line":"            client.set_missing_host_key_policy(paramiko.AutoAddPolicy())"}],"source_content_type":"text/x-python","patch_set":9,"id":"7f231b9d_72a0df90","line":52,"in_reply_to":"7f231b9d_eef41cf3","updated":"2017-06-17 13:08:52.000000000","message":"This should be checked by the above condition. I\u0027ll add a todo until I figure how to instruct paramiko to use a known host key.","commit_id":"dcddc62e34e76165a10cef0e1c157d5ac12e3ffb"},{"author":{"_account_id":16068,"name":"Tobias Henkel","email":"tobias.henkel@bmw.de","username":"tobias.henkel"},"change_message_id":"2eabb18f2807650f77790147f2fc6f53fc6e8a7d","unresolved":false,"context_lines":[{"line_number":49,"context_line":"            ))"},{"line_number":50,"context_line":"            return False"},{"line_number":51,"context_line":""},{"line_number":52,"context_line":"        # Check node ssh access"},{"line_number":53,"context_line":"        client \u003d paramiko.client.SSHClient()"},{"line_number":54,"context_line":"        try:"},{"line_number":55,"context_line":"            # TODO: force paramiko to use the node[\u0027host-key\u0027]"},{"line_number":56,"context_line":"            client.set_missing_host_key_policy(paramiko.AutoAddPolicy())"},{"line_number":57,"context_line":"            client.connect(node[\"name\"], username\u003dnode[\"username\"])"},{"line_number":58,"context_line":"            client.exec_command(\u0027echo okay\u0027)"},{"line_number":59,"context_line":"        except paramiko.AuthenticationException:"},{"line_number":60,"context_line":"            self.log.error(\"%s: AuthenticationException\" % node[\"name\"])"},{"line_number":61,"context_line":"            return False"},{"line_number":62,"context_line":"        finally:"},{"line_number":63,"context_line":"            client.close()"},{"line_number":64,"context_line":"        return True"},{"line_number":65,"context_line":""},{"line_number":66,"context_line":"    def start(self):"}],"source_content_type":"text/x-python","patch_set":13,"id":"7f231b9d_7c2651bd","line":63,"range":{"start_line":52,"start_character":0,"end_line":63,"end_character":26},"updated":"2017-06-19 18:54:40.000000000","message":"Do you think this is needed? I think the openstack provider just does a keyscan.","commit_id":"1af1792ceca7cb0a1ddf323bd26a147869679a28"},{"author":{"_account_id":9311,"name":"Tristan Cacqueray","email":"tdecacqu@redhat.com","username":"tristanC"},"change_message_id":"dc1b9ef277413a9df7e658b6f1f2f5c9a2d64472","unresolved":false,"context_lines":[{"line_number":49,"context_line":"            ))"},{"line_number":50,"context_line":"            return False"},{"line_number":51,"context_line":""},{"line_number":52,"context_line":"        # Check node ssh access"},{"line_number":53,"context_line":"        client \u003d paramiko.client.SSHClient()"},{"line_number":54,"context_line":"        try:"},{"line_number":55,"context_line":"            # TODO: force paramiko to use the node[\u0027host-key\u0027]"},{"line_number":56,"context_line":"            client.set_missing_host_key_policy(paramiko.AutoAddPolicy())"},{"line_number":57,"context_line":"            client.connect(node[\"name\"], username\u003dnode[\"username\"])"},{"line_number":58,"context_line":"            client.exec_command(\u0027echo okay\u0027)"},{"line_number":59,"context_line":"        except paramiko.AuthenticationException:"},{"line_number":60,"context_line":"            self.log.error(\"%s: AuthenticationException\" % node[\"name\"])"},{"line_number":61,"context_line":"            return False"},{"line_number":62,"context_line":"        finally:"},{"line_number":63,"context_line":"            client.close()"},{"line_number":64,"context_line":"        return True"},{"line_number":65,"context_line":""},{"line_number":66,"context_line":"    def start(self):"}],"source_content_type":"text/x-python","patch_set":13,"id":"7f231b9d_71fe6f6c","line":63,"range":{"start_line":52,"start_character":0,"end_line":63,"end_character":26},"in_reply_to":"7f231b9d_7c2651bd","updated":"2017-06-20 02:45:43.000000000","message":"I think it\u0027s better to fail early instead of waiting for executor to fail connecting. Though this may be offbeat since the username needs to be in-sync with the zuul executor default_username setting.","commit_id":"1af1792ceca7cb0a1ddf323bd26a147869679a28"},{"author":{"_account_id":1,"name":"James E. Blair","email":"jim@acmegating.com","username":"corvus"},"change_message_id":"b7c27d379142048a34be75a107d433312243fcf8","unresolved":false,"context_lines":[{"line_number":49,"context_line":"            ))"},{"line_number":50,"context_line":"            return False"},{"line_number":51,"context_line":""},{"line_number":52,"context_line":"        # Check node ssh access"},{"line_number":53,"context_line":"        client \u003d paramiko.client.SSHClient()"},{"line_number":54,"context_line":"        try:"},{"line_number":55,"context_line":"            # TODO: force paramiko to use the node[\u0027host-key\u0027]"}],"source_content_type":"text/x-python","patch_set":34,"id":"df87a7cf_fd9535e5","line":52,"updated":"2017-12-06 17:32:56.000000000","message":"Why do we do this here when we just removed this from the openstack driver?\n\nI know we\u0027ve talked about adding it back to openstack for the purposes of changing how the keyscan is done.  But until we do that, it seems strange for this to behave differently.  It is required?","commit_id":"3f4fc539781c38a53cedc380d1503f0d2e5393ad"},{"author":{"_account_id":9311,"name":"Tristan Cacqueray","email":"tdecacqu@redhat.com","username":"tristanC"},"change_message_id":"446d70e2f562759aff51dbeb636d5026a7891163","unresolved":false,"context_lines":[{"line_number":49,"context_line":"            ))"},{"line_number":50,"context_line":"            return False"},{"line_number":51,"context_line":""},{"line_number":52,"context_line":"        # Check node ssh access"},{"line_number":53,"context_line":"        client \u003d paramiko.client.SSHClient()"},{"line_number":54,"context_line":"        try:"},{"line_number":55,"context_line":"            # TODO: force paramiko to use the node[\u0027host-key\u0027]"}],"source_content_type":"text/x-python","patch_set":34,"id":"df87a7cf_34e16e2b","line":52,"in_reply_to":"df87a7cf_fd9535e5","updated":"2017-12-07 01:37:03.000000000","message":"It was simply to fail early (e.g. if ssh doesn\u0027t work, no need to continue and pass the node to zuul), next ps will remove that code.","commit_id":"3f4fc539781c38a53cedc380d1503f0d2e5393ad"}],"nodepool/launcher.py":[{"author":{"_account_id":4146,"name":"Clark Boylan","email":"cboylan@sapwetik.org","username":"cboylan"},"change_message_id":"88ad6209db797fec2e1015f77b2e49582413e991","unresolved":false,"context_lines":[{"line_number":851,"context_line":"        for pool in label.pools:"},{"line_number":852,"context_line":"            if pool.provider.driver !\u003d \"openstack\":"},{"line_number":853,"context_line":"                # No need to manage image for provider !\u003d openstack"},{"line_number":854,"context_line":"                return True"},{"line_number":855,"context_line":"            for pool_label in pool.labels.values():"},{"line_number":856,"context_line":"                if pool_label.cloud_image:"},{"line_number":857,"context_line":"                    manager \u003d self.getProviderManager(pool.provider.name)"}],"source_content_type":"text/x-python","patch_set":5,"id":"df140735_c2299d9b","line":854,"updated":"2017-05-31 19:30:41.000000000","message":"Rather than hard code this to the openstack driver here, might be better to make this an attribute of the driver?\n\n  if not pool.provider.driver.manage_images:\n      return True\n\nThat way other drivers could potentially have managed images?","commit_id":"14a0a14aca2d6ce13c29aa1b68781644b4110b4a"},{"author":{"_account_id":9311,"name":"Tristan Cacqueray","email":"tdecacqu@redhat.com","username":"tristanC"},"change_message_id":"d69ed3c96a1c2372d257761d11de49fbea5fd021","unresolved":false,"context_lines":[{"line_number":851,"context_line":"        for pool in label.pools:"},{"line_number":852,"context_line":"            if pool.provider.driver !\u003d \"openstack\":"},{"line_number":853,"context_line":"                # No need to manage image for provider !\u003d openstack"},{"line_number":854,"context_line":"                return True"},{"line_number":855,"context_line":"            for pool_label in pool.labels.values():"},{"line_number":856,"context_line":"                if pool_label.cloud_image:"},{"line_number":857,"context_line":"                    manager \u003d self.getProviderManager(pool.provider.name)"}],"source_content_type":"text/x-python","patch_set":5,"id":"df140735_b565b7e3","line":854,"in_reply_to":"df140735_c2299d9b","updated":"2017-06-01 08:11:29.000000000","message":"Good idea, I\u0027ll add that in the config extension change ( https://review.openstack.org/468751 )","commit_id":"14a0a14aca2d6ce13c29aa1b68781644b4110b4a"}],"nodepool/tests/fixtures/config_validate/good.yaml":[{"author":{"_account_id":16068,"name":"Tobias Henkel","email":"tobias.henkel@bmw.de","username":"tobias.henkel"},"change_message_id":"2eabb18f2807650f77790147f2fc6f53fc6e8a7d","unresolved":false,"context_lines":[{"line_number":19,"context_line":"  - name: trusty-external"},{"line_number":20,"context_line":"    min-ready: 1"},{"line_number":21,"context_line":"  - name: static-centos"},{"line_number":22,"context_line":"    min-ready: 1"},{"line_number":23,"context_line":""},{"line_number":24,"context_line":"providers:"},{"line_number":25,"context_line":"  - name: cloud1"}],"source_content_type":"text/x-yaml","patch_set":13,"id":"7f231b9d_7988a321","line":22,"range":{"start_line":22,"start_character":4,"end_line":22,"end_character":16},"updated":"2017-06-19 18:54:40.000000000","message":"min-ready doesn\u0027t seem to make sense for static nodes it probably shoud be made optional if it\u0027s not yet","commit_id":"1af1792ceca7cb0a1ddf323bd26a147869679a28"},{"author":{"_account_id":9311,"name":"Tristan Cacqueray","email":"tdecacqu@redhat.com","username":"tristanC"},"change_message_id":"dc1b9ef277413a9df7e658b6f1f2f5c9a2d64472","unresolved":false,"context_lines":[{"line_number":19,"context_line":"  - name: trusty-external"},{"line_number":20,"context_line":"    min-ready: 1"},{"line_number":21,"context_line":"  - name: static-centos"},{"line_number":22,"context_line":"    min-ready: 1"},{"line_number":23,"context_line":""},{"line_number":24,"context_line":"providers:"},{"line_number":25,"context_line":"  - name: cloud1"}],"source_content_type":"text/x-yaml","patch_set":13,"id":"7f231b9d_91658b48","line":22,"range":{"start_line":22,"start_character":4,"end_line":22,"end_character":16},"in_reply_to":"7f231b9d_7988a321","updated":"2017-06-20 02:45:43.000000000","message":"Done","commit_id":"1af1792ceca7cb0a1ddf323bd26a147869679a28"}],"nodepool/tests/test_driver_static.py":[{"author":{"_account_id":1,"name":"James E. Blair","email":"jim@acmegating.com","username":"corvus"},"change_message_id":"b7c27d379142048a34be75a107d433312243fcf8","unresolved":false,"context_lines":[{"line_number":54,"context_line":"        nodes \u003d self.waitForNodes(\u0027fake-label\u0027)"},{"line_number":55,"context_line":"        self.assertEqual(len(nodes), 1)"},{"line_number":56,"context_line":"        nodes \u003d self.waitForNodes(\u0027fake-concurrent-label\u0027, 2)"},{"line_number":57,"context_line":"        self.assertEqual(len(nodes), 2)"}],"source_content_type":"text/x-python","patch_set":34,"id":"df87a7cf_bdea4d72","line":57,"updated":"2017-12-06 17:32:56.000000000","message":"It would be good to have a test that requested nodes, then returned the nodes and requested them again, to exercise the full lifecycle.","commit_id":"3f4fc539781c38a53cedc380d1503f0d2e5393ad"},{"author":{"_account_id":9311,"name":"Tristan Cacqueray","email":"tdecacqu@redhat.com","username":"tristanC"},"change_message_id":"446d70e2f562759aff51dbeb636d5026a7891163","unresolved":false,"context_lines":[{"line_number":54,"context_line":"        nodes \u003d self.waitForNodes(\u0027fake-label\u0027)"},{"line_number":55,"context_line":"        self.assertEqual(len(nodes), 1)"},{"line_number":56,"context_line":"        nodes \u003d self.waitForNodes(\u0027fake-concurrent-label\u0027, 2)"},{"line_number":57,"context_line":"        self.assertEqual(len(nodes), 2)"}],"source_content_type":"text/x-python","patch_set":34,"id":"df87a7cf_f43d468f","line":57,"in_reply_to":"df87a7cf_bdea4d72","updated":"2017-12-07 01:37:03.000000000","message":"Done","commit_id":"3f4fc539781c38a53cedc380d1503f0d2e5393ad"}]}
