Merge pull request #1322 in FS/freeswitch from ~SAFAROV/freeswitch2:FS-10461 to master
* commit 'd5cceb304adacc60d4c58471acbe8e0ce93c773d': FS-10461: created scripts to build docker base image
This commit is contained in:
commit
67b2a1e9fc
|
@ -0,0 +1,37 @@
|
|||
#
|
||||
# FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
||||
# Copyright (C) 2005-2016, Anthony Minessale II <anthm@freeswitch.org>
|
||||
#
|
||||
# Version: MPL 1.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/F
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Michael Jerris <mike@jerris.com>
|
||||
# Portions created by the Initial Developer are Copyright (C)
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Sergey Safarov <s.safarov@gmail.com>
|
||||
#
|
||||
|
||||
FROM scratch
|
||||
|
||||
ADD freeswitch_img.tar.gz /
|
||||
COPY docker-entrypoint.sh healthcheck.sh sounds_version.txt /
|
||||
|
||||
HEALTHCHECK --interval=15s --timeout=5s \
|
||||
CMD /healthcheck.sh
|
||||
|
||||
ENTRYPOINT ["/docker-entrypoint.sh"]
|
|
@ -0,0 +1,103 @@
|
|||
About
|
||||
-----
|
||||
|
||||
This is minimized official FreeSwitch docker container.
|
||||
Container designed to run on host network.
|
||||
Size of container decreased to 120MB (54MB compressed)
|
||||
Significantly increased security:
|
||||
1) removed all libs except libc, busybox, freeswitch and dependent libs.
|
||||
2) removed 'system' API command from vanila config
|
||||
3) updated FreeSwitch default SIP password to random value
|
||||
|
||||
Used environment variables
|
||||
--------------------------
|
||||
|
||||
1) ```SOUND_RATES``` - rates of sound files that must be downloaded and installed. Available values ```8000```, ```16000```, ```32000```, ```48000```. May defined multiply values using semicolon as delimiter. Example ```SOUND_RATES=8000:16000```;
|
||||
2) ```SOUND_TYPES``` - types of sound files that must be downloaded and installed. Available values music, ```en-us-callie```, ```ru-RU-elena```, ```en-ca-june```, ```fr-ca-june```, ```pt-BR-karina```, ```sv-se-jakob```, ```zh-cn-sinmei```, ```zh-hk-sinmei```. Example ```SOUND_TYPES=music:en-us-callie```;
|
||||
3) ```EPMD``` - start epmd daemon, useful when you use mod_erlang and mod_kazoo FreeSwitch modules. Available values ```true```, ```false```.
|
||||
|
||||
Usage container
|
||||
---------------
|
||||
|
||||
1) Creating volume for sound files. This may be skipped if you not use freeswitch MOH and other sound files.
|
||||
```sh
|
||||
docker volume create --name freeswitch-sounds
|
||||
```
|
||||
|
||||
2) Stating container
|
||||
```sh
|
||||
docker run --net=host --name freeswitch \
|
||||
-e SOUND_RATES=8000:16000 \
|
||||
-e SOUND_TYPES=music:en-us-callie \
|
||||
-v freeswitch-sounds:/usr/share/freeswitch/sounds \
|
||||
-v /etc/freeswitch/:/etc/freeswitch \
|
||||
safarov/freeswitch
|
||||
```
|
||||
|
||||
systemd unit file
|
||||
-----------------
|
||||
You can use this systemd unit file on your hosts.
|
||||
```sh
|
||||
$ cat /etc/systemd/system/freeswitch-docker.service
|
||||
[Unit]
|
||||
Description=freeswitch Container
|
||||
After=docker.service network-online.target
|
||||
Requires=docker.service
|
||||
|
||||
|
||||
[Service]
|
||||
Restart=always
|
||||
TimeoutStartSec=0
|
||||
#One ExecStart/ExecStop line to prevent hitting bugs in certain systemd versions
|
||||
ExecStart=/bin/sh -c 'docker rm -f freeswitch; \
|
||||
docker run -t --net=host --name freeswitch \
|
||||
-e SOUND_RATES=8000:16000 \
|
||||
-e SOUND_TYPES=music:en-us-callie \
|
||||
-v freeswitch-sounds:/usr/share/freeswitch/sounds \
|
||||
-v /etc/kazoo/freeswitch/:/etc/freeswitch \
|
||||
freeswitch'
|
||||
ExecStop=-/bin/sh -c '/usr/bin/docker stop freeswitch; \
|
||||
/usr/bin/docker rm -f freeswitch;'
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
Unit file can be placed to ```/etc/systemd/system/freeswitch-docker.service``` and enabled by command
|
||||
```sh
|
||||
systemd start freeswitch-docker.service
|
||||
systemd enable freeswitch-docker.service
|
||||
```
|
||||
|
||||
.bashrc file
|
||||
------------
|
||||
To simplify freeswitch managment you can add alias for ```fs_cli``` to ```.bashrc``` file as example bellow.
|
||||
```sh
|
||||
alias fs_cli='docker exec -i -t freeswitch /usr/bin/fs_cli'
|
||||
```
|
||||
|
||||
How to create custom container
|
||||
------------------------------
|
||||
This container created from scratch image by addiding required freeswitch files packaged to tar.gz archive.
|
||||
To create custom container:
|
||||
1) install required FreeSwitch packages. Now supported debian dist
|
||||
```sh
|
||||
apt-get install freeswitch-conf-vanilla
|
||||
```
|
||||
2) clone freeswitch repo
|
||||
```sh
|
||||
git clone https://freeswitch.org/stash/projects/FS/repos/freeswitch/browse
|
||||
```
|
||||
3) execute ```make_min_archive.sh``` script
|
||||
```sh
|
||||
cd freeswitch/docker/base_image
|
||||
./make_min_archive.sh
|
||||
```
|
||||
4) build custom container
|
||||
```sh
|
||||
docker build -t freeswitch_custom .
|
||||
```
|
||||
|
||||
Read more
|
||||
---------
|
||||
|
||||
[Dockerfile of official FreeSwitch container](https://freeswitch.org/stash/projects/FS/repos/freeswitch/browse/docker/release)
|
|
@ -0,0 +1,127 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
# FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
||||
# Copyright (C) 2005-2016, Anthony Minessale II <anthm@freeswitch.org>
|
||||
#
|
||||
# Version: MPL 1.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/F
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Michael Jerris <mike@jerris.com>
|
||||
# Portions created by the Initial Developer are Copyright (C)
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Sergey Safarov <s.safarov@gmail.com>
|
||||
#
|
||||
|
||||
BASEURL=http://files.freeswitch.org
|
||||
PID_FILE=/var/run/freeswitch/freeswitch.pid
|
||||
|
||||
get_password() {
|
||||
< /dev/urandom tr -dc _A-Z-a-z-0-9 | head -c${1:-12};echo;
|
||||
}
|
||||
|
||||
get_sound_version() {
|
||||
local SOUND_TYPE=$1
|
||||
grep "$SOUND_TYPE" sounds_version.txt | sed -E "s/$SOUND_TYPE\s+//"
|
||||
}
|
||||
|
||||
wget_helper() {
|
||||
local SOUND_FILE=$1
|
||||
grep -q $SOUND_FILE /usr/share/freeswitch/sounds/soundfiles_present.txt 2> /dev/null
|
||||
if [ "$?" -eq 0 ]; then
|
||||
echo "Skiping download of $SOUND_FILE. Already present"
|
||||
return
|
||||
fi
|
||||
wget $BASEURL/$SOUND_FILE
|
||||
if [ -f $SOUND_FILE ]; then
|
||||
echo $SOUND_FILE >> /usr/share/freeswitch/sounds/soundfiles_present.txt
|
||||
fi
|
||||
}
|
||||
|
||||
download_sound_rates() {
|
||||
local i
|
||||
local f
|
||||
local SOUND_TYPE=$1
|
||||
local SOUND_VERSION=$2
|
||||
|
||||
for i in $SOUND_RATES
|
||||
do
|
||||
f=freeswitch-sounds-$SOUND_TYPE-$i-$SOUND_VERSION.tar.gz
|
||||
echo "Downloading $f"
|
||||
wget_helper $f
|
||||
done
|
||||
}
|
||||
|
||||
download_sound_types() {
|
||||
local i
|
||||
local SOUND_VERSION
|
||||
for i in $SOUND_TYPES
|
||||
do
|
||||
SOUND_VERSION=$(get_sound_version $i)
|
||||
download_sound_rates $i $SOUND_VERSION
|
||||
done
|
||||
}
|
||||
|
||||
extract_sound_files() {
|
||||
local SOUND_FILES=freeswitch-sounds-*.tar.gz
|
||||
for f in $SOUND_FILES
|
||||
do
|
||||
if [ -f $f ]; then
|
||||
echo "Extracting file $f"
|
||||
tar xzf $f -C /usr/share/freeswitch/sounds/
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
delete_archives() {
|
||||
local FILES_COUNT=$(ls -1 freeswitch-sounds-*.tar.gz 2> /dev/null | wc -l)
|
||||
if [ "$FILES_COUNT" -ne 0 ]; then
|
||||
echo "Removing downloaded 'tar.gz' archives"
|
||||
rm -f freeswitch-sounds-*.tar.gz
|
||||
fi
|
||||
}
|
||||
|
||||
SOUND_RATES=$(echo "$SOUND_RATES" | sed -e 's/:/\n/g')
|
||||
SOUND_TYPES=$(echo "$SOUND_TYPES" | sed -e 's/:/\n/g')
|
||||
|
||||
if [ -z "$SOUND_RATES" -o -z "$SOUND_TYPES" ]; then
|
||||
echo "Environment variables 'SOUND_RATES' or 'SOUND_TYPES' not defined. Skiping sound files checking."
|
||||
else
|
||||
download_sound_types
|
||||
extract_sound_files
|
||||
delete_archives
|
||||
fi
|
||||
|
||||
if [ "$EPMD"="true" ]; then
|
||||
/usr/bin/epmd -daemon
|
||||
fi
|
||||
|
||||
if [ ! -f "/etc/freeswitch/freeswitch.xml" ]; then
|
||||
SIP_PASSWORD=$(get_password)
|
||||
mkdir -p /etc/freeswitch
|
||||
cp -varf /usr/share/freeswitch/conf/vanilla/* /etc/freeswitch/
|
||||
sed -i -e "s/default_password=.*\?/default_password=$SIP_PASSWORD\"/" /etc/freeswitch/vars.xml
|
||||
echo "New FreeSwitch password for SIP calls set to '$SIP_PASSWORD'"
|
||||
fi
|
||||
|
||||
trap '/usr/bin/freeswitch -stop' SIGTERM
|
||||
|
||||
/usr/bin/freeswitch -nc -nf -nonat &
|
||||
pid="$!"
|
||||
|
||||
wait $pid
|
||||
exit 0
|
|
@ -0,0 +1,30 @@
|
|||
diff -ur a/usr/share/freeswitch/conf/vanilla/autoload_configs/logfile.conf.xml b/usr/share/freeswitch/conf/vanilla/autoload_configs/logfile.conf.xml
|
||||
--- a/usr/share/freeswitch/conf/vanilla/autoload_configs/logfile.conf.xml 2017-06-13 13:15:43.000000000 +0000
|
||||
+++ b/usr/share/freeswitch/conf/vanilla/autoload_configs/logfile.conf.xml 2017-07-02 18:38:58.000000000 +0000
|
||||
@@ -25,5 +25,15 @@
|
||||
<map name="all" value="console,debug,info,notice,warning,err,crit,alert"/>
|
||||
</mappings>
|
||||
</profile>
|
||||
+ <profile name="stdout">
|
||||
+ <settings>
|
||||
+ <param name="logfile" value="/dev/stdout"/>
|
||||
+ <param name="rollover" value="0"/>
|
||||
+ <param name="uuid" value="true" />
|
||||
+ </settings>
|
||||
+ <mappings>
|
||||
+ <map name="all" value="warning,err,crit,alert"/>
|
||||
+ </mappings>
|
||||
+ </profile>
|
||||
</profiles>
|
||||
</configuration>
|
||||
diff -ur a/usr/share/freeswitch/conf/vanilla/vars.xml b/usr/share/freeswitch/conf/vanilla/vars.xml
|
||||
--- a/usr/share/freeswitch/conf/vanilla/vars.xml 2017-06-13 13:15:43.000000000 +0000
|
||||
+++ b/usr/share/freeswitch/conf/vanilla/vars.xml 2017-07-02 18:38:58.000000000 +0000
|
||||
@@ -13,6 +13,7 @@
|
||||
WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
|
||||
-->
|
||||
<X-PRE-PROCESS cmd="set" data="default_password=1234"/>
|
||||
+ <X-PRE-PROCESS cmd="set" data="disable_system_api_commands=false"/>
|
||||
<!-- Did you change it yet? -->
|
||||
<!--
|
||||
The following variables are set dynamically - calculated if possible by freeswitch - and
|
|
@ -0,0 +1,41 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
# FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
||||
# Copyright (C) 2005-2016, Anthony Minessale II <anthm@freeswitch.org>
|
||||
#
|
||||
# Version: MPL 1.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/F
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Michael Jerris <mike@jerris.com>
|
||||
# Portions created by the Initial Developer are Copyright (C)
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Sergey Safarov <s.safarov@gmail.com>
|
||||
#
|
||||
|
||||
# Check FreeSwitch status
|
||||
fs_cli -x status | grep -q ^UP || exit 1
|
||||
|
||||
# Check erlang related modules is registered on epmd daemon
|
||||
KAZOO_EXIST=$(fs_cli -x "module_exists mod_kazoo")
|
||||
ERLANG_EXITS=$(fs_cli -x "module_exists mod_erlang_event")
|
||||
|
||||
if [ "$KAZOO_EXIST" == "true" -o "$ERLANG_EXITS" == "true" ]; then
|
||||
/usr/bin/epmd -names | grep -qE "^name freeswitch at port" || exit 1
|
||||
fi
|
||||
|
||||
exit 0
|
|
@ -0,0 +1,163 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
# FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
||||
# Copyright (C) 2005-2016, Anthony Minessale II <anthm@freeswitch.org>
|
||||
#
|
||||
# Version: MPL 1.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/F
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Michael Jerris <mike@jerris.com>
|
||||
# Portions created by the Initial Developer are Copyright (C)
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Sergey Safarov <s.safarov@gmail.com>
|
||||
#
|
||||
|
||||
BUILD_ROOT=/tmp/freeswitch
|
||||
FILELIST=/tmp/filelist
|
||||
FILELIST_BINARY=/tmp/filelist_binary
|
||||
WITHOUT_PERL="true"
|
||||
WITHOUT_PYTHON="true"
|
||||
WITHOUT_JAVA="true"
|
||||
TMP_TAR=/tmp/freeswitch_min.tar.gz
|
||||
IMG_TAR=/tmp/freeswitch_img.tar.gz
|
||||
|
||||
clean_build_root() {
|
||||
rm -Rf $BUILD_ROOT
|
||||
mkdir -p $BUILD_ROOT
|
||||
rm -f $TMP_TAR
|
||||
rm -f $IMG_TAR
|
||||
}
|
||||
|
||||
fs_files_debian() {
|
||||
local PACKAGES
|
||||
PACKAGES=$(dpkg-query -f '${binary:Package}\n' -W 'freeswitch*')
|
||||
PACKAGES="libc6 $PACKAGES"
|
||||
for pkg in $PACKAGES
|
||||
do
|
||||
dpkg-query -L $pkg 2> /dev/null
|
||||
done
|
||||
}
|
||||
|
||||
extra_files_debian() {
|
||||
cat << EOF
|
||||
/etc
|
||||
/bin
|
||||
/bin/busybox
|
||||
/usr/bin
|
||||
/usr/bin/epmd
|
||||
/usr/lib
|
||||
/usr/lib/erlang
|
||||
/usr/lib/erlang/bin
|
||||
/usr/lib/erlang/bin/epmd
|
||||
/usr/lib/erlang/erts-6.2
|
||||
/usr/lib/erlang/erts-6.2/bin
|
||||
/usr/lib/erlang/erts-6.2/bin/epmd
|
||||
EOF
|
||||
}
|
||||
|
||||
sort_filelist() {
|
||||
sort $FILELIST | uniq > $FILELIST.new
|
||||
mv -f $FILELIST.new $FILELIST
|
||||
}
|
||||
|
||||
filter_unnecessary_files() {
|
||||
# excluded following files and directories recursive
|
||||
# /.
|
||||
# /lib/systemd/
|
||||
# /usr/share/doc/
|
||||
# /usr/share/lintian/
|
||||
# /usr/share/freeswitch/sounds/
|
||||
# all "*.flac" files
|
||||
|
||||
sed -i \
|
||||
-e '\|^/\.$|d' \
|
||||
-e '\|^/lib/systemd|d' \
|
||||
-e '\|^/usr/share/doc|d' \
|
||||
-e '\|^/usr/share/lintian|d' \
|
||||
-e '\|^/usr/share/freeswitch/sounds/|d' \
|
||||
-e '\|^/.*\.flac$|d' \
|
||||
-e '\|^/.*/flac$|d' \
|
||||
$FILELIST
|
||||
|
||||
# if disabled Perl and python removing this too
|
||||
if [ "$WITHOUT_PERL"="true" ];then
|
||||
sed -i -e '\|^/usr/share/perl5|d' $FILELIST
|
||||
fi
|
||||
if [ "$WITHOUT_PYTHON"="true" ];then
|
||||
sed -i -e '\|^/usr/share/pyshared|d' -e '\|^/usr/share/python-support|d' $FILELIST
|
||||
fi
|
||||
if [ "$WITHOUT_JAVA"="true" ];then
|
||||
sed -i -e '\|^/usr/share/freeswitch/scripts/freeswitch.jar|d' $FILELIST
|
||||
fi
|
||||
}
|
||||
|
||||
ldd_helper() {
|
||||
TESTFILE=$1
|
||||
ldd $TESTFILE 2> /dev/null > /dev/null || return
|
||||
|
||||
RESULT=$(ldd $TESTFILE | grep -oP '\s\S+\s\(\S+\)' | sed -e 's/^\s//' -e 's/\s.*$//') #'
|
||||
# This for tests
|
||||
# echo $TESTFILE
|
||||
echo "$RESULT"
|
||||
}
|
||||
|
||||
find_binaries() {
|
||||
rm -f $FILELIST_BINARY
|
||||
for f in $(cat $FILELIST)
|
||||
do
|
||||
ldd_helper $f >> $FILELIST_BINARY
|
||||
done
|
||||
sort $FILELIST_BINARY | sort | uniq | sed -e '/linux-vdso.so.1/d' > $FILELIST_BINARY.new
|
||||
mv -f $FILELIST_BINARY.new $FILELIST_BINARY
|
||||
cat $FILELIST_BINARY | xargs realpath > $FILELIST_BINARY.new
|
||||
cat $FILELIST_BINARY.new >> $FILELIST_BINARY
|
||||
rm -f $FILELIST_BINARY.new
|
||||
}
|
||||
|
||||
tar_files() {
|
||||
local TARLIST=/tmp/tarlist
|
||||
cat $FILELIST > $TARLIST
|
||||
cat $FILELIST_BINARY >> $TARLIST
|
||||
tar -czf $TMP_TAR --no-recursion -T $TARLIST
|
||||
rm -f $TARLIST
|
||||
}
|
||||
|
||||
make_image_tar() {
|
||||
local CURDIR=`pwd`
|
||||
cd $BUILD_ROOT
|
||||
tar xzf $TMP_TAR
|
||||
find usr/share/freeswitch/conf/* -maxdepth 0 -type d -not -name vanilla -exec rm -Rf {} \;
|
||||
# Patching config file
|
||||
patch -p 1 < $CURDIR/freeswitch-config.patch
|
||||
busybox --install -s bin
|
||||
tar czf $IMG_TAR *
|
||||
cd $CURDIR
|
||||
}
|
||||
|
||||
apt-get --assume-yes install busybox patch
|
||||
|
||||
clean_build_root
|
||||
fs_files_debian > $FILELIST
|
||||
extra_files_debian >> $FILELIST
|
||||
sort_filelist
|
||||
filter_unnecessary_files
|
||||
find_binaries
|
||||
tar_files
|
||||
make_image_tar
|
||||
mv $IMG_TAR .
|
||||
clean_build_root
|
|
@ -0,0 +1,10 @@
|
|||
music 1.0.52
|
||||
en-us-callie 1.0.51
|
||||
ru-RU-elena 1.0.51
|
||||
en-ca-june 1.0.51
|
||||
fr-ca-june 1.0.51
|
||||
pt-BR-karina 1.0.51
|
||||
sv-se-jakob 1.0.50
|
||||
zh-cn-sinmei 1.0.51
|
||||
zh-hk-sinmei 1.0.51
|
||||
|
Loading…
Reference in New Issue