root / lib / qlang.py @ d5d76ab2
History | View | Annotate | Download (9.8 kB)
1 | a123dc19 | Michael Hanselmann | #
|
---|---|---|---|
2 | a123dc19 | Michael Hanselmann | #
|
3 | a123dc19 | Michael Hanselmann | |
4 | 2cfbc784 | Iustin Pop | # Copyright (C) 2010, 2011, 2012 Google Inc.
|
5 | a123dc19 | Michael Hanselmann | #
|
6 | a123dc19 | Michael Hanselmann | # This program is free software; you can redistribute it and/or modify
|
7 | a123dc19 | Michael Hanselmann | # it under the terms of the GNU General Public License as published by
|
8 | a123dc19 | Michael Hanselmann | # the Free Software Foundation; either version 2 of the License, or
|
9 | a123dc19 | Michael Hanselmann | # (at your option) any later version.
|
10 | a123dc19 | Michael Hanselmann | #
|
11 | a123dc19 | Michael Hanselmann | # This program is distributed in the hope that it will be useful, but
|
12 | a123dc19 | Michael Hanselmann | # WITHOUT ANY WARRANTY; without even the implied warranty of
|
13 | a123dc19 | Michael Hanselmann | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
14 | a123dc19 | Michael Hanselmann | # General Public License for more details.
|
15 | a123dc19 | Michael Hanselmann | #
|
16 | a123dc19 | Michael Hanselmann | # You should have received a copy of the GNU General Public License
|
17 | a123dc19 | Michael Hanselmann | # along with this program; if not, write to the Free Software
|
18 | a123dc19 | Michael Hanselmann | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
19 | a123dc19 | Michael Hanselmann | # 02110-1301, USA.
|
20 | a123dc19 | Michael Hanselmann | |
21 | a123dc19 | Michael Hanselmann | |
22 | 341ff8e9 | Michael Hanselmann | """Module for a simple query language
|
23 | 341ff8e9 | Michael Hanselmann |
|
24 | 341ff8e9 | Michael Hanselmann | A query filter is always a list. The first item in the list is the operator
|
25 | 341ff8e9 | Michael Hanselmann | (e.g. C{[OP_AND, ...]}), while the other items depend on the operator. For
|
26 | 341ff8e9 | Michael Hanselmann | logic operators (e.g. L{OP_AND}, L{OP_OR}), they are subfilters whose results
|
27 | 341ff8e9 | Michael Hanselmann | are combined. Unary operators take exactly one other item (e.g. a subfilter for
|
28 | 341ff8e9 | Michael Hanselmann | L{OP_NOT} and a field name for L{OP_TRUE}). Binary operators take exactly two
|
29 | 341ff8e9 | Michael Hanselmann | operands, usually a field name and a value to compare against. Filters are
|
30 | 341ff8e9 | Michael Hanselmann | converted to callable functions by L{query._CompileFilter}.
|
31 | 341ff8e9 | Michael Hanselmann |
|
32 | 341ff8e9 | Michael Hanselmann | """
|
33 | a123dc19 | Michael Hanselmann | |
34 | 7578ab0a | Michael Hanselmann | import re |
35 | b459a848 | Andrea Spadaccini | import string # pylint: disable=W0402 |
36 | f8638e28 | Michael Hanselmann | import logging |
37 | 7578ab0a | Michael Hanselmann | |
38 | 7578ab0a | Michael Hanselmann | import pyparsing as pyp |
39 | 7578ab0a | Michael Hanselmann | |
40 | 7578ab0a | Michael Hanselmann | from ganeti import errors |
41 | 3f2f55bb | Michael Hanselmann | from ganeti import netutils |
42 | 16629d10 | Michael Hanselmann | from ganeti import utils |
43 | f8638e28 | Michael Hanselmann | from ganeti import compat |
44 | 7578ab0a | Michael Hanselmann | |
45 | 7578ab0a | Michael Hanselmann | |
46 | 341ff8e9 | Michael Hanselmann | # Logic operators with one or more operands, each of which is a filter on its
|
47 | 341ff8e9 | Michael Hanselmann | # own
|
48 | a123dc19 | Michael Hanselmann | OP_OR = "|"
|
49 | 88076fd1 | Michael Hanselmann | OP_AND = "&"
|
50 | 88076fd1 | Michael Hanselmann | |
51 | 88076fd1 | Michael Hanselmann | |
52 | 341ff8e9 | Michael Hanselmann | # Unary operators with exactly one operand
|
53 | 88076fd1 | Michael Hanselmann | OP_NOT = "!"
|
54 | 3b877f08 | Michael Hanselmann | OP_TRUE = "?"
|
55 | 88076fd1 | Michael Hanselmann | |
56 | 88076fd1 | Michael Hanselmann | |
57 | 341ff8e9 | Michael Hanselmann | # Binary operators with exactly two operands, the field name and an
|
58 | 341ff8e9 | Michael Hanselmann | # operator-specific value
|
59 | a123dc19 | Michael Hanselmann | OP_EQUAL = "="
|
60 | 88076fd1 | Michael Hanselmann | OP_NOT_EQUAL = "!="
|
61 | ad48eacc | Michael Hanselmann | OP_LT = "<"
|
62 | ad48eacc | Michael Hanselmann | OP_LE = "<="
|
63 | ad48eacc | Michael Hanselmann | OP_GT = ">"
|
64 | ad48eacc | Michael Hanselmann | OP_GE = ">="
|
65 | 88076fd1 | Michael Hanselmann | OP_REGEXP = "=~"
|
66 | 88076fd1 | Michael Hanselmann | OP_CONTAINS = "=[]"
|
67 | a123dc19 | Michael Hanselmann | |
68 | a123dc19 | Michael Hanselmann | |
69 | 0b0ca0c0 | Michael Hanselmann | #: Characters used for detecting user-written filters (see L{_CheckFilter})
|
70 | ad48eacc | Michael Hanselmann | FILTER_DETECTION_CHARS = frozenset("()=/!~'\"\\<>" + string.whitespace) |
71 | f8638e28 | Michael Hanselmann | |
72 | 0b0ca0c0 | Michael Hanselmann | #: Characters used to detect globbing filters (see L{_CheckGlobbing})
|
73 | f8638e28 | Michael Hanselmann | GLOB_DETECTION_CHARS = frozenset("*?") |
74 | 3f2f55bb | Michael Hanselmann | |
75 | 3f2f55bb | Michael Hanselmann | |
76 | 60cba7f8 | Michael Hanselmann | def MakeSimpleFilter(namefield, values): |
77 | 31554d0a | Michael Hanselmann | """Builds simple a filter.
|
78 | 60cba7f8 | Michael Hanselmann |
|
79 | 60cba7f8 | Michael Hanselmann | @param namefield: Name of field containing item name
|
80 | 60cba7f8 | Michael Hanselmann | @param values: List of names
|
81 | 60cba7f8 | Michael Hanselmann |
|
82 | 60cba7f8 | Michael Hanselmann | """
|
83 | 60cba7f8 | Michael Hanselmann | if values:
|
84 | 60cba7f8 | Michael Hanselmann | return [OP_OR] + [[OP_EQUAL, namefield, i] for i in values] |
85 | 60cba7f8 | Michael Hanselmann | |
86 | 60cba7f8 | Michael Hanselmann | return None |
87 | 7578ab0a | Michael Hanselmann | |
88 | 7578ab0a | Michael Hanselmann | |
89 | 7578ab0a | Michael Hanselmann | def _ConvertLogicOp(op): |
90 | 7578ab0a | Michael Hanselmann | """Creates parsing action function for logic operator.
|
91 | 7578ab0a | Michael Hanselmann |
|
92 | 7578ab0a | Michael Hanselmann | @type op: string
|
93 | 7578ab0a | Michael Hanselmann | @param op: Operator for data structure, e.g. L{OP_AND}
|
94 | 7578ab0a | Michael Hanselmann |
|
95 | 7578ab0a | Michael Hanselmann | """
|
96 | 7578ab0a | Michael Hanselmann | def fn(toks): |
97 | 7578ab0a | Michael Hanselmann | """Converts parser tokens to query operator structure.
|
98 | 7578ab0a | Michael Hanselmann |
|
99 | 7578ab0a | Michael Hanselmann | @rtype: list
|
100 | 7578ab0a | Michael Hanselmann | @return: Query operator structure, e.g. C{[OP_AND, ["=", "foo", "bar"]]}
|
101 | 7578ab0a | Michael Hanselmann |
|
102 | 7578ab0a | Michael Hanselmann | """
|
103 | 7578ab0a | Michael Hanselmann | operands = toks[0]
|
104 | 7578ab0a | Michael Hanselmann | |
105 | 7578ab0a | Michael Hanselmann | if len(operands) == 1: |
106 | 7578ab0a | Michael Hanselmann | return operands[0] |
107 | 7578ab0a | Michael Hanselmann | |
108 | 7578ab0a | Michael Hanselmann | # Build query operator structure
|
109 | 7578ab0a | Michael Hanselmann | return [[op] + operands.asList()]
|
110 | 7578ab0a | Michael Hanselmann | |
111 | 7578ab0a | Michael Hanselmann | return fn
|
112 | 7578ab0a | Michael Hanselmann | |
113 | 7578ab0a | Michael Hanselmann | |
114 | 7578ab0a | Michael Hanselmann | _KNOWN_REGEXP_DELIM = "/#^|"
|
115 | 7578ab0a | Michael Hanselmann | _KNOWN_REGEXP_FLAGS = frozenset("si") |
116 | 7578ab0a | Michael Hanselmann | |
117 | 7578ab0a | Michael Hanselmann | |
118 | 7578ab0a | Michael Hanselmann | def _ConvertRegexpValue(_, loc, toks): |
119 | 7578ab0a | Michael Hanselmann | """Regular expression value for condition.
|
120 | 7578ab0a | Michael Hanselmann |
|
121 | 7578ab0a | Michael Hanselmann | """
|
122 | 7578ab0a | Michael Hanselmann | (regexp, flags) = toks[0]
|
123 | 7578ab0a | Michael Hanselmann | |
124 | 7578ab0a | Michael Hanselmann | # Ensure only whitelisted flags are used
|
125 | 7578ab0a | Michael Hanselmann | unknown_flags = (frozenset(flags) - _KNOWN_REGEXP_FLAGS)
|
126 | 7578ab0a | Michael Hanselmann | if unknown_flags:
|
127 | 7578ab0a | Michael Hanselmann | raise pyp.ParseFatalException("Unknown regular expression flags: '%s'" % |
128 | 7578ab0a | Michael Hanselmann | "".join(unknown_flags), loc)
|
129 | 7578ab0a | Michael Hanselmann | |
130 | 7578ab0a | Michael Hanselmann | if flags:
|
131 | 7578ab0a | Michael Hanselmann | re_flags = "(?%s)" % "".join(sorted(flags)) |
132 | 7578ab0a | Michael Hanselmann | else:
|
133 | 7578ab0a | Michael Hanselmann | re_flags = ""
|
134 | 7578ab0a | Michael Hanselmann | |
135 | 7578ab0a | Michael Hanselmann | re_cond = re_flags + regexp |
136 | 7578ab0a | Michael Hanselmann | |
137 | 7578ab0a | Michael Hanselmann | # Test if valid
|
138 | 7578ab0a | Michael Hanselmann | try:
|
139 | 7578ab0a | Michael Hanselmann | re.compile(re_cond) |
140 | 7578ab0a | Michael Hanselmann | except re.error, err:
|
141 | 7578ab0a | Michael Hanselmann | raise pyp.ParseFatalException("Invalid regular expression (%s)" % err, loc) |
142 | 7578ab0a | Michael Hanselmann | |
143 | 7578ab0a | Michael Hanselmann | return [re_cond]
|
144 | 7578ab0a | Michael Hanselmann | |
145 | 7578ab0a | Michael Hanselmann | |
146 | 7578ab0a | Michael Hanselmann | def BuildFilterParser(): |
147 | 7578ab0a | Michael Hanselmann | """Builds a parser for query filter strings.
|
148 | 7578ab0a | Michael Hanselmann |
|
149 | 7578ab0a | Michael Hanselmann | @rtype: pyparsing.ParserElement
|
150 | 7578ab0a | Michael Hanselmann |
|
151 | 7578ab0a | Michael Hanselmann | """
|
152 | 7578ab0a | Michael Hanselmann | field_name = pyp.Word(pyp.alphas, pyp.alphanums + "_/.")
|
153 | 7578ab0a | Michael Hanselmann | |
154 | 7578ab0a | Michael Hanselmann | # Integer
|
155 | 7578ab0a | Michael Hanselmann | num_sign = pyp.Word("-+", exact=1) |
156 | 7578ab0a | Michael Hanselmann | number = pyp.Combine(pyp.Optional(num_sign) + pyp.Word(pyp.nums)) |
157 | 7578ab0a | Michael Hanselmann | number.setParseAction(lambda toks: int(toks[0])) |
158 | 7578ab0a | Michael Hanselmann | |
159 | 16629d10 | Michael Hanselmann | quoted_string = pyp.quotedString.copy().setParseAction(pyp.removeQuotes) |
160 | 16629d10 | Michael Hanselmann | |
161 | 7578ab0a | Michael Hanselmann | # Right-hand-side value
|
162 | 16629d10 | Michael Hanselmann | rval = (number | quoted_string) |
163 | 7578ab0a | Michael Hanselmann | |
164 | 7578ab0a | Michael Hanselmann | # Boolean condition
|
165 | 7578ab0a | Michael Hanselmann | bool_cond = field_name.copy() |
166 | 7578ab0a | Michael Hanselmann | bool_cond.setParseAction(lambda (fname, ): [[OP_TRUE, fname]])
|
167 | 7578ab0a | Michael Hanselmann | |
168 | 7578ab0a | Michael Hanselmann | # Simple binary conditions
|
169 | 7578ab0a | Michael Hanselmann | binopstbl = { |
170 | 7578ab0a | Michael Hanselmann | "==": OP_EQUAL,
|
171 | 7578ab0a | Michael Hanselmann | "!=": OP_NOT_EQUAL,
|
172 | ad48eacc | Michael Hanselmann | "<": OP_LT,
|
173 | ad48eacc | Michael Hanselmann | "<=": OP_LE,
|
174 | ad48eacc | Michael Hanselmann | ">": OP_GT,
|
175 | ad48eacc | Michael Hanselmann | ">=": OP_GE,
|
176 | 7578ab0a | Michael Hanselmann | } |
177 | 7578ab0a | Michael Hanselmann | |
178 | 7578ab0a | Michael Hanselmann | binary_cond = (field_name + pyp.oneOf(binopstbl.keys()) + rval) |
179 | 7578ab0a | Michael Hanselmann | binary_cond.setParseAction(lambda (lhs, op, rhs): [[binopstbl[op], lhs, rhs]])
|
180 | 7578ab0a | Michael Hanselmann | |
181 | 7578ab0a | Michael Hanselmann | # "in" condition
|
182 | 7578ab0a | Michael Hanselmann | in_cond = (rval + pyp.Suppress("in") + field_name)
|
183 | 7578ab0a | Michael Hanselmann | in_cond.setParseAction(lambda (value, field): [[OP_CONTAINS, field, value]])
|
184 | 7578ab0a | Michael Hanselmann | |
185 | 7578ab0a | Michael Hanselmann | # "not in" condition
|
186 | 7578ab0a | Michael Hanselmann | not_in_cond = (rval + pyp.Suppress("not") + pyp.Suppress("in") + field_name) |
187 | 7578ab0a | Michael Hanselmann | not_in_cond.setParseAction(lambda (value, field): [[OP_NOT, [OP_CONTAINS,
|
188 | 7578ab0a | Michael Hanselmann | field, value]]]) |
189 | 7578ab0a | Michael Hanselmann | |
190 | 7578ab0a | Michael Hanselmann | # Regular expression, e.g. m/foobar/i
|
191 | 7578ab0a | Michael Hanselmann | regexp_val = pyp.Group(pyp.Optional("m").suppress() +
|
192 | 7578ab0a | Michael Hanselmann | pyp.MatchFirst([pyp.QuotedString(i, escChar="\\")
|
193 | 7578ab0a | Michael Hanselmann | for i in _KNOWN_REGEXP_DELIM]) + |
194 | 7578ab0a | Michael Hanselmann | pyp.Optional(pyp.Word(pyp.alphas), default=""))
|
195 | 7578ab0a | Michael Hanselmann | regexp_val.setParseAction(_ConvertRegexpValue) |
196 | 7578ab0a | Michael Hanselmann | regexp_cond = (field_name + pyp.Suppress("=~") + regexp_val)
|
197 | 7578ab0a | Michael Hanselmann | regexp_cond.setParseAction(lambda (field, value): [[OP_REGEXP, field, value]])
|
198 | 7578ab0a | Michael Hanselmann | |
199 | 7578ab0a | Michael Hanselmann | not_regexp_cond = (field_name + pyp.Suppress("!~") + regexp_val)
|
200 | 7578ab0a | Michael Hanselmann | not_regexp_cond.setParseAction(lambda (field, value):
|
201 | 7578ab0a | Michael Hanselmann | [[OP_NOT, [OP_REGEXP, field, value]]]) |
202 | 7578ab0a | Michael Hanselmann | |
203 | 16629d10 | Michael Hanselmann | # Globbing, e.g. name =* "*.site"
|
204 | 16629d10 | Michael Hanselmann | glob_cond = (field_name + pyp.Suppress("=*") + quoted_string)
|
205 | 16629d10 | Michael Hanselmann | glob_cond.setParseAction(lambda (field, value):
|
206 | 16629d10 | Michael Hanselmann | [[OP_REGEXP, field, |
207 | 16629d10 | Michael Hanselmann | utils.DnsNameGlobPattern(value)]]) |
208 | 16629d10 | Michael Hanselmann | |
209 | 16629d10 | Michael Hanselmann | not_glob_cond = (field_name + pyp.Suppress("!*") + quoted_string)
|
210 | 16629d10 | Michael Hanselmann | not_glob_cond.setParseAction(lambda (field, value):
|
211 | 16629d10 | Michael Hanselmann | [[OP_NOT, [OP_REGEXP, field, |
212 | 16629d10 | Michael Hanselmann | utils.DnsNameGlobPattern(value)]]]) |
213 | 16629d10 | Michael Hanselmann | |
214 | 7578ab0a | Michael Hanselmann | # All possible conditions
|
215 | 7578ab0a | Michael Hanselmann | condition = (binary_cond ^ bool_cond ^ |
216 | 7578ab0a | Michael Hanselmann | in_cond ^ not_in_cond ^ |
217 | 16629d10 | Michael Hanselmann | regexp_cond ^ not_regexp_cond ^ |
218 | 16629d10 | Michael Hanselmann | glob_cond ^ not_glob_cond) |
219 | 7578ab0a | Michael Hanselmann | |
220 | 7578ab0a | Michael Hanselmann | # Associativity operators
|
221 | 7578ab0a | Michael Hanselmann | filter_expr = pyp.operatorPrecedence(condition, [ |
222 | 7578ab0a | Michael Hanselmann | (pyp.Keyword("not").suppress(), 1, pyp.opAssoc.RIGHT, |
223 | 7578ab0a | Michael Hanselmann | lambda toks: [[OP_NOT, toks[0][0]]]), |
224 | 7578ab0a | Michael Hanselmann | (pyp.Keyword("and").suppress(), 2, pyp.opAssoc.LEFT, |
225 | 7578ab0a | Michael Hanselmann | _ConvertLogicOp(OP_AND)), |
226 | 7578ab0a | Michael Hanselmann | (pyp.Keyword("or").suppress(), 2, pyp.opAssoc.LEFT, |
227 | 7578ab0a | Michael Hanselmann | _ConvertLogicOp(OP_OR)), |
228 | 7578ab0a | Michael Hanselmann | ]) |
229 | 7578ab0a | Michael Hanselmann | |
230 | 7578ab0a | Michael Hanselmann | parser = pyp.StringStart() + filter_expr + pyp.StringEnd() |
231 | 7578ab0a | Michael Hanselmann | parser.parseWithTabs() |
232 | 7578ab0a | Michael Hanselmann | |
233 | 7578ab0a | Michael Hanselmann | # Originally C{parser.validate} was called here, but there seems to be some
|
234 | 7578ab0a | Michael Hanselmann | # issue causing it to fail whenever the "not" operator is included above.
|
235 | 7578ab0a | Michael Hanselmann | |
236 | 7578ab0a | Michael Hanselmann | return parser
|
237 | 7578ab0a | Michael Hanselmann | |
238 | 7578ab0a | Michael Hanselmann | |
239 | 7578ab0a | Michael Hanselmann | def ParseFilter(text, parser=None): |
240 | 7578ab0a | Michael Hanselmann | """Parses a query filter.
|
241 | 7578ab0a | Michael Hanselmann |
|
242 | 7578ab0a | Michael Hanselmann | @type text: string
|
243 | 7578ab0a | Michael Hanselmann | @param text: Query filter
|
244 | 7578ab0a | Michael Hanselmann | @type parser: pyparsing.ParserElement
|
245 | 7578ab0a | Michael Hanselmann | @param parser: Pyparsing object
|
246 | 7578ab0a | Michael Hanselmann | @rtype: list
|
247 | 7578ab0a | Michael Hanselmann |
|
248 | 7578ab0a | Michael Hanselmann | """
|
249 | f8638e28 | Michael Hanselmann | logging.debug("Parsing as query filter: %s", text)
|
250 | f8638e28 | Michael Hanselmann | |
251 | 7578ab0a | Michael Hanselmann | if parser is None: |
252 | 7578ab0a | Michael Hanselmann | parser = BuildFilterParser() |
253 | 7578ab0a | Michael Hanselmann | |
254 | 7578ab0a | Michael Hanselmann | try:
|
255 | 7578ab0a | Michael Hanselmann | return parser.parseString(text)[0] |
256 | 7578ab0a | Michael Hanselmann | except pyp.ParseBaseException, err:
|
257 | 7578ab0a | Michael Hanselmann | raise errors.QueryFilterParseError("Failed to parse query filter" |
258 | 7578ab0a | Michael Hanselmann | " '%s': %s" % (text, err), err)
|
259 | 3f2f55bb | Michael Hanselmann | |
260 | 3f2f55bb | Michael Hanselmann | |
261 | f8638e28 | Michael Hanselmann | def _IsHostname(text): |
262 | f8638e28 | Michael Hanselmann | """Checks if a string could be a hostname.
|
263 | 3f2f55bb | Michael Hanselmann |
|
264 | 3f2f55bb | Michael Hanselmann | @rtype: bool
|
265 | 3f2f55bb | Michael Hanselmann |
|
266 | 3f2f55bb | Michael Hanselmann | """
|
267 | 3f2f55bb | Michael Hanselmann | try:
|
268 | 3f2f55bb | Michael Hanselmann | netutils.Hostname.GetNormalizedName(text) |
269 | 3f2f55bb | Michael Hanselmann | except errors.OpPrereqError:
|
270 | f8638e28 | Michael Hanselmann | return False |
271 | f8638e28 | Michael Hanselmann | else:
|
272 | 3f2f55bb | Michael Hanselmann | return True |
273 | 3f2f55bb | Michael Hanselmann | |
274 | f8638e28 | Michael Hanselmann | |
275 | f8638e28 | Michael Hanselmann | def _CheckFilter(text): |
276 | f8638e28 | Michael Hanselmann | """CHecks if a string could be a filter.
|
277 | f8638e28 | Michael Hanselmann |
|
278 | f8638e28 | Michael Hanselmann | @rtype: bool
|
279 | f8638e28 | Michael Hanselmann |
|
280 | f8638e28 | Michael Hanselmann | """
|
281 | f8638e28 | Michael Hanselmann | return bool(frozenset(text) & FILTER_DETECTION_CHARS) |
282 | f8638e28 | Michael Hanselmann | |
283 | f8638e28 | Michael Hanselmann | |
284 | f8638e28 | Michael Hanselmann | def _CheckGlobbing(text): |
285 | f8638e28 | Michael Hanselmann | """Checks if a string could be a globbing pattern.
|
286 | f8638e28 | Michael Hanselmann |
|
287 | f8638e28 | Michael Hanselmann | @rtype: bool
|
288 | f8638e28 | Michael Hanselmann |
|
289 | f8638e28 | Michael Hanselmann | """
|
290 | f8638e28 | Michael Hanselmann | return bool(frozenset(text) & GLOB_DETECTION_CHARS) |
291 | f8638e28 | Michael Hanselmann | |
292 | f8638e28 | Michael Hanselmann | |
293 | 6f287cf3 | Iustin Pop | def _MakeFilterPart(namefield, text, isnumeric=False): |
294 | f8638e28 | Michael Hanselmann | """Generates filter for one argument.
|
295 | f8638e28 | Michael Hanselmann |
|
296 | f8638e28 | Michael Hanselmann | """
|
297 | 6f287cf3 | Iustin Pop | if isnumeric:
|
298 | 6f287cf3 | Iustin Pop | try:
|
299 | 6f287cf3 | Iustin Pop | number = int(text)
|
300 | 6f287cf3 | Iustin Pop | except (TypeError, ValueError), err: |
301 | 76b62028 | Iustin Pop | raise errors.OpPrereqError("Invalid job ID passed: %s" % str(err), |
302 | 6f287cf3 | Iustin Pop | errors.ECODE_INVAL) |
303 | 6f287cf3 | Iustin Pop | return [OP_EQUAL, namefield, number]
|
304 | 6f287cf3 | Iustin Pop | elif _CheckGlobbing(text):
|
305 | f8638e28 | Michael Hanselmann | return [OP_REGEXP, namefield, utils.DnsNameGlobPattern(text)]
|
306 | f8638e28 | Michael Hanselmann | else:
|
307 | f8638e28 | Michael Hanselmann | return [OP_EQUAL, namefield, text]
|
308 | f8638e28 | Michael Hanselmann | |
309 | f8638e28 | Michael Hanselmann | |
310 | 6f287cf3 | Iustin Pop | def MakeFilter(args, force_filter, namefield=None, isnumeric=False): |
311 | f8638e28 | Michael Hanselmann | """Try to make a filter from arguments to a command.
|
312 | f8638e28 | Michael Hanselmann |
|
313 | f8638e28 | Michael Hanselmann | If the name could be a filter it is parsed as such. If it's just a globbing
|
314 | f8638e28 | Michael Hanselmann | pattern, e.g. "*.site", such a filter is constructed. As a last resort the
|
315 | f8638e28 | Michael Hanselmann | names are treated just as a plain name filter.
|
316 | f8638e28 | Michael Hanselmann |
|
317 | f8638e28 | Michael Hanselmann | @type args: list of string
|
318 | f8638e28 | Michael Hanselmann | @param args: Arguments to command
|
319 | f8638e28 | Michael Hanselmann | @type force_filter: bool
|
320 | f8638e28 | Michael Hanselmann | @param force_filter: Whether to force treatment as a full-fledged filter
|
321 | 03ec545a | Michael Hanselmann | @type namefield: string
|
322 | 03ec545a | Michael Hanselmann | @param namefield: Name of field to use for simple filters (use L{None} for
|
323 | 03ec545a | Michael Hanselmann | a default of "name")
|
324 | 6f287cf3 | Iustin Pop | @type isnumeric: bool
|
325 | 6f287cf3 | Iustin Pop | @param isnumeric: Whether the namefield type is numeric, as opposed to
|
326 | 6f287cf3 | Iustin Pop | the default string type; this influences how the filter is built
|
327 | f8638e28 | Michael Hanselmann | @rtype: list
|
328 | f8638e28 | Michael Hanselmann | @return: Query filter
|
329 | f8638e28 | Michael Hanselmann |
|
330 | f8638e28 | Michael Hanselmann | """
|
331 | 03ec545a | Michael Hanselmann | if namefield is None: |
332 | 03ec545a | Michael Hanselmann | namefield = "name"
|
333 | 03ec545a | Michael Hanselmann | |
334 | f8638e28 | Michael Hanselmann | if (force_filter or |
335 | f8638e28 | Michael Hanselmann | (args and len(args) == 1 and _CheckFilter(args[0]))): |
336 | f8638e28 | Michael Hanselmann | try:
|
337 | f8638e28 | Michael Hanselmann | (filter_text, ) = args |
338 | f8638e28 | Michael Hanselmann | except (TypeError, ValueError): |
339 | f8638e28 | Michael Hanselmann | raise errors.OpPrereqError("Exactly one argument must be given as a" |
340 | 2cfbc784 | Iustin Pop | " filter", errors.ECODE_INVAL)
|
341 | f8638e28 | Michael Hanselmann | |
342 | f8638e28 | Michael Hanselmann | result = ParseFilter(filter_text) |
343 | f8638e28 | Michael Hanselmann | elif args:
|
344 | 6f287cf3 | Iustin Pop | result = [OP_OR] + map(compat.partial(_MakeFilterPart, namefield,
|
345 | 6f287cf3 | Iustin Pop | isnumeric=isnumeric), args) |
346 | f8638e28 | Michael Hanselmann | else:
|
347 | f8638e28 | Michael Hanselmann | result = None
|
348 | f8638e28 | Michael Hanselmann | |
349 | f8638e28 | Michael Hanselmann | return result |