Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
O
OpnSense
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Kulya
OpnSense
Commits
8e107684
Commit
8e107684
authored
Apr 06, 2015
by
Ad Schellevis
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
style fixes configd
parent
cba10171
Changes
6
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
104 additions
and
108 deletions
+104
-108
__init__.py
src/opnsense/service/modules/addons/__init__.py
+1
-0
template_helpers.py
src/opnsense/service/modules/addons/template_helpers.py
+7
-5
config.py
src/opnsense/service/modules/config.py
+7
-9
ph_inline_actions.py
src/opnsense/service/modules/ph_inline_actions.py
+3
-3
processhandler.py
src/opnsense/service/modules/processhandler.py
+43
-43
template.py
src/opnsense/service/modules/template.py
+43
-48
No files found.
src/opnsense/service/modules/addons/__init__.py
View file @
8e107684
...
@@ -29,3 +29,4 @@
...
@@ -29,3 +29,4 @@
--------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------
package : configd
package : configd
"""
"""
src/opnsense/service/modules/addons/template_helpers.py
View file @
8e107684
...
@@ -30,8 +30,9 @@
...
@@ -30,8 +30,9 @@
package : configd
package : configd
"""
"""
class
Helpers
(
object
):
class
Helpers
(
object
):
def
__init__
(
self
,
template_in_data
):
def
__init__
(
self
,
template_in_data
):
""" initialize template helpers
""" initialize template helpers
:param template_in_data:
:param template_in_data:
...
@@ -39,22 +40,22 @@ class Helpers(object):
...
@@ -39,22 +40,22 @@ class Helpers(object):
"""
"""
self
.
_template_in_data
=
template_in_data
self
.
_template_in_data
=
template_in_data
def
getNodeByTag
(
self
,
tag
):
def
getNodeByTag
(
self
,
tag
):
""" get tree node by tag
""" get tree node by tag
:param tag: tag in dot notation (section.item)
:param tag: tag in dot notation (section.item)
:return: dict or None if not found
:return: dict or None if not found
"""
"""
node
=
self
.
_template_in_data
node
=
self
.
_template_in_data
for
item
in
tag
.
split
(
'.'
):
for
item
in
tag
.
split
(
'.'
):
if
node
.
has_key
(
item
)
:
if
item
in
node
:
node
=
node
[
item
]
node
=
node
[
item
]
else
:
else
:
# not found
# not found
return
None
return
None
# path found, return
# path found, return
return
node
return
node
def
exists
(
self
,
tag
):
def
exists
(
self
,
tag
):
"""
"""
check if node exists in dictionary structure
check if node exists in dictionary structure
:param tag: tag in dot notation (section.item)
:param tag: tag in dot notation (section.item)
...
@@ -64,3 +65,4 @@ class Helpers(object):
...
@@ -64,3 +65,4 @@ class Helpers(object):
return
True
return
True
else
:
else
:
return
False
return
False
src/opnsense/service/modules/config.py
View file @
8e107684
...
@@ -43,7 +43,7 @@ import xml.etree.cElementTree as ElementTree
...
@@ -43,7 +43,7 @@ import xml.etree.cElementTree as ElementTree
class
Config
(
object
):
class
Config
(
object
):
def
__init__
(
self
,
filename
):
def
__init__
(
self
,
filename
):
self
.
_filename
=
filename
self
.
_filename
=
filename
self
.
_config_data
=
{}
self
.
_config_data
=
{}
self
.
_file_mod
=
0
self
.
_file_mod
=
0
...
@@ -62,25 +62,25 @@ class Config(object):
...
@@ -62,25 +62,25 @@ class Config(object):
self
.
_config_data
=
self
.
_traverse
(
root
)
self
.
_config_data
=
self
.
_traverse
(
root
)
self
.
_file_mod
=
mod_time
self
.
_file_mod
=
mod_time
def
_traverse
(
self
,
xmlNode
):
def
_traverse
(
self
,
xmlNode
):
""" traverse xml node and return ordered dictionary structure
""" traverse xml node and return ordered dictionary structure
:param xmlNode: ElementTree node
:param xmlNode: ElementTree node
:return: collections.OrderedDict
:return: collections.OrderedDict
"""
"""
this_item
=
collections
.
OrderedDict
()
this_item
=
collections
.
OrderedDict
()
if
len
(
list
(
xmlNode
))
>
0
:
if
len
(
list
(
xmlNode
))
>
0
:
for
item
in
list
(
xmlNode
):
for
item
in
list
(
xmlNode
):
item_content
=
self
.
_traverse
(
item
)
item_content
=
self
.
_traverse
(
item
)
if
this_item
.
has_key
(
item
.
tag
)
:
if
item
.
tag
in
this_item
:
if
type
(
this_item
[
item
.
tag
])
!=
list
:
if
type
(
this_item
[
item
.
tag
])
!=
list
:
tmp_item
=
copy
.
deepcopy
(
this_item
[
item
.
tag
])
tmp_item
=
copy
.
deepcopy
(
this_item
[
item
.
tag
])
this_item
[
item
.
tag
]
=
[]
this_item
[
item
.
tag
]
=
[]
this_item
[
item
.
tag
]
.
append
(
tmp_item
)
this_item
[
item
.
tag
]
.
append
(
tmp_item
)
if
item_content
!=
None
:
if
item_content
is
not
None
:
# skip empty fields
# skip empty fields
this_item
[
item
.
tag
]
.
append
(
item_content
)
this_item
[
item
.
tag
]
.
append
(
item_content
)
elif
item_content
!=
None
:
elif
item_content
is
not
None
:
# create a new named item
# create a new named item
this_item
[
item
.
tag
]
=
self
.
_traverse
(
item
)
this_item
[
item
.
tag
]
=
self
.
_traverse
(
item
)
else
:
else
:
...
@@ -89,8 +89,7 @@ class Config(object):
...
@@ -89,8 +89,7 @@ class Config(object):
return
this_item
return
this_item
def
indent
(
self
,
elem
,
level
=
0
):
def
indent
(
self
,
elem
,
level
=
0
):
""" indent cElementTree (prettyprint fix)
""" indent cElementTree (prettyprint fix)
used from : http://infix.se/2007/02/06/gentlemen-indent-your-xml
used from : http://infix.se/2007/02/06/gentlemen-indent-your-xml
@param elem: cElementTree
@param elem: cElementTree
...
@@ -110,7 +109,6 @@ class Config(object):
...
@@ -110,7 +109,6 @@ class Config(object):
if
level
and
(
not
elem
.
tail
or
not
elem
.
tail
.
strip
()):
if
level
and
(
not
elem
.
tail
or
not
elem
.
tail
.
strip
()):
elem
.
tail
=
i
elem
.
tail
=
i
def
get
(
self
):
def
get
(
self
):
""" get active config data, load from disc if file in memory is different
""" get active config data, load from disc if file in memory is different
...
...
src/opnsense/service/modules/ph_inline_actions.py
View file @
8e107684
...
@@ -37,7 +37,7 @@ __author__ = 'Ad Schellevis'
...
@@ -37,7 +37,7 @@ __author__ = 'Ad Schellevis'
import
syslog
import
syslog
def
execute
(
action
,
parameters
):
def
execute
(
action
,
parameters
):
""" wrapper for inline functions
""" wrapper for inline functions
:param action: action object ( processhandler.Action type )
:param action: action object ( processhandler.Action type )
...
@@ -54,7 +54,7 @@ def execute(action,parameters):
...
@@ -54,7 +54,7 @@ def execute(action,parameters):
# send generated filenames to syslog
# send generated filenames to syslog
for
filename
in
filenames
:
for
filename
in
filenames
:
syslog
.
syslog
(
syslog
.
LOG_DEBUG
,
'
%
s generated
%
s'
%
(
parameters
,
filename
)
)
syslog
.
syslog
(
syslog
.
LOG_DEBUG
,
'
%
s generated
%
s'
%
(
parameters
,
filename
)
)
del
conf
del
conf
del
tmpl
del
tmpl
...
...
src/opnsense/service/modules/processhandler.py
View file @
8e107684
...
@@ -47,6 +47,7 @@ import uuid
...
@@ -47,6 +47,7 @@ import uuid
import
shlex
import
shlex
import
ph_inline_actions
import
ph_inline_actions
class
Handler
(
object
):
class
Handler
(
object
):
""" Main handler class, opens unix domain socket and starts listening
""" Main handler class, opens unix domain socket and starts listening
- New connections are handed over to a HandlerClient type object in a new thread
- New connections are handed over to a HandlerClient type object in a new thread
...
@@ -58,12 +59,12 @@ class Handler(object):
...
@@ -58,12 +59,12 @@ class Handler(object):
-> execute ActionHandler command using Action objects
-> execute ActionHandler command using Action objects
<- send back result string
<- send back result string
"""
"""
def
__init__
(
self
,
socket_filename
,
config_path
,
simulation_mode
=
False
):
def
__init__
(
self
,
socket_filename
,
config_path
,
simulation_mode
=
False
):
""" Constructor
""" Constructor
:param socket_filename: filename of unix domain socket to use
:param socket_filename: filename of unix domain socket to use
:param config_path: location of configuration files
:param config_path: location of configuration files
:param
emulat
e: emulation mode, do not start actual (script) commands
:param
simulation_mod
e: emulation mode, do not start actual (script) commands
:return: object
:return: object
"""
"""
self
.
socket_filename
=
socket_filename
self
.
socket_filename
=
socket_filename
...
@@ -90,7 +91,7 @@ class Handler(object):
...
@@ -90,7 +91,7 @@ class Handler(object):
sock
=
socket
.
socket
(
socket
.
AF_UNIX
,
socket
.
SOCK_STREAM
)
sock
=
socket
.
socket
(
socket
.
AF_UNIX
,
socket
.
SOCK_STREAM
)
sock
.
bind
(
self
.
socket_filename
)
sock
.
bind
(
self
.
socket_filename
)
os
.
chmod
(
self
.
socket_filename
,
0o666
)
os
.
chmod
(
self
.
socket_filename
,
0o666
)
sock
.
listen
(
30
)
sock
.
listen
(
30
)
while
True
:
while
True
:
# wait for a connection to arrive
# wait for a connection to arrive
...
@@ -100,7 +101,7 @@ class Handler(object):
...
@@ -100,7 +101,7 @@ class Handler(object):
client_address
=
client_address
,
client_address
=
client_address
,
action_handler
=
actHandler
,
action_handler
=
actHandler
,
simulation_mode
=
self
.
simulation_mode
)
simulation_mode
=
self
.
simulation_mode
)
if
self
.
single_threaded
:
if
self
.
single_threaded
:
# run single threaded
# run single threaded
cmd_thread
.
run
()
cmd_thread
.
run
()
else
:
else
:
...
@@ -116,20 +117,20 @@ class Handler(object):
...
@@ -116,20 +117,20 @@ class Handler(object):
except
:
except
:
# something went wrong... send traceback to syslog, restart listener (wait for a short time)
# something went wrong... send traceback to syslog, restart listener (wait for a short time)
print
(
traceback
.
format_exc
())
print
(
traceback
.
format_exc
())
syslog
.
syslog
(
syslog
.
LOG_ERR
,
'Handler died on
%
s'
%
traceback
.
format_exc
())
syslog
.
syslog
(
syslog
.
LOG_ERR
,
'Handler died on
%
s'
%
traceback
.
format_exc
())
time
.
sleep
(
1
)
time
.
sleep
(
1
)
class
HandlerClient
(
threading
.
Thread
):
class
HandlerClient
(
threading
.
Thread
):
""" Handle commands via specified socket connection
""" Handle commands via specified socket connection
"""
"""
def
__init__
(
self
,
connection
,
client_address
,
action_handler
,
simulation_mode
=
False
):
def
__init__
(
self
,
connection
,
client_address
,
action_handler
,
simulation_mode
=
False
):
"""
"""
:param connection: socket connection object
:param connection: socket connection object
:param client_address: client address ( from socket accept )
:param client_address: client address ( from socket accept )
:param action_handler: action handler object
:param action_handler: action handler object
:param
emulat
e: Emulation mode, do not start actual (script) commands
:param
simulation_mod
e: Emulation mode, do not start actual (script) commands
:return: None
:return: None
"""
"""
threading
.
Thread
.
__init__
(
self
)
threading
.
Thread
.
__init__
(
self
)
...
@@ -180,10 +181,10 @@ class HandlerClient(threading.Thread):
...
@@ -180,10 +181,10 @@ class HandlerClient(threading.Thread):
# execute requested action
# execute requested action
if
self
.
simulation_mode
:
if
self
.
simulation_mode
:
self
.
action_handler
.
showAction
(
exec_command
,
exec_action
,
exec_params
)
self
.
action_handler
.
showAction
(
exec_command
,
exec_action
,
exec_params
)
result
=
'OK'
result
=
'OK'
else
:
else
:
result
=
self
.
action_handler
.
execute
(
exec_command
,
exec_action
,
exec_params
)
result
=
self
.
action_handler
.
execute
(
exec_command
,
exec_action
,
exec_params
)
if
not
exec_in_background
:
if
not
exec_in_background
:
# send response back to client( including trailing enter )
# send response back to client( including trailing enter )
...
@@ -197,7 +198,7 @@ class HandlerClient(threading.Thread):
...
@@ -197,7 +198,7 @@ class HandlerClient(threading.Thread):
# send end of stream characters
# send end of stream characters
if
not
exec_in_background
:
if
not
exec_in_background
:
self
.
connection
.
sendall
(
"
%
c
%
c
%
c"
%
(
chr
(
0
),
chr
(
0
),
chr
(
0
)))
self
.
connection
.
sendall
(
"
%
c
%
c
%
c"
%
(
chr
(
0
),
chr
(
0
),
chr
(
0
)))
except
SystemExit
:
except
SystemExit
:
# ignore system exit related errors
# ignore system exit related errors
pass
pass
...
@@ -214,10 +215,11 @@ class HandlerClient(threading.Thread):
...
@@ -214,10 +215,11 @@ class HandlerClient(threading.Thread):
if
not
exec_in_background
:
if
not
exec_in_background
:
self
.
connection
.
close
()
self
.
connection
.
close
()
class
ActionHandler
(
object
):
class
ActionHandler
(
object
):
""" Start/stop services and functions using configuration data defined in conf/actions_<topic>.conf
""" Start/stop services and functions using configuration data defined in conf/actions_<topic>.conf
"""
"""
def
__init__
(
self
,
config_path
):
def
__init__
(
self
,
config_path
):
""" Initialize action handler to start system functions
""" Initialize action handler to start system functions
:param config_path: full path of configuration data
:param config_path: full path of configuration data
...
@@ -234,11 +236,12 @@ class ActionHandler(object):
...
@@ -234,11 +236,12 @@ class ActionHandler(object):
"""
"""
self
.
action_map
=
{}
self
.
action_map
=
{}
for
config_filename
in
glob
.
glob
(
'
%
s/actions_*.conf'
%
(
self
.
config_path
))
+
glob
.
glob
(
'
%
s/actions.d/actions_*.conf'
%
(
self
.
config_path
)):
for
config_filename
in
glob
.
glob
(
'
%
s/actions_*.conf'
%
self
.
config_path
)
\
+
glob
.
glob
(
'
%
s/actions.d/actions_*.conf'
%
self
.
config_path
):
# this topic's name (service, filter, template, etc)
# this topic's name (service, filter, template, etc)
# make sure there's an action map index for this topic
# make sure there's an action map index for this topic
topic_name
=
config_filename
.
split
(
'actions_'
)[
-
1
]
.
split
(
'.'
)[
0
]
topic_name
=
config_filename
.
split
(
'actions_'
)[
-
1
]
.
split
(
'.'
)[
0
]
if
self
.
action_map
.
has_key
(
topic_name
)
==
False
:
if
topic_name
not
in
self
.
action_map
:
self
.
action_map
[
topic_name
]
=
{}
self
.
action_map
[
topic_name
]
=
{}
# traverse config directory and open all filenames starting with actions_
# traverse config directory and open all filenames starting with actions_
...
@@ -248,12 +251,12 @@ class ActionHandler(object):
...
@@ -248,12 +251,12 @@ class ActionHandler(object):
# map configuration data on object
# map configuration data on object
action_obj
=
Action
()
action_obj
=
Action
()
for
act_prop
in
cnf
.
items
(
section
):
for
act_prop
in
cnf
.
items
(
section
):
setattr
(
action_obj
,
act_prop
[
0
],
act_prop
[
1
])
setattr
(
action_obj
,
act_prop
[
0
],
act_prop
[
1
])
if
section
.
find
(
'.'
)
>
-
1
:
if
section
.
find
(
'.'
)
>
-
1
:
# at this moment we only support 2 levels of actions ( 3 if you count topic as well )
# at this moment we only support 2 levels of actions ( 3 if you count topic as well )
for
alias
in
section
.
split
(
'.'
)[
0
]
.
split
(
'|'
):
for
alias
in
section
.
split
(
'.'
)[
0
]
.
split
(
'|'
):
if
self
.
action_map
[
topic_name
]
.
has_key
(
alias
)
==
False
:
if
alias
not
in
self
.
action_map
[
topic_name
]
:
self
.
action_map
[
topic_name
][
alias
]
=
{}
self
.
action_map
[
topic_name
][
alias
]
=
{}
self
.
action_map
[
topic_name
][
alias
][
section
.
split
(
'.'
)[
1
]]
=
action_obj
self
.
action_map
[
topic_name
][
alias
][
section
.
split
(
'.'
)[
1
]]
=
action_obj
else
:
else
:
...
@@ -269,20 +272,20 @@ class ActionHandler(object):
...
@@ -269,20 +272,20 @@ class ActionHandler(object):
:return: action object or None if not found
:return: action object or None if not found
"""
"""
action_obj
=
None
action_obj
=
None
if
self
.
action_map
.
has_key
(
command
)
:
if
command
in
self
.
action_map
:
if
self
.
action_map
[
command
]
.
has_key
(
action
)
:
if
action
in
self
.
action_map
[
command
]
:
if
type
(
self
.
action_map
[
command
][
action
])
==
dict
:
if
type
(
self
.
action_map
[
command
][
action
])
==
dict
:
if
len
(
parameters
)
>
0
and
self
.
action_map
[
command
][
action
]
.
has_key
(
parameters
[
0
])
==
True
:
if
len
(
parameters
)
>
0
and
parameters
[
0
]
in
self
.
action_map
[
command
][
action
]
:
# 3 level action ( "interface linkup start" for example )
# 3 level action ( "interface linkup start" for example )
if
isinstance
(
self
.
action_map
[
command
][
action
][
parameters
[
0
]],
Action
):
if
isinstance
(
self
.
action_map
[
command
][
action
][
parameters
[
0
]],
Action
):
action_obj
=
self
.
action_map
[
command
][
action
][
parameters
[
0
]]
action_obj
=
self
.
action_map
[
command
][
action
][
parameters
[
0
]]
action_obj
.
setParameterStartPos
(
1
)
action_obj
.
setParameterStartPos
(
1
)
elif
isinstance
(
self
.
action_map
[
command
][
action
],
Action
):
elif
isinstance
(
self
.
action_map
[
command
][
action
],
Action
):
action_obj
=
self
.
action_map
[
command
][
action
]
action_obj
=
self
.
action_map
[
command
][
action
]
return
action_obj
return
action_obj
def
execute
(
self
,
command
,
action
,
parameters
):
def
execute
(
self
,
command
,
action
,
parameters
):
""" execute configuration defined action
""" execute configuration defined action
:param command: command/topic for example interface
:param command: command/topic for example interface
...
@@ -291,27 +294,27 @@ class ActionHandler(object):
...
@@ -291,27 +294,27 @@ class ActionHandler(object):
:return: OK on success, else error code
:return: OK on success, else error code
"""
"""
action_params
=
[]
action_params
=
[]
action_obj
=
self
.
findAction
(
command
,
action
,
parameters
)
action_obj
=
self
.
findAction
(
command
,
action
,
parameters
)
if
action_obj
is
not
None
:
if
action_obj
is
not
None
:
if
parameters
is
not
None
and
len
(
parameters
)
>
action_obj
.
getParameterStartPos
():
if
parameters
is
not
None
and
len
(
parameters
)
>
action_obj
.
getParameterStartPos
():
action_params
=
parameters
[
action_obj
.
getParameterStartPos
():]
action_params
=
parameters
[
action_obj
.
getParameterStartPos
():]
return
'
%
s
\n
'
%
action_obj
.
execute
(
action_params
)
return
'
%
s
\n
'
%
action_obj
.
execute
(
action_params
)
return
'Action not found
\n
'
return
'Action not found
\n
'
def
showAction
(
self
,
command
,
action
,
parameters
):
def
showAction
(
self
,
command
,
action
,
parameters
):
""" debug/simulation mode: show action information
""" debug/simulation mode: show action information
:return:
:return:
"""
"""
action_obj
=
self
.
findAction
(
command
,
action
,
parameters
)
action_obj
=
self
.
findAction
(
command
,
action
,
parameters
)
print
(
'---------------------------------------------------------------------'
)
print
(
'---------------------------------------------------------------------'
)
print
(
'execute
%
s.
%
s with parameters :
%
s '
%
(
command
,
action
,
parameters
)
)
print
(
'execute
%
s.
%
s with parameters :
%
s '
%
(
command
,
action
,
parameters
)
)
print
(
'action object
%
s (
%
s)'
%
(
action_obj
,
action_obj
.
command
)
)
print
(
'action object
%
s (
%
s)'
%
(
action_obj
,
action_obj
.
command
)
)
print
(
'---------------------------------------------------------------------'
)
print
(
'---------------------------------------------------------------------'
)
class
Action
(
object
):
class
Action
(
object
):
""" Action class, handles actual (system) calls.
""" Action class, handles actual (system) calls.
set command, parameters (template) type and log message
set command, parameters (template) type and log message
...
@@ -327,7 +330,7 @@ class Action(object):
...
@@ -327,7 +330,7 @@ class Action(object):
self
.
message
=
None
self
.
message
=
None
self
.
_parameter_start_pos
=
0
self
.
_parameter_start_pos
=
0
def
setParameterStartPos
(
self
,
pos
):
def
setParameterStartPos
(
self
,
pos
):
"""
"""
:param pos: start position of parameter list
:param pos: start position of parameter list
...
@@ -341,7 +344,7 @@ class Action(object):
...
@@ -341,7 +344,7 @@ class Action(object):
"""
"""
return
self
.
_parameter_start_pos
return
self
.
_parameter_start_pos
def
execute
(
self
,
parameters
):
def
execute
(
self
,
parameters
):
""" execute an action
""" execute an action
:param parameters: list of parameters
:param parameters: list of parameters
...
@@ -350,15 +353,15 @@ class Action(object):
...
@@ -350,15 +353,15 @@ class Action(object):
# send-out syslog message
# send-out syslog message
if
self
.
message
is
not
None
:
if
self
.
message
is
not
None
:
if
self
.
message
.
count
(
'
%
s'
)
>
0
and
parameters
is
not
None
and
len
(
parameters
)
>
0
:
if
self
.
message
.
count
(
'
%
s'
)
>
0
and
parameters
is
not
None
and
len
(
parameters
)
>
0
:
syslog
.
syslog
(
syslog
.
LOG_NOTICE
,
self
.
message
%
tuple
(
parameters
[
0
:
self
.
message
.
count
(
'
%
s'
)])
)
syslog
.
syslog
(
syslog
.
LOG_NOTICE
,
self
.
message
%
tuple
(
parameters
[
0
:
self
.
message
.
count
(
'
%
s'
)])
)
else
:
else
:
syslog
.
syslog
(
syslog
.
LOG_NOTICE
,
self
.
message
)
syslog
.
syslog
(
syslog
.
LOG_NOTICE
,
self
.
message
)
# validate input
# validate input
if
self
.
type
is
None
:
if
self
.
type
is
None
:
# no action type, nothing to do here
# no action type, nothing to do here
return
'No action type'
return
'No action type'
elif
self
.
type
.
lower
()
in
(
'script'
,
'script_output'
):
elif
self
.
type
.
lower
()
in
(
'script'
,
'script_output'
):
# script type commands, basic script type only uses exit statuses, script_output sends back stdout data.
# script type commands, basic script type only uses exit statuses, script_output sends back stdout data.
if
self
.
command
is
None
:
if
self
.
command
is
None
:
# no command supplied, exit
# no command supplied, exit
...
@@ -367,11 +370,11 @@ class Action(object):
...
@@ -367,11 +370,11 @@ class Action(object):
# build script command to execute, shared for both types
# build script command to execute, shared for both types
script_command
=
self
.
command
script_command
=
self
.
command
if
self
.
parameters
is
not
None
and
type
(
self
.
parameters
)
==
str
:
if
self
.
parameters
is
not
None
and
type
(
self
.
parameters
)
==
str
:
script_command
=
'
%
s
%
s'
%
(
script_command
,
self
.
parameters
)
script_command
=
'
%
s
%
s'
%
(
script_command
,
self
.
parameters
)
if
script_command
.
find
(
'
%
s'
)
>
-
1
and
len
(
parameters
)
>
0
:
if
script_command
.
find
(
'
%
s'
)
>
-
1
and
len
(
parameters
)
>
0
:
# use command execution parameters in action parameter template
# use command execution parameters in action parameter template
# use quotes on parameters to prevent code injection
# use quotes on parameters to prevent code injection
script_command
=
script_command
%
tuple
(
map
(
lambda
x
:
'"'
+
x
.
replace
(
'"'
,
'
\\
"'
)
+
'"'
,
script_command
=
script_command
%
tuple
(
map
(
lambda
x
:
'"'
+
x
.
replace
(
'"'
,
'
\\
"'
)
+
'"'
,
parameters
[
0
:
script_command
.
count
(
'
%
s'
)]))
parameters
[
0
:
script_command
.
count
(
'
%
s'
)]))
if
self
.
type
.
lower
()
==
'script'
:
if
self
.
type
.
lower
()
==
'script'
:
...
@@ -382,16 +385,16 @@ class Action(object):
...
@@ -382,16 +385,16 @@ class Action(object):
if
exit_status
==
0
:
if
exit_status
==
0
:
return
'OK'
return
'OK'
else
:
else
:
return
'Error (
%
d)'
%
exit_status
return
'Error (
%
d)'
%
exit_status
except
:
except
:
syslog
.
syslog
(
syslog
.
LOG_ERR
,
'Script action failed at
%
s'
%
traceback
.
format_exc
())
syslog
.
syslog
(
syslog
.
LOG_ERR
,
'Script action failed at
%
s'
%
traceback
.
format_exc
())
return
'Execute error'
return
'Execute error'
elif
self
.
type
.
lower
()
==
'script_output'
:
elif
self
.
type
.
lower
()
==
'script_output'
:
try
:
try
:
script_output
=
subprocess
.
check_output
(
script_command
,
shell
=
True
)
script_output
=
subprocess
.
check_output
(
script_command
,
shell
=
True
)
return
script_output
return
script_output
except
:
except
:
syslog
.
syslog
(
syslog
.
LOG_ERR
,
'Script action failed at
%
s'
%
traceback
.
format_exc
())
syslog
.
syslog
(
syslog
.
LOG_ERR
,
'Script action failed at
%
s'
%
traceback
.
format_exc
())
return
'Execute error'
return
'Execute error'
# fallback should never get here
# fallback should never get here
...
@@ -405,13 +408,10 @@ class Action(object):
...
@@ -405,13 +408,10 @@ class Action(object):
else
:
else
:
inline_act_parameters
=
''
inline_act_parameters
=
''
return
ph_inline_actions
.
execute
(
self
,
inline_act_parameters
)
return
ph_inline_actions
.
execute
(
self
,
inline_act_parameters
)
except
:
except
:
syslog
.
syslog
(
syslog
.
LOG_ERR
,
'Inline action failed at
%
s'
%
traceback
.
format_exc
())
syslog
.
syslog
(
syslog
.
LOG_ERR
,
'Inline action failed at
%
s'
%
traceback
.
format_exc
())
return
'Execute error'
return
'Execute error'
return
'Unknown action type'
return
'Unknown action type'
src/opnsense/service/modules/template.py
View file @
8e107684
...
@@ -41,9 +41,10 @@ import copy
...
@@ -41,9 +41,10 @@ import copy
import
jinja2
import
jinja2
import
addons.template_helpers
import
addons.template_helpers
class
Template
(
object
):
class
Template
(
object
):
def
__init__
(
self
,
target_root_directory
=
"/"
):
def
__init__
(
self
,
target_root_directory
=
"/"
):
""" constructor
""" constructor
:return:
:return:
"""
"""
...
@@ -55,82 +56,80 @@ class Template(object):
...
@@ -55,82 +56,80 @@ class Template(object):
# setup jinja2 environment
# setup jinja2 environment
self
.
_template_dir
=
os
.
path
.
dirname
(
os
.
path
.
abspath
(
__file__
))
+
'/../templates/'
self
.
_template_dir
=
os
.
path
.
dirname
(
os
.
path
.
abspath
(
__file__
))
+
'/../templates/'
self
.
_j2_env
=
jinja2
.
Environment
(
loader
=
jinja2
.
FileSystemLoader
(
self
.
_template_dir
),
trim_blocks
=
True
)
self
.
_j2_env
=
jinja2
.
Environment
(
loader
=
jinja2
.
FileSystemLoader
(
self
.
_template_dir
),
trim_blocks
=
True
)
def
_readManifest
(
self
,
filename
):
def
_readManifest
(
self
,
filename
):
"""
"""
:param filename: manifest filename (path/+MANIFEST)
:param filename: manifest filename (path/+MANIFEST)
:return: dictionary containing manifest items
:return: dictionary containing manifest items
"""
"""
result
=
{}
result
=
{}
for
line
in
open
(
filename
,
'r'
)
.
read
()
.
split
(
'
\n
'
):
for
line
in
open
(
filename
,
'r'
)
.
read
()
.
split
(
'
\n
'
):
parts
=
line
.
split
(
':'
)
parts
=
line
.
split
(
':'
)
if
len
(
parts
)
>
1
:
if
len
(
parts
)
>
1
:
result
[
parts
[
0
]]
=
':'
.
join
(
parts
[
1
:])
result
[
parts
[
0
]]
=
':'
.
join
(
parts
[
1
:])
return
result
return
result
def
_readTargets
(
self
,
filename
):
def
_readTargets
(
self
,
filename
):
""" read raw target filename masks
""" read raw target filename masks
:param filename: targets filename (path/+TARGETS)
:param filename: targets filename (path/+TARGETS)
:return: dictionary containing +TARGETS filename sets
:return: dictionary containing +TARGETS filename sets
"""
"""
result
=
{}
result
=
{}
for
line
in
open
(
filename
,
'r'
)
.
read
()
.
split
(
'
\n
'
):
for
line
in
open
(
filename
,
'r'
)
.
read
()
.
split
(
'
\n
'
):
parts
=
line
.
split
(
':'
)
parts
=
line
.
split
(
':'
)
if
len
(
parts
)
>
1
and
parts
[
0
]
.
strip
()[
0
]
!=
'#'
:
if
len
(
parts
)
>
1
and
parts
[
0
]
.
strip
()[
0
]
!=
'#'
:
result
[
parts
[
0
]]
=
':'
.
join
(
parts
[
1
:])
.
strip
()
result
[
parts
[
0
]]
=
':'
.
join
(
parts
[
1
:])
.
strip
()
return
result
return
result
def
list_module
(
self
,
module_name
,
read_manifest
=
False
):
def
list_module
(
self
,
module_name
,
read_manifest
=
False
):
""" list single module content
""" list single module content
:param module_name: module name in dot notation ( company.module )
:param module_name: module name in dot notation ( company.module )
:param read_manifest: boolean, read manifest file if it exists
:param read_manifest: boolean, read manifest file if it exists
:return: dictionary with module data
:return: dictionary with module data
"""
"""
result
=
{}
result
=
{}
file_path
=
'
%
s/
%
s'
%
(
self
.
_template_dir
,
module_name
.
replace
(
'.'
,
'/'
))
file_path
=
'
%
s/
%
s'
%
(
self
.
_template_dir
,
module_name
.
replace
(
'.'
,
'/'
))
if
os
.
path
.
exists
(
'
%
s/+MANIFEST'
%
file_path
)
and
read_manifest
:
if
os
.
path
.
exists
(
'
%
s/+MANIFEST'
%
file_path
)
and
read_manifest
:
result
[
'+MANIFEST'
]
=
self
.
_readManifest
(
'
%
s/+MANIFEST'
%
file_path
)
result
[
'+MANIFEST'
]
=
self
.
_readManifest
(
'
%
s/+MANIFEST'
%
file_path
)
if
os
.
path
.
exists
(
'
%
s/+TARGETS'
%
file_path
)
:
if
os
.
path
.
exists
(
'
%
s/+TARGETS'
%
file_path
)
:
result
[
'+TARGETS'
]
=
self
.
_readTargets
(
'
%
s/+TARGETS'
%
file_path
)
result
[
'+TARGETS'
]
=
self
.
_readTargets
(
'
%
s/+TARGETS'
%
file_path
)
else
:
else
:
result
[
'+TARGETS'
]
=
{}
result
[
'+TARGETS'
]
=
{}
return
result
return
result
def
list_modules
(
self
,
read_manifest
=
False
):
def
list_modules
(
self
):
""" traverse template directory and list all modules
""" traverse template directory and list all modules
the template directory is structured like Manufacturer/Module/config_files
the template directory is structured like Manufacturer/Module/config_files
:param read_manifest: boolean, read manifest file if it exists
:return: list (dict) of registered modules
:return: list (dict) of registered modules
"""
"""
result
=
{}
result
=
{}
for
root
,
dirs
,
files
in
os
.
walk
(
self
.
_template_dir
):
for
root
,
dirs
,
files
in
os
.
walk
(
self
.
_template_dir
):
if
len
(
root
)
>
len
(
self
.
_template_dir
):
if
len
(
root
)
>
len
(
self
.
_template_dir
):
module_name
=
'.'
.
join
(
root
.
replace
(
self
.
_template_dir
,
''
)
.
split
(
'/'
)[:
2
])
module_name
=
'.'
.
join
(
root
.
replace
(
self
.
_template_dir
,
''
)
.
split
(
'/'
)[:
2
])
if
result
.
has_key
(
module_name
)
==
False
:
if
module_name
not
in
result
:
result
[
module_name
]
=
self
.
list_module
(
module_name
)
result
[
module_name
]
=
self
.
list_module
(
module_name
)
return
result
return
result
def
setConfig
(
self
,
config_data
):
def
setConfig
(
self
,
config_data
):
""" set config data
""" set config data
:param config_data: config data as dictionary/list structure
:param config_data: config data as dictionary/list structure
:return: None
:return: None
"""
"""
if
type
(
config_data
)
in
(
dict
,
collections
.
OrderedDict
):
if
type
(
config_data
)
in
(
dict
,
collections
.
OrderedDict
):
self
.
_config
=
config_data
self
.
_config
=
config_data
else
:
else
:
# no data given, reset
# no data given, reset
self
.
_config
=
{}
self
.
_config
=
{}
def
__findStringTags
(
self
,
instr
):
def
__findStringTags
(
self
,
instr
):
"""
"""
:param instr: string with optional tags [field.$$]
:param instr: string with optional tags [field.$$]
:return:
:return:
...
@@ -142,7 +141,7 @@ class Template(object):
...
@@ -142,7 +141,7 @@ class Template(object):
return
retval
return
retval
def
__findFilters
(
self
,
tags
):
def
__findFilters
(
self
,
tags
):
""" match tags to config and construct a dictionary which we can use to construct the output filenames
""" match tags to config and construct a dictionary which we can use to construct the output filenames
:param tags: list of tags [xmlnode.xmlnode.
%
.xmlnode,xmlnode]
:param tags: list of tags [xmlnode.xmlnode.
%
.xmlnode,xmlnode]
:return: dictionary containing key (tagname) value {existing node key, value}
:return: dictionary containing key (tagname) value {existing node key, value}
...
@@ -155,25 +154,25 @@ class Template(object):
...
@@ -155,25 +154,25 @@ class Template(object):
config_ptr
=
self
.
_config
config_ptr
=
self
.
_config
target_keys
=
[]
target_keys
=
[]
for
xmlNodeName
in
tag
.
split
(
'.'
):
for
xmlNodeName
in
tag
.
split
(
'.'
):
if
config_ptr
.
has_key
(
xmlNodeName
)
:
if
xmlNodeName
in
config_ptr
:
config_ptr
=
config_ptr
[
xmlNodeName
]
config_ptr
=
config_ptr
[
xmlNodeName
]
elif
xmlNodeName
==
'
%
'
:
elif
xmlNodeName
==
'
%
'
:
target_keys
=
config_ptr
.
keys
()
target_keys
=
config_ptr
.
keys
()
else
:
else
:
break
break
if
len
(
target_keys
)
==
0
:
if
len
(
target_keys
)
==
0
:
# single node, only used for string replacement in output name.
# single node, only used for string replacement in output name.
result
[
tag
]
=
{
tag
:
config_ptr
}
result
[
tag
]
=
{
tag
:
config_ptr
}
else
:
else
:
# multiple node's, find all nodes
# multiple node's, find all nodes
for
target_node
in
target_keys
:
for
target_node
in
target_keys
:
config_ptr
=
self
.
_config
config_ptr
=
self
.
_config
str_wildcard_loc
=
len
(
tag
.
split
(
'
%
'
)[
0
]
.
split
(
'.'
))
str_wildcard_loc
=
len
(
tag
.
split
(
'
%
'
)[
0
]
.
split
(
'.'
))
filter_target
=
[]
filter_target
=
[]
for
xmlNodeName
in
tag
.
replace
(
'
%
'
,
target_node
)
.
split
(
'.'
):
for
xmlNodeName
in
tag
.
replace
(
'
%
'
,
target_node
)
.
split
(
'.'
):
if
config_ptr
.
has_key
(
xmlNodeName
)
:
if
xmlNodeName
in
config_ptr
:
if
type
(
config_ptr
[
xmlNodeName
])
in
(
collections
.
OrderedDict
,
dict
):
if
type
(
config_ptr
[
xmlNodeName
])
in
(
collections
.
OrderedDict
,
dict
):
if
str_wildcard_loc
>=
len
(
filter_target
):
if
str_wildcard_loc
>=
len
(
filter_target
):
filter_target
.
append
(
xmlNodeName
)
filter_target
.
append
(
xmlNodeName
)
if
str_wildcard_loc
==
len
(
filter_target
):
if
str_wildcard_loc
==
len
(
filter_target
):
...
@@ -186,47 +185,44 @@ class Template(object):
...
@@ -186,47 +185,44 @@ class Template(object):
return
result
return
result
def
_create_directory
(
self
,
filename
):
def
_create_directory
(
self
,
filename
):
""" create directory
""" create directory
:param filename: create path for filename ( if not existing )
:param filename: create path for filename ( if not existing )
:return: None
:return: None
"""
"""
fparts
=
[]
fparts
=
[]
for
fpart
in
filename
.
strip
()
.
split
(
'/'
)[:
-
1
]:
for
fpart
in
filename
.
strip
()
.
split
(
'/'
)[:
-
1
]:
fparts
.
append
(
fpart
)
fparts
.
append
(
fpart
)
if
len
(
fpart
)
>
1
:
if
len
(
fpart
)
>
1
:
if
os
.
path
.
exists
(
'/'
.
join
(
fparts
))
==
False
:
if
not
os
.
path
.
exists
(
'/'
.
join
(
fparts
))
:
os
.
mkdir
(
'/'
.
join
(
fparts
))
os
.
mkdir
(
'/'
.
join
(
fparts
))
def
generate
(
self
,
module_name
,
create_directory
=
True
):
def
generate
(
self
,
module_name
,
create_directory
=
True
):
""" generate configuration files using bound config and template data
""" generate configuration files using bound config and template data
:param module_name: module name in dot notation ( company.module )
:param module_name: module name in dot notation ( company.module )
:param create_directory: automatically create directories to place template output in ( if not existing )
:param create_directory: automatically create directories to place template output in ( if not existing )
:return: list of generated output files
:return: list of generated output files
"""
"""
result
=
[]
result
=
[]
module_data
=
self
.
list_module
(
module_name
)
module_data
=
self
.
list_module
(
module_name
)
for
src_template
in
module_data
[
'+TARGETS'
]
.
keys
():
for
src_template
in
module_data
[
'+TARGETS'
]
.
keys
():
target
=
module_data
[
'+TARGETS'
][
src_template
]
target
=
module_data
[
'+TARGETS'
][
src_template
]
target_filename_tags
=
self
.
__findStringTags
(
target
)
target_filename_tags
=
self
.
__findStringTags
(
target
)
target_filters
=
self
.
__findFilters
(
target_filename_tags
)
target_filters
=
self
.
__findFilters
(
target_filename_tags
)
result_filenames
=
{
target
:{}}
result_filenames
=
{
target
:
{}}
for
target_filter
in
target_filters
.
keys
():
for
target_filter
in
target_filters
.
keys
():
for
key
in
target_filters
[
target_filter
]
.
keys
():
for
key
in
target_filters
[
target_filter
]
.
keys
():
for
filename
in
result_filenames
.
keys
():
for
filename
in
result_filenames
.
keys
():
if
filename
.
find
(
'[
%
s]'
%
target_filter
)
>
-
1
:
if
filename
.
find
(
'[
%
s]'
%
target_filter
)
>
-
1
:
new_filename
=
filename
.
replace
(
'[
%
s]'
%
target_filter
,
target_filters
[
target_filter
][
key
])
new_filename
=
filename
.
replace
(
'[
%
s]'
%
target_filter
,
target_filters
[
target_filter
][
key
])
result_filenames
[
new_filename
]
=
copy
.
deepcopy
(
result_filenames
[
filename
])
result_filenames
[
new_filename
]
=
copy
.
deepcopy
(
result_filenames
[
filename
])
result_filenames
[
new_filename
][
key
]
=
target_filters
[
target_filter
][
key
]
result_filenames
[
new_filename
][
key
]
=
target_filters
[
target_filter
][
key
]
j2_page
=
self
.
_j2_env
.
get_template
(
'
%
s/
%
s'
%
(
module_name
.
replace
(
'.'
,
'/'
),
src_template
))
j2_page
=
self
.
_j2_env
.
get_template
(
'
%
s/
%
s'
%
(
module_name
.
replace
(
'.'
,
'/'
),
src_template
))
for
filename
in
result_filenames
.
keys
():
for
filename
in
result_filenames
.
keys
():
if
not
(
filename
.
find
(
'['
)
!=
-
1
and
filename
.
find
(
']'
)
!=
-
1
)
:
if
not
(
filename
.
find
(
'['
)
!=
-
1
and
filename
.
find
(
']'
)
!=
-
1
)
:
# copy config data
# copy config data
cnf_data
=
copy
.
deepcopy
(
self
.
_config
)
cnf_data
=
copy
.
deepcopy
(
self
.
_config
)
cnf_data
[
'TARGET_FILTERS'
]
=
result_filenames
[
filename
]
cnf_data
[
'TARGET_FILTERS'
]
=
result_filenames
[
filename
]
...
@@ -240,16 +236,15 @@ class Template(object):
...
@@ -240,16 +236,15 @@ class Template(object):
content
=
j2_page
.
render
(
cnf_data
)
content
=
j2_page
.
render
(
cnf_data
)
# prefix filename with defined root directory
# prefix filename with defined root directory
filename
=
(
'
%
s/
%
s'
%
(
self
.
_target_root_directory
,
filename
))
.
replace
(
'//'
,
'/'
)
filename
=
(
'
%
s/
%
s'
%
(
self
.
_target_root_directory
,
filename
))
.
replace
(
'//'
,
'/'
)
if
create_directory
:
if
create_directory
:
# make sure the target directory exists
# make sure the target directory exists
self
.
_create_directory
(
filename
)
self
.
_create_directory
(
filename
)
f_out
=
open
(
filename
,
'wb'
)
f_out
=
open
(
filename
,
'wb'
)
f_out
.
write
(
content
)
f_out
.
write
(
content
)
f_out
.
close
()
f_out
.
close
()
result
.
append
(
filename
)
result
.
append
(
filename
)
return
result
return
result
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment