1818import sys
1919from time import time
2020
21+ from nav .metrics .names import escape_metric_name
22+
23+
2124DEFAULT_PREFIX = "nav.dhcp"
2225DEFAULT_CONFIG_FILE = "/etc/dhcpd/dhcpd.conf"
2326DEFAULT_CMD_PATH = pathlib .Path ("/usr/bin/dhcpd-pools" )
2427DEFAULT_PORT = "2004"
25- DEFAULT_PROTOCOL = ' text' # MB doesn't trust pickle so we go with text
28+ DEFAULT_PROTOCOL = " text" # MB doesn't trust pickle so we go with text
2629
2730# graphite likes pickle protocol 2. Python 3: 3, Python 3.8+: 4
2831PICKLE_PROTOCOL = range (0 , pickle .HIGHEST_PROTOCOL + 1 )
3336 "touched" : "touch" ,
3437 "free" : "free" ,
3538}
39+ VERSION = "0.2"
3640
3741
3842Metric = namedtuple ("Metric" , ["path" , "value" , "timestamp" ])
@@ -77,11 +81,27 @@ def parse_args():
7781 "--location" ,
7882 help = (
7983 "Location, if any, to append to the metric prefix to build the path."
80- ' If the vlan is named "vlan1" and the location is "building1.cellar"'
84+ ' If the location is named "vlan1" and the location is "building1.cellar"'
8185 " the resulting metric path would be PREFIX.building1.cellar.vlan1"
8286 ),
8387 type = str ,
8488 )
89+ parser .add_argument (
90+ "--extract-vlan" ,
91+ help = (
92+ "Try to extract the name of a vlan from the location."
93+ ' If the vlan is named "vlan1_baluba" '
94+ " the resulting metric path would be PREFIX.vlan1"
95+ ),
96+ action = "store_true" ,
97+ default = False ,
98+ )
99+ parser .add_argument (
100+ "--version" ,
101+ help = "Show version of script and exit" ,
102+ action = "store_true" ,
103+ default = False ,
104+ )
85105 protocol_choices = ("text" ,) + tuple (str (p ) for p in PICKLE_PROTOCOL )
86106 parser .add_argument (
87107 "-P" ,
@@ -115,6 +135,16 @@ def parse_args():
115135 return args
116136
117137
138+ def get_config_from_args (args ):
139+ config = None
140+ if getattr (args , "extract_vlan" , False ):
141+ class Config :
142+ pass
143+ config = Config ()
144+ config .extract_vlan = True
145+ return config
146+
147+
118148# run command and store json output
119149def exec_dhcpd_pools (config_file , cmd_path = DEFAULT_CMD_PATH ):
120150 flags = f"-c { config_file } { FLAGS } " .split ()
@@ -126,24 +156,24 @@ def exec_dhcpd_pools(config_file, cmd_path=DEFAULT_CMD_PATH):
126156
127157
128158# reformat the data
129- def render (jsonblob , prefix , protocol = DEFAULT_PROTOCOL ):
159+ def render (jsonblob , prefix , protocol = DEFAULT_PROTOCOL , config = None ):
130160 if isinstance (protocol , int ):
131- return _render_pickle (jsonblob , prefix , protocol )
132- return _render_text (jsonblob , prefix )
161+ return _render_pickle (jsonblob , prefix , protocol , config )
162+ return _render_text (jsonblob , prefix , config )
133163
134164
135- def _render_text (jsonblob , prefix ):
165+ def _render_text (jsonblob , prefix , config = None ):
136166 template = "{metric.path} {metric.value} {metric.timestamp}\n "
137- input = _tuplify (jsonblob , prefix )
167+ input = _tuplify (jsonblob , prefix , config )
138168 output = []
139169 for metric in input :
140170 line = template .format (metric = metric )
141171 output .append (line )
142172 return "" .join (output ).encode ("ascii" )
143173
144174
145- def _render_pickle (jsonblob , prefix , protocol ):
146- input = _tuplify (jsonblob , prefix )
175+ def _render_pickle (jsonblob , prefix , protocol , config = None ):
176+ input = _tuplify (jsonblob , prefix , config )
147177 output = []
148178 for metric in input :
149179 output .append ((metric .path , (metric .timestamp , metric .value )))
@@ -153,12 +183,14 @@ def _render_pickle(jsonblob, prefix, protocol):
153183 return message
154184
155185
156- def _tuplify (jsonblob , prefix ):
186+ def _tuplify (jsonblob , prefix , config = None ):
157187 timestamp = trunc (time ())
158188 data = jsonblob ["shared-networks" ]
159189 output = list ()
160190 for vlan_stat in data :
161- vlan = _clean_vlan (vlan_stat ["location" ])
191+ vlan = escape_metric_name (vlan_stat ["location" ])
192+ if config :
193+ vlan = _extract_vlan (vlan )
162194 if not vlan :
163195 continue
164196 for key , metric in METRIC_MAPPER .items ():
@@ -168,7 +200,7 @@ def _tuplify(jsonblob, prefix):
168200 return output
169201
170202
171- def _clean_vlan (location ):
203+ def _extract_vlan (location ):
172204 regex = re .search ("vlan\d+" , location )
173205 if regex :
174206 return regex .group ()
@@ -193,13 +225,17 @@ def send_to_graphite(metrics_blob, server, port):
193225
194226def main ():
195227 args = parse_args ()
228+ if args .version :
229+ print (f"version: { VERSION } " )
230+ sys .exit (0 )
231+ config = get_config_from_args (args )
196232 jsonblob = exec_dhcpd_pools (args .config_file , args .command )
197- output = render (jsonblob , args .actual_prefix , args .protocol )
233+ output = render (jsonblob , args .actual_prefix , args .protocol , config )
198234 if args .noop :
199235 if args .protocol == "text" :
200- print (output .decode (' ascii' ))
236+ print (output .decode (" ascii" ))
201237 else :
202- print (hexlify (output ).decode (' ascii' ))
238+ print (hexlify (output ).decode (" ascii" ))
203239 else :
204240 send_to_graphite (output , args .server , args .port )
205241
0 commit comments