slapos-configure.sh 18.3 KB
Newer Older
1 2
#! /bin/bash
#
3 4
# This script need root rights. Before run it, make sure you have root
# right.
5
#
6 7
# It used to configure slapos node, it could be run at anytime to
# check the configure of slapos node. The main functions:
8
#
9
#     * Install msloop network adapter, named to re6stnet-lo
10 11 12 13 14 15 16 17 18
#
#     * ipv6: Ipv6 configure
#
#     * re6stnet: Install re6stnet and register to nexedi re6stnet if it hasn't
#
#     * node: Create node configure file by parameters ca/key
#
#     * client: Create client configure file by parameters ca/key
#
19
#     * cron: create cron configure file
20 21 22
#
# Usage:
#
23
#    ./slapos-configure
24 25 26
#
export PATH=/usr/local/bin:/usr/bin:$PATH

27 28 29 30 31 32 33
grep -q "export CYGWIN=server" ~/.bash_profie || echo "export CYGWIN=server" >> ~/.bash_profile
grep -q "export CYGWIN=server" ~/.profie || echo "export CYGWIN=server" >> ~/.profile

#-------------------------------------------------
# Common functions
#-------------------------------------------------

34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
#
# Return connection name by line, and replace space with '%'
#
function get_all_connections()
{
    netsh interface ipv6 show interface | \
    grep "^[ 0-9]\+ " | \
    sed -e "s/^[ 0-9]\+[a-zA-Z]\+//" -e "s/^\s*//" -e "s/ /%/g"
}

#
# Check all the connection names, and compare the original connection
# list, return the new connection name
#
# If nothing found, return empty
# If more than one, return the first one
#
function get_new_connection()
{
    original_connections=" $* "
    current_connections=$(get_all_connections)

    for name in $current_connections ; do
        [[ ! "$original_connections" == *[\ ]$name[\ ]* ]] && \
        echo ${name//%/ } && return 0
    done
}

#
# Remove all ipv4/ipv6 addresses in the connection re6stnet-lo
#
function reset_connection()
{
    ifname=${1-re6stnet-lo}
    for addr in $(netsh interface ipv6 show address $ifname level=normal | \
                grep "^Manual" | \
                sed -e "s/^\(\w\+\s\+\)\{4\}//") ; do
        netsh interface ipv6 del address $ifname $addr
    done
    netsh interface ip set address $ifname source=dhcp
    # for addr in $(netsh interface ip show address $ifname | \
    #             grep "IP Address:" | \
    #             sed -e "s/IP Address://") ; do
    #     netsh interface del address $ifname $addr
    # done
}

#
# Transfer connection name to GUID
#
function connection2guid()
{
    ifname=${1-re6stnet-lo}
87 88 89 90
    #
    # This command doesn't work in the Windows 7, Window 8, maybe
    # Vista. Because no guid information in these platforms.
    #
91 92 93
    # netsh interface ipv6 show interface $ifname | \
    #     grep "^GUID\s*:" | \
    #     sed -e "s/^GUID\s*:\s*//"
94 95
    #
    # So we use getmac to repleace it:
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
    getmac /fo list /v | grep -A3 "^Connection Name: *$ifname\$" \
        | grep "^Transport Name:" | sed -e "s/^.*Tcpip_//g"
}

#
# Show error message and waiting for user to press any key quit
#
function show_error_exit()
{
    msg=${1-Failed to configure Slapos Node in this computer.}
    echo $msg
    read -n 1 -p "Press any key to exit..."
    exit 1
}

#
# Query the parameter, usage:
#
114
#   query_parameter ACTUAL EXCPETED MESSAGE
115 116 117 118 119 120
#
function query_parameter()
{
    if [[ X$1 == X || $1 == "*" || $1 == "all" ]] ; then
        return 1
    fi
121
    if [[ $1 == "?" || $1 == "query" ]] ; then
122 123 124 125 126 127 128 129 130 131 132 133 134
        read -n 1 -p $3 user_ack
        if [[ X$user_ack == X[Yy] ]] ; then
            return 1
        else
            return 0
        fi
    fi
    if [[ $1 == $2 ]] ; then
        return 1
    fi
    return 0
}

135 136 137
#-------------------------------------------------
# Constants
#-------------------------------------------------
138 139 140 141 142
slapos_client_home=~/.slapos
client_configure_file=$slapos_client_home/slapos.cfg
client_certificate_file=$slapos_client_home/certificate
client_key_file=$slapos_client_home/key
client_template_file=/etc/slapos/slapos-client.cfg.example
143
url_client_template_file=http://git.erp5.org/gitweb/slapos.core.git/blob_plain/HEAD:/slapos-client.cfg.example
144 145 146 147 148

node_certificate_file=/etc/opt/slapos/ssl/computer.crt
node_key_file=/etc/opt/slapos/ssl/computer.key
node_config_file=/etc/opt/slapos/slapos.cfg
node_template_file=/etc/slapos/slapos.cfg.example
149 150
url_node_template_file=http://git.erp5.org/gitweb/slapos.core.git/blob_plain/HEAD:/slapos.cfg.example

151
slapos_ifname=re6stnet-lo
152 153 154 155 156 157 158 159 160 161
# Hope it will not confilct with original network in the local machine
ipv4_local_network=10.201.67.0/24

slapos_runner_file=/etc/slapos/scripts/slap-runner.html
slaprunner_cfg=http://git.erp5.org/gitweb/slapos.git/blob_plain/refs/heads/cygwin-0:/software/slaprunner/software.cfg
slaprunner_title="Node Runner"

#-------------------------------------------------
# Create paths
#-------------------------------------------------
162

163 164 165
mkdir -p /etc/opt/slapos/ssl/partition_pki
mkdir -p $slapos_client_home

166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206
#-------------------------------------------------
# Configure cygwin server services
#-------------------------------------------------

echo Checking cygserver service ...
cygrunsrv --query cygserver > /dev/null
if (( $? )) ; then
    echo Run cygserver-config ...
    /usr/bin/cygserver-config --yes || \
        show_error_exit "Failed to run cygserver-config"
    echo OK.
else
    echo The cygserver service has been installed.
fi

echo Checking syslog-ng service ...
cygrunsrv --query syslog-ng > /dev/null
if (( $? )) ; then
    echo Run syslog-ng-config ...
    /usr/bin/syslog-ng-config --yes || \
        show_error_exit "Failed to run syslog-ng-config"
    echo OK.
else
    echo The syslog-ng service has been installed.
fi

echo Checking cron service ...
cygrunsrv --query cron > /dev/null
if (( $? )) ; then
    echo Run cron-config ...
    /usr/bin/cron-config --yes || \
        show_error_exit "Failed to run cron-config"
    echo OK.
else
    echo The cron service has been installed.
fi

#-------------------------------------------------
# Configure slapos network
#-------------------------------------------------

207 208 209 210 211 212 213 214 215 216 217 218 219 220
#
# Add msloop network adapter, ane name it as "re6stnet-lo"
#
echo Checking slapos network adapter: $slapos_ifname ...
original_connections=$(echo $(get_all_connections))
if [[ ! " $original_connections " == *[\ ]$slapos_ifname[\ ]* ]] ; then
    echo Installing slapos network adapter ...
    devcon install $WINDIR\\inf\\netloop.inf *MSLOOP
    connection_name=$(get_new_connection $original_connections)
    [[ "X$connection_name" == "X" ]] && \
        show_error_exit "Add msloop network adapter failed."
    echo
    netsh interface set interface name="$connection_name" newname="$slapos_ifname"
fi
221 222
#ip -4 addr add $ipv4_local_network dev $slapos_ifname
# reset_connection $slapos_ifname
223
echo SlapOS network adapter OK.
224
echo Slapos ipv4_local_network is $ipv4_local_network
225

226 227 228
#-------------------------------------------------
# Generate slapos node configure file
#-------------------------------------------------
229

230
echo Checking computer certificate file ...
231
if [[ ! -f $node_certificate_file ]] ; then
232 233
    read -p "Where is computer certificate file (/computer.crt): " certificate_file
    [[ X$certificate_file == X ]] && certificate_file=/computer.crt
234 235 236 237 238
    [[ ! -f "$certificate_file" ]] && \
        show_error_exit "Certificate file $certificate_file doesn't exists."
    echo "Copy certificate from $certificate_file to $node_certificate_file"
    certificate_file=$(cygpath -u $certificate_file)
    cp $certificate_file $node_certificate_file
239 240
else
    echo Found computer certificate file: $node_certificate_file
241
fi
242 243 244
openssl x509 -noout -in $node_certificate_file || \
    show_error_exit "Invalid computer certificate: $node_certificate_file."
echo Check computer certificate OK.
245

246
echo Checking computer guid ...
247 248 249 250 251
computer_id=$(grep  CN=COMP $node_certificate_file | sed -e "s/^.*, CN=//g" | sed -e "s%/emailAddress.*\$%%g")
[[ "$computer_id" == COMP-+([0-9]) ]] || \
    show_error_exit "Invalid computer id specified."
echo Computer GUID is: $computer_id

252
echo Checking computer key file ...
253
if [[ ! -f $node_key_file ]] ; then
254 255
    read -p "Where is computer key file (/computer.key): " key_file
    [[ X$key_file == X ]] && key_file=/computer.key
256 257 258 259 260
    [[ ! -f "$key_file" ]] && \
        show_error_exit "Key file $key_file doesn't exists."
    echo "Copy key from $key_file to $node_key_file"
    key_file=$(cygpath -u $key_file)
    cp $key_file $node_key_file
261 262
else
    echo Found computer key file: $node_key_file
263
fi
264 265 266
openssl rsa -noout -in $node_key_file -check || \
    show_error_exit "Invalid computer key: $node_key_file."
echo Check computer key OK.
267 268 269

# Create node configure file, replace interface_name with guid of
# re6stnet-lo
270
echo Checking computer configure file ...
271 272
if [[ ! -f $node_config_file ]] ; then
    [[ -f $node_template_file ]] || \
273
        (cd /etc/slapos; wget $url_node_template_file -O $node_template_file) || \
274
        show_error_exit "Download slapos.cfg.example failed."
275
    echo "Copy computer configure file from $node_template_file to $node_config_file"
276 277 278
    cp $node_template_file $node_config_file
fi

279 280 281 282 283 284 285 286
interface_guid=$(connection2guid $slapos_ifname) || \
    show_error_exit "Failed to get guid of interface: $slapos_ifname."

echo Computer configuration information:
echo    interface name:     $slapos_ifname
echo              GUID:     $interface_guid
echo    ipv4_local_network: $ipv4_local_network
echo    computer_id:        $computer_id
287 288 289 290 291 292
# generate /etc/slapos/slapos.cfg
sed -i  -e "s%^\\s*interface_name.*$%interface_name = $interface_guid%" \
        -e "s%^#\?\\s*ipv6_interface.*$%# ipv6_interface =%g" \
        -e "s%^ipv4_local_network.*$%ipv4_local_network = $ipv4_local_network%" \
        -e "s%^computer_id.*$%computer_id = $computer_id%" \
        $node_config_file
293
echo Check computer configure file OK.
294

295 296 297 298 299
#-------------------------------------------------
# Generate slapos client configure file
#-------------------------------------------------

echo Checking client certificate file ...
300
if [[ ! -f $client_certificate_file ]] ; then
301 302
    read -p "Where is client certificate file (/certificate): " certificate_file
    [[ X$certificate_file == X ]] && certificate_file=/certificate
303 304
    [[ ! -f "$certificate_file" ]] && \
        show_error_exit "Certificate file $certificate_file doesn't exists."
305
    echo "Copy client certificate from $certificate_file to $client_certificate_file"
306 307 308
    certificate_file=$(cygpath -u $certificate_file)
    cp $certificate_file $client_certificate_file
fi
309 310 311
openssl x509 -noout -in $client_certificate_file || \
    show_error_exit "Invalid client certificate: $client_certificate_file."
echo Check client certificate Ok.
312

313
echo Checking client key file ...
314
if [[ ! -f $client_key_file ]] ; then
315 316
    read -p "Where is client key file (/key): " key_file
    [[ X$key_file == X ]] && key_file=/key
317 318
    [[ ! -f "$key_file" ]] && \
        show_error_exit "Key file $key_file doesn't exists."
319
    echo "Copy client key from $key_file to $client_key_file"
320 321 322
    key_file=$(cygpath -u $key_file)
    cp $key_file $client_key_file
fi
323 324 325
openssl rsa -noout -in $client_key_file -check || \
    show_error_exit "Invalid client key: $client_key_file."
echo Checking computer key OK.
326

327
echo Checking client configure file ...
328
if [[ ! -f $client_configure_file ]] ; then
329 330 331 332 333
    [[ -f $client_template_file ]] || \
    (cd /etc/slapos; wget $url_client_template_file -O $client_template_file) || \
    show_error_exit "Download slapos-client.cfg.example failed."
    echo "Copy client configure file from $client_template_file to $client_config_file"
    cp $client_template_file $client_configure_file
334 335
fi

336 337 338 339
echo Client configuration information:
echo     client certificate file: $client_certificate_file
echo     client key file:         $client_key_file
echo
340 341 342
sed -i -e "s%^cert_file.*$%cert_file = $client_certificate_file%" \
       -e "s%^key_file.*$%key_file = $client_key_file%" \
       $client_configure_file
343
echo Check client configure file OK.
344

345
#-------------------------------------------------
346
# Re6stnet
347
#-------------------------------------------------
348 349

# Check ipv6, install it if it isn't installed.
350 351 352 353
echo Checking ipv6 protocol ...
netsh interface ipv6 show interface > /dev/null || netsh interface ipv6 install || \
    show_error_exit "Failed to install ipv6 protocol."
echo IPv6 protocol has been installed.
354 355

# miniupnpc is required by re6stnet
356
echo Checking miniupnpc ...
357
if [[ ! -d /opt/miniupnpc ]] ; then
358 359 360 361 362 363 364 365 366 367 368
    [[ -f /miniupnpc.tar.gz ]] || show_error_exit "No package found: /miniupnpc.tar.gz"
    echo "Installing miniupnpc ..."
    cd /opt
    tar xzf /miniupnpc.tar.gz --no-same-owner
    mv $(ls -d miniupnpc-*) miniupnpc
    cd miniupnpc
    make
    python setup.py install || show_error_exit "Failed to install miniupnpc."
    echo "Install miniupnpc OK."
else
    echo Check miniupnpc OK.
369 370 371
fi

# pyOpenSSL is required by re6stnet
372
echo Checking pyOpenSSL ...
373
if [[ ! -d /opt/pyOpenSSL ]] ; then
374 375 376 377 378 379 380 381 382 383
    [[ -f /pyOpenSSL.tar.gz ]] || show_error_exit "No package found: /pyOpenSSL.tar.gz"
    echo "Installing pyOpenSSL ..."
    cd /opt
    tar xzf /pyOpenSSL.tar.gz --no-same-owner
    mv $(ls -d pyOpenSSL-*) pyOpenSSL
    cd pyOpenSSL
    python setup.py install ||  show_error_exit "Failed ot install pyOpenSSL."
    echo "Install pyOpenSSL OK."
else
    echo Check pyOpenSSL OK.
384 385 386
fi

# Install re6stnet
387
echo Checking re6stnet ...
388 389 390 391 392 393 394 395 396 397 398
if [[ ! -d /opt/re6stnet ]] ; then
    echo "Installing re6stnet ..."
    cd /opt
    if [[ -f /re6stnet.tar.gz ]] ; then
        tar xzf /re6stnet.tar.gz --no-same-owner
        mv $(ls -d re6stnet-*) re6stnet
    else
        echo "Clone re6stnet from http://git.erp5.org/repos/re6stnet.git"
		git clone -b cygwin http://git.erp5.org/repos/re6stnet.git
    fi
    cd re6stnet
399 400 401 402
    python setup.py install || show_error_exit "Failed to install re6stnet."
    echo "Install re6stnet OK."
else
    echo Check re6stnet OK.
403 404
fi

405
echo Checking re6stent configuration ...
406 407 408
mkdir -p /etc/re6stnet
cd /etc/re6stnet
if [[ ! -f re6stnet.conf ]] ; then
409 410 411 412 413 414 415 416 417 418 419 420 421
    echo Register to http://re6stnet.nexedi.com ...
    # Your subnet: 2001:67c:1254:e:19::/80 (CN=917529/32)
    mysubnet=$(re6st-conf --registry http://re6stnet.nexedi.com/ --anonymous | grep "^Your subnet:") \
        || show_error_exit "Register to nexedi re6stnet failed"
    echo Register OK.
    echo
    echo $mysubnet
    echo
    echo Write subnet information to re6stnet.conf
    echo "# $mysubnet" >> re6stnet.conf
    echo Write "table 0" to re6stnet.conf
    echo "table 0" >> re6stnet.conf

422
fi
423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438
[[ ! -f re6stnet.conf ]] && \
    show_error_exit "Failed to register to nexedi re6stnet: no /etc/re6stnet/re6stnet.conf found."
grep -q "^table " re6stnet.conf || \
    show_error_exit "Error: no parameter 'table 0' found in the /etc/re6stnet/re6stnet.conf"
grep -q "^# Your subnet: " re6stnet.conf || \
    show_error_exit "Error: no subnet found in the /etc/re6stnet/re6stnet.conf"
echo Check re6stnet configuration OK.

#-------------------------------------------------
# Create instance of Web Runner
#-------------------------------------------------
grep -q "location.reload" $slapos_runner_file
if (( $? )) ; then
    echo
    echo Installing Web Runner ...
    echo
439

440 441 442 443 444 445 446 447 448 449 450
    re6stnet_ipv6=$(cat /etc/re6stnet/re6stnet.conf | grep "Your subnet" | \
        sed -e "s/^.*subnet: //g" -e "s/ (CN.*\$//g")1
    echo "Re6stnet address in this computer: $re6stnet_ipv6"
    netsh interface ipv6 show addr $slapos_ifname | grep -q $re6stnet_ipv6 || \
        netsh interface ipv6 add addr $slapos_ifname re6stnet_ipv6
    echo Run slapformat ...
    /opt/slapos/bin/slapos node format -cv --now ||
        show_error_exit "Failed to run slapos format."
    echo
    
    echo "Supply $slaprunner_cfg in the computer $computer_id"
451
    /opt/slapos/bin/slapos supply  $slaprunner_cfg $computer_id
452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525
    echo "Request an instance 'Node Runner' ..."
    while true ; do
        /opt/slapos/bin/slapos node software
        /opt/slapos/bin/slapos node instance
        /opt/slapos/bin/slapos request $slaprunner_title $slaprunner_cfg --node computer_guid=$computer_id && break
    done

    # Connection parameters of instance are:
    #  {'backend_url': 'http://[2001:67c:1254:45::c5d5]:50000',
    #  'cloud9-url': 'http://localhost:9999',
    #  'password_recovery_code': 'e2d01c14',
    #  'ssh_command': 'ssh 2001:67c:1254:45::c5d5 -p 2222',
    #  'url': 'http://softinst39090.host.vifib.net/'}
    slaprunner_url=$(/opt/slapos/bin/slapos request $slaprunner_title \
        $slaprunner_cfg --node computer_guid=$computer_id \
        | grep backend_url | sed -e "s/^.*': '//g" -e "s/',.*$//g")
    echo Got node runner url: $slaprunner_url

    echo <<EOF > $slapos_runner_file
<html>
<head><title>SlapOS Web Runner</title>
<script LANGUAGE="JavaScript">
<!--
function openwin() {
  location.reload("$slaprunner_url")
}
//-->
</script>
</head>
<body onload="openwin()"/>
</html>
EOF
    echo Generate file: $slapos_runner_file

    # Apply patches to slapos.cookbook for inotifix
    patch_file=/etc/slapos/patches/slapos-cookbook-inotifyx.patch
    if [[ -f $patch_file ]] ; then
        echo "Apply patch: $patch_file"
        for x in $(find /opt/slapgrid/ -name slapos.cookbook-*.egg) ; do
            echo Apply to $x
            cd $x
            patch -p1 < $patch_file
        done
    fi
    echo
    echo Install Web Runner OK.
    echo
fi

#-------------------------------------------------
# Configure crontab
#-------------------------------------------------
cron_file=/var/cron/tabs/$(whoami)
if [[ ! -f $cron_file ]] ; then
    cat <<EOF  > $cron_file
SHELL=/bin/sh
PATH=/usr/bin:/usr/sbin:/sbin:/bin
MAILTO=""

# Run "Installation/Destruction of Software Releases" and "Deploy/Start/Stop Partitions" once per minute
* * * * * Administrator /opt/slapos/bin/slapos node software --verbose --logfile=/opt/slapos/log/slapos-node-software.log > /dev/null 2>&1
* * * * * Administrator /opt/slapos/bin/slapos node instance --verbose --logfile=/opt/slapos/log/slapos-node-instance.log > /dev/null 2>&1

# Run "Destroy Partitions to be destroyed" once per hour
0 * * * * Administrator /opt/slapos/bin/slapos node report --maximal_delay=3600 --verbose --logfile=/opt/slapos/log/slapos-node-report.log > /dev/null 2>&1

# Run "Check/add IPs and so on" once per hour
0 * * * * Administrator /opt/slapos/bin/slapos node format >> /opt/slapos/log/slapos-node-format.log 2>&1


# Make sure we have only good network routes if we use VPN
# * * * * * root if [ -f /etc/opt/slapos/openvpn-needed  ]; then ifconfig tapVPN | grep "Scope:Global" > /dev/null ;if [ $? = 0 ]; then ROUTES=$(ip -6 r l | grep default | awk '{print $5}'); for GW in $ROUTES ; do if [ ! $GW = tapVPN ]; then /sbin/ip -6 route del default dev $GW > /dev/null 2>&1;fi ;done ;fi ;fi
EOF
fi
526 527 528 529

echo SlapOS Node configure successfully.
read -n 1 -p "Press any key to exit..."
exit 0