Merge "Move create_keypair to api.base module and add creation params."
diff --git a/neutron_tempest_plugin/api/test_auto_allocated_topology.py b/neutron_tempest_plugin/api/test_auto_allocated_topology.py
index 37f9ad1..0baa2a8 100644
--- a/neutron_tempest_plugin/api/test_auto_allocated_topology.py
+++ b/neutron_tempest_plugin/api/test_auto_allocated_topology.py
@@ -63,7 +63,7 @@
up = {'admin_state_up': True}
networks = _count(self.client.list_networks(**up)['networks'])
- subnets = _count(self.client.list_subnets(**up)['subnets'])
+ subnets = _count(self.client.list_subnets()['subnets'])
routers = _count(self.client.list_routers(**up)['routers'])
return networks, subnets, routers
diff --git a/tools/customize_ubuntu_image b/tools/customize_ubuntu_image
new file mode 100755
index 0000000..9c3fd07
--- /dev/null
+++ b/tools/customize_ubuntu_image
@@ -0,0 +1,172 @@
+#!/bin/bash
+
+# IMPLEMENTATION NOTE: It was not possible to implement this script using
+# virt-customize because of below ubuntu bugs:
+# - https://bugs.launchpad.net/ubuntu/+source/libguestfs/+bug/1632405
+# - https://bugs.launchpad.net/ubuntu/+source/isc-dhcp/+bug/1650740
+#
+# It has therefore been adopted a more low level strategy performing below
+# steps:
+# - mount guest image to a temporary folder
+# - set up an environment suitable for executing chroot
+# - execute customize_image function inside chroot environment
+# - cleanup chroot environment
+
+# Array of packages to be installed of guest image
+INSTALL_GUEST_PACKAGES=(
+ socat # used to replace nc for testing advanced network features like
+ # multicast
+)
+
+# Function to be executed once after chroot on guest image
+# Add more customization steps here
+function customize_image {
+ # dhclient-script requires to read /etc/fstab for setting up network
+ touch /etc/fstab
+ chmod ugo+r /etc/fstab
+
+ # Ubuntu guest image _apt user could require access to below folders
+ local apt_user_folders=( /var/lib/apt/lists/partial )
+ mkdir -p "${apt_user_folders[@]}"
+ chown _apt.root -fR "${apt_user_folders[@]}"
+
+ # Install desired packages to Ubuntu guest image
+ apt-get update -y
+ apt-get install -y "${INSTALL_GUEST_PACKAGES[@]}"
+}
+
+function main {
+ set -eux
+ trap cleanup EXIT
+ "${ENTRY_POINT:-chroot_image}" "$@"
+}
+
+# Chroot to guest image then executes customize_image function inside it
+function chroot_image {
+ local image_file=$1
+ local temp_dir=${TEMP_DIR:-$(make_temp -d)}
+
+ # Mount guest image into a temporary directory
+ local mount_dir=${temp_dir}/mount
+ mkdir -p "${mount_dir}"
+ mount_image "${mount_dir}" "${temp_dir}/pid"
+
+ # Mount system directories
+ bind_dir "/dev" "${mount_dir}/dev"
+ bind_dir "/dev/pts" "${mount_dir}/dev/pts"
+ bind_dir "/proc" "${mount_dir}/proc"
+ bind_dir "/sys" "${mount_dir}/sys"
+
+ # Mount to keep temporary files out of guest image
+ mkdir -p "${temp_dir}/apt" "${temp_dir}/cache" "${temp_dir}/tmp"
+ bind_dir "${temp_dir}/cache" "${mount_dir}/var/cache"
+ bind_dir "${temp_dir}/tmp" "${mount_dir}/tmp"
+ bind_dir "${temp_dir}/tmp" "${mount_dir}/var/tmp"
+ bind_dir "${temp_dir}/apt" "${mount_dir}/var/lib/apt"
+
+ # Replace /etc/resolv.conf symlink to use the same DNS as this host
+ sudo rm -f "${mount_dir}/etc/resolv.conf"
+ sudo cp /etc/resolv.conf "${mount_dir}/etc/resolv.conf"
+
+ # Makesure /etc/fstab exists and it is readable because it is required by
+ # /sbin/dhclient-script
+ sudo touch /etc/fstab
+ sudo chmod 644 /etc/fstab
+
+ # Copy this script to mount dir
+ local script_name=$(basename "$0")
+ local script_file=${mount_dir}/${script_name}
+ sudo cp "$0" "${script_file}"
+ sudo chmod 500 "${script_file}"
+ add_cleanup sudo rm -f "'${script_file}'"
+
+ # Execute customize_image inside chroot environment
+ local command_line=( ${CHROOT_COMMAND:-customize_image} )
+ local entry_point=${command_line[0]}
+ unset command_line[0]
+ sudo -E "ENTRY_POINT=${entry_point}" \
+ chroot "${mount_dir}" "/${script_name}" "${command_line[@]:-}"
+}
+
+# Mounts guest image to $1 directory writing pid to $1 pid file
+# Then registers umount of such directory for final cleanup
+function mount_image {
+ local mount_dir=$1
+ local pid_file=$2
+
+ # export libguest settings
+ export LIBGUESTFS_BACKEND=${LIBGUESTFS_BACKEND:-direct}
+ export LIBGUESTFS_BACKEND_SETTINGS=${LIBGUESTFS_BACKEND_SETTINGS:-force_tcg}
+
+ # Mount guest image
+ sudo -E guestmount -i \
+ --add "${image_file}" \
+ --pid-file "${pid_file}" \
+ "${mount_dir}"
+
+ add_cleanup \
+ 'ENTRY_POINT=umount_image' \
+ "'$0'" "'${mount_dir}'" "'${pid_file}'"
+}
+
+# Unmounts guest image directory
+function umount_image {
+ local mount_dir=$1
+ local pid_file=$2
+ local timeout=10
+
+ # Take PID just before unmounting
+ local pid=$(cat ${pid_file} || true)
+ sudo -E guestunmount "${mount_dir}"
+
+ if [ "${pid:-}" != "" ]; then
+ # Make sure guestmount process is not running before using image
+ # file again
+ local count=${timeout}
+ while sudo kill -0 "${pid}" 2> /dev/null && (( count-- > 0 )); do
+ sleep 1
+ done
+ if [ ${count} == 0 ]; then
+ # It is not safe to use image file at this point
+ echo "Wait for guestmount to exit failed after ${timeout} seconds"
+ fi
+ fi
+}
+
+# Creates a temporary file or directory and register removal for final cleanup
+function make_temp {
+ local temporary=$(mktemp "$@")
+ add_cleanup sudo rm -fR "'${temporary}'"
+ echo "${temporary}"
+}
+
+# Bind directory $1 to directory $2 and register umount for final cleanup
+function bind_dir {
+ local source_dir=$1
+ local target_dir=$2
+ sudo mount --bind "${source_dir}" "${target_dir}"
+ add_cleanup sudo umount "'${target_dir}'"
+}
+
+# Registers a command line to be executed for final cleanup
+function add_cleanup {
+ CLEANUP_FILE=${CLEANUP_FILE:-$(mktemp)}
+
+ echo -e "$*" >> ${CLEANUP_FILE}
+}
+
+# Execute command lines for final cleanup in reversed order
+function cleanup {
+ error=$?
+
+ local cleanup_file=${CLEANUP_FILE:-}
+ if [ -r "${cleanup_file}" ]; then
+ tac "${cleanup_file}" | bash +e -x
+ CLEANUP_FILE=
+ rm -fR "${cleanup_file}"
+ fi
+
+ exit ${error}
+}
+
+main "$@"