예제 #1
0
    def __init__(self):
        super(CommonConf, self).__init__()
        self.log = logging.getLogger('xivo_sysconf.modules.commonconf')

        http_json_server.register(self.generate , CMD_RW, 
            safe_init=self.safe_init, 
            name='commonconf_generate')
        http_json_server.register(self.apply, CMD_R, name='commonconf_apply')
예제 #2
0
파일: munin.py 프로젝트: Eyepea/xivo-skaro
    def __init__(self):
        super(Munin, self).__init__()
        self.log = logging.getLogger("xivo_sysconf.modules.munin")

        http_json_server.register(self.update, CMD_R, safe_init=self.safe_init, name="munin_update")

        self.cmd1 = ["/usr/sbin/xivo-monitoring-update"]
        self.cmd2 = ["/usr/bin/munin-cron", "--force-root"]
예제 #3
0
    def __init__(self):
        super(Munin, self).__init__()
        self.log = logging.getLogger('xivo_sysconf.modules.munin')

        http_json_server.register(self.update , CMD_R, 
            safe_init=self.safe_init, 
            name='munin_update')
            
        self.cmd1 = ['/usr/sbin/update-pf-stats-munin']
        self.cmd2 = ['/usr/bin/sudo','-u','munin','/usr/bin/munin-cron']
예제 #4
0
파일: ha.py 프로젝트: Eyepea/xivo-gallifrey
    def __init__(self):
        super(Ha, self).__init__()
        self.log = logging.getLogger("xivo_sysconf.modules.ha")

        http_json_server.register(self.generate, CMD_RW, name="ha_generate", safe_init=self.safe_init)
        http_json_server.register(self.status, CMD_R, name="ha_status")
        http_json_server.register(self.apply, CMD_R, name="ha_apply")
        http_json_server.register(self.stop, CMD_R, name="ha_stop")
예제 #5
0
def main(argv=None):
    "entry point"
    argv = argv or sys.argv[1:]
    http_json_server.register(status_check, CMD_R, name='status-check')

    configuration = load_config(argv)
    setup_logging(configuration['log_file'],
                  log_level=configuration['log_level'])

    http_server_options = prepare_http_server_options(configuration)
    http_json_server.init(http_server_options)

    try:
        os.umask(022)
        http_json_server.run(http_server_options)
    except SystemExit:
        raise
    except Exception:
        log.exception("bad things happen")
예제 #6
0
파일: dahdi.py 프로젝트: Eyepea/xivo-skaro
    def __init__(self):
        super(Dahdi, self).__init__()
        self.log = logging.getLogger('xivo_sysconf.modules.dahdi')

        http_json_server.register(self.spansinfo , CMD_R,    name='dahdi_get_spansinfo',
            safe_init=self.safe_init)
        http_json_server.register(self.cardsinfo , CMD_R,    name='dahdi_get_cardsinfo')
        http_json_server.register(self.setconfig , CMD_RW,    name='dahdi_set_config')
예제 #7
0
        logger.error("service %s is not valid", e.service_name)
    return output


def _validate_action(service_name, action):
    if action not in ['stop', 'start', 'restart']:
        raise InvalidActionException(service_name, action)


def _run_action_for_service_validated(service, action):
    output = ''
    try:
        command = ['/bin/systemctl', action, '{}.service'.format(service)]
        p = subprocess.Popen(command,
                             stdout=subprocess.PIPE,
                             stderr=subprocess.STDOUT,
                             close_fds=True)
        output = p.communicate()[0]
        logger.debug("%s : return code %d", ' '.join(command), p.returncode)

        if p.returncode != 0:
            raise HttpReqError(500, output)
    except OSError:
        logger.exception("Error while executing action")
        raise HttpReqError(500, "can't manage services")

    return output


http_json_server.register(services, CMD_RW, name='services')
예제 #8
0
logger = logging.getLogger('xivo_sysconf.modules.services')

def services(args, options):
    """
    POST /services

    >>> services({'networking': 'restart'})
    """
    for svc, act in args.iteritems():
        if act not in ['stop', 'start', 'restart']:
            logger.error("action %s not authorized on %s service" % (act, svc))

        try:
            p = subprocess.Popen(["/etc/init.d/%s" % svc, act], \
                stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
            ret = p.wait()
            output = p.stdout.read()
            logger.debug("/etc/init.d/%s %s : %d" % (svc, act, ret))

            if ret != 0:
                raise HttpReqError(500, output)
        except OSError:
            traceback.print_exc()
            raise HttpReqError(500, "can't manage services")

    return output


http_json_server.register(services, CMD_RW, name='services')

예제 #9
0
파일: wizard.py 프로젝트: Eyepea/xivo-skaro
            subprocess.check_call(["sudo", "-u", "postgres", "psql", "-f",
                                   "/%s" % args['xivoscript']])
        except (OSError, subprocess.CalledProcessError), e:
            log.exception('error')
            raise HttpReqError(500, "Can't create xivo DB with postgresql")
        try:
            subprocess.check_call(["sudo", "-u", "postgres", "psql", "-f",
                                   "/%s" % args['ipbxscript']])
        except (OSError, subprocess.CalledProcessError), e:
            log.exception('error')
            raise HttpReqError(500, "Can't create IPBX DB with postgresql")
    else:
        raise HttpReqError(415, "invalid db backend")


http_json_server.register(exec_db_file, CMD_RW, name="exec_db_file")

def safe_init(options):
    """Load parameters, etc"""
    global Wdc

    cfg = options.configuration

    Wdc['xivo_config_path'] = cfg.get('general', 'xivo_config_path')

    if cfg.has_section('wizard'):
        for x in Wdc.iterkeys():
            if cfg.has_option('wizard', x):
                Wdc[x] = cfg.get('wizard', x)

    Wdc['lock_timeout'] = float(Wdc['lock_timeout'])
예제 #10
0
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License along
    with this program; if not, write to the Free Software Foundation, Inc.,
    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA..
"""

from xivo import http_json_server
from xivo.http_json_server import HttpReqError
from xivo.http_json_server import CMD_R


def uuid(args, options):
    try:
        with open('/usr/share/pf-xivo/XIVO-UUID') as f:
            uuid = f.read()[:-1]
        return {'uuid': uuid}
    except:
        raise HttpReqError(500, "cannot read xivo uuid", json=True)


http_json_server.register(uuid, CMD_R, name='xivo_uuid')
예제 #11
0
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License along
    with this program; if not, write to the Free Software Foundation, Inc.,
    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA..
"""

import os.path, logging

from xivo import http_json_server
from xivo.http_json_server import CMD_R

logger = logging.getLogger('xivo_sysconf.modules.services')

def timezone(args, options):
    """Return system timezone. * is Debian specific (and probably ubuntu too) *
    GET /timezone

    >>> return: 'Europe/Paris'
    """
    tz = None
    if os.path.exists('/etc/timezone'):
        with open('/etc/timezone') as f:
            tz = f.readline()[:-1]

    return tz


http_json_server.register(timezone, CMD_R, name='timezone')

예제 #12
0
 def __init__(self):
     http_json_server.register(self.generate,
                               CMD_RW,
                               safe_init=self.safe_init,
                               name='commonconf_generate')
     http_json_server.register(self.apply, CMD_R, name='commonconf_apply')
예제 #13
0
                    return True
                elif not eth:
                    raise HttpReqError(404, "interface not found")

                eth['flags'] &= ~dumbnet.INTF_FLAG_UP
                if eth.has_key('gateway'):
                    del eth['gateway']
                self.netcfg.set(eth)
            except HttpReqError, e:
                raise e.__class__(e.code, e.text)
            except Exception, e:
                if netifacesbakfile:
                    copy2(netifacesbakfile, self.CONFIG['interfaces_file'])
                raise e.__class__(str(e))
            return True
        finally:
            self.LOCK.release()


dnetintf = DNETIntf()

http_json_server.register(dnetintf.discover_netifaces, CMD_R, safe_init=dnetintf.safe_init)
http_json_server.register(dnetintf.netiface, CMD_R)
http_json_server.register(dnetintf.netiface_from_dst_address, CMD_R)
http_json_server.register(dnetintf.netiface_from_src_address, CMD_R)
http_json_server.register(dnetintf.modify_physical_eth_ipv4, CMD_RW)
http_json_server.register(dnetintf.replace_virtual_eth_ipv4, CMD_RW)
http_json_server.register(dnetintf.modify_eth_ipv4, CMD_RW)
http_json_server.register(dnetintf.change_state_eth_ipv4, CMD_RW)
http_json_server.register(dnetintf.delete_eth_ipv4, CMD_R)
예제 #14
0
	def __init__(self):
		super(OpenSSL, self).__init__()

		http_json_server.register(self.listCertificates, CMD_R,
						name='openssl_listcertificates', safe_init=self.safe_init)
		http_json_server.register(self.getCertificateInfos, CMD_R,
						name='openssl_certificateinfos')
		http_json_server.register(self.getPubKey, CMD_R,
						name='openssl_exportpubkey')
		http_json_server.register(self.export, CMD_R,
						name='openssl_export')
		http_json_server.register(self.createSSLCACertificate, CMD_RW,
						name='openssl_createcacertificate')
		http_json_server.register(self.createSSLCertificate, CMD_RW,
						name='openssl_createcertificate')
		http_json_server.register(self.deleteCertificate, CMD_R, name='openssl_deletecertificate')
		http_json_server.register(self._import, CMD_RW,
						name='openssl_import')
예제 #15
0
# -*- coding: utf-8 -*-
# Copyright 2011-2021 The Wazo Authors  (see the AUTHORS file)
# SPDX-License-Identifier: GPL-3.0-or-later

import subprocess
from xivo.http_json_server import register, CMD_R, HttpReqError

DHCPD_UDPATE_COMMAND = ['dhcpd-update', '-dr']


def dhcpd_update(args, options):
    """Download the latest ISC dhcp server configuration files and
    regenerate the affected configuration files via the dhcpd-update
    command.

    """
    try:
        returncode = subprocess.call(DHCPD_UDPATE_COMMAND, close_fds=True)
    except OSError as e:
        raise HttpReqError(500, "error while executing dhcpd-update command: %s" % e)
    else:
        if returncode:
            raise HttpReqError(500, "dhcpd-update command returned %s" % returncode)
        else:
            return True


register(dhcpd_update, CMD_R, name='dhcpd_update')
예제 #16
0
파일: lshw.py 프로젝트: Eyepea/xivo-skaro
            if value is not None:
                lshw_cmd.append(value)

    try:
        lshw = subprocess.Popen(lshw_cmd,
                                stdout=subprocess.PIPE,
                                stderr=subprocess.PIPE,
                                close_fds=True)

        if lshw.wait():
            log.error(lshw.stderr.read())
            raise LshwExecutionError("A problem occurred while executing command. (command: %r, error: %r)"
                                     % (lshw_cmd, lshw.stderr.read()))

        data = lshw.stdout.read()
        match = LSHW_RE_XML_DECLARATION(data)

        # XXX Workaround when missing XML top-level
        if match:
            xml = "%s<lshw>%s</lshw>" % (match.group(1), match.group(2))
        else:
            xml = "<lshw>%s</lshw>" % data

        return xml2dict.Parse(xml)
    finally:
        LSHWLOCK.release()


http_json_server.register(Lshw, CMD_R, name='lshw')
예제 #17
0
    with open('/etc/pf-xivo/routes', 'w') as f:
        f.write("### AUTOMATICALLY GENERATED BY sysconfd. DO NOT EDIT ###\n")
        f.write(datetime.now().strftime("# $%Y/%m/%d %H:%M:%S$\n"))

        for route in args:
            if route['disable']:
                continue
            
            if route['iface'] != iface:
                iface = route['iface']
                f.write("\n[%s]\n" % iface)

            f.write("%s = %s;%s;%s\n" % \
                (route['name'], route['destination'], route['netmask'], route['gateway']))

            try:
                (eid, verbose) = network.route_set(route['destination'], route['netmask'], route['gateway'], iface)
                if eid != 0 and route['current']:
                    ret = False
            except Exception, e:
                raise HttpReqError(500, 'Cannot apply route')

    network.route_flush_cache()
    return ret


http_json_server.register(network_config, CMD_R)
http_json_server.register(rename_ethernet_interface, CMD_RW)
http_json_server.register(swap_ethernet_interfaces, CMD_RW)
http_json_server.register(routes, CMD_RW)
예제 #18
0
    if cfg.get('resolvconf'):
        for x in Rcc.iterkeys():
            if cfg['resolvconf'].get(x):
                Rcc[x] = cfg['resolvconf'].get(x)

    Rcc['lock_timeout'] = float(Rcc['lock_timeout'])

    for optname in ('hostname', 'hosts', 'resolvconf'):
        Rcc["%s_tpl_file" % optname] = os.path.join(
            tpl_path, Rcc["%s_tpl_file" % optname])

        Rcc["%s_custom_tpl_file" % optname] = os.path.join(
            custom_tpl_path,
            Rcc["%s_tpl_file" % optname],
        )

        Rcc["%s_path" % optname] = os.path.dirname(Rcc["%s_file" % optname])
        Rcc["%s_backup_file" % optname] = os.path.join(
            backup_path,
            Rcc["%s_file" % optname].lstrip(os.path.sep),
        )
        Rcc["%s_backup_path" % optname] = os.path.join(
            backup_path,
            Rcc["%s_path" % optname].lstrip(os.path.sep),
        )


http_json_server.register(Hosts, CMD_RW, safe_init=safe_init, name='hosts')
http_json_server.register(ResolvConf, CMD_RW, name='resolv_conf')
예제 #19
0

class _CronFileInstaller(object):
    DEFAULT_CRON_DIR = '/etc/cron.d'

    def __init__(self, cron_dir=DEFAULT_CRON_DIR):
        self._cron_dir = cron_dir

    def add_cronfile(self, filename, content):
        abs_filename = os.path.join(self._cron_dir, filename)
        with open(abs_filename, 'w') as fobj:
            fobj.write(content)

    def remove_cronfile(self, filename):
        abs_filename = os.path.join(self._cron_dir, filename)
        try:
            os.unlink(abs_filename)
        except OSError as e:
            if e.errno != errno.ENOENT:
                raise


ha_config_manager = HAConfigManager(_PostgresConfigUpdater,
                                    _CronFileInstaller())
http_json_server.register(ha_config_manager.get_ha_config,
                          CMD_R,
                          name='get_ha_config')
http_json_server.register(ha_config_manager.update_ha_config,
                          CMD_RW,
                          name='update_ha_config')
예제 #20
0
파일: ha.py 프로젝트: Eyepea/xivo-skaro
    def restart_postgres(self):
        command_args = ['/etc/init.d/postgresql', 'restart']
        subprocess.check_call(command_args, close_fds=True)


class _CronFileInstaller(object):
    DEFAULT_CRON_DIR = '/etc/cron.d'

    def __init__(self, cron_dir=DEFAULT_CRON_DIR):
        self._cron_dir = cron_dir

    def add_cronfile(self, filename, content):
        abs_filename = os.path.join(self._cron_dir, filename)
        with open(abs_filename, 'w') as fobj:
            fobj.write(content)

    def remove_cronfile(self, filename):
        abs_filename = os.path.join(self._cron_dir, filename)
        try:
            os.unlink(abs_filename)
        except OSError as e:
            if e.errno != errno.ENOENT:
                raise


ha_config_manager = HAConfigManager(_PostgresConfigUpdater, _CronFileInstaller())
http_json_server.register(ha_config_manager.get_ha_config, CMD_R,
                          name='get_ha_config')
http_json_server.register(ha_config_manager.update_ha_config, CMD_RW,
                          name='update_ha_config')
예제 #21
0

def _move_directory(old_path, new_path):
    if not os.path.exists(old_path):
        return

    dirname = os.path.dirname(new_path)
    commands = [["rm", "-rf", new_path],
                [
                    "install", "-d", "-m", "750", "-o", ASTERISK_USER, "-g",
                    ASTERISK_GROUP, dirname
                ], ["mv", old_path, new_path]]

    for cmd in commands:
        subprocess.check_call(cmd)


def _is_valid_path_component(path_component):
    return bool(path_component and path_component != os.curdir
                and path_component != os.pardir
                and os.sep not in path_component)


asterisk = Asterisk()
http_json_server.register(asterisk.delete_voicemail,
                          CMD_R,
                          name='delete_voicemail')
http_json_server.register(asterisk.move_voicemail,
                          CMD_R,
                          name='move_voicemail')
예제 #22
0
    'sccp update config',
    ]

def exec_cmd_asterisk(cmd, options):
    """
    POST /exec_cmd_asterisk

    >>> exec_cmd_asterisk(sip reload)
    """
    if cmd in AST_CMD_REQUESTS or cmd.startswith('sip show peer'):
        try:
            p = subprocess.Popen(['asterisk', '-rx', cmd],
                                stdout=subprocess.PIPE,
                                stderr=subprocess.STDOUT,
                                close_fds=True)
            output = p.communicate()[0]

            if p.returncode != 0:
                raise HttpReqError(500, output)
            else:
                logger.info("Asterisk command '%s' successfully executed", cmd)
        except OSError:
            logger.exception("Error while executing asterisk command")
            raise HttpReqError(500, "can't manage exec_cmd_asterisk")
        return output
    else:
        logger.error("cmd %s not authorized on", cmd)


http_json_server.register(exec_cmd_asterisk, CMD_RW, name='exec_cmd_asterisk')
예제 #23
0
        Wdc["%s_config_custom_tpl_file" % x] = os.path.join(Wdc['custom_templates_path'],
                                                            Wdc["%s_tpl_directory" % x],
                                                            Wdc["%s_config_filename" % x])

    for x in ('modules', 'extconfig', 'res_mysql', 'cdr_mysql', 'res_sqlite'):
        Wdc["asterisk_%s_file" % x] = os.path.join(Wdc['asterisk_config_path'],
                                                   Wdc["asterisk_%s_config_filename" % x])

        Wdc["asterisk_%s_tpl_file" % x] = os.path.join(Wdc['templates_path'],
                                                       Wdc['asterisk_tpl_directory'],
                                                       Wdc["asterisk_%s_config_filename" % x])

        Wdc["asterisk_%s_custom_tpl_file" % x] = os.path.join(Wdc['custom_templates_path'],
                                                              Wdc['asterisk_tpl_directory'],
                                                              Wdc["asterisk_%s_config_filename" % x])

    for x in ('xivo', 'ipbx', 'cti'):
        Wdc["webinterface_%s_file" % x] = os.path.join(Wdc['webinterface_config_path'],
                                                       Wdc["webinterface_%s_config_filename" % x])

        Wdc["webinterface_%s_tpl_file" % x] = os.path.join(Wdc['templates_path'],
                                                           Wdc['webinterface_tpl_directory'],
                                                           Wdc["webinterface_%s_config_filename" % x])

        Wdc["webinterface_%s_custom_tpl_file" % x] = os.path.join(Wdc['custom_templates_path'],
                                                                  Wdc['webinterface_tpl_directory'],
                                                                  Wdc["webinterface_%s_config_filename" % x])

http_json_server.register(set_db_backends, CMD_RW, safe_init=safe_init)
예제 #24
0
        Rcc["%s_tpl_file" % optname] = os.path.join(tpl_path,
                                                    Rcc["%s_tpl_file" % optname])

        Rcc["%s_custom_tpl_file" % optname] = os.path.join(custom_tpl_path,
                                                           Rcc["%s_tpl_file" % optname])

        Rcc["%s_path" % optname] = os.path.dirname(Rcc["%s_file" % optname])
        Rcc["%s_backup_file" % optname] = os.path.join(backup_path,
                                                       Rcc["%s_file" % optname].lstrip(os.path.sep))
        Rcc["%s_backup_path" % optname] = os.path.join(backup_path,
                                                       Rcc["%s_path" % optname].lstrip(os.path.sep))

def GetDns(args, options):
    """Read system DNS configuration
    """
    dns = {'search': [], 'nameservers': []}
    with open('/etc/resolv.conf') as f:
        for line in f.xreadlines():
            line = line[:-1].split(' ')
            
            if line[0]   == 'nameserver':
                dns['nameservers'].append(line[1])
            elif line[0] == 'search':
                dns['search'].append(line[1])
        
    return dns

http_json_server.register(Hosts, CMD_RW, safe_init=safe_init, name='hosts')
http_json_server.register(ResolvConf, CMD_RW, name='resolv_conf')
http_json_server.register(GetDns, CMD_R, name='dns')
예제 #25
0
# -*- coding: utf-8 -*-
# Copyright (C) 2012-2015 Avencall
# SPDX-License-Identifier: GPL-3.0-or-later

from xivo.http_json_server import register, CMD_RW
from wazo_sysconfd.request_handlers.request import RequestHandlersProxy


proxy = RequestHandlersProxy()
register(proxy.handle_request, CMD_RW, safe_init=proxy.safe_init, at_start=proxy.at_start,
         name='exec_request_handlers')
예제 #26
0
from wazo_sysconfd.modules.services import services

logger = logging.getLogger('wazo_sysconfd.modules.xivoctl')


def xivoctl(args, options):
    for service, act in args.iteritems():
        if service == 'wazo-service':
            try:
                if act == 'start':
                    services({'asterisk': 'stop'}, {})
                p = subprocess.Popen(["%s" % service, act],
                                     stdout=subprocess.PIPE,
                                     stderr=subprocess.STDOUT,
                                     close_fds=True)
                output = p.communicate()[0]
                logger.debug("%s %s : %d", service, act, p.returncode)

                if p.returncode != 0:
                    raise HttpReqError(500, output)
            except OSError:
                logger.exception("Error while executing %s script", service)
                raise HttpReqError(500, "can't manage xivoctl")
        else:
            logger.error("service not exist: %s", service)

    return output


http_json_server.register(xivoctl, CMD_RW)
예제 #27
0
        self._get_ipbxengine()

        return self._dependencies_list()

    def dependencies_xivo(self, args, options):
        """
        GET /dependencies_xivo
        
        Just returns xivo dependencies and their status
        """

        self.reqpkg = 'xivo'
        self.opts = {}

        self.args = args
        self.options = options

        self._get_dependency_level()

        return self._dependencies_list()


packages = Packages()

http_json_server.register(packages.aptcache_update, CMD_R)
http_json_server.register(packages.dependencies_asterisk, CMD_R)
http_json_server.register(packages.dependencies_mysql, CMD_R)
http_json_server.register(packages.dependencies_postgresql, CMD_R)
http_json_server.register(packages.dependencies_sqlite, CMD_R)
http_json_server.register(packages.dependencies_xivo, CMD_R)
예제 #28
0
from xivo.http_json_server import HttpReqError
from xivo.http_json_server import CMD_R


class Asterisk(object):
    def __init__(self, base_vmail_path='/var/spool/asterisk/voicemail'):
        self._base_vmail_path = base_vmail_path

    def delete_voicemail(self, args, options):
        """Delete spool dir associated with voicemail

            options:
                name    : voicemail name
                context : voicemail context (opt. default is 'default')
        """
        if 'name' not in options:
            raise HttpReqError(400, "missing 'name' arg", json=True)
        context = options.get('context', 'default')

        vmpath = os.path.join(self._base_vmail_path, context, options['name'])
        if not os.path.exists(vmpath):
            raise HttpReqError(404, "voicemail spool dir not found", json=True)
        shutil.rmtree(vmpath)

        return True


asterisk = Asterisk()
http_json_server.register(asterisk.delete_voicemail, CMD_R,
                          name='delete_voicemail')
예제 #29
0
파일: dhcp.py 프로젝트: Eyepea/xivo-skaro
    You should have received a copy of the GNU General Public License along
    with this program; if not, write to the Free Software Foundation, Inc.,
    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA..
"""

import subprocess
from xivo.http_json_server import register, CMD_R, HttpReqError

DHCPD_UDPATE_COMMAND = ['dhcpd-update', '-dr']


def dhcpd_update(args, options):
    """Download the latest ISC dhcp server configuration files and
    regenerate the affected configuration files via the dhcpd-update
    command.
    
    """
    try:
        returncode = subprocess.call(DHCPD_UDPATE_COMMAND, close_fds=True)
    except OSError, e:
        raise HttpReqError(500, "error while executing dhcpd-update command", e)
    else:
        if returncode:
            raise HttpReqError(500, "dhcpd-update command returned %s" % returncode)
        else:
            return True


register(dhcpd_update, CMD_R, name='dhcpd_update')