blob: 8f4769833856a87dc29e828ef5960983214d9f88 [file] [log] [blame]
# */
# * Licensed to the Apache Software Foundation (ASF) under one
# * or more contributor license agreements. See the NOTICE file
# * distributed with this work for additional information
# * regarding copyright ownership. The ASF licenses this file
# * to you 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 json
import time
import requests
__author__ = 'Jeff.West@yahoo.com'
# The purpose of this script is to set certain nodes in an ElasticSearch cluster to be excluded from index allocation,
# generally for the purpose of decomissioning or troubleshooting a node.
# you can optionally shut down nodes as they have all the replicas removed from them
SHUTDOWN_NODES = True
# these are the nodes which will have shard allocation disabled. The replicas will then be gradually moved off these
# nodes. The amount of time required depends on the size of the index, speed of network, CPU and cluster load
exclude_nodes = [
'elasticsearch206west',
'elasticsearch207west',
]
base_url = 'http://localhost:9200'
nodes_string = ",".join(exclude_nodes)
print 'Excluding: ' + nodes_string
url_template = '%s/_cluster/settings' % base_url
status_code = 503
# when a cluster is under load, it is possible that a 5xx will be returned.
while status_code >= 500:
r = requests.put(
'%s/_cluster/settings' % base_url,
data=json.dumps({
"transient": {
"cluster.routing.allocation.exclude._host": nodes_string
}
}))
status_code = r.status_code
print '%s: %s' % (r.status_code, r.text)
ready = False
nodes_shut_down = []
while not ready:
ready = True
nodes_left = 0
bytes_left = 0
for node in exclude_nodes:
node_url = '%s/_nodes/%s/stats' % (base_url, node)
r = requests.get(node_url)
if r.status_code == 200:
# print r.text
node_stats = r.json()
for field, data in node_stats.get('nodes').iteritems():
if data.get('name') == node:
size = data.get('indices', {}).get('store', {}).get('size_in_bytes', 1)
docs = data.get('indices', {}).get('docs', {}).get('count', 1)
if size > 0 and docs > 0:
print 'Node: %s - size %s' % (node, size)
bytes_left += size
ready = False and ready
nodes_left += 1
else:
if SHUTDOWN_NODES:
if not node in nodes_shut_down:
nodes_shut_down.append(node)
shutdown_url = '%s/_cluster/nodes/%s/_shutdown' % (base_url, node)
print 'Shutting down node %s: %s' % (node, shutdown_url)
r = requests.post(shutdown_url)
if r.status_code == 200:
nodes_shut_down.append(node)
print 'Shut down node %s' % node
else:
print 'Shutdown failed: %s: %s' % (r.status_code, r.text)
if not ready:
print 'NOT READY! Waiting for %s nodes and %s GB' % (nodes_left, bytes_left / 1024.0 / 1000000)
time.sleep(10)
print 'READY TO MOVE!'