11#!/usr/bin/env python
22# -*- coding: utf-8 -*-
3-
43import json
54import re
65
@@ -26,152 +25,136 @@ def log_and_raise_error(code, desc):
2625# All functions starting with `parse_` are helper functions compatible with the `Parser` class.
2726# Each should accept `args` as input and return either (result, None) on success,
2827# or (None, error_message) on failure.
28+ class Parser :
29+ def __init__ (self , args ):
30+ self .args = args
31+ self .values = {}
32+ self .errors = []
2933
34+ def parse_bridge (self , args ):
35+ BRIDGE_REGEX = re .compile (r"\b\w+\d+\b" )
36+ bridge = args .get ("bridge" )
3037
31- def parse_bridge (args ):
32- BRIDGE_REGEX = re .compile (r"\b\w+\d+\b" )
33- bridge = args .get ("bridge" )
34-
35- if bridge is None :
36- return None , "bridge parameter is missing"
37-
38- if not BRIDGE_REGEX .match (bridge ):
39- return None , "'{}' is not a valid bridge name" .format (bridge )
40-
41- return bridge , None
42-
43-
44- def parse_mac (args ):
45- MAC_REGEX = re .compile (r"^([0-9A-Fa-f]{2}:){5}([0-9A-Fa-f]{2})$" )
46- mac_addr = args .get ("mac" )
47-
48- if mac_addr is None :
49- return None , None # no mac means network wide rule
50-
51- if not MAC_REGEX .match (mac_addr ) or MAC_REGEX .match (mac_addr ).group (0 ) != mac_addr :
52- return None , "'{}' is not a valid MAC" .format (mac_addr )
53-
54- return mac_addr , None
55-
38+ if bridge is None :
39+ log_and_raise_error (E_PARSER , "bridge parameter is missing" )
5640
57- def parse_iprange (args ):
58- IPRANGE_REGEX = re .compile (
59- r"^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}"
60- r"(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(/\d{1,2})?$"
61- )
62- ip_range = args .get ("iprange" )
41+ if not BRIDGE_REGEX .match (bridge ):
42+ log_and_raise_error (E_PARSER , "'{}' is not a valid bridge name" .format (bridge ))
6343
64- if ip_range is None :
65- return None , "ip range parameter is missing"
44+ return bridge
6645
67- if not IPRANGE_REGEX .match (ip_range ):
68- return None , "'{}' is not a valid IP range" .format (ip_range )
46+ def parse_mac (self , args ):
47+ MAC_REGEX = re .compile (r"^([0-9A-Fa-f]{2}:){5}([0-9A-Fa-f]{2})$" )
48+ mac_addr = args .get ("mac" )
6949
70- return ip_range , None
50+ if mac_addr is None :
51+ return None
7152
53+ if not MAC_REGEX .match (mac_addr ) or MAC_REGEX .match (mac_addr ).group (0 ) != mac_addr :
54+ log_and_raise_error (E_PARSER , "'{}' is not a valid MAC" .format (mac_addr ))
7255
73- def parse_direction (args ):
74- direction = args .get ("direction" )
56+ return mac_addr
7557
76- if direction is None :
77- return (None , None ), "direction parameter is missing"
58+ def parse_iprange (self , args ):
59+ IPRANGE_REGEX = re .compile (
60+ r"^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}"
61+ r"(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(/\d{1,2})?$"
62+ )
63+ ip_range = args .get ("iprange" )
7864
79- dir = direction .lower ().split ("/" )
80- has_to = "to" in dir
81- has_from = "from" in dir
65+ if ip_range is None :
66+ log_and_raise_error (E_PARSER , "ip range parameter is missing" )
8267
83- if not ( has_to or has_from ):
84- return ( None , None ), "'{}' is not a valid direction " .format (direction )
68+ if not IPRANGE_REGEX . match ( ip_range ):
69+ log_and_raise_error ( E_PARSER , "'{}' is not a valid IP range " .format (ip_range ) )
8570
86- return ( has_to , has_from ), None
71+ return ip_range
8772
73+ def parse_direction (self , args ):
74+ direction = args .get ("direction" )
8875
89- def parse_protocol ( args ) :
90- protocol = args . get ( "protocol " )
76+ if direction is None :
77+ log_and_raise_error ( E_PARSER , "direction parameter is missing " )
9178
92- if protocol is None :
93- return None , "protocol parameter is missing"
79+ dir = direction .lower ().split ("/" )
80+ has_to = "to" in dir
81+ has_from = "from" in dir
9482
95- protocol = protocol .lower ()
83+ if not (has_to or has_from ):
84+ log_and_raise_error (E_PARSER , "'{}' is not a valid direction" .format (direction ))
9685
97- if protocol not in VALID_PROTOCOLS :
98- return None , "'{}' is not a supported protocol" .format (protocol )
86+ return (has_to , has_from )
9987
100- return protocol , None
88+ def parse_protocol (self , args ):
89+ protocol = args .get ("protocol" )
10190
91+ if protocol is None :
92+ log_and_raise_error (E_PARSER , "protocol parameter is missing" )
10293
103- def parse_port (args ):
104- port = args .get ("port" )
105- if port is None :
106- return None , None # Port is optional
94+ protocol = protocol .lower ()
10795
108- try :
109- p = int (port )
110- if not (0 <= p <= 65535 ):
111- raise ValueError
112- return port , None
113- except ValueError :
114- return None , "'{}' is not a valid port" .format (port )
96+ if protocol not in VALID_PROTOCOLS :
97+ log_and_raise_error (E_PARSER , "'{}' is not a supported protocol" .format (protocol ))
11598
99+ return protocol
116100
117- def parse_allow ( args ):
118- allow = args .get ("allow " )
119- if allow is None :
120- return None , "allow parameter is missing"
101+ def parse_port ( self , args ):
102+ port = args .get ("port " )
103+ if port is None :
104+ return None
121105
122- if allow .lower () not in ["true" , "false" ]:
123- return None , "allow parameter should be true or false, not '{}'" .format (allow )
106+ try :
107+ p = int (port )
108+ if not (0 <= p <= 65535 ):
109+ raise ValueError
110+ return port
111+ except ValueError :
112+ log_and_raise_error (E_PARSER , "'{}' is not a valid port" .format (port ))
124113
125- if allow .lower () == "true" :
126- return True , None
114+ def parse_allow (self , args ):
115+ allow = args .get ("allow" )
116+ if allow is None :
117+ log_and_raise_error (E_PARSER , "allow parameter is missing" )
127118
128- return False , None
119+ if allow .lower () not in ["true" , "false" ]:
120+ log_and_raise_error (E_PARSER , "allow parameter should be true or false, not '{}'" .format (allow ))
129121
130- def parse_priority (args ):
131- priority = args .get ("priority" )
132- if priority is None :
133- return None , None # Priority is optional
122+ if allow .lower () == "true" :
123+ return True
134124
135- try :
136- p = int (priority )
137- if not (0 <= p <= 65535 ):
138- raise ValueError
139- return priority , None
140- except ValueError :
141- return None , "'{}' is not a valid priority" .format (priority )
125+ return False
142126
127+ def parse_priority (self , args ):
128+ priority = args .get ("priority" )
129+ if priority is None :
130+ return None
143131
144- class Parser :
145- def __init__ (self , args ):
146- self .args = args
147- self .values = {}
148- self .errors = []
132+ try :
133+ p = int (priority )
134+ if not (0 <= p <= 65535 ):
135+ raise ValueError
136+ return priority
137+ except ValueError :
138+ log_and_raise_error (E_PARSER , "'{}' is not a valid priority" .format (priority ))
149139
150140 def read (self , key , parse_fn , dests = None ):
151141 # parse_fn can return a single value or a tuple of values.
152142 # In this case we are expecting dests to match the expected
153143 # returned tuple
154- val , err = parse_fn (self .args )
155- if err :
156- self .errors .append (err )
157- return self
144+ val = parse_fn (self .args )
158145
159146 if dests is not None :
160147 if not isinstance (val , tuple ):
161- self .errors .append (
162- "Internal error: parse {}: doesn't return a tuple while dests is set" .format (
163- key
164- )
148+ log_and_raise_error (
149+ E_PARSER ,
150+ "Internal error: parse {}: doesn't return a tuple while dests is set" .format (key )
165151 )
166- return self
167152
168153 if len (dests ) != len (val ):
169- self .errors .append (
170- "Internal error: parse {}: dests is {} while {} was expected" .format (
171- key , len (dests ), len (val )
172- )
154+ log_and_raise_error (
155+ E_PARSER ,
156+ "Internal error: parse {}: dests is {} while {} was expected" .format (key , len (dests ), len (val ))
173157 )
174- return self
175158
176159 for d , v in zip (dests , val ):
177160 self .values [d ] = v
@@ -231,17 +214,18 @@ def build_rules_string(args):
231214def add_rule (_session , args ):
232215 _LOGGER .info ("Calling add rule with args {}" .format (args ))
233216
234- parser = (
235- Parser (args )
236- .read ("bridge" , parse_bridge )
237- .read ("mac" , parse_mac )
238- .read ("direction" , parse_direction , dests = ["has_to" , "has_from" ])
239- .read ("protocol" , parse_protocol )
240- .read ("iprange" , parse_iprange )
241- .read ("port" , parse_port )
242- .read ("allow" , parse_allow )
243- .read ("priority" , parse_priority )
244- )
217+ try :
218+ parser = Parser (args )
219+ parser .read ("bridge" , parser .parse_bridge )
220+ parser .read ("mac" , parser .parse_mac )
221+ parser .read ("direction" , parser .parse_direction , dests = ["has_to" , "has_from" ])
222+ parser .read ("protocol" , parser .parse_protocol )
223+ parser .read ("iprange" , parser .parse_iprange )
224+ parser .read ("port" , parser .parse_port )
225+ parser .read ("allow" , parser .parse_allow )
226+ parser .read ("priority" , parser .parse_priority )
227+ except XenAPIPlugin .Failure as e :
228+ log_and_raise_error (E_PARSER , "add_rule: Failed to get parameters: {}" .format (e .params [1 ]))
245229
246230 if parser .errors :
247231 log_and_raise_error (E_PARSER , "add_rule: Failed to get parameters: {}" .format (parser .errors ))
@@ -274,15 +258,16 @@ def add_rule(_session, args):
274258def del_rule (_session , args ):
275259 _LOGGER .info ("Calling delete rule with args {}" .format (args ))
276260
277- parser = (
278- Parser (args )
279- .read ("bridge" , parse_bridge )
280- .read ("mac" , parse_mac )
281- .read ("destination" , parse_direction , dests = ["has_to" , "has_from" ])
282- .read ("protocol" , parse_protocol )
283- .read ("iprange" , parse_iprange )
284- .read ("port" , parse_port )
285- )
261+ try :
262+ parser = Parser (args )
263+ parser .read ("bridge" , parser .parse_bridge )
264+ parser .read ("mac" , parser .parse_mac )
265+ parser .read ("destination" , parser .parse_direction , dests = ["has_to" , "has_from" ])
266+ parser .read ("protocol" , parser .parse_protocol )
267+ parser .read ("iprange" , parser .parse_iprange )
268+ parser .read ("port" , parser .parse_port )
269+ except XenAPIPlugin .Failure as e :
270+ log_and_raise_error (E_PARSER , "del_rule: Failed to get parameters: {}" .format (e .params [1 ]))
286271
287272 if parser .errors :
288273 log_and_raise_error (E_PARSER , "del_rule: Failed to get parameters: {}" .format (parser .errors ))
@@ -311,10 +296,11 @@ def del_rule(_session, args):
311296def dump_flows (_session , args ):
312297 _LOGGER .info ("Calling dump flows with args {}" .format (args ))
313298
314- bridge , err = parse_bridge (args )
315-
316- if err :
317- log_and_raise_error (E_PARSER , "dump flows: {}" .format (err ))
299+ parser = Parser (args )
300+ try :
301+ bridge = parser .parse_bridge (args )
302+ except XenAPIPlugin .Failure as e :
303+ log_and_raise_error (E_PARSER , "dump_flows: Failed to get parameters: {}" .format (e .params [1 ]))
318304
319305 ofctl_cmd = [OVS_OFCTL_CMD , "-O" , OPENFLOW_PROTOCOL , "dump-flows" , bridge ]
320306 cmd = run_command (ofctl_cmd , check = False )
0 commit comments