#!/bin/sh

#
# Netmagis database creation
#
# Syntax :
#	netmagis-dbcreate [netmagis] [mac]
#
# History
#   2002/02/11 : pda        : design
#   2002/02/12 : pda/jean   : adapt to new data model
#   2002/04/19 : pda/jean   : unique constraint on name+domain
#   2002/04/19 : pda        : unique constraint on domain name
#   2002/04/23 : pda        : add priority in domain permissions
#   2002/04/23 : pda/jean   : add zone generation management
#   2002/05/02 : pda/jean   : use PG objects for zone tables
#   2002/05/06 : pda        : id for zone table
#   2002/05/21 : pda        : add communaute table
#   2004/01/22 : pda        : use new data model
#   2005/04/08 : pda        : use new data model (v 1.3)
#   2007/11/27 : pda/jean   : pgsql 8.2
#   2007/11/27 : pda/jean   : add log table
#   2011/01/21 : pda        : i18n
#   2011/01/21 : pda        : use new config file
#   2011/07/17 : pda        : defuser is given a value and created
#   2011/12/28 : pda        : add dotattr table
#   2012/01/21 : jean       : add p_genl attribute
#   2012/04/08 : pda        : simplify users
#   2012/04/08 : pda        : mac database creation
#   2012/06/15 : pda/jean   : drop -u/-w for an obsolete privileged user
#   2012/06/19 : pda        : don't create copy database
#   2012/09/20 : pda/jean   : remove dnsupdateperiod
#   2012/09/27 : pda/jean   : rename dns.zone.domain
#   2012/10/24 : pda/jean   : dhcp generation is per view
#

usage ()
{
    (
	echo "usage: $0 [netmagis] [mac]"
	echo "  netmagis : create netmagis database and schemas"
	echo "  mac      : create mac database and schema"
    ) >&2
    exit 1
}

# defuser is used for initial database migration
defuser="nobody"

##############################################################################
# Configuration file read
##############################################################################

init_env ()
{
    # Main netmagis database parameters (dnsdb*)
    varlist="dnsdbhost dnsdbport dnsdbname dnsdbuser dnsdbpassword rootusers"
    eval `/usr/local/bin/netmagis-config -c $varlist`

    if [ $? != 0 ]
    then
	usage
	exit 1
    fi

    # Mac database parameters (macdb*)
    varlist="macdbhost macdbport macdbname macdbuser macdbpassword"
    eval `/usr/local/bin/netmagis-config -c $varlist`

    if [ $? != 0 ]
    then
	usage
	exit 1
    fi

    # These variables are searched in a second pass, since they can be empty
    # (the first pass used the "-c" flag) 
    varlist="pwgen ouiurl"
    eval `/usr/local/bin/netmagis-config $varlist`
}

##############################################################################
# Generic database creation
##############################################################################

# returns an error if creation failed
db_create_if_not_exists ()
{
    r=0
    if psql --no-psqlrc -c "" 2> /dev/null
    then :
    else
	# black magic: use template0 to avoid encoding incompatibility
	createdb -E unicode --template=template0
	r=$?
    fi
    return $r
}

# $* = schemas to test
# returns true if schema exists
db_test_schemas ()
{
    schemas=`psql --quiet --no-psqlrc --tuples-only --no-align \
		    -c "SELECT nspname FROM pg_catalog.pg_namespace"`
    r=1
    for i
    do
	if echo "$schemas" | grep "^$i$" > /dev/null
	then
	    (
		echo "Error: schema '$i' already exists in database '$PGDATABASE'"
		echo "Use either 'DROP SCHEMA $i' SQL command to destroy schema"
		echo "or 'dropdb $PGDATABASE' shell command to destroy database"
	    ) >&2
	    r=0
	    break
	fi
    done
    return $r
}

##############################################################################
# SQL file execution
##############################################################################

# $1 = file (relative to /usr/local/lib/netmagis)
sql_file_execute ()
{
    PGCLIENTENCODING=utf8
    export PGCLIENTENCODING

    psql --no-psqlrc --quiet --file /usr/local/lib/netmagis/$1 2>&1 \
	| grep -v 'NOTICE: .* will create implicit'
}

##############################################################################
# Language creation
##############################################################################

# $1 = language
# exits if creation failed
create_language ()
{
    if psql --quiet --no-psqlrc -c "CREATE EXTENSION IF NOT EXISTS $1"
    then :
    else
	echo "Unable to create language "$1" in database '$PGDATABASE'" >&2
	exit 1
    fi
}

##############################################################################
# Create netmagis database
##############################################################################

create_netmagis ()
{
    echo "Creating main Netmagis database as '$dnsdbname'"

    PGHOST="$dnsdbhost"
    PGPORT="$dnsdbport"
    PGDATABASE="$dnsdbname"
    PGUSER="$dnsdbuser"
    PGPASSWORD="$dnsdbpassword"
    export PGHOST PGPORT PGDATABASE PGUSER PGPASSWORD

    ###############################
    # Create main netmagis database
    ###############################

    if db_create_if_not_exists
    then :
    else
	echo "Erreur while creating database '$PGDATABASE'" 2>&1
	exit 1
    fi

    # exit if schema already exist
    if db_test_schemas "global" "dns" "topo" "pgauth"
    then
	exit 1
    fi

    ###############################
    # Initialize main netmagis database schemas and contents
    ###############################

    create_language plpgsql
    create_language pltcl

    create_netmagis_schemas

    netmagis_insert_config

    ###############################
    # Create netmagis application users
    ###############################

    for u in $rootusers
    do
	netmagis_create_user $u
    done

    netmagis_create_user $defuser

    if [ "$pwgen" = "" ]
    then
	echo "Netmagis configuration parameter 'pwgen' uninitialized" >&2
    else
	echo "Users $rootusers have been created" >&2
	echo "You can change passwords within netmagis application" >&2
    fi
}

##############################################################################
# Netmagis schema creation
##############################################################################

create_netmagis_schemas ()
{
    for i in schema-main.sql functions.sql triggers.sql
    do
	sql_file_execute $i
    done
}

##############################################################################
# Default values for Netmagis config keys
##############################################################################

netmagis_insert_config ()
{
    psql --no-psqlrc --quiet --file - <<'EOF'

    COPY global.config (key, value) FROM stdin;
datefmt	%d/%m/%Y %H:%M:%S
dayfmt	%a %d %b %Y
authmethod	pgsql
authexpire	36000
authtoklen	32
wtmpexpire	365
pageformat	a4
default_lease_time	600
max_lease_time	3600
min_lease_time	300
topoactive	0
dhcpdefdomain	example.com
defdomain	example.com
topofrom	nobody.topo@example.com
topoto	noc@example.com another@example.com
topographddelay	5
toposendddelay	5
topomaxstatus	100
sensorexpire	30
modeqexpire	30
ifchangeexpire	30
fullrancidmin	2
fullrancidmax	4
macactive	0
failloginthreshold1	3
failloginthreshold2	10
faillogindelay1	120
faillogindelay2	300
failipthreshold1	10
failipthreshold2	30
failipdelay1	300
failipdelay2	1200
casurl	https://cas.example.com/cas/
ldapurl	ldap://ldap.example.com/
ldapbinddn	cn=admin,ou=accounts,ou=operators,dc=example,dc=com
ldapbindpw	*
ldapbasedn	ou=people,dc=example,dc=com
ldapsearchlogin	(&(objectClass=People)(uid=%s))
ldapattrlogin	uid
ldapattrname	sn
ldapattrgivenname	givenName
ldapattrmail	mail
ldapattrphone	telephoneNumber
ldapattrmobile	
ldapattrfax	facsimileTelephoneNumber
ldapattraddr	postalAddress postalCode l
authpgminpwlen	10
authpgmaxpwlen	128
authpgmailfrom	nobody.netmagis@example.com
authpgmailreplyto	nobody.netmagis@example.com
authpgmailcc	
authpgmailbcc	
authpgmailsubject	Password change
authpgmailbody	Password changed (%2$s) for user %1$s. Best regards.
authpggroupes	netmagis
schemaversion	23
\.

    -- id 0 is used in zone creation script
    COPY dns.hinfo (name, sort, present) FROM stdin;
Unspecified	0	0
PC/Windows	10	1
PC/Unix	20	1
Macintosh/MacOS	30	1
Other/Unix	50	1
Printer	70	1
Network equipment	100	1
\.

    COPY dns.view (name, gendhcp) FROM stdin;
default	0
\.

    COPY topo.lastrun (date) FROM stdin;
\N
\.

    COPY topo.ignoreequsers (login) FROM stdin;
conf
\.

    COPY topo.vlan (vlanid, descr) FROM stdin;
1	default
\.

    COPY topo.eqtype (type) FROM stdin;
cisco
juniper
hp
\.

    COPY topo.confcmd (idtype, action, rank, model, command) FROM stdin;
1	prologue	100	.*	configure terminal
1	ifreset	90	.*29.0.*	interface %1$s\ndefault switchport nonegotiate\ndefault switchport trunk allowed vlan\ndefault switchport trunk native vlan\ndefault switchport access vlan\ndefault switchport mode
1	ifreset	100	.*	interface %1$s\nno switchport\nswitchport voice vlan none\nswitchport
1	ifdisable	100	.*	interface %1$s\nshutdown
1	ifenable	100	.*	interface %1$s\nno shutdown
1	ifaccess	100	.*	interface %1$s\nswitchport mode access\nswitchport access vlan %2$s\nspanning-tree portfast 
1	ifvoice	100	.*	interface %1$s\nswitchport voice vlan %2$s
1	ifdesc	100	.*	interface %1$s\ndescription %2$s
1	epilogue	100	.*	line con 0\nexit\nexit\nwrite memory 
2	prologue	100	.*	configure
2	ifreset	100	.*	delete interfaces %1$s unit 0 family ethernet-switching\ndelete ethernet-switching-options voip interface %1$s
2	ifdisable	100	.*	set interfaces %1$s disable
2	ifenable	100	.*	delete interfaces %1$s disable
2	ifaccess	100	.*	set interfaces %1$s unit 0 family ethernet-switching port-mode access\nset interfaces %1$s unit 0 family ethernet-switching vlan members %2$s
2	ifdesc	100	.*	set interfaces %1$s description "%2$s"
2	ifvoice	100	.*	set interfaces %1$s unit 0 family ethernet-switching\nset ethernet-switching-options voip interface %1$s vlan %2$s
2	epilogue	100	.*	commit\nexit configuration
3	prologue	100	.*	configure terminal
3	resetvlan	100	.*	vlan %2$s\nno tagged %1$s\nno untagged %1$s
3	ifenable	100	.*	interface %1$s\nenable
3	ifdisable	100	.*	interface %1$s\ndisable
3	ifaccess	100	.*	vlan %2$s\nuntagged %1$s
3	ifvoice	100	.*	vlan %2$s\ntagged %1$s
3	ifdesc	100	.*	interface %1$s\nname "%2$s"
3	epilogue	100	.*	vlan 1\nexit\nexit\nwrite memory
\.

    COPY topo.dotattr (rank, type, regexp, gvattr) FROM stdin;
10100	2	juniper/M.*	shape=circle\nstyle=filled fillcolor=lightgrey\nfixedsize=true height=1
10200	2	cisco/12000.*	shape=doublecircle\nstyle=filled fillcolor=lightgrey\nfixedsize=true height=1
10300	2	juniper/EX8.*	shape=box style=filled fillcolor=lightblue
10400	2	juniper/Chassis.*	shape=box style=filled fillcolor=lightblue
10500	2	cisco/WS-C45.*	shape=box style=filled fillcolor=lightblue
10600	2	cisco/WS-C37.*	shape=box style=filled fillcolor=lightblue height=.25
10700	2	cisco/WS-C29.*	shape=box style=filled fillcolor=lightblue height=.25
10800	2	cisco/WS-.*PS	shape=box style=filled fillcolor=yellow height=.25
10900	2	cisco/37.*	shape=octagon style=filled fillcolor=orange1 height=.25
11000	2	cisco/38.*	shape=octagon style=filled fillcolor=orange1
11100	2	cisco/.*routeur	shape=circle\nstyle=filled fillcolor=lightgrey\nfixedsize=true height=1
11200	2	cisco/1605.*	shape=circle\nstyle=filled fillcolor=lightgrey\nfixedsize=true height=1
11300	2	cisco/1721.*	shape=circle\nstyle=filled fillcolor=lightgrey\nfixedsize=true height=1
11400	2	cisco/7206.*	shape=circle\nstyle=filled fillcolor=lightgrey\nfixedsize=true height=1
11500	2	juniper/EX2.*	shape=box style=filled fillcolor=SteelBlue height=.25
11600	2	juniper/EX4.*	shape=box style=filled fillcolor=SteelBlue height=.25
11900	2	fwroutebridge.*	shape=Mcircle\nstyle=filled fillcolor=tomato\nheight=1
13000	2	fwroute.*	shape=circle\nstyle=filled fillcolor=tomato\nheight=1
13100	2	fw.*	shape=box style=filled fillcolor=tomato height=.25
13200	2	switch.*	shape=box style=filled fillcolor=lightgrey height=.25
13300	2	hp.*	shape=box style=filled fillcolor=pink height=.25
13400	2	.*	shape=triangle
20100	3	router	shape=circle\nstyle=filled fillcolor=lightgrey\nfixedsize=true height=1.5
20200	3	host	shape=box\nstyle=filled fillcolor=lightblue\nheight=.25
20300	3	cloud	shape=ellipse\nstyle=filled fillcolor=palegreen\nwidth=1.5
\.

    COPY pgauth.realm (realm, descr, admin) FROM stdin;
authadmin	Administrators of internal PostgreSQL auth	1
netmagis	Netmagis users	0
\.

    COPY global.nmgroup (name, p_admin) FROM stdin;
wheel	1
\.
EOF

    psql --no-psqlrc --quiet -c "INSERT INTO global.config (key, value)
					VALUES ('defuser', '$defuser')"
}

##############################################################################
# Create Netmagis users
##############################################################################

netmagis_create_user ()
{
    user="$1"
    psql --no-psqlrc --quiet --file - <<EOF
    INSERT INTO pgauth.user (login, password, lastname, firstname)
	VALUES ('$user', '*', 'Boss', 'Joe') ;
    INSERT INTO pgauth.member (login, realm) VALUES ('$user', 'authadmin') ;
    INSERT INTO pgauth.member (login, realm) VALUES ('$user', 'netmagis') ;
    INSERT INTO global.nmuser (login, present, idgrp) VALUES ('$user', 1, 1) ;
EOF

    if [ "$pwgen" != "" ]
    then
	adminpw=$($pwgen)
	cryptpw=$(openssl passwd -1 "$adminpw")
	psql --no-psqlrc --quiet -c "UPDATE pgauth.user
					SET password = '$cryptpw'
					WHERE login = '$user'"
	echo "Password for Netmagis user '$user' is '$adminpw'." >&2
    fi

}

##############################################################################
# Create mac database
##############################################################################

create_mac ()
{
    echo "Creating MAC database as '$macdbname'"

    PGHOST="$macdbhost"
    PGPORT="$macdbport"
    PGDATABASE="$macdbname"
    PGUSER="$macdbuser"
    PGPASSWORD="$macdbpassword"
    export PGHOST PGPORT PGDATABASE PGUSER PGPASSWORD

    ###############################
    # Create mac database
    ###############################

    if db_create_if_not_exists
    then :
    else
	echo "Erreur while creating database '$PGDATABASE'" 2>&1
	exit 1
    fi

    # exit if schema already exist
    if db_test_schemas "mac"
    then
	exit 1
    fi

    ###############################
    # Initialize mac database schemas and contents
    ###############################

    create_mac_schemas
    insert_mac_oui
}

##############################################################################
# Mac database 
##############################################################################

create_mac_schemas ()
{
    sql_file_execute schema-mac.sql
}

insert_mac_oui ()
{
    /usr/local/sbin/netmagis-getoui
}

##############################################################################
# Main program
##############################################################################

#
# Initialize environnement
#

init_env

#
# Syntax checking
#       
 
args=`getopt h $*`

if [ $? != 0 ]
then usage
fi

set -- $args

while true
do
    case "$1" in
	-h) usage
	    exit 0
	    ;;
	--) shift
	    break
	    ;;
    esac
done

if [ $# = 0 ]
then set netmagis mac
fi

#
# Check actions
#

for action
do
    case "$action" in
	netmagis|mac) ;;
	*)
	    echo "Unknown action '$action'" >&2
	    usage
	    exit 1
	    ;;
    esac
done

#
# Do actions
#

for action
do
    case "$action" in
	netmagis) create_netmagis ;;
	mac)      create_mac ;;
    esac
done


exit 0
