mirror of https://github.com/sipwise/ngcpcfg.git
commit
3436c08361
@ -0,0 +1,59 @@
|
||||
# for syntax checks
|
||||
BASH_SCRIPTS = scripts/* functions/* etc/ngcp-config/ngcpcfg.cfg helper/build_config sbin/ngcpcfg
|
||||
PERL_SCRIPTS = helper/sort-yml \
|
||||
helper/sync-db \
|
||||
helper/tt2-wrapper \
|
||||
helper/validate-yml helper/fileformat_version \
|
||||
sbin/ngcp-network \
|
||||
sbin/ngcp-sync-constants
|
||||
|
||||
all: docs
|
||||
|
||||
docs: html pdf epub man
|
||||
|
||||
html:
|
||||
asciidoc docs/ngcpcfg.txt
|
||||
|
||||
pdf:
|
||||
a2x --icons -a toc -a toclevels=3 -a docinfo -f pdf docs/ngcpcfg.txt
|
||||
|
||||
epub:
|
||||
a2x --icons -a toc -a toclevels=3 -a docinfo -f epub docs/ngcpcfg.txt
|
||||
|
||||
man:
|
||||
asciidoc -d manpage -b docbook docs/ngcpcfg.txt
|
||||
sed -i 's/<emphasis role="strong">/<emphasis role="bold">/' docs/ngcpcfg.xml
|
||||
xsltproc --nonet /usr/share/xml/docbook/stylesheet/nwalsh/manpages/docbook.xsl docs/ngcpcfg.xml
|
||||
pod2man --section=8 sbin/ngcp-network > ngcp-network.8
|
||||
pod2man --section=8 sbin/ngcp-sync-constants > ngcp-sync-constants.8
|
||||
|
||||
|
||||
clean:
|
||||
rm -f docs/ngcpcfg.xml docs/ngcpcfg.epub docs/ngcpcfg.html docs/ngcpcfg.pdf
|
||||
rm -f ngcpcfg.8 ngcp-network.8 ngcp-sync-constants.8
|
||||
|
||||
dist-clean:
|
||||
rm -f docs/ngcpcfg.html docs/ngcpcfg.pdf
|
||||
rm -f docs/ngcpcfg.epub ngcpcfg.8
|
||||
|
||||
# check for syntax errors
|
||||
syntaxcheck: shellcheck perlcheck
|
||||
|
||||
shellcheck:
|
||||
@echo -n "Checking for shell syntax errors"; \
|
||||
for SCRIPT in $(BASH_SCRIPTS); do \
|
||||
test -r $${SCRIPT} || continue ; \
|
||||
bash -n $${SCRIPT} || exit ; \
|
||||
echo -n "."; \
|
||||
done; \
|
||||
echo " done."; \
|
||||
|
||||
perlcheck:
|
||||
@echo "Checking for perl syntax errors:"; \
|
||||
for SCRIPT in $(PERL_SCRIPTS); do \
|
||||
test -r $${SCRIPT} || continue ; \
|
||||
perl -CSD -w -c $${SCRIPT} || exit ; \
|
||||
done; \
|
||||
echo "-> perl check done."; \
|
||||
|
||||
# EOF
|
@ -0,0 +1,357 @@
|
||||
ngcp-ngcpcfg (0.16.0) unstable; urgency=low
|
||||
|
||||
* New release splitting of ha/carrier features.
|
||||
|
||||
-- Michael Prokop <mprokop@sipwise.com> Wed, 13 Mar 2013 14:21:25 +0100
|
||||
|
||||
ngcp-ngcpcfg (0.15.3) unstable; urgency=low
|
||||
|
||||
* ngcp-sync-constants takes MySQL credentials from /etc/mysql/sipwise.cnf
|
||||
|
||||
-- Kirill Solomko <ksolomko@sipwise.com> Wed, 15 Jan 2013 16:32:11 +0100
|
||||
|
||||
ngcp-ngcpcfg (0.15.2) unstable; urgency=low
|
||||
|
||||
* Fix sync for asterisk ODBC credentials.
|
||||
|
||||
-- Andrew Pogrebennyk <apogrebennyk@sipwise.com> Wed, 02 Jan 2013 11:27:23 +0100
|
||||
|
||||
ngcp-ngcpcfg (0.15.1) unstable; urgency=low
|
||||
|
||||
* Make sure to sync both sems and sems_prepaid passwords.
|
||||
|
||||
-- Andrew Pogrebennyk <apogrebennyk@sipwise.com> Fri, 21 Dec 2012 21:47:51 +0100
|
||||
|
||||
ngcp-ngcpcfg (0.15.0) unstable; urgency=low
|
||||
|
||||
* Implement ngcp-network command-line tool.
|
||||
* Implement ngcp-ngcpcfg-carrier package.
|
||||
* Add helper functions for network.yml transition.
|
||||
* support configuration directory /etc/ngcp-config/ngcpcfg.d
|
||||
* provide carton/cpanfile integration for running testsuite on Jenkins
|
||||
* Check the fax_gateways defined or not
|
||||
* Add support to netmask for the fax_gateways
|
||||
|
||||
-- Andrew Pogrebennyk <apogrebennyk@sipwise.com> Fri, 21 Dec 2012 11:27:15 +0100
|
||||
|
||||
ngcp-ngcpcfg (0.14.1) unstable; urgency=low
|
||||
|
||||
[ mwang ]
|
||||
* sync-db: Check the fax_gateways defined or not
|
||||
|
||||
-- Jon Bonilla <jbonilla@sipwise.com> Wed, 22 Aug 2012 12:50:01 +0200
|
||||
|
||||
ngcp-ngcpcfg (0.14.0) unstable; urgency=low
|
||||
|
||||
[ Michael Prokop ]
|
||||
* Adjust configuration file handling to properly work with UTF-8 input
|
||||
* Run etckeeper when invoking "ngcpcfg commit"
|
||||
* Adjust detection of new configuration files that are not yet tracked
|
||||
* Bump Standards-Version to 3.9.3
|
||||
* etckeeper: check for etckeeper binary and initialised .git repo
|
||||
* commit: do not exit on errors during sync-db
|
||||
* services option: run inside a function so --dry-run option works
|
||||
correct
|
||||
* wrap and sort items in Debian packaging files
|
||||
|
||||
[ Andreas Granig ]
|
||||
* On commit, also sync various options with db using helper/sync-db
|
||||
|
||||
[ Min Wang ]
|
||||
* helper/sync-db related changes:
|
||||
- Add sync fax_gateways for kamailio dispatcher table
|
||||
- Add reloading dispatcher once fax_gateways changes
|
||||
- Print out the reload dispatcher return status
|
||||
|
||||
-- Michael Prokop <mprokop@sipwise.com> Fri, 10 Aug 2012 18:33:19 +0200
|
||||
|
||||
ngcp-ngcpcfg (0.13.1) unstable; urgency=low
|
||||
|
||||
* Do not rely on TTL but instead use timeout when checking other host(s)
|
||||
* pull: no need to run fetch check in subshell
|
||||
* pull: avoid diverging branches if changes take place on both sides.
|
||||
Thanks to Andrew Pogrebennyk for catching the bug + providing
|
||||
instructions to reproduce it
|
||||
* pull: exit with return code of pull command
|
||||
|
||||
-- Michael Prokop <mprokop@sipwise.com> Mon, 14 May 2012 15:27:05 +0200
|
||||
|
||||
ngcp-ngcpcfg (0.13.0) unstable; urgency=low
|
||||
|
||||
[ Michael Prokop ]
|
||||
* Install ngcpcfg manpage in main ngcp-ngcpcfg package
|
||||
|
||||
[ Andrew Pogrebennyk ]
|
||||
* Add yml upgrade scripts for 2.5
|
||||
* Add testfiles for 2.5 ce and pro
|
||||
* Add yml update helper scripts
|
||||
|
||||
-- Michael Prokop <mprokop@sipwise.com> Tue, 03 Apr 2012 16:24:30 +0200
|
||||
|
||||
ngcp-ngcpcfg (0.12.4) unstable; urgency=low
|
||||
|
||||
[ Michael Prokop ]
|
||||
* perlcheck: invoke perl with -CSD option
|
||||
|
||||
-- Michael Prokop <mprokop@sipwise.com> Thu, 26 Jan 2012 17:38:19 +0100
|
||||
|
||||
ngcp-ngcpcfg (0.12.3) unstable; urgency=low
|
||||
|
||||
[ Richard Fuchs ]
|
||||
* Fix handling of utf8 files
|
||||
|
||||
[ Michael Prokop ]
|
||||
* Config builder: do not output error message, provide
|
||||
debugging instructions instead
|
||||
|
||||
-- Michael Prokop <mprokop@sipwise.com> Thu, 26 Jan 2012 16:51:51 +0100
|
||||
|
||||
ngcp-ngcpcfg (0.12.2) unstable; urgency=low
|
||||
|
||||
* provide force-reload in ngcpcfg-status init script
|
||||
* diff command: drop --addremove option and make it the
|
||||
default behaviour
|
||||
|
||||
-- Michael Prokop <mprokop@sipwise.com> Thu, 26 Jan 2012 12:36:56 +0100
|
||||
|
||||
ngcp-ngcpcfg (0.12.1) unstable; urgency=low
|
||||
|
||||
* upgrade scripts:
|
||||
- update internal file format information
|
||||
- bump fileversion of cdrexport to 003
|
||||
|
||||
-- Michael Prokop <mprokop@sipwise.com> Fri, 02 Dec 2011 22:23:58 +0100
|
||||
|
||||
ngcp-ngcpcfg (0.12.0) unstable; urgency=low
|
||||
|
||||
[ Michael Prokop ]
|
||||
* Add simple sort-file script for easier comparison of upgrade script output
|
||||
* Provide upgrade scripts for recent sip:provider releases
|
||||
* Update configuration files according to recent development
|
||||
* Add fileformat_version helper script for usage inside upgrade scripts
|
||||
* Error out if encoding of a central configuration file isn't ASCII nor UTF-8
|
||||
* tt2-wrapper: explicitely set utf8 mode for stdout
|
||||
* Run xsltproc with --nonet option
|
||||
* Add config.yml/constants.yml testfiles for new sip:provider releases
|
||||
|
||||
[ Jon Bonilla ]
|
||||
* Adapt upgrade scripts to recent development
|
||||
* Adapt testfile to recent development
|
||||
|
||||
-- Michael Prokop <mprokop@sipwise.com> Tue, 29 Nov 2011 17:49:45 +0100
|
||||
|
||||
ngcp-ngcpcfg (0.11.1) unstable; urgency=low
|
||||
|
||||
* Bugfixes:
|
||||
- ngcpcfg: fix usage instructions regarding --debug switch
|
||||
|
||||
* Debian packaging:
|
||||
- rework debian/rules to use generic rule to build packages
|
||||
- use team as entry in Maintainer field of debian/control
|
||||
|
||||
* Testsuite improvements:
|
||||
- test tt2 processing + precedence of files
|
||||
- validate ngcpcfg without any arguments, with --version
|
||||
and with --help
|
||||
|
||||
* High Availability Setup:
|
||||
- pull: add further debug statements
|
||||
- push: use 'ngcpcfg apply' in default action and support
|
||||
--noapply for disabling the behaviour
|
||||
- push: use ngcpcfg pull instead of native git commands
|
||||
- push: if ssh login does not work report it with specific
|
||||
error message
|
||||
|
||||
-- Michael Prokop <mprokop@sipwise.com> Thu, 22 Sep 2011 01:34:04 +0200
|
||||
|
||||
ngcp-ngcpcfg (0.11.0) unstable; urgency=low
|
||||
|
||||
* Bugfixes:
|
||||
- Do not strip $CONFIG_POOL variable from provided file/directory
|
||||
arguments when generating file list
|
||||
- Get rid of files *.tt2.sp{1,2} where a *.customtt.tt2.sp{1,2}
|
||||
exists as well
|
||||
|
||||
* New features:
|
||||
- Build option: support generation of modified files only when
|
||||
using --modified-only option
|
||||
- Diff: support --addremove option to list new/removed files
|
||||
- Provide version information through -v, --version + version options
|
||||
- Push: be more verbose when operation fails
|
||||
- Services: support --dry-run as alternative to 'test' option,
|
||||
error out on unknown options
|
||||
- Support --debug option to run actions in debug mode
|
||||
- Support new option "diff" to show pending modifications in
|
||||
configuration pool
|
||||
|
||||
* Improvements:
|
||||
- Do not remove temporary filelist files in debug mode
|
||||
- Extend package description of ngcp-ngcpcfg-ha
|
||||
- Redesign code for generating the file list
|
||||
- Update ngcpcfg manpage (document new options, clarify
|
||||
precedence of configuration files,...)
|
||||
|
||||
* High Availability Setup:
|
||||
- Do not add host to host list if build operation was successfull
|
||||
- Fix typo in warning message (registerted<->registered)
|
||||
- Support --nobuild option to skip build process when pushing
|
||||
changes
|
||||
- When pushing changes then execute 'build' on all pushed hosts
|
||||
|
||||
-- Michael Prokop <mprokop@sipwise.com> Mon, 29 Aug 2011 13:42:23 +0200
|
||||
|
||||
ngcp-ngcpcfg (0.10.0) unstable; urgency=low
|
||||
|
||||
* Add further logic and user information for validating YAML syntax.
|
||||
* Make sure customtt.tt2 template files are preferred over
|
||||
non-customtt.tt2 files in non-HA setups.
|
||||
* encrypt/decrypt: get rid of ngcpcfg-share on glusterfs and
|
||||
local cache on encrypt and try to restore it iff possible or otherwis
|
||||
* Fix unset variable if calling ngcpcfg without any options
|
||||
and having ngcpcfg-locker installed.
|
||||
* Usage text: correctly indent optional features.
|
||||
* Add build-arch/build-indep targets to debian/rules to make lintian happy.
|
||||
* Drop essential package tar from Depends of ngcp-ngcpcfg-locker.
|
||||
* Drop essential package bsdutils from Depends.
|
||||
|
||||
-- Michael Prokop <mprokop@sipwise.com> Sat, 20 Aug 2011 00:20:34 +0200
|
||||
|
||||
ngcp-ngcpcfg (0.9.0) unstable; urgency=low
|
||||
|
||||
* Before generating new configuration files from templates
|
||||
test known .yml files for valid syntax.
|
||||
* New package ngcp-ngcpcfg-locker: support encrypting/decrypting
|
||||
ngcpcfg configuration files.
|
||||
* Initial version of an upgrade script to support safe upgrades.
|
||||
|
||||
-- Michael Prokop <mprokop@sipwise.com> Mon, 04 Jul 2011 15:49:36 +0200
|
||||
|
||||
ngcp-ngcpcfg (0.8.0) unstable; urgency=low
|
||||
|
||||
[ Michael Prokop ]
|
||||
* Adjust package description.
|
||||
* Upgrade script:
|
||||
- Add clir and block-override VSC.
|
||||
- Add www_admin.peer with preference_features flag.
|
||||
- Add preference_features switch for domains in www-admin.
|
||||
* Fix gitignore configuration of ngcpcfg.
|
||||
* Bump Standards-Version to 3.9.2.
|
||||
* HA features:
|
||||
- Store node name in /etc/ngcp_ha_node.
|
||||
- Use glusterfs share as default remote target and make setup
|
||||
consistent between involved nodes.
|
||||
|
||||
[ Andreas Granig ]
|
||||
* Aligned to x.y.z versioning scheme.
|
||||
|
||||
-- Michael Prokop <mprokop@sipwise.com> Sat, 11 Jun 2011 01:44:46 +0200
|
||||
|
||||
ngcp-ngcpcfg (0.7.0) unstable; urgency=low
|
||||
|
||||
[ Michael Prokop ]
|
||||
* Bugfix:
|
||||
- Make sure we switch to $NGCPCTL_MAIN before marking host as
|
||||
initialised.
|
||||
* Features:
|
||||
- Support shared setup (via ngcp-ngcpcfg-ha).
|
||||
- Support .sp1 and .sp2 files for shared setup (ngcp-ngcpcfg-ha).
|
||||
- Provide debugging option through environment variable DEBUG.
|
||||
- Send status messages to syslog.
|
||||
- Check for Debian package versions of templates on all nodes and do
|
||||
NOT push in case of different package versions (applies only
|
||||
to files that are going to be pushed and not to all templates,
|
||||
ngcp-ngcpcfg-ha only).
|
||||
- Provide upgrade package ngcp-ngcpcfg-upgrade to apply schema
|
||||
changes when upgrading from 2.1 to 2.2.
|
||||
- Support {pre,post}build scripts within template directory.
|
||||
- Initial testsuite to check for regressions.
|
||||
- Provide validate-yml script to validate configuration file.
|
||||
- Provide sort-yml script to sort configuration file for easier
|
||||
comparison with other configuration files.
|
||||
- Provide warning message if a service script did not return
|
||||
with exit code 0.
|
||||
- Support {pre,post}build scripts within template directory.
|
||||
* Changes:
|
||||
- Refactor code to minimise user interface script and provide
|
||||
options (build/commit/...) through separate scripts.
|
||||
- Drop HELPER configuration variable from ngcpcfg.cfg.
|
||||
- Slightly improve /etc/ngcp-config/ngcpcfg.cfg (description and
|
||||
sorting of variables.
|
||||
* Debian packaging:
|
||||
- Drop shlibs:Depends from Depends, we do not have any libraries.
|
||||
- Fix typo in long description.
|
||||
- Add debian/source/format (1.0 format).
|
||||
- Provide syntaxchecks for bash and perl scripts as Q/A mechanism
|
||||
in build process.
|
||||
- Add perl packages to Build-Depends.
|
||||
- Drop unnecessary libtemplate-plugin-yaml-perl from Depends.
|
||||
- Run syntax checks for code while building, therefore add
|
||||
libhash-merge-perl, libtemplate-perl and libyaml-perl to
|
||||
Build-Depends.
|
||||
|
||||
[ Richard Fuchs ]
|
||||
* Add libyaml-tiny-perl to Build-Depends.
|
||||
|
||||
[ Jon Bonilla ]
|
||||
* Add support to ngcpcfg.{pre|post}build directory generic files.
|
||||
|
||||
-- Andreas Granig <agranig@sipwise.com> Fri, 29 Apr 2011 12:10:13 +0200
|
||||
|
||||
ngcp-ngcpcfg (0.6) unstable; urgency=low
|
||||
|
||||
[ Jon Bonilla ]
|
||||
* Add constants.yaml file handling so the user can configure
|
||||
just configurable options.
|
||||
|
||||
[ Andreas Granig ]
|
||||
* Added "apply" as a short-cut for build, then services, then commit.
|
||||
|
||||
[ Michael Prokop ]
|
||||
* Iff a directory does not exist yet create it with permissions 755.
|
||||
* Update stderr printf handling.
|
||||
* Integrate etckeeper commit in "apply" shortcut.
|
||||
* Update copyright (GPL-3+).
|
||||
* Work around a git index issue with generated files for use with
|
||||
the service command.
|
||||
|
||||
-- Michael Prokop <mprokop@sipwise.com> Tue, 30 Nov 2010 11:52:19 +0100
|
||||
|
||||
ngcp-ngcpcfg (0.5) unstable; urgency=low
|
||||
|
||||
* Support .prebuild and .postbuild scripts inside template pool
|
||||
which are executre before/after generation of output file.
|
||||
* Support building of specific files/directories only so it's
|
||||
possible to execute e.g. 'ngcpcfg build /etc/apache2' to
|
||||
skip generation of any files besides the ones inside /etc/apache2.
|
||||
|
||||
-- Michael Prokop <mprokop@sipwise.com> Tue, 16 Nov 2010 18:27:28 +0100
|
||||
|
||||
ngcp-ngcpcfg (0.4) unstable; urgency=low
|
||||
|
||||
* Support additional config.local.yml config file.
|
||||
* Support .customtt.tt2 files for local configuration.
|
||||
* Provide service files through same directory as templates.
|
||||
* Unify service executions.
|
||||
* Make generated files r/o.
|
||||
* Inform if config has changed and is not "build" yet.
|
||||
* Show which files have been modified.
|
||||
|
||||
-- Michael Prokop <mprokop@sipwise.com> Wed, 10 Nov 2010 13:04:56 +0100
|
||||
|
||||
ngcp-ngcpcfg (0.3) unstable; urgency=low
|
||||
|
||||
* Unify directory names, configuration files,...
|
||||
|
||||
-- Michael Prokop <mprokop@sipwise.com> Wed, 20 Oct 2010 14:03:01 +0200
|
||||
|
||||
ngcp-ngcpcfg (0.2) unstable; urgency=low
|
||||
|
||||
* Support non-shared setup.
|
||||
|
||||
-- Michael Prokop <mprokop@sipwise.com> Tue, 12 Oct 2010 18:02:10 +0200
|
||||
|
||||
ngcp-ngcpcfg (0.1) unstable; urgency=low
|
||||
|
||||
* Initial release.
|
||||
|
||||
-- Michael Prokop <mprokop@sipwise.com> Thu, 26 Aug 2010 17:19:32 +0200
|
@ -0,0 +1 @@
|
||||
5
|
@ -0,0 +1,60 @@
|
||||
Source: ngcp-ngcpcfg
|
||||
Section: admin
|
||||
Priority: extra
|
||||
Maintainer: Sipwise Development Team <support@sipwise.com>
|
||||
Build-Depends: asciidoc,
|
||||
debhelper (>= 5),
|
||||
docbook-xsl,
|
||||
libdata-validate-ip-perl,
|
||||
libdbd-mysql-perl,
|
||||
libhash-merge-perl,
|
||||
libio-interface-perl,
|
||||
liblist-moreutils-perl,
|
||||
libnet-netmask-perl,
|
||||
libregexp-ipv6-perl,
|
||||
libtemplate-perl,
|
||||
libyaml-perl,
|
||||
libyaml-tiny-perl,
|
||||
xsltproc
|
||||
Standards-Version: 3.9.4
|
||||
Homepage: http://sipwise.com/
|
||||
|
||||
Package: ngcp-ngcpcfg
|
||||
Architecture: all
|
||||
Depends: etckeeper,
|
||||
file,
|
||||
git-core,
|
||||
libdata-validate-ip-perl,
|
||||
libdbd-mysql-perl,
|
||||
libhash-merge-perl,
|
||||
libio-interface-perl,
|
||||
liblist-moreutils-perl,
|
||||
libnet-netmask-perl,
|
||||
libregexp-ipv6-perl,
|
||||
libtemplate-perl,
|
||||
libyaml-perl,
|
||||
libyaml-tiny-perl,
|
||||
${misc:Depends},
|
||||
${perl:Depends}
|
||||
Description: central and templated based Configuration Management System for NGCP platforms
|
||||
ngcp-ngcpcfg is a Configuration Management System providing central
|
||||
configuration and template based handling of configuration
|
||||
files, featuring handling of local configuration changes and
|
||||
updates as well as synchronisation between servers.
|
||||
|
||||
Package: ngcp-ngcpcfg-locker
|
||||
Architecture: all
|
||||
Depends: gnupg,
|
||||
ngcp-ngcpcfg,
|
||||
${misc:Depends}
|
||||
Description: Encrypt and decrypt feature for ngcp-ngcpcfg
|
||||
This package provides the encrypt and decrypt options for
|
||||
usage via ngcpcfg.
|
||||
|
||||
Package: ngcp-ngcpcfg-testsuite
|
||||
Architecture: all
|
||||
Depends: ngcp-ngcpcfg,
|
||||
${misc:Depends}
|
||||
Description: testsuite for ngcpcfg
|
||||
This package provides a testsuite to automatically test ngcpcfg
|
||||
features and detect any possible breakages.
|
@ -0,0 +1,23 @@
|
||||
Upstream Author: The Sipwise Team - http://sipwise.com
|
||||
Copyright: 2007-2013, Sipwise GmbH, Austria
|
||||
License: GPL-3+
|
||||
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 3 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 package; if not, write to the Free
|
||||
Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
Boston, MA 02110-1301 USA
|
||||
.
|
||||
On Debian systems, the full text of the GNU General Public
|
||||
License version 3 can be found in the file
|
||||
`/usr/share/common-licenses/GPL-3'.
|
@ -0,0 +1,2 @@
|
||||
scripts/decrypt usr/share/ngcp-ngcpcfg/scripts/
|
||||
scripts/encrypt usr/share/ngcp-ngcpcfg/scripts/
|
@ -0,0 +1 @@
|
||||
testsuite/* usr/share/ngcp-ngcpcfg/testsuite/
|
@ -0,0 +1,19 @@
|
||||
etc/ngcp-config/ngcpcfg.cfg etc/ngcp-config/
|
||||
functions/main usr/share/ngcp-ngcpcfg/functions/
|
||||
helper/build_config usr/share/ngcp-ngcpcfg/helper/
|
||||
helper/fileformat_version usr/share/ngcp-ngcpcfg/helper/
|
||||
helper/sort-yml usr/share/ngcp-ngcpcfg/helper/
|
||||
helper/sync-db usr/share/ngcp-ngcpcfg/helper/
|
||||
helper/tt2-wrapper usr/share/ngcp-ngcpcfg/helper/
|
||||
helper/validate-yml usr/share/ngcp-ngcpcfg/helper/
|
||||
lib/* usr/lib/ngcp-ngcpcfg/
|
||||
sbin/ngcp-network usr/sbin/
|
||||
sbin/ngcpcfg usr/sbin/
|
||||
sbin/ngcp-sync-constants usr/sbin/
|
||||
scripts/build usr/share/ngcp-ngcpcfg/scripts/
|
||||
scripts/commit usr/share/ngcp-ngcpcfg/scripts/
|
||||
scripts/diff usr/share/ngcp-ngcpcfg/scripts/
|
||||
scripts/etckeeper usr/share/ngcp-ngcpcfg/scripts/
|
||||
scripts/initialise usr/share/ngcp-ngcpcfg/scripts/
|
||||
scripts/services usr/share/ngcp-ngcpcfg/scripts/
|
||||
scripts/status usr/share/ngcp-ngcpcfg/scripts/
|
@ -0,0 +1,3 @@
|
||||
ngcpcfg.8
|
||||
ngcp-network.8
|
||||
ngcp-sync-constants.8
|
@ -0,0 +1,31 @@
|
||||
#!/bin/sh
|
||||
# postinst script for ngcp-ngcpcfg
|
||||
|
||||
set -e
|
||||
|
||||
case "$1" in
|
||||
configure)
|
||||
if ! [ -d /etc/.git ] ; then
|
||||
cd /etc
|
||||
etckeeper init
|
||||
git rm --cached -r ngcp-config || true
|
||||
grep -q '^ngcp-config$' .gitignore || echo 'ngcp-config' >> .gitignore
|
||||
git commit -a -m "initial commit"
|
||||
fi
|
||||
;;
|
||||
|
||||
abort-upgrade|abort-remove|abort-deconfigure)
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "postinst called with unknown argument \`$1'" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# dh_installdeb will replace this with shell code automatically
|
||||
# generated by other debhelper scripts.
|
||||
|
||||
#DEBHELPER#
|
||||
|
||||
exit 0
|
@ -0,0 +1,68 @@
|
||||
#!/usr/bin/make -f
|
||||
# -*- makefile -*-
|
||||
# Sample debian/rules that uses debhelper.
|
||||
# This file was originally written by Joey Hess and Craig Small.
|
||||
# As a special exception, when this file is copied by dh-make into a
|
||||
# dh-make output file, you may use that output file without restriction.
|
||||
# This special exception was added by Craig Small in version 0.37 of dh-make.
|
||||
|
||||
# Uncomment this to turn on verbose mode.
|
||||
# export DH_VERBOSE=1
|
||||
|
||||
b=$(CURDIR)/debian/build
|
||||
VERSION:=$(shell dpkg-parsechangelog | awk '/Version: / { print $$2 }')
|
||||
|
||||
build: build-stamp
|
||||
|
||||
build-stamp:
|
||||
dh_testdir
|
||||
$(MAKE) man
|
||||
# catch any syntax errors *before* building the .deb
|
||||
$(MAKE) syntaxcheck
|
||||
touch $@
|
||||
|
||||
clean:
|
||||
dh_testdir
|
||||
dh_testroot
|
||||
rm -rf build-stamp $(b)
|
||||
dh_auto_clean
|
||||
dh_clean
|
||||
|
||||
install: build
|
||||
dh_testdir
|
||||
dh_testroot
|
||||
dh_clean -k
|
||||
dh_installdirs
|
||||
|
||||
%:
|
||||
@echo "--- Building: $@"
|
||||
dh_installdirs -p$@ -P$(b)/$@
|
||||
dh_link -p$@ -P$(b)/$@
|
||||
dh_installdocs -p$@ -P$(b)/$@
|
||||
dh_installman -p$@ -P$(b)/$@
|
||||
dh_installchangelogs -p$@ -P$(b)/$@
|
||||
dh_install -p$@ -P$(b)/$@
|
||||
test -r $(b)/$@/usr/sbin/ngcp-network && \
|
||||
sed -i -e "s/VERSION = 'UNRELEASED'/VERSION = '$(VERSION)'/" \
|
||||
$(b)/$@/usr/sbin/ngcp-network || true
|
||||
dh_link -p$@ -P$(b)/$@
|
||||
dh_strip -p$@ -P$(b)/$@
|
||||
dh_compress --exclude=examples/etc/ --exclude=packages/ -p$@ -P$(b)/$@
|
||||
dh_fixperms -p$@ -P$(b)/$@
|
||||
dh_makeshlibs -p$@ -P$(b)/$@ -V
|
||||
dh_installdeb -p$@ -P$(b)/$@
|
||||
dh_shlibdeps -p$@ -P$(b)/$@
|
||||
dh_installdebconf -p$@ -P$(b)/$@
|
||||
dh_gencontrol -p$@ -P$(b)/$@
|
||||
dh_md5sums -p$@ -P$(b)/$@
|
||||
dh_builddeb -p$@ -P$(b)/$@
|
||||
|
||||
binary-all: build install
|
||||
|
||||
binary-indep: build install \
|
||||
ngcp-ngcpcfg \
|
||||
ngcp-ngcpcfg-locker \
|
||||
ngcp-ngcpcfg-testsuite
|
||||
|
||||
binary: binary-indep binary-arch
|
||||
.PHONY: build clean binary-indep binary-arch binary install
|
@ -0,0 +1 @@
|
||||
1.0
|
@ -0,0 +1,467 @@
|
||||
ngcpcfg(8)
|
||||
==========
|
||||
|
||||
Name
|
||||
----
|
||||
ngcpcfg - central and template based Configuration Management
|
||||
|
||||
Synopsis
|
||||
--------
|
||||
ngcpcfg <action> [ options ]
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
ngcpcfg is a Configuration Management System, developed for the Sipwise Next
|
||||
Generation Platform. It provides a central mechanism for handling configuration
|
||||
changes, updates and synchronisation between servers through a main
|
||||
configuration which is simple and easy to read and modify.
|
||||
|
||||
tl;dr? - ngcpcfg for the impatient
|
||||
----------------------------------
|
||||
|
||||
The main system configuration is done in the file _/etc/ngcp-config/config.yml_.
|
||||
After modifying the file execute 'ngcpcfg apply' to build the accordingly
|
||||
configurations file.
|
||||
|
||||
Taxonomy
|
||||
--------
|
||||
|
||||
*central yml files*:: *.yml files inside _/etc/ngcp-config/_
|
||||
|
||||
*High Availability setup*:: ngcpcfg running in a cluster setup (e.g.
|
||||
sip:providerPRO or sip:carrier), depends on Debian package ngcp-ngcpcfg-ha.
|
||||
|
||||
*local repository*:: the directory _/etc/ngcp-config/_, being a Git repository
|
||||
|
||||
*remote systems*:: the other nodes inside a High Availability setup, as defined
|
||||
in _/etc/ngcp-config/systems.cfg_
|
||||
|
||||
*shared repository*:: Git repository shared amongst nodes inside a High
|
||||
Availability setup, as defined by the GLUSTERFS setting in
|
||||
/etc/ngcp-config/ngcpcfg.d/shared_storage.cfg (requires ngcp-ngcpcfg-ha) and
|
||||
being _/mnt/glusterfs_ by default
|
||||
|
||||
*templates*:: template toolkit files with .tt2 suffix, found in
|
||||
_/etc/ngcp-config/templates/etc/_
|
||||
|
||||
[[configfiles]]
|
||||
Configuration files
|
||||
-------------------
|
||||
|
||||
Main configuration files
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
* _/etc/ngcp-config/config.yml_: central configuration file, to be configured with
|
||||
$EDITOR, webfrontend,...
|
||||
|
||||
* _/etc/ngcp-config/config.$HOSTNAME.yml_: host specific configuration file,
|
||||
depending on the hostname (:= $HOSTNAME) of the system.
|
||||
|
||||
* _/etc/ngcp-config/config.local.yml_: local configuration, not being host
|
||||
specific.
|
||||
|
||||
* _/etc/ngcp-config/constants.yml_: configuration file that has precedence over
|
||||
any other .yml file _/etc/ngcp-config/_, defining important constant settings.
|
||||
This file is *not* supposed to be modified by the user (without having a very
|
||||
good reason).
|
||||
|
||||
* _/etc/ngcp-config/ngcpcfg.cfg_: main configuration file for ngcpcfg itself,
|
||||
provides global variables used inside ngcpcfg and its helper scripts. This file
|
||||
is *not* supposed to be modified by the user (without having a very good
|
||||
reason).
|
||||
|
||||
* _/etc/ngcp-config/ngcpcfg.d/_: configuration directory for ngcpcfg itself.
|
||||
Files with suffix '.cfg' inside this directory are sourced after
|
||||
/etc/ngcp-config/ngcpcfg.cfg has been read. Files inside this directory are
|
||||
*not* supposed to be modified by the user (without having a very good reason).
|
||||
|
||||
[IMPORTANT]
|
||||
Configuration file priority: constants.yml takes precedence over
|
||||
config.local.yml, over config.$HOSTNAME.yml, over config.yml.
|
||||
|
||||
High Availability setup specific configuration files
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
* _/etc/ngcp_ha_node_: defines node name in the High Availability setup, usually
|
||||
being _sp1_ for the first node and _sp2_ for the second node.
|
||||
|
||||
* _/etc/ngcp-config/systems.cfg_: configuration file that specifies to which
|
||||
hosts changes should be pushed to.
|
||||
|
||||
Supported template files
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Example for generating a configuration file named_/etc/foobar/baz_:
|
||||
|
||||
* _/etc/ngcp-config/templates/etc/foobar/baz.tt2_: main and default template
|
||||
file, used by template-handler for generating /etc/foobar/baz. Configuration
|
||||
file is usually provided by a Debian package.
|
||||
|
||||
* _/etc/ngcp-config/templates/etc/foobar/baz.customtt.tt2_: system specific
|
||||
template file, but configuration usually isn't provided by a Debian package and
|
||||
can be modified independent from any Debian package mechanism.
|
||||
|
||||
* _/etc/ngcp-config/templates/etc/foobar/baz.tt2.$HA_NODE_: node specific
|
||||
template file. $HA_NODE is determined using the content of /etc/ngcp_ha_node
|
||||
(usually being _sp1_ for the first node and _sp2_ for the second node on the
|
||||
Sipwise Next Generation Platform). Wheras _*customtt.tt2_ files are used on all
|
||||
nodes in a High Availability setup the _*.tt2.$HA_NODE*_ file is specific for
|
||||
the single node only. A common usage case is master vs. slave configuration of a
|
||||
service. Configuration file is usually provided by a Debian package. Note:
|
||||
Feature is available in the High Availability setup only.
|
||||
|
||||
* _/etc/ngcp-config/templates/etc/foobar/baz.customtt.tt2.$HA_NODE_: node
|
||||
specific template file. Regarding $HA_NODE the same as for _baz.tt2.$HA_NODE_
|
||||
applies (see previous bullet), but the configuration file usually isn't provided
|
||||
by a Debian package but can be modified independent from any Debian package
|
||||
mechanism. Note: Feature is available in the High Availability setup only.
|
||||
|
||||
[IMPORTANT]
|
||||
Configuration file priority: *.customtt.tt2.$HA_NODE takes precedence over
|
||||
*.customtt.tt2, over *.tt2.$HA_NODE, over *.tt2.
|
||||
|
||||
Support action related files
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Example for handling a configuration file named _/etc/foobar/baz_:
|
||||
|
||||
* _/etc/ngcp-config/templates/etc/foobar/baz.services_: service file, defining
|
||||
actions that have to be executed when file /etc/foobar/baz was modified.
|
||||
|
||||
* _/etc/ngcp-config/templates/etc/foobar/ngcpcfg.services_: service file,
|
||||
defining actions that have to be executed whenever *any* file inside /etc/foobar
|
||||
was modified.
|
||||
|
||||
* _/etc/ngcp-config/templates/etc/foobar/baz.postbuild_: script which is
|
||||
executed *after* a configuration file (/etc/foobar/baz) has been generated. The
|
||||
environment variable "$output_file" containing the file name of the generated
|
||||
configuration file (/etc/foobar/baz) is available within the postbuild script. A
|
||||
common usage case for postbuild files is adjusting file permissions.
|
||||
|
||||
* _/etc/ngcp-config/templates/etc/foobar/baz.prebuild_: script which is
|
||||
executed *before* a configuration file (/etc/foobar/baz) is generated. The
|
||||
environment variable "$output_file" containing the file name of the generated
|
||||
configuration file (/etc/foobar/baz) is available within the postbuild script.
|
||||
|
||||
Syntax and layout of configuration files
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
* _/etc/ngcp-config/ngcpcfg.cfg_: plain shell syntax style "key=value" entries
|
||||
|
||||
* _/etc/ngcp-config/systems.cfg_: one hostname or IP address per line
|
||||
|
||||
* _central yml files_ (*.yml): YAML configuration syntax (see http://yaml.org/)
|
||||
|
||||
* _template files_ (*.tt2): whatever the according software (Kamailio,
|
||||
MySQL,...) needs. Any variables that should be replaced by the configuration
|
||||
management system (based on the main configuration files *.yml inside
|
||||
/etc/ngcp-config/) have to be written in the YAML syntax (see http://yaml.org/)
|
||||
|
||||
* _service files_ (*.services) and _build files_ ({post,pre}build): file will be
|
||||
executed under "bash $FILE", so you can use commands e.g. like
|
||||
"/etc/init.d/foobar restart" and any further shell scripting syntax inside the
|
||||
services files
|
||||
|
||||
Options
|
||||
-------
|
||||
|
||||
**--debug** <action> [<further_options>]::
|
||||
|
||||
Run actions (see next section) in verbose mode, useful for debugging.
|
||||
|
||||
**--help**::
|
||||
|
||||
Display usage information and exit.
|
||||
|
||||
**--version**::
|
||||
|
||||
Display ngcpcfg version and exit.
|
||||
|
||||
Actions
|
||||
-------
|
||||
|
||||
**apply**::
|
||||
|
||||
Executes the _build_, _services_ and _commit_ commands in a batch (assuming each
|
||||
command worked as expected). This option serves as a shortcut for the most
|
||||
commonly executed commands.
|
||||
|
||||
**build** [--modified-only] [<files_or_directories>|<pattern>]::
|
||||
|
||||
Generate configuration files, based on values defined the central yml files and
|
||||
based on the templates in the configuration tree (/etc/ngcp-config/templates by
|
||||
default). The *--modified-only* option checks for _modified_ and _uncommitted_
|
||||
configuration files (central yml files and templates) and builds the relevant
|
||||
files only. If a central yml file is modified it builds all configuration files.
|
||||
If changes are in template files only just the according template files are
|
||||
considered for rebuild. If a file (e.g. _/etc/rsyslog.conf_) or directory (e.g.
|
||||
_/etc/mysql/_) is provided as argument to the _build_ option only the specified
|
||||
file / files inside the directory will be generated. If the argument doesn't
|
||||
start with the /etc prefix the argument is considered as pattern, matching all
|
||||
files/directories which include the specified pattern. The pattern can include
|
||||
shell globbing patterns - so argument 'mo..t' will match the files
|
||||
/etc/ngcp-monitoring-tools/collective-check.conf, /etc/monit/monitrc,
|
||||
/etc/ha.d/resource.d/monit-services and /etc/default/monit iff they are present.
|
||||
You can combine _<files_or_directories>_ and _<pattern>_ and use multiple
|
||||
arguments.
|
||||
|
||||
**commit** [<commit_message>]::
|
||||
|
||||
Commit all modified files in _/etc/ngcp-config_ and record changes in _/etc_ by
|
||||
executing the etckeeper(8) command through
|
||||
'/usr/share/ngcp-ngcpcfg/scripts/etckeeper'. To check whether there are any
|
||||
pending changes to be committed execute 'ngcpcfg status'.
|
||||
|
||||
**decrypt**::
|
||||
|
||||
Decrypt /etc/ngcp-config-crypted.tgz.gpg and restore configuration files,
|
||||
doing the reverse operation of the _encrypt_ option.
|
||||
Note: This feature is only available if the ngcp-ngcpcfg-locker package is
|
||||
installed.
|
||||
|
||||
**diff** [<options_for_git_diff>]::
|
||||
|
||||
Show changes between ngcpcfg's Git repository and the working tree inside
|
||||
_/etc/ngcp-config_. You can specify options for the underlying 'git diff'
|
||||
command, e.g. 'ngcpcfg diff HEAD^' will show all changes that have been recorded
|
||||
with the last _commit_ operation (see manpage git-rev-parse(1) for details how
|
||||
to specify revisions). If the tool doesn't report anything it means that there
|
||||
are neither any uncommited changes nor any new or removed files (files which are
|
||||
not yet (un)registered to the repository).
|
||||
|
||||
**encrypt**::
|
||||
|
||||
Encrypt /etc/ngcp-config and all resulting configuration files with a user
|
||||
defined password and save the result as /etc/ngcp-config-crypted.tgz.gpg.
|
||||
Note: This feature is only available if the ngcp-ngcpcfg-locker package is
|
||||
installed.
|
||||
|
||||
**help**::
|
||||
|
||||
Display usage information and exit.
|
||||
|
||||
**initialise**::
|
||||
|
||||
If ngcpcfg was installed but isn't configured yet the 'initialise' option sets
|
||||
up ngcpcfg accordingly. Follow the instructions from the <<setup_instructions,
|
||||
Setup instructions>> section.
|
||||
|
||||
**init-mgmt** <server>::
|
||||
|
||||
Set up specified '<server>' for usage as shared repository whereas '<server>'
|
||||
usually corresponds to the IP/hostname of the central management system in a
|
||||
sip:carrier environment. Further details about the details of the setup
|
||||
are available in the <<init-mgmt>> section.
|
||||
Note: This feature is only available if the ngcp-ngcpcfg-carrier package is installed.
|
||||
|
||||
**pull**::
|
||||
|
||||
Retrieve modifications from shared repository.
|
||||
Note: This option is available in the High Availability setup only.
|
||||
|
||||
**push** [--nobuild] [--noapply] [--shared-only] [<host(s)>]::
|
||||
|
||||
Push modifications to shared repository and remote systems. After changes have been
|
||||
pushed to the node the _apply_ operation will be executed on each remote system
|
||||
to rebuild the configuration files (unless the '--noapply' operation has been
|
||||
specified, then only the _build_ operation will be executed). To skip building
|
||||
any configuration files at all the '--nobuild' option can be specified (implying
|
||||
to also skip the _apply_ operation). If the '--shared-only' option is set then
|
||||
the any pending commits will be pushed only to the shared repository only, any
|
||||
foreign hosts will be skipped then. If hostname(s) or IP address(es) is given
|
||||
as argument then the changes will be pushed to the shared repository and to the
|
||||
given hosts only. If no host has has been specified then the hosts specified in
|
||||
_/etc/ngcp-config/systems.cfg_ are used.
|
||||
Note: This option is available in the High Availability setup only.
|
||||
|
||||
**services** [--dry-run]::
|
||||
|
||||
Execute any defined service actions for modified configuration files. If the
|
||||
_--dry-run_ option is present the services won't be executed but you'll be
|
||||
noticed which service files would be executed if being invoked without the
|
||||
_--dry-run__ option.
|
||||
|
||||
**status**::
|
||||
|
||||
Display the current state of the configuration system, like modified
|
||||
configuration files and pending actions.
|
||||
|
||||
|
||||
Usage examples
|
||||
--------------
|
||||
|
||||
The main workflow *without* High Availability setup is:
|
||||
|
||||
ngcpcfg status # check for pending operations
|
||||
$EDITOR /etc/ngcp-config/config.yml # adjust/extend configuration
|
||||
ngcpcfg apply "summary of changes" # build configs, run services + commit changes
|
||||
|
||||
If you do not want to execute the _apply_ shortcut command but instead run the
|
||||
single actions, then you can execute:
|
||||
|
||||
ngcpcfg status # check for pending operations
|
||||
$EDITOR /etc/ngcp-config/config.yml # adjust/extend configuration
|
||||
ngcpcfg build # generate/update configuration files
|
||||
ngcpcfg services # restart services for modified configs
|
||||
ngcpcfg commit "summary of changes" # register changes
|
||||
|
||||
The main workflow *with* High Availability setup is:
|
||||
|
||||
ngcpcfg status # check for pending operations
|
||||
ngcpcfg pull # retrieve possibly pending updates
|
||||
$EDITOR /etc/ngcp-config/config.yml # adjust/extend configuration
|
||||
ngcpcfg build # generate/update configuration files
|
||||
ngcpcfg services # restart services for modified configs
|
||||
ngcpcfg commit "summary of changes" # register changes
|
||||
ngcpcfg push # upload changes to shared storage + remote systems
|
||||
ngcpcfg status # check for possibly outstanding issues
|
||||
|
||||
[[faq]]
|
||||
Frequently asked questions
|
||||
--------------------------
|
||||
|
||||
What does ngcpcfg mean?
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
'ngcp' is the http://www.sipwise.com/[Sipwise Next Generation Communication
|
||||
Platform] and 'cfg' stands for the ConFiGuration management system of the
|
||||
ngcp system.
|
||||
|
||||
Does ngcpcfg require a shared storage?
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Only if you are using ngcpcfg in a High Availability setup and using the 'push'
|
||||
functionality (which is highly recommended in a HA Setup).
|
||||
|
||||
How does the configuration management system work?
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
ngcpcfg takes the central yml files (/etc/ngcp-config/*.yml) as input for
|
||||
configuration, searches for supported templates files (*.tt2) in the template
|
||||
pool (_/etc/ngcp-config/templates/etc/_) and builds the resulting configuration
|
||||
files in _/etc_.
|
||||
|
||||
[[errorhandling]]
|
||||
Error handling - what does this error message mean?
|
||||
---------------------------------------------------
|
||||
|
||||
Error message:
|
||||
|
||||
Error: Failed hosts: hostname (down)
|
||||
|
||||
Background: The system "hostname" is not reachable via ICMP, which means it's
|
||||
not reachable for the ngcpcfg system.
|
||||
|
||||
How to fix: Make sure the system is up and running and reachable via ssh from
|
||||
the system where you are running the "pull" action.
|
||||
|
||||
Error message:
|
||||
|
||||
error: Your local changes to 'config.yml' would be overwritten by merge. Aborting.
|
||||
|
||||
Background: the file 'config.yml' (in this example) on the system where you are
|
||||
pushing to contains local modifications which are uncommitted yet. To avoid data
|
||||
damage the system can't resolve this situation automatically.
|
||||
|
||||
How to fix:
|
||||
|
||||
1) Throw away the changes on the remote system (where you are pushing to,
|
||||
important: your changes on the system where you are executing the commands will
|
||||
be gone!):
|
||||
|
||||
cd /etc/ngcp-config ; git checkout -- config.yml
|
||||
|
||||
To get rid of *any* modified files (included added/removed files) the following
|
||||
commands will do the job (use with care and only execute it if you're aware of
|
||||
the consequences):
|
||||
|
||||
cd /etc/ngcp-config
|
||||
git checkout -- .
|
||||
git clean -xdf
|
||||
|
||||
2) Resolve the merge conflict:
|
||||
|
||||
cd /etc/ngcp-config
|
||||
git pull
|
||||
$EDITOR config.yml # resolve conflict
|
||||
ngcpcfg commit 'merge conflict on system sp2'
|
||||
ngcpcfg pull # just to make sure
|
||||
ngcpcfg push # push changes back to the other systems
|
||||
|
||||
[[init-mgmt]]
|
||||
init-mgmt setup
|
||||
---------------
|
||||
|
||||
This section documents the 'ngcpcfg init-mgmt' feature in more detail.
|
||||
The feature is provided through the ngcp-ngcpcfg-carrier package.
|
||||
|
||||
The script deprecates the shared repository /mnt/glusterfs/ngcpcfg-share of the
|
||||
local system by renaming it to /mnt/glusterfs/ngcpcfg-share.unused. It then
|
||||
registers the two according nodes (the local system plus the second node which
|
||||
makes the PRO pair) in /etc/ngcp-config/systems.cfg. It sets the 'mgmgt_server'
|
||||
variable in /etc/ngcp-config/carrier.cfg to '<server>'. Then it makes sure that
|
||||
the automated login via SSH between the two according nodes as well as the
|
||||
<server> works. It clones the local shared repository to the '<server>'. Finally
|
||||
it updates the remote origin for the shared repository on both nodes to point to
|
||||
'<server>:/mnt/glusterfs/ngcpcfg_<role>' whereas '<role>' corresponds to the
|
||||
system's hostname without the trailing 'a' and 'b' suffix.
|
||||
|
||||
[NOTE]
|
||||
To check which remote repository is in use execute
|
||||
'cd /etc/ngcp-config; git remote show origin | grep URL'.
|
||||
|
||||
[[setup_instructions]]
|
||||
Setup instructions
|
||||
------------------
|
||||
|
||||
Requirements for High Availability setup:
|
||||
|
||||
* glusterfs is supposed to be set up working and deployed at /mnt/glusterfs
|
||||
(as defined via /etc/ngcp-config/ngcpcfg.cfg)
|
||||
|
||||
* hosts are expected to be set up for automatic ssh login (ssh-keygen && ssh-copy-id)
|
||||
|
||||
* node names are expected to be sp1 and sp2 so the .tt2.sp1 and .tt2.sp2
|
||||
template files are supported
|
||||
|
||||
Configuration on sp1 (expected to be master node in initial setup):
|
||||
|
||||
ngcpcfg initialise
|
||||
ngcpcfg build
|
||||
printf "sp1\nsp2\n" > /etc/ngcp-config/systems.cfg
|
||||
ngcpcfg commit "provide systems.cfg"
|
||||
|
||||
Configuration on sp2 (and any further existing system):
|
||||
|
||||
ngcpcfg initialise
|
||||
ngcpcfg build
|
||||
|
||||
Please note that you do not have to run this steps if you are using the Sipwise
|
||||
Next Generation Platform since the installation steps are fully automated.
|
||||
|
||||
Involved frameworks
|
||||
-------------------
|
||||
|
||||
* git: Distributed Version Control system
|
||||
* tt2: Template Toolkit
|
||||
* make: Utility for Directing compilation
|
||||
* yaml: Generic data serialization language
|
||||
|
||||
Limitations
|
||||
-----------
|
||||
|
||||
ngcpcfg was designed specifically for the Sipwise Next Generation Platform,
|
||||
though with being as generic as possible in mind. The system is supposed to be
|
||||
useful for configuration management on other systems/platforms and it's possible
|
||||
to adapt it for different needs through a variety of configuration parameters,
|
||||
though keep in mind that ngcpcfg was implemented for some very specific use
|
||||
cases.
|
||||
|
||||
Author
|
||||
------
|
||||
Michael Prokop <mprokop@sipwise.com>
|
||||
|
||||
/////////////////////////////
|
||||
// vim: ft=asciidoc tw=80 ai
|
||||
/////////////////////////////
|
@ -0,0 +1,22 @@
|
||||
# Filename: /etc/ngcp-config/ngcpcfg.cfg
|
||||
# Purpose: main configuration file for ngcpcfg tools
|
||||
# Note: do not modify unless you have a really good reason to do so
|
||||
|
||||
# directory name where ngcpcfg is managed through git
|
||||
NGCPCTL_MAIN='/etc/ngcp-config'
|
||||
NGCPCTL_CONFIG="${NGCPCTL_MAIN}/config.yml"
|
||||
HOST_CONFIG="${NGCPCTL_MAIN}/config.$(hostname).yml"
|
||||
LOCAL_CONFIG="${NGCPCTL_MAIN}/config.local.yml"
|
||||
CONSTANTS_CONFIG="${NGCPCTL_MAIN}/constants.yml"
|
||||
NETWORK_CONFIG="${NGCPCTL_MAIN}/network.yml"
|
||||
|
||||
# configuration files that should be managed
|
||||
CONFIG_POOL='/etc'
|
||||
|
||||
# location of templates
|
||||
TEMPLATE_POOL="${NGCPCTL_MAIN}/templates/${CONFIG_POOL}"
|
||||
|
||||
# location of service definitions
|
||||
SERVICES_POOL="${NGCPCTL_MAIN}/templates/${CONFIG_POOL}"
|
||||
|
||||
## END OF FILE #################################################################
|
@ -0,0 +1,192 @@
|
||||
# Filename: /usr/share/ngcp-ngcpcfg/functions/main
|
||||
# Purpose: helper functions for ngcpcfg
|
||||
################################################################################
|
||||
|
||||
## logging functions {{{
|
||||
log_info() {
|
||||
logger -t ngcpcfg -- "$*"
|
||||
echo "$*"
|
||||
}
|
||||
|
||||
# info without ending newline
|
||||
log_info_n() {
|
||||
logger -t ngcpcfg -- "$*"
|
||||
printf -- "$*"
|
||||
}
|
||||
|
||||
log_warn() {
|
||||
logger -t ngcpcfg -- "Warning: $*"
|
||||
echo "Warning: $*"
|
||||
}
|
||||
|
||||
log_error() {
|
||||
logger -t ngcpcfg -- "Error: $*"
|
||||
echo "Error: $*" >&2
|
||||
}
|
||||
|
||||
log_debug() {
|
||||
if [ -n "${DEBUG:-}" ] ; then
|
||||
logger -t ngcpcfg -- "Debug: $*"
|
||||
echo ; echo "DEBUG: $*" ; echo # newlines to avoid messup with cmdline output
|
||||
fi
|
||||
}
|
||||
## }}}
|
||||
|
||||
## important variables we depend on to operate successfully {{{
|
||||
# support test suite which requires system independent configuration
|
||||
if [ -r ngcpcfg-testsuite.cfg ] ; then
|
||||
. ngcpcfg-testsuite.cfg
|
||||
else
|
||||
if [ -r /etc/ngcp-config/ngcpcfg.cfg ] ; then
|
||||
log_debug "sourcing configuration file /etc/ngcp-config/ngcpcfg.cfg"
|
||||
. /etc/ngcp-config/ngcpcfg.cfg
|
||||
|
||||
if [ -d /etc/ngcp-config/ngcpcfg.d ] ; then
|
||||
for file in /etc/ngcp-config/ngcpcfg.d/*.cfg ; do
|
||||
if test -r $file ; then
|
||||
log_debug "sourcing configuration file $file"
|
||||
. $file
|
||||
fi
|
||||
done
|
||||
fi
|
||||
elif [ -r /etc/ngcp-config-crypted.tgz.gpg ] ; then
|
||||
log_error "Configuration pool locked. Please contact your distributor. Exiting."
|
||||
exit 1
|
||||
else
|
||||
log_error "Could not read configuration file /etc/ngcp-config/ngcpcfg.cfg. Exiting."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if ! [ -r "$NGCPCTL_CONFIG" ] ; then
|
||||
log_error "Configuration file ${NGCPCTL_CONFIG} does not exist (unconfigured?) - exiting."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! [ -r "$CONSTANTS_CONFIG" ] ; then
|
||||
log_error "Constants file ${CONSTANTS_CONFIG} does not exist (unconfigured?) - exiting."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! [ -n "${NETWORK_CONFIG:-}" ] ; then
|
||||
log_warn "NETWORK_CONFIG is not configured in $NGCPCTL_CONFIG - continuing anyway."
|
||||
elif ! [ -r "$NETWORK_CONFIG" ] ; then
|
||||
log_error "Constants file ${NETWORK_CONFIG} does not exist (unconfigured?) - exiting."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! [ -d "$TEMPLATE_POOL" ] ; then
|
||||
log_error "No template directory (${TEMPLATE_POOL}) found - exiting."
|
||||
exit 1
|
||||
fi
|
||||
## }}}
|
||||
|
||||
## environment variables {{{
|
||||
export PN="ngcpcfg"
|
||||
export HNAME="$(hostname)"
|
||||
|
||||
# avoid warnings by perl script complaining about locales
|
||||
export LANG=C
|
||||
export LC_ALL=C
|
||||
|
||||
# make sure it's available in all helper scripts
|
||||
[ -n "${DEBUG:-}" ] && export DEBUG
|
||||
|
||||
# export for access via build_config etc
|
||||
export CONFIG_POOL
|
||||
export HOST_CONFIG
|
||||
export LOCAL_CONFIG
|
||||
export NGCPCTL_CONFIG
|
||||
export CONSTANTS_CONFIG
|
||||
export NETWORK_CONFIG
|
||||
## }}}
|
||||
|
||||
## HA / carrier features {{{
|
||||
if [ -r /usr/share/ngcp-ngcpcfg/functions/ha_features ] ; then
|
||||
. /usr/share/ngcp-ngcpcfg/functions/ha_features
|
||||
set_ha_file # set $HA_FILE for usage in generate_template_list
|
||||
fi
|
||||
|
||||
if [ -r /usr/share/ngcp-ngcpcfg/functions/carrier_features ] ; then
|
||||
. /usr/share/ngcp-ngcpcfg/functions/carrier_features
|
||||
fi
|
||||
## }}}
|
||||
|
||||
## functions {{{
|
||||
generate_template_list() {
|
||||
[ -n "$TEMPLATE_POOL" ] || return 1
|
||||
|
||||
local filelist_prepared=$(mktemp)
|
||||
local filelist_final=$(mktemp)
|
||||
|
||||
# iterate over all files
|
||||
for file in $(find "$TEMPLATE_POOL" -name \*.tt2 -o -name \*.tt2"${HA_FILE:-}") ; do
|
||||
# *NO* arguments provided via cmdline
|
||||
if [ -z "${1:-}" ] ; then
|
||||
echo "$file" >> "${filelist_prepared}"
|
||||
else
|
||||
# arguments (file list/pattern) provided via cmdline
|
||||
for arg in $* ; do
|
||||
if echo $file | grep -q "${arg}" ; then
|
||||
echo "$file" >> "${filelist_prepared}"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
done
|
||||
|
||||
# remove all filenames where a preferred filename exists
|
||||
# foo.customtt.tt2.spX > foo.customtt.tt2 > foo.tt2.spX > foo.tt2
|
||||
for line in $(cat ${filelist_prepared}); do
|
||||
|
||||
# reduce filenames from "foo.*" to "foo"
|
||||
if [ -n "${HA_FILE:-}" ] ; then
|
||||
normalized_filename="${line%${HA_FILE}}"
|
||||
else
|
||||
normalized_filename="${line}"
|
||||
fi
|
||||
normalized_filename="${normalized_filename%.customtt.tt2}"
|
||||
normalized_filename="${normalized_filename%.tt2}"
|
||||
|
||||
# foo.customtt.tt2.sp{1,2}
|
||||
if [ -n "${HA_FILE:-}" ] ; then
|
||||
if grep -q "^${normalized_filename}.customtt.tt2${HA_FILE:-}" "${filelist_prepared}" ; then
|
||||
echo "${normalized_filename}.customtt.tt2${HA_FILE:-}" >> "${filelist_final}"
|
||||
continue
|
||||
fi
|
||||
fi
|
||||
|
||||
# foo.customtt.tt2
|
||||
if grep -q "^${normalized_filename}.customtt.tt2$" "${filelist_prepared}" ; then
|
||||
echo "${normalized_filename}.customtt.tt2" >> "${filelist_final}"
|
||||
continue
|
||||
fi
|
||||
|
||||
# foo.tt2.sp{1,2}
|
||||
if [ -n "${HA_FILE:-}" ] ; then
|
||||
if grep -q "^${normalized_filename}.tt2${HA_FILE}" "${filelist_prepared}" ; then
|
||||
echo "${normalized_filename}.tt2${HA_FILE}" >> "${filelist_final}"
|
||||
continue
|
||||
fi
|
||||
fi
|
||||
|
||||
# file should be used, so list it
|
||||
echo "$line" >> "${filelist_final}"
|
||||
done
|
||||
|
||||
# output file list, make sure we provide the file names just once
|
||||
sort -u ${filelist_final}
|
||||
|
||||
if [ -n "${DEBUG:-}" ] ; then
|
||||
# send to stderr since stdout is used from outside
|
||||
log_debug "Not removing temporary filelist files since we are in debug mode:" >&2
|
||||
log_debug " filelist_prepared = ${filelist_prepared}" >&2
|
||||
log_debug " filelist_final = ${filelist_final}" >&2
|
||||
else
|
||||
rm -f "${filelist_prepared}" "${filelist_final}"
|
||||
fi
|
||||
|
||||
unset filelist_prepared filelist_final
|
||||
}
|
||||
## }}}
|
||||
|
||||
## END OF FILE #################################################################
|
@ -0,0 +1,102 @@
|
||||
#!/bin/bash
|
||||
# Filename: /usr/share/ngcp-ngcpcfg/helper/build_config
|
||||
# Purpose: builds output configuration file based on tt2 template file
|
||||
# using /usr/share/ngcp-ngcpcfg/helper/tt2-wrapper
|
||||
################################################################################
|
||||
|
||||
set -e
|
||||
set -u
|
||||
|
||||
if [ "${#:-}" -ne 1 ] ; then
|
||||
echo "Usage: /usr/share/ngcp-ngcpcfg/helper/build_config <input_file>" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "${CONFIG_POOL:-}" ] ; then
|
||||
echo "Error: $CONFIG_POOL is not set." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# support for testsuite
|
||||
if [ -z "${FUNCTIONS:-}" ] ; then
|
||||
FUNCTIONS='/usr/share/ngcp-ngcpcfg/functions/'
|
||||
fi
|
||||
|
||||
if [ -z "${HELPER:-}" ] ; then
|
||||
HELPER='/usr/share/ngcp-ngcpcfg/helper/'
|
||||
fi
|
||||
|
||||
. ${FUNCTIONS}/main
|
||||
|
||||
# main script
|
||||
|
||||
input_file="$1" # like /etc/ngcp-config/templates/etc/mysql/my.cnf.tt2
|
||||
# calculate output file {{{
|
||||
x=${input_file##${NGCPCTL_MAIN}/templates/} # drop leading /etc/ngcp-config
|
||||
y=${x%%.tt2} # drop trailing suffix '.tt2'
|
||||
[ -n "${HA_FILE:-}" ] && y=${y%%.tt2${HA_FILE}} # drop trailing suffix '.tt2.sp{1,2}'
|
||||
y=${y%%.customtt} # drop trailing suffix '.customtt'
|
||||
# }}}
|
||||
export output_file="${y}" # like /etc/mysql/my.cnf, export variable
|
||||
# for usage within {pre,post}build scripts
|
||||
|
||||
# pre-execution script in template store:
|
||||
if [ -r "${NGCPCTL_MAIN}/templates/${output_file}.prebuild" ] ; then
|
||||
log_info "Executing prebuild for ${output_file}"
|
||||
bash "${NGCPCTL_MAIN}/templates/${output_file}.prebuild"
|
||||
elif [ -r "${NGCPCTL_MAIN}/templates/$(dirname ${output_file})/ngcpcfg.prebuild" ] ; then
|
||||
log_info "Executing prebuild for ${output_file}"
|
||||
bash "${NGCPCTL_MAIN}/templates/$(dirname ${output_file})/ngcpcfg.prebuild"
|
||||
fi
|
||||
|
||||
# if output directory does not exist yet, create it
|
||||
if ! [ -d "$(dirname ${output_file})" ] ; then
|
||||
umask 0022 # directory permissions should be '755'
|
||||
mkdir -p "$(dirname ${output_file})"
|
||||
fi
|
||||
|
||||
# assume safe defaults
|
||||
umask 0077
|
||||
|
||||
# read host specific configuration file only if it exists
|
||||
[ -r "${HOST_CONFIG:-}" ] && host_conf="$HOST_CONFIG"
|
||||
|
||||
# read local config only if it exists
|
||||
[ -r "${LOCAL_CONFIG:-}" ] && local_conf="$LOCAL_CONFIG"
|
||||
|
||||
TT_WRAPPER="${HELPER}/tt2-wrapper"
|
||||
|
||||
log_debug "Output file ${output_file} based on ${input_file}"
|
||||
log_debug "Executing: $TT_WRAPPER ${input_file} ${host_conf:-} ${local_conf:-} $NGCPCTL_CONFIG ${NETWORK_CONFIG:-} $CONSTANTS_CONFIG > ${output_file}"
|
||||
if "$TT_WRAPPER" "${input_file}" ${host_conf:-} ${local_conf:-} "$NGCPCTL_CONFIG" "${NETWORK_CONFIG:-}" "$CONSTANTS_CONFIG" > "${output_file}" 2>/dev/null ; then
|
||||
log_info "Generating ${output_file}: OK"
|
||||
RC=0
|
||||
else
|
||||
log_error "Generating ${output_file} based on ${input_file}: FAILED"
|
||||
RC=1
|
||||
|
||||
log_info "NOTE: Check those files for valid syntax and encoding:"
|
||||
for f in "${input_file}" ${host_conf:-} ${local_conf:-} "$NGCPCTL_CONFIG" "${NETWORK_CONFIG:-}" "$CONSTANTS_CONFIG" ; do
|
||||
[ -r "$f" ] && log_info "$f"
|
||||
done
|
||||
log_info "Running /usr/share/ngcp-ngcpcfg/helper/tt2-wrapper <file> should provide more details."
|
||||
|
||||
fi
|
||||
|
||||
# set permissions for generated config based on the ones of the template
|
||||
chmod --reference="${input_file}" "${output_file}"
|
||||
# finally drop all write permissions
|
||||
chmod a-w "${output_file}"
|
||||
|
||||
# post-execution script in template store:
|
||||
if [ -r "${NGCPCTL_MAIN}/templates/${output_file}.postbuild" ] ; then
|
||||
log_info "Executing postbuild for ${output_file}"
|
||||
bash "${NGCPCTL_MAIN}/templates/${output_file}.postbuild"
|
||||
elif [ -r "${NGCPCTL_MAIN}/templates/$(dirname ${output_file})/ngcpcfg.postbuild" ] ; then
|
||||
log_info "Executing postbuild for ${output_file}"
|
||||
bash "${NGCPCTL_MAIN}/templates/$(dirname ${output_file})/ngcpcfg.postbuild"
|
||||
fi
|
||||
|
||||
exit $RC
|
||||
|
||||
## END OF FILE #################################################################
|
@ -0,0 +1,21 @@
|
||||
#!/usr/bin/perl
|
||||
# Purpose: report internal->fileformat setting of /etc/ngcp-config/config.yml
|
||||
################################################################################
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use YAML::Tiny;
|
||||
my $yaml = YAML::Tiny->new;
|
||||
$yaml = YAML::Tiny->read("/etc/ngcp-config/config.yml");
|
||||
my $fileformat = $yaml->[0]->{internal}->{fileformat};
|
||||
|
||||
if (defined $fileformat) {
|
||||
print "$fileformat\n";
|
||||
exit 0;
|
||||
} else {
|
||||
print "undefined\n";
|
||||
exit 1;
|
||||
}
|
||||
|
||||
## END OF FILE #################################################################
|
@ -0,0 +1,18 @@
|
||||
#!/usr/bin/perl -CSD
|
||||
# Purpose: sort yaml configuration file
|
||||
################################################################################
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use YAML::Tiny;
|
||||
|
||||
my $yaml = YAML::Tiny->new;
|
||||
my $inputfile = shift or die 'You did not specify an input file name';
|
||||
my $outputfile = shift or die 'You did not specify an ouput file name';
|
||||
|
||||
$yaml = YAML::Tiny->read($inputfile);
|
||||
|
||||
open(my $fh, '>', "$outputfile") or die "Could not open $outputfile for writing";
|
||||
print $fh $yaml->write_string() or die "Could not write YAML to $outputfile";
|
||||
|
||||
## END OF FILE #################################################################
|
@ -0,0 +1,188 @@
|
||||
#!/usr/bin/perl -CSD
|
||||
# Purpose: template toolkit helper script
|
||||
################################################################################
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use YAML qw/LoadFile/;
|
||||
use Template;
|
||||
use Hash::Merge qw(merge);
|
||||
use DBI;
|
||||
|
||||
sub sync_extra_sockets;
|
||||
|
||||
my $tt = Template->new({ ABSOLUTE => 1, RELATIVE => 1 });
|
||||
|
||||
my $config = {};
|
||||
foreach my $file (@ARGV) {
|
||||
$config = merge($config, LoadFile($file) || die $!);
|
||||
}
|
||||
|
||||
open my $SWFH, '<', '/etc/mysql/sipwise.cnf';
|
||||
my $dbpass = join ' ', <$SWFH>;
|
||||
close $SWFH;
|
||||
$dbpass =~ s/^.*SIPWISE_DB_PASSWORD=\'([^\']+)\'.*$/$1/;
|
||||
chomp $dbpass;
|
||||
my $dbuser = 'sipwise';
|
||||
my $dbname = $config->{ossbss}->{provisioning}->{database}->{name};
|
||||
|
||||
unless(defined $dbname) {
|
||||
print "Could not determine provisioning db name\n";
|
||||
exit 1;
|
||||
}
|
||||
unless(defined $dbuser) {
|
||||
print "Could not determine provisioning db user\n";
|
||||
exit 1;
|
||||
}
|
||||
unless(defined $dbpass) {
|
||||
print "Could not determine provisioning db password\n";
|
||||
exit 1;
|
||||
}
|
||||
|
||||
my $dbh = DBI->connect('DBI:mysql:'.$dbname, $dbuser, $dbpass);
|
||||
unless(defined $dbh) {
|
||||
print "Could not connect to database '$dbname': $DBI::errstr\n";
|
||||
exit 1;
|
||||
}
|
||||
|
||||
exit 1 unless(sync_extra_sockets());
|
||||
|
||||
$dbh->disconnect;
|
||||
|
||||
# this part sync with kamailio db
|
||||
$dbuser = $config->{kamailio}->{proxy}->{dbrwuser};
|
||||
$dbname = $config->{kamailio}->{proxy}->{dbname};
|
||||
$dbpass = $config->{kamailio}->{proxy}->{dbrwpw};
|
||||
unless(defined $dbname) {
|
||||
print "Could not determine kamailio db name\n";
|
||||
exit 1;
|
||||
}
|
||||
unless(defined $dbuser) {
|
||||
print "Could not determine kamailio db user\n";
|
||||
exit 1;
|
||||
}
|
||||
unless(defined $dbpass) {
|
||||
print "Could not determine kamailio db password\n";
|
||||
exit 1;
|
||||
}
|
||||
|
||||
$dbh = DBI->connect('DBI:mysql:'.$dbname, $dbuser, $dbpass);
|
||||
unless(defined $dbh) {
|
||||
print "Could not connect to database '$dbname': $DBI::errstr\n";
|
||||
exit 1;
|
||||
}
|
||||
|
||||
exit 1 unless(sync_faxserver_uris());
|
||||
$dbh->disconnect;
|
||||
|
||||
exit 0;
|
||||
|
||||
## kamailio.lb.extra_sockets handling: ##############################
|
||||
sub sync_extra_sockets {
|
||||
my $pref_name = 'outbound_socket';
|
||||
my $sth = $dbh->prepare("select id from voip_preferences where attribute=?");
|
||||
$sth->execute($pref_name);
|
||||
my $res = $sth->fetchrow_hashref();
|
||||
unless(defined $res) {
|
||||
print "Could not find preference '$pref_name' in db\n";
|
||||
return;
|
||||
}
|
||||
my $pref_id = $res->{id};
|
||||
$sth->finish;
|
||||
|
||||
my $enum_insert_sth = $dbh->prepare("insert into voip_preferences_enum (preference_id, label, value, usr_pref, dom_pref, peer_pref) values(?, ?, ?, 1, 1, 1)");
|
||||
my $enum_update_sth = $dbh->prepare("update voip_preferences_enum set value=? where id=?");
|
||||
my $enum_delete_sth = $dbh->prepare("delete from voip_preferences_enum where id=?");
|
||||
$sth = $dbh->prepare("select id, label, value from voip_preferences_enum where preference_id=?");
|
||||
$sth->execute($pref_id);
|
||||
|
||||
my $sockets = $config->{kamailio}->{lb}->{extra_sockets};
|
||||
my $dbsockets = $sth->fetchall_hashref('label');
|
||||
$sth->finish;
|
||||
|
||||
foreach my $row (keys %{$dbsockets}) {
|
||||
$row = $dbsockets->{$row};
|
||||
next if($row->{label} eq 'default');
|
||||
if(!exists $sockets->{$row->{label}}) {
|
||||
print "socket $row->{label} does not exist anymore in config, delete from db\n";
|
||||
$enum_delete_sth->execute($row->{id});
|
||||
} elsif($sockets->{$row->{label}} ne $row->{value}) {
|
||||
print "update $row->{label}=$row->{value} to $row->{label}=$sockets->{$row->{label}} in db\n";
|
||||
$enum_update_sth->execute($sockets->{$row->{label}}, $row->{id});
|
||||
delete $sockets->{$row->{label}};
|
||||
} else {
|
||||
print "socket $row->{label}=$row->{value} is sync between config and db\n";
|
||||
delete $sockets->{$row->{label}};
|
||||
}
|
||||
}
|
||||
foreach my $sock(keys %{$sockets}) {
|
||||
print "insert new socket $sock=$sockets->{$sock} from config into db\n";
|
||||
$enum_insert_sth->execute($pref_id, $sock, $sockets->{$sock});
|
||||
}
|
||||
|
||||
$enum_insert_sth->finish;
|
||||
$enum_update_sth->finish;
|
||||
$enum_delete_sth->finish;
|
||||
return 1;
|
||||
}
|
||||
|
||||
## faxserver.hw_fax_gateways handling: ##############################
|
||||
sub sync_faxserver_uris {
|
||||
my $fax_set_id = 4;
|
||||
my $reload_dispatcher = 0;
|
||||
my $dispatcher_insert_sth = $dbh->prepare("insert into dispatcher (setid, destination, flags, priority, description) values(4, ?, 0, 0, 'Fax2Mail Servers')");
|
||||
my $dispatcher_delete_sth = $dbh->prepare("delete from dispatcher where id=?");
|
||||
|
||||
my $sth = $dbh->prepare("select id,destination from dispatcher where setid=?");
|
||||
$sth->execute($fax_set_id);
|
||||
my $db_fax_gateways = $sth->fetchall_hashref('destination');
|
||||
$sth->finish;
|
||||
|
||||
# array reference
|
||||
my $yaml_fax_gateways = $config->{faxserver}->{fax_gateways};
|
||||
unless(defined $yaml_fax_gateways) {
|
||||
return 1;
|
||||
}
|
||||
my @tmp_array = @{$yaml_fax_gateways};
|
||||
# turn the array into hash reference
|
||||
my $fax_gateways = {};
|
||||
foreach my $gw (@tmp_array) {
|
||||
# e.g: sip:127.0.0.1:5070/255.255.255.0, remove /255.255.255.0
|
||||
my @new_gw_parts = split('/', $gw);
|
||||
my $gw_sip_parts = $new_gw_parts[0];
|
||||
$fax_gateways->{$gw_sip_parts} = 1 ;
|
||||
}
|
||||
|
||||
foreach my $row (keys %{$db_fax_gateways}) {
|
||||
$row = $db_fax_gateways->{$row};
|
||||
if(!exists $fax_gateways->{$row->{destination}}) {
|
||||
print "fax gateway $row->{destination} does not exist anymore in config, delete from db\n";
|
||||
$dispatcher_delete_sth->execute($row->{id});
|
||||
$reload_dispatcher ||= 1;
|
||||
} else {
|
||||
print "fax gateway $row->{destination} sync between config and db\n";
|
||||
delete $fax_gateways->{$row->{destination}};
|
||||
}
|
||||
}
|
||||
foreach my $fax_gw(keys %{$fax_gateways}) {
|
||||
print "insert new fax gateway $fax_gw from config into db\n";
|
||||
$dispatcher_insert_sth->execute($fax_gw);
|
||||
$reload_dispatcher ||= 1;
|
||||
}
|
||||
|
||||
$dispatcher_insert_sth->finish;
|
||||
$dispatcher_delete_sth->finish;
|
||||
|
||||
if($reload_dispatcher){
|
||||
print "fax gateway changes, need to reload kamailio dispatcher ... \n";
|
||||
my $result = `ngcp-kamctl proxy dispatcher reload`;
|
||||
print "reload kamailio dispatcher done, status was: $? \n";
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
|
||||
## END OF FILE #################################################################
|
@ -0,0 +1,26 @@
|
||||
#!/usr/bin/perl -CSD
|
||||
# Purpose: template toolkit helper script
|
||||
################################################################################
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use YAML qw/LoadFile/;
|
||||
use Template;
|
||||
use Hash::Merge qw(merge);
|
||||
|
||||
my $tt = Template->new({ ABSOLUTE => 1, RELATIVE => 1, EVAL_PERL => 1 });
|
||||
my $template = shift(@ARGV);
|
||||
|
||||
my $config = {};
|
||||
foreach my $file (@ARGV) {
|
||||
$config = merge($config, LoadFile($file) || die $!);
|
||||
}
|
||||
|
||||
# NOTE: we can't rely on "$tt->process($template, $config)" because the config
|
||||
# file is UTF8 encoded but is then being read as a binary 8bit file and written
|
||||
# as UTF8 file again, causing wide characters getting encoded twice
|
||||
open my $fh, '<', $template or die "Unable to open file for reading: $!";
|
||||
$tt->process($fh, $config) or die $tt->error;
|
||||
|
||||
## END OF FILE #################################################################
|
@ -0,0 +1,17 @@
|
||||
#!/usr/bin/perl -CSD
|
||||
# Purpose: validate yml file format
|
||||
################################################################################
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use YAML::Tiny;
|
||||
use File::Temp qw/tempfile/;
|
||||
|
||||
my $yaml = YAML::Tiny->new;
|
||||
my $inputfile = shift or die 'You did not specify an input file name';
|
||||
my $outputfile = new File::Temp( UNLINK => 1 );
|
||||
$yaml = YAML::Tiny->read($inputfile);
|
||||
open(my $fh, '>', "$outputfile") or die "Could not open $outputfile for writing";
|
||||
print $fh $yaml->write_string() or die "Could not write YAML to $outputfile";
|
||||
|
||||
## END OF FILE #################################################################
|
@ -0,0 +1,30 @@
|
||||
[%
|
||||
# Return an array of advertised IPs from the interface of a given
|
||||
# type for all nodes which act as a given role
|
||||
#
|
||||
# @param argv.role The role of the node to process
|
||||
# One of: proxy, lb, mgmt
|
||||
# @param argv.type The interface type of a node to extract
|
||||
# the advertised ips from
|
||||
# One of: web_int, web_ext, sip_int, sip_ext, ...
|
||||
# @return out The array of advertised ips
|
||||
-%]
|
||||
[% blktmp.processed_hosts = {} -%]
|
||||
[% out = [] -%]
|
||||
[% FOREACH host IN hosts.keys -%]
|
||||
[% IF hosts.$host.role.grep('^' _ argv.role _ '$').size() && !blktmp.processed_hosts.$host.defined -%]
|
||||
[% FOREACH iface IN hosts.$host.interfaces -%]
|
||||
[% FOREACH realiface IN hosts.$host.keys -%]
|
||||
[% IF realiface == iface -%]
|
||||
[% IF hosts.$host.$realiface.type.grep('^' _ argv.type _ '$').size() -%]
|
||||
[% peer = hosts.$host.peer -%]
|
||||
[% blktmp.processed_hosts.$peer = 1 -%]
|
||||
[% FOREACH ip IN hosts.$host.$realiface.advertised_ip -%]
|
||||
[% out.push(ip) -%]
|
||||
[% END -%]
|
||||
[% END -%]
|
||||
[% END -%]
|
||||
[% END -%]
|
||||
[% END -%]
|
||||
[% END -%]
|
||||
[% END -%]
|
@ -0,0 +1,21 @@
|
||||
[%
|
||||
# Return an array of advertised IPs for a given host
|
||||
#
|
||||
# @param argv.host The host to get all shared IPs for.
|
||||
# @param argv.type The interface type or empty string for all types.
|
||||
# @return out The array of advertised ips.
|
||||
-%]
|
||||
[% IF !hosts.${argv.host}.defined -%][% argv.host = 'self' -%][% END -%]
|
||||
[% out = [] -%]
|
||||
[% IF !argv.type.length -%][% argv.type = '.*' -%][% END -%]
|
||||
[% FOREACH iface IN hosts.${argv.host}.interfaces -%]
|
||||
[% FOREACH realiface IN hosts.${argv.host}.keys -%]
|
||||
[% IF realiface == iface -%]
|
||||
[% IF hosts.${argv.host}.$realiface.type.grep('^' _ argv.type _ '$').size() -%]
|
||||
[% FOREACH ip IN hosts.${argv.host}.$realiface.advertised_ip -%]
|
||||
[% out.push(ip) -%]
|
||||
[% END -%]
|
||||
[% END -%]
|
||||
[% END -%]
|
||||
[% END -%]
|
||||
[% END -%]
|
@ -0,0 +1,31 @@
|
||||
[%
|
||||
# Return an array of hashes with name and ip within a given type
|
||||
# for all nodes.
|
||||
#
|
||||
# @param argv.role The role of the node to process
|
||||
# One of: proxy, lb, mgmt
|
||||
# @param argv.type The interface type of a node to extract
|
||||
# the ip from
|
||||
# One of: web_int, web_ext, sip_int, sip_ext, ...
|
||||
# @return out The array of hashes with fields "name" and "ip", e.g.:
|
||||
# [
|
||||
# {name=>'sp1', ip='192.168.255.251'},
|
||||
# {name=>'sp2', ip='192.168.255.252'}
|
||||
# ]
|
||||
-%]
|
||||
[% out = [] -%]
|
||||
[% FOREACH host IN hosts.keys -%]
|
||||
[% IF hosts.$host.role.grep('^' _ argv.role _ '$').size() -%]
|
||||
[% FOREACH iface IN hosts.$host.interfaces -%]
|
||||
[% FOREACH realiface IN hosts.$host.keys -%]
|
||||
[% IF realiface == iface -%]
|
||||
[% IF hosts.$host.$realiface.type.grep('^' _ argv.type _ '$').size() -%]
|
||||
[% IF !out.grep('^' _ hosts.$host.$realiface.ip _ '$').size() -%]
|
||||
[% out.push({ name = host, ip = hosts.$host.$realiface.ip }) -%]
|
||||
[% END -%]
|
||||
[% END -%]
|
||||
[% END -%]
|
||||
[% END -%]
|
||||
[% END -%]
|
||||
[% END -%]
|
||||
[% END -%]
|
@ -0,0 +1,27 @@
|
||||
[%
|
||||
# Return an array of IPs from the interface of a given
|
||||
# type for all nodes which act as a given role
|
||||
#
|
||||
# @param argv.role The role of the node to process
|
||||
# One of: proxy, lb, mgmt
|
||||
# @param argv.type The interface type of a node to extract
|
||||
# the ip from
|
||||
# One of: web_int, web_ext, sip_int, sip_ext, ...
|
||||
# @return out The array of ips
|
||||
-%]
|
||||
[% out = [] -%]
|
||||
[% FOREACH host IN hosts.keys -%]
|
||||
[% IF hosts.$host.role.grep('^' _ argv.role _ '$').size() -%]
|
||||
[% FOREACH iface IN hosts.$host.interfaces -%]
|
||||
[% FOREACH realiface IN hosts.$host.keys -%]
|
||||
[% IF realiface == iface -%]
|
||||
[% IF hosts.$host.$realiface.type.grep('^' _ argv.type _ '$').size() -%]
|
||||
[% IF !out.grep('^' _ hosts.$host.$realiface.ip _ '$').size() -%]
|
||||
[% out.push(hosts.$host.$realiface.ip) -%]
|
||||
[% END -%]
|
||||
[% END -%]
|
||||
[% END -%]
|
||||
[% END -%]
|
||||
[% END -%]
|
||||
[% END -%]
|
||||
[% END -%]
|
@ -0,0 +1,19 @@
|
||||
[%
|
||||
# Return an array of IPs for a given host.
|
||||
#
|
||||
# @param argv.host The host to get all IPs for.
|
||||
# @param argv.type The interface type or empty string for all types.
|
||||
# @return out The array of ips.
|
||||
-%]
|
||||
[% IF !hosts.${argv.host}.defined -%][% argv.host = 'self' -%][% END -%]
|
||||
[% out = [] -%]
|
||||
[% IF !argv.type.length -%][% argv.type = '.*' -%][% END -%]
|
||||
[% FOREACH iface IN hosts.${argv.host}.interfaces -%]
|
||||
[% FOREACH realiface IN hosts.${argv.host}.keys -%]
|
||||
[% IF realiface == iface -%]
|
||||
[% IF hosts.${argv.host}.$realiface.type.grep('^' _ argv.type _ '$').size() -%]
|
||||
[% out.push(hosts.${argv.host}.$realiface.ip) -%]
|
||||
[% END -%]
|
||||
[% END -%]
|
||||
[% END -%]
|
||||
[% END -%]
|
@ -0,0 +1,30 @@
|
||||
[%
|
||||
# Return an array of shared IPs from the interface of a given
|
||||
# type for all nodes which act as a given role
|
||||
#
|
||||
# @param argv.role The role of the node to process
|
||||
# One of: proxy, lb, mgmt
|
||||
# @param argv.type The interface type of a node to extract
|
||||
# the shared ip from
|
||||
# One of: web_int, web_ext, sip_int, sip_ext, ...
|
||||
# @return out The array of shared ips
|
||||
-%]
|
||||
[% blktmp.processed_hosts = {} -%]
|
||||
[% out = [] -%]
|
||||
[% FOREACH host IN hosts.keys -%]
|
||||
[% IF hosts.$host.role.grep('^' _ argv.role _ '$').size() && !blktmp.processed_hosts.$host.defined -%]
|
||||
[% FOREACH iface IN hosts.$host.interfaces -%]
|
||||
[% FOREACH realiface IN hosts.$host.keys -%]
|
||||
[% IF realiface == iface -%]
|
||||
[% IF hosts.$host.$realiface.type.grep('^' _ argv.type _ '$').size() -%]
|
||||
[% peer = hosts.$host.peer -%]
|
||||
[% blktmp.processed_hosts.$peer = 1 -%]
|
||||
[% FOREACH ip IN hosts.$host.$realiface.shared_ip -%]
|
||||
[% out.push(ip) -%]
|
||||
[% END -%]
|
||||
[% END -%]
|
||||
[% END -%]
|
||||
[% END -%]
|
||||
[% END -%]
|
||||
[% END -%]
|
||||
[% END -%]
|
@ -0,0 +1,21 @@
|
||||
[%
|
||||
# Return an array of shared IPs for a given host
|
||||
#
|
||||
# @param argv.host The host to get all shared IPs for.
|
||||
# @param argv.type The interface type or empty string for all types.
|
||||
# @return out The array of shared ips.
|
||||
-%]
|
||||
[% IF !hosts.${argv.host}.defined -%][% argv.host = 'self' -%][% END -%]
|
||||
[% out = [] -%]
|
||||
[% IF !argv.type.length -%][% argv.type = '.*' -%][% END -%]
|
||||
[% FOREACH iface IN hosts.${argv.host}.interfaces -%]
|
||||
[% FOREACH realiface IN hosts.${argv.host}.keys -%]
|
||||
[% IF realiface == iface -%]
|
||||
[% IF hosts.${argv.host}.$realiface.type.grep('^' _ argv.type _ '$').size() -%]
|
||||
[% FOREACH ip IN hosts.${argv.host}.$realiface.shared_ip -%]
|
||||
[% out.push(ip) -%]
|
||||
[% END -%]
|
||||
[% END -%]
|
||||
[% END -%]
|
||||
[% END -%]
|
||||
[% END -%]
|
@ -0,0 +1,30 @@
|
||||
[%
|
||||
# Return an array of shared IPv6 addresses from the interface of a given
|
||||
# type for all nodes which act as a given role
|
||||
#
|
||||
# @param argv.role The role of the node to process
|
||||
# One of: proxy, lb, mgmt
|
||||
# @param argv.type The interface type of a node to extract
|
||||
# the shared ip from
|
||||
# One of: web_int, web_ext, sip_int, sip_ext, ...
|
||||
# @return out The array of shared IPv6 addresses
|
||||
-%]
|
||||
[% blktmp.processed_hosts = {} -%]
|
||||
[% out = [] -%]
|
||||
[% FOREACH host IN hosts.keys -%]
|
||||
[% IF hosts.$host.role.grep('^' _ argv.role _ '$').size() && !blktmp.processed_hosts.$host.defined -%]
|
||||
[% FOREACH iface IN hosts.$host.interfaces -%]
|
||||
[% FOREACH realiface IN hosts.$host.keys -%]
|
||||
[% IF realiface == iface -%]
|
||||
[% IF hosts.$host.$realiface.type.grep('^' _ argv.type _ '$').size() -%]
|
||||
[% peer = hosts.$host.peer -%]
|
||||
[% blktmp.processed_hosts.$peer = 1 -%]
|
||||
[% FOREACH ip IN hosts.$host.$realiface.shared_v6ip -%]
|
||||
[% out.push(ip) -%]
|
||||
[% END -%]
|
||||
[% END -%]
|
||||
[% END -%]
|
||||
[% END -%]
|
||||
[% END -%]
|
||||
[% END -%]
|
||||
[% END -%]
|
@ -0,0 +1,21 @@
|
||||
[%
|
||||
# Return an array of shared IPs for a given host
|
||||
#
|
||||
# @param argv.host The host to get all shared IPs for.
|
||||
# @param argv.type The interface type or empty string for all types.
|
||||
# @return out The array of shared ips
|
||||
-%]
|
||||
[% IF !hosts.${argv.host}.defined -%][% argv.host = 'self' -%][% END -%]
|
||||
[% out = [] -%]
|
||||
[% IF !argv.type.length -%][% argv.type = '.*' -%][% END -%]
|
||||
[% FOREACH iface IN hosts.${argv.host}.interfaces -%]
|
||||
[% FOREACH realiface IN hosts.${argv.host}.keys -%]
|
||||
[% IF realiface == iface -%]
|
||||
[% IF hosts.${argv.host}.$realiface.type.grep('^' _ argv.type _ '$').size() -%]
|
||||
[% FOREACH ip IN hosts.${argv.host}.$realiface.shared_v6ip -%]
|
||||
[% out.push(ip) -%]
|
||||
[% END -%]
|
||||
[% END -%]
|
||||
[% END -%]
|
||||
[% END -%]
|
||||
[% END -%]
|
@ -0,0 +1,25 @@
|
||||
[%
|
||||
# Return an array of IPv6 addresses from the interface of a given
|
||||
# type for all nodes which act as a given role
|
||||
#
|
||||
# @param argv.role The role of the node to process
|
||||
# One of: proxy, lb, mgmt
|
||||
# @param argv.type The interface type of a node to extract
|
||||
# the ip from
|
||||
# One of: web_int, web_ext, sip_int, sip_ext, ...
|
||||
# @return out The array of ips
|
||||
-%]
|
||||
[% out = [] -%]
|
||||
[% FOREACH host IN hosts.keys -%]
|
||||
[% IF hosts.$host.role.grep('^' _ argv.role _ '$').size() -%]
|
||||
[% FOREACH iface IN hosts.$host.interfaces -%]
|
||||
[% FOREACH realiface IN hosts.$host.keys -%]
|
||||
[% IF realiface == iface -%]
|
||||
[% IF hosts.$host.$realiface.type.grep('^' _ argv.type _ '$').size() -%]
|
||||
[% out.push(hosts.$host.$realiface.v6ip) -%]
|
||||
[% END -%]
|
||||
[% END -%]
|
||||
[% END -%]
|
||||
[% END -%]
|
||||
[% END -%]
|
||||
[% END -%]
|
@ -0,0 +1,22 @@
|
||||
[%
|
||||
# Return an array of IPs for a given host. The order is iface1_sharedip_1,
|
||||
# iface1_sharedip_n, iface1_ip, iface2_sharedip_1, ...
|
||||
#
|
||||
# @param argv.host The host to get all IPs for.
|
||||
# @param argv.type The interface type or empty string for all types.
|
||||
# @return out The array of ips.
|
||||
-%]
|
||||
[% IF !hosts.${argv.host}.defined -%][% argv.host = 'self' -%][% END -%]
|
||||
[% out = [] -%]
|
||||
[% IF !argv.type.length -%][% argv.type = '.*' -%][% END -%]
|
||||
[% FOREACH iface IN hosts.${argv.host}.interfaces -%]
|
||||
[% FOREACH realiface IN hosts.${argv.host}.keys -%]
|
||||
[% IF realiface == iface -%]
|
||||
[% IF hosts.${argv.host}.$realiface.type.grep('^' _ argv.type _ '$').size() -%]
|
||||
[% IF hosts.${argv.host}.$realiface.v6ip.defined -%]
|
||||
[% out.push(hosts.${argv.host}.$realiface.v6ip) -%]
|
||||
[% END -%]
|
||||
[% END -%]
|
||||
[% END -%]
|
||||
[% END -%]
|
||||
[% END -%]
|
@ -0,0 +1,15 @@
|
||||
[%
|
||||
# Returns the (alphabetically) first hostname of a node pair for
|
||||
# a given host.
|
||||
#
|
||||
# @param argv.host The hostname to get the first name for.
|
||||
# @return out The alphabetically first name.
|
||||
-%]
|
||||
[% IF !hosts.${argv.host}.defined -%]
|
||||
[% argv.host = 'self' -%]
|
||||
[% END -%]
|
||||
[% blktmp.hosts = [argv.host] -%]
|
||||
[% IF hosts.${argv.host}.peer.defined -%]
|
||||
[% blktmp.hosts.push(hosts.${argv.host}.peer) -%]
|
||||
[% END -%]
|
||||
[% out = blktmp.hosts.sort.0 -%]
|
@ -0,0 +1,15 @@
|
||||
[%
|
||||
# Returns the hostname of the node calling this function.
|
||||
#
|
||||
# @return out The hostname of the node calling this function.
|
||||
-%]
|
||||
[% PERL -%]
|
||||
# don't trust hostname(1) as this might differ from the hostname of
|
||||
# the system which runs the installer, instead rely on /etc/hostname
|
||||
open my $hh, '<', '/etc/hostname' or die "Error opening /etc/hostname";
|
||||
my $hostname = <$hh>;
|
||||
close $hh;
|
||||
chomp $hostname;
|
||||
die "Fatal error retrieving hostname [$hostname]" unless length $hostname;
|
||||
$stash->set(out => $hostname);
|
||||
[% END -%]
|
@ -0,0 +1,23 @@
|
||||
[%
|
||||
# Returns the interface name with a certain type for a given host
|
||||
#
|
||||
# @param argv.host The hostname to get the interface from.
|
||||
# @param argv.type The interface type
|
||||
# One of: web_int, web_ext, sip_int, sip_ext, ...
|
||||
# @return out The interface name
|
||||
-%]
|
||||
[% IF !hosts.${argv.host}.defined -%]
|
||||
[% argv.host = 'self' -%]
|
||||
[% END -%]
|
||||
[% out = '' -%]
|
||||
[% FOREACH iface IN hosts.${argv.host}.interfaces -%]
|
||||
[% FOREACH realiface IN hosts.${argv.host}.keys -%]
|
||||
[% IF realiface == iface -%]
|
||||
[% IF hosts.${argv.host}.$realiface.type.grep('^' _ argv.type _ '$').size() -%]
|
||||
[% out = realiface -%]
|
||||
[% RETURN -%]
|
||||
[% END -%]
|
||||
[% END -%]
|
||||
[% END -%]
|
||||
[% END -%]
|
||||
|
@ -0,0 +1,10 @@
|
||||
[%
|
||||
# Returns the peer name of a given host
|
||||
#
|
||||
# @param argv.host The hostname to get the peername for.
|
||||
# @return out The peername.
|
||||
-%]
|
||||
[% IF !hosts.${argv.host}.defined -%]
|
||||
[% argv.host = 'self' -%]
|
||||
[% END -%]
|
||||
[% out = hosts.${argv.host}.peer -%]
|
@ -0,0 +1,15 @@
|
||||
[%
|
||||
# Checks whether a given host has a given role
|
||||
#
|
||||
# @param argv.host The hostname to check the role for
|
||||
# @param argv.role The role of the node to process
|
||||
# One of: proxy, lb, mgmt
|
||||
# @return out 0 if false, 1 if true
|
||||
-%]
|
||||
[% IF !hosts.${argv.host}.defined -%]
|
||||
[% argv.host = 'self' -%]
|
||||
[% END -%]
|
||||
[% out = 0 -%]
|
||||
[% IF hosts.${argv.host}.role.grep('^' _ argv.role _ '$').size() -%]
|
||||
[% out = 1 -%]
|
||||
[% END -%]
|
@ -0,0 +1,781 @@
|
||||
#!/usr/bin/perl -CSD
|
||||
|
||||
use warnings;
|
||||
use strict;
|
||||
|
||||
use Carp;
|
||||
use Data::Validate::IP;
|
||||
use English qw( -no_match_vars );
|
||||
use Getopt::Long;
|
||||
use IO::Interface;
|
||||
use IO::Socket;
|
||||
use IPC::Open3;
|
||||
use List::MoreUtils qw{ any };
|
||||
use Net::Netmask;
|
||||
use Pod::Usage;
|
||||
use Regexp::IPv6 qw($IPv6_re);
|
||||
use Socket;
|
||||
use Sys::Hostname;
|
||||
use YAML::Tiny;
|
||||
|
||||
our $VERSION = 'UNRELEASED';
|
||||
|
||||
# defaults / option handling {{{
|
||||
open my $hh, '<', '/etc/hostname'
|
||||
or croak "Error opening /etc/hostname: $ERRNO";
|
||||
my $host = <$hh>;
|
||||
close $hh or croak 'Error closing file handling for /etc/hostname';
|
||||
chomp $host;
|
||||
length $host or croak "Fatal error retrieving hostname [$host]";
|
||||
|
||||
my $advertised_ip;
|
||||
my $bond_miimon;
|
||||
my $bond_mode;
|
||||
my $bond_slaves;
|
||||
my $broadcast;
|
||||
my @dns_nameservers;
|
||||
my $gateway;
|
||||
my $help;
|
||||
my $hwaddr;
|
||||
my $inputfile = '/etc/ngcp-config/network.yml';
|
||||
my $internal_iface;
|
||||
my $ip;
|
||||
my $ip_v6;
|
||||
my $man;
|
||||
my $move_from;
|
||||
my $move_to;
|
||||
my $netmask;
|
||||
my $outputfile = $inputfile;
|
||||
my $peer;
|
||||
my @remove_host;
|
||||
my @remove_interface;
|
||||
my @roles;
|
||||
my @set_interface;
|
||||
my $shared_ip;
|
||||
my $shared_ip_v6;
|
||||
my @type;
|
||||
my $verbose;
|
||||
my $version;
|
||||
my $vlan_raw_device;
|
||||
|
||||
GetOptions(
|
||||
'advertised-ip=s' => \$advertised_ip,
|
||||
'bond-miimon=s' => \$bond_miimon,
|
||||
'bond-mode=s' => \$bond_mode,
|
||||
'bond-slaves=s' => \$bond_slaves,
|
||||
'broadcast=s' => \$broadcast,
|
||||
'dns=s' => \@dns_nameservers,
|
||||
'gateway=s' => \$gateway,
|
||||
'help' => \$help,
|
||||
'host=s' => \$host,
|
||||
'hwaddr=s' => \$hwaddr,
|
||||
'input-file=s' => \$inputfile,
|
||||
'internal-iface=s' => \$internal_iface,
|
||||
'ip=s' => \$ip,
|
||||
'ipv6=s' => \$ip_v6,
|
||||
'man' => \$man,
|
||||
'move-from=s' => \$move_from,
|
||||
'move-to=s' => \$move_to,
|
||||
'netmask=s' => \$netmask,
|
||||
'output-file=s' => \$outputfile,
|
||||
'peer=s' => \$peer,
|
||||
'remove-host=s' => \@remove_host,
|
||||
'remove-interface=s' => \@remove_interface,
|
||||
'role=s' => \@roles,
|
||||
'set-interface=s' => \@set_interface,
|
||||
'shared-ip=s' => \$shared_ip,
|
||||
'shared-ipv6=s' => \$shared_ip_v6,
|
||||
'type=s' => \@type,
|
||||
'verbose' => \$verbose,
|
||||
'version' => \$version,
|
||||
'vlan-raw-device=s' => \$vlan_raw_device,
|
||||
) or pod2usage(2);
|
||||
|
||||
if ($help) {
|
||||
pod2usage(0);
|
||||
}
|
||||
|
||||
if ($version) {
|
||||
print "$PROGRAM_NAME, v$version\n";
|
||||
exit 0;
|
||||
}
|
||||
|
||||
if ($man) {
|
||||
pod2usage( -exitstatus => 0, -verbose => 2 );
|
||||
}
|
||||
|
||||
# validate input
|
||||
if ($ip) {
|
||||
logger("validating specified IP address $ip");
|
||||
if ( is_ipv4($ip) || $ip =~ /^(auto|none|delete)$/msx ) {
|
||||
logger('valid IPv4 address');
|
||||
}
|
||||
else {
|
||||
croak "Specified IP $ip is not a valid IPv4 address";
|
||||
}
|
||||
}
|
||||
|
||||
if ($ip_v6) {
|
||||
logger("validating specified IP address $ip_v6");
|
||||
if ( is_ipv6($ip_v6) || $ip_v6 =~ /^(auto|none|delete)$/msx ) {
|
||||
logger('valid IPv6 address');
|
||||
}
|
||||
else {
|
||||
croak "Specified IP $ip_v6 is not a valid IPv6 address";
|
||||
}
|
||||
}
|
||||
|
||||
foreach my $opt (
|
||||
$bond_miimon, $bond_mode, $broadcast, @dns_nameservers,
|
||||
$gateway, @set_interface, $host, $hwaddr,
|
||||
$internal_iface, $ip, $ip_v6, $move_from,
|
||||
$move_to, $netmask, $peer, @remove_host,
|
||||
@remove_interface, @roles, @type, $vlan_raw_device
|
||||
)
|
||||
{
|
||||
if ( defined $opt && $opt =~ /\s/msx ) {
|
||||
logger("invalid option argument $opt");
|
||||
croak "Command line option does not accept whitespace in '$opt'.";
|
||||
}
|
||||
}
|
||||
|
||||
# }}}
|
||||
|
||||
my $yaml = YAML::Tiny->new;
|
||||
logger("reading input file $inputfile");
|
||||
$yaml = YAML::Tiny->read($inputfile)
|
||||
or croak "File $inputfile could not be read";
|
||||
|
||||
if ( -e "$outputfile" && !-w "$outputfile" ) {
|
||||
croak "Could not open $outputfile for writing (are you user root?)";
|
||||
}
|
||||
|
||||
my $spce;
|
||||
if ( defined $yaml->[0]->{hosts}->{self} ) {
|
||||
logger('host "self" identified and set, assuming spce system');
|
||||
$host = 'self';
|
||||
$spce = 1;
|
||||
}
|
||||
|
||||
# helper functions {{{
|
||||
sub logger {
|
||||
if ($verbose) {
|
||||
print "@_\n" or croak 'Error sending log output';
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
sub get_interface_details {
|
||||
my $interface = shift or croak "Usage: $PROGRAM_NAME <interface> <setting>";
|
||||
my $setting = shift or croak "Usage: $PROGRAM_NAME <interface> <setting>";
|
||||
|
||||
my $s = IO::Socket::INET->new( Proto => 'tcp' );
|
||||
return $s->$setting($interface);
|
||||
}
|
||||
|
||||
sub get_ip6_addr {
|
||||
|
||||
my $interface = shift or croak 'Usage: runcmd <interface>';
|
||||
my $cmd = 'ip';
|
||||
my @args = ( '-6', 'addr', 'show', 'dev', $interface, 'scope', 'global' );
|
||||
|
||||
logger("get_ip6_addr for device $interface");
|
||||
logger("$cmd @args");
|
||||
|
||||
my $childpid = open3 'HIS_WRITE', 'HIS_OUT', 'HIS_ERR', $cmd, @args;
|
||||
my @stderr = <HIS_ERR>;
|
||||
my @stdout = <HIS_OUT>;
|
||||
|
||||
logger("stdout: @stdout");
|
||||
logger("stderr: @stderr");
|
||||
|
||||
close HIS_OUT or croak 'Failed to close stdout';
|
||||
close HIS_ERR or croak 'Failed to close stderr';
|
||||
|
||||
waitpid $childpid, 0;
|
||||
if ($CHILD_ERROR) {
|
||||
croak "Problem with execution [return code $CHILD_ERROR]:\n@stderr";
|
||||
}
|
||||
|
||||
foreach my $line (@stdout) {
|
||||
if ( $line =~ /^\s*inet6\s+($IPv6_re)\/\d+.*scope.*global.*$/msx ) {
|
||||
return $1;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
sub set_interface {
|
||||
my $iface = shift;
|
||||
|
||||
logger("set_interface: interface = $iface");
|
||||
logger("set_interface: host = $host");
|
||||
|
||||
if ( defined $ip && $ip =~ /^auto$/msx ) {
|
||||
logger("get_interface_details( $iface, 'if_addr' );");
|
||||
$ip = get_interface_details( $iface, 'if_addr' );
|
||||
}
|
||||
|
||||
if ( defined $ip_v6 && $ip_v6 =~ /^auto$/msx ) {
|
||||
logger("get_interface_details( $iface, 'if_addr' );");
|
||||
$ip_v6 = get_ip6_addr($iface);
|
||||
}
|
||||
|
||||
if ( defined $netmask && $netmask =~ /^auto$/msx ) {
|
||||
logger("get_interface_details( $iface, 'if_netmask' );");
|
||||
$netmask = get_interface_details( $iface, 'if_netmask' );
|
||||
}
|
||||
|
||||
if ( defined $hwaddr && $hwaddr =~ /^auto$/msx ) {
|
||||
logger("get_interface_details( $iface, 'if_hwaddr' );");
|
||||
$hwaddr = get_interface_details( $iface, 'if_hwaddr' );
|
||||
}
|
||||
|
||||
my $settings = {
|
||||
'advertised_ip' => $advertised_ip,
|
||||
'bond_miimon' => $bond_miimon,
|
||||
'bond_mode' => $bond_mode,
|
||||
'bond_slaves' => $bond_slaves,
|
||||
'broadcast' => $broadcast,
|
||||
'gateway' => $gateway,
|
||||
'hwaddr' => $hwaddr,
|
||||
'ip' => $ip,
|
||||
'netmask' => $netmask,
|
||||
'shared_ip' => $shared_ip,
|
||||
'shared_v6ip' => $shared_ip_v6,
|
||||
'v6ip' => $ip_v6,
|
||||
'vlan_raw_device' => $vlan_raw_device,
|
||||
};
|
||||
|
||||
foreach my $k ( keys %{$settings} ) {
|
||||
if ( defined $settings->{$k} ) {
|
||||
if ( $settings->{$k} =~ /^none$/msx ) {
|
||||
logger("unsetting entry $k");
|
||||
undef $yaml->[0]->{hosts}->{$host}->{$iface}->{$k};
|
||||
}
|
||||
elsif ( $settings->{$k} =~ /^delete$/msx ) {
|
||||
logger("deleting entry $k");
|
||||
delete $yaml->[0]->{hosts}->{$host}->{$iface}->{$k};
|
||||
}
|
||||
else {
|
||||
logger("$k: $settings->{$k}");
|
||||
if($k eq 'shared_ip' || $k eq 'shared_v6ip' || $k eq 'advertised_ip') {
|
||||
push @{ $yaml->[0]->{hosts}->{$host}->{$iface}->{$k} }, $settings->{$k};
|
||||
}
|
||||
else {
|
||||
$yaml->[0]->{hosts}->{$host}->{$iface}->{$k} = $settings->{$k};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (@dns_nameservers) {
|
||||
foreach my $dns (@dns_nameservers) {
|
||||
logger("set_iface_config( $iface, 'dns_nameservers', $dns)");
|
||||
set_iface_config( $iface, 'dns_nameservers', $dns );
|
||||
}
|
||||
}
|
||||
|
||||
if (@type) {
|
||||
foreach my $type (@type) {
|
||||
logger("set_iface_config( $iface, 'type', $type)");
|
||||
set_iface_config( $iface, 'type', $type );
|
||||
}
|
||||
}
|
||||
|
||||
# add interface to list of available interfaces
|
||||
my $ifaces = $yaml->[0]->{hosts}->{$host}->{interfaces};
|
||||
if ( !defined $ifaces ) {
|
||||
logger("no interfaces defined yet, adding interface $iface");
|
||||
$yaml->[0]->{hosts}->{$host}->{interfaces}->[0] = "$iface";
|
||||
}
|
||||
else {
|
||||
logger("interface = $iface");
|
||||
|
||||
if ( any { /^${iface}$/msx } @{$ifaces} ) {
|
||||
logger("interface $iface already listed on host $host");
|
||||
}
|
||||
else {
|
||||
push @{$ifaces}, $iface;
|
||||
logger("adding $iface to list of interfaces on host $host");
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
sub remove_interface {
|
||||
my $rem_iface = shift or croak 'Usage: remove_interface <interface>';
|
||||
|
||||
delete $yaml->[0]->{hosts}->{$host}->{$rem_iface};
|
||||
|
||||
my $ifaces = $yaml->[0]->{hosts}->{$host}->{interfaces};
|
||||
if ( defined $ifaces ) {
|
||||
logger("removing interface @$ifaces as requested");
|
||||
undef @{$ifaces};
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
sub set_yml_config {
|
||||
my $setting = shift or croak 'Usage: set_yml_config <setting> <value>';
|
||||
my $value = shift or croak 'Usage: set_yml_config <setting> <value>';
|
||||
|
||||
$yaml->[0]->{hosts}->{$host}->{$setting} = "$value";
|
||||
logger("\$yaml->[0]->{hosts}->{\$host}->{$setting} = $value");
|
||||
return;
|
||||
}
|
||||
|
||||
sub set_iface_config {
|
||||
my $iface = shift
|
||||
or croak 'Usage: set_iface_config <iface> <setting> <value>';
|
||||
my $setting = shift
|
||||
or croak 'Usage: set_iface_config <iface> <setting> <value>';
|
||||
my $value = shift
|
||||
or croak 'Usage: set_iface_config <iface> <setting> <value>';
|
||||
|
||||
if ( any { /^${value}$/msx }
|
||||
@{ $yaml->[0]->{hosts}->{$host}->{$iface}->{$setting} } )
|
||||
{
|
||||
logger("$value for $setting on $iface already defined in host $host");
|
||||
}
|
||||
else {
|
||||
push @{ $yaml->[0]->{hosts}->{$host}->{$iface}->{$setting} }, $value;
|
||||
logger(
|
||||
"\$yaml->[0]->{hosts}->{\$host}->{$iface}->{$setting} => $value");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
sub set_role {
|
||||
my $new_role = shift or croak 'Usage: set_role <value>';
|
||||
|
||||
if ( any { /^${new_role}$/msx } @{ $yaml->[0]->{hosts}->{$host}->{role} } )
|
||||
{
|
||||
logger("role $new_role already defined in host $host");
|
||||
}
|
||||
else {
|
||||
push @{ $yaml->[0]->{hosts}->{$host}->{role} }, $new_role;
|
||||
logger("\$yaml->[0]->{hosts}->{\$host}->{role} => $new_role");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
sub move_settings {
|
||||
my $from = shift;
|
||||
my $to = shift;
|
||||
|
||||
if ( defined $from && !defined $to ) {
|
||||
croak '--move-from option must be used with --move-to option together';
|
||||
}
|
||||
|
||||
if ( !defined $from && defined $to ) {
|
||||
croak '--move-to option must be used with --move-from option together';
|
||||
}
|
||||
|
||||
# ha, nothing to do for us
|
||||
if ( !defined $from && !defined $to ) {
|
||||
return;
|
||||
}
|
||||
|
||||
logger("from = $from");
|
||||
logger("to = $to");
|
||||
|
||||
if (@roles) {
|
||||
foreach my $role (@roles) {
|
||||
logger("role = $role");
|
||||
|
||||
# get rid of the entry from the old section
|
||||
my @tmp =
|
||||
grep { !/^${role}$/msx }
|
||||
@{ $yaml->[0]->{hosts}->{$from}->{role} };
|
||||
$yaml->[0]->{hosts}->{$from}->{role} = [];
|
||||
push @{ $yaml->[0]->{hosts}->{$from}->{role} }, @tmp;
|
||||
|
||||
# add it to its new place
|
||||
push @{ $yaml->[0]->{hosts}->{$to}->{role} }, $role;
|
||||
}
|
||||
}
|
||||
|
||||
if (@type) {
|
||||
foreach my $type (@type) {
|
||||
logger("type = $type");
|
||||
|
||||
# get rid of the entry from the old section
|
||||
my @tmp =
|
||||
grep { !/^${type}$/msx }
|
||||
@{ $yaml->[0]->{hosts}->{$host}->{$from}->{type} };
|
||||
$yaml->[0]->{hosts}->{$host}->{$from}->{type} = [];
|
||||
push @{ $yaml->[0]->{hosts}->{$host}->{$from}->{type} }, @tmp;
|
||||
|
||||
# add it to its new place, but only if not already defined yet
|
||||
if ( any { /^${type}$/msx }
|
||||
@{ $yaml->[0]->{hosts}->{$host}->{$to}->{type} } )
|
||||
{
|
||||
logger("type $type is already defined on host $host, interface $to");
|
||||
}
|
||||
else {
|
||||
push @{ $yaml->[0]->{hosts}->{$host}->{$to}->{type} }, $type;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
# }}}
|
||||
|
||||
# main execution {{{
|
||||
if (@set_interface) {
|
||||
foreach my $interface (@set_interface) {
|
||||
logger("set_interface($interface)");
|
||||
set_interface($interface);
|
||||
}
|
||||
}
|
||||
|
||||
if (@remove_host) {
|
||||
foreach my $rhost (@remove_host) {
|
||||
logger("removing host $rhost");
|
||||
delete $yaml->[0]->{hosts}->{$rhost};
|
||||
}
|
||||
}
|
||||
|
||||
if (@remove_interface) {
|
||||
foreach my $riface (@remove_interface) {
|
||||
logger("remove_interface($riface)");
|
||||
remove_interface($riface);
|
||||
}
|
||||
}
|
||||
|
||||
if ( @roles && ( !defined $move_from || !defined $move_to ) ) {
|
||||
foreach my $role (@roles) {
|
||||
logger("set_role($role)");
|
||||
set_role($role);
|
||||
}
|
||||
}
|
||||
|
||||
if ( defined $peer && ( !defined $move_from || !defined $move_to ) ) {
|
||||
logger("set_yml_config('peer', $peer)");
|
||||
set_yml_config( 'peer', $peer );
|
||||
}
|
||||
|
||||
if ( defined $internal_iface
|
||||
&& ( !defined $move_from || !defined $move_to ) )
|
||||
{
|
||||
logger("set_yml_config('internal_iface', $internal_iface)");
|
||||
set_yml_config( 'internal_iface', $internal_iface );
|
||||
}
|
||||
|
||||
move_settings( $move_from, $move_to );
|
||||
|
||||
open my $fh, '>', "$outputfile"
|
||||
or croak "Could not open $outputfile for writing";
|
||||
logger("writing output file $outputfile");
|
||||
print {$fh} $yaml->write_string()
|
||||
or croak "Could not write YAML to $outputfile";
|
||||
close $fh or croak "Couldn't close '$fh': $OS_ERROR";
|
||||
|
||||
# }}}
|
||||
|
||||
__END__
|
||||
|
||||
=head1 NAME
|
||||
ngcp-network - command line interface to ngcp's network configuration settings
|
||||
|
||||
=head1 SYNOPSIS
|
||||
ngcp-network <options ...>
|
||||
|
||||
=head1 OPTIONS
|
||||
|
||||
=over 8
|
||||
|
||||
=item B<--advertised-ip=<IP>>
|
||||
|
||||
Set advertised_ip configuration to specified argument.
|
||||
|
||||
=item B<--bond-miimon=<setting>>
|
||||
|
||||
Set bond_miimon configuration to specified argument.
|
||||
|
||||
=item B<--bond-mode=<mode>>
|
||||
|
||||
Set bond_mode configuration to specified argument.
|
||||
|
||||
=item B<--bond-slaves=<slaves>>
|
||||
|
||||
Set bond_slaves configuration to specified argument.
|
||||
|
||||
=item B<--broadcast=<IP>>
|
||||
|
||||
Set broadcast configuration to specified argument.
|
||||
|
||||
=item B<--dns=<nameserver>>
|
||||
|
||||
Set dns_nameservers configuration to specified argument.
|
||||
Can be specified multiple times in one single command line.
|
||||
|
||||
=item B<--gateway=<IP>>
|
||||
|
||||
Set gateway configuration to specified argument.
|
||||
|
||||
=item B<--help>
|
||||
|
||||
Print the help message and exit.
|
||||
|
||||
=item B<--host=<name>>
|
||||
|
||||
Apply configuration changes for specified host entry instead of using the
|
||||
hostname of the currently running system. NOTE: If running the sip:provider CE
|
||||
edition this configuration option can't be changed as the only configured host
|
||||
is set to and supposed to be 'self' there.
|
||||
|
||||
=item B<--hwaddr=<MAC_address>>
|
||||
|
||||
Set hwaddr configuration (MAC address of network device) to specified argument.
|
||||
|
||||
=item B<--input-file=<filename>>
|
||||
|
||||
Use specified file as input, defaults to /etc/ngcp-config/network.yml if unset.
|
||||
|
||||
=item B<--internal-iface=<name>>
|
||||
|
||||
Set internal-iface configuration to specified argument.
|
||||
|
||||
=item B<--ip=<IP>>
|
||||
|
||||
Set ip configuration (IPv4 address) to specified argument. If set to 'auto' and
|
||||
the selected interface is available on the running host then the IP address will
|
||||
be determined based on its current settings.
|
||||
|
||||
=item B<--ipv6=<IP>>
|
||||
|
||||
Set ip configuration (IPv6 address) to specified argument. If set to 'auto' and
|
||||
the selected interface is available on the running host then the IP address will
|
||||
be determined based on its current settings.
|
||||
|
||||
=item B<--man>
|
||||
|
||||
Prints the manual page and exits.
|
||||
|
||||
=item B<--move-from=<source>>
|
||||
|
||||
Move item from specified level (being host for --role and interface for --type).
|
||||
The item needs to be chosen via --type or --role. To be used in combination with
|
||||
--move-to=....
|
||||
|
||||
=item B<--move-to=<target>>
|
||||
|
||||
Move item to specified level (being host for --role and interface for --type).
|
||||
The item needs to be chosen via --type or --role. To be used in combination with
|
||||
--move-to=....
|
||||
|
||||
=item B<--netmask=<IP>>
|
||||
|
||||
Set netmask configuration to specified argument.
|
||||
|
||||
=item B<--output-file=<filename>>
|
||||
|
||||
Store resulting file under specified argument. If unset defaults to
|
||||
/etc/ngcp-config/network.yml.
|
||||
|
||||
=item B<--peer=<nodename>>
|
||||
|
||||
Set peer configuration (being the corresponding other node in a PRO setup) to
|
||||
specified argument.
|
||||
|
||||
=item B<--remove-host=<host>>
|
||||
|
||||
Remove the specified host from the configuration file.
|
||||
Can be specified multiple times (--remove-host=sp1 --remove-host=sp2 ...).
|
||||
|
||||
=item B<--remove-interface=<interface>>
|
||||
|
||||
Remove the specified interface from the configuration file.
|
||||
Can be specified multiple times (--remove-interface=eth5 --remove-interface=eth6 ...).
|
||||
|
||||
=item B<--role=<role>>
|
||||
|
||||
Set role configuration for host to specified argument.
|
||||
Can be specified multiple times (--role=lb --role=proxy ...).
|
||||
|
||||
=item B<--set-interface=<name>>
|
||||
|
||||
Add specified network interface. Can be combined with options like --hwaddr,
|
||||
--ip, --netmask,... to set specified arguments as configuration options for the
|
||||
given network interface.
|
||||
|
||||
NOTE: If multiple --set-interface options are specified in one command line
|
||||
(e.g. '--set-interface=lo --set-interface=eth0 --set-interface=eth1') then
|
||||
options like --hwaddr can't be sanely combined with different settings on
|
||||
multiple interfaces. Instead invoke ngcp-network with the --set-interface option
|
||||
mulitple times.
|
||||
|
||||
=item B<--shared-ip=<IP>>
|
||||
|
||||
Set shared_ip configuration to specified argument.
|
||||
|
||||
=item B<--shared-ipv6=<IP>>
|
||||
|
||||
Set shared_v6ip configuration to specified argument.
|
||||
|
||||
=item B<--type=<name>>
|
||||
|
||||
Set type configuration to specified argument.
|
||||
Can be specified multiple times in one single command line.
|
||||
|
||||
=item B<--verbose>
|
||||
|
||||
Be more verbose about execution.
|
||||
|
||||
=item B<--version>
|
||||
|
||||
Display program version and exit.
|
||||
|
||||
=item B<--vlan-raw-device=<device>>
|
||||
|
||||
Set vlan_raw_device configuration to specified argument.
|
||||
|
||||
=back
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
B<This program> will read the given input file(s) and do something
|
||||
useful with the contents thereof.
|
||||
|
||||
=head1 USAGE
|
||||
|
||||
Usage examples useful especially on sip:provider CE systems:
|
||||
|
||||
ngcp-network --set-interface=eth0 --ip=192.168.23.42 --netmask=255.25.255.248
|
||||
ngcp-network --set-interface=eth1 --ip=auto --netmask=auto
|
||||
|
||||
Usage examples useful especially on sip:provider PRO systems:
|
||||
|
||||
ngcp-network --set-interface=lo --set-interface=eth0 --set-interface=eth1 --ip=auto --netmask=auto
|
||||
|
||||
ngcp-network --peer=sp2
|
||||
ngcp-network --host=sp2 --peer=sp1
|
||||
|
||||
ngcp-network --set-interface=eth1 --ip=auto --netmask=auto
|
||||
ngcp-network --move-from=lo --move-to=eth1 --type=ha_int
|
||||
|
||||
ngcp-network --set-interface=eth1 --host=sp2 --ip=192.168.255.252 --netmask=255.255.255.248 --type=ha_int
|
||||
|
||||
Usage examples useful especially on sip:carrier systems:
|
||||
|
||||
ngcp-network --host=proxy2 --set-interface=eth0 --ip=192.168.10.42 --netmask=255.255.255.0
|
||||
|
||||
=head1 REQUIRED ARGUMENTS
|
||||
|
||||
Depending on the setting you are trying to apply there are different sets of
|
||||
required arguments. Some examples:
|
||||
|
||||
--move-from=INTERFACE1 --move-to=INTERFACE2 --type=XXX
|
||||
|
||||
Move specified type setting XXX from INTERFACE1 section to INTERFACE2.
|
||||
|
||||
--move-from=HOST1 --move-to=HOST2 --role=XXX
|
||||
|
||||
Move specified role setting XXX from HOST1 to HOST2.
|
||||
|
||||
--set-interface=INTERFACE --ip=[1.2.3.4|auto|none|delete] --netmask=[255.25.255.0|auto|none|delete] ...
|
||||
|
||||
Configure IP, netmask,... on specified INTERFACE.
|
||||
|
||||
=head1 DIAGNOSTICS
|
||||
|
||||
=head2 Unknown option: ...
|
||||
|
||||
The specified command line option is not support.
|
||||
|
||||
=head2 File ... could not be read ...
|
||||
|
||||
The specified input file doesn't exist or can't be read.
|
||||
|
||||
=head2 Error opening /etc/hostname: ...
|
||||
|
||||
The file /etc/hostname couldn't be read, either because the file doesn't exist
|
||||
or having wrong file permissions.
|
||||
|
||||
=head2 Fatal error retrieving hostname [...]
|
||||
|
||||
No valid hostname could not be retrieved from /etc/hostname.
|
||||
|
||||
=head2 Specified IP ... is not a valid IPv4 address
|
||||
|
||||
The specified IP address is not considered a valid IPv4 address.
|
||||
|
||||
=head2 Specified IP ... is not a valid IPv6 address
|
||||
|
||||
The specified IP address is not considered a valid IPv6 address.
|
||||
|
||||
=head2 Command line option does not accept whitespace in ...
|
||||
|
||||
An argument to a command line option contains whitespace(s),
|
||||
which isn't supported to avoid problems with the YAML file format.
|
||||
|
||||
=head2 Could not open [...] for writing (are you user root?)
|
||||
|
||||
The configuration file couldn't be stored, usually caused by user executing the
|
||||
program not having write permissions on the file.
|
||||
|
||||
=head2 Error sending log output
|
||||
|
||||
Using the --verbose option the more detailed information couldn't be printed to
|
||||
the console.
|
||||
|
||||
=head2 --move-from option must be used with --move-to option together
|
||||
|
||||
The --move-from option was specified in the command line but the --move-to
|
||||
option is missing.
|
||||
|
||||
=head2 --move-to option must be used with --move-from option together
|
||||
|
||||
The --move-to option was specified in the command line but the --move-from
|
||||
option is missing.
|
||||
|
||||
=head2 Could not open ... for writing
|
||||
|
||||
The file can't be written, usually caused because the user doesn't have write
|
||||
permissions on the file.
|
||||
|
||||
=head2 Could not write YAML to ...
|
||||
|
||||
There is an error in storing the configuration in the YAML format.
|
||||
|
||||
=head1 EXIT STATUS
|
||||
|
||||
Exit code 0 means that everything should have went fine.
|
||||
Exit code 2 means something with the command line options or retrieving default settings went wrong.
|
||||
Exit code 9 means the specified argument to a command line option is not valid.
|
||||
|
||||
=head1 CONFIGURATION
|
||||
|
||||
There's no configuration file for the ngcp-network script itself supported at the moment.
|
||||
The main configuration file ngcp-network operates on is /etc/ngcp-config/network.yml.
|
||||
|
||||
=head1 DEPENDENCIES
|
||||
|
||||
ngcp-network relies on a bunch of Perl modules, all of them specified as dependencies
|
||||
through the ngcp-ngcpcfg Debian package.
|
||||
|
||||
=head1 INCOMPATIBILITIES
|
||||
|
||||
No known at this time.
|
||||
|
||||
=head1 BUGS AND LIMITATIONS
|
||||
|
||||
Please report problems you notice to the Sipwise Development Team <support@sipwise.com>.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Michael Prokop <mprokop@sipwise.com>
|
||||
|
||||
=head1 LICENSE AND COPYRIGHT
|
||||
|
||||
GPL-3+, Sipwise GmbH, Austria
|
||||
|
||||
=cut
|
@ -0,0 +1,308 @@
|
||||
#!/usr/bin/perl -w
|
||||
#----------------------------------------------------------------------
|
||||
# Syncronizes passwords from constants.yml with MySQL
|
||||
#----------------------------------------------------------------------
|
||||
use strict;
|
||||
use DBI;
|
||||
use YAML::Tiny;
|
||||
use Getopt::Long;
|
||||
use Data::Dumper;
|
||||
#----------------------------------------------------------------------
|
||||
use constant CONSTANTS_YML => "/etc/ngcp-config/constants.yml";
|
||||
use constant MYSQL_CREDENTIALS => "/etc/mysql/sipwise.cnf";
|
||||
use constant MYSQL_DATA => {
|
||||
voisniff => { dbuser => 'dbpassword' },
|
||||
cleanuptools => { dbuser => 'dbpassword' },
|
||||
rsyslog => { dbuser => 'dbpassword' },
|
||||
sems => { dbuser => 'dbpassword',
|
||||
prepaid_dbuser => 'prepaid_dbpassword' },
|
||||
rateomat => { accountingdb => { user => 'pass' } },
|
||||
faxserver => { hylafax => { db_user => 'db_pass' } },
|
||||
cdrexport => { dbuser => 'dbpassword' },
|
||||
checktools => { dbuser => 'dbpassword' },
|
||||
mysql => { repuser => 'reppassword' },
|
||||
kamailio => { proxy => { dbrwuser => 'dbrwpw',
|
||||
dbrouser => 'dbropw' } },
|
||||
mediator => { dbuser => 'dbpassword' },
|
||||
asterisk => { odbc => { dbuser => 'dbpassword' } },
|
||||
ossbss => { provisioning => {
|
||||
billingdb => { user => 'pass' } } },
|
||||
};
|
||||
use constant COPY_PASSWORDS => [ # pairs of from/to
|
||||
{ rateomat => { accountingdb => { user => 'pass' }}},
|
||||
{ rateomat => { billingdb => { user => 'pass' }}},
|
||||
|
||||
{ kamailio => { proxy => { dbrwuser => 'dbrwpw' }}},
|
||||
{ kamailio => { lb => { dbrwuser => 'dbrwpw' }}},
|
||||
|
||||
{ kamailio => { proxy => { dbrouser => 'dbropw' }}},
|
||||
{ kamailio => { lb => { dbrouser => 'dbropw' }}},
|
||||
|
||||
{ ossbss => { provisioning => { billingdb => { user => 'pass' }}}},
|
||||
{ ossbss => { provisioning => { database => { user => 'pass' }}}},
|
||||
|
||||
{ ossbss => { provisioning => { billingdb => { user => 'pass' }}}},
|
||||
{ ossbss => { provisioning => { openserdb => { user => 'pass' }}}},
|
||||
|
||||
{ ossbss => { provisioning => { billingdb => { user => 'pass' }}}},
|
||||
{ reminder => { dbuser => 'dbpassword' }}
|
||||
|
||||
];
|
||||
|
||||
sub Usage {
|
||||
print <<USAGE;
|
||||
==
|
||||
Syncronizes passwords from constants.yml with MySQL
|
||||
==
|
||||
$0 [options]
|
||||
Options:
|
||||
-help|-h|-? -- this help
|
||||
-init-passwords|-i -- generate new passwords (constants.yml is updated)
|
||||
-test|-t -- test mode (no updates)
|
||||
-verbose|-v -- verbose mode
|
||||
USAGE
|
||||
exit 0;
|
||||
}
|
||||
my $dbh;
|
||||
my $mysql_db = 'mysql';
|
||||
my $mysql_host = 'localhost';
|
||||
my $mysql_port = 3360;
|
||||
my $mysql_user = 'sipwise';
|
||||
my $mysql_pass = '';
|
||||
|
||||
my $yml = {};
|
||||
my $yml_ref = {};
|
||||
my $password_length = 20;
|
||||
my $init_passwords = 0;
|
||||
my $debug = 0;
|
||||
my $test_mode = 0;
|
||||
|
||||
GetOptions("h|?|help" => \&Usage,
|
||||
"i|init-passwords" => \$init_passwords,
|
||||
"t|test" => \$test_mode,
|
||||
"v|verbose" => \$debug);
|
||||
#----------------------------------------------------------------------
|
||||
sub pwgen {
|
||||
my @list = ("a".."z",0..9,"A".."Z");
|
||||
my @randoms;
|
||||
for (1..$password_length) {
|
||||
push @randoms, $list[int(rand($#list))];
|
||||
}
|
||||
return join "", @randoms;
|
||||
}
|
||||
|
||||
sub get_mysql_credentials {
|
||||
open(my $fh, "<", MYSQL_CREDENTIALS)
|
||||
or die "Can't open ".MYSQL_CREDENTIALS.": ".$!;
|
||||
($mysql_pass = <$fh>) =~ s/^.+='(.+?)'\s*$/$1/;
|
||||
close $fh;
|
||||
}
|
||||
|
||||
sub connect_db {
|
||||
get_mysql_credentials();
|
||||
$dbh = DBI->connect("DBI:mysql:database=$mysql_db;
|
||||
host=$mysql_host;
|
||||
port=$mysql_port",
|
||||
$mysql_user, $mysql_pass,
|
||||
{ PrintError => 0, AutoCommit => 0 })
|
||||
or die "Can't connect to MySQL database $mysql_db: ". $DBI::errstr;
|
||||
}
|
||||
|
||||
sub sync_mysql_data {
|
||||
|
||||
my $sth_sel = $dbh->prepare(<<SQL);
|
||||
SELECT count(*) from user
|
||||
WHERE User = ?
|
||||
SQL
|
||||
my $sth_upd = $dbh->prepare(<<SQL);
|
||||
UPDATE user
|
||||
SET Password=PASSWORD(?)
|
||||
WHERE User = ?
|
||||
SQL
|
||||
|
||||
foreach my $key (keys %{MYSQL_DATA()}) {
|
||||
$yml_ref = $yml->[0]->{$key};
|
||||
print $key." => " if $debug;
|
||||
my $opts = { init_passwords => $key eq "mysql" ? 0 : $init_passwords };
|
||||
my $data = get_user_pass(MYSQL_DATA->{$key}, $opts);
|
||||
foreach my $pair (@$data) {
|
||||
my $user = $pair->{'user'};
|
||||
my $pass = $pair->{'pass'};
|
||||
next unless ($user && $pass);
|
||||
$sth_sel->execute($user);
|
||||
(my $count) = $sth_sel->fetchrow_array();
|
||||
if ($count) {
|
||||
print " ---> updating $user => $pass\n" if $debug;
|
||||
$sth_upd->execute($pass, $user) unless $test_mode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$sth_sel->finish;
|
||||
$sth_upd->finish;
|
||||
|
||||
return if $test_mode;
|
||||
|
||||
$dbh->do('FLUSH PRIVILEGES')
|
||||
or die "Can't flush MySQL privileges: ". $DBI::errstr;
|
||||
}
|
||||
|
||||
sub get_user_pass {
|
||||
my $h_ref = shift || "No data passed to fetch_mysql_data";
|
||||
my $opts = shift;
|
||||
|
||||
my @data;
|
||||
foreach my $ref (keys %$h_ref) {
|
||||
if (ref($ref) eq 'HASH') {
|
||||
return get_user_pass($ref, $opts);
|
||||
} elsif (ref($h_ref->{$ref}) eq 'HASH') {
|
||||
print $ref." => " if $debug;
|
||||
$yml_ref = $yml_ref->{$ref};
|
||||
return get_user_pass($h_ref->{$ref}, $opts);
|
||||
} else {
|
||||
print " ".$ref." -- ".$h_ref->{$ref} if $debug;
|
||||
$opts->{'init_passwords'} and $yml_ref->{$h_ref->{$ref}} = pwgen();
|
||||
my %pair;
|
||||
$pair{'user'} = $yml_ref->{$ref};
|
||||
$pair{'pass'} = $yml_ref->{$h_ref->{$ref}};
|
||||
$pair{'user_key'} = $ref;
|
||||
$pair{'pass_key'} = $h_ref->{$ref};
|
||||
push @data, \%pair;
|
||||
}
|
||||
}
|
||||
print "\n" if $debug;
|
||||
return \@data;
|
||||
}
|
||||
|
||||
sub copy_passwords {
|
||||
print "Copying internal passwords\n" if $debug;
|
||||
my $saved_init_passwords = $init_passwords;
|
||||
$init_passwords = 0;
|
||||
my $pairs_count = $#{+COPY_PASSWORDS};
|
||||
for (my $idx=0;$idx<$pairs_count+1;$idx++) {
|
||||
next if $idx % 2;
|
||||
die "Incorrect from/to pair" if $idx+1 >= $pairs_count+1;
|
||||
$yml_ref = $yml->[0];
|
||||
print "from => " if $debug;
|
||||
my $from_data = get_user_pass(COPY_PASSWORDS->[$idx]);
|
||||
die "No 'from' user/pass data available" if $#$from_data == -1;
|
||||
$yml_ref = $yml->[0];
|
||||
print "to => " if $debug;
|
||||
my $to_data = get_user_pass(COPY_PASSWORDS->[$idx+1]);
|
||||
die "No 'from' user/pass data available" if $#$to_data == -1;
|
||||
my $user = $from_data->[0]{'user'};
|
||||
my $pass = $from_data->[0]{'pass'};
|
||||
my $user_key = $to_data->[0]{'user_key'};
|
||||
my $pass_key = $to_data->[0]{'pass_key'};
|
||||
if ($user && $pass && $user_key && $pass_key) {
|
||||
print " ---> updating $user => $pass\n" if $debug;
|
||||
$yml_ref->{$user_key} = $user;
|
||||
$yml_ref->{$pass_key} = $pass;
|
||||
}
|
||||
}
|
||||
$init_passwords = $saved_init_passwords;
|
||||
}
|
||||
|
||||
sub main {
|
||||
$yml = new YAML::Tiny;
|
||||
$yml = YAML::Tiny->read(CONSTANTS_YML)
|
||||
or die "Can't read constants file: $!\n";
|
||||
|
||||
if ($init_passwords and not $test_mode and not -w CONSTANTS_YML) {
|
||||
die CONSTANTS_YML . " is not writable";
|
||||
}
|
||||
|
||||
print "[TEST MODE]\n" if $test_mode;
|
||||
|
||||
connect_db();
|
||||
eval {
|
||||
$dbh->begin_work;
|
||||
print "Syncing ".CONSTANTS_YML." -> MySQL ... ";
|
||||
print "\n" if $debug;
|
||||
sync_mysql_data();
|
||||
};
|
||||
if ($@) {
|
||||
$dbh->rollback;
|
||||
die "\nError during syncronization: " . $@;
|
||||
} else {
|
||||
$test_mode ? $dbh->rollback : $dbh->commit;
|
||||
}
|
||||
$dbh->disconnect if $dbh;
|
||||
|
||||
print "Done.\n";
|
||||
|
||||
return unless $init_passwords;
|
||||
|
||||
copy_passwords();
|
||||
|
||||
return if $test_mode;
|
||||
|
||||
print "Writing new passwords into ".CONSTANTS_YML." ... ";
|
||||
$yml->write(CONSTANTS_YML);
|
||||
print "Done\n";
|
||||
|
||||
# print Data::Dumper->Dumpxs([$yml]),"\n";
|
||||
}
|
||||
#----------------------------------------------------------------------
|
||||
main();
|
||||
|
||||
exit 0;
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
ngcp-sync-constants - syncronizes passwords from constants.yml with MySQL
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
ngcp-sync-constants [ options ... ]
|
||||
|
||||
=over 8
|
||||
|
||||
=item B<--init-passwords>
|
||||
New passwords are generated (passwords for "mysql" is not generated to avoid replication problems)
|
||||
|
||||
=item B<--test>
|
||||
No real updates, only for checks
|
||||
|
||||
=item B<--verbose>
|
||||
Verbose mode where all changes are written to STDOUT
|
||||
|
||||
=back
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
B<This program> reads constants.yml file, parses it and syncronizes all required passwords with MySQL
|
||||
|
||||
=head1 EXIT STATUS
|
||||
|
||||
=over 8
|
||||
|
||||
=item B<exit code 0>
|
||||
Everything is ok
|
||||
|
||||
=item B<exit code != 0>
|
||||
Something is wrong, an error message raises
|
||||
|
||||
=back
|
||||
|
||||
=head1 INCOMPATIBILITIES
|
||||
|
||||
No known at this time.
|
||||
|
||||
=head1 BUGS AND LIMITATIONS
|
||||
|
||||
Please report problems you notice to the Sipwise Development Team <support@sipwise.com>.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Kirill Solomko <ksolomko@sipwise.com>
|
||||
|
||||
=head1 LICENSE AND COPYRIGHT
|
||||
|
||||
GPL-3+, Sipwise GmbH, Austria
|
||||
|
||||
=cut
|
@ -0,0 +1,147 @@
|
||||
#!/bin/bash
|
||||
# Purpose: user interface for configuration management system
|
||||
################################################################################
|
||||
|
||||
set -e
|
||||
set -u
|
||||
|
||||
# support for testsuite
|
||||
if [ -z "${FUNCTIONS:-}" ] ; then
|
||||
FUNCTIONS='/usr/share/ngcp-ngcpcfg/functions/'
|
||||
fi
|
||||
|
||||
if [ -z "${SCRIPTS:-}" ] ; then
|
||||
SCRIPTS='/usr/share/ngcp-ngcpcfg/scripts/'
|
||||
fi
|
||||
|
||||
if ! [ -r "${FUNCTIONS}/main" ] ; then
|
||||
printf "Error: ${FUNCTIONS}/main could not be read. Exiting.\n" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ "${1:-}" == "decrypt" ]] ; then
|
||||
# do NOT source ${FUNCTIONS}/main but just provide
|
||||
# the part we need for executing ngcpcfg itself
|
||||
log_debug() {
|
||||
if [ -n "${DEBUG:-}" ] ; then
|
||||
logger -t ngcpcfg -- "Debug: $*"
|
||||
echo ; echo "DEBUG: $*" ; echo # newlines to avoid messup with cmdline output
|
||||
fi
|
||||
}
|
||||
else
|
||||
. ${FUNCTIONS}/main
|
||||
fi
|
||||
|
||||
# helper functions
|
||||
initialise() {
|
||||
log_debug "${SCRIPTS}/initialise $*"
|
||||
"${SCRIPTS}"/initialise $*
|
||||
}
|
||||
|
||||
build() {
|
||||
log_debug "${SCRIPTS}/build $*"
|
||||
"${SCRIPTS}"/build $*
|
||||
}
|
||||
|
||||
services() {
|
||||
log_debug "${SCRIPTS}/services $*"
|
||||
"${SCRIPTS}"/services $*
|
||||
}
|
||||
|
||||
encrypt() {
|
||||
log_debug "${SCRIPTS}/encrypt $*"
|
||||
"${SCRIPTS}"/encrypt $*
|
||||
}
|
||||
|
||||
decrypt() {
|
||||
log_debug "${SCRIPTS}/decrypt $*"
|
||||
"${SCRIPTS}"/decrypt $*
|
||||
}
|
||||
|
||||
diff() {
|
||||
log_debug "${SCRIPTS}/diff $*"
|
||||
"${SCRIPTS}"/diff $*
|
||||
}
|
||||
|
||||
etckeeper() {
|
||||
log_debug "${SCRIPTS}/etckeeper $*"
|
||||
"${SCRIPTS}"/etckeeper $*
|
||||
}
|
||||
|
||||
commit() {
|
||||
log_debug "${SCRIPTS}/commit $*"
|
||||
"${SCRIPTS}"/commit $*
|
||||
}
|
||||
|
||||
status() {
|
||||
log_debug "${SCRIPTS}/status $*"
|
||||
"${SCRIPTS}"/status $*
|
||||
}
|
||||
|
||||
usage() {
|
||||
# make sure to output errors on stderr
|
||||
[ "${1:-}" = "1" ] && exec >&2
|
||||
|
||||
printf "%s - Configuration Management System\n\n" "$PN"
|
||||
printf "Usage:
|
||||
|
||||
$PN build [opts] - generate/update configuration files
|
||||
$PN commit [msg] - commit and record changes (without pushing)
|
||||
$PN diff [opts] - display pending configuration changes
|
||||
$PN help - display this help screen and exit
|
||||
$PN version - display program version and exit
|
||||
$PN initialise - initialise setup (to be executed only once on setup)
|
||||
"
|
||||
|
||||
# display only if ngcp-ngcpcfg-ha is available
|
||||
if [ -r /usr/share/ngcp-ngcpcfg/functions/ha_features ] ; then
|
||||
printf " $PN push [opts] - push modifications to other systems (shared storage setup only)\n"
|
||||
printf " $PN pull - retrieve modifications from shared storage (shared storage setup only)\n"
|
||||
# printf " $PN upgrade - upgrade all systems [WIP - do not use unless you know what you are doing!]\n"
|
||||
fi
|
||||
|
||||
# display only if ngcp-ngcpcfg-locker is available
|
||||
if [ -r /usr/share/ngcp-ngcpcfg/scripts/encrypt ] ; then
|
||||
printf " $PN encrypt - encrypt /etc/ngcp-config and all resulting configuration files\n"
|
||||
printf " $PN decrypt - decrypt /etc/ngcp-config-crypted.tgz.gpg and restore config files\n"
|
||||
fi
|
||||
|
||||
# display only if ngcp-ngcpcfg-carrier is available
|
||||
if [ -r /usr/share/ngcp-ngcpcfg/scripts/init-mgmt ] ; then
|
||||
printf " $PN init-mgmt <srv> - set up mgmgt server for carrier environment (to be executed only once)\n"
|
||||
fi
|
||||
|
||||
printf " $PN services [opts] - execute service handlers for modified configuration files
|
||||
$PN apply - a short-cut for build-services-commit-etckeeper
|
||||
$PN status - display status of configuration file\n\n"
|
||||
|
||||
printf "For further usage information and options visit the ngcpcfg manpage.\n"
|
||||
}
|
||||
|
||||
version() {
|
||||
versinfo=$(dpkg --list ngcp-ngcpcfg 2>/dev/null | awk '/^ii/ {print $3}')
|
||||
[ -n "${versinfo:-}" ] || versinfo='information not available'
|
||||
printf "ngcpcfg, version ${versinfo}\n"
|
||||
}
|
||||
|
||||
case ${1:-} in
|
||||
build) shift ; build "$*" ;;
|
||||
commit) shift ; commit "$*" ;;
|
||||
initialise) initialise;;
|
||||
push) shift ; push "$*" ;;
|
||||
pull) shift ; pull "$*" ;;
|
||||
services) shift ; services "$*" ;;
|
||||
status) status;;
|
||||
apply) shift ; build && services && commit "$*" && etckeeper ;;
|
||||
encrypt) shift ; encrypt "$*" ;;
|
||||
decrypt) shift ; decrypt "$*" ;;
|
||||
upgrade) shift ; upgrade "$*" ;;
|
||||
diff) shift ; diff "$*" ;;
|
||||
init-mgmt) shift ; init-mgmt "$*" ;;
|
||||
--debug) export DEBUG=1 ; shift ; $0 $* ;;
|
||||
-h|--help|help) usage ; exit 0;;
|
||||
-v|--version|version) version ; exit 0;;
|
||||
*) usage 1; exit 1;;
|
||||
esac
|
||||
|
||||
## END OF FILE #################################################################
|
@ -0,0 +1,129 @@
|
||||
#!/bin/bash
|
||||
# Purpose: search for existing .tt2 (template toolkit) files
|
||||
# and generate configuration files based on ngcpcfg's config
|
||||
################################################################################
|
||||
|
||||
set -e
|
||||
set -u
|
||||
|
||||
# support testsuite
|
||||
if [ -z "${FUNCTIONS:-}" ] ; then
|
||||
FUNCTIONS='/usr/share/ngcp-ngcpcfg/functions/'
|
||||
fi
|
||||
|
||||
if [ -z "${HELPER:-}" ] ; then
|
||||
HELPER='/usr/share/ngcp-ngcpcfg/helper/'
|
||||
fi
|
||||
|
||||
if ! [ -r ${FUNCTIONS}/main ] ; then
|
||||
printf "Error: ${FUNCTIONS}/main could not be read. Exiting.\n" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
. ${FUNCTIONS}/main
|
||||
|
||||
MODIFIED_ONLY=false
|
||||
if [ -n "${1:-}" ] ; then
|
||||
case "$1" in
|
||||
*--modified-only*) MODIFIED_ONLY=true ; shift ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# make sure encoding is OK
|
||||
for f in ${NGCPCTL_CONFIG:-} ${HOST_CONFIG:-} ${LOCAL_CONFIG:-} ${NETWORK_CONFIG:-} ${CONSTANTS_CONFIG:-} ; do
|
||||
if [ -r "$f" ] && ! file "$f" | grep -qe "UTF-8" -qe "ASCII" ; then
|
||||
log_error "Encoding check of ${f} fails: neither ASCII nor UTF-8."
|
||||
log_error "Please convert ${f} to UTF-8."
|
||||
log_info
|
||||
log_info "NOTE:"
|
||||
log_info "* Check encoding via:"
|
||||
log_info " # file ${f}"
|
||||
log_info "* To convert ISO-8859/latin1 to UTF-8 execute:"
|
||||
log_info " # iconv -f latin1 -t utf8 < ${f} > ${f}.tmp && mv ${f}.tmp ${f}"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
# check for valid YAML syntax
|
||||
for f in ${NGCPCTL_CONFIG:-} ${HOST_CONFIG:-} ${LOCAL_CONFIG:-} ${NETWORK_CONFIG:-} ${CONSTANTS_CONFIG:-} ; do
|
||||
if [ -r "$f" ] ; then
|
||||
# use YAML::Tiny for checking
|
||||
log_debug "Validating main YAML syntax of ${f}"
|
||||
if ! "${HELPER}/validate-yml" "${f}" 2>/dev/null ; then
|
||||
log_error "Invalid file syntax in ${f}:"
|
||||
"${HELPER}/validate-yml" "${f}"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
build_config_files() {
|
||||
for file in $(generate_template_list $*) ; do
|
||||
log_debug "${HELPER}/build_config $file"
|
||||
"${HELPER}/build_config" "${file}"
|
||||
RC=$(($RC + $?))
|
||||
done
|
||||
}
|
||||
|
||||
# main script
|
||||
RC=0
|
||||
|
||||
if ! $MODIFIED_ONLY ; then
|
||||
build_config_files "$*"
|
||||
else
|
||||
log_info "Considering modified files only due to --modified-only option."
|
||||
|
||||
if git status | grep -q 'working directory clean' ; then
|
||||
log_info "No changes found, nothing to do."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if git diff-index --name-only HEAD | grep \
|
||||
-qe "$(basename $NGCPCTL_CONFIG)" \
|
||||
-qe "$(basename $HOST_CONFIG)" \
|
||||
-qe "$(basename $LOCAL_CONFIG)" \
|
||||
-qe "$(basename $NETWORK_CONFIG)" \
|
||||
-qe "$(basename $CONSTANTS_CONFIG)" ; then
|
||||
log_info "Main configuation files has been changed, running full rebuild."
|
||||
log_debug "Executing: build_config_files $*"
|
||||
build_config_files "$*"
|
||||
fi
|
||||
|
||||
if git diff-index --name-only HEAD | grep -q templates/ || \
|
||||
git status --porcelain | awk '/^\?\? / {print $2}' 2>/dev/null | grep -q templates/ ; then
|
||||
log_debug "Template config changed, identifying files."
|
||||
for file in $(git diff-index --name-only HEAD) \
|
||||
$(git status --porcelain | awk '/^\?\? / {print $2}') ; do
|
||||
build_file="${file##templates/}"
|
||||
build_file="${build_file%%.services}"
|
||||
build_file="${build_file%%.customtt}"
|
||||
|
||||
# drop HA file suffix of all registered nodes
|
||||
if [ -r /etc/ngcp-config/systems.cfg ] ; then
|
||||
for host in $(cat /etc/ngcp-config/systems.cfg) ; do
|
||||
build_file="${build_file%%.${host}}"
|
||||
done
|
||||
fi
|
||||
|
||||
build_file="${build_file%%.tt2}"
|
||||
build_file="/${build_file}"
|
||||
|
||||
# generate file list
|
||||
case "${file_list:-}" in
|
||||
# avoid duplicates
|
||||
*"${build_file}"*) # do nothing
|
||||
;;
|
||||
# append to file list
|
||||
*) file_list=" ${file_list:-} $build_file"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
log_debug "Executing: build_config_files ${file_list}"
|
||||
build_config_files ${file_list}
|
||||
fi
|
||||
fi
|
||||
|
||||
exit "$RC"
|
||||
|
||||
## END OF FILE #################################################################
|
@ -0,0 +1,67 @@
|
||||
#!/bin/bash
|
||||
# Purpose: commit pending changes
|
||||
################################################################################
|
||||
|
||||
set -e
|
||||
set -u
|
||||
|
||||
if ! [ -r /usr/share/ngcp-ngcpcfg/functions/main ] ; then
|
||||
printf "Error: /usr/share/ngcp-ngcpcfg/functions/main could not be read. Exiting.\n" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
. /usr/share/ngcp-ngcpcfg/functions/main
|
||||
|
||||
if [ -z "${HELPER:-}" ] ; then
|
||||
HELPER='/usr/share/ngcp-ngcpcfg/helper/'
|
||||
fi
|
||||
|
||||
# main script
|
||||
|
||||
cd "$NGCPCTL_MAIN"
|
||||
|
||||
"${HELPER}/sync-db" "$NGCPCTL_CONFIG" "$CONSTANTS_CONFIG" || true
|
||||
|
||||
|
||||
if ! git config user.name >/dev/null ; then
|
||||
log_debug 'git config user.name ngcp-config'
|
||||
git config user.name "ngcp-config"
|
||||
fi
|
||||
if ! git config user.email >/dev/null ; then
|
||||
log_debug 'git config user.email "root@$(hostname)"'
|
||||
git config user.email "root@$(hostname)"
|
||||
fi
|
||||
|
||||
if ! git config --global user.name >/dev/null ; then
|
||||
log_debug 'git config --global user.name "git user on $(hostname)"'
|
||||
git config --global user.name "git user on $(hostname)"
|
||||
fi
|
||||
if ! git config --global user.email >/dev/null ; then
|
||||
log_debug 'git config --global user.email "root@$(hostname)"'
|
||||
git config --global user.email "root@$(hostname)"
|
||||
fi
|
||||
|
||||
# commit message
|
||||
if [ -z "${1:-}" ] ; then
|
||||
msg="commiting uncommented changes"
|
||||
else
|
||||
msg="$*"
|
||||
fi
|
||||
|
||||
log_debug "git status | grep -q 'working directory clean'"
|
||||
if git status | grep -q 'working directory clean' ; then
|
||||
log_info "OK: nothing to commit."
|
||||
else
|
||||
log_debug 'git add . ; git commit -a -m "$msg [$(date --rfc-3339=ns)]"'
|
||||
git add .
|
||||
git commit -a -m "$msg [$(date --rfc-3339=ns)]" >/dev/null
|
||||
log_info "OK"
|
||||
fi
|
||||
|
||||
log_debug "/usr/share/ngcp-ngcpcfg/scripts/etckeeper"
|
||||
/usr/share/ngcp-ngcpcfg/scripts/etckeeper >/dev/null
|
||||
|
||||
log_info "Synchronizing data from ${CONSTANTS_CONFIG}"
|
||||
ngcp-sync-constants >/dev/null
|
||||
|
||||
## END OF FILE #################################################################
|
@ -0,0 +1,88 @@
|
||||
#!/bin/bash
|
||||
# Purpose: decrypt ngcp configuration archive
|
||||
################################################################################
|
||||
|
||||
set -e
|
||||
set -u
|
||||
|
||||
# helper functions {{{
|
||||
# sadly we can't source ${FUNCTIONS}/main as we are missing a bunch of
|
||||
# configuration files that are supposed to be available, therefore
|
||||
# provide the main functions we need for successfull execution of the
|
||||
# decrypt function
|
||||
log_info() {
|
||||
logger -t ngcpcfg -- "$*"
|
||||
echo "$*"
|
||||
}
|
||||
|
||||
# info without ending newline
|
||||
log_info_n() {
|
||||
logger -t ngcpcfg -- "$*"
|
||||
printf -- "$*"
|
||||
}
|
||||
log_debug() {
|
||||
if [ -n "${DEBUG:-}" ] ; then
|
||||
logger -t ngcpcfg -- "Debug: $*"
|
||||
echo ; echo "DEBUG: $*" ; echo # newlines to avoid messup with cmdline output
|
||||
fi
|
||||
}
|
||||
|
||||
log_warn() {
|
||||
logger -t ngcpcfg -- "Warning: $*"
|
||||
echo "Warning: $*"
|
||||
}
|
||||
|
||||
log_error() {
|
||||
logger -t ngcpcfg -- "Error: $*"
|
||||
echo "Error: $*" >&2
|
||||
}
|
||||
# }}}
|
||||
|
||||
# main script
|
||||
if ! type -p gpg &>/dev/null ; then
|
||||
log_error "gpg binary not found, exiting."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
RC=0
|
||||
TARGZ=/etc/ngcp-config-crypted.tgz
|
||||
|
||||
if ! gpg -d "$TARGZ".gpg > "$TARGZ" ; then
|
||||
log_error "Error while decrypting ${TARGZ}.gpg"
|
||||
RC=1
|
||||
else
|
||||
cd / # important to extract files at according place
|
||||
if tar zxf "$TARGZ" ; then
|
||||
log_info "Successfully restored configuration archive ${TARGZ}.gpg"
|
||||
log_info "Now you should be able to run 'ngcpcfg apply' again."
|
||||
else
|
||||
log_error "Error while restoring ${TARGZ}.gpg"
|
||||
RC=1
|
||||
fi
|
||||
fi
|
||||
|
||||
if ! [ -d /mnt/glusterfs/shared_config ] ; then
|
||||
log_warn "Looks like glusterfs is not running, can not install it automatically.
|
||||
|
||||
Please execute the following command on one node
|
||||
as soon as glusterfs share is mounted again:
|
||||
|
||||
git clone --bare /etc/ngcp-config /mnt/glusterfs/ngcpcfg-share
|
||||
|
||||
|
||||
"
|
||||
else
|
||||
if [ -d /mnt/glusterfs/ngcpcfg-share ] ; then
|
||||
log_info "Shared storage exists already, ignoring request to (re)install it."
|
||||
else
|
||||
log_info "Copying git repository to shared storage."
|
||||
git clone --bare /etc/ngcp-config /mnt/glusterfs/ngcpcfg-share
|
||||
fi
|
||||
fi
|
||||
|
||||
# don't leave the unencrypted archive behind
|
||||
rm -f "$TARGZ"
|
||||
|
||||
exit "$RC"
|
||||
|
||||
## END OF FILE #################################################################
|
@ -0,0 +1,36 @@
|
||||
#!/bin/bash
|
||||
# Purpose: show changes in configuration pool
|
||||
################################################################################
|
||||
|
||||
set -e
|
||||
set -u
|
||||
|
||||
if ! [ -r /usr/share/ngcp-ngcpcfg/functions/main ] ; then
|
||||
printf "Error: /usr/share/ngcp-ngcpcfg/functions/main could not be read. Exiting.\n" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
. /usr/share/ngcp-ngcpcfg/functions/main
|
||||
|
||||
# main script
|
||||
log_debug "cd $NGCPCTL_MAIN"
|
||||
cd "$NGCPCTL_MAIN"
|
||||
|
||||
log_debug "git diff $*"
|
||||
git diff $*
|
||||
|
||||
# added files
|
||||
log_debug "git status --porcelain | awk '/^\?\? / {print \$2}'"
|
||||
if git status --porcelain | awk '/^\?\? / {print $2}' | grep -q . ; then
|
||||
log_info "* New but not yet registered files inside ${NGCPCTL_MAIN}:"
|
||||
git status --porcelain | awk '/^\?\? / {print $2}'
|
||||
fi
|
||||
|
||||
# deleted files
|
||||
log_debug "git status --porcelain | awk '/^D / {print \$2}'"
|
||||
if git status --porcelain | awk '/^D / {print $2}' | grep -q . ; then
|
||||
log_info "* Removed but not yet unregistered files inside ${NGCPCTL_MAIN}:"
|
||||
git status --porcelain | awk '/^D / {print $2}'
|
||||
fi
|
||||
|
||||
## END OF FILE #################################################################
|
@ -0,0 +1,71 @@
|
||||
#!/bin/bash
|
||||
# Purpose: encrypt ngcp configuration files
|
||||
################################################################################
|
||||
|
||||
set -e
|
||||
set -u
|
||||
|
||||
# support testsuite
|
||||
if [ -z "${FUNCTIONS:-}" ] ; then
|
||||
FUNCTIONS='/usr/share/ngcp-ngcpcfg/functions/'
|
||||
fi
|
||||
|
||||
if [ -z "${HELPER:-}" ] ; then
|
||||
HELPER='/usr/share/ngcp-ngcpcfg/helper/'
|
||||
fi
|
||||
|
||||
if ! [ -r ${FUNCTIONS}/main ] ; then
|
||||
printf "Error: ${FUNCTIONS}/main could not be read. Exiting.\n" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
. ${FUNCTIONS}/main
|
||||
|
||||
get_config_file_list() {
|
||||
for file in $(find "$TEMPLATE_POOL" -name \*.tt2 -o -name \*.tt2"${HA_FILE:-}") ; do
|
||||
x=${file##${NGCPCTL_MAIN}/templates/} # drop leading /etc/ngcp-config
|
||||
y=${x%%.tt2} # drop trailing suffix '.tt2'
|
||||
y=${y%%.tt2.sp1} # drop trailing suffix '.tt2.sp1'
|
||||
y=${y%%.tt2.sp2} # drop trailing suffix '.tt2.sp2'
|
||||
y=${y%%.customtt} # drop trailing suffix '.customtt'
|
||||
# if the file does not exist (e.g. because "ngcpcfg apply"
|
||||
# hasn't been executed yet for whatever reason, then don't
|
||||
# report missing files, otherwise tar will complain
|
||||
if [ -r "/${y}" ] ; then
|
||||
echo "/${y}"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# main script
|
||||
if ! type -p gpg &>/dev/null ; then
|
||||
log_error "gpg binary not found, exiting."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
RC=0
|
||||
TARGZ=/etc/ngcp-config-crypted.tgz
|
||||
FILES=$(get_config_file_list)
|
||||
|
||||
tar zcf "$TARGZ" /etc/ngcp-config/ $FILES /etc/.git
|
||||
if gpg --symmetric "$TARGZ" ; then
|
||||
log_info "Successfully created crypted ngcpcfg configuration archive ${TARGZ}.gpg"
|
||||
else
|
||||
log_error "Error while setting up $TARGZ"
|
||||
RC=1
|
||||
fi
|
||||
|
||||
log_info_n "Now really erase all configuration files managed by ngcpcfg? [y/N] "
|
||||
a='' ; read a
|
||||
if [[ "$a" == "y" ]] || [ "$a" == "Y" ]] ; then
|
||||
rm -rf "$NGCPCTL_MAIN" ; rm -f "$TARGZ" ; rm -f $FILES ; rm -rf /etc/.git
|
||||
# make sure we don't leavy any stuff on shared storage
|
||||
rm -rf /var/lib/glusterfs/export/ngcpcfg-share
|
||||
rm -rf /mnt/glusterfs/ngcpcfg-share/
|
||||
else
|
||||
log_info "Skipping as requested."
|
||||
fi
|
||||
|
||||
exit "$RC"
|
||||
|
||||
## END OF FILE #################################################################
|
@ -0,0 +1,41 @@
|
||||
#!/bin/bash
|
||||
# Purpose: wrapper around etckeeper for usage inside ngcpcfg
|
||||
################################################################################
|
||||
|
||||
set -e
|
||||
set -u
|
||||
|
||||
if ! [ -r /usr/share/ngcp-ngcpcfg/functions/main ] ; then
|
||||
printf "Error: /usr/share/ngcp-ngcpcfg/functions/main could not be read. Exiting.\n" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
. /usr/share/ngcp-ngcpcfg/functions/main
|
||||
|
||||
# main script
|
||||
|
||||
log_debug "cd /etc"
|
||||
cd /etc
|
||||
|
||||
log_debug "type -p etckeeper"
|
||||
if ! type -p etckeeper &>/dev/null ; then
|
||||
log_warn "etckeeper is not available, skipping etckeeper execution"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
log_debug "test -d .git"
|
||||
if ! [ -d .git ] ; then
|
||||
log_warn "etckeeper has not been initialized yet, skipping etckeeper execution"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
log_info "Checking state of /etc files"
|
||||
log_debug 'git status | grep -q "working directory clean"'
|
||||
if git status | grep -q 'working directory clean' ; then
|
||||
log_info "OK: nothing to commit."
|
||||
else
|
||||
log_debug 'etckeeper commit "ngcpcfg apply on $(date)"'
|
||||
etckeeper commit "ngcpcfg apply on $(date)"
|
||||
fi
|
||||
|
||||
## END OF FILE #################################################################
|
@ -0,0 +1,78 @@
|
||||
#!/bin/bash
|
||||
# Purpose: initialise ngcpcfg setup
|
||||
################################################################################
|
||||
|
||||
set -e
|
||||
set -u
|
||||
|
||||
if ! [ -r /usr/share/ngcp-ngcpcfg/functions/main ] ; then
|
||||
printf "Error: /usr/share/ngcp-ngcpcfg/functions/main could not be read. Exiting.\n" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
. /usr/share/ngcp-ngcpcfg/functions/main
|
||||
|
||||
# main script
|
||||
|
||||
log_debug "cd $NGCPCTL_MAIN"
|
||||
cd "$NGCPCTL_MAIN"
|
||||
|
||||
if [ -d .git ] ; then
|
||||
log_info "Git directory in $NGCPCTL_MAIN exists already, skipping creation."
|
||||
else
|
||||
log_debug "git init"
|
||||
git init >/dev/null
|
||||
fi
|
||||
|
||||
# ignore files we do not consider as valid template files
|
||||
if ! grep -qs '^# begin section managed by ngcpcfg' .gitignore ; then
|
||||
echo '# begin section managed by ngcpcfg (do not edit this section by hand)
|
||||
# new and old versions of conffiles, stored by dpkg
|
||||
*.dpkg-*
|
||||
# new and old versions of conffiles, stored by ucf
|
||||
*.ucf-*
|
||||
|
||||
# old versions of files
|
||||
*.old
|
||||
|
||||
# editor temp files
|
||||
*~
|
||||
.*.sw?
|
||||
.sw?
|
||||
\#*\#
|
||||
DEADJOE
|
||||
|
||||
# end section managed by ngcpcfg' >> .gitignore
|
||||
fi
|
||||
|
||||
log_debug "git add ."
|
||||
git add .
|
||||
|
||||
if ! git status | grep -q 'working directory clean' ; then
|
||||
log_debug "git commit -a -m \"initial version of ngcpcfg on $HNAME\""
|
||||
git commit -a -m "initial version of ngcpcfg on $HNAME" >/dev/null
|
||||
fi
|
||||
|
||||
if type -p init_ha &>/dev/null ; then
|
||||
log_debug "init_ha function"
|
||||
init_ha
|
||||
fi
|
||||
|
||||
if ! [ -r /etc/.gitignore ] ; then
|
||||
log_info "etckeeper not present, ignoring request to add ngcp-config to /etc/.gitignore."
|
||||
else
|
||||
log_debug 'grep -q ngcp-config /etc/.gitignore'
|
||||
if ! grep -q ngcp-config /etc/.gitignore ; then
|
||||
log_info_n "etckeeper seems to be present, adding "$NGCPCTL_MAIN" to ignore list: "
|
||||
echo "ngcp-config" >> /etc/.gitignore
|
||||
log_debug 'cd /etc ; git add .gitignore ; git commit -m "add ngcp-config directory to .gitignore"'
|
||||
cd /etc
|
||||
git add .gitignore
|
||||
git commit -m 'add ngcp-config directory to .gitignore' >/dev/null
|
||||
log_info "OK"
|
||||
fi
|
||||
fi
|
||||
|
||||
log_info "Successfully finished setup."
|
||||
|
||||
## END OF FILE #################################################################
|
@ -0,0 +1,98 @@
|
||||
#!/bin/bash
|
||||
# Purpose: detect modified files in config tree and execute
|
||||
# any defined service modifications
|
||||
################################################################################
|
||||
|
||||
set -e
|
||||
set -u
|
||||
|
||||
if ! [ -r /usr/share/ngcp-ngcpcfg/functions/main ] ; then
|
||||
printf "Error: /usr/share/ngcp-ngcpcfg/functions/main could not be read. Exiting.\n" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
. /usr/share/ngcp-ngcpcfg/functions/main
|
||||
|
||||
# main script
|
||||
|
||||
cd "$CONFIG_POOL"
|
||||
|
||||
DRYRUN='false'
|
||||
if [[ "${1:-}" == "test" ]] || [[ "${1:-}" == "--dry-run" ]]; then
|
||||
DRYRUN='true'
|
||||
elif [[ -n "${1:-}" ]] ; then
|
||||
log_error "Unsupported option(s) given: $*"
|
||||
log_info "Did you mean '--dry-run'?"
|
||||
exit 1
|
||||
fi
|
||||
log_debug "DRYRUN = $DRYRUN"
|
||||
|
||||
TMPFILE="$(mktemp)"
|
||||
|
||||
# unify service calls
|
||||
unifyer() {
|
||||
file="$1"
|
||||
|
||||
# make sure services are listed just once to
|
||||
# avoid re-execution of services (which will
|
||||
# happen if /etc/foo/ngcpcfg.services exists
|
||||
# and several file inside /etc/foo are modified)
|
||||
if ! grep -q "^${file}$" "$TMPFILE" ; then
|
||||
echo "$file" >> $TMPFILE
|
||||
fi
|
||||
}
|
||||
|
||||
# NOTES:
|
||||
# * 'git ls-files -o' also shows ignored files
|
||||
# * 'git status --porcelain |grep '^?? ' not available in git 1.5
|
||||
|
||||
# The 'git diff' command fixes a strange race condition where 'git diff-index'
|
||||
# lists *all* generated file(s) where the time stamp differs, resulting in a
|
||||
# list of *all* generated files (which is not what we want).
|
||||
# After running 'git diff' the following 'git diff-index ...' command lists
|
||||
# only the modified files as we want and need it. See BTS #211 for bugreport.
|
||||
git diff &>/dev/null
|
||||
|
||||
for file in $(git diff-index --name-only HEAD) ; do
|
||||
if [ -r "$file" ] && [ -r "${SERVICES_POOL}/${file}".services ] ; then
|
||||
log_debug "unifyer ${SERVICES_POOL}/${file}.services"
|
||||
unifyer "${SERVICES_POOL}/${file}".services
|
||||
elif [ -r "$file" ] && [ -r $SERVICES_POOL/"$(dirname $file)"/ngcpcfg.services ] ; then
|
||||
log_debug "unifyer ${SERVICES_POOL}/$(dirname $file)/ngcpcfg.services"
|
||||
unifyer "${SERVICES_POOL}"/"$(dirname $file)/ngcpcfg.services"
|
||||
fi
|
||||
done
|
||||
|
||||
exec_wrapper() {
|
||||
# normalize path (get rid of "./" and "//")
|
||||
line="$(echo $1 | sed -e 's/\.\///g ; s/\/\//\//g')"
|
||||
|
||||
if $DRYRUN ; then
|
||||
log_info "TEST MODE: Would execute action for ${line}"
|
||||
return 0
|
||||
fi
|
||||
|
||||
log_info "Executing action for $line"
|
||||
if [ -x "$line" ] ; then
|
||||
log_debug "$line"
|
||||
if ! "$line" ; then
|
||||
log_warn "$line returned with error code, continuing anyway."
|
||||
fi
|
||||
elif [ -r "$line" ] ; then
|
||||
log_debug "bash $line"
|
||||
if ! bash "$line" ; then
|
||||
log_warn "$line returned with error code, continuing anyway."
|
||||
fi
|
||||
else
|
||||
log_error "Error: $line could not be read."
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
for line in $(cat $TMPFILE) ; do
|
||||
exec_wrapper "$line"
|
||||
done
|
||||
|
||||
rm -f "$TMPFILE"
|
||||
|
||||
## END OF FILE #################################################################
|
@ -0,0 +1,69 @@
|
||||
#!/bin/bash
|
||||
# Purpose: display state of ngcpcfg setup and pending/recommended actions
|
||||
################################################################################
|
||||
|
||||
set -e
|
||||
set -u
|
||||
|
||||
if ! [ -r /usr/share/ngcp-ngcpcfg/functions/main ] ; then
|
||||
printf "Error: /usr/share/ngcp-ngcpcfg/functions/main could not be read. Exiting.\n" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
. /usr/share/ngcp-ngcpcfg/functions/main
|
||||
|
||||
# main script
|
||||
|
||||
if ! [ -d "${NGCPCTL_MAIN:-}" ] ; then
|
||||
log_error "Directory ${NGCPCTL_MAIN:-} does not exist yet. Execute 'ngcpcfg initialise'."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log_debug "cd $NGCPCTL_MAIN"
|
||||
cd "$NGCPCTL_MAIN"
|
||||
|
||||
log_info "Checking state of ngcpcfg:"
|
||||
if ! [ -r /etc/ngcp-config/.git/HEAD ] ; then
|
||||
log_warn "ngcpcfg has not been initialised yet. Execute 'ngcpcfg initialise'."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
log_info "OK: has been initialised already "
|
||||
|
||||
log_info "Checking state of configuration files:"
|
||||
log_debug "git status | grep -q 'working directory clean'"
|
||||
if git status | grep -q 'working directory clean' ; then
|
||||
log_info "OK: nothing to commit."
|
||||
else
|
||||
if git diff-index --name-only HEAD | grep -q . ; then
|
||||
log_info "ACTION_NEEDED: configuration files have been modified:"
|
||||
log_debug "git diff-index --name-only HEAD | sed \"s;^;${NGCPCTL_MAIN}/;\""
|
||||
git diff-index --name-only HEAD | sed "s;^;${NGCPCTL_MAIN}/;"
|
||||
fi
|
||||
|
||||
if git ls-files --other --exclude-standard | grep -q . ; then
|
||||
log_info "ACTION_NEEDED: configuration files have been added:"
|
||||
log_debug "git ls-files --other --exclude-standard | sed \"s;^;${NGCPCTL_MAIN}/;\""
|
||||
git ls-files --other --exclude-standard | sed "s;^;${NGCPCTL_MAIN}/;"
|
||||
fi
|
||||
|
||||
log_info "-> execute 'ngcpcfg build' and 'ngcpcfg commit'"
|
||||
fi
|
||||
|
||||
if which status_ha &>/dev/null ; then
|
||||
log_debug "status_ha function"
|
||||
status_ha
|
||||
fi
|
||||
|
||||
log_debug "cd /etc"
|
||||
cd /etc
|
||||
|
||||
log_info "Checking state of /etc files"
|
||||
log_debug "git status | grep -q 'working directory clean'"
|
||||
if git status | grep -q 'working directory clean' ; then
|
||||
log_info "OK: nothing to commit."
|
||||
else
|
||||
log_info "ACTION_NEEDED: configuration files changed (execute 'etckeeper commit [message]')."
|
||||
fi
|
||||
|
||||
## END OF FILE #################################################################
|
@ -0,0 +1,16 @@
|
||||
all: prepare test
|
||||
|
||||
prepare:
|
||||
carton install
|
||||
|
||||
test:
|
||||
mkdir -p ../reports/
|
||||
rm -f ../reports/ngcp-network.tap
|
||||
bash ./ngcp-network > ../reports/ngcp-network.tap
|
||||
|
||||
clean:
|
||||
rm -rf testfiles
|
||||
|
||||
dist-clean: clean
|
||||
rm -rf ../reports/
|
||||
rm -rf local
|
@ -0,0 +1,89 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
set -u
|
||||
|
||||
# when invoked under DEBUG_SHELL=1 then provide
|
||||
# interactive shell before exiting
|
||||
if [ -n "${DEBUG_SHELL:-}" ] ; then
|
||||
bailout() { bash; exit 1; }
|
||||
else
|
||||
bailout() { exit 1; }
|
||||
fi
|
||||
|
||||
export testsuite="$(dirname $PWD/$0)"
|
||||
|
||||
TMPDIR="$(mktemp -d)"
|
||||
echo "Switching to temporary directory $TMPDIR"
|
||||
cd "$TMPDIR"
|
||||
cp -a ${testsuite}/* .
|
||||
|
||||
export FUNCTIONS="$testsuite/../functions/"
|
||||
export HELPER="$testsuite/../helper/"
|
||||
export SCRIPTS="$testsuite/../scripts/"
|
||||
|
||||
echo -n "Testing ngcpcfg without any arguments: "
|
||||
if $testsuite/../sbin/ngcpcfg 2>&1 | grep -q "^Usage:$" ; then
|
||||
echo OK
|
||||
else
|
||||
echo "Error with executing ngcpcfg without any arguments" >&2
|
||||
bailout
|
||||
fi
|
||||
|
||||
echo -n "Testing ngcpcfg --help: "
|
||||
if $testsuite/../sbin/ngcpcfg --help 2>&1 | grep -q "^Usage:$" ; then
|
||||
echo OK
|
||||
else
|
||||
echo "Error with executing ngcpcfg --help" >&2
|
||||
bailout
|
||||
fi
|
||||
|
||||
echo -n "Testing ngcpcfg --version: "
|
||||
if $testsuite/../sbin/ngcpcfg --version 2>&1 | grep -q "version" ; then
|
||||
echo OK
|
||||
else
|
||||
echo "Error with executing ngcpcfg --version" >&2
|
||||
bailout
|
||||
fi
|
||||
|
||||
echo "Testing ngcpcfg build:"
|
||||
$testsuite/../sbin/ngcpcfg build > build.log
|
||||
|
||||
oldIFS="$IFS"
|
||||
IFS="
|
||||
"
|
||||
for line in $(cat build.log) ; do
|
||||
case "$line" in
|
||||
Generating\ testsuite/*OK) echo generation OK ;;
|
||||
Executing\ postbuild\ for\ testsuite/*) echo postbuild OK;;
|
||||
chgrp\ www-data\ testsuite/ngcp-ossbss/logging.conf) echo postbuild OK;;
|
||||
DEBUG:*) ;; # support running under "--debug"
|
||||
*)
|
||||
echo "Error caught: $line" >&2
|
||||
bailout
|
||||
;;
|
||||
esac
|
||||
done
|
||||
IFS="$oldIFS"
|
||||
|
||||
# test main tt2 processing
|
||||
if [[ $(cat testsuite/testtemplate) == "foo" ]] ; then
|
||||
echo "template test is OK"
|
||||
else
|
||||
echo "Error with [ngcp-config/templates/]testsuite/testtemplate.tt2" >&2
|
||||
bailout
|
||||
fi
|
||||
|
||||
# test precedence of files
|
||||
if [[ $(cat testsuite/precedence/all/test) == "test.custom.tt2" ]] ; then
|
||||
echo "precedence test is OK"
|
||||
else
|
||||
echo "Error with [ngcp-config/templates/]testsuite/precedence/all/*" >&2
|
||||
bailout
|
||||
fi
|
||||
|
||||
rm -rf "$TMPDIR"
|
||||
|
||||
echo "Everything seems to be ok."
|
||||
|
||||
# EOF
|
@ -0,0 +1,13 @@
|
||||
requires 'Carp';
|
||||
requires 'Data::Validate::IP';
|
||||
requires 'Getopt::Long';
|
||||
requires 'IO::Interface';
|
||||
requires 'IO::Socket';
|
||||
requires 'IPC::Open3';
|
||||
requires 'List::MoreUtils';
|
||||
requires 'Net::Netmask';
|
||||
requires 'Pod::Usage';
|
||||
requires 'Regexp::IPv6';
|
||||
requires 'Socket';
|
||||
requires 'Sys::Hostname';
|
||||
requires 'YAML::Tiny';
|
@ -0,0 +1,70 @@
|
||||
---
|
||||
hosts:
|
||||
sp1:
|
||||
eth0:
|
||||
dns_nameservers:
|
||||
- 2.3.4.5
|
||||
- 3.4.5.6
|
||||
gateway: 1.2.3.1
|
||||
hwaddr: de:ad:be:ef:23:42
|
||||
ip: 1.2.3.4
|
||||
netmask: 255.255.255.0
|
||||
eth1:
|
||||
hwaddr: de:ad:be:ef:42:23
|
||||
ip: 192.168.255.251
|
||||
netmask: 255.255.255.248
|
||||
type:
|
||||
- ha_int
|
||||
interfaces:
|
||||
- lo
|
||||
- eth0
|
||||
- eth1
|
||||
lo:
|
||||
hwaddr: 00:00:00:00:00:00
|
||||
ip: 127.0.0.1
|
||||
netmask: 255.0.0.0
|
||||
shared_ip: ~
|
||||
shared_v6ip: ~
|
||||
type:
|
||||
- sip_int
|
||||
- web_ext
|
||||
- sip_ext
|
||||
- rtp_ext
|
||||
- ssh_ext
|
||||
- mon_ext
|
||||
- web_int
|
||||
v6ip: '::1'
|
||||
peer: sp2
|
||||
role:
|
||||
- proxy
|
||||
- lb
|
||||
- mgmt
|
||||
sp2:
|
||||
eth1:
|
||||
ip: 192.168.255.252
|
||||
netmask: 255.255.255.248
|
||||
type:
|
||||
- ha_int
|
||||
interfaces:
|
||||
- lo
|
||||
- eth1
|
||||
lo:
|
||||
hwaddr: 00:00:00:00:00:00
|
||||
ip: 127.0.0.1
|
||||
netmask: 255.0.0.0
|
||||
shared_ip: ~
|
||||
shared_v6ip: ~
|
||||
type:
|
||||
- sip_int
|
||||
- web_ext
|
||||
- sip_ext
|
||||
- rtp_ext
|
||||
- ssh_ext
|
||||
- mon_ext
|
||||
- web_int
|
||||
v6ip: '::1'
|
||||
peer: sp1
|
||||
role:
|
||||
- proxy
|
||||
- lb
|
||||
- mgmt
|
@ -0,0 +1,24 @@
|
||||
---
|
||||
hosts:
|
||||
sp1:
|
||||
eth42:
|
||||
ip: 1.2.3.4
|
||||
netmask: 255.255.255.248
|
||||
interfaces:
|
||||
- lo
|
||||
- eth42
|
||||
lo:
|
||||
ip: 127.0.0.1
|
||||
netmask: 255.255.255.0
|
||||
type:
|
||||
- sip_int
|
||||
- ha_int
|
||||
- web_ext
|
||||
- sip_ext
|
||||
- rtp_ext
|
||||
- ssh_ext
|
||||
- mon_ext
|
||||
role:
|
||||
- proxy
|
||||
- lb
|
||||
- mgmt
|
@ -0,0 +1,20 @@
|
||||
---
|
||||
hosts:
|
||||
sp1:
|
||||
interfaces:
|
||||
- lo
|
||||
lo:
|
||||
ip: 127.0.0.1
|
||||
netmask: 255.255.255.0
|
||||
type:
|
||||
- sip_int
|
||||
- ha_int
|
||||
- web_ext
|
||||
- sip_ext
|
||||
- rtp_ext
|
||||
- ssh_ext
|
||||
- mon_ext
|
||||
role:
|
||||
- proxy
|
||||
- lb
|
||||
- mgmt
|
@ -0,0 +1,279 @@
|
||||
|
||||
|
||||
#These values might be changed to constants.yml
|
||||
networking:
|
||||
eaddress: 192.168.51.117
|
||||
ha:
|
||||
eiface: eth0
|
||||
bindnetaddr: 192.168.51.0
|
||||
mcastaddr: 226.94.1.1
|
||||
mcastport: 5405
|
||||
|
||||
database:
|
||||
bufferpoolsize: 254M
|
||||
kamailio:
|
||||
port: 5060
|
||||
disable_tcp: yes
|
||||
authenticate_bye: no
|
||||
|
||||
multi_homed: no
|
||||
allow_peer_relay: no
|
||||
|
||||
use_enum: no
|
||||
enum_suffix: e164.arpa.
|
||||
patterns:
|
||||
emergency: 112|911|999
|
||||
asterisk:
|
||||
sip:
|
||||
bindport: 5070
|
||||
dtmfmode: rfc2833
|
||||
rtp:
|
||||
minport: 10000
|
||||
maxport: 20000
|
||||
voicemail:
|
||||
serveremail: voicebox@sip.sipwise.com
|
||||
maxmsg: 30
|
||||
max_msg_length: 180
|
||||
min_msg_length: 3
|
||||
maxgreet: 60
|
||||
fromstring: Voicemail server
|
||||
mailsubject: '[Voicebox] New message ${VM_MSGNUM} in voicebox ${VM_MAILBOX}'
|
||||
mailbody: 'You have received a new message from ${VM_CALLERID} in voicebox ${VM_MAILBOX} on ${VM_DATE}.'
|
||||
log:
|
||||
facility: local6
|
||||
mediator:
|
||||
interval: 10
|
||||
rateomat:
|
||||
splitpeakparts: 0
|
||||
loopinterval: 10
|
||||
ossbss:
|
||||
htpasswd:
|
||||
- user: ngcpsoap
|
||||
pass: '{SHA}w4zj3mxbmynIQ1jsUEjSkN2z2pk='
|
||||
apache:
|
||||
port: 2443
|
||||
serveradmin: support@sipwise.com
|
||||
servername: '"myserver"'
|
||||
sslcertfile: /etc/apache2/ssl/myserver.crt
|
||||
sslcertkeyfile: /etc/apache2/ssl/myserver.pem
|
||||
provisioning:
|
||||
log_passwords: 0
|
||||
no_logline_truncate: 0
|
||||
allow_ip_as_domain: 1
|
||||
allow_numeric_usernames: 0
|
||||
tmpdir: /tmp
|
||||
|
||||
faxpw_min_char: 0
|
||||
|
||||
routing:
|
||||
cc_regex: '[1-9]\d{0,3}'
|
||||
ac_regex: '[1-9]\d{0,4}'
|
||||
sn_regex: '[1-9]\d+'
|
||||
logging:
|
||||
ossbss:
|
||||
facility: local0
|
||||
level: DEBUG
|
||||
identity: provisioning
|
||||
web:
|
||||
facility: local0
|
||||
level: DEBUG
|
||||
apache:
|
||||
err:
|
||||
facility: local7
|
||||
level: info
|
||||
acc:
|
||||
facility: daemon
|
||||
level: info
|
||||
identity: oss
|
||||
www_admin:
|
||||
apache:
|
||||
port: 1443
|
||||
serveradmin: support@sipwise.com
|
||||
servername: '"myserver"'
|
||||
sslcertfile: /etc/apache2/ssl/myserver.crt
|
||||
sslcertkeyfile: /etc/apache2/ssl/myserver.pem
|
||||
billing_features: 1
|
||||
peering_features: 1
|
||||
voicemail_features: 1
|
||||
fax_features: 1
|
||||
conference_features: 1
|
||||
cc_dial_prefix: 00
|
||||
ac_dial_prefix: 0
|
||||
dashboard:
|
||||
enabled: 1
|
||||
subscriber:
|
||||
extension_features: 0
|
||||
audiofile_features: 0
|
||||
domain:
|
||||
rewrite_features: 1
|
||||
audiofile_features: 0
|
||||
vsc_features: 0
|
||||
default_admin_settings:
|
||||
is_master: 0
|
||||
is_active: 1
|
||||
read_only: 0
|
||||
show_passwords: 1
|
||||
call_data: 0
|
||||
fees_csv:
|
||||
element_order:
|
||||
- destination
|
||||
- zone
|
||||
- zone_detail
|
||||
- onpeak_init_rate
|
||||
- onpeak_init_interval
|
||||
- onpeak_follow_rate
|
||||
- onpeak_follow_interval
|
||||
- offpeak_init_rate
|
||||
- offpeak_init_interval
|
||||
- offpeak_follow_rate
|
||||
- offpeak_follow_interval
|
||||
- use_free_time
|
||||
speed_dial_vsc_presets:
|
||||
vsc:
|
||||
- '*0'
|
||||
- '*1'
|
||||
- '*2'
|
||||
- '*3'
|
||||
- '*4'
|
||||
- '*5'
|
||||
- '*6'
|
||||
- '*7'
|
||||
- '*8'
|
||||
- '*9'
|
||||
logging:
|
||||
apache:
|
||||
err:
|
||||
facility: local7
|
||||
level: info
|
||||
acc:
|
||||
facility: daemon
|
||||
level: info
|
||||
identity: oss
|
||||
www_csc:
|
||||
apache:
|
||||
port: 443
|
||||
serveradmin: support@sipwise.com
|
||||
servername: myserver
|
||||
sslcertfile: /etc/apache2/ssl/myserver.crt
|
||||
sslcertkeyfile: /etc/apache2/ssl/myserver.pem
|
||||
site_domain: sip.yourdomain.tld
|
||||
display_account_info: 0
|
||||
sip_server: sip.yourdomain.tld
|
||||
tftp_server: tftp.yourdomain.tld
|
||||
payment_features: 0
|
||||
cc_dial_prefix: 00
|
||||
ac_dial_prefix: 0
|
||||
site_config:
|
||||
title: Sipwise NGCP CSC
|
||||
default_language: en
|
||||
default_uri: '/desktop'
|
||||
languages:
|
||||
- en
|
||||
- es
|
||||
company:
|
||||
name: Your Company
|
||||
logo: 'https://some.server/path/to/logo.gif'
|
||||
hotline: ''
|
||||
city: ''
|
||||
street: ''
|
||||
phone: ''
|
||||
fax: ''
|
||||
email: ''
|
||||
webserver: ''
|
||||
main_menu:
|
||||
desktop: 1
|
||||
calllist: 1
|
||||
voicebox: 1
|
||||
addressbook: 1
|
||||
callforward: 1
|
||||
callblock: 1
|
||||
reminder: 1
|
||||
device: 0
|
||||
account: 1
|
||||
logging:
|
||||
apache:
|
||||
err:
|
||||
facility: local7
|
||||
level: info
|
||||
acc:
|
||||
facility: daemon
|
||||
level: info
|
||||
identity: csc
|
||||
rtpproxy:
|
||||
minport: 30000
|
||||
maxport: 40000
|
||||
sems:
|
||||
bindport: 5080
|
||||
lowport: 40001
|
||||
highport: 50000
|
||||
xmlrpcport: 8090
|
||||
vsc:
|
||||
voicemail_number: 2000
|
||||
cfu_code: 72
|
||||
cfb_code: 90
|
||||
cft_code: 92
|
||||
cfna_code: 93
|
||||
speedial_code: 50
|
||||
reminder_code: 55
|
||||
rsyslog:
|
||||
external_log: 0
|
||||
external_address: 192.168.32.1
|
||||
external_proto: udp
|
||||
external_port: 514
|
||||
external_loglevel: warning
|
||||
reminder:
|
||||
retries: 2
|
||||
retry_time: 60
|
||||
wait_time: 30
|
||||
sip_fromuser: reminder
|
||||
sip_fromdomain: voicebox.sipwise.local
|
||||
checktools:
|
||||
sip_check_enable: 1
|
||||
mysql_check_enable: 1
|
||||
mpt_check_enable: 0
|
||||
exim_check_enable: 0
|
||||
kamailio_check_dialog_active_enable: 1
|
||||
kamailio_check_dialog_early_enable: 0
|
||||
kamailio_check_usrloc_regusers_enable: 1
|
||||
kamailio_check_usrloc_regdevices_enable: 0
|
||||
oss_check_provisioned_subscribers_enable: 1
|
||||
|
||||
force: 0
|
||||
mysql_check_replication: 1
|
||||
kamailio_check_dialog_local_enable: 0
|
||||
kamailio_check_dialog_relay_enable: 0
|
||||
kamailio_check_dialog_incoming_enable: 0
|
||||
kamailio_check_dialog_outgoing_enable: 0
|
||||
|
||||
|
||||
collcheck:
|
||||
maxage: 600
|
||||
cpuidle: 0.1
|
||||
swapfree: 0.5
|
||||
dfused: 0.9
|
||||
memused: 0.7
|
||||
loadshort: 3
|
||||
loadmedium: 2
|
||||
loadlong: 2
|
||||
siptimeout: 15
|
||||
eximmaxqueue: 15
|
||||
|
||||
cdrexport:
|
||||
exportpath: '/home/jail/home/cdrexport'
|
||||
filepreffix: sipwise
|
||||
fileversion: 001
|
||||
monthly_folder: yes
|
||||
daily_folder: yes
|
||||
cleanuptools:
|
||||
batch: 10000
|
||||
archive_targetdir: '/tmp'
|
||||
compress: gzip
|
||||
acc_days: 90
|
||||
trash_days: 30
|
||||
acc2_days: 180
|
||||
general:
|
||||
companyname: sipwise
|
||||
lang: en
|
||||
adminmail: nomail@nodomain.org
|
||||
|
||||
# vim: ft=yaml
|
@ -0,0 +1,127 @@
|
||||
|
||||
|
||||
#############################
|
||||
#
|
||||
# DO NOT EDIT THIS FILE!!
|
||||
#
|
||||
# This file contains some values not being handled by the ngcp configuration framework.
|
||||
# Editing this file may cause your system to stop working.
|
||||
# Do not manually edit this file unless you know what you're doing.
|
||||
#
|
||||
#
|
||||
############################
|
||||
|
||||
database:
|
||||
dbhost: localhost
|
||||
dbport: 3306
|
||||
kamailio:
|
||||
dbengine: MYSQL
|
||||
dbname: kamailio
|
||||
dbrootuser: root
|
||||
dbropw: jJXgh7AAmkJ4KCMWYHCX
|
||||
dbrouser: kamailioro
|
||||
dbrwpw: g7PYspcXhLRNjgwPghkx
|
||||
dbrwuser: kamailio
|
||||
uaccryptpw: UwrpwmpCUMhfv4zscuha
|
||||
asterisk:
|
||||
asterisk:
|
||||
internal_timing: no
|
||||
odbc:
|
||||
dbuser: asterisk
|
||||
dbpassword: cx9W7PWMmkjRVpzzYkts
|
||||
dbname: kamailio
|
||||
mediator:
|
||||
dbuser: mediator
|
||||
dbpassword: AcMcrhbzXhUmTvTf9gsm
|
||||
srcdbname: kamailio
|
||||
destdbname: accounting
|
||||
provdbname: provisioning
|
||||
rateomat:
|
||||
billingdb:
|
||||
name: billing
|
||||
user: rateomat
|
||||
pass: dn7iM9YgPcJhmHXo9eWr
|
||||
accountingdb:
|
||||
name: accounting
|
||||
user: rateomat
|
||||
pass: dn7iM9YgPcJhmHXo9eWr
|
||||
mysql:
|
||||
|
||||
repuser: replicator
|
||||
reppassword: KtXpr3jT7jtcd7PmnTbd
|
||||
|
||||
ossbss:
|
||||
provisioning:
|
||||
database:
|
||||
name: provisioning
|
||||
user: soap
|
||||
pass: hEuxXrzLF43X93ULhoNu
|
||||
billingdb:
|
||||
name: billing
|
||||
user: soap
|
||||
pass: hEuxXrzLF43X93ULhoNu
|
||||
openserdb:
|
||||
name: kamailio
|
||||
user: soap
|
||||
pass: hEuxXrzLF43X93ULhoNu
|
||||
acl:
|
||||
- user: csc
|
||||
pass: RMYisfV4rvpWYVKosYnU
|
||||
allow:
|
||||
- Voip
|
||||
- Billing
|
||||
fax:
|
||||
sendfax: /usr/bin/sendfax
|
||||
faxserver: 127.0.0.1
|
||||
default_sender: webfax
|
||||
routing:
|
||||
internal_domain: voip.sipwise.local
|
||||
no_such_number: no_such_number
|
||||
voicebox_domain: voicebox.local
|
||||
fax2mail_domain: fax2mail.local
|
||||
conference_domain: conference.local
|
||||
backends:
|
||||
available:
|
||||
- Billing
|
||||
- Voip
|
||||
enabled:
|
||||
- Billing
|
||||
- Voip
|
||||
www_csc:
|
||||
prov_user: csc
|
||||
prov_pass: RMYisfV4rvpWYVKosYnU
|
||||
sems:
|
||||
dbuser: soap
|
||||
dbpassword: hEuxXrzLF43X93ULhoNu
|
||||
rsyslog:
|
||||
dbname: syslog
|
||||
dbuser: rsyslog
|
||||
dbpassword: bAmjr7gTaevK4tFofkaP
|
||||
rotate_days: 28
|
||||
reminder:
|
||||
context: reminder
|
||||
sip_peer: sip_proxy
|
||||
dbname: provisioning
|
||||
dbuser: soap
|
||||
dbpassword: hEuxXrzLF43X93ULhoNu
|
||||
checktools:
|
||||
dbuser: nagios
|
||||
dbpassword: XM4s47qEyJrckCoqPVYe
|
||||
sipuser: nagios
|
||||
sipdomain: voip.sipwise.local
|
||||
sip_check_ip: 127.0.0.1
|
||||
cdrexport:
|
||||
dbuser: exporter
|
||||
dbpassword: zghivhVEv7fPMRiLAPRR
|
||||
dbname: accounting
|
||||
cleanuptools:
|
||||
dbuser: dbcleaner
|
||||
dbpassword: q43aaqRucmTmYz9gvJhe
|
||||
acc_db: kamailio
|
||||
trash_db: kamailio
|
||||
#### Do not touch this! ####
|
||||
configuration_framework:
|
||||
constants_version: 4083
|
||||
config_version: 4083
|
||||
|
||||
# vim: ft=yaml
|
@ -0,0 +1,18 @@
|
||||
|
||||
# /etc/crontab: system-wide crontab
|
||||
# Unlike any other crontab you don't have to run the `crontab'
|
||||
# command to install the new version when you edit this file
|
||||
# and files in /etc/cron.d. These files also have username fields,
|
||||
# that none of the other crontabs do.
|
||||
|
||||
SHELL=/bin/sh
|
||||
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
|
||||
|
||||
# m h dom mon dow user command
|
||||
17 * * * * root cd / && run-parts --report /etc/cron.hourly
|
||||
59 23 * * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )
|
||||
47 6 * * 7 root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )
|
||||
52 6 1 * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )
|
||||
#
|
||||
|
||||
|
@ -0,0 +1,170 @@
|
||||
[client]
|
||||
|
||||
port = [% database.dbport %]
|
||||
socket = /var/run/mysqld/mysqld.sock
|
||||
default_character_set = utf8
|
||||
|
||||
#----------------------------------------------------------------
|
||||
|
||||
[safe_mysqld]
|
||||
|
||||
syslog
|
||||
|
||||
#----------------------------------------------------------------
|
||||
|
||||
[mysqld]
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
user = mysql
|
||||
port = [% database.dbport %]
|
||||
socket = /var/run/mysqld/mysqld.sock
|
||||
|
||||
max_connections = 2048
|
||||
back_log = 128
|
||||
max_connect_errors = 1000
|
||||
connect_timeout = 2
|
||||
wait_timeout = 60
|
||||
|
||||
max_allowed_packet = 16M
|
||||
net_buffer_length = 8K
|
||||
|
||||
default_character_set = utf8
|
||||
character_set_server = utf8
|
||||
|
||||
default_collation = utf8_general_ci
|
||||
init_connect = 'SET NAMES utf8; SET sql_mode = STRICT_TRANS_TABLES'
|
||||
|
||||
basedir = /usr
|
||||
datadir = /var/lib/mysql
|
||||
tmpdir = /tmp
|
||||
language = /usr/share/mysql/english
|
||||
log-error = /var/log/mysql/mysqld.err
|
||||
pid-file = /var/run/mysqld/mysqld.pid
|
||||
log_slow_queries = /var/log/mysql/slow-queries.log
|
||||
log_output = FILE
|
||||
long_query_time = 5
|
||||
log_long_format
|
||||
#log = /var/log/mysql/queries.log
|
||||
|
||||
|
||||
#Binlog options
|
||||
log_bin = /var/lib/mysql/log-bin
|
||||
max_binlog_size = 512M
|
||||
expire_logs_days = 90 #Values 0-99
|
||||
binlog_format = row
|
||||
binlog_cache_size = 1M
|
||||
sync_binlog = 1
|
||||
|
||||
relay_log = /var/lib/mysql/log-relay-bin
|
||||
max_relay_log_size = 512M
|
||||
|
||||
|
||||
|
||||
|
||||
#Replication options
|
||||
|
||||
server_id = 1
|
||||
auto_increment_offset = 1
|
||||
auto_increment_increment = 2
|
||||
master-host = sp2
|
||||
|
||||
|
||||
|
||||
|
||||
master-port=[% database.dbport %]
|
||||
master-user=[% mysql.repuser %]
|
||||
master-password=[% mysql.reppassword %]
|
||||
master-connect-retry=10
|
||||
|
||||
replicate-wild-do-table=kamailio.%
|
||||
replicate-wild-do-table=provisioning.%
|
||||
replicate-wild-do-table=operating.%
|
||||
replicate-wild-do-table=billing.%
|
||||
replicate-wild-do-table=accounting.%
|
||||
replicate-wild-do-table=syslog.%
|
||||
replicate-ignore-table=accounting.acc_backup
|
||||
replicate-ignore-table=accounting.acc_trash
|
||||
replicate-ignore-table=kamailio.acc_backup
|
||||
replicate-ignore-table=kamailio.acc_trash
|
||||
|
||||
|
||||
|
||||
|
||||
table_cache = 4096
|
||||
join_buffer_size = 8M
|
||||
tmp_table_size = 64M
|
||||
sort_buffer_size = 8M
|
||||
thread_cache_size = 64
|
||||
thread_concurrency = 8
|
||||
thread_stack = 192K
|
||||
|
||||
|
||||
|
||||
# Query cache, disabled
|
||||
query_cache_size = 0
|
||||
query_cache_type = 1
|
||||
query_cache_limit = 2M
|
||||
|
||||
transaction_isolation = REPEATABLE-READ
|
||||
|
||||
# MyISAM options
|
||||
key_buffer_size = 256M
|
||||
read_buffer_size = 2M
|
||||
read_rnd_buffer_size = 8M
|
||||
myisam_sort_buffer_size = 128M
|
||||
bulk_insert_buffer_size = 64M
|
||||
myisam_max_sort_file_size = 10G
|
||||
myisam_repair_threads = 2
|
||||
#myisam_recover_options = DEFAULT
|
||||
|
||||
|
||||
|
||||
# InnoDB options
|
||||
innodb_data_home_dir = /var/lib/mysql
|
||||
innodb_data_file_path = ibdata1:10M:autoextend
|
||||
innodb_file_per_table
|
||||
innodb_buffer_pool_size = [% database.bufferpoolsize %]
|
||||
innodb_additional_mem_pool_size = 32M
|
||||
innodb_log_group_home_dir = /var/lib/mysql
|
||||
innodb_log_files_in_group = 4
|
||||
innodb_log_file_size = 128M
|
||||
innodb_log_buffer_size = 8M
|
||||
innodb_max_dirty_pages_pct = 80
|
||||
innodb_flush_log_at_trx_commit = 1
|
||||
innodb_lock_wait_timeout = 50
|
||||
innodb_flush_method = O_DIRECT
|
||||
innodb_thread_concurrency = 32
|
||||
innodb_autoinc_lock_mode = 1
|
||||
innodb_locks_unsafe_for_binlog
|
||||
innodb_fast_shutdown = 1
|
||||
innodb_max_purge_lag = 0
|
||||
|
||||
#----------------------------------------------------------------
|
||||
|
||||
[mysqldump]
|
||||
|
||||
quick
|
||||
max_allowed_packet = 16M
|
||||
single_transaction
|
||||
|
||||
|
||||
#----------------------------------------------------------------
|
||||
|
||||
[mysql]
|
||||
|
||||
#no_auto_rehash
|
||||
|
||||
|
||||
#----------------------------------------------------------------
|
||||
|
||||
[myisamchk]
|
||||
|
||||
# databases
|
||||
key_buffer = 256M
|
||||
sort_buffer = 256M
|
||||
read_buffer = 64M
|
||||
write_buffer = 64M
|
@ -0,0 +1,170 @@
|
||||
[client]
|
||||
|
||||
port = [% database.dbport %]
|
||||
socket = /var/run/mysqld/mysqld.sock
|
||||
default_character_set = utf8
|
||||
|
||||
#----------------------------------------------------------------
|
||||
|
||||
[safe_mysqld]
|
||||
|
||||
syslog
|
||||
|
||||
#----------------------------------------------------------------
|
||||
|
||||
[mysqld]
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
user = mysql
|
||||
port = [% database.dbport %]
|
||||
socket = /var/run/mysqld/mysqld.sock
|
||||
|
||||
max_connections = 2048
|
||||
back_log = 128
|
||||
max_connect_errors = 1000
|
||||
connect_timeout = 2
|
||||
wait_timeout = 60
|
||||
|
||||
max_allowed_packet = 16M
|
||||
net_buffer_length = 8K
|
||||
|
||||
default_character_set = utf8
|
||||
character_set_server = utf8
|
||||
|
||||
default_collation = utf8_general_ci
|
||||
init_connect = 'SET NAMES utf8; SET sql_mode = STRICT_TRANS_TABLES'
|
||||
|
||||
basedir = /usr
|
||||
datadir = /var/lib/mysql
|
||||
tmpdir = /tmp
|
||||
language = /usr/share/mysql/english
|
||||
log-error = /var/log/mysql/mysqld.err
|
||||
pid-file = /var/run/mysqld/mysqld.pid
|
||||
log_slow_queries = /var/log/mysql/slow-queries.log
|
||||
log_output = FILE
|
||||
long_query_time = 5
|
||||
log_long_format
|
||||
#log = /var/log/mysql/queries.log
|
||||
|
||||
|
||||
#Binlog options
|
||||
log_bin = /var/lib/mysql/log-bin
|
||||
max_binlog_size = 512M
|
||||
expire_logs_days = 90 #Values 0-99
|
||||
binlog_format = row
|
||||
binlog_cache_size = 1M
|
||||
sync_binlog = 1
|
||||
|
||||
relay_log = /var/lib/mysql/log-relay-bin
|
||||
max_relay_log_size = 512M
|
||||
|
||||
|
||||
|
||||
|
||||
#Replication options
|
||||
|
||||
server_id = 2
|
||||
auto_increment_offset = 2
|
||||
auto_increment_increment = 2
|
||||
master-host = sp1
|
||||
|
||||
|
||||
|
||||
|
||||
master-port=[% database.dbport %]
|
||||
master-user=[% mysql.repuser %]
|
||||
master-password=[% mysql.reppassword %]
|
||||
master-connect-retry=10
|
||||
|
||||
replicate-wild-do-table=kamailio.%
|
||||
replicate-wild-do-table=provisioning.%
|
||||
replicate-wild-do-table=operating.%
|
||||
replicate-wild-do-table=billing.%
|
||||
replicate-wild-do-table=accounting.%
|
||||
replicate-wild-do-table=syslog.%
|
||||
replicate-ignore-table=accounting.acc_backup
|
||||
replicate-ignore-table=accounting.acc_trash
|
||||
replicate-ignore-table=kamailio.acc_backup
|
||||
replicate-ignore-table=kamailio.acc_trash
|
||||
|
||||
|
||||
|
||||
|
||||
table_cache = 4096
|
||||
join_buffer_size = 8M
|
||||
tmp_table_size = 64M
|
||||
sort_buffer_size = 8M
|
||||
thread_cache_size = 64
|
||||
thread_concurrency = 8
|
||||
thread_stack = 192K
|
||||
|
||||
|
||||
|
||||
# Query cache, disabled
|
||||
query_cache_size = 0
|
||||
query_cache_type = 1
|
||||
query_cache_limit = 2M
|
||||
|
||||
transaction_isolation = REPEATABLE-READ
|
||||
|
||||
# MyISAM options
|
||||
key_buffer_size = 256M
|
||||
read_buffer_size = 2M
|
||||
read_rnd_buffer_size = 8M
|
||||
myisam_sort_buffer_size = 128M
|
||||
bulk_insert_buffer_size = 64M
|
||||
myisam_max_sort_file_size = 10G
|
||||
myisam_repair_threads = 2
|
||||
#myisam_recover_options = DEFAULT
|
||||
|
||||
|
||||
|
||||
# InnoDB options
|
||||
innodb_data_home_dir = /var/lib/mysql
|
||||
innodb_data_file_path = ibdata1:10M:autoextend
|
||||
innodb_file_per_table
|
||||
innodb_buffer_pool_size = [% database.bufferpoolsize %]
|
||||
innodb_additional_mem_pool_size = 32M
|
||||
innodb_log_group_home_dir = /var/lib/mysql
|
||||
innodb_log_files_in_group = 4
|
||||
innodb_log_file_size = 128M
|
||||
innodb_log_buffer_size = 8M
|
||||
innodb_max_dirty_pages_pct = 80
|
||||
innodb_flush_log_at_trx_commit = 1
|
||||
innodb_lock_wait_timeout = 50
|
||||
innodb_flush_method = O_DIRECT
|
||||
innodb_thread_concurrency = 32
|
||||
innodb_autoinc_lock_mode = 1
|
||||
innodb_locks_unsafe_for_binlog
|
||||
innodb_fast_shutdown = 1
|
||||
innodb_max_purge_lag = 0
|
||||
|
||||
#----------------------------------------------------------------
|
||||
|
||||
[mysqldump]
|
||||
|
||||
quick
|
||||
max_allowed_packet = 16M
|
||||
single_transaction
|
||||
|
||||
|
||||
#----------------------------------------------------------------
|
||||
|
||||
[mysql]
|
||||
|
||||
#no_auto_rehash
|
||||
|
||||
|
||||
#----------------------------------------------------------------
|
||||
|
||||
[myisamchk]
|
||||
|
||||
# databases
|
||||
key_buffer = 256M
|
||||
sort_buffer = 256M
|
||||
read_buffer = 64M
|
||||
write_buffer = 64M
|
@ -0,0 +1,6 @@
|
||||
#!/bin/bash
|
||||
|
||||
/etc/init.d/mysql restart
|
||||
sleep 2
|
||||
|
||||
# vim: ft=sh
|
@ -0,0 +1 @@
|
||||
echo chgrp www-data ${output_file}
|
@ -0,0 +1,16 @@
|
||||
|
||||
log4perl.logger.Sipwise.Provisioning = [% ossbss.logging.ossbss.level %], ProvSyslogApp
|
||||
|
||||
log4perl.appender.ProvSyslogApp = Log::Dispatch::Syslog
|
||||
log4perl.appender.ProvSyslogApp.facility = [% ossbss.logging.ossbss.facility %]
|
||||
log4perl.appender.ProvSyslogApp.ident = [% ossbss.logging.ossbss.identity %]
|
||||
log4perl.appender.ProvSyslogApp.layout = PatternLayout
|
||||
log4perl.appender.ProvSyslogApp.layout.ConversionPattern = %M: %m%n
|
||||
|
||||
log4perl.logger.Catalyst = WARN, CatalystSyslogApp
|
||||
log4perl.logger.csc = [% ossbss.logging.web.level %], CatalystSyslogApp
|
||||
log4perl.logger.admin = [% ossbss.logging.web.level %], CatalystSyslogApp
|
||||
|
||||
log4perl.appender.CatalystSyslogApp = Log::Dispatch::Syslog
|
||||
log4perl.appender.CatalystSyslogApp.facility = [% ossbss.logging.web.facility %]
|
||||
log4perl.appender.CatalystSyslogApp.layout = PatternLayout
|
@ -0,0 +1,21 @@
|
||||
#!/bin/bash
|
||||
|
||||
MYSQL_USER='sipwise'
|
||||
|
||||
. /etc/mysql/sipwise.cnf
|
||||
. /etc/ngcp-ossbss/mysql_values.cfg
|
||||
|
||||
#dispatcher values reloaded
|
||||
MYCOM="mysql -u$MYSQL_USER -p$SIPWISE_DB_PASSWORD kamailio -e"
|
||||
$MYCOM "update dispatcher set destination='sip:$EADDRESS:$ASTERISK_PORT' where setid='2' "
|
||||
$MYCOM "update dispatcher set destination='sip:$EADDRESS:$SEMS_PORT' where setid='3' "
|
||||
|
||||
#xmlrcp values reloaded
|
||||
#sems ip does not need to change
|
||||
#kamailio rpc port not configurable at the moment
|
||||
MYCOM="mysql -u$MYSQL_USER -p$SIPWISE_DB_PASSWORD provisioning -e"
|
||||
$MYCOM "update xmlhosts set ip='$EADDRESS' where id='1' "
|
||||
$MYCOM "update xmlhosts set port='$SEMS_XMLRPCPORT' where id='2' "
|
||||
|
||||
/etc/init.d/kamailio restart
|
||||
sleep 2
|
@ -0,0 +1,4 @@
|
||||
EADDRESS='[% networking.eaddress %]'
|
||||
ASTERISK_PORT='[% asterisk.sip.bindport %]'
|
||||
SEMS_PORT='[% sems.bindport %]'
|
||||
SEMS_XMLRPCPORT='[% sems.xmlrpcport %]'
|
@ -0,0 +1,65 @@
|
||||
<config logconf="/etc/ngcp-ossbss/logging.conf"
|
||||
usrprefs_as_number="1"
|
||||
speed_dial_destinations_as_number="1"
|
||||
log_passwords="[% ossbss.provisioning.log_passwords %]"
|
||||
no_logline_truncate="[% ossbss.provisioning.no_logline_truncate %]"
|
||||
allow_ip_as_domain="[% ossbss.provisioning.allow_ip_as_domain %]"
|
||||
allow_numeric_usernames="[% ossbss.provisioning.allow_numeric_usernames %]"
|
||||
tmpdir="[% ossbss.provisioning.tmpdir %]"
|
||||
fax_features="[% www_admin.fax_features %]"
|
||||
faxpw_min_char="[% ossbss.provisioning.faxpw_min_char %]"
|
||||
prov_data_typing="1"
|
||||
voicemail_map_via_number="0"
|
||||
apache_port="[% ossbss.apache.port %]"
|
||||
customer_features="0"
|
||||
product_features="0"
|
||||
numberblock_features="0"
|
||||
lnp_features="0"
|
||||
>
|
||||
<database dsn="DBI:mysql:database=[% ossbss.provisioning.database.name %];host=[% database.dbhost %];port=[% database.dbport %]"
|
||||
username="[% ossbss.provisioning.database.user %]"
|
||||
password="[% ossbss.provisioning.database.pass %]" />
|
||||
<billingdb dsn="DBI:mysql:database=[% ossbss.provisioning.billingdb.name %];host=[% database.dbhost %];port=[% database.dbport %]"
|
||||
username="[% ossbss.provisioning.billingdb.user %]"
|
||||
password="[% ossbss.provisioning.billingdb.pass %]" />
|
||||
<openserdb dsn="DBI:mysql:database=[% ossbss.provisioning.openserdb.name %];host=[% database.dbhost %];port=[% database.dbport %]"
|
||||
username="[% ossbss.provisioning.openserdb.user %]"
|
||||
password="[% ossbss.provisioning.openserdb.pass %]" />
|
||||
<acl>
|
||||
[% FOREACH aclentry = ossbss.provisioning.acl %]
|
||||
<[% aclentry.user %] password="[% aclentry.pass %]" [% FOREACH aclallow = aclentry.allow %][% aclallow %]="" [% END %] />
|
||||
[% END %]
|
||||
</acl>
|
||||
<invoice template="/usr/local/etc/corporate.pdf" />
|
||||
<fax sendfax="[% ossbss.provisioning.fax.sendfax %]"
|
||||
faxserver="[% ossbss.provisioning.fax.faxserver %]"
|
||||
default_sender="[% ossbss.provisioning.fax.default_sender %]" />
|
||||
<vsc>
|
||||
<actions>error</actions>
|
||||
<actions>unknown</actions>
|
||||
<actions>cfu_on</actions>
|
||||
<actions>cfu_off</actions>
|
||||
<actions>cfb_on</actions>
|
||||
<actions>cfb_off</actions>
|
||||
<actions>cft_on</actions>
|
||||
<actions>cft_off</actions>
|
||||
<actions>cfna_on</actions>
|
||||
<actions>cfna_off</actions>
|
||||
<actions>reminder_on</actions>
|
||||
<actions>reminder_off</actions>
|
||||
</vsc>
|
||||
<routing internal_domain="[% ossbss.provisioning.routing.internal_domain %]"
|
||||
no_such_number="[% ossbss.provisioning.routing.no_such_number %]"
|
||||
voicebox_domain="[% ossbss.provisioning.routing.voicebox_domain %]"
|
||||
fax2mail_domain="[% ossbss.provisioning.routing.fax2mail_domain %]"
|
||||
conference_domain="[% ossbss.provisioning.routing.conference_domain %]"
|
||||
cc_regex="[% ossbss.provisioning.routing.cc_regex %]"
|
||||
ac_regex="[% ossbss.provisioning.routing.ac_regex %]"
|
||||
sn_regex="[% ossbss.provisioning.routing.sn_regex %]"
|
||||
/>
|
||||
<reserved_usernames>voicebox</reserved_usernames>
|
||||
<system rrd_path="/var/lib/collectd/rrd" />
|
||||
[% FOREACH backend = ossbss.provisioning.backends.enabled %]
|
||||
<backends_enabled>[% backend %]</backends_enabled>
|
||||
[% END %]
|
||||
</config>
|
@ -0,0 +1,4 @@
|
||||
|
||||
[% FOREACH htentry = ossbss.htpasswd %]
|
||||
[% htentry.user %]:[% htentry.pass %]
|
||||
[% END %]
|
@ -0,0 +1,2 @@
|
||||
|
||||
/etc/init.d/apache2 reload
|
@ -0,0 +1,40 @@
|
||||
|
||||
<config debugging="0"
|
||||
log4perlconf="/etc/ngcp-ossbss/logging.conf"
|
||||
billing_features="[% www_admin.billing_features %]"
|
||||
peering_features="[% www_admin.peering_features %]"
|
||||
voicemail_features="[% www_admin.voicemail_features %]"
|
||||
fax_features="[% www_admin.fax_features %]"
|
||||
conference_features="[% www_admin.conference_features %]"
|
||||
customer_features="0"
|
||||
product_features="0"
|
||||
numberblock_features="0"
|
||||
lnp_features="0"
|
||||
cc_dial_prefix="[% www_admin.cc_dial_prefix %]"
|
||||
ac_dial_prefix="[% www_admin.ac_dial_prefix %]"
|
||||
voicebox_domain="[% ossbss.provisioning.routing.voicebox_domain %]"
|
||||
fax2mail_domain="[% ossbss.provisioning.routing.fax2mail_domain %]"
|
||||
conference_domain="[% ossbss.provisioning.routing.conference_domain %]"
|
||||
>
|
||||
<dashboard enabled="[% www_admin.dashboard.enabled %]" />
|
||||
<subscriber extension_features="[% www_admin.subscriber.extension_features %]"
|
||||
audiofile_features="[% www_admin.subscriber.audiofile_features %]"
|
||||
/>
|
||||
<domain rewrite_features="[% www_admin.domain.rewrite_features %]"
|
||||
audiofile_features="[% www_admin.domain.audiofile_features %]"
|
||||
vsc_features="[% www_admin.domain.vsc_features %]"
|
||||
/>
|
||||
<default_admin_settings is_master="[% www_admin.default_admin_settings.is_master %]" is_active="[% www_admin.default_admin_settings.is_active %]"
|
||||
read_only="[% www_admin.default_admin_settings.read_only %]" show_passwords="[% www_admin.default_admin_settings.show_passwords %]"
|
||||
call_data="[% www_admin.default_admin_settings.call_data %]" />
|
||||
<fees_csv>
|
||||
[% FOREACH feecsvelement = www_admin.fees_csv.element_order %]
|
||||
<element_order>[% feecsvelement %]</element_order>
|
||||
[% END %]
|
||||
</fees_csv>
|
||||
<speed_dial_vsc_presets>
|
||||
[% FOREACH speeddialvsc = www_admin.speed_dial_vsc_presets.vsc %]
|
||||
<vsc>[% speeddialvsc %]</vsc>
|
||||
[% END %]
|
||||
</speed_dial_vsc_presets>
|
||||
</config>
|
@ -0,0 +1 @@
|
||||
test.custom.tt2
|
@ -0,0 +1 @@
|
||||
test.custom.tt2.sp1
|
@ -0,0 +1 @@
|
||||
test.tt2
|
@ -0,0 +1 @@
|
||||
test.tt2.sp1
|
@ -0,0 +1 @@
|
||||
[% TAGS [- -] %]foo
|
@ -0,0 +1,120 @@
|
||||
#!/bin/bash
|
||||
|
||||
# defaults
|
||||
if [ -d local ] ; then # running with carton
|
||||
CMD="perl -Ilocal/lib/perl5 -CSD ../sbin/ngcp-network"
|
||||
else
|
||||
CMD="perl -CSD ../sbin/ngcp-network"
|
||||
fi
|
||||
|
||||
count=0
|
||||
RC=0
|
||||
|
||||
OUTPUT=$(mktemp) || exit 1
|
||||
|
||||
# generated files
|
||||
rm -rf testfiles
|
||||
mkdir testfiles
|
||||
|
||||
bailout() {
|
||||
rm -f "$OUTPUT"
|
||||
}
|
||||
|
||||
trap bailout 1 2 3 3 6 9 14 15
|
||||
|
||||
OK() {
|
||||
printf "ok ${1} ${2}\n"
|
||||
}
|
||||
|
||||
FAIL() {
|
||||
printf "not ok ${1} ${2}\n"
|
||||
RC=1
|
||||
}
|
||||
|
||||
assertEqualFiles() {
|
||||
[ "$#" -eq 2 ] || return 1
|
||||
|
||||
(( count++ ))
|
||||
|
||||
if cmp "$1" "$2" 2>/dev/null ; then
|
||||
OK "$count" "$2" >> "$OUTPUT"
|
||||
else
|
||||
echo "files $1 and $2 do not match" >&2
|
||||
FAIL "$count" "$2 # $2 differs from $1" >> "$OUTPUT"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
# make sure ip/netmask/interface can be set on exisiting host
|
||||
${CMD} --input-file=network-config/network_pro.yml --output-file=testfiles/eth42.yml \
|
||||
--host=sp1 --set-interface=eth42 --ip=1.2.3.4 --netmask=255.255.255.248
|
||||
assertEqualFiles testfiles/eth42.yml network-config/eth42.yml
|
||||
|
||||
# verify deployment steps
|
||||
ROLE=sp1; PEER=sp2; DEFAULT_INSTALL_DEV=eth0; INTERNAL_DEV=eth1;
|
||||
|
||||
in_counter=1; out_counter=1 # do not hardcode input/output files
|
||||
|
||||
${CMD} --host=$ROLE --set-interface=lo --ip=127.0.0.1 --netmask=255.0.0.0 \
|
||||
--hwaddr=00:00:00:00:00:00 --ipv6='::1' --type=web_int \
|
||||
--input-file=network-config/network_pro.yml --output-file=testfiles/deploy_${out_counter}.yml
|
||||
((out_counter++))
|
||||
|
||||
${CMD} --host=$ROLE --set-interface=lo --shared-ip=none --shared-ipv6=none \
|
||||
--input-file=testfiles/deploy_${in_counter}.yml --output-file=testfiles/deploy_${out_counter}.yml
|
||||
((out_counter++)) ; ((in_counter++))
|
||||
|
||||
${CMD} --host=$ROLE --set-interface=$DEFAULT_INSTALL_DEV --ip=1.2.3.4 \
|
||||
--netmask=255.255.255.0 --hwaddr=de:ad:be:ef:23:42 --dns=2.3.4.5 --dns=3.4.5.6 \
|
||||
--gateway=1.2.3.1 \
|
||||
--input-file=testfiles/deploy_${in_counter}.yml --output-file=testfiles/deploy_${out_counter}.yml
|
||||
((out_counter++)) ; ((in_counter++))
|
||||
|
||||
${CMD} --host=$ROLE --set-interface=$INTERNAL_DEV --ip=192.168.255.251 \
|
||||
--netmask=255.255.255.248 --hwaddr=de:ad:be:ef:42:23 \
|
||||
--input-file=testfiles/deploy_${in_counter}.yml --output-file=testfiles/deploy_${out_counter}.yml
|
||||
((out_counter++)) ; ((in_counter++))
|
||||
|
||||
${CMD} --host=$ROLE --peer=$PEER \
|
||||
--input-file=testfiles/deploy_${in_counter}.yml --output-file=testfiles/deploy_${out_counter}.yml
|
||||
((out_counter++)) ; ((in_counter++))
|
||||
|
||||
${CMD} --host=$ROLE --move-from=lo --move-to=$INTERNAL_DEV --type=ha_int \
|
||||
--input-file=testfiles/deploy_${in_counter}.yml --output-file=testfiles/deploy_${out_counter}.yml
|
||||
((out_counter++)) ; ((in_counter++))
|
||||
|
||||
${CMD} --host=$PEER --peer=$ROLE \
|
||||
--input-file=testfiles/deploy_${in_counter}.yml --output-file=testfiles/deploy_${out_counter}.yml
|
||||
((out_counter++)) ; ((in_counter++))
|
||||
|
||||
${CMD} --host=$PEER --set-interface=lo --shared-ip=none --shared-ipv6=none \
|
||||
--input-file=testfiles/deploy_${in_counter}.yml --output-file=testfiles/deploy_${out_counter}.yml
|
||||
((out_counter++)) ; ((in_counter++))
|
||||
|
||||
${CMD} --host=$PEER --set-interface=lo --ipv6='::1' --ip=127.0.0.1 --netmask=255.0.0.0 --hwaddr=00:00:00:00:00:00 \
|
||||
--input-file=testfiles/deploy_${in_counter}.yml --output-file=testfiles/deploy_${out_counter}.yml
|
||||
((out_counter++)) ; ((in_counter++))
|
||||
|
||||
${CMD} --host=$PEER --set-interface=eth1 --ip=192.168.255.252 --netmask=255.255.255.248 --type=ha_int \
|
||||
--input-file=testfiles/deploy_${in_counter}.yml --output-file=testfiles/deploy_${out_counter}.yml
|
||||
((out_counter++)) ; ((in_counter++))
|
||||
|
||||
${CMD} --host=$PEER --role=proxy --role=lb --role=mgmt \
|
||||
--input-file=testfiles/deploy_${in_counter}.yml --output-file=testfiles/deploy_${out_counter}.yml
|
||||
((out_counter++)) ; ((in_counter++))
|
||||
|
||||
${CMD} --host=$PEER --set-interface=lo --type=sip_int --type=web_ext --type=sip_ext \
|
||||
--type=rtp_ext --type=ssh_ext --type=mon_ext --type=web_int \
|
||||
--input-file=testfiles/deploy_${in_counter}.yml --output-file=testfiles/deployment.yml
|
||||
|
||||
assertEqualFiles testfiles/deployment.yml network-config/deployment.yml
|
||||
|
||||
|
||||
# TAP output
|
||||
printf "1..$count\n"
|
||||
cat "$OUTPUT"
|
||||
|
||||
bailout
|
||||
|
||||
exit $RC
|
@ -0,0 +1,31 @@
|
||||
# Filename: /etc/ngcp-config/ngcpcfg.cfg
|
||||
# Purpose: main configuration file for ngcpcfg tools
|
||||
# Note: do not modify unless you have a really good reason to do so
|
||||
|
||||
# directory name where ngcpcfg is managed through git
|
||||
NGCPCTL_MAIN='./ngcp-config'
|
||||
NGCPCTL_CONFIG="${NGCPCTL_MAIN}/config.yml"
|
||||
HOST_CONFIG="${NGCPCTL_MAIN}/config.$(hostname).yml"
|
||||
LOCAL_CONFIG="${NGCPCTL_MAIN}/config.local.yml"
|
||||
CONSTANTS_CONFIG="${NGCPCTL_MAIN}/constants.yml"
|
||||
|
||||
# configuration files that should be managed
|
||||
CONFIG_POOL='/tmp/output'
|
||||
|
||||
# location of templates
|
||||
TEMPLATE_POOL="${NGCPCTL_MAIN}/templates/testsuite"
|
||||
|
||||
# location of service definitions
|
||||
SERVICES_POOL="${NGCPCTL_MAIN}/templates/testsuite"
|
||||
|
||||
## NOTE: only supported with ngcp-ngcpcfg-ha
|
||||
# supported values: {true,false}
|
||||
SHARED_STORAGE='true'
|
||||
|
||||
# name of shared storage
|
||||
GLUSTERFS='./glusterfs'
|
||||
|
||||
# name of shared storage repository
|
||||
NGCPCTL_SHARE="${GLUSTERFS}/ngcpcfg-share"
|
||||
|
||||
## END OF FILE #################################################################
|
Loading…
Reference in new issue