Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 213 lines (188 sloc) 8.45 kB
962298e @stotch Added default behavior, handling of long and short options for modify…
stotch authored
1 #!/usr/bin/python
2
d2452a9 @voldemort Step 1 : Generate cluster script cleanup
authored
3 #
4 # Copyright 2013 LinkedIn, Inc
5 #
6 # Licensed under the Apache License, Version 2.0 (the "License");
7 # you may not use this file except in compliance with the License.
8 # You may obtain a copy of the License at
9 #
10 # http://www.apache.org/licenses/LICENSE-2.0
11 #
12 # Unless required by applicable law or agreed to in writing, software
13 # distributed under the License is distributed on an "AS IS" BASIS,
14 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 # See the License for the specific language governing permissions and
16 # limitations under the License.
17
18 # Python 2.7+ required
19 # This script encapsulates the cluster.xml generation for a zoned and a non-zoned
20 # cluster. Passing --zones <num of zones> switch to the script generates a zoned cluster
21 # config. A non zoned cluster is generated otherwise.
22 #
23 # The newly generated cluster.xml file is placed in the output dir.
24 #
25 # Example use for a zoned cluster :
26 # python generate_cluster_xml.py --file <file with host names, one host per line>
27 # --name <name of the cluster>
28 # --nodes <number of nodes>
3944a3c @voldemort Cleanup the arguments and add sanity check
authored
29 # --partitions <number of partitions>
5d1e8e3 @voldemort Step 2: Add logic to handle zoned clusters
authored
30 # --sock-port <port no>
31 # --admin-port <port no>
32 # --http-port <port no>
3944a3c @voldemort Cleanup the arguments and add sanity check
authored
33 # --current-stores <current_stores.xml>
5d1e8e3 @voldemort Step 2: Add logic to handle zoned clusters
authored
34 # --output-dir <output directory>
d2452a9 @voldemort Step 1 : Generate cluster script cleanup
authored
35 # --zones <number of zones>
36 #
3944a3c @voldemort Cleanup the arguments and add sanity check
authored
37 # For non zoned cluster use :
38 # python generate_cluster_xml.py --file <file with host names, one host per line>
39 # --name <name of the cluster>
40 # --nodes <number of nodes>
41 # --partitions <number of partitions>
42 # --sock-port <port no>
43 # --admin-port <port no>
44 # --http-port <port no>
45 # --current-stores <current_stores.xml>
46 # --output-dir <output directory>
155b934 @voldemort Fix comments and typos
authored
47 #
48 # Note the absence of the --zones switch for the non zoned cluster use case.
d2452a9 @voldemort Step 1 : Generate cluster script cleanup
authored
49
4786eae @jkreps Add cluster control scripts. Patch on http://code.google.com/p/projec…
jkreps authored
50 import sys
51 import random
d2452a9 @voldemort Step 1 : Generate cluster script cleanup
authored
52 import os
53 import errno
5d1e8e3 @voldemort Step 2: Add logic to handle zoned clusters
authored
54 import subprocess
55
d2452a9 @voldemort Step 1 : Generate cluster script cleanup
authored
56 try:
57 import argparse
58 except ImportError:
59 print "Python 2.7 or higher is needed"
962298e @stotch Added default behavior, handling of long and short options for modify…
stotch authored
60
3944a3c @voldemort Cleanup the arguments and add sanity check
authored
61
962298e @stotch Added default behavior, handling of long and short options for modify…
stotch authored
62 # Get a random seed
3aa9d12 @stotch Fixed --seed argument handling so that it actually works, now
stotch authored
63 rseed = int(random.randint(00000000001,99999999999))
962298e @stotch Added default behavior, handling of long and short options for modify…
stotch authored
64
65 # Setup and argument parser
66 parser = argparse.ArgumentParser(description='Build a voldemort cluster.xml.')
67 # Add supported arguments
a9a23f6 @baepiff added hosts list file option
baepiff authored
68 parser.add_argument('-f', '--file', type=str, dest='file',
c61182a @baepiff fixed wrong variable name and modified poor expressions
baepiff authored
69 help='the file of the list of hosts(one per line)')
962298e @stotch Added default behavior, handling of long and short options for modify…
stotch authored
70 parser.add_argument('-N', '--name', type=str, default='voldemort', dest='name',
ab97905 @stotch Per Jay Wylie's review, no longer using a dict to store the partition…
stotch authored
71 help='the name you want to give the cluster')
3944a3c @voldemort Cleanup the arguments and add sanity check
authored
72 parser.add_argument('-n', '--nodes', type=int, default=6, dest='nodes',
962298e @stotch Added default behavior, handling of long and short options for modify…
stotch authored
73 help='the number of nodes in the cluster')
5d1e8e3 @voldemort Step 2: Add logic to handle zoned clusters
authored
74 parser.add_argument('-p', '--partitions', type=int, default=1500,
75 dest='partitions', help='number of partitions')
76 parser.add_argument('-sp', '--socket-port', type=int, default=6666,
962298e @stotch Added default behavior, handling of long and short options for modify…
stotch authored
77 dest='sock_port', help='socket port number')
5d1e8e3 @voldemort Step 2: Add logic to handle zoned clusters
authored
78 parser.add_argument('-ap', '--admin-port', type=int, default=6667,
962298e @stotch Added default behavior, handling of long and short options for modify…
stotch authored
79 dest='admin_port', help='admin port number')
5d1e8e3 @voldemort Step 2: Add logic to handle zoned clusters
authored
80 parser.add_argument('-hp', '--http-port', type=int, default=6665,
962298e @stotch Added default behavior, handling of long and short options for modify…
stotch authored
81 dest='http_port', help='http port number')
3944a3c @voldemort Cleanup the arguments and add sanity check
authored
82 parser.add_argument('-s', '--current-stores', type=str, default= "config/tools/dummy-stores-3zoned.xml",
83 dest='current_stores',
5d1e8e3 @voldemort Step 2: Add logic to handle zoned clusters
authored
84 help='Path to current stores xml. If you do not have info about the stores yet'
85 'use config/tools/dummy-stores.xml from the root voldemort home folder.')
d2452a9 @voldemort Step 1 : Generate cluster script cleanup
authored
86 parser.add_argument('-o', '--output-dir', type=str, dest='output_dir',
87 help='output directory location')
5d1e8e3 @voldemort Step 2: Add logic to handle zoned clusters
authored
88 parser.add_argument('-z', '--zones', type=int, dest='zones',
3944a3c @voldemort Cleanup the arguments and add sanity check
authored
89 help='For non zoned clusters do not provide this argument.'
90 'For zoned clusters provide this argument with at least two zones.')
5d1e8e3 @voldemort Step 2: Add logic to handle zoned clusters
authored
91
92 genType = parser.add_mutually_exclusive_group()
93 genType.add_argument('--seed', type=int, default=rseed, dest='seed',
94 help='seed for randomizing partition distribution')
d2452a9 @voldemort Step 1 : Generate cluster script cleanup
authored
95
962298e @stotch Added default behavior, handling of long and short options for modify…
stotch authored
96 # Parse arguments
97 args = parser.parse_args()
98
d2452a9 @voldemort Step 1 : Generate cluster script cleanup
authored
99 # Check if the input file exists
100 try:
101 with open(args.file): pass
102 except IOError:
103 print 'File does not exist'
104
105 # create output-dir if it does not exist
106 try:
107 os.makedirs(args.output_dir)
108 except OSError as exception:
109 if exception.errno != errno.EEXIST:
110 raise
111
112 # Open a new file named cluster.xml
5d1e8e3 @voldemort Step 2: Add logic to handle zoned clusters
authored
113 clusterXMLFilePath = os.path.join(os.path.abspath(args.output_dir), 'cluster.xml')
114 fileHandle = open(clusterXMLFilePath, 'w')
d2452a9 @voldemort Step 1 : Generate cluster script cleanup
authored
115
5d1e8e3 @voldemort Step 2: Add logic to handle zoned clusters
authored
116 # TODO : It would be ideal to have the script accept a list of zone ids.
962298e @stotch Added default behavior, handling of long and short options for modify…
stotch authored
117 if args.zones:
118 zones = args.zones
3944a3c @voldemort Cleanup the arguments and add sanity check
authored
119 if (zones == 1):
120 print "For non zoned clusters do not provide this argument."
121 print "For zoned clusters provide this argument with at least two zones."
122 sys.exit(1)
962298e @stotch Added default behavior, handling of long and short options for modify…
stotch authored
123 if (args.nodes % zones) != 0:
124 print "Number of nodes must be evenly divisible by number of zones"
125 sys.exit(1)
126
127 # Store arguments
a9a23f6 @baepiff added hosts list file option
baepiff authored
128 if args.file:
c61182a @baepiff fixed wrong variable name and modified poor expressions
baepiff authored
129 hostList = open(args.file).readlines()
a9a23f6 @baepiff added hosts list file option
baepiff authored
130 nodes = len(hostList)
131 else:
132 nodes = args.nodes
962298e @stotch Added default behavior, handling of long and short options for modify…
stotch authored
133 partitions = args.partitions
134 name = args.name
135 http_port = args.http_port
136 sock_port = args.sock_port
137 admin_port = args.admin_port
3aa9d12 @stotch Fixed --seed argument handling so that it actually works, now
stotch authored
138 seed = args.seed
3944a3c @voldemort Cleanup the arguments and add sanity check
authored
139 vold_home = os.pardir
140 current_stores = os.path.join(vold_home, args.current_stores);
962298e @stotch Added default behavior, handling of long and short options for modify…
stotch authored
141
142 # Generate the full list of partition IDs
5d1e8e3 @voldemort Step 2: Add logic to handle zoned clusters
authored
143 part_ids = range(partitions)
144 if part_ids < 1500:
3944a3c @voldemort Cleanup the arguments and add sanity check
authored
145 print 'Warning : The number of partitions seems to be low. Assuming max of 3 zones and 50 nodes ' \
146 'per zone, a partition value of 1500 is recommended as it ensures an average of 10 ' \
147 'partitions per node.'
148 print 'Warning : The number of partitions seems to be low. Recommended value is 1500 or more.'
149
962298e @stotch Added default behavior, handling of long and short options for modify…
stotch authored
150 # Generate full list of zone IDs
151 if args.zones:
152 zone_ids = range(zones)
153 zone_id = 0
415d982 @stotch Getting rid of some unused and deprecated code, added in a comment to…
stotch authored
154
155 # Shuffle up the partitions
962298e @stotch Added default behavior, handling of long and short options for modify…
stotch authored
156 random.seed(seed)
157 random.shuffle(part_ids)
158
ab97905 @stotch Per Jay Wylie's review, no longer using a dict to store the partition…
stotch authored
159 # Printing cluster.xml
d2452a9 @voldemort Step 1 : Generate cluster script cleanup
authored
160 print >> fileHandle, "<cluster>"
161 print >> fileHandle, " <name>%s</name>" % name
162
163 if args.zones:
164 for i in range(args.zones):
165 print >> fileHandle, " <zone>"
166 print >> fileHandle, " <zone-id>%d</zone-id>" % i
167 proximityList = list()
168 for j in range(1, len(zone_ids) ):
169 proximityList.append(zone_ids[(i+j)%len(zone_ids)])
170 print >> fileHandle, " <proximity-list>%s</proximity-list>" % str(proximityList).strip('[]')
171 print >> fileHandle, " </zone>"
962298e @stotch Added default behavior, handling of long and short options for modify…
stotch authored
172
155b934 @voldemort Fix comments and typos
authored
173 # TODO : Currently, random partitions are assigned to the nodes in a round robin fashion.
3944a3c @voldemort Cleanup the arguments and add sanity check
authored
174 # A better approach would be to have some intelligence in the allocation such that
175 # consecutive partition-ids do not land on the same node.
5d1e8e3 @voldemort Step 2: Add logic to handle zoned clusters
authored
176
962298e @stotch Added default behavior, handling of long and short options for modify…
stotch authored
177 for i in xrange(nodes):
3944a3c @voldemort Cleanup the arguments and add sanity check
authored
178 j = i
179 node_partitions = list()
180 while j < len(part_ids):
181 node_partitions.append(str(part_ids[j]))
182 j += nodes;
183 partitionslist = ", ".join(node_partitions);
184
d2452a9 @voldemort Step 1 : Generate cluster script cleanup
authored
185 print >> fileHandle, " <server>"
186 print >> fileHandle, " <id>%d</id>" % i
a9a23f6 @baepiff added hosts list file option
baepiff authored
187 if args.file:
d2452a9 @voldemort Step 1 : Generate cluster script cleanup
authored
188 print >> fileHandle, " <host>%s</host>" % hostList[i].strip()
a9a23f6 @baepiff added hosts list file option
baepiff authored
189 else:
d2452a9 @voldemort Step 1 : Generate cluster script cleanup
authored
190 print >> fileHandle, " <host>host%d</host>" % i
191 print >> fileHandle, " <http-port>%d</http-port>" % http_port
192 print >> fileHandle, " <socket-port>%d</socket-port>" % sock_port
193 print >> fileHandle, " <admin-port>%d</admin-port>" % admin_port
3944a3c @voldemort Cleanup the arguments and add sanity check
authored
194 print >> fileHandle, " <partitions>%s</partitions>" % partitionslist
962298e @stotch Added default behavior, handling of long and short options for modify…
stotch authored
195 # If zones are being used, assign a zone-id
196 if args.zones:
d2452a9 @voldemort Step 1 : Generate cluster script cleanup
authored
197 print >> fileHandle, " <zone-id>%d</zone-id>" % zone_id
962298e @stotch Added default behavior, handling of long and short options for modify…
stotch authored
198 if zone_id == (zones - 1):
199 zone_id = 0
200 else:
201 zone_id += 1
d2452a9 @voldemort Step 1 : Generate cluster script cleanup
authored
202 print >> fileHandle, " </server>"
203 print >> fileHandle, "</cluster>"
4786eae @jkreps Add cluster control scripts. Patch on http://code.google.com/p/projec…
jkreps authored
204
5d1e8e3 @voldemort Step 2: Add logic to handle zoned clusters
authored
205 fileHandle.close()
206
3944a3c @voldemort Cleanup the arguments and add sanity check
authored
207 # For zoned clusters call rebalance-new-cluster.sh
5d1e8e3 @voldemort Step 2: Add logic to handle zoned clusters
authored
208 if args.zones:
299bb61 @voldemort Rename new cluster script
authored
209 scriptPath = vold_home + '/bin/rebalance-new-zoned-cluster.sh'
5d1e8e3 @voldemort Step 2: Add logic to handle zoned clusters
authored
210 cmd = [scriptPath, '-v', vold_home, '-c', clusterXMLFilePath, '-s', current_stores,
211 '-o', os.path.abspath(args.output_dir)]
212 subprocess.call(cmd)
Something went wrong with that request. Please try again.