Integration testing preparation for Ironic
Add ability to create/register qemu vms for Ironic testing purposes Implements bp:deprecate-baremetal-driver Change-Id: If452438fcc0ff562531b33a36cd189b235654b48
This commit is contained in:
parent
1fef36e526
commit
06fb29c661
@ -24,10 +24,17 @@ if is_service_enabled ir-api ir-cond; then
|
|||||||
# Start the ironic API and ironic taskmgr components
|
# Start the ironic API and ironic taskmgr components
|
||||||
echo_summary "Starting Ironic"
|
echo_summary "Starting Ironic"
|
||||||
start_ironic
|
start_ironic
|
||||||
|
|
||||||
|
if [[ "$IRONIC_BAREMETAL_BASIC_OPS" = "True" ]]; then
|
||||||
|
prepare_baremetal_basic_ops
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "$1" == "unstack" ]]; then
|
if [[ "$1" == "unstack" ]]; then
|
||||||
stop_ironic
|
stop_ironic
|
||||||
|
if [[ "$IRONIC_BAREMETAL_BASIC_OPS" = "True" ]]; then
|
||||||
|
cleanup_baremetal_basic_ops
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "$1" == "clean" ]]; then
|
if [[ "$1" == "clean" ]]; then
|
||||||
|
10
files/apts/ironic
Normal file
10
files/apts/ironic
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
libguestfs0
|
||||||
|
libvirt-bin
|
||||||
|
openssh-client
|
||||||
|
openvswitch-switch
|
||||||
|
openvswitch-datapath-dkms
|
||||||
|
python-libguestfs
|
||||||
|
python-libvirt
|
||||||
|
syslinux
|
||||||
|
tftpd-hpa
|
||||||
|
xinetd
|
9
files/rpms/ironic
Normal file
9
files/rpms/ironic
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
libguestfs
|
||||||
|
libvirt
|
||||||
|
libvirt-python
|
||||||
|
openssh-clients
|
||||||
|
openvswitch
|
||||||
|
python-libguestfs
|
||||||
|
syslinux
|
||||||
|
tftp-server
|
||||||
|
xinetd
|
@ -140,7 +140,10 @@ BM_DEPLOY_KERNEL=${BM_DEPLOY_KERNEL:-}
|
|||||||
|
|
||||||
# If you need to add any extra flavors to the deploy ramdisk image
|
# If you need to add any extra flavors to the deploy ramdisk image
|
||||||
# eg, specific network drivers, specify them here
|
# eg, specific network drivers, specify them here
|
||||||
BM_DEPLOY_FLAVOR=${BM_DEPLOY_FLAVOR:-}
|
#
|
||||||
|
# NOTE(deva): this will be moved to lib/ironic in a future patch
|
||||||
|
# for now, set the default to a suitable value for Ironic's needs
|
||||||
|
BM_DEPLOY_FLAVOR=${BM_DEPLOY_FLAVOR:--a amd64 ubuntu deploy-ironic}
|
||||||
|
|
||||||
# set URL and version for google shell-in-a-box
|
# set URL and version for google shell-in-a-box
|
||||||
BM_SHELL_IN_A_BOX=${BM_SHELL_IN_A_BOX:-http://shellinabox.googlecode.com/files/shellinabox-2.14.tar.gz}
|
BM_SHELL_IN_A_BOX=${BM_SHELL_IN_A_BOX:-http://shellinabox.googlecode.com/files/shellinabox-2.14.tar.gz}
|
||||||
@ -220,7 +223,7 @@ function upload_baremetal_deploy {
|
|||||||
BM_DEPLOY_KERNEL=bm-deploy.kernel
|
BM_DEPLOY_KERNEL=bm-deploy.kernel
|
||||||
BM_DEPLOY_RAMDISK=bm-deploy.initramfs
|
BM_DEPLOY_RAMDISK=bm-deploy.initramfs
|
||||||
if [ ! -e "$TOP_DIR/files/$BM_DEPLOY_KERNEL" -o ! -e "$TOP_DIR/files/$BM_DEPLOY_RAMDISK" ]; then
|
if [ ! -e "$TOP_DIR/files/$BM_DEPLOY_KERNEL" -o ! -e "$TOP_DIR/files/$BM_DEPLOY_RAMDISK" ]; then
|
||||||
$BM_IMAGE_BUILD_DIR/bin/ramdisk-image-create $BM_DEPLOY_FLAVOR deploy \
|
$BM_IMAGE_BUILD_DIR/bin/ramdisk-image-create $BM_DEPLOY_FLAVOR \
|
||||||
-o $TOP_DIR/files/bm-deploy
|
-o $TOP_DIR/files/bm-deploy
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
265
lib/ironic
265
lib/ironic
@ -18,16 +18,19 @@
|
|||||||
# - stop_ironic
|
# - stop_ironic
|
||||||
# - cleanup_ironic
|
# - cleanup_ironic
|
||||||
|
|
||||||
# Save trace setting
|
# Save trace and pipefail settings
|
||||||
XTRACE=$(set +o | grep xtrace)
|
XTRACE=$(set +o | grep xtrace)
|
||||||
|
PIPEFAIL=$(set +o | grep pipefail)
|
||||||
set +o xtrace
|
set +o xtrace
|
||||||
|
set +o pipefail
|
||||||
|
|
||||||
# Defaults
|
# Defaults
|
||||||
# --------
|
# --------
|
||||||
|
|
||||||
# Set up default directories
|
# Set up default directories
|
||||||
IRONIC_DIR=$DEST/ironic
|
IRONIC_DIR=$DEST/ironic
|
||||||
|
IRONIC_DATA_DIR=$DATA_DIR/ironic
|
||||||
|
IRONIC_STATE_PATH=/var/lib/ironic
|
||||||
IRONICCLIENT_DIR=$DEST/python-ironicclient
|
IRONICCLIENT_DIR=$DEST/python-ironicclient
|
||||||
IRONIC_AUTH_CACHE_DIR=${IRONIC_AUTH_CACHE_DIR:-/var/cache/ironic}
|
IRONIC_AUTH_CACHE_DIR=${IRONIC_AUTH_CACHE_DIR:-/var/cache/ironic}
|
||||||
IRONIC_CONF_DIR=${IRONIC_CONF_DIR:-/etc/ironic}
|
IRONIC_CONF_DIR=${IRONIC_CONF_DIR:-/etc/ironic}
|
||||||
@ -35,6 +38,28 @@ IRONIC_CONF_FILE=$IRONIC_CONF_DIR/ironic.conf
|
|||||||
IRONIC_ROOTWRAP_CONF=$IRONIC_CONF_DIR/rootwrap.conf
|
IRONIC_ROOTWRAP_CONF=$IRONIC_CONF_DIR/rootwrap.conf
|
||||||
IRONIC_POLICY_JSON=$IRONIC_CONF_DIR/policy.json
|
IRONIC_POLICY_JSON=$IRONIC_CONF_DIR/policy.json
|
||||||
|
|
||||||
|
# Set up defaults for functional / integration testing
|
||||||
|
IRONIC_SCRIPTS_DIR=${IRONIC_SCRIPTS_DIR:-$TOP_DIR/tools/ironic/scripts}
|
||||||
|
IRONIC_TEMPLATES_DIR=${IRONIC_TEMPLATES_DIR:-$TOP_DIR/tools/ironic/templates}
|
||||||
|
IRONIC_BAREMETAL_BASIC_OPS=$(trueorfalse False $IRONIC_BAREMETAL_BASIC_OPS)
|
||||||
|
IRONIC_SSH_USERNAME=${IRONIC_SSH_USERNAME:-`whoami`}
|
||||||
|
IRONIC_SSH_KEY_DIR=${IRONIC_SSH_KEY_DIR:-$IRONIC_DATA_DIR/ssh_keys}
|
||||||
|
IRONIC_SSH_KEY_FILENAME=${IRONIC_SSH_KEY_FILENAME:-ironic_key}
|
||||||
|
IRONIC_KEY_FILE=$IRONIC_SSH_KEY_DIR/$IRONIC_SSH_KEY_FILENAME
|
||||||
|
IRONIC_SSH_VIRT_TYPE=${IRONIC_SSH_VIRT_TYPE:-virsh}
|
||||||
|
IRONIC_TFTPBOOT_DIR=${IRONIC_TFTPBOOT_DIR:-$IRONIC_DATA_DIR/tftpboot}
|
||||||
|
IRONIC_VM_SSH_PORT=${IRONIC_VM_SSH_PORT:-2222}
|
||||||
|
IRONIC_VM_SSH_ADDRESS=${IRONIC_VM_SSH_ADDRESS:-$HOST_IP}
|
||||||
|
IRONIC_VM_COUNT=${IRONIC_VM_COUNT:-1}
|
||||||
|
IRONIC_VM_SPECS_CPU=${IRONIC_VM_SPECS_CPU:-1}
|
||||||
|
IRONIC_VM_SPECS_RAM=${IRONIC_VM_SPECS_RAM:-256}
|
||||||
|
IRONIC_VM_SPECS_DISK=${IRONIC_VM_SPECS_DISK:-10}
|
||||||
|
IRONIC_VM_EMULATOR=${IRONIC_VM_EMULATOR:-/usr/bin/qemu-system-x86_64}
|
||||||
|
IRONIC_VM_NETWORK_BRIDGE=${IRONIC_VM_NETWORK_BRIDGE:-brbm}
|
||||||
|
IRONIC_VM_NETWORK_RANGE=${IRONIC_VM_NETWORK_RANGE:-192.0.2.0/24}
|
||||||
|
IRONIC_VM_MACS_CSV_FILE=${IRONIC_VM_MACS_CSV_FILE:-$IRONIC_DATA_DIR/ironic_macs.csv}
|
||||||
|
IRONIC_AUTHORIZED_KEYS_FILE=${IRONIC_AUTHORIZED_KEYS_FILE:-$HOME/.ssh/authorized_keys}
|
||||||
|
|
||||||
# Support entry points installation of console scripts
|
# Support entry points installation of console scripts
|
||||||
IRONIC_BIN_DIR=$(get_python_exec_prefix)
|
IRONIC_BIN_DIR=$(get_python_exec_prefix)
|
||||||
|
|
||||||
@ -86,8 +111,8 @@ function configure_ironic {
|
|||||||
iniset $IRONIC_CONF_FILE DEFAULT debug True
|
iniset $IRONIC_CONF_FILE DEFAULT debug True
|
||||||
inicomment $IRONIC_CONF_FILE DEFAULT log_file
|
inicomment $IRONIC_CONF_FILE DEFAULT log_file
|
||||||
iniset $IRONIC_CONF_FILE DEFAULT sql_connection `database_connection_url ironic`
|
iniset $IRONIC_CONF_FILE DEFAULT sql_connection `database_connection_url ironic`
|
||||||
|
iniset $IRONIC_CONF_FILE DEFAULT state_path $IRONIC_STATE_PATH
|
||||||
iniset $IRONIC_CONF_FILE DEFAULT use_syslog $SYSLOG
|
iniset $IRONIC_CONF_FILE DEFAULT use_syslog $SYSLOG
|
||||||
|
|
||||||
# Configure Ironic conductor, if it was enabled.
|
# Configure Ironic conductor, if it was enabled.
|
||||||
if is_service_enabled ir-cond; then
|
if is_service_enabled ir-cond; then
|
||||||
configure_ironic_conductor
|
configure_ironic_conductor
|
||||||
@ -97,6 +122,10 @@ function configure_ironic {
|
|||||||
if is_service_enabled ir-api; then
|
if is_service_enabled ir-api; then
|
||||||
configure_ironic_api
|
configure_ironic_api
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [[ "$IRONIC_BAREMETAL_BASIC_OPS" == "True" ]]; then
|
||||||
|
configure_ironic_auxiliary
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# configure_ironic_api() - Is used by configure_ironic(). Performs
|
# configure_ironic_api() - Is used by configure_ironic(). Performs
|
||||||
@ -125,6 +154,10 @@ function configure_ironic_conductor {
|
|||||||
cp -r $IRONIC_DIR/etc/ironic/rootwrap.d $IRONIC_CONF_DIR
|
cp -r $IRONIC_DIR/etc/ironic/rootwrap.d $IRONIC_CONF_DIR
|
||||||
|
|
||||||
iniset $IRONIC_CONF_FILE DEFAULT rootwrap_config $IRONIC_ROOTWRAP_CONF
|
iniset $IRONIC_CONF_FILE DEFAULT rootwrap_config $IRONIC_ROOTWRAP_CONF
|
||||||
|
iniset $IRONIC_CONF_FILE conductor api_url http://$SERVICE_HOST:6385
|
||||||
|
iniset $IRONIC_CONF_FILE pxe tftp_server $SERVICE_HOST
|
||||||
|
iniset $IRONIC_CONF_FILE pxe tftp_root $IRONIC_TFTPBOOT_DIR
|
||||||
|
iniset $IRONIC_CONF_FILE pxe tftp_master_path $IRONIC_TFTPBOOT_DIR/master_images
|
||||||
}
|
}
|
||||||
|
|
||||||
# create_ironic_cache_dir() - Part of the init_ironic() process
|
# create_ironic_cache_dir() - Part of the init_ironic() process
|
||||||
@ -225,9 +258,233 @@ function stop_ironic {
|
|||||||
screen -S $SCREEN_NAME -p ir-cond -X kill
|
screen -S $SCREEN_NAME -p ir-cond -X kill
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function is_ironic {
|
||||||
|
if ( is_service_enabled ir-cond && is_service_enabled ir-api ); then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
# Restore xtrace
|
function configure_ironic_dirs {
|
||||||
|
sudo mkdir -p $IRONIC_DATA_DIR
|
||||||
|
sudo mkdir -p $IRONIC_STATE_PATH
|
||||||
|
sudo mkdir -p $IRONIC_TFTPBOOT_DIR
|
||||||
|
sudo chown -R $STACK_USER $IRONIC_DATA_DIR $IRONIC_STATE_PATH
|
||||||
|
sudo chown -R $STACK_USER:$LIBVIRT_GROUP $IRONIC_TFTPBOOT_DIR
|
||||||
|
if is_ubuntu; then
|
||||||
|
PXEBIN=/usr/lib/syslinux/pxelinux.0
|
||||||
|
elif is_fedora; then
|
||||||
|
PXEBIN=/usr/share/syslinux/pxelinux.0
|
||||||
|
fi
|
||||||
|
if [ ! -f $PXEBIN ]; then
|
||||||
|
die $LINENO "pxelinux.0 (from SYSLINUX) not found."
|
||||||
|
fi
|
||||||
|
|
||||||
|
cp $PXEBIN $IRONIC_TFTPBOOT_DIR
|
||||||
|
mkdir -p $IRONIC_TFTPBOOT_DIR/pxelinux.cfg
|
||||||
|
}
|
||||||
|
|
||||||
|
function ironic_ensure_libvirt_group {
|
||||||
|
groups $STACK_USER | grep -q $LIBVIRT_GROUP || adduser $STACK_USER $LIBVIRT_GROUP
|
||||||
|
}
|
||||||
|
|
||||||
|
function create_bridge_and_vms {
|
||||||
|
ironic_ensure_libvirt_group
|
||||||
|
|
||||||
|
# Call libvirt setup scripts in a new shell to ensure any new group membership
|
||||||
|
sudo su $STACK_USER -c "$IRONIC_SCRIPTS_DIR/setup-network"
|
||||||
|
|
||||||
|
sudo su $STACK_USER -c "$IRONIC_SCRIPTS_DIR/create-nodes \
|
||||||
|
$IRONIC_VM_SPECS_CPU $IRONIC_VM_SPECS_RAM $IRONIC_VM_SPECS_DISK \
|
||||||
|
amd64 $IRONIC_VM_COUNT $IRONIC_VM_NETWORK_BRIDGE $IRONIC_VM_EMULATOR" >> $IRONIC_VM_MACS_CSV_FILE
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function enroll_vms {
|
||||||
|
|
||||||
|
CHASSIS_ID=$(ironic chassis-create -d "ironic test chassis" | grep " uuid " | get_field 2)
|
||||||
|
IRONIC_NET_ID=$(neutron net-list | grep private | get_field 1)
|
||||||
|
local idx=0
|
||||||
|
|
||||||
|
# work around; need to know what netns neutron uses for private network
|
||||||
|
neutron port-create private
|
||||||
|
|
||||||
|
while read MAC; do
|
||||||
|
|
||||||
|
NODE_ID=$(ironic node-create --chassis_uuid $CHASSIS_ID --driver pxe_ssh \
|
||||||
|
-i ssh_virt_type=$IRONIC_SSH_VIRT_TYPE \
|
||||||
|
-i ssh_address=$IRONIC_VM_SSH_ADDRESS \
|
||||||
|
-i ssh_port=$IRONIC_VM_SSH_PORT \
|
||||||
|
-i ssh_username=$IRONIC_SSH_USERNAME \
|
||||||
|
-i ssh_key_filename=$IRONIC_SSH_KEY_DIR/$IRONIC_SSH_KEY_FILENAME \
|
||||||
|
-p cpus=$IRONIC_VM_SPECS_CPU \
|
||||||
|
-p memory_mb=$IRONIC_VM_SPECS_RAM \
|
||||||
|
-p local_gb=$IRONIC_VM_SPECS_DISK \
|
||||||
|
-p cpu_arch=x86_64 \
|
||||||
|
| grep " uuid " | get_field 2)
|
||||||
|
|
||||||
|
ironic port-create --address $MAC --node_uuid $NODE_ID
|
||||||
|
|
||||||
|
idx=$((idx+1))
|
||||||
|
|
||||||
|
done < $IRONIC_VM_MACS_CSV_FILE
|
||||||
|
|
||||||
|
# create the nova flavor
|
||||||
|
nova flavor-create baremetal auto $IRONIC_VM_SPECS_RAM $IRONIC_VM_SPECS_DISK $IRONIC_VM_SPECS_CPU
|
||||||
|
nova flavor-key baremetal set "cpu_arch"="x86_64" "baremetal:deploy_kernel_id"="$BM_DEPLOY_KERNEL_ID" "baremetal:deploy_ramdisk_id"="$BM_DEPLOY_RAMDISK_ID"
|
||||||
|
|
||||||
|
# intentional sleep to make sure the tag has been set to port
|
||||||
|
sleep 10
|
||||||
|
TAPDEV=$(sudo ip netns exec qdhcp-${IRONIC_NET_ID} ip link list | grep tap | cut -d':' -f2 | cut -b2-)
|
||||||
|
TAG_ID=$(sudo ovs-vsctl show |grep ${TAPDEV} -A1 -m1 | grep tag | cut -d':' -f2 | cut -b2-)
|
||||||
|
|
||||||
|
# make sure veth pair is not existing, otherwise delete its links
|
||||||
|
sudo ip link show ovs-tap1 && sudo ip link delete ovs-tap1
|
||||||
|
sudo ip link show brbm-tap1 && sudo ip link delete brbm-tap1
|
||||||
|
# create veth pair for future interconnection between br-int and brbm
|
||||||
|
sudo ip link add brbm-tap1 type veth peer name ovs-tap1
|
||||||
|
sudo ip link set dev brbm-tap1 up
|
||||||
|
sudo ip link set dev ovs-tap1 up
|
||||||
|
|
||||||
|
sudo ovs-vsctl -- --if-exists del-port ovs-tap1 -- add-port br-int ovs-tap1 tag=$TAG_ID
|
||||||
|
sudo ovs-vsctl -- --if-exists del-port brbm-tap1 -- add-port $IRONIC_VM_NETWORK_BRIDGE brbm-tap1
|
||||||
|
}
|
||||||
|
|
||||||
|
function configure_tftpd {
|
||||||
|
# enable tftp natting for allowing connections to SERVICE_HOST's tftp server
|
||||||
|
sudo modprobe nf_conntrack_tftp
|
||||||
|
sudo modprobe nf_nat_tftp
|
||||||
|
|
||||||
|
if is_ubuntu; then
|
||||||
|
PXEBIN=/usr/lib/syslinux/pxelinux.0
|
||||||
|
elif is_fedora; then
|
||||||
|
PXEBIN=/usr/share/syslinux/pxelinux.0
|
||||||
|
fi
|
||||||
|
if [ ! -f $PXEBIN ]; then
|
||||||
|
die $LINENO "pxelinux.0 (from SYSLINUX) not found."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# stop tftpd and setup serving via xinetd
|
||||||
|
stop_service tftpd-hpa || true
|
||||||
|
[ -f /etc/init/tftpd-hpa.conf ] && echo "manual" | sudo tee /etc/init/tftpd-hpa.override
|
||||||
|
sudo cp $IRONIC_TEMPLATES_DIR/tftpd-xinetd.template /etc/xinetd.d/tftp
|
||||||
|
sudo sed -e "s|%TFTPBOOT_DIR%|$IRONIC_TFTPBOOT_DIR|g" -i /etc/xinetd.d/tftp
|
||||||
|
|
||||||
|
# setup tftp file mapping to satisfy requests at the root (booting) and
|
||||||
|
# /tftpboot/ sub-dir (as per deploy-ironic elements)
|
||||||
|
echo "r ^([^/]) $IRONIC_TFTPBOOT_DIR/\1" >$IRONIC_TFTPBOOT_DIR/map-file
|
||||||
|
echo "r ^(/tftpboot/) $IRONIC_TFTPBOOT_DIR/\2" >>$IRONIC_TFTPBOOT_DIR/map-file
|
||||||
|
|
||||||
|
chmod -R 0755 $IRONIC_TFTPBOOT_DIR
|
||||||
|
restart_service xinetd
|
||||||
|
}
|
||||||
|
|
||||||
|
function configure_ironic_ssh_keypair {
|
||||||
|
# Generating ssh key pair for stack user
|
||||||
|
if [[ ! -d $IRONIC_SSH_KEY_DIR ]]; then
|
||||||
|
mkdir -p $IRONIC_SSH_KEY_DIR
|
||||||
|
fi
|
||||||
|
if [[ ! -d $HOME/.ssh ]]; then
|
||||||
|
mkdir -p $HOME/.ssh
|
||||||
|
chmod 700 $HOME/.ssh
|
||||||
|
fi
|
||||||
|
echo -e 'n\n' | ssh-keygen -q -t rsa -P '' -f $IRONIC_KEY_FILE
|
||||||
|
cat $IRONIC_KEY_FILE.pub | tee -a $IRONIC_AUTHORIZED_KEYS_FILE
|
||||||
|
}
|
||||||
|
|
||||||
|
function ironic_ssh_check {
|
||||||
|
local KEY_FILE=$1
|
||||||
|
local FLOATING_IP=$2
|
||||||
|
local PORT=$3
|
||||||
|
local DEFAULT_INSTANCE_USER=$4
|
||||||
|
local ACTIVE_TIMEOUT=$5
|
||||||
|
if ! timeout $ACTIVE_TIMEOUT sh -c "while ! ssh -p $PORT -o StrictHostKeyChecking=no -i $KEY_FILE ${DEFAULT_INSTANCE_USER}@$FLOATING_IP echo success; do sleep 1; done"; then
|
||||||
|
die $LINENO "server didn't become ssh-able!"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function configure_ironic_sshd {
|
||||||
|
# Ensure sshd server accepts connections from localhost only
|
||||||
|
|
||||||
|
SSH_CONFIG=/etc/ssh/sshd_config
|
||||||
|
HOST_PORT=$IRONIC_VM_SSH_ADDRESS:$IRONIC_VM_SSH_PORT
|
||||||
|
if ! sudo grep ListenAddress $SSH_CONFIG | grep $HOST_PORT; then
|
||||||
|
echo "ListenAddress $HOST_PORT" | sudo tee -a $SSH_CONFIG
|
||||||
|
fi
|
||||||
|
|
||||||
|
SSH_SERVICE_NAME=sshd
|
||||||
|
if is_ubuntu; then
|
||||||
|
SSH_SERVICE_NAME=ssh
|
||||||
|
fi
|
||||||
|
|
||||||
|
restart_service $SSH_SERVICE_NAME
|
||||||
|
# to ensure ssh service is up and running
|
||||||
|
sleep 3
|
||||||
|
ironic_ssh_check $IRONIC_SSH_KEY_DIR/$IRONIC_SSH_KEY_FILENAME $IRONIC_VM_SSH_ADDRESS $IRONIC_VM_SSH_PORT $IRONIC_SSH_USERNAME 10
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function configure_ironic_auxiliary {
|
||||||
|
configure_ironic_dirs
|
||||||
|
configure_ironic_ssh_keypair
|
||||||
|
configure_ironic_sshd
|
||||||
|
}
|
||||||
|
|
||||||
|
function prepare_baremetal_basic_ops {
|
||||||
|
|
||||||
|
# install diskimage-builder
|
||||||
|
git_clone $BM_IMAGE_BUILD_REPO $BM_IMAGE_BUILD_DIR $BM_IMAGE_BUILD_BRANCH
|
||||||
|
|
||||||
|
# make sure all needed service were enabled
|
||||||
|
for srv in nova glance key neutron; do
|
||||||
|
if ! is_service_enabled "$srv"; then
|
||||||
|
die $LINENO "$srv should be enabled for ironic tests"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
SCREEN_NAME=${SCREEN_NAME:-stack}
|
||||||
|
SERVICE_DIR=${SERVICE_DIR:-${DEST}/status}
|
||||||
|
|
||||||
|
# stop all nova services
|
||||||
|
stop_nova || true
|
||||||
|
|
||||||
|
# remove any nova services failure status
|
||||||
|
find $SERVICE_DIR/$SCREEN_NAME -name 'n-*.failure' -exec rm -f '{}' \;
|
||||||
|
|
||||||
|
# start them again
|
||||||
|
start_nova_api
|
||||||
|
start_nova
|
||||||
|
|
||||||
|
TOKEN=$(keystone token-get | grep ' id ' | get_field 2)
|
||||||
|
die_if_not_set $LINENO TOKEN "Keystone fail to get token"
|
||||||
|
|
||||||
|
echo_summary "Creating and uploading baremetal images for ironic"
|
||||||
|
|
||||||
|
# build and upload separate deploy kernel & ramdisk
|
||||||
|
upload_baremetal_deploy $TOKEN
|
||||||
|
|
||||||
|
create_bridge_and_vms
|
||||||
|
enroll_vms
|
||||||
|
configure_tftpd
|
||||||
|
}
|
||||||
|
|
||||||
|
function cleanup_baremetal_basic_ops {
|
||||||
|
rm -f $IRONIC_VM_MACS_CSV_FILE
|
||||||
|
if [ -f $IRONIC_KEY_FILE ]; then
|
||||||
|
KEY=`cat $IRONIC_KEY_FILE.pub`
|
||||||
|
# remove public key from authorized_keys
|
||||||
|
grep -v "$KEY" $IRONIC_AUTHORIZED_KEYS_FILE > temp && mv temp $IRONIC_AUTHORIZED_KEYS_FILE
|
||||||
|
chmod 0600 $IRONIC_AUTHORIZED_KEYS_FILE
|
||||||
|
fi
|
||||||
|
sudo rm -rf $IRONIC_DATA_DIR $IRONIC_STATE_PATH
|
||||||
|
sudo su $STACK_USER -c "$IRONIC_SCRIPTS_DIR/cleanup-nodes $IRONIC_VM_COUNT $IRONIC_VM_NETWORK_BRIDGE"
|
||||||
|
sudo rm -rf /etc/xinetd.d/tftp /etc/init/tftpd-hpa.override
|
||||||
|
restart_service xinetd
|
||||||
|
}
|
||||||
|
|
||||||
|
# Restore xtrace + pipefail
|
||||||
$XTRACE
|
$XTRACE
|
||||||
|
$PIPEFAIL
|
||||||
|
|
||||||
# Tell emacs to use shell-script-mode
|
# Tell emacs to use shell-script-mode
|
||||||
## Local variables:
|
## Local variables:
|
||||||
|
75
lib/nova_plugins/hypervisor-ironic
Normal file
75
lib/nova_plugins/hypervisor-ironic
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
# lib/nova_plugins/hypervisor-ironic
|
||||||
|
# Configure the ironic hypervisor
|
||||||
|
|
||||||
|
# Enable with:
|
||||||
|
# VIRT_DRIVER=ironic
|
||||||
|
|
||||||
|
# Dependencies:
|
||||||
|
# ``functions`` file
|
||||||
|
# ``nova`` configuration
|
||||||
|
|
||||||
|
# install_nova_hypervisor - install any external requirements
|
||||||
|
# configure_nova_hypervisor - make configuration changes, including those to other services
|
||||||
|
# start_nova_hypervisor - start any external services
|
||||||
|
# stop_nova_hypervisor - stop any external services
|
||||||
|
# cleanup_nova_hypervisor - remove transient data and cache
|
||||||
|
|
||||||
|
# Save trace setting
|
||||||
|
MY_XTRACE=$(set +o | grep xtrace)
|
||||||
|
set +o xtrace
|
||||||
|
|
||||||
|
|
||||||
|
# Defaults
|
||||||
|
# --------
|
||||||
|
|
||||||
|
# Entry Points
|
||||||
|
# ------------
|
||||||
|
|
||||||
|
# clean_nova_hypervisor - Clean up an installation
|
||||||
|
function cleanup_nova_hypervisor {
|
||||||
|
# This function intentionally left blank
|
||||||
|
:
|
||||||
|
}
|
||||||
|
|
||||||
|
# configure_nova_hypervisor - Set config files, create data dirs, etc
|
||||||
|
function configure_nova_hypervisor {
|
||||||
|
iniset $NOVA_CONF ironic sql_connection `database_connection_url nova_bm`
|
||||||
|
LIBVIRT_FIREWALL_DRIVER=${LIBVIRT_FIREWALL_DRIVER:-"nova.virt.firewall.NoopFirewallDriver"}
|
||||||
|
iniset $NOVA_CONF DEFAULT compute_driver ironic.nova.virt.ironic.IronicDriver
|
||||||
|
iniset $NOVA_CONF DEFAULT firewall_driver $LIBVIRT_FIREWALL_DRIVER
|
||||||
|
iniset $NOVA_CONF DEFAULT scheduler_host_manager ironic.nova.scheduler.ironic_host_manager.IronicHostManager
|
||||||
|
iniset $NOVA_CONF DEFAULT ram_allocation_ratio 1.0
|
||||||
|
iniset $NOVA_CONF DEFAULT reserved_host_memory_mb 0
|
||||||
|
# ironic section
|
||||||
|
iniset $NOVA_CONF ironic admin_username admin
|
||||||
|
iniset $NOVA_CONF ironic admin_password $ADMIN_PASSWORD
|
||||||
|
iniset $NOVA_CONF ironic admin_url $KEYSTONE_AUTH_PROTOCOL://$KEYSTONE_AUTH_HOST:$KEYSTONE_AUTH_PORT/v2.0
|
||||||
|
iniset $NOVA_CONF ironic admin_tenant_name demo
|
||||||
|
iniset $NOVA_CONF ironic api_endpoint http://$SERVICE_HOST:6358/v1
|
||||||
|
}
|
||||||
|
|
||||||
|
# install_nova_hypervisor() - Install external components
|
||||||
|
function install_nova_hypervisor {
|
||||||
|
# This function intentionally left blank
|
||||||
|
:
|
||||||
|
}
|
||||||
|
|
||||||
|
# start_nova_hypervisor - Start any required external services
|
||||||
|
function start_nova_hypervisor {
|
||||||
|
# This function intentionally left blank
|
||||||
|
:
|
||||||
|
}
|
||||||
|
|
||||||
|
# stop_nova_hypervisor - Stop any external services
|
||||||
|
function stop_nova_hypervisor {
|
||||||
|
# This function intentionally left blank
|
||||||
|
:
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# Restore xtrace
|
||||||
|
$MY_XTRACE
|
||||||
|
|
||||||
|
# Local variables:
|
||||||
|
# mode: shell-script
|
||||||
|
# End:
|
2
stackrc
2
stackrc
@ -267,7 +267,7 @@ DEFAULT_VIRT_DRIVER=libvirt
|
|||||||
is_package_installed xenserver-core && DEFAULT_VIRT_DRIVER=xenserver
|
is_package_installed xenserver-core && DEFAULT_VIRT_DRIVER=xenserver
|
||||||
VIRT_DRIVER=${VIRT_DRIVER:-$DEFAULT_VIRT_DRIVER}
|
VIRT_DRIVER=${VIRT_DRIVER:-$DEFAULT_VIRT_DRIVER}
|
||||||
case "$VIRT_DRIVER" in
|
case "$VIRT_DRIVER" in
|
||||||
libvirt)
|
ironic|libvirt)
|
||||||
LIBVIRT_TYPE=${LIBVIRT_TYPE:-kvm}
|
LIBVIRT_TYPE=${LIBVIRT_TYPE:-kvm}
|
||||||
if [[ "$os_VENDOR" =~ (Debian) ]]; then
|
if [[ "$os_VENDOR" =~ (Debian) ]]; then
|
||||||
LIBVIRT_GROUP=libvirt
|
LIBVIRT_GROUP=libvirt
|
||||||
|
@ -55,7 +55,13 @@ export_proxy_variables
|
|||||||
# ================
|
# ================
|
||||||
|
|
||||||
# Install package requirements
|
# Install package requirements
|
||||||
install_package $(get_packages general $ENABLED_SERVICES)
|
PACKAGES=$(get_packages general $ENABLED_SERVICES)
|
||||||
|
if is_ubuntu && echo $PACKAGES | grep -q dkms ; then
|
||||||
|
# ensure headers for the running kernel are installed for any DKMS builds
|
||||||
|
PACKAGES="$PACKAGES linux-headers-$(uname -r)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
install_package $PACKAGES
|
||||||
|
|
||||||
if [[ -n "$SYSLOG" && "$SYSLOG" != "False" ]]; then
|
if [[ -n "$SYSLOG" && "$SYSLOG" != "False" ]]; then
|
||||||
if is_ubuntu || is_fedora; then
|
if is_ubuntu || is_fedora; then
|
||||||
|
25
tools/ironic/scripts/cleanup-nodes
Executable file
25
tools/ironic/scripts/cleanup-nodes
Executable file
@ -0,0 +1,25 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# **cleanup-nodes**
|
||||||
|
|
||||||
|
# Cleans up baremetal poseur nodes and volumes created during ironic setup
|
||||||
|
# Assumes calling user has proper libvirt group membership and access.
|
||||||
|
|
||||||
|
set -exu
|
||||||
|
|
||||||
|
LIBVIRT_STORAGE_POOL=${LIBVIRT_STORAGE_POOL:-"default"}
|
||||||
|
|
||||||
|
VM_COUNT=$1
|
||||||
|
NETWORK_BRIDGE=$2
|
||||||
|
|
||||||
|
for (( idx=0; idx<$VM_COUNT; idx++ )); do
|
||||||
|
NAME="baremetal${NETWORK_BRIDGE}_${idx}"
|
||||||
|
VOL_NAME="baremetal${NETWORK_BRIDGE}-${idx}.qcow2"
|
||||||
|
virsh list | grep -q $NAME && virsh destroy $NAME
|
||||||
|
virsh list --inactive | grep -q $NAME && virsh undefine $NAME
|
||||||
|
|
||||||
|
if virsh pool-list | grep -q $LIBVIRT_STORAGE_POOL ; then
|
||||||
|
virsh vol-list $LIBVIRT_STORAGE_POOL | grep -q $VOL_NAME &&
|
||||||
|
virsh vol-delete $VOL_NAME --pool $LIBVIRT_STORAGE_POOL
|
||||||
|
fi
|
||||||
|
done
|
78
tools/ironic/scripts/configure-vm
Executable file
78
tools/ironic/scripts/configure-vm
Executable file
@ -0,0 +1,78 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import os.path
|
||||||
|
|
||||||
|
import libvirt
|
||||||
|
|
||||||
|
templatedir = os.path.join(os.path.dirname(os.path.dirname(__file__)),
|
||||||
|
'templates')
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = argparse.ArgumentParser(
|
||||||
|
description="Configure a kvm virtual machine for the seed image.")
|
||||||
|
parser.add_argument('--name', default='seed',
|
||||||
|
help='the name to give the machine in libvirt.')
|
||||||
|
parser.add_argument('--image',
|
||||||
|
help='Use a custom image file (must be qcow2).')
|
||||||
|
parser.add_argument('--engine', default='qemu',
|
||||||
|
help='The virtualization engine to use')
|
||||||
|
parser.add_argument('--arch', default='i686',
|
||||||
|
help='The architecture to use')
|
||||||
|
parser.add_argument('--memory', default='2097152',
|
||||||
|
help="Maximum memory for the VM in KB.")
|
||||||
|
parser.add_argument('--cpus', default='1',
|
||||||
|
help="CPU count for the VM.")
|
||||||
|
parser.add_argument('--bootdev', default='hd',
|
||||||
|
help="What boot device to use (hd/network).")
|
||||||
|
parser.add_argument('--network', default="brbm",
|
||||||
|
help='The libvirt network name to use')
|
||||||
|
parser.add_argument('--libvirt-nic-driver', default='e1000',
|
||||||
|
help='The libvirt network driver to use')
|
||||||
|
parser.add_argument('--emulator', default=None,
|
||||||
|
help='Path to emulator bin for vm template')
|
||||||
|
args = parser.parse_args()
|
||||||
|
with file(templatedir + '/vm.xml', 'rb') as f:
|
||||||
|
source_template = f.read()
|
||||||
|
params = {
|
||||||
|
'name': args.name,
|
||||||
|
'imagefile': args.image,
|
||||||
|
'engine': args.engine,
|
||||||
|
'arch': args.arch,
|
||||||
|
'memory': args.memory,
|
||||||
|
'cpus': args.cpus,
|
||||||
|
'bootdev': args.bootdev,
|
||||||
|
'network': args.network,
|
||||||
|
'emulator': args.emulator,
|
||||||
|
}
|
||||||
|
|
||||||
|
if args.emulator:
|
||||||
|
params['emulator'] = args.emulator
|
||||||
|
else:
|
||||||
|
if os.path.exists("/usr/bin/kvm"): # Debian
|
||||||
|
params['emulator'] = "/usr/bin/kvm"
|
||||||
|
elif os.path.exists("/usr/bin/qemu-kvm"): # Redhat
|
||||||
|
params['emulator'] = "/usr/bin/qemu-kvm"
|
||||||
|
|
||||||
|
nicparams = {
|
||||||
|
'nicdriver': args.libvirt_nic_driver,
|
||||||
|
'network': args.network,
|
||||||
|
}
|
||||||
|
|
||||||
|
params['bm_network'] = """
|
||||||
|
<!-- neutron friendly 'bare metal' network -->
|
||||||
|
<interface type='network'>
|
||||||
|
<source network='%(network)s'/>
|
||||||
|
<virtualport type='openvswitch'/>
|
||||||
|
<model type='%(nicdriver)s'/>
|
||||||
|
<address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
|
||||||
|
</interface>""" % nicparams
|
||||||
|
|
||||||
|
libvirt_template = source_template % params
|
||||||
|
conn = libvirt.open("qemu:///system")
|
||||||
|
a = conn.defineXML(libvirt_template)
|
||||||
|
print ("Created machine %s with UUID %s" % (args.name, a.UUIDString()))
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
68
tools/ironic/scripts/create-nodes
Executable file
68
tools/ironic/scripts/create-nodes
Executable file
@ -0,0 +1,68 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# **create-nodes**
|
||||||
|
|
||||||
|
# Creates baremetal poseur nodes for ironic testing purposes
|
||||||
|
|
||||||
|
set -exu
|
||||||
|
|
||||||
|
# Keep track of the devstack directory
|
||||||
|
TOP_DIR=$(cd $(dirname "$0")/.. && pwd)
|
||||||
|
|
||||||
|
CPU=$1
|
||||||
|
MEM=$(( 1024 * $2 ))
|
||||||
|
# extra G to allow fuzz for partition table : flavor size and registered size
|
||||||
|
# need to be different to actual size.
|
||||||
|
DISK=$(( $3 + 1))
|
||||||
|
|
||||||
|
case $4 in
|
||||||
|
i386) ARCH='i686' ;;
|
||||||
|
amd64) ARCH='x86_64' ;;
|
||||||
|
*) echo "Unsupported arch $4!" ; exit 1 ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
TOTAL=$(($5 - 1))
|
||||||
|
BRIDGE=$6
|
||||||
|
EMULATOR=$7
|
||||||
|
|
||||||
|
LIBVIRT_NIC_DRIVER=${LIBVIRT_NIC_DRIVER:-"e1000"}
|
||||||
|
LIBVIRT_STORAGE_POOL=${LIBVIRT_STORAGE_POOL:-"default"}
|
||||||
|
|
||||||
|
if ! virsh pool-list --all | grep -q $LIBVIRT_STORAGE_POOL; then
|
||||||
|
virsh pool-define-as --name $LIBVIRT_STORAGE_POOL dir --target /var/lib/libvirt/images >&2
|
||||||
|
virsh pool-autostart $LIBVIRT_STORAGE_POOL >&2
|
||||||
|
virsh pool-start $LIBVIRT_STORAGE_POOL >&2
|
||||||
|
fi
|
||||||
|
|
||||||
|
pool_state=$(virsh pool-info $LIBVIRT_STORAGE_POOL | grep State | awk '{ print $2 }')
|
||||||
|
if [ "$pool_state" != "running" ] ; then
|
||||||
|
[ ! -d /var/lib/libvirt/images ] && sudo mkdir /var/lib/libvirt/images
|
||||||
|
virsh pool-start $LIBVIRT_STORAGE_POOL >&2
|
||||||
|
fi
|
||||||
|
|
||||||
|
PREALLOC=
|
||||||
|
if [ -f /etc/debian_version ]; then
|
||||||
|
PREALLOC="--prealloc-metadata"
|
||||||
|
fi
|
||||||
|
|
||||||
|
DOMS=""
|
||||||
|
for idx in $(seq 0 $TOTAL) ; do
|
||||||
|
NAME="baremetal${BRIDGE}_${idx}"
|
||||||
|
DOMS="$DOMS $NAME"
|
||||||
|
VOL_NAME="baremetal${BRIDGE}-${idx}.qcow2"
|
||||||
|
(virsh list --all | grep -q $NAME) && continue
|
||||||
|
|
||||||
|
virsh vol-list --pool $LIBVIRT_STORAGE_POOL | grep -q $VOL_NAME &&
|
||||||
|
virsh vol-delete $VOL_NAME --pool $LIBVIRT_STORAGE_POOL >&2
|
||||||
|
virsh vol-create-as $LIBVIRT_STORAGE_POOL ${VOL_NAME} ${DISK}G --format qcow2 $PREALLOC >&2
|
||||||
|
volume_path=$(virsh vol-path --pool $LIBVIRT_STORAGE_POOL $VOL_NAME)
|
||||||
|
# Pre-touch the VM to set +C, as it can only be set on empty files.
|
||||||
|
sudo touch "$volume_path"
|
||||||
|
sudo chattr +C "$volume_path" || true
|
||||||
|
$TOP_DIR/scripts/configure-vm --bootdev network --name $NAME --image "$volume_path" --arch $ARCH --cpus $CPU --memory $MEM --libvirt-nic-driver $LIBVIRT_NIC_DRIVER --emulator $EMULATOR --network $BRIDGE >&2
|
||||||
|
done
|
||||||
|
|
||||||
|
for dom in $DOMS ; do
|
||||||
|
# echo mac
|
||||||
|
virsh dumpxml $dom | grep "mac address" | head -1 | cut -d\' -f2
|
||||||
|
done
|
24
tools/ironic/scripts/setup-network
Executable file
24
tools/ironic/scripts/setup-network
Executable file
@ -0,0 +1,24 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# **setup-network**
|
||||||
|
|
||||||
|
# Setups openvswitch libvirt network suitable for
|
||||||
|
# running baremetal poseur nodes for ironic testing purposes
|
||||||
|
|
||||||
|
set -exu
|
||||||
|
|
||||||
|
# Keep track of the devstack directory
|
||||||
|
TOP_DIR=$(cd $(dirname "$0")/.. && pwd)
|
||||||
|
BRIDGE_SUFFIX=${1:-''}
|
||||||
|
BRIDGE_NAME=brbm$BRIDGE_SUFFIX
|
||||||
|
|
||||||
|
# Only add bridge if missing
|
||||||
|
(sudo ovs-vsctl list-br | grep ${BRIDGE_NAME}$) || sudo ovs-vsctl add-br ${BRIDGE_NAME}
|
||||||
|
|
||||||
|
# remove bridge before replacing it.
|
||||||
|
(virsh net-list | grep "${BRIDGE_NAME} ") && virsh net-destroy ${BRIDGE_NAME}
|
||||||
|
(virsh net-list --inactive | grep "${BRIDGE_NAME} ") && virsh net-undefine ${BRIDGE_NAME}
|
||||||
|
|
||||||
|
virsh net-define <(sed s/brbm/$BRIDGE_NAME/ $TOP_DIR/templates/brbm.xml)
|
||||||
|
virsh net-autostart ${BRIDGE_NAME}
|
||||||
|
virsh net-start ${BRIDGE_NAME}
|
6
tools/ironic/templates/brbm.xml
Normal file
6
tools/ironic/templates/brbm.xml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<network>
|
||||||
|
<name>brbm</name>
|
||||||
|
<forward mode='bridge'/>
|
||||||
|
<bridge name='brbm'/>
|
||||||
|
<virtualport type='openvswitch'/>
|
||||||
|
</network>
|
11
tools/ironic/templates/tftpd-xinetd.template
Normal file
11
tools/ironic/templates/tftpd-xinetd.template
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
service tftp
|
||||||
|
{
|
||||||
|
protocol = udp
|
||||||
|
port = 69
|
||||||
|
socket_type = dgram
|
||||||
|
wait = yes
|
||||||
|
user = root
|
||||||
|
server = /usr/sbin/in.tftpd
|
||||||
|
server_args = -v -v -v -v -v --map-file %TFTPBOOT_DIR%/map-file %TFTPBOOT_DIR%
|
||||||
|
disable = no
|
||||||
|
}
|
43
tools/ironic/templates/vm.xml
Normal file
43
tools/ironic/templates/vm.xml
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
<domain type='%(engine)s'>
|
||||||
|
<name>%(name)s</name>
|
||||||
|
<memory unit='KiB'>%(memory)s</memory>
|
||||||
|
<vcpu>%(cpus)s</vcpu>
|
||||||
|
<os>
|
||||||
|
<type arch='%(arch)s' machine='pc-1.0'>hvm</type>
|
||||||
|
<boot dev='%(bootdev)s'/>
|
||||||
|
<bootmenu enable='no'/>
|
||||||
|
</os>
|
||||||
|
<features>
|
||||||
|
<acpi/>
|
||||||
|
<apic/>
|
||||||
|
<pae/>
|
||||||
|
</features>
|
||||||
|
<clock offset='utc'/>
|
||||||
|
<on_poweroff>destroy</on_poweroff>
|
||||||
|
<on_reboot>restart</on_reboot>
|
||||||
|
<on_crash>restart</on_crash>
|
||||||
|
<devices>
|
||||||
|
<emulator>%(emulator)s</emulator>
|
||||||
|
<disk type='file' device='disk'>
|
||||||
|
<driver name='qemu' type='qcow2' cache='writeback'/>
|
||||||
|
<source file='%(imagefile)s'/>
|
||||||
|
<target dev='vda' bus='virtio'/>
|
||||||
|
<address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/>
|
||||||
|
</disk>
|
||||||
|
<controller type='ide' index='0'>
|
||||||
|
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/>
|
||||||
|
</controller>
|
||||||
|
%(network)s
|
||||||
|
%(bm_network)s
|
||||||
|
<input type='mouse' bus='ps2'/>
|
||||||
|
<graphics type='vnc' port='-1' autoport='yes'/>
|
||||||
|
<video>
|
||||||
|
<model type='cirrus' vram='9216' heads='1'/>
|
||||||
|
<address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
|
||||||
|
</video>
|
||||||
|
<memballoon model='virtio'>
|
||||||
|
<address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/>
|
||||||
|
</memballoon>
|
||||||
|
</devices>
|
||||||
|
</domain>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user