opennebula-node-kvm deploy
This commit is contained in:
@@ -45,7 +45,7 @@ if [ ! -e "${ONEHOME}/.ssh/config" ] && [ -z "$2" ]; then
|
||||
fi
|
||||
|
||||
# Set permissions and owner oneadmin:cloud
|
||||
for F in /var/lock/one /var/log/one /var/run/one
|
||||
for F in /var/lock/one /var/log/one /var/run/one /usr/lib/one
|
||||
do
|
||||
if [ ! -d "${F}" ]; then
|
||||
mkdir -p "${F}"
|
||||
|
||||
@@ -9,13 +9,44 @@ arch="noarch"
|
||||
options="!check"
|
||||
license="Apache"
|
||||
|
||||
depends=""
|
||||
depends="
|
||||
opennebula-common
|
||||
libvirt-daemon
|
||||
qemu-img
|
||||
qemu-system-x86_64
|
||||
ruby
|
||||
vlan
|
||||
ipset
|
||||
pciutils
|
||||
rsync
|
||||
tar
|
||||
cronie
|
||||
logrotate
|
||||
augeas
|
||||
libxml2
|
||||
iptables"
|
||||
|
||||
install="
|
||||
${pkgname}.post-install
|
||||
${pkgname}.post-deinstall"
|
||||
|
||||
source=""
|
||||
source="
|
||||
/etc/cron.d/opennebula-node
|
||||
/etc/init.d/opennebula-gate-proxy
|
||||
/etc/logrotate.d/opennebula-gate-proxy
|
||||
/etc/sudoers.d/opennebula-node-kvm
|
||||
/etc/sysctl.d/bridge-nf-call.conf
|
||||
/usr/bin/onegate-proxy
|
||||
/usr/bin/qemu-kvm-one-gen
|
||||
/usr/lib/one/onegate-proxy/onegate-proxy.rb
|
||||
"
|
||||
|
||||
package() {
|
||||
}
|
||||
install -Dm700 "${srcdir}/etc/cron.d/opennebula-node" "${pkgdir}/etc/cron.d/opennebula-node"
|
||||
install -Dm755 "${srcdir}/etc/init.d/opennebula-gate-proxy" "${pkgdir}/etc/init.d/opennebula-gate-proxy"
|
||||
install -Dm644 "${srcdir}/etc/logrotate.d/opennebula-gate-proxy" "${pkgdir}/etc/logrotate.d/opennebula-gate-proxy"
|
||||
install -Dm400 "${srcdir}/etc/sudoers.d/opennebula-node-kvm" "${pkgdir}/etc/sudoers.d/opennebula-node-kvm"
|
||||
install -Dm644 "${srcdir}/etc/sysctl.d/bridge-nf-call.conf" "${pkgdir}/etc/sysctl.d/bridge-nf-call.conf"
|
||||
install -Dm744 "${srcdir}/usr/bin/onegate-proxy" "${pkgdir}/usr/bin/onegate-proxy"
|
||||
install -Dm744 "${srcdir}/usr/bin/qemu-kvm-one-gen" "${pkgdir}/usr/bin/qemu-kvm-one-gen"
|
||||
install -Dm744 -o oneadmin -g cloud "${srcdir}/usr/lib/one/onegate-proxy/onegate-proxy.rb" "${pkgdir}/usr/lib/one/onegate-proxy/onegate-proxy.rb"
|
||||
|
||||
4
opennebula-node-kvm/etc/cron.d/opennebula-node
Normal file
4
opennebula-node-kvm/etc/cron.d/opennebula-node
Normal file
@@ -0,0 +1,4 @@
|
||||
SHELL=/bin/sh
|
||||
|
||||
# activate LVM volumes on reboot
|
||||
@reboot oneadmin test -x /var/tmp/one/tm/fs_lvm/activate && /var/tmp/one/tm/fs_lvm/activate >/dev/null 2>&1
|
||||
30
opennebula-node-kvm/etc/init.d/opennebula-gate-proxy
Normal file
30
opennebula-node-kvm/etc/init.d/opennebula-gate-proxy
Normal file
@@ -0,0 +1,30 @@
|
||||
#!/sbin/openrc-run
|
||||
|
||||
name=$RC_SVCNAME
|
||||
description="OpenNebula Gate Proxy Service"
|
||||
command="/usr/bin/ruby /usr/lib/one/onegate-proxy/onegate-proxy.rb"
|
||||
command_user="oneadmin:cloud"
|
||||
pidfile="/run/one/${RC_SVCNAME}.pid"
|
||||
supervisor="supervise-daemon"
|
||||
|
||||
depend() {
|
||||
need opennebula
|
||||
after syslog networking netmount
|
||||
}
|
||||
|
||||
start() {
|
||||
ebegin "Starting $RC_SVCNAME"
|
||||
start-stop-daemon --background \
|
||||
--exec $command \
|
||||
--make-pidfile --pidfile $pidfile --user $command_user \
|
||||
--start
|
||||
eend $?
|
||||
}
|
||||
|
||||
stop() {
|
||||
ebegin "Stopping $RC_SVCNAME"
|
||||
start-stop-daemon --stop \
|
||||
--exec $command \
|
||||
--pidfile $pidfile --user $command_user
|
||||
eend $?
|
||||
}
|
||||
11
opennebula-node-kvm/etc/logrotate.d/opennebula-gate-proxy
Normal file
11
opennebula-node-kvm/etc/logrotate.d/opennebula-gate-proxy
Normal file
@@ -0,0 +1,11 @@
|
||||
/var/log/one/onegate-proxy.log {
|
||||
delaycompress
|
||||
dateext
|
||||
dateformat -%Y%m%d-%s
|
||||
compress
|
||||
weekly
|
||||
rotate 52
|
||||
missingok
|
||||
notifempty
|
||||
copytruncate
|
||||
}
|
||||
1
opennebula-node-kvm/etc/sudoers.d/opennebula-node-kvm
Normal file
1
opennebula-node-kvm/etc/sudoers.d/opennebula-node-kvm
Normal file
@@ -0,0 +1 @@
|
||||
oneadmin ALL=(ALL:ALL) NOPASSWD: ONE_CEPH, ONE_NET, ONE_OVS, ONE_LVM, ONE_MEM, ONE_VGPU
|
||||
3
opennebula-node-kvm/etc/sysctl.d/bridge-nf-call.conf
Normal file
3
opennebula-node-kvm/etc/sysctl.d/bridge-nf-call.conf
Normal file
@@ -0,0 +1,3 @@
|
||||
net.bridge.bridge-nf-call-arptables = 1
|
||||
net.bridge.bridge-nf-call-ip6tables = 1
|
||||
net.bridge.bridge-nf-call-iptables = 1
|
||||
@@ -1,57 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
ONEHOME=/var/lib/one
|
||||
ONE_GROUP=cloud
|
||||
ONE_USER=oneadmin
|
||||
ONE_UID=9869
|
||||
ONE_GID=9869
|
||||
ONE_COMMENT="OpenNebula administrator account"
|
||||
|
||||
create_cloudgroup() {
|
||||
if ! getent group $ONE_GROUP > /dev/null 2>&1; then
|
||||
addgroup --system --gid $ONE_GID $ONE_GROUP
|
||||
fi
|
||||
}
|
||||
|
||||
create_oneuser() {
|
||||
if ! getent passwd $ONE_USER > /dev/null 2>&1; then
|
||||
adduser --system --gecos "$ONE_COMMENT" --uid $ONE_UID --ingroup $ONE_GROUP --home $ONEHOME --shell /bin/ash $ONE_USER
|
||||
else
|
||||
ONEHOME=`getent passwd $ONE_USER | cut -f6 -d:`
|
||||
# Renable user (give him a shell)
|
||||
usermod --shell /bin/ash $ONE_USER
|
||||
fi
|
||||
|
||||
if ! getent group disk | grep "\b$ONE_USER\b" &>/dev/null; then
|
||||
usermod -a -G disk $ONE_USER
|
||||
fi
|
||||
}
|
||||
|
||||
create_cloudgroup
|
||||
create_oneuser
|
||||
|
||||
# Install ~oneadmin/.ssh/config if not present on a fresh install only
|
||||
if [ ! -e "${ONEHOME}/.ssh/config" ] && [ -z "$2" ]; then
|
||||
if [ ! -d "${ONEHOME}/.ssh" ]; then
|
||||
mkdir -p "${ONEHOME}/.ssh"
|
||||
chmod 0700 "${ONEHOME}/.ssh"
|
||||
chown "$ONE_USER:$ONE_GROUP" "${ONEHOME}/.ssh"
|
||||
fi
|
||||
cp /usr/share/one/ssh/config "${ONEHOME}/.ssh/config"
|
||||
chmod 0600 "${ONEHOME}/.ssh/config"
|
||||
chown "$ONE_USER:$ONE_GROUP" "${ONEHOME}/.ssh/config"
|
||||
fi
|
||||
|
||||
# Set permissions and owner oneadmin:cloud
|
||||
for F in /var/lock/one /var/log/one /var/run/one
|
||||
do
|
||||
if [ ! -d "${F}" ]; then
|
||||
mkdir -p "${F}"
|
||||
chmod 0750 "${F}"
|
||||
chown "${ONE_USER}:${ONE_GROUP}" "${F}"
|
||||
fi
|
||||
done
|
||||
|
||||
exit 0
|
||||
140
opennebula-node-kvm/opennebula-node-kvm.post-install
Normal file
140
opennebula-node-kvm/opennebula-node-kvm.post-install
Normal file
@@ -0,0 +1,140 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
ONEHOME=/var/lib/one
|
||||
ONE_GROUP=cloud
|
||||
ONE_USER=oneadmin
|
||||
|
||||
# Add oneadmin user into libvirt group
|
||||
if getent group libvirt >/dev/null && ! getent group libvirt | cut -f4 -d: | grep -q "\<$ONE_USER\>"; then
|
||||
adduser $ONE_USER libvirt
|
||||
fi
|
||||
|
||||
# Add oneadmin user into kvm group
|
||||
if getent group kvm >/dev/null && ! getent group kvm | cut -f4 -d: | grep -q "\<$ONE_USER\>"; then
|
||||
adduser $ONE_USER kvm
|
||||
fi
|
||||
|
||||
# Backup libvirt/QEMU configuration, reconfigure for OpenNebula
|
||||
if [ -e /etc/libvirt/qemu.conf ]; then
|
||||
cp -f /etc/libvirt/qemu.conf "/etc/libvirt/qemu.conf.$(date +'%Y-%m-%d_%H:%M:%S')"
|
||||
fi
|
||||
|
||||
AUGTOOL=$(augtool -A 2>/dev/null <<EOF
|
||||
set /augeas/load/Libvirtd_qemu/lens Libvirtd_qemu.lns
|
||||
set /augeas/load/Libvirtd_qemu/incl /etc/libvirt/qemu.conf
|
||||
load
|
||||
|
||||
set /files/etc/libvirt/qemu.conf/user oneadmin
|
||||
set /files/etc/libvirt/qemu.conf/group cloud
|
||||
set /files/etc/libvirt/qemu.conf/dynamic_ownership 0
|
||||
|
||||
save
|
||||
EOF
|
||||
)
|
||||
|
||||
# generate generic qemu-kvm-one symlink
|
||||
/usr/bin/qemu-kvm-one-gen
|
||||
|
||||
if [ -n "${AUGTOOL}" ] && [ -z "${AUGTOOL##*Saved *}" ]; then
|
||||
systemctl try-restart libvirtd 2>/dev/null || true
|
||||
fi
|
||||
|
||||
# # Automatically added by dh_systemd_enable/12.10ubuntu1
|
||||
# if [ "$1" = "configure" ] || [ "$1" = "abort-upgrade" ] || [ "$1" = "abort-deconfigure" ] || [ "$1" = "abort-remove" ] ; then
|
||||
# if deb-systemd-helper debian-installed 'opennebula-gate-proxy.service'; then
|
||||
# # This will only remove masks created by d-s-h on package removal.
|
||||
# deb-systemd-helper unmask 'opennebula-gate-proxy.service' >/dev/null || true
|
||||
#
|
||||
# if deb-systemd-helper --quiet was-enabled 'opennebula-gate-proxy.service'; then
|
||||
# # Create new symlinks, if any.
|
||||
# deb-systemd-helper enable 'opennebula-gate-proxy.service' >/dev/null || true
|
||||
# fi
|
||||
# fi
|
||||
#
|
||||
# # Update the statefile to add new symlinks (if any), which need to be cleaned
|
||||
# # up on purge. Also remove old symlinks.
|
||||
# deb-systemd-helper update-state 'opennebula-gate-proxy.service' >/dev/null || true
|
||||
# fi
|
||||
# # End automatically added section
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
create_cloudgroup() {
|
||||
if ! getent group $ONE_GROUP > /dev/null 2>&1; then
|
||||
addgroup --system --gid $ONE_GID $ONE_GROUP
|
||||
fi
|
||||
}
|
||||
|
||||
create_oneuser() {
|
||||
if ! getent passwd $ONE_USER > /dev/null 2>&1; then
|
||||
adduser --system --gecos "$ONE_COMMENT" --uid $ONE_UID --ingroup $ONE_GROUP --home $ONEHOME --shell /bin/ash $ONE_USER
|
||||
else
|
||||
ONEHOME=`getent passwd $ONE_USER | cut -f6 -d:`
|
||||
# Renable user (give him a shell)
|
||||
usermod --shell /bin/ash $ONE_USER
|
||||
fi
|
||||
|
||||
if ! getent group disk | grep "\b$ONE_USER\b" &>/dev/null; then
|
||||
usermod -a -G disk $ONE_USER
|
||||
fi
|
||||
}
|
||||
|
||||
create_cloudgroup
|
||||
create_oneuser
|
||||
|
||||
# Install ~oneadmin/.ssh/config if not present on a fresh install only
|
||||
if [ ! -e "${ONEHOME}/.ssh/config" ] && [ -z "$2" ]; then
|
||||
if [ ! -d "${ONEHOME}/.ssh" ]; then
|
||||
mkdir -p "${ONEHOME}/.ssh"
|
||||
chmod 0700 "${ONEHOME}/.ssh"
|
||||
chown "$ONE_USER:$ONE_GROUP" "${ONEHOME}/.ssh"
|
||||
fi
|
||||
cp /usr/share/one/ssh/config "${ONEHOME}/.ssh/config"
|
||||
chmod 0600 "${ONEHOME}/.ssh/config"
|
||||
chown "$ONE_USER:$ONE_GROUP" "${ONEHOME}/.ssh/config"
|
||||
fi
|
||||
|
||||
# Set permissions and owner oneadmin:cloud
|
||||
for F in /var/lock/one /var/log/one /var/run/one
|
||||
do
|
||||
if [ ! -d "${F}" ]; then
|
||||
mkdir -p "${F}"
|
||||
chmod 0750 "${F}"
|
||||
chown "${ONE_USER}:${ONE_GROUP}" "${F}"
|
||||
fi
|
||||
done
|
||||
|
||||
exit 0
|
||||
120
opennebula-node-kvm/usr/bin/onegate-proxy
Executable file
120
opennebula-node-kvm/usr/bin/onegate-proxy
Executable file
@@ -0,0 +1,120 @@
|
||||
#!/bin/bash
|
||||
|
||||
# -------------------------------------------------------------------------- #
|
||||
# Copyright 2002-2023, OpenNebula Project, OpenNebula Systems #
|
||||
# #
|
||||
# Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 #
|
||||
# #
|
||||
# Unless required by applicable law or agreed to in writing, software #
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, #
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
|
||||
# See the License for the specific language governing permissions and #
|
||||
# limitations under the License. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
if [ -z "$ONE_LOCATION" ]; then
|
||||
ONEGATE_PROXY_PID=/var/run/one/onegate-proxy.pid
|
||||
ONEGATE_PROXY_SERVER=/usr/lib/one/onegate-proxy/onegate-proxy.rb
|
||||
ONEGATE_PROXY_LOCK_FILE=/var/lock/one/.onegate-proxy.lock
|
||||
ONEGATE_PROXY_LOG=/var/log/one/onegate-proxy.log
|
||||
ONEGATE_PROXY_LOG_ERROR=/var/log/one/onegate-proxy.error
|
||||
else
|
||||
ONEGATE_PROXY_PID=$ONE_LOCATION/var/onegate-proxy.pid
|
||||
ONEGATE_PROXY_SERVER=$ONE_LOCATION/lib/onegate-proxy/onegate-proxy.rb
|
||||
ONEGATE_PROXY_LOCK_FILE=$ONE_LOCATION/var/.onegate-proxy.lock
|
||||
ONEGATE_PROXY_LOG=$ONE_LOCATION/var/onegate-proxy.log
|
||||
ONEGATE_PROXY_LOG_ERROR=$ONE_LOCATION/var/onegate-proxy.error
|
||||
fi
|
||||
|
||||
setup()
|
||||
{
|
||||
if [ -f $ONEGATE_PROXY_LOCK_FILE ]; then
|
||||
if [ -f $ONEGATE_PROXY_PID ]; then
|
||||
ONEGATEPID=`cat $ONEGATE_PROXY_PID`
|
||||
ps $ONEGATEPID &> /dev/null
|
||||
if [ $? -eq 0 ]; then
|
||||
echo -n "OneGate Server is still running (PID:$ONEGATEPID). Please "
|
||||
echo "try 'onegate-proxy stop' first."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
echo "Stale .lock detected. Erasing it."
|
||||
rm $ONEGATE_PROXY_LOCK_FILE
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
start()
|
||||
{
|
||||
if [ ! -f "$ONEGATE_PROXY_SERVER" ]; then
|
||||
echo "Cannot find $ONEGATE_PROXY_SERVER."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Start the onegate daemon
|
||||
touch $ONEGATE_PROXY_LOCK_FILE
|
||||
ruby $ONEGATE_PROXY_SERVER > $ONEGATE_PROXY_LOG 2>$ONEGATE_PROXY_LOG_ERROR &
|
||||
LASTPID=$!
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Error executing onegate-proxy."
|
||||
echo "Check $ONEGATE_PROXY_LOG_ERROR and $ONEGATE_PROXY_LOG for more information"
|
||||
exit 1
|
||||
else
|
||||
echo $LASTPID > $ONEGATE_PROXY_PID
|
||||
fi
|
||||
|
||||
sleep 1
|
||||
ps $LASTPID &> /dev/null
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Error executing onegate-proxy."
|
||||
echo "Check $ONEGATE_PROXY_LOG_ERROR and $ONEGATE_PROXY_LOG for more information"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "onegate-proxy started"
|
||||
}
|
||||
|
||||
#
|
||||
# Function that stops the daemon/service
|
||||
#
|
||||
stop()
|
||||
{
|
||||
if [ ! -f $ONEGATE_PROXY_PID ]; then
|
||||
echo "Couldn't find onegate-proxy process pid."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Kill the onegate daemon
|
||||
kill -INT `cat $ONEGATE_PROXY_PID` &> /dev/null
|
||||
|
||||
# Remove pid files
|
||||
rm -f $ONEGATE_PROXY_LOCK_FILE &> /dev/null
|
||||
rm -f $ONEGATE_PROXY_PID &> /dev/null
|
||||
|
||||
echo "onegate-proxy stopped"
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
setup
|
||||
start
|
||||
;;
|
||||
stop)
|
||||
stop
|
||||
;;
|
||||
restart)
|
||||
stop
|
||||
setup
|
||||
start
|
||||
;;
|
||||
*)
|
||||
echo "Usage: onegate-proxy {start|stop|restart}" >&2
|
||||
exit 3
|
||||
;;
|
||||
esac
|
||||
120
opennebula-node-kvm/usr/bin/qemu-kvm-one-gen
Executable file
120
opennebula-node-kvm/usr/bin/qemu-kvm-one-gen
Executable file
@@ -0,0 +1,120 @@
|
||||
#!/bin/sh
|
||||
|
||||
# -------------------------------------------------------------------------- #
|
||||
# Copyright 2002-2023, OpenNebula Project, OpenNebula Systems #
|
||||
# #
|
||||
# Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 #
|
||||
# #
|
||||
# Unless required by applicable law or agreed to in writing, software #
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, #
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
|
||||
# See the License for the specific language governing permissions and #
|
||||
# limitations under the License. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
set -e
|
||||
|
||||
CMD=$(basename ${0})
|
||||
|
||||
# file path to the new qemu-kvm symlink
|
||||
QEMU_ONE="/usr/bin/qemu-kvm-one"
|
||||
|
||||
#
|
||||
# functions
|
||||
#
|
||||
|
||||
print_usage()
|
||||
{
|
||||
cat <<EOF
|
||||
NAME:
|
||||
${CMD} - System agnostic QEMU/KVM symlink generator
|
||||
|
||||
It will try to find a qemu-kvm binary in the system from a list of known
|
||||
paths and if successful - it will create a proper symlink:
|
||||
'${QEMU_ONE}'
|
||||
|
||||
USAGE:
|
||||
${CMD} [-f|--force]
|
||||
Find the system QEMU binary and create the symlink
|
||||
|
||||
-f|--force: This option will overwrite existing symlink or file
|
||||
|
||||
${CMD} -h|--help
|
||||
Print this help
|
||||
EOF
|
||||
}
|
||||
|
||||
#
|
||||
# main
|
||||
#
|
||||
|
||||
FORCE_CREATE=
|
||||
case "$1" in
|
||||
'')
|
||||
:
|
||||
;;
|
||||
-h|--help)
|
||||
print_usage
|
||||
exit 0
|
||||
;;
|
||||
-f|--force)
|
||||
FORCE_CREATE=yes
|
||||
;;
|
||||
*)
|
||||
echo "ERROR: ${CMD}: Unknown option '${1}' !" >&2
|
||||
print_usage >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# find cpu arch or default to x86_64
|
||||
if command -v arch >/dev/null 2>&1 ; then
|
||||
ARCH=$(arch)
|
||||
else
|
||||
ARCH="x86_64"
|
||||
fi
|
||||
|
||||
# verify that symlink is not already created
|
||||
if [ -L "${QEMU_ONE}" ] ; then
|
||||
# symlink already exists
|
||||
|
||||
qemu_target=$(readlink "${QEMU_ONE}")
|
||||
|
||||
if [ -e "${qemu_target}" ] && [ -z "${FORCE_CREATE}" ] ; then
|
||||
# symlink is valid
|
||||
exit 0
|
||||
fi
|
||||
elif [ -e "${QEMU_ONE}" ] ; then
|
||||
# there is a file of the same name and it is not a symlink
|
||||
|
||||
if [ -z "${FORCE_CREATE}" ] ; then
|
||||
echo "ERROR: ${CMD}: File '${QEMU_ONE}' already exists but it is not a symlink !" >&2
|
||||
exit 1
|
||||
else
|
||||
# --force is used
|
||||
rm -f "${QEMU_ONE}"
|
||||
fi
|
||||
fi
|
||||
|
||||
# search the known paths for qemu binary
|
||||
#
|
||||
# NOTE: you can add new supported paths here in the future
|
||||
for QEMU_BIN in \
|
||||
/usr/libexec/qemu-kvm \
|
||||
/usr/bin/qemu-kvm \
|
||||
/usr/bin/qemu-system-${ARCH} \
|
||||
;
|
||||
do
|
||||
if [ -e "${QEMU_BIN}" ] ; then
|
||||
ln -s ${FORCE_CREATE:+-f} "${QEMU_BIN}" "${QEMU_ONE}"
|
||||
exit 0
|
||||
fi
|
||||
done
|
||||
|
||||
# no qemu binary found -> we signal error and exit
|
||||
echo "ERROR: ${CMD}: No qemu kvm binary found !" >&2
|
||||
exit 1
|
||||
309
opennebula-node-kvm/usr/lib/one/onegate-proxy/onegate-proxy.rb
Normal file
309
opennebula-node-kvm/usr/lib/one/onegate-proxy/onegate-proxy.rb
Normal file
@@ -0,0 +1,309 @@
|
||||
#!/usr/bin/env ruby
|
||||
# -------------------------------------------------------------------------- #
|
||||
# Copyright 2002-2023, OpenNebula Project, OpenNebula Systems #
|
||||
# #
|
||||
# Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 #
|
||||
# #
|
||||
# Unless required by applicable law or agreed to in writing, software #
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, #
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
|
||||
# See the License for the specific language governing permissions and #
|
||||
# limitations under the License. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
# frozen_string_literal: true
|
||||
|
||||
# rubocop:disable Lint/MissingCopEnableDirective
|
||||
# rubocop:disable Lint/RedundantRequireStatement
|
||||
# rubocop:disable Layout/FirstHashElementIndentation
|
||||
# rubocop:disable Layout/HashAlignment
|
||||
# rubocop:disable Layout/HeredocIndentation
|
||||
# rubocop:disable Layout/IndentationWidth
|
||||
# rubocop:disable Style/HashSyntax
|
||||
# rubocop:disable Style/ParallelAssignment
|
||||
|
||||
ONE_LOCATION = ENV['ONE_LOCATION']
|
||||
|
||||
if !ONE_LOCATION
|
||||
RUBY_LIB_LOCATION = '/usr/lib/one/ruby'
|
||||
GEMS_LOCATION = '/usr/share/one/gems'
|
||||
ETC_LOCATION = '/etc/one'
|
||||
REMOTES_LOCATION = '/var/tmp/one'
|
||||
else
|
||||
RUBY_LIB_LOCATION = ONE_LOCATION + '/lib/ruby'
|
||||
GEMS_LOCATION = ONE_LOCATION + '/share/gems'
|
||||
ETC_LOCATION = ONE_LOCATION + '/etc'
|
||||
REMOTES_LOCATION = ONE_LOCATION + '/var/remotes'
|
||||
end
|
||||
|
||||
CONFIGURATION_FILE = REMOTES_LOCATION + '/etc/onegate-proxy.conf'
|
||||
|
||||
# %%RUBYGEMS_SETUP_BEGIN%%
|
||||
if File.directory?(GEMS_LOCATION)
|
||||
real_gems_path = File.realpath(GEMS_LOCATION)
|
||||
if !defined?(Gem) || Gem.path != [real_gems_path]
|
||||
$LOAD_PATH.reject! {|p| p =~ /vendor_ruby/ }
|
||||
|
||||
# Suppress warnings from Rubygems
|
||||
# https://github.com/OpenNebula/one/issues/5379
|
||||
begin
|
||||
verb = $VERBOSE
|
||||
$VERBOSE = nil
|
||||
require 'rubygems'
|
||||
Gem.use_paths(real_gems_path)
|
||||
ensure
|
||||
$VERBOSE = verb
|
||||
end
|
||||
end
|
||||
end
|
||||
# %%RUBYGEMS_SETUP_END%%
|
||||
|
||||
$LOAD_PATH << RUBY_LIB_LOCATION
|
||||
|
||||
require 'async/io'
|
||||
require 'async/io/stream'
|
||||
require 'async/io/trap'
|
||||
require 'etc'
|
||||
require 'pp'
|
||||
require 'rb-inotify'
|
||||
require 'socket'
|
||||
require 'yaml'
|
||||
|
||||
$stdout.sync = true
|
||||
$stderr.sync = true
|
||||
|
||||
DEFAULT_OPTIONS = {
|
||||
:debug_level => 2, # 0 = ERROR, 1 = WARNING, 2 = INFO, 3 = DEBUG
|
||||
:process_owner => 'oneadmin',
|
||||
:onegate_addr => '127.0.0.1',
|
||||
:onegate_port => '5030',
|
||||
:service_addr => '169.254.16.9'
|
||||
}.freeze
|
||||
|
||||
# Proxy-class for converting log levels between OpenNebula and
|
||||
# the socketry/console library. It also splits specific log levels
|
||||
# into separate stdout and stderr loggers.
|
||||
class Logger
|
||||
|
||||
LOG_LEVEL_MAP = {
|
||||
0 => '3', # ERROR
|
||||
1 => '2', # WARN
|
||||
2 => '1', # INFO
|
||||
3 => '0' # DEBUG
|
||||
}.freeze
|
||||
|
||||
def initialize(log_level = 2)
|
||||
@out = Console::Logger.default_logger $stdout, {
|
||||
'CONSOLE_LEVEL' => LOG_LEVEL_MAP[log_level]
|
||||
}
|
||||
@err = Console::Logger.default_logger $stderr, {
|
||||
'CONSOLE_LEVEL' => LOG_LEVEL_MAP[log_level]
|
||||
}
|
||||
end
|
||||
|
||||
# rubocop:disable Style/ArgumentsForwarding
|
||||
def error(*args, &block)
|
||||
@err.error(*args, &block)
|
||||
end
|
||||
|
||||
def warn(*args, &block)
|
||||
@err.warn(*args, &block)
|
||||
end
|
||||
|
||||
def info(*args, &block)
|
||||
@out.info(*args, &block)
|
||||
end
|
||||
|
||||
def debug(*args, &block)
|
||||
@err.debug(*args, &block)
|
||||
end
|
||||
# rubocop:enable Style/ArgumentsForwarding
|
||||
|
||||
end
|
||||
|
||||
# Class that implements a classic two-way TCP socket proxy (async).
|
||||
class OneGateProxy
|
||||
|
||||
def initialize(options = {})
|
||||
@options = DEFAULT_OPTIONS.dup.merge! options
|
||||
@options.each {|k, v| instance_variable_set("@#{k}", v) }
|
||||
|
||||
@logger = Logger.new options[:debug_level]
|
||||
|
||||
@sigint = Async::IO::Trap.new :INT
|
||||
@sigint.install!
|
||||
|
||||
@inotify = setup_inotify
|
||||
@inotify_io = Async::IO::Generic.new @inotify.to_io
|
||||
|
||||
@proxy_ep = Async::IO::Endpoint.socket setup_socket
|
||||
end
|
||||
|
||||
def run
|
||||
# NOTE: At this point all config should be set in stone,
|
||||
# we can drop root privileges..
|
||||
drop_privileges
|
||||
|
||||
Async do |task|
|
||||
# Make CTRL-C work..
|
||||
task.async do
|
||||
@sigint.wait { exit 0 }
|
||||
end
|
||||
|
||||
# Handle filesystem notifications..
|
||||
task.async do
|
||||
@inotify.process while @inotify_io.wait_readable
|
||||
end
|
||||
|
||||
glue_peers task
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def drop_privileges
|
||||
new_gid, new_uid = Etc.getpwnam(@process_owner).gid,
|
||||
Etc.getpwnam(@process_owner).uid
|
||||
|
||||
@logger.info(self) do
|
||||
"Drop root privileges -> #{@process_owner}"
|
||||
end
|
||||
|
||||
Process::Sys.setgid new_gid
|
||||
Process::Sys.setuid new_uid
|
||||
end
|
||||
|
||||
def setup_inotify
|
||||
inotify = INotify::Notifier.new
|
||||
inotify.watch(CONFIGURATION_FILE, :modify) do
|
||||
@logger.info(self) do
|
||||
"#{CONFIGURATION_FILE} has been just updated, exiting.."
|
||||
end
|
||||
# We assume here that the service will be restarted by
|
||||
# the service manager.
|
||||
exit 0
|
||||
end
|
||||
inotify
|
||||
rescue Errno::ENOENT => e
|
||||
@logger.error(self) do
|
||||
e.message
|
||||
end
|
||||
# We assume here that the service will be restarted by
|
||||
# the service manager.
|
||||
exit e.class::Errno
|
||||
end
|
||||
|
||||
def setup_service_addr
|
||||
# NOTE: We need the service_addr to be defined on one of the interfaces
|
||||
# inside the host, one natural choice is the loopback interface (lo).
|
||||
# Effectively we set it once, subsequent restarts of the service should
|
||||
# honor the idempotence.
|
||||
ip_address_add_cmd = lambda do |cidr_host, nic_device|
|
||||
check = "[ -n \"$(ip a s to '#{cidr_host}' dev '#{nic_device}')\" ]"
|
||||
apply = "ip a a '#{cidr_host}' dev '#{nic_device}'"
|
||||
"#{check.strip} >/dev/null 2>&1 || #{apply.strip}"
|
||||
end
|
||||
system ip_address_add_cmd.call "#{@service_addr}/32", 'lo'
|
||||
end
|
||||
|
||||
def setup_socket(listen = Socket::SOMAXCONN)
|
||||
# NOTE: Must be executed before calling bind(), otherwise it fails..
|
||||
setup_service_addr
|
||||
|
||||
sock = Socket.new Socket::AF_INET, Socket::SOCK_STREAM, 0
|
||||
sock.setsockopt Socket::SOL_SOCKET, Socket::SO_REUSEADDR, 1
|
||||
|
||||
@logger.info(self) do
|
||||
"Bind #{Addrinfo.tcp(@service_addr, @onegate_port).inspect}"
|
||||
end
|
||||
|
||||
sock.bind Socket.pack_sockaddr_in(@onegate_port, @service_addr)
|
||||
sock.listen listen
|
||||
sock
|
||||
end
|
||||
|
||||
def glue_streams(stream1, stream2, task)
|
||||
Async do
|
||||
concurrent = []
|
||||
concurrent << task.async do
|
||||
while (chunk = stream1.read_partial)
|
||||
stream2.write chunk
|
||||
stream2.flush
|
||||
end
|
||||
end
|
||||
concurrent << task.async do
|
||||
while (chunk = stream2.read_partial)
|
||||
stream1.write chunk
|
||||
stream1.flush
|
||||
end
|
||||
end
|
||||
concurrent.each(&:wait)
|
||||
end
|
||||
end
|
||||
|
||||
def glue_peers(task)
|
||||
@proxy_ep.accept do |vm_peer|
|
||||
@logger.debug(self) do
|
||||
"Accept #{vm_peer.remote_address.inspect}"
|
||||
end
|
||||
|
||||
begin
|
||||
gate_ep = Async::IO::Endpoint.tcp @onegate_addr,
|
||||
@onegate_port
|
||||
gate_ep.connect do |gate_peer|
|
||||
vm_stream, gate_stream = Async::IO::Stream.new(vm_peer),
|
||||
Async::IO::Stream.new(gate_peer)
|
||||
|
||||
glue_streams(vm_stream, gate_stream, task).wait
|
||||
|
||||
@logger.debug(self) do
|
||||
"Close #{gate_peer.remote_address.inspect}"
|
||||
end
|
||||
|
||||
gate_peer.close
|
||||
end
|
||||
rescue Errno::ECONNREFUSED,
|
||||
Errno::ECONNRESET,
|
||||
Errno::EHOSTUNREACH,
|
||||
Errno::ETIMEDOUT => e
|
||||
@logger.error(self) do
|
||||
e.message
|
||||
end
|
||||
end
|
||||
|
||||
@logger.debug(self) do
|
||||
"Close #{vm_peer.remote_address.inspect}"
|
||||
end
|
||||
|
||||
vm_peer.close
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
if caller.empty?
|
||||
options = DEFAULT_OPTIONS.dup
|
||||
|
||||
# NOTE: The "CONFIGURATION_FILE" is updated during the host sync procedure.
|
||||
begin
|
||||
options.merge! YAML.load_file(CONFIGURATION_FILE)
|
||||
rescue StandardError => e
|
||||
warn "Error parsing config file #{CONFIGURATION_FILE}: #{e.message}"
|
||||
exit 1
|
||||
end
|
||||
|
||||
puts <<~HEADER
|
||||
--------------------------------------
|
||||
Proxy configuration
|
||||
--------------------------------------
|
||||
#{options.pretty_inspect.strip}
|
||||
--------------------------------------
|
||||
HEADER
|
||||
|
||||
service = OneGateProxy.new options
|
||||
service.run
|
||||
end
|
||||
Reference in New Issue
Block a user