1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36 """
37 Usage: nodeset [options] [command]
38
39 Commands:
40 --count, -c <nodeset> [nodeset ...]
41 Return the number of nodes in nodesets.
42 --expand, -e <nodeset> [nodeset ...]
43 Expand nodesets to separate nodes.
44 --fold, -f <nodeset> [nodeset ...]
45 Compact/fold nodesets (or separate nodes) into one nodeset.
46 Options:
47 --autostep=<number>, -a <number>
48 Specify auto step threshold number when folding nodesets.
49 If not specified, auto step is disabled.
50 Example: autostep=4, "node2 node4 node6" folds in node[2,4,6]
51 autostep=3, "node2 node4 node6" folds in node[2-6/2]
52 --exclude=<nodeset>, -x <nodeset>
53 Exclude provided node or nodeset from result. Can be specified
54 several times.
55 --help, -h
56 This help page.
57 --intersection, -i
58 Calculate nodesets intersection before processing command. This
59 means that only nodes that are in every provided nodesets are
60 used.
61 --xor, -X
62 Calculate symmetric difference (XOR) between two nodesets before
63 processing command. This means that nodes present in only one of
64 the nodesets are used.
65 --rangeset, -R
66 Switch to RangeSet instead of NodeSet. Useful when working on
67 numerical cluster ranges, eg. 1,5,18-31.
68 --quiet, -q
69 Quiet mode, hide any parse error messages (on stderr).
70 --version, -v
71 Show ClusterShell version and exit.
72 """
73
74 import getopt
75 import signal
76 import sys
77
78 sys.path.insert(0, '../lib')
79
80 from ClusterShell.NodeSet import NodeSet, NodeSetParseError
81 from ClusterShell.NodeSet import RangeSet, RangeSetParseError
82 from ClusterShell import __version__
83
84
86 """
87 Main script function.
88 """
89 autostep = None
90 command = None
91 preprocess = None
92 quiet = False
93 class_set = NodeSet
94
95
96 try:
97 opts, args = getopt.getopt(args[1:], "a:cefhiqvx:RX", ["autostep=",
98 "count", "expand", "fold", "help", "intersection", "quiet",
99 "rangeset", "version", "exclude=", "xor"])
100 except getopt.error, msg:
101 print >>sys.stderr, msg
102 print >>sys.stderr, "Try `%s -h' for more information." % args[0]
103 sys.exit(2)
104
105
106 for opt in [ "-R", "--rangeset" ]:
107 if opt in [k for k, v in opts]:
108 class_set = RangeSet
109
110
111 excludes = class_set()
112
113
114 for k, v in opts:
115 if k in ("-a", "--autostep"):
116 try:
117 autostep = int(v)
118 except ValueError, e:
119 print >>sys.stderr, e
120 elif k in ("-c", "--count"):
121 command = "count"
122 elif k in ("-e", "--expand"):
123 command = "expand"
124 elif k in ("-f", "--fold"):
125 command = "fold"
126 elif k in ("-h", "--help"):
127 print __doc__
128 sys.exit(0)
129 elif k in ("-i", "--intersection"):
130 if preprocess and preprocess != class_set.intersection_update:
131 print >>sys.stderr, "ERROR: Conflicting options."
132 sys.exit(2)
133 preprocess = class_set.intersection_update
134 elif k in ("-q", "--quiet"):
135 quiet = True
136 elif k in ("-v", "--version"):
137 print __version__
138 sys.exit(0)
139 elif k in ("-x", "--exclude"):
140 excludes.update(class_set(v))
141 elif k in ("-X", "--xor"):
142 if preprocess and preprocess != class_set.symmetric_difference_update:
143 print >>sys.stderr, "ERROR: Conflicting options."
144 sys.exit(2)
145 preprocess = class_set.symmetric_difference_update
146
147
148 if not command:
149 print >>sys.stderr, "ERROR: no command specified."
150 print __doc__
151 sys.exit(1)
152
153 try:
154
155 read_stdin = len(args) < 1
156 ns = None
157
158 if len(args):
159 if '-' in args:
160
161 read_stdin = True
162 args.remove('-')
163 if len(args):
164
165 if not preprocess:
166 preprocess = class_set.update
167
168
169
170 ns = class_set(args[0], autostep=autostep)
171 for arg in args[1:]:
172 preprocess(ns, class_set(arg, autostep=autostep))
173
174 if read_stdin:
175
176
177 if not preprocess:
178 preprocess = class_set.update
179
180 for line in sys.stdin.readlines():
181 line = line[0:line.find('#')].strip()
182 for node in line.split():
183 if not ns:
184 ns = class_set(node, autostep=autostep)
185 else:
186 preprocess(ns, class_set(node, autostep=autostep))
187
188
189 if excludes:
190 ns.difference_update(excludes)
191
192 if command == "expand":
193 print " ".join(ns)
194 elif command == "fold":
195 print ns
196 else:
197 print len(ns)
198 except (NodeSetParseError, RangeSetParseError), e:
199 if not quiet:
200 print >>sys.stderr, "%s parse error:" % class_set.__name__, e
201
202
203
204 if hasattr(e, 'part') and e.part:
205 print >>sys.stderr, ">>", e.part
206 sys.exit(1)
207
208 if __name__ == '__main__':
209 try:
210 run_nodeset(sys.argv)
211 except AssertionError, e:
212 print >>sys.stderr, "ERROR:", e
213 sys.exit(1)
214 except KeyboardInterrupt:
215 sys.exit(128 + signal.SIGINT)
216 sys.exit(0)
217