add file support
Signed-off-by: Nico Schottelius <nico@wurzel.schottelius.org>
This commit is contained in:
parent
4207124c52
commit
9afb57412d
2 changed files with 62 additions and 26 deletions
|
@ -20,11 +20,14 @@
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
|
|
||||||
|
import ipaddress
|
||||||
import logging
|
import logging
|
||||||
import re
|
import re
|
||||||
import socket
|
import socket
|
||||||
import http.server
|
import http.server
|
||||||
|
import os
|
||||||
import socketserver
|
import socketserver
|
||||||
|
import shutil
|
||||||
|
|
||||||
import multiprocessing
|
import multiprocessing
|
||||||
|
|
||||||
|
@ -37,10 +40,11 @@ class Trigger():
|
||||||
"""cdist trigger handling"""
|
"""cdist trigger handling"""
|
||||||
|
|
||||||
# Arguments that are only trigger specific
|
# Arguments that are only trigger specific
|
||||||
triggers_args = [ "http_port", "ipv6", "directory", "content" ]
|
triggers_args = [ "http_port", "ipv6", "directory", "source" ]
|
||||||
|
|
||||||
|
|
||||||
def __init__(self, http_port=None, dry_run=False, ipv6=False,
|
def __init__(self, http_port=None, dry_run=False, ipv6=False,
|
||||||
directory=None, content=None, cdistargs=None):
|
directory=None, source=None, cdistargs=None):
|
||||||
self.log = logging.getLogger("trigger")
|
self.log = logging.getLogger("trigger")
|
||||||
self.dry_run = dry_run
|
self.dry_run = dry_run
|
||||||
self.http_port = int(http_port)
|
self.http_port = int(http_port)
|
||||||
|
@ -48,7 +52,7 @@ class Trigger():
|
||||||
self.args = cdistargs
|
self.args = cdistargs
|
||||||
|
|
||||||
self.directory = directory
|
self.directory = directory
|
||||||
self.content = content
|
self.source = source
|
||||||
|
|
||||||
log.debug("IPv6: %s", self.ipv6)
|
log.debug("IPv6: %s", self.ipv6)
|
||||||
|
|
||||||
|
@ -59,7 +63,7 @@ class Trigger():
|
||||||
httpdcls = HTTPServerV6
|
httpdcls = HTTPServerV6
|
||||||
else:
|
else:
|
||||||
httpdcls = HTTPServerV4
|
httpdcls = HTTPServerV4
|
||||||
httpd = httpdcls(self.args, server_address, TriggerHttp)
|
httpd = httpdcls(self.args, self.directory, self.source, server_address, TriggerHttp)
|
||||||
|
|
||||||
log.debug("Starting server at port %d", self.http_port)
|
log.debug("Starting server at port %d", self.http_port)
|
||||||
if self.dry_run:
|
if self.dry_run:
|
||||||
|
@ -86,44 +90,73 @@ class Trigger():
|
||||||
t.run()
|
t.run()
|
||||||
|
|
||||||
class TriggerHttp(http.server.BaseHTTPRequestHandler):
|
class TriggerHttp(http.server.BaseHTTPRequestHandler):
|
||||||
|
actions = { "cdist": [ "config", "install" ],
|
||||||
|
"file": [ "present", "absent" ]
|
||||||
|
}
|
||||||
|
|
||||||
|
def do_HEAD(self):
|
||||||
|
self.dispatch_request()
|
||||||
|
|
||||||
|
def do_POST(self):
|
||||||
|
self.dispatch_request()
|
||||||
|
|
||||||
def do_GET(self):
|
def do_GET(self):
|
||||||
|
self.dispatch_request()
|
||||||
|
|
||||||
|
def dispatch_request(self):
|
||||||
host = self.client_address[0]
|
host = self.client_address[0]
|
||||||
code = 200
|
code = 200
|
||||||
mode = None
|
|
||||||
|
|
||||||
self.cdistargs = self.server.cdistargs
|
self.cdistargs = self.server.cdistargs
|
||||||
|
|
||||||
m = re.match("^/(?P<subsystem>cdist|file)/(?P<action>create|delete|config|install)/", "/cdist/install/")
|
# FIXME: generate regexp based on self.actions
|
||||||
|
m = re.match("^/(?P<subsystem>cdist|file)/(?P<action>present|absent|config|install)/", self.path)
|
||||||
|
|
||||||
if m:
|
if m:
|
||||||
subsystem = m.group('subsystem')
|
subsystem = m.group('subsystem')
|
||||||
action = m.group('action')
|
action = m.group('action')
|
||||||
log.debug("Calling {} -> {}".format(subsystem, action))
|
handler = getattr(self, "handler_" + subsystem)
|
||||||
|
|
||||||
|
if not action in self.actions[subsystem]:
|
||||||
|
code = 404
|
||||||
else:
|
else:
|
||||||
code = 404
|
code = 404
|
||||||
|
|
||||||
if mode:
|
if code == 200:
|
||||||
log.debug("Running cdist for %s in mode %s", host, mode)
|
log.debug("Calling {} -> {}".format(subsystem, action))
|
||||||
if self.server.dry_run:
|
handler(action, host)
|
||||||
log.info("Dry run, skipping cdist execution")
|
|
||||||
else:
|
|
||||||
self.run_cdist(mode, host)
|
|
||||||
log.debug("cdist run finished")
|
|
||||||
else:
|
|
||||||
log.info("Unsupported mode in path %s, ignoring", self.path)
|
|
||||||
|
|
||||||
self.send_response(code)
|
self.send_response(code)
|
||||||
self.end_headers()
|
self.end_headers()
|
||||||
|
|
||||||
def do_HEAD(self):
|
def handler_file(self, action, host):
|
||||||
self.do_GET()
|
if not self.server.directory or not self.server.source:
|
||||||
|
log.info("Cannot server file request: directory or source not setup")
|
||||||
|
return
|
||||||
|
|
||||||
def do_POST(self):
|
try:
|
||||||
self.do_GET()
|
ipaddress.ip_address(host)
|
||||||
|
except ValueError:
|
||||||
|
log.error("Host is not a valid IP address - aborting")
|
||||||
|
return
|
||||||
|
|
||||||
def run_cdist(self, mode, host):
|
dst = os.path.join(self.server.directory, host)
|
||||||
cname = mode.title()
|
|
||||||
module = getattr(cdist, mode)
|
if action == "present":
|
||||||
|
shutil.copyfile(self.server.source, dst)
|
||||||
|
if action == "absent":
|
||||||
|
if os.path.exists(dst):
|
||||||
|
os.remove(dst)
|
||||||
|
|
||||||
|
def handler_cdist(self, action, host):
|
||||||
|
log.debug("Running cdist for %s in mode %s", host, mode)
|
||||||
|
|
||||||
|
if self.server.dry_run:
|
||||||
|
log.info("Dry run, skipping cdist execution")
|
||||||
|
return
|
||||||
|
|
||||||
|
cname = action.title()
|
||||||
|
module = getattr(cdist, action)
|
||||||
theclass = getattr(module, cname)
|
theclass = getattr(module, cname)
|
||||||
|
|
||||||
if hasattr(self.cdistargs, 'out_path'):
|
if hasattr(self.cdistargs, 'out_path'):
|
||||||
|
@ -145,9 +178,12 @@ class HTTPServerV6(socketserver.ForkingMixIn, http.server.HTTPServer):
|
||||||
"""
|
"""
|
||||||
address_family = socket.AF_INET6
|
address_family = socket.AF_INET6
|
||||||
|
|
||||||
def __init__(self, cdistargs, *args, **kwargs):
|
def __init__(self, cdistargs, directory, source, *args, **kwargs):
|
||||||
self.cdistargs = cdistargs
|
self.cdistargs = cdistargs
|
||||||
self.dry_run = cdistargs.dry_run
|
self.dry_run = cdistargs.dry_run
|
||||||
|
self.directory = directory
|
||||||
|
self.source = source
|
||||||
|
|
||||||
http.server.HTTPServer.__init__(self, *args, **kwargs)
|
http.server.HTTPServer.__init__(self, *args, **kwargs)
|
||||||
|
|
||||||
class HTTPServerV4(HTTPServerV6):
|
class HTTPServerV4(HTTPServerV6):
|
||||||
|
|
|
@ -197,8 +197,8 @@ def commandline():
|
||||||
help=('Where to create local files'))
|
help=('Where to create local files'))
|
||||||
|
|
||||||
parser['trigger'].add_argument(
|
parser['trigger'].add_argument(
|
||||||
'-C', '--content', action='store', required=False,
|
'-S', '--source', action='store', required=False,
|
||||||
help=('What to store in created files'))
|
help=('Which file to copy for creation'))
|
||||||
|
|
||||||
parser['trigger'].set_defaults(func=cdist.trigger.Trigger.commandline)
|
parser['trigger'].set_defaults(func=cdist.trigger.Trigger.commandline)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue