2 # Copyright 2016 Telefónica Investigación y Desarrollo S.A.U.
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
8 # http://www.apache.org/licenses/LICENSE-2.0
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
17 echo -e "usage: $0 [OPTIONS]"
18 echo -e "Install OSM from binaries or source code (by default, from binaries)"
20 echo -e " --uninstall: uninstall OSM: remove the containers and delete NAT rules"
21 echo -e " --source: install OSM from source code using the latest stable tag"
22 echo -e " -r <repo>: use specified repository name for osm packages"
23 echo -e " -R <release>: use specified release for osm binaries (deb packages, lxd images, ...)"
24 echo -e " -u <repo base>: use specified repository url for osm packages"
25 echo -e " -k <repo key>: use specified repository public key url"
26 echo -e " -b <refspec>: install OSM from source code using a specific branch (master, v2.0, ...) or tag"
27 echo -e " -b master (main dev branch)"
28 echo -e " -b v2.0 (v2.0 branch)"
29 echo -e " -b tags/v1.1.0 (a specific tag)"
31 echo -e " --lxdimages: download lxd images from OSM repository instead of creating them from scratch"
32 echo -e " -l <lxd_repo>: use specified repository url for lxd images"
33 echo -e " -p <path>: use specified repository path for lxd images"
34 echo -e " --lightweight: install lightweight build of OSM (default installation)"
35 echo -e " --soui: install classic build of OSM (Rel THREE v3.1, based on LXD containers, with SO and UI)"
36 echo -e " --vimemu: additionally fetch, build, and deploy the VIM emulator as a docker container"
37 echo -e " --develop: (deprecated, use '-b master') install OSM from source code using the master branch"
38 # echo -e " --reconfigure: reconfigure the modules (DO NOT change NAT rules)"
39 echo -e " --nat: install only NAT rules"
40 echo -e " --noconfigure: DO NOT install osmclient, DO NOT install NAT rules, DO NOT configure modules"
41 # echo -e " --update: update to the latest stable release or to the latest commit if using a specific branch"
42 echo -e " --showopts: print chosen options and exit (only for debugging)"
43 echo -e " -y: do not prompt for confirmation, assumes yes"
44 echo -e " -D <devops path> use local devops installation path"
45 echo -e " -h / --help: print this help"
48 #Uninstall OSM: remove containers
50 echo -e "\nUninstalling OSM"
51 if [ $RC_CLONE ] ||
[ -n "$TEST_INSTALLER" ]; then
52 $OSM_DEVOPS/jenkins
/host
/clean_container RO
53 $OSM_DEVOPS/jenkins
/host
/clean_container VCA
54 $OSM_DEVOPS/jenkins
/host
/clean_container MON
55 $OSM_DEVOPS/jenkins
/host
/clean_container SO
56 #$OSM_DEVOPS/jenkins/host/clean_container UI
58 lxc stop RO
&& lxc delete RO
59 lxc stop VCA
&& lxc delete VCA
60 lxc stop MON
&& lxc delete MON
61 lxc stop SO-ub
&& lxc delete SO-ub
63 echo -e "\nDeleting imported lxd images if they exist"
64 lxc image show osm-ro
&>/dev
/null
&& lxc image delete osm-ro
65 lxc image show osm-vca
&>/dev
/null
&& lxc image delete osm-vca
66 lxc image show osm-soui
&>/dev
/null
&& lxc image delete osm-soui
70 #Uninstall lightweight OSM: remove dockers
71 function uninstall_lightweight
(){
72 echo -e "\nUninstalling lightweight OSM"
76 while [ ${COUNTER} -lt 30 ]; do
78 result
=$
(docker stack ps osm |
wc -l)
79 #echo "Dockers running: $result"
80 if [ "${result}" == "0" ]; then
85 if [ "${result}" == "0" ]; then
86 echo "All dockers of the stack osm were removed"
88 FATAL
"Some dockers of the stack osm could not be removed. Could not uninstall OSM in single shot. Try to uninstall again"
91 docker image
rm osm
/ro
92 docker image
rm osm
/lcm
93 docker image
rm osm
/light-ui
94 docker image
rm osm
/nbi
95 docker image
rm osm
/mon
96 docker image
rm osm
/pm
100 #Configure NAT rules, based on the current IP addresses of containers
102 echo -e "\nChecking required packages: iptables-persistent"
103 dpkg
-l iptables-persistent
&>/dev
/null ||
! echo -e " Not installed.\nInstalling iptables-persistent requires root privileges" || \
104 sudo DEBIAN_FRONTEND
=noninteractive apt-get
-yq install iptables-persistent
105 echo -e "\nConfiguring NAT rules"
106 echo -e " Required root privileges"
107 sudo
$OSM_DEVOPS/installers
/nat_osm
111 echo "FATAL error: Cannot install OSM due to \"$1\""
115 #Update RO, SO and UI:
117 echo -e "\nUpdating components"
119 echo -e " Updating RO"
122 INSTALL_FOLDER
="/opt/openmano"
123 echo -e " Fetching the repo"
124 lxc
exec $CONTAINER -- git
-C $INSTALL_FOLDER fetch
--all
126 BRANCH
=`lxc exec $CONTAINER -- git -C $INSTALL_FOLDER status -sb | head -n1 | sed -n 's/^## \(.*\).*/\1/p'|awk '{print $1}' |sed 's/\(.*\)\.\.\..*/\1/'`
127 [ -z "$BRANCH" ] && FATAL
"Could not find the current branch in use in the '$MDG'"
128 CURRENT
=`lxc exec $CONTAINER -- git -C $INSTALL_FOLDER status |head -n1`
129 CURRENT_COMMIT_ID
=`lxc exec $CONTAINER -- git -C $INSTALL_FOLDER rev-parse HEAD`
130 echo " FROM: $CURRENT ($CURRENT_COMMIT_ID)"
131 # COMMIT_ID either was previously set with -b option, or is an empty string
132 CHECKOUT_ID
=$COMMIT_ID
133 [ -z "$CHECKOUT_ID" ] && [ "$BRANCH" == "HEAD" ] && CHECKOUT_ID
="tags/$LATEST_STABLE_DEVOPS"
134 [ -z "$CHECKOUT_ID" ] && [ "$BRANCH" != "HEAD" ] && CHECKOUT_ID
="$BRANCH"
135 if [[ $CHECKOUT_ID == "tags/"* ]]; then
136 REMOTE_COMMIT_ID
=`lxc exec $CONTAINER -- git -C $INSTALL_FOLDER rev-list -n 1 $CHECKOUT_ID`
138 REMOTE_COMMIT_ID
=`lxc exec $CONTAINER -- git -C $INSTALL_FOLDER rev-parse origin/$CHECKOUT_ID`
140 echo " TO: $CHECKOUT_ID ($REMOTE_COMMIT_ID)"
141 if [ "$CURRENT_COMMIT_ID" == "$REMOTE_COMMIT_ID" ]; then
142 echo " Nothing to be done."
144 echo " Update required."
145 lxc
exec $CONTAINER -- service osm-ro stop
146 lxc
exec $CONTAINER -- git
-C /opt
/openmano stash
147 lxc
exec $CONTAINER -- git
-C /opt
/openmano pull
--rebase
148 lxc
exec $CONTAINER -- git
-C /opt
/openmano checkout
$CHECKOUT_ID
149 lxc
exec $CONTAINER -- git
-C /opt
/openmano stash pop
150 lxc
exec $CONTAINER -- /opt
/openmano
/database_utils
/migrate_mano_db.sh
151 lxc
exec $CONTAINER -- service osm-ro start
155 echo -e " Updating SO and UI"
158 INSTALL_FOLDER
="" # To be filled in
159 echo -e " Fetching the repo"
160 lxc
exec $CONTAINER -- git
-C $INSTALL_FOLDER fetch
--all
162 BRANCH
=`lxc exec $CONTAINER -- git -C $INSTALL_FOLDER status -sb | head -n1 | sed -n 's/^## \(.*\).*/\1/p'|awk '{print $1}' |sed 's/\(.*\)\.\.\..*/\1/'`
163 [ -z "$BRANCH" ] && FATAL
"Could not find the current branch in use in the '$MDG'"
164 CURRENT
=`lxc exec $CONTAINER -- git -C $INSTALL_FOLDER status |head -n1`
165 CURRENT_COMMIT_ID
=`lxc exec $CONTAINER -- git -C $INSTALL_FOLDER rev-parse HEAD`
166 echo " FROM: $CURRENT ($CURRENT_COMMIT_ID)"
167 # COMMIT_ID either was previously set with -b option, or is an empty string
168 CHECKOUT_ID
=$COMMIT_ID
169 [ -z "$CHECKOUT_ID" ] && [ "$BRANCH" == "HEAD" ] && CHECKOUT_ID
="tags/$LATEST_STABLE_DEVOPS"
170 [ -z "$CHECKOUT_ID" ] && [ "$BRANCH" != "HEAD" ] && CHECKOUT_ID
="$BRANCH"
171 if [[ $CHECKOUT_ID == "tags/"* ]]; then
172 REMOTE_COMMIT_ID
=`lxc exec $CONTAINER -- git -C $INSTALL_FOLDER rev-list -n 1 $CHECKOUT_ID`
174 REMOTE_COMMIT_ID
=`lxc exec $CONTAINER -- git -C $INSTALL_FOLDER rev-parse origin/$CHECKOUT_ID`
176 echo " TO: $CHECKOUT_ID ($REMOTE_COMMIT_ID)"
177 if [ "$CURRENT_COMMIT_ID" == "$REMOTE_COMMIT_ID" ]; then
178 echo " Nothing to be done."
180 echo " Update required."
181 # Instructions to be added
182 # lxc exec SO-ub -- ...
185 echo -e "Updating MON Container"
188 INSTALL_FOLDER
="/root/MON"
189 echo -e " Fetching the repo"
190 lxc
exec $CONTAINER -- git
-C $INSTALL_FOLDER fetch
--all
192 BRANCH
=`lxc exec $CONTAINER -- git -C $INSTALL_FOLDER status -sb | head -n1 | sed -n 's/^## \(.*\).*/\1/p'|awk '{print $1}' |sed 's/\(.*\)\.\.\..*/\1/'`
193 [ -z "$BRANCH" ] && FATAL
"Could not find the current branch in use in the '$MDG'"
194 CURRENT
=`lxc exec $CONTAINER -- git -C $INSTALL_FOLDER status |head -n1`
195 CURRENT_COMMIT_ID
=`lxc exec $CONTAINER -- git -C $INSTALL_FOLDER rev-parse HEAD`
196 echo " FROM: $CURRENT ($CURRENT_COMMIT_ID)"
197 # COMMIT_ID either was previously set with -b option, or is an empty string
198 CHECKOUT_ID
=$COMMIT_ID
199 [ -z "$CHECKOUT_ID" ] && [ "$BRANCH" == "HEAD" ] && CHECKOUT_ID
="tags/$LATEST_STABLE_DEVOPS"
200 [ -z "$CHECKOUT_ID" ] && [ "$BRANCH" != "HEAD" ] && CHECKOUT_ID
="$BRANCH"
201 if [[ $CHECKOUT_ID == "tags/"* ]]; then
202 REMOTE_COMMIT_ID
=`lxc exec $CONTAINER -- git -C $INSTALL_FOLDER rev-list -n 1 $CHECKOUT_ID`
204 REMOTE_COMMIT_ID
=`lxc exec $CONTAINER -- git -C $INSTALL_FOLDER rev-parse origin/$CHECKOUT_ID`
206 echo " TO: $CHECKOUT_ID ($REMOTE_COMMIT_ID)"
207 if [ "$CURRENT_COMMIT_ID" == "$REMOTE_COMMIT_ID" ]; then
208 echo " Nothing to be done."
210 echo " Update required."
215 function so_is_up
() {
219 SO_IP
=`lxc list SO-ub -c 4|grep eth0 |awk '{print $2}'`
224 while [ $time -le $timelength ]
226 if [[ `curl -k -X GET https://$SO_IP:8008/api/operational/vcs/info \
227 -H 'accept: application/vnd.yang.data+json' \
228 -H 'authorization: Basic YWRtaW46YWRtaW4=' \
229 -H 'cache-control: no-cache' 2> /dev/null | jq '.[].components.component_info[] | select(.component_name=="RW.Restconf")' 2>/dev/null | grep "RUNNING" | wc -l` -eq 1 ]]
231 echo "RW.Restconf running....SO is up"
240 FATAL
"OSM Failed to startup. SO failed to startup"
243 function vca_is_up
() {
244 if [[ `lxc exec VCA -- juju status | grep "osm" | wc -l` -eq 1 ]]; then
245 echo "VCA is up and running"
249 FATAL
"OSM Failed to startup. VCA failed to startup"
252 function mon_is_up
() {
253 if [[ `curl http://$RO_IP:9090/openmano/ | grep "works" | wc -l` -eq 1 ]]; then
254 echo "MON is up and running"
258 FATAL
"OSM Failed to startup. MON failed to startup"
261 function ro_is_up
() {
265 RO_IP
=`lxc list RO -c 4|grep eth0 |awk '{print $2}'`
270 while [ $time -le $timelength ]; do
271 if [[ `curl http://$RO_IP:9090/openmano/ | grep "works" | wc -l` -eq 1 ]]; then
272 echo "RO is up and running"
280 FATAL
"OSM Failed to startup. RO failed to startup"
284 function configure_RO
(){
285 .
$OSM_DEVOPS/installers
/export_ips
286 echo -e " Configuring RO"
287 lxc
exec RO
-- sed -i -e "s/^\#\?log_socket_host:.*/log_socket_host: $SO_CONTAINER_IP/g" /etc
/osm
/openmanod.cfg
288 lxc
exec RO
-- service osm-ro restart
292 lxc
exec RO
-- openmano tenant-delete
-f osm
>/dev
/null
293 lxc
exec RO
-- openmano tenant-create osm
> /dev
/null
294 lxc
exec RO
-- sed -i '/export OPENMANO_TENANT=osm/d' .bashrc
295 lxc
exec RO
-- sed -i '$ i export OPENMANO_TENANT=osm' .bashrc
296 lxc
exec RO
-- sh
-c 'echo "export OPENMANO_TENANT=osm" >> .bashrc'
299 function configure_VCA
(){
300 echo -e " Configuring VCA"
301 JUJU_PASSWD
=`date +%s | sha256sum | base64 | head -c 32`
302 echo -e "$JUJU_PASSWD\n$JUJU_PASSWD" | lxc
exec VCA
-- juju change-user-password
305 function configure_SOUI
(){
306 .
$OSM_DEVOPS/installers
/export_ips
307 JUJU_CONTROLLER_IP
=`lxc exec VCA -- lxc list -c 4 |grep eth0 |awk '{print $2}'`
308 RO_TENANT_ID
=`lxc exec RO -- openmano tenant-list osm |awk '{print $1}'`
310 echo -e " Configuring MON"
311 #Information to be added about SO socket for logging
313 echo -e " Configuring SO"
314 sudo route add
-host $JUJU_CONTROLLER_IP gw
$VCA_CONTAINER_IP
315 sudo ip route add
10.44.127.0/24 via
$VCA_CONTAINER_IP
316 sudo
sed -i "$ i route add -host $JUJU_CONTROLLER_IP gw $VCA_CONTAINER_IP" /etc
/rc.
local
317 sudo
sed -i "$ i ip route add 10.44.127.0/24 via $VCA_CONTAINER_IP" /etc
/rc.
local
318 # make journaling persistent
319 lxc
exec SO-ub
-- mkdir
-p /var
/log
/journal
320 lxc
exec SO-ub
-- systemd-tmpfiles
--create --prefix /var
/log
/journal
321 lxc
exec SO-ub
-- systemctl restart systemd-journald
323 echo RIFT_EXTERNAL_ADDRESS
=$DEFAULT_IP | lxc
exec SO-ub
-- tee -a /usr
/rift
/etc
/default
/launchpad
325 lxc
exec SO-ub
-- systemctl restart launchpad
327 so_is_up
$SO_CONTAINER_IP
329 #delete existing config agent (could be there on reconfigure)
330 curl
-k --request DELETE \
331 --url https
://$SO_CONTAINER_IP:8008/api
/config
/config-agent
/account
/osmjuju \
332 --header 'accept: application/vnd.yang.data+json' \
333 --header 'authorization: Basic YWRtaW46YWRtaW4=' \
334 --header 'cache-control: no-cache' \
335 --header 'content-type: application/vnd.yang.data+json' &> /dev
/null
337 result
=$
(curl
-k --request POST \
338 --url https
://$SO_CONTAINER_IP:8008/api
/config
/config-agent \
339 --header 'accept: application/vnd.yang.data+json' \
340 --header 'authorization: Basic YWRtaW46YWRtaW4=' \
341 --header 'cache-control: no-cache' \
342 --header 'content-type: application/vnd.yang.data+json' \
343 --data '{"account": [ { "name": "osmjuju", "account-type": "juju", "juju": { "ip-address": "'$JUJU_CONTROLLER_IP'", "port": "17070", "user": "admin", "secret": "'$JUJU_PASSWD'" } } ]}')
344 [[ $result =~ .
*success.
* ]] || FATAL
"Failed config-agent configuration: $result"
347 #result=$(curl -k --request PUT \
348 # --url https://$SO_CONTAINER_IP:8008/api/config/resource-orchestrator \
349 # --header 'accept: application/vnd.yang.data+json' \
350 # --header 'authorization: Basic YWRtaW46YWRtaW4=' \
351 # --header 'cache-control: no-cache' \
352 # --header 'content-type: application/vnd.yang.data+json' \
353 # --data '{ "openmano": { "host": "'$RO_CONTAINER_IP'", "port": "9090", "tenant-id": "'$RO_TENANT_ID'" }, "name": "osmopenmano", "account-type": "openmano" }')
355 result
=$
(curl
-k --request PUT \
356 --url https
://$SO_CONTAINER_IP:8008/api
/config
/project
/default
/ro-account
/account \
357 --header 'accept: application/vnd.yang.data+json' \
358 --header 'authorization: Basic YWRtaW46YWRtaW4=' \
359 --header 'cache-control: no-cache' \
360 --header 'content-type: application/vnd.yang.data+json' \
361 --data '{"rw-ro-account:account": [ { "openmano": { "host": "'$RO_CONTAINER_IP'", "port": "9090", "tenant-id": "'$RO_TENANT_ID'"}, "name": "osmopenmano", "ro-account-type": "openmano" }]}')
362 [[ $result =~ .
*success.
* ]] || FATAL
"Failed resource-orchestrator configuration: $result"
364 result
=$
(curl
-k --request PATCH \
365 --url https
://$SO_CONTAINER_IP:8008/v
2/api
/config
/openidc-provider-config
/rw-ui-client
/redirect-uri \
366 --header 'accept: application/vnd.yang.data+json' \
367 --header 'authorization: Basic YWRtaW46YWRtaW4=' \
368 --header 'cache-control: no-cache' \
369 --header 'content-type: application/vnd.yang.data+json' \
370 --data '{"redirect-uri": "https://'$DEFAULT_IP':8443/callback" }')
371 [[ $result =~ .
*success.
* ]] || FATAL
"Failed redirect-uri configuration: $result"
373 result
=$
(curl
-k --request PATCH \
374 --url https
://$SO_CONTAINER_IP:8008/v
2/api
/config
/openidc-provider-config
/rw-ui-client
/post-logout-redirect-uri \
375 --header 'accept: application/vnd.yang.data+json' \
376 --header 'authorization: Basic YWRtaW46YWRtaW4=' \
377 --header 'cache-control: no-cache' \
378 --header 'content-type: application/vnd.yang.data+json' \
379 --data '{"post-logout-redirect-uri": "https://'$DEFAULT_IP':8443/?api_server=https://'$DEFAULT_IP'" }')
380 [[ $result =~ .
*success.
* ]] || FATAL
"Failed post-logout-redirect-uri configuration: $result"
382 lxc
exec SO-ub
-- tee /etc
/network
/interfaces.d
/60-rift.cfg
<<EOF
384 iface lo:1 inet static
386 netmask 255.255.255.255
388 lxc
exec SO-ub ifup lo
:1
391 #Configure RO, VCA, and SO with the initial configuration:
392 # RO -> tenant:osm, logs to be sent to SO
393 # VCA -> juju-password
394 # SO -> route to Juju Controller, add RO account, add VCA account
395 function configure
(){
396 #Configure components
397 echo -e "\nConfiguring components"
403 function install_lxd
() {
405 sudo apt-get
install -y lxd
409 lxc network create lxdbr0 ipv4.address
=auto ipv4.nat
=true ipv6.address
=none ipv6.nat
=false
410 DEFAULT_INTERFACE
=$
(route
-n |
awk '$1~/^0.0.0.0/ {print $8}')
411 DEFAULT_MTU
=$
(ip addr show
$DEFAULT_INTERFACE | perl
-ne 'if (/mtu\s(\d+)/) {print $1;}')
412 lxc profile device
set default eth0 mtu
$DEFAULT_MTU
413 #sudo systemctl stop lxd-bridge
414 #sudo systemctl --system daemon-reload
415 #sudo systemctl enable lxd-bridge
416 #sudo systemctl start lxd-bridge
420 # ask to the user and parse a response among 'y', 'yes', 'n' or 'no'. Case insensitive
421 # Params: $1 text to ask; $2 Action by default, can be 'y' for yes, 'n' for no, other or empty for not allowed
422 # Return: true(0) if user type 'yes'; false (1) if user type 'no'
423 read -e -p "$1" USER_CONFIRMATION
425 [ -z "$USER_CONFIRMATION" ] && [ "$2" == 'y' ] && return 0
426 [ -z "$USER_CONFIRMATION" ] && [ "$2" == 'n' ] && return 1
427 [ "${USER_CONFIRMATION,,}" == "yes" ] ||
[ "${USER_CONFIRMATION,,}" == "y" ] && return 0
428 [ "${USER_CONFIRMATION,,}" == "no" ] ||
[ "${USER_CONFIRMATION,,}" == "n" ] && return 1
429 read -e -p "Please type 'yes' or 'no': " USER_CONFIRMATION
433 function launch_container_from_lxd
(){
436 export OSM_BASE_IMAGE
=$2
437 if ! container_exists
$OSM_BUILD_CONTAINER; then
439 [[ "$OSM_BUILD_CONTAINER_PRIVILEGED" == yes ]] && CONTAINER_OPTS
="$CONTAINER_OPTS -c security.privileged=true"
440 [[ "$OSM_BUILD_CONTAINER_ALLOW_NESTED" == yes ]] && CONTAINER_OPTS
="$CONTAINER_OPTS -c security.nesting=true"
441 create_container
$OSM_BASE_IMAGE $OSM_BUILD_CONTAINER $CONTAINER_OPTS
442 wait_container_up
$OSM_BUILD_CONTAINER
446 function install_osmclient
(){
447 CLIENT_RELEASE
=${RELEASE#"-R "}
448 CLIENT_REPOSITORY_KEY
="OSM%20ETSI%20Release%20Key.gpg"
449 CLIENT_REPOSITORY
=${REPOSITORY#"-r "}
450 [ -z "$REPOSITORY_BASE" ] && REPOSITORY_BASE
="-u https://osm-download.etsi.org/repository/osm/debian"
451 CLIENT_REPOSITORY_BASE
=${REPOSITORY_BASE#"-u "}
452 key_location
=$CLIENT_REPOSITORY_BASE/$CLIENT_RELEASE/$CLIENT_REPOSITORY_KEY
453 curl
$key_location | sudo apt-key add
-
454 sudo add-apt-repository
-y "deb [arch=amd64] $CLIENT_REPOSITORY_BASE/$CLIENT_RELEASE $CLIENT_REPOSITORY osmclient"
456 sudo apt-get
install -y python-pip
457 sudo
-H pip
install pip
==9.0.3
458 sudo
-H pip
install python-magic
459 sudo apt-get
install -y python-osmclient
460 #sed 's,OSM_SOL005=[^$]*,OSM_SOL005=True,' -i ${HOME}/.bashrc
461 #echo 'export OSM_HOSTNAME=localhost' >> ${HOME}/.bashrc
462 #echo 'export OSM_SOL005=True' >> ${HOME}/.bashrc
463 [ -z "$INSTALL_LIGHTWEIGHT" ] && export OSM_HOSTNAME
=`lxc list | awk '($2=="SO-ub"){print $6}'`
464 [ -z "$INSTALL_LIGHTWEIGHT" ] && export OSM_RO_HOSTNAME
=`lxc list | awk '($2=="RO"){print $6}'`
465 [ -n "$INSTALL_LIGHTWEIGHT" ] && export OSM_HOSTNAME
=localhost
466 echo -e "\nOSM client installed"
467 echo -e "You might be interested in adding the following OSM client env variables to your .bashrc file:"
468 echo " export OSM_HOSTNAME=${OSM_HOSTNAME}"
469 [ -n "$INSTALL_LIGHTWEIGHT" ] && echo " export OSM_SOL005=True"
470 [ -z "$INSTALL_LIGHTWEIGHT" ] && echo " export OSM_RO_HOSTNAME=${OSM_RO_HOSTNAME}"
474 function install_from_lxdimages
(){
475 LXD_RELEASE
=${RELEASE#"-R "}
476 if [ -n "$LXD_REPOSITORY_PATH" ]; then
477 LXD_IMAGE_DIR
="$LXD_REPOSITORY_PATH"
479 LXD_IMAGE_DIR
="$(mktemp -d -q --tmpdir "osmimages.XXXXXX
")"
480 trap 'rm -rf "$LXD_IMAGE_DIR"' EXIT
482 echo -e "\nDeleting previous lxd images if they exist"
483 lxc image show osm-ro
&>/dev
/null
&& lxc image delete osm-ro
484 lxc image show osm-vca
&>/dev
/null
&& lxc image delete osm-vca
485 lxc image show osm-soui
&>/dev
/null
&& lxc image delete osm-soui
486 echo -e "\nImporting osm-ro"
487 [ -z "$LXD_REPOSITORY_PATH" ] && wget
-O $LXD_IMAGE_DIR/osm-ro.
tar.gz
$LXD_REPOSITORY_BASE/$LXD_RELEASE/osm-ro.
tar.gz
488 lxc image import
$LXD_IMAGE_DIR/osm-ro.
tar.gz
--alias osm-ro
489 rm -f $LXD_IMAGE_DIR/osm-ro.
tar.gz
490 echo -e "\nImporting osm-vca"
491 [ -z "$LXD_REPOSITORY_PATH" ] && wget
-O $LXD_IMAGE_DIR/osm-vca.
tar.gz
$LXD_REPOSITORY_BASE/$LXD_RELEASE/osm-vca.
tar.gz
492 lxc image import
$LXD_IMAGE_DIR/osm-vca.
tar.gz
--alias osm-vca
493 rm -f $LXD_IMAGE_DIR/osm-vca.
tar.gz
494 echo -e "\nImporting osm-soui"
495 [ -z "$LXD_REPOSITORY_PATH" ] && wget
-O $LXD_IMAGE_DIR/osm-soui.
tar.gz
$LXD_REPOSITORY_BASE/$LXD_RELEASE/osm-soui.
tar.gz
496 lxc image import
$LXD_IMAGE_DIR/osm-soui.
tar.gz
--alias osm-soui
497 rm -f $LXD_IMAGE_DIR/osm-soui.
tar.gz
498 launch_container_from_lxd RO osm-ro
500 launch_container_from_lxd VCA osm-vca
501 vca_is_up
&& track VCA
502 launch_container_from_lxd MON osm-mon
503 mon_is_up
&& track MON
504 launch_container_from_lxd SO osm-soui
505 #so_is_up && track SOUI
509 function install_docker_ce
() {
510 # installs and configures Docker CE
511 echo "Installing Docker CE ..."
512 sudo apt-get
-qq update
513 sudo apt-get
install -y apt-transport-https ca-certificates software-properties-common
514 curl
-fsSL https
://download.docker.com
/linux
/ubuntu
/gpg | sudo apt-key add
-
515 sudo add-apt-repository
"deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
516 sudo apt-get
-qq update
517 sudo apt-get
install -y docker-ce
518 echo "Adding user to group 'docker'"
519 sudo groupadd
-f docker
520 sudo usermod
-aG docker
$USER
521 echo "... Docker CE installation done"
523 sudo service docker restart
524 echo "... restarted Docker service"
527 function install_docker_compose
() {
528 # installs and configures docker-compose
529 echo "Installing Docker Compose ..."
530 sudo curl
-L https
://github.com
/docker
/compose
/releases
/download
/1.18.0/docker-compose-
`uname -s`-`uname -m` -o /usr
/local
/bin
/docker-compose
531 sudo
chmod +x
/usr
/local
/bin
/docker-compose
532 echo "... Docker Compose installation done"
535 function install_juju
() {
536 echo "Installing juju"
537 sudo snap
install juju
--classic
538 sudo dpkg-reconfigure
-p medium lxd
539 sg lxd
-c "juju bootstrap localhost osm"
540 echo "Finished installation of juju"
543 function generate_docker_images
() {
544 echo "Pulling and generating docker images"
545 newgrp docker
<< EONG
546 docker pull wurstmeister/kafka
547 docker pull wurstmeister/zookeeper
550 git -C ${LWTEMPDIR} clone https://osm.etsi.org/gerrit/osm/MON
551 docker build ${LWTEMPDIR}/MON -f ${LWTEMPDIR}/MON/docker/Dockerfile -t osm/mon || ! echo "cannot build MON docker image" >&2
552 docker build ${LWTEMPDIR}/MON/policy_module -f ${LWTEMPDIR}/MON/policy_module/Dockerfile -t osm/pm || ! echo "cannot build PM docker image" >&2
553 git -C ${LWTEMPDIR} clone https://osm.etsi.org/gerrit/osm/NBI
554 docker build ${LWTEMPDIR}/NBI -f ${LWTEMPDIR}/NBI/Dockerfile.local -t osm/nbi || ! echo "cannot build NBI docker image" >&2
555 git -C ${LWTEMPDIR} clone https://osm.etsi.org/gerrit/osm/RO
556 docker build ${LWTEMPDIR}/RO -f ${LWTEMPDIR}/RO/docker/Dockerfile-local -t osm/ro || ! echo "cannot build RO docker image" >&2
557 docker build ${LWTEMPDIR}/RO/lcm -t osm/lcm || ! echo "cannot build LCM docker image" >&2
558 # git -C ${LWTEMPDIR} clone https://github.com/superfluidity/osm-light-ui.git
559 # docker build ${LWTEMPDIR}/osm-light-ui -t osm/light-ui -f ${LWTEMPDIR}/osm-light-ui/code/docker/Dockerfile
560 git -C ${LWTEMPDIR} clone https://osm.etsi.org/gerrit/osm/LW-UI
561 docker build ${LWTEMPDIR}/LW-UI -t osm/light-ui -f ${LWTEMPDIR}/LW-UI/Dockerfile
563 echo "Finished generation of docker images"
566 function generate_docker_env_files
() {
567 echo "Generating docker env files"
568 OSMLCM_VCA_HOST
=`juju show-controller|grep api-endpoints|awk -F\' '{print $2}'|awk -F\: '{print $1}'`
569 OSMLCM_VCA_SECRET
=`grep password ${HOME}/.local/share/juju/accounts.yaml |awk '{print $2}'`
570 MYSQL_ROOT_PASSWORD
=`date +%s | sha256sum | base64 | head -c 32`
571 echo "OSMLCM_VCA_HOST=${OSMLCM_VCA_HOST}" |sudo
tee ${OSM_DEVOPS}/installers
/docker
/lcm.env
572 echo "OSMLCM_VCA_SECRET=${OSMLCM_VCA_SECRET}" |sudo
tee -a ${OSM_DEVOPS}/installers
/docker
/lcm.env
573 echo "MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}" |sudo
tee ${OSM_DEVOPS}/installers
/docker
/ro-db.env
574 echo "RO_DB_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}" |sudo
tee ${OSM_DEVOPS}/installers
/docker
/ro.env
575 echo "OS_NOTIFIER_URI=http://${DEFAULT_IP}:8662" |sudo
tee ${OSM_DEVOPS}/installers
/docker
/mon.env
576 echo "Finished generation of docker env files"
579 function deploy_lightweight
() {
580 echo "Deploying lightweight build"
581 if [ "${DEFAULT_MTU}" != "1500" ]; then
582 DOCKER_NETS
=`sg docker -c "docker network list" | awk '{print $2}' | egrep -v "^ID$" | paste -d " " -s`
583 DOCKER_GW_NET
=`sg docker -c "docker network inspect ${DOCKER_NETS}" | grep Subnet | awk -F\" '{print $4}' | egrep "^172" | sort -u | tail -1 | awk -F\. '{if ($2 != 255) print $1"."$2+1"."$3"."$4; else print "-1";}'`
584 sg docker
-c "docker network create --subnet ${DOCKER_GW_NET} --opt com.docker.network.bridge.name=docker_gwbridge --opt com.docker.network.bridge.enable_icc=false --opt com.docker.network.bridge.enable_ip_masquerade=true --opt com.docker.network.driver.mtu=${DEFAULT_MTU} docker_gwbridge"
586 newgrp docker
<< EONG
587 docker swarm init --advertise-addr ${DEFAULT_IP}
588 docker network create --driver=overlay --attachable --opt com.docker.network.driver.mtu=${DEFAULT_MTU} netOSM
589 docker stack deploy -c ${OSM_DEVOPS}/installers/docker/docker-compose.yaml osm
590 #docker-compose -f /usr/share/osm-devops/installers/docker/docker-compose.yaml up -d
592 echo "Finished deployment of lightweight build"
595 function install_lightweight
() {
596 echo "Installing lightweight build of OSM"
597 LWTEMPDIR
="$(mktemp -d -q --tmpdir "installosmlight.XXXXXX
")"
598 trap 'rm -rf "${LWTEMPDIR}"' EXIT
599 DEFAULT_IF
=`route -n |awk '$1~/^0.0.0.0/ {print $8}'`
600 DEFAULT_IP
=`ip -o -4 a |grep ${DEFAULT_IF}|awk '{split($4,a,"/"); print a[1]}'`
601 DEFAULT_MTU
=$
(ip addr show
${DEFAULT_IF} | perl
-ne 'if (/mtu\s(\d+)/) {print $1;}')
602 need_packages_lw
="lxd"
603 echo -e "Checking required packages: $need_packages_lw"
604 dpkg
-l $need_packages_lw &>/dev
/null \
605 ||
! echo -e "One or several required packages are not installed. Updating apt cache requires root privileges." \
606 || sudo apt-get update \
607 || FATAL
"failed to run apt-get update"
608 dpkg
-l $need_packages_lw &>/dev
/null \
609 ||
! echo -e "Installing $need_packages_lw requires root privileges." \
610 || sudo apt-get
install -y $need_packages_lw \
611 || FATAL
"failed to install $need_packages_lw"
614 #install_docker_compose
615 generate_docker_images
616 generate_docker_env_files
618 [ -n "$INSTALL_VIMEMU" ] && install_vimemu
623 function install_vimemu
() {
624 echo "\nInstalling vim-emu"
625 EMUTEMPDIR
="$(mktemp -d -q --tmpdir "installosmvimemu.XXXXXX
")"
626 trap 'rm -rf "${EMUTEMPDIR}"' EXIT
627 # clone vim-emu repository (attention: branch is currently master only)
628 echo "Cloning vim-emu repository ..."
629 git clone https
://osm.etsi.org
/gerrit
/osm
/vim-emu.git
$EMUTEMPDIR
630 # build vim-emu docker
631 echo "Building vim-emu Docker container..."
632 sudo docker build
-t vim-emu-img
-f $EMUTEMPDIR/Dockerfile
$EMUTEMPDIR/
633 # start vim-emu container as daemon
634 echo "Starting vim-emu Docker container 'vim-emu' ..."
635 if [ -n "$INSTALL_LIGHTWEIGHT" ]; then
636 # in lightweight mode, the emulator needs to be attached to netOSM
637 sudo docker run
--name vim-emu
-t -d --rm --privileged --pid='host' --network=netOSM
-v /var
/run
/docker.sock
:/var
/run
/docker.sock vim-emu-img python examples
/osm_default_daemon_topology_2_pop.py
640 sudo docker run
--name vim-emu
-t -d --rm --privileged --pid='host' -v /var
/run
/docker.sock
:/var
/run
/docker.sock vim-emu-img python examples
/osm_default_daemon_topology_2_pop.py
642 echo "Waiting for 'vim-emu' container to start ..."
644 export VIMEMU_HOSTNAME
=$
(sudo docker inspect
-f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' vim-emu
)
645 echo "vim-emu running at ${VIMEMU_HOSTNAME} ..."
646 # print vim-emu connection info
647 echo -e "\nYou might be interested in adding the following vim-emu env variables to your .bashrc file:"
648 echo " export VIMEMU_HOSTNAME=${VIMEMU_HOSTNAME}"
649 echo -e "To add the emulated VIM to OSM you should do:"
650 echo " osm vim-create --name emu-vim1 --user username --password password --auth_url http://${VIMEMU_HOSTNAME}:6001/v2.0 --tenant tenantName --account_type openstack"
653 function dump_vars
(){
654 echo "DEVELOP=$DEVELOP"
655 echo "INSTALL_FROM_SOURCE=$INSTALL_FROM_SOURCE"
656 echo "UNINSTALL=$UNINSTALL"
658 echo "UPDATE=$UPDATE"
659 echo "RECONFIGURE=$RECONFIGURE"
660 echo "TEST_INSTALLER=$TEST_INSTALLER"
661 echo "INSTALL_VIMEMU=$INSTALL_VIMEMU"
662 echo "INSTALL_LXD=$INSTALL_LXD"
663 echo "INSTALL_FROM_LXDIMAGES=$INSTALL_FROM_LXDIMAGES"
664 echo "LXD_REPOSITORY_BASE=$LXD_REPOSITORY_BASE"
665 echo "LXD_REPOSITORY_PATH=$LXD_REPOSITORY_PATH"
666 echo "INSTALL_LIGHTWEIGHT=$INSTALL_LIGHTWEIGHT"
667 echo "RELEASE=$RELEASE"
668 echo "REPOSITORY=$REPOSITORY"
669 echo "REPOSITORY_BASE=$REPOSITORY_BASE"
670 echo "REPOSITORY_KEY=$REPOSITORY_KEY"
671 echo "NOCONFIGURE=$NOCONFIGURE"
672 echo "SHOWOPTS=$SHOWOPTS"
673 echo "Install from specific refspec (-b): $COMMIT_ID"
678 duration
=$
((ctime
- SESSION_ID
))
679 url
="http://www.woopra.com/track/ce?project=osm.etsi.org&cookie=${SESSION_ID}"
680 #url="${url}&ce_campaign_name=${CAMPAIGN_NAME}"
682 [ -n "$INSTALL_FROM_SOURCE" ] && event_name
="src"
683 [ -n "$INSTALL_FROM_LXDIMAGES" ] && event_name
="lxd"
684 event_name
="${event_name}_$1"
685 url
="${url}&event=${event_name}&ce_duration=${duration}"
686 wget
-q -O /dev
/null
$url
699 INSTALL_FROM_SOURCE
=""
700 RELEASE
="-R ReleaseTHREE"
701 REPOSITORY
="-r stable"
703 INSTALL_FROM_LXDIMAGES
=""
704 LXD_REPOSITORY_BASE
="https://osm-download.etsi.org/repository/osm/lxd"
705 LXD_REPOSITORY_PATH
=""
706 INSTALL_LIGHTWEIGHT
="y"
709 SESSION_ID
=`date +%s`
712 while getopts ":hy-:b:r:k:u:R:l:p:D:" o
; do
721 REPOSITORY
="-r ${OPTARG}"
724 RELEASE
="-R ${OPTARG}"
727 REPOSITORY_KEY
="-k ${OPTARG}"
730 REPOSITORY_BASE
="-u ${OPTARG}"
733 LXD_REPOSITORY_BASE
="${OPTARG}"
736 LXD_REPOSITORY_PATH
="${OPTARG}"
739 OSM_DEVOPS
="${OPTARG}"
742 [ "${OPTARG}" == "help" ] && usage
&& exit 0
743 [ "${OPTARG}" == "source" ] && INSTALL_FROM_SOURCE
="y" && continue
744 [ "${OPTARG}" == "develop" ] && DEVELOP
="y" && continue
745 [ "${OPTARG}" == "uninstall" ] && UNINSTALL
="y" && continue
746 [ "${OPTARG}" == "nat" ] && NAT
="y" && continue
747 [ "${OPTARG}" == "update" ] && UPDATE
="y" && continue
748 [ "${OPTARG}" == "reconfigure" ] && RECONFIGURE
="y" && continue
749 [ "${OPTARG}" == "test" ] && TEST_INSTALLER
="y" && continue
750 [ "${OPTARG}" == "lxdinstall" ] && INSTALL_LXD
="y" && continue
751 [ "${OPTARG}" == "lxdimages" ] && INSTALL_FROM_LXDIMAGES
="y" && continue
752 [ "${OPTARG}" == "lightweight" ] && INSTALL_LIGHTWEIGHT
="y" && continue
753 [ "${OPTARG}" == "soui" ] && INSTALL_LIGHTWEIGHT
="" && RELEASE
="-R ReleaseTHREE" && REPOSITORY
="-r stable" && continue
754 [ "${OPTARG}" == "vimemu" ] && INSTALL_VIMEMU
="y" && continue
755 [ "${OPTARG}" == "noconfigure" ] && NOCONFIGURE
="y" && continue
756 [ "${OPTARG}" == "showopts" ] && SHOWOPTS
="y" && continue
757 [ "${OPTARG}" == "daily" ] && RELEASE_DAILY
="y" && continue
758 echo -e "Invalid option: '--$OPTARG'\n" >&2
762 echo -e "Invalid option: '-$OPTARG'\n" >&2
774 if [ -n "$SHOWOPTS" ]; then
779 [ -n "$RELEASE_DAILY" ] && echo -e "\nInstalling from daily build repo" && RELEASE
="-R ReleaseTHREE-daily" && REPOSITORY
="-r testing" && COMMIT_ID
="master"
781 # if develop, we force master
782 [ -z "$COMMIT_ID" ] && [ -n "$DEVELOP" ] && COMMIT_ID
="master"
784 # forcing source from master removed. Now only install from source when explicit
785 # [ -n "$COMMIT_ID" ] && [ "$COMMIT_ID" == "master" ] && INSTALL_FROM_SOURCE="y"
787 if [ -z "$OSM_DEVOPS" ]; then
788 if [ -n "$TEST_INSTALLER" ]; then
789 echo -e "\nUsing local devops repo for OSM installation"
790 TEMPDIR
="$(dirname $(realpath $(dirname $0)))"
792 echo -e "\nCreating temporary dir for OSM installation"
793 TEMPDIR
="$(mktemp -d -q --tmpdir "installosm.XXXXXX
")"
794 trap 'rm -rf "$TEMPDIR"' EXIT
798 need_packages
="git jq wget curl tar"
799 echo -e "Checking required packages: $need_packages"
800 dpkg
-l $need_packages &>/dev
/null \
801 ||
! echo -e "One or several required packages are not installed. Updating apt cache requires root privileges." \
802 || sudo apt-get update \
803 || FATAL
"failed to run apt-get update"
804 dpkg
-l $need_packages &>/dev
/null \
805 ||
! echo -e "Installing $need_packages requires root privileges." \
806 || sudo apt-get
install -y $need_packages \
807 || FATAL
"failed to install $need_packages"
809 if [ -z "$OSM_DEVOPS" ]; then
810 if [ -z "$TEST_INSTALLER" ]; then
811 echo -e "\nCloning devops repo temporarily"
812 git clone https
://osm.etsi.org
/gerrit
/osm
/devops.git
$TEMPDIR
816 echo -e "\nGuessing the current stable release"
817 LATEST_STABLE_DEVOPS
=`git -C $TEMPDIR tag -l v[0-9].* | sort -V | tail -n1`
818 [ -z "$COMMIT_ID" ] && [ -z "$LATEST_STABLE_DEVOPS" ] && echo "Could not find the current latest stable release" && exit 0
819 echo "Latest tag in devops repo: $LATEST_STABLE_DEVOPS"
820 [ -z "$COMMIT_ID" ] && [ -n "$LATEST_STABLE_DEVOPS" ] && COMMIT_ID
="tags/$LATEST_STABLE_DEVOPS"
822 if [ -n "$RELEASE_DAILY" ]; then
823 echo "Using master/HEAD devops"
824 git
-C $TEMPDIR checkout master
825 elif [ -z "$TEST_INSTALLER" ]; then
826 git
-C $TEMPDIR checkout tags
/$LATEST_STABLE_DEVOPS
831 OSM_JENKINS
="$OSM_DEVOPS/jenkins"
832 .
$OSM_JENKINS/common
/all_funcs
834 [ -n "$INSTALL_LIGHTWEIGHT" ] && [ -n "$UNINSTALL" ] && uninstall_lightweight
&& echo -e "\nDONE" && exit 0
835 [ -n "$UNINSTALL" ] && uninstall
&& echo -e "\nDONE" && exit 0
836 [ -n "$NAT" ] && nat
&& echo -e "\nDONE" && exit 0
837 [ -n "$UPDATE" ] && update
&& echo -e "\nDONE" && exit 0
838 [ -n "$RECONFIGURE" ] && configure
&& echo -e "\nDONE" && exit 0
840 #Installation starts here
841 [ -n "$INSTALL_LIGHTWEIGHT" ] && install_lightweight
&& echo -e "\nDONE" && exit 0
842 echo -e "\nInstalling OSM from refspec: $COMMIT_ID"
843 if [ -n "$INSTALL_FROM_SOURCE" ] && [ -z "$ASSUME_YES" ]; then
844 ! ask_user
"The installation will take about 75-90 minutes. Continue (Y/n)? " y
&& echo "Cancelled!" && exit 1
847 echo -e "Checking required packages: lxd"
848 lxd
--version &>/dev
/null || FATAL
"lxd not present, exiting."
849 [ -n "$INSTALL_LXD" ] && echo -e "\nInstalling and configuring lxd" && install_lxd
851 wget
-q -O- https
://osm-download.etsi.org
/ftp
/osm-4.0
-four/README.txt
&> /dev
/null
854 # use local devops for containers
855 export OSM_USE_LOCAL_DEVOPS
=true
856 if [ -n "$INSTALL_FROM_SOURCE" ]; then #install from source
857 echo -e "\nCreating the containers and building from source ..."
858 $OSM_DEVOPS/jenkins
/host
/start_build RO
--notest checkout
$COMMIT_ID || FATAL
"RO container build failed (refspec: '$COMMIT_ID')"
860 $OSM_DEVOPS/jenkins
/host
/start_build VCA || FATAL
"VCA container build failed"
861 vca_is_up
&& track VCA
862 $OSM_DEVOPS/jenkins
/host
/start_build MON || FATAL
"MON install failed"
863 mon_is_up
&& track MON
864 $OSM_DEVOPS/jenkins
/host
/start_build SO checkout
$COMMIT_ID || FATAL
"SO container build failed (refspec: '$COMMIT_ID')"
865 $OSM_DEVOPS/jenkins
/host
/start_build UI checkout
$COMMIT_ID || FATAL
"UI container build failed (refspec: '$COMMIT_ID')"
866 #so_is_up && track SOUI
868 elif [ -n "$INSTALL_FROM_LXDIMAGES" ]; then #install from LXD images stored in OSM repo
869 echo -e "\nInstalling from lxd images ..."
870 install_from_lxdimages
871 else #install from binaries
872 echo -e "\nCreating the containers and installing from binaries ..."
873 $OSM_DEVOPS/jenkins
/host
/install RO
$REPOSITORY $RELEASE $REPOSITORY_KEY $REPOSITORY_BASE || FATAL
"RO install failed"
875 $OSM_DEVOPS/jenkins
/host
/start_build VCA || FATAL
"VCA install failed"
876 vca_is_up
&& track VCA
877 $OSM_DEVOPS/jenkins
/host
/install MON || FATAL
"MON build failed"
878 mon_is_up
&& track MON
879 $OSM_DEVOPS/jenkins
/host
/install SO
$REPOSITORY $RELEASE $REPOSITORY_KEY $REPOSITORY_BASE || FATAL
"SO install failed"
880 $OSM_DEVOPS/jenkins
/host
/install UI
$REPOSITORY $RELEASE $REPOSITORY_KEY $REPOSITORY_BASE || FATAL
"UI install failed"
881 #so_is_up && track SOUI
885 #Install iptables-persistent and configure NAT rules
886 [ -z "$NOCONFIGURE" ] && nat
888 #Configure components
889 [ -z "$NOCONFIGURE" ] && configure
892 [ -z "$NOCONFIGURE" ] && install_osmclient
894 #Install vim-emu (optional)
895 [ -n "$INSTALL_VIMEMU" ] && install_docker_ce
&& install_vimemu
897 wget
-q -O- https
://osm-download.etsi.org
/ftp
/osm-4.0
-four/README2.txt
&> /dev
/null