Merge "Move functions into separate method"
This commit is contained in:
commit
dfbfacef7f
@ -196,6 +196,8 @@ Add DPM-Guest Tools
|
|||||||
|
|
||||||
cp nova-dpm/dpm_guest_tools/usr/lib/systemd/system/autoconfigure_networking.service /usr/lib/systemd/system/autoconfigure_networking.service
|
cp nova-dpm/dpm_guest_tools/usr/lib/systemd/system/autoconfigure_networking.service /usr/lib/systemd/system/autoconfigure_networking.service
|
||||||
|
|
||||||
|
cp nova-dpm/dpm_guest_tools/usr/bin/dpm_guest_image_tools_common /usr/bin/
|
||||||
|
|
||||||
cp nova-dpm/dpm_guest_tools/usr/bin/setmac.sh /usr/bin/setmac.sh
|
cp nova-dpm/dpm_guest_tools/usr/bin/setmac.sh /usr/bin/setmac.sh
|
||||||
|
|
||||||
cp nova-dpm/dpm_guest_tools/etc/udev/rules.d/80-setmac.rules /etc/udev/rules.d/80-setmac.rules
|
cp nova-dpm/dpm_guest_tools/etc/udev/rules.d/80-setmac.rules /etc/udev/rules.d/80-setmac.rules
|
||||||
|
@ -23,10 +23,14 @@
|
|||||||
|
|
||||||
# Exit on error
|
# Exit on error
|
||||||
set -e
|
set -e
|
||||||
|
source $(dirname "$0")/dpm_guest_image_tools_common
|
||||||
|
|
||||||
LOG_PREFIX=$(basename "$0")
|
LOG_PREFIX=$(basename "$0")
|
||||||
REGEX_DEV_NO="[0-9A-Fa-f]{4}"
|
# This script usually gets called by systemd. Systemd takes care of writing
|
||||||
REGEX_MAC="[0-9A-Fa-f]{12}"
|
# stdout and stderr into the journal. Using "echo" here ensures, that
|
||||||
|
# all the messages show up under the corresponding systemd unit and not as
|
||||||
|
# separate entity.
|
||||||
|
LOG_TARGET="stdout"
|
||||||
|
|
||||||
# Regex to match
|
# Regex to match
|
||||||
# <devno>,<port>;
|
# <devno>,<port>;
|
||||||
@ -34,46 +38,7 @@ REGEX_MAC="[0-9A-Fa-f]{12}"
|
|||||||
REGEX="($REGEX_DEV_NO),([0-1])(,$REGEX_MAC)?;"
|
REGEX="($REGEX_DEV_NO),([0-1])(,$REGEX_MAC)?;"
|
||||||
|
|
||||||
#CMDLINE="some stuff 0001,1,000000000011;0004,;0007,0; more stuff"
|
#CMDLINE="some stuff 0001,1,000000000011;0004,;0007,0; more stuff"
|
||||||
CMDLINE=$(cat /proc/cmdline)
|
CMDLINE=$(get_cmdline)
|
||||||
|
|
||||||
function log {
|
|
||||||
# $1 = message to log
|
|
||||||
# This script usually gets called by systemd. Systemd takes care of writing
|
|
||||||
# stdout and stderr into the journal. Using "echo" here ensures, that
|
|
||||||
# all the messages show up under the corresponding systemd unit.
|
|
||||||
echo "$LOG_PREFIX: $1"
|
|
||||||
}
|
|
||||||
|
|
||||||
function get_device_bus_id {
|
|
||||||
# $1 = the device number
|
|
||||||
# returns the corresponding device_bus_id
|
|
||||||
|
|
||||||
echo "0.0.$1"
|
|
||||||
}
|
|
||||||
|
|
||||||
function device_exists {
|
|
||||||
# $1 = the device bus id
|
|
||||||
local dev_bus_id="$1"
|
|
||||||
|
|
||||||
# Check if device is already configured
|
|
||||||
path="/sys/bus/ccwgroup/devices/$dev_bus_id"
|
|
||||||
if ! [ -d "$path" ]; then
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
function configure_device {
|
|
||||||
# $1 = the device bus id
|
|
||||||
# $2 = the port no
|
|
||||||
local dev_bus_id="$1"
|
|
||||||
local port_no="$2"
|
|
||||||
|
|
||||||
# TODO(andreas_s): Do not depend on znetconf
|
|
||||||
# Errors of the following command are written to stderr, and therefore
|
|
||||||
# show up in the systemd units journal
|
|
||||||
znetconf -a $dev_bus_id -o portno=$port_no,layer2=1
|
|
||||||
return "$?"
|
|
||||||
}
|
|
||||||
|
|
||||||
log "Start"
|
log "Start"
|
||||||
|
|
||||||
|
205
guest_image_tools/usr/bin/dpm_guest_image_tools_common
Normal file
205
guest_image_tools/usr/bin/dpm_guest_image_tools_common
Normal file
@ -0,0 +1,205 @@
|
|||||||
|
#! /bin/bash
|
||||||
|
# Copyright 2017 IBM Corp. All Rights Reserved.
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
# Allow caller to define a different folder for the root directory
|
||||||
|
ROOT_DIR=${ROOT_DIR:-}
|
||||||
|
# Allow caller to define a different LOG prefix
|
||||||
|
LOG_PREFIX=${LOG_PREFIX:-"DPM-guest-image-tools"}
|
||||||
|
# Allow caller to define a different LOG target
|
||||||
|
LOG_TARGET=${LOG_TARGET:-"syslog"}
|
||||||
|
|
||||||
|
# Matches MAC in format: xxxxxxxxxxxx
|
||||||
|
REGEX_MAC="[0-9A-Fa-f]{12}"
|
||||||
|
REGEX_DEV_NO="[0-9A-Fa-f]{4}"
|
||||||
|
REGEX_EXTRACT_DEVNO="qeth/0\.0\.($REGEX_DEV_NO)/net"
|
||||||
|
REGEX_EXTRACT_IFNAME="/net/(.{1,15})"
|
||||||
|
|
||||||
|
function log {
|
||||||
|
# $1 = message to log
|
||||||
|
|
||||||
|
local log_msg="$LOG_PREFIX: $1"
|
||||||
|
|
||||||
|
if [[ $LOG_TARGET == "syslog" ]]; then
|
||||||
|
logger $log_msg
|
||||||
|
elif [[ $LOG_TARGET == "stdout" ]]; then
|
||||||
|
echo $log_msg
|
||||||
|
else
|
||||||
|
# Logging disabled
|
||||||
|
:
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function extract_devno {
|
||||||
|
# Extracts the device number out of a device path
|
||||||
|
# $1 = the device path, e.g. "/devices/qeth/0.0.0001/net/enc1"
|
||||||
|
# Returns: device number, e.g. "0001"
|
||||||
|
|
||||||
|
local dev_path="$1"
|
||||||
|
if [[ $dev_path =~ $REGEX_EXTRACT_DEVNO ]]; then
|
||||||
|
echo "${BASH_REMATCH[1]}"
|
||||||
|
else
|
||||||
|
log "Could not extract devno from '$dev_path'. Skipping!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function extract_interface_name {
|
||||||
|
# Extracts the interface name out of a device path
|
||||||
|
# $1 = the device path, e.g. "/devices/qeth/0.0.0001/net/enc1"
|
||||||
|
# Returns: interface name, e.g. "enc1"
|
||||||
|
|
||||||
|
local dev_path="$1"
|
||||||
|
if [[ $dev_path =~ $REGEX_EXTRACT_IFNAME ]]; then
|
||||||
|
echo "${BASH_REMATCH[1]}"
|
||||||
|
else
|
||||||
|
log "Could not find interface for device number '$devno' in path 'dev_path'. Skipping!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function extract_mac {
|
||||||
|
# Get the mac address to a given device number from the cmdline
|
||||||
|
# $1 = the device number, e.g. "0001"
|
||||||
|
# $2 = the cmdline, e.g. "0001,0,aabbccddeeff;"
|
||||||
|
# Returns: The MAC address in format xx:xx:xx:xx:xx:xx
|
||||||
|
|
||||||
|
local devno="$1"
|
||||||
|
local cmdline="$2"
|
||||||
|
# Regex matches: <devno>,<port>,<mac>;
|
||||||
|
regex=${devno}",[0-1],("${REGEX_MAC}");"
|
||||||
|
if [[ $cmdline =~ $regex ]]; then
|
||||||
|
local mac_tmp="${BASH_REMATCH[1]}"
|
||||||
|
# Insert ':' into MAC again
|
||||||
|
echo ${mac_tmp:0:2}:${mac_tmp:2:2}:${mac_tmp:4:2}:${mac_tmp:6:2}:${mac_tmp:8:2}:${mac_tmp:10:2}
|
||||||
|
else
|
||||||
|
log "No MAC for devno '$devno' found in cmdline '$cmdline'. Exit."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function is_locally_administered_mac {
|
||||||
|
# Verifies if a MAC is a locally administered unicast MAC
|
||||||
|
# $1 = MAC, e.g. "00:11:22:33:44:55"
|
||||||
|
# Returns <nothing>
|
||||||
|
# rc 0 = True, rc 1 = False
|
||||||
|
|
||||||
|
local mac="$1"
|
||||||
|
|
||||||
|
# Only Unicast MACs that have the "locally administered" bit set are allowed
|
||||||
|
# by OSA. The "locally administered" bit is the "second least significant"
|
||||||
|
# bit of the most significant MAC byte. In addition only unicast addresses
|
||||||
|
# are allowed. The unicast bit is the least significant bit of the most
|
||||||
|
# significant byte.
|
||||||
|
# Example: AA:BB:CC:DD:EE:FF
|
||||||
|
# Most significant Byte: ^^
|
||||||
|
# In Binary: 1010 1010
|
||||||
|
# Second least significant bit: ^ = locally administered = 1
|
||||||
|
# Least significant bit: ^ = unicast = 0
|
||||||
|
# Therefore the only MACs are allowed, that have the 10 as those 2 bits.
|
||||||
|
# This results in the following possible MACs (where X can be any hex char):
|
||||||
|
# X2:XX:XX:XX:XX:XX
|
||||||
|
# X6:XX:XX:XX:XX:XX
|
||||||
|
# XA:XX:XX:XX:XX:XX
|
||||||
|
# XE:XX:XX:XX:XX:XX
|
||||||
|
local regex="^[0-9A-Fa-f][26AaEe]"
|
||||||
|
if [[ $mac =~ $regex ]]; then
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function get_ip_cmd {
|
||||||
|
# Determines the path of the ip cmd
|
||||||
|
# Returns: Path to ip cmd
|
||||||
|
|
||||||
|
# When this script is called from a udev rule, it is not able to find
|
||||||
|
# the ip command. Also the 'which' command is not working. As different
|
||||||
|
# distros install it to different locations, we need to try out which
|
||||||
|
# path is working.
|
||||||
|
local paths=("/usr/sbin/ip" "/sbin/ip")
|
||||||
|
|
||||||
|
for path in "${paths[@]}"; do
|
||||||
|
local full_path=$ROOT_DIR$path
|
||||||
|
if [[ -x $full_path ]]; then
|
||||||
|
echo "$full_path"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
log "'ip' command not found. Exiting."
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
function set_mac {
|
||||||
|
# This function sets the given MAC on the given interface
|
||||||
|
# $1 = Interface name to set the mac on, e.g. "enc1"
|
||||||
|
# $2 = The mac address, e.g. "00:11:22:33:44:55"
|
||||||
|
|
||||||
|
local if_name="$1"
|
||||||
|
local mac="$2"
|
||||||
|
if ! is_locally_administered_mac "$mac" ; then
|
||||||
|
log "MAC $mac is not a locally administered MAC. Aborting!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
local ip_cmd=$(get_ip_cmd)
|
||||||
|
local cmd="$ip_cmd link set $if_name address $mac 2>&1 > /dev/null"
|
||||||
|
stderr=$(eval "$cmd")
|
||||||
|
local rc=$?
|
||||||
|
if [[ $rc != 0 ]]; then
|
||||||
|
log "Operation '$cmd' failed with exit rc '$rc': $stderr. Aborting!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
log "Successfully set MAC of interface '$if_name' to '$mac'"
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function get_device_bus_id {
|
||||||
|
# $1 = the device number
|
||||||
|
# returns the corresponding device_bus_id
|
||||||
|
|
||||||
|
echo "0.0.$1"
|
||||||
|
}
|
||||||
|
|
||||||
|
function device_exists {
|
||||||
|
# $1 = the device bus id
|
||||||
|
local dev_bus_id="$1"
|
||||||
|
|
||||||
|
# Check if device is already configured
|
||||||
|
path="/sys/bus/ccwgroup/devices/$dev_bus_id"
|
||||||
|
if ! [ -d "$path" ]; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function configure_device {
|
||||||
|
# $1 = the device bus id
|
||||||
|
# $2 = the port no
|
||||||
|
local dev_bus_id="$1"
|
||||||
|
local port_no="$2"
|
||||||
|
|
||||||
|
# TODO(andreas_s): Do not depend on znetconf
|
||||||
|
# Errors of the following command are written to stderr, and therefore
|
||||||
|
# show up in the systemd units journal
|
||||||
|
znetconf -a $dev_bus_id -o portno=$port_no,layer2=1
|
||||||
|
return "$?"
|
||||||
|
}
|
||||||
|
|
||||||
|
function get_cmdline {
|
||||||
|
#Example: "some stuff nics=0001,0,aabbccddeeff;abcd,1,001122334455;"
|
||||||
|
echo $(cat /proc/cmdline)
|
||||||
|
}
|
@ -23,152 +23,10 @@
|
|||||||
|
|
||||||
# Exit on error
|
# Exit on error
|
||||||
set -e
|
set -e
|
||||||
|
source $(dirname "$0")/dpm_guest_image_tools_common
|
||||||
|
|
||||||
# Matches MAC in format: xxxxxxxxxxxx
|
|
||||||
REGEX_MAC="[0-9A-Fa-f]{12}"
|
|
||||||
REGEX_EXTRACT_DEVNO="qeth/0\.0\.([0-9A-Fa-f]{4})/net"
|
|
||||||
REGEX_EXTRACT_IFNAME="/net/(.{1,15})"
|
|
||||||
LOG_PREFIX=$(basename "$0")
|
LOG_PREFIX=$(basename "$0")
|
||||||
|
|
||||||
|
|
||||||
function log {
|
|
||||||
# $1 = message to log
|
|
||||||
|
|
||||||
# Logging to syslog
|
|
||||||
logger "$LOG_PREFIX: $1"
|
|
||||||
}
|
|
||||||
|
|
||||||
function extract_devno {
|
|
||||||
# Extracts the device number out of a device path
|
|
||||||
# $1 = the device path, e.g. "/devices/qeth/0.0.0001/net/enc1"
|
|
||||||
# Returns: device number, e.g. "0001"
|
|
||||||
|
|
||||||
local dev_path="$1"
|
|
||||||
if [[ $dev_path =~ $REGEX_EXTRACT_DEVNO ]]; then
|
|
||||||
echo "${BASH_REMATCH[1]}"
|
|
||||||
else
|
|
||||||
log "Could not extract devno from '$dev_path'. Skipping!"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
function extract_interface_name {
|
|
||||||
# Extracts the interface name out of a device path
|
|
||||||
# $1 = the device path, e.g. "/devices/qeth/0.0.0001/net/enc1"
|
|
||||||
# Returns: interface name, e.g. "enc1"
|
|
||||||
|
|
||||||
local dev_path="$1"
|
|
||||||
if [[ $dev_path =~ $REGEX_EXTRACT_IFNAME ]]; then
|
|
||||||
echo "${BASH_REMATCH[1]}"
|
|
||||||
else
|
|
||||||
log "Could not find interface for device number '$devno' in path 'dev_path'. Skipping!"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function extract_mac {
|
|
||||||
# Get the mac address to a given device number from the cmdline
|
|
||||||
# $1 = the device number, e.g. "0001"
|
|
||||||
# $2 = the cmdline, e.g. "0001,0,aabbccddeeff;"
|
|
||||||
# Returns: The MAC address in format xx:xx:xx:xx:xx:xx
|
|
||||||
|
|
||||||
local devno="$1"
|
|
||||||
local cmdline="$2"
|
|
||||||
# Regex matches: <devno>,<port>,<mac>;
|
|
||||||
regex=${devno}",[0-1],("${REGEX_MAC}");"
|
|
||||||
if [[ $cmdline =~ $regex ]]; then
|
|
||||||
local mac_tmp="${BASH_REMATCH[1]}"
|
|
||||||
# Insert ':' into MAC again
|
|
||||||
echo ${mac_tmp:0:2}:${mac_tmp:2:2}:${mac_tmp:4:2}:${mac_tmp:6:2}:${mac_tmp:8:2}:${mac_tmp:10:2}
|
|
||||||
else
|
|
||||||
log "No MAC for devno '$devno' found in cmdline '$cmdline'. Exit."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
function is_locally_administered_mac {
|
|
||||||
# Verifies if a MAC is a locally administered unicast MAC
|
|
||||||
# $1 = MAC, e.g. "00:11:22:33:44:55"
|
|
||||||
# Returns <nothing>
|
|
||||||
# rc 0 = True, rc 1 = False
|
|
||||||
|
|
||||||
local mac="$1"
|
|
||||||
|
|
||||||
# Only Unicast MACs that have the "locally administered" bit set are allowed
|
|
||||||
# by OSA. The "locally administered" bit is the "second least significant"
|
|
||||||
# bit of the most significant MAC byte. In addition only unicast addresses
|
|
||||||
# are allowed. The unicast bit is the least significant bit of the most
|
|
||||||
# significant byte.
|
|
||||||
# Example: AA:BB:CC:DD:EE:FF
|
|
||||||
# Most significant Byte: ^^
|
|
||||||
# In Binary: 1010 1010
|
|
||||||
# Second least significant bit: ^ = locally administered = 1
|
|
||||||
# Least significant bit: ^ = unicast = 0
|
|
||||||
# Therefore the only MACs are allowed, that have the 10 as those 2 bits.
|
|
||||||
# This results in the following possible MACs (where X can be any hex char):
|
|
||||||
# X2:XX:XX:XX:XX:XX
|
|
||||||
# X6:XX:XX:XX:XX:XX
|
|
||||||
# XA:XX:XX:XX:XX:XX
|
|
||||||
# XE:XX:XX:XX:XX:XX
|
|
||||||
local regex="^[0-9A-Fa-f][26AaEe]"
|
|
||||||
if [[ $mac =~ $regex ]]; then
|
|
||||||
return 0
|
|
||||||
else
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
function get_ip_cmd {
|
|
||||||
# Determines the path of the ip cmd
|
|
||||||
# Returns: Path to ip cmd
|
|
||||||
|
|
||||||
# When this script is called from a udev rule, it is not able to find
|
|
||||||
# the ip command. Also the 'which' command is not working. As different
|
|
||||||
# distros install it to different locations, we need to try out which
|
|
||||||
# path is working.
|
|
||||||
local paths=("/usr/sbin/ip" "/sbin/ip")
|
|
||||||
|
|
||||||
for path in "${paths[@]}"; do
|
|
||||||
if [[ -x $path ]]; then
|
|
||||||
echo "$path"
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
log "'ip' command not found. Exiting."
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
function set_mac {
|
|
||||||
# This function sets the given MAC on the given interface
|
|
||||||
# $1 = Interface name to set the mac on, e.g. "enc1"
|
|
||||||
# $2 = The mac address, e.g. "00:11:22:33:44:55"
|
|
||||||
|
|
||||||
local if_name="$1"
|
|
||||||
local mac="$2"
|
|
||||||
if ! is_locally_administered_mac "$mac" ; then
|
|
||||||
log "MAC $mac is not a locally administered MAC. Aborting!"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
local ip_cmd=$(get_ip_cmd)
|
|
||||||
local cmd="$ip_cmd link set $if_name address $mac 2>&1 > /dev/null"
|
|
||||||
stderr=$(eval "$cmd")
|
|
||||||
local rc=$?
|
|
||||||
if [[ $rc != 0 ]]; then
|
|
||||||
log "Operation '$cmd' failed with exit rc '$rc': $stderr. Aborting!"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
log "Successfully set MAC of interface '$if_name' to '$mac'"
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function get_cmdline {
|
|
||||||
#Example: "some stuff nics=0001,0,aabbccddeeff;abcd,1,001122334455;"
|
|
||||||
echo $(cat /proc/cmdline)
|
|
||||||
}
|
|
||||||
|
|
||||||
# e.g. /devices/qeth/0.0.0001/net/enc1
|
# e.g. /devices/qeth/0.0.0001/net/enc1
|
||||||
DEV_PATH="$1"
|
DEV_PATH="$1"
|
||||||
CMDLINE=$(get_cmdline)
|
CMDLINE=$(get_cmdline)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user