diff --git a/.java-version b/.java-version index 6259340971be..2dbc24b32d3c 100644 --- a/.java-version +++ b/.java-version @@ -1 +1 @@ -1.8 +11.0 diff --git a/.travis.yml b/.travis.yml index a7429fe2ed5e..e5ad914562fe 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,13 +14,16 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. + sudo: required -dist: xenial -group: edge +dist: bionic +group: stable language: java + jdk: - - openjdk8 + - openjdk11 + python: - "2.7" @@ -44,7 +47,9 @@ env: smoke/test_affinity_groups_projects smoke/test_async_job smoke/test_create_list_domain_account_project + smoke/test_create_network smoke/test_deploy_vgpu_enabled_vm + smoke/test_deploy_vm_extra_config_data smoke/test_deploy_vm_iso smoke/test_deploy_vm_root_resize smoke/test_deploy_vm_with_userdata @@ -98,6 +103,7 @@ env: smoke/test_ssvm smoke/test_staticroles smoke/test_templates + smoke/test_update_security_group smoke/test_usage smoke/test_usage_events" @@ -152,6 +158,7 @@ env: component/test_project_resources" - TESTS="component/test_project_usage + component/test_protocol_number_security_group component/test_resource_limits" - TESTS="component/test_regions_accounts diff --git a/INSTALL.md b/INSTALL.md index 85da4beb8c3d..6840626156f5 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -15,15 +15,8 @@ was tested against a CentOS 7 x86_64 setup. Install tools and dependencies used for development: - $ yum install git java-1.8.0-openjdk java-1.8.0-openjdk-devel \ - mysql mysql-server mkisofs gcc python MySQL-python openssh-clients wget - - # yum -y update - # yum -y install java-1.8.0-openjdk - # yum -y install java-1.8.0-openjdk-devel - # yum -y install mysql-server - # yum -y install git - # yum -y install genisoimage + # yum -y install git java-11-openjdk java-11-openjdk-devel \ + mysql mysql-server mkisofs git gcc python MySQL-python openssh-clients wget Set up Maven (3.6.0): diff --git a/README.md b/README.md index 4f250f0f9af1..7b520812be3f 100644 --- a/README.md +++ b/README.md @@ -148,3 +148,4 @@ The following provides more details on the included cryptographic software: * CloudStack makes use of the Bouncy Castle general-purpose encryption library. * CloudStack can optionally interacts with and controls OpenSwan-based VPNs. * CloudStack has a dependency on and makes use of JSch - a java SSH2 implementation. + diff --git a/agent/bindir/libvirtqemuhook.in b/agent/bindir/libvirtqemuhook.in index 27e07119ccc3..894d68c7b0b1 100755 --- a/agent/bindir/libvirtqemuhook.in +++ b/agent/bindir/libvirtqemuhook.in @@ -65,11 +65,15 @@ def handleMigrateBegin(): bridge = source.getAttribute("bridge") if isOldStyleBridge(bridge): vlanId = bridge.replace("cloudVirBr", "") + phyDev = getGuestNetworkDevice() elif isNewStyleBridge(bridge): vlanId = re.sub(r"br(\w+)-", "", bridge) + phyDev = re.sub(r"-(\d+)$", "" , re.sub(r"^br", "" ,bridge)) + netlib = networkConfig() + if not netlib.isNetworkDev(phyDev): + phyDev = getGuestNetworkDevice() else: continue - phyDev = getGuestNetworkDevice() newBrName = "br" + phyDev + "-" + vlanId source.setAttribute("bridge", newBrName) print(domain.toxml()) diff --git a/agent/distro/centos/SYSCONFDIR/rc.d/init.d/cloud-agent.in b/agent/distro/centos/SYSCONFDIR/rc.d/init.d/cloud-agent.in deleted file mode 100755 index d1769ccdfb01..000000000000 --- a/agent/distro/centos/SYSCONFDIR/rc.d/init.d/cloud-agent.in +++ /dev/null @@ -1,119 +0,0 @@ -#!/bin/bash - -# chkconfig: 35 99 10 -# description: Cloud Agent - -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you 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. - -# WARNING: if this script is changed, then all other initscripts MUST BE changed to match it as well - -. /etc/rc.d/init.d/functions - -# set environment variables - -SHORTNAME=`basename $0` -PIDFILE=@PIDDIR@/"$SHORTNAME".pid -LOCKFILE=@LOCKDIR@/"$SHORTNAME" -LOGFILE=@AGENTLOG@ -PROGNAME="Cloud Agent" -CLASS="com.cloud.agent.AgentShell" -JSVC=`which jsvc 2>/dev/null`; - -# exit if we don't find jsvc -if [ -z "$JSVC" ]; then - echo no jsvc found in path; - exit 1; -fi - -unset OPTIONS -[ -r @SYSCONFDIR@/sysconfig/"$SHORTNAME" ] && source @SYSCONFDIR@/sysconfig/"$SHORTNAME" - -# The first existing directory is used for JAVA_HOME (if JAVA_HOME is not defined in $DEFAULT) -JDK_DIRS="/usr/lib/jvm/jre /usr/lib/jvm/java-6-openjdk /usr/lib/jvm/java-6-openjdk-i386 /usr/lib/jvm/java-6-openjdk-amd64 /usr/lib/jvm/java-6-sun /usr/lib/jvm/java-1.5.0-sun /usr/lib/j2sdk1.5-sun /usr/lib/j2sdk1.5-ibm" - -for jdir in $JDK_DIRS; do - if [ -r "$jdir/bin/java" -a -z "${JAVA_HOME}" ]; then - JAVA_HOME="$jdir" - fi -done -export JAVA_HOME - -SCP="@SYSTEMCLASSPATH@" -DCP="@DEPSCLASSPATH@" -ACP="@AGENTCLASSPATH@" -JCP="/usr/share/java/commons-daemon.jar" - -# We need to append the JSVC daemon JAR to the classpath -# AgentShell implements the JSVC daemon methods -export CLASSPATH="$SCP:$DCP:$ACP:$JCP:@AGENTSYSCONFDIR@:@AGENTLIBDIR@" - -start() { - echo -n $"Starting $PROGNAME: " - if hostname --fqdn >/dev/null 2>&1 ; then - $JSVC -cp "$CLASSPATH" -pidfile "$PIDFILE" -errfile SYSLOG $CLASS - RETVAL=$? - echo - else - failure - echo - echo The host name does not resolve properly to an IP address. Cannot start "$PROGNAME". > /dev/stderr - RETVAL=9 - fi - [ $RETVAL = 0 ] && touch ${LOCKFILE} - return $RETVAL -} - -stop() { - echo -n $"Stopping $PROGNAME: " - $JSVC -pidfile "$PIDFILE" -stop $CLASS - RETVAL=$? - echo - [ $RETVAL = 0 ] && rm -f ${LOCKFILE} ${PIDFILE} -} - - -# See how we were called. -case "$1" in - start) - start - ;; - stop) - stop - ;; - status) - status -p ${PIDFILE} $SHORTNAME - RETVAL=$? - ;; - restart) - stop - sleep 3 - start - ;; - condrestart) - if status -p ${PIDFILE} $SHORTNAME >&/dev/null; then - stop - sleep 3 - start - fi - ;; - *) - echo $"Usage: $SHORTNAME {start|stop|restart|condrestart|status|help}" - RETVAL=3 -esac - -exit $RETVAL diff --git a/agent/distro/fedora/SYSCONFDIR/rc.d/init.d/cloud-agent.in b/agent/distro/fedora/SYSCONFDIR/rc.d/init.d/cloud-agent.in deleted file mode 100755 index d1769ccdfb01..000000000000 --- a/agent/distro/fedora/SYSCONFDIR/rc.d/init.d/cloud-agent.in +++ /dev/null @@ -1,119 +0,0 @@ -#!/bin/bash - -# chkconfig: 35 99 10 -# description: Cloud Agent - -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you 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. - -# WARNING: if this script is changed, then all other initscripts MUST BE changed to match it as well - -. /etc/rc.d/init.d/functions - -# set environment variables - -SHORTNAME=`basename $0` -PIDFILE=@PIDDIR@/"$SHORTNAME".pid -LOCKFILE=@LOCKDIR@/"$SHORTNAME" -LOGFILE=@AGENTLOG@ -PROGNAME="Cloud Agent" -CLASS="com.cloud.agent.AgentShell" -JSVC=`which jsvc 2>/dev/null`; - -# exit if we don't find jsvc -if [ -z "$JSVC" ]; then - echo no jsvc found in path; - exit 1; -fi - -unset OPTIONS -[ -r @SYSCONFDIR@/sysconfig/"$SHORTNAME" ] && source @SYSCONFDIR@/sysconfig/"$SHORTNAME" - -# The first existing directory is used for JAVA_HOME (if JAVA_HOME is not defined in $DEFAULT) -JDK_DIRS="/usr/lib/jvm/jre /usr/lib/jvm/java-6-openjdk /usr/lib/jvm/java-6-openjdk-i386 /usr/lib/jvm/java-6-openjdk-amd64 /usr/lib/jvm/java-6-sun /usr/lib/jvm/java-1.5.0-sun /usr/lib/j2sdk1.5-sun /usr/lib/j2sdk1.5-ibm" - -for jdir in $JDK_DIRS; do - if [ -r "$jdir/bin/java" -a -z "${JAVA_HOME}" ]; then - JAVA_HOME="$jdir" - fi -done -export JAVA_HOME - -SCP="@SYSTEMCLASSPATH@" -DCP="@DEPSCLASSPATH@" -ACP="@AGENTCLASSPATH@" -JCP="/usr/share/java/commons-daemon.jar" - -# We need to append the JSVC daemon JAR to the classpath -# AgentShell implements the JSVC daemon methods -export CLASSPATH="$SCP:$DCP:$ACP:$JCP:@AGENTSYSCONFDIR@:@AGENTLIBDIR@" - -start() { - echo -n $"Starting $PROGNAME: " - if hostname --fqdn >/dev/null 2>&1 ; then - $JSVC -cp "$CLASSPATH" -pidfile "$PIDFILE" -errfile SYSLOG $CLASS - RETVAL=$? - echo - else - failure - echo - echo The host name does not resolve properly to an IP address. Cannot start "$PROGNAME". > /dev/stderr - RETVAL=9 - fi - [ $RETVAL = 0 ] && touch ${LOCKFILE} - return $RETVAL -} - -stop() { - echo -n $"Stopping $PROGNAME: " - $JSVC -pidfile "$PIDFILE" -stop $CLASS - RETVAL=$? - echo - [ $RETVAL = 0 ] && rm -f ${LOCKFILE} ${PIDFILE} -} - - -# See how we were called. -case "$1" in - start) - start - ;; - stop) - stop - ;; - status) - status -p ${PIDFILE} $SHORTNAME - RETVAL=$? - ;; - restart) - stop - sleep 3 - start - ;; - condrestart) - if status -p ${PIDFILE} $SHORTNAME >&/dev/null; then - stop - sleep 3 - start - fi - ;; - *) - echo $"Usage: $SHORTNAME {start|stop|restart|condrestart|status|help}" - RETVAL=3 -esac - -exit $RETVAL diff --git a/agent/distro/opensuse/sles/SYSCONFDIR/init.d/cloud-agent.in b/agent/distro/opensuse/sles/SYSCONFDIR/init.d/cloud-agent.in deleted file mode 100644 index 3a1d053be2d1..000000000000 --- a/agent/distro/opensuse/sles/SYSCONFDIR/init.d/cloud-agent.in +++ /dev/null @@ -1,172 +0,0 @@ -#!/bin/bash -### BEGIN INIT INFO -# Provides: cloudstack-agent -# Required-Start: $network -# Required-Stop: $network -# Default-Start: 3 4 5 -# Default-Stop: 0 1 2 6 -# X-Interactive: true -# Short-Description: Start/stop apache2 web server -### END INIT INFO - -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you 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. - -# WARNING: if this script is changed, then all other initscripts MUST BE changed to match it as well - -. /lib/lsb/init-functions -. /etc/rc.status - -# set environment variables - -SHORTNAME=`basename $0` -PIDFILE=@PIDDIR@/"$SHORTNAME".pid -LOCKFILE=@LOCKDIR@/"$SHORTNAME" -LOGFILE=@AGENTLOG@ -PROGNAME="Cloud Agent" -CLASS="com.cloud.agent.AgentShell" - -unset OPTIONS -[ -r @SYSCONFDIR@/default/"$SHORTNAME" ] && source @SYSCONFDIR@/default/"$SHORTNAME" - -# The first existing directory is used for JAVA_HOME (if JAVA_HOME is not defined in $DEFAULT) -JDK_DIRS="/usr/lib/jvm/java-6-openjdk /usr/lib/jvm/java-6-openjdk-i386 /usr/lib/jvm/java-6-openjdk-amd64 /usr/lib/jvm/java-6-sun /usr/lib/jvm/java-1.5.0-sun /usr/lib/j2sdk1.5-sun /usr/lib/j2sdk1.5-ibm" - -for jdir in $JDK_DIRS; do - if [ -r "$jdir/bin/java" -a -z "${JAVA_HOME}" ]; then - JAVA_HOME="$jdir" - fi -done -export JAVA_HOME - -SCP="@SYSTEMCLASSPATH@" -DCP="@DEPSCLASSPATH@" -ACP="@AGENTCLASSPATH@" -JCP="/usr/share/java/commons-daemon.jar" - -# We need to append the JSVC daemon JAR to the classpath -# AgentShell implements the JSVC daemon methods -export CLASSPATH="$SCP:$DCP:$ACP:$JCP:@AGENTSYSCONFDIR@" - -wait_for_network() { - i=1 - while [ $i -lt 10 ] - do - # Under Ubuntu and Debian libvirt by default creates a bridge called virbr0. - # That's why we want more then 3 lines back from brctl, so that there is a manually created bridge - if [ "$(brctl show|wc -l)" -gt 2 ]; then - break - else - sleep 1 - let i=$i+1 - continue - fi - done -} - -start() { - log_daemon_msg $"Starting $PROGNAME" "$SHORTNAME" - if [ -s "$PIDFILE" ] && kill -0 $(cat "$PIDFILE") >/dev/null 2>&1; then - log_progress_msg "apparently already running" - log_end_msg 0 - exit 0 - fi - if hostname --fqdn >/dev/null 2>&1 ; then - true - else - log_failure_msg "The host name does not resolve properly to an IP address. Cannot start $PROGNAME" - log_end_msg 1 - exit 1 - fi - - wait_for_network - - if jsvc -cp "$CLASSPATH" -pidfile "$PIDFILE" -errfile SYSLOG $CLASS - RETVAL=$? - then - rc=0 - sleep 1 - if ! kill -0 $(cat "$PIDFILE") >/dev/null 2>&1; then - log_failure_msg "$PROG failed to start" - rc=1 - fi - else - rc=1 - fi - - if [ $rc -eq 0 ]; then - log_end_msg 0 - else - log_end_msg 1 - rm -f "$PIDFILE" - fi -} - -stop() { - SHUTDOWN_WAIT="30" - count="0" - - echo -n $"Stopping $PROGNAME" "$SHORTNAME" - jsvc -pidfile "$PIDFILE" -stop $CLASS - - until [ "$count" -gt "$SHUTDOWN_WAIT" ] - do - agentPid=`ps aux|grep [j]svc|grep cloud-agent` - if [ "$?" -gt "0" ];then - break - fi - sleep 1 - let count="${count}+1" - done - - agentPid=`ps aux|grep [j]svc|grep cloud-agent` - if [ "$?" -eq "0" ]; then - agentPid=`ps aux|grep [j]svc|awk '{print $2}'` - if [ "$agentPid" != "" ]; then - kill -9 $agentPid - fi - fi - - log_end_msg $? - rm -f "$PIDFILE" -} - - -# See how we were called. -case "$1" in - start) - start - ;; - stop) - stop - ;; - status) - status_of_proc -p "$PIDFILE" "$PROG" "$SHORTNAME" - RETVAL=$? - ;; - restart) - stop - sleep 3 - start - ;; - *) - echo $"Usage: $SHORTNAME {start|stop|restart|status|help}" - RETVAL=3 -esac - -exit $RETVAL - diff --git a/agent/distro/rhel/SYSCONFDIR/rc.d/init.d/cloud-agent.in b/agent/distro/rhel/SYSCONFDIR/rc.d/init.d/cloud-agent.in deleted file mode 100644 index 271d45d06d61..000000000000 --- a/agent/distro/rhel/SYSCONFDIR/rc.d/init.d/cloud-agent.in +++ /dev/null @@ -1,122 +0,0 @@ -#!/bin/bash - -# chkconfig: 35 99 10 -# description: Cloud Agent - -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you 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. - -# WARNING: if this script is changed, then all other initscripts MUST BE changed to match it as well - -. /etc/rc.d/init.d/functions - -# set environment variables - -SHORTNAME=`basename $0` -PIDFILE=@PIDDIR@/"$SHORTNAME".pid -LOCKFILE=@LOCKDIR@/"$SHORTNAME" -LOGFILE=@AGENTLOG@ -PROGNAME="Cloud Agent" -CLASS="com.cloud.agent.AgentShell" -JSVC=`which jsvc 2>/dev/null`; - -# exit if we don't find jsvc -if [ -z "$JSVC" ]; then - echo no jsvc found in path; - exit 1; -fi - -unset OPTIONS -[ -r @SYSCONFDIR@/sysconfig/"$SHORTNAME" ] && source @SYSCONFDIR@/sysconfig/"$SHORTNAME" - -# The first existing directory is used for JAVA_HOME (if JAVA_HOME is not defined in $DEFAULT) -JDK_DIRS="/usr/lib/jvm/jre /usr/lib/jvm/java-6-openjdk /usr/lib/jvm/java-6-openjdk-i386 /usr/lib/jvm/java-6-openjdk-amd64 /usr/lib/jvm/java-6-sun /usr/lib/jvm/java-1.5.0-sun /usr/lib/j2sdk1.5-sun /usr/lib/j2sdk1.5-ibm /usr/lib/jvm/jre-1.7.0" - -jhome="" -for jdir in $JDK_DIRS; do - if [ -r "$jdir/bin/java" -a -z "${JAVA_HOME}" ]; then - jhome="$jdir" - fi -done -if [ ! -z $jhome ];then -export JAVA_HOME="$jhome" -fi - -SCP="@SYSTEMCLASSPATH@" -DCP="@DEPSCLASSPATH@" -ACP="@AGENTCLASSPATH@" -JCP="/usr/share/java/commons-daemon.jar" - -# We need to append the JSVC daemon JAR to the classpath -# AgentShell implements the JSVC daemon methods -export CLASSPATH="$SCP:$DCP:$ACP:$JCP:@AGENTSYSCONFDIR@:@AGENTLIBDIR@" - -start() { - echo -n $"Starting $PROGNAME: " - if hostname --fqdn >/dev/null 2>&1 ; then - $JSVC -cp "$CLASSPATH" -pidfile "$PIDFILE" -errfile SYSLOG $CLASS - RETVAL=$? - echo - else - failure - echo - echo The host name does not resolve properly to an IP address. Cannot start "$PROGNAME". > /dev/stderr - RETVAL=9 - fi - [ $RETVAL = 0 ] && touch ${LOCKFILE} - return $RETVAL -} - -stop() { - echo -n $"Stopping $PROGNAME: " - $JSVC -pidfile "$PIDFILE" -stop $CLASS - RETVAL=$? - echo - [ $RETVAL = 0 ] && rm -f ${LOCKFILE} ${PIDFILE} -} - - -# See how we were called. -case "$1" in - start) - start - ;; - stop) - stop - ;; - status) - status -p ${PIDFILE} $SHORTNAME - RETVAL=$? - ;; - restart) - stop - sleep 3 - start - ;; - condrestart) - if status -p ${PIDFILE} $SHORTNAME >&/dev/null; then - stop - sleep 3 - start - fi - ;; - *) - echo $"Usage: $SHORTNAME {start|stop|restart|condrestart|status|help}" - RETVAL=3 -esac - -exit $RETVAL diff --git a/agent/distro/sles/SYSCONFDIR/init.d/cloud-agent.in b/agent/distro/sles/SYSCONFDIR/init.d/cloud-agent.in deleted file mode 100644 index 3a1d053be2d1..000000000000 --- a/agent/distro/sles/SYSCONFDIR/init.d/cloud-agent.in +++ /dev/null @@ -1,172 +0,0 @@ -#!/bin/bash -### BEGIN INIT INFO -# Provides: cloudstack-agent -# Required-Start: $network -# Required-Stop: $network -# Default-Start: 3 4 5 -# Default-Stop: 0 1 2 6 -# X-Interactive: true -# Short-Description: Start/stop apache2 web server -### END INIT INFO - -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you 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. - -# WARNING: if this script is changed, then all other initscripts MUST BE changed to match it as well - -. /lib/lsb/init-functions -. /etc/rc.status - -# set environment variables - -SHORTNAME=`basename $0` -PIDFILE=@PIDDIR@/"$SHORTNAME".pid -LOCKFILE=@LOCKDIR@/"$SHORTNAME" -LOGFILE=@AGENTLOG@ -PROGNAME="Cloud Agent" -CLASS="com.cloud.agent.AgentShell" - -unset OPTIONS -[ -r @SYSCONFDIR@/default/"$SHORTNAME" ] && source @SYSCONFDIR@/default/"$SHORTNAME" - -# The first existing directory is used for JAVA_HOME (if JAVA_HOME is not defined in $DEFAULT) -JDK_DIRS="/usr/lib/jvm/java-6-openjdk /usr/lib/jvm/java-6-openjdk-i386 /usr/lib/jvm/java-6-openjdk-amd64 /usr/lib/jvm/java-6-sun /usr/lib/jvm/java-1.5.0-sun /usr/lib/j2sdk1.5-sun /usr/lib/j2sdk1.5-ibm" - -for jdir in $JDK_DIRS; do - if [ -r "$jdir/bin/java" -a -z "${JAVA_HOME}" ]; then - JAVA_HOME="$jdir" - fi -done -export JAVA_HOME - -SCP="@SYSTEMCLASSPATH@" -DCP="@DEPSCLASSPATH@" -ACP="@AGENTCLASSPATH@" -JCP="/usr/share/java/commons-daemon.jar" - -# We need to append the JSVC daemon JAR to the classpath -# AgentShell implements the JSVC daemon methods -export CLASSPATH="$SCP:$DCP:$ACP:$JCP:@AGENTSYSCONFDIR@" - -wait_for_network() { - i=1 - while [ $i -lt 10 ] - do - # Under Ubuntu and Debian libvirt by default creates a bridge called virbr0. - # That's why we want more then 3 lines back from brctl, so that there is a manually created bridge - if [ "$(brctl show|wc -l)" -gt 2 ]; then - break - else - sleep 1 - let i=$i+1 - continue - fi - done -} - -start() { - log_daemon_msg $"Starting $PROGNAME" "$SHORTNAME" - if [ -s "$PIDFILE" ] && kill -0 $(cat "$PIDFILE") >/dev/null 2>&1; then - log_progress_msg "apparently already running" - log_end_msg 0 - exit 0 - fi - if hostname --fqdn >/dev/null 2>&1 ; then - true - else - log_failure_msg "The host name does not resolve properly to an IP address. Cannot start $PROGNAME" - log_end_msg 1 - exit 1 - fi - - wait_for_network - - if jsvc -cp "$CLASSPATH" -pidfile "$PIDFILE" -errfile SYSLOG $CLASS - RETVAL=$? - then - rc=0 - sleep 1 - if ! kill -0 $(cat "$PIDFILE") >/dev/null 2>&1; then - log_failure_msg "$PROG failed to start" - rc=1 - fi - else - rc=1 - fi - - if [ $rc -eq 0 ]; then - log_end_msg 0 - else - log_end_msg 1 - rm -f "$PIDFILE" - fi -} - -stop() { - SHUTDOWN_WAIT="30" - count="0" - - echo -n $"Stopping $PROGNAME" "$SHORTNAME" - jsvc -pidfile "$PIDFILE" -stop $CLASS - - until [ "$count" -gt "$SHUTDOWN_WAIT" ] - do - agentPid=`ps aux|grep [j]svc|grep cloud-agent` - if [ "$?" -gt "0" ];then - break - fi - sleep 1 - let count="${count}+1" - done - - agentPid=`ps aux|grep [j]svc|grep cloud-agent` - if [ "$?" -eq "0" ]; then - agentPid=`ps aux|grep [j]svc|awk '{print $2}'` - if [ "$agentPid" != "" ]; then - kill -9 $agentPid - fi - fi - - log_end_msg $? - rm -f "$PIDFILE" -} - - -# See how we were called. -case "$1" in - start) - start - ;; - stop) - stop - ;; - status) - status_of_proc -p "$PIDFILE" "$PROG" "$SHORTNAME" - RETVAL=$? - ;; - restart) - stop - sleep 3 - start - ;; - *) - echo $"Usage: $SHORTNAME {start|stop|restart|status|help}" - RETVAL=3 -esac - -exit $RETVAL - diff --git a/agent/distro/ubuntu/SYSCONFDIR/init.d/cloud-agent.in b/agent/distro/ubuntu/SYSCONFDIR/init.d/cloud-agent.in deleted file mode 100755 index c30e526d282e..000000000000 --- a/agent/distro/ubuntu/SYSCONFDIR/init.d/cloud-agent.in +++ /dev/null @@ -1,173 +0,0 @@ -#!/bin/bash - -### BEGIN INIT INFO -# Provides: cloudstack-agent -# Required-Start: $network $local_fs -# Required-Stop: $network $local_fs -# Default-Start: 3 4 5 -# Default-Stop: 0 1 2 6 -# Short-Description: Start/stop Apache CloudStack Agent -# Description: This scripts Starts/Stops the Apache CloudStack agent -## The CloudStack Agent is a part of the Apache CloudStack project and is used -## for managing KVM-based Hypervisors and performing secondary storage tasks inside -## the Secondary Storage System Virtual Machine. -## JSVC (Java daemonizing) is used for starting and stopping the agent -### END INIT INFO - -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you 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. - -. /lib/lsb/init-functions - -SHORTNAME="cloud-agent" -PIDFILE=@PIDDIR@/"$SHORTNAME".pid -LOCKFILE=@LOCKDIR@/"$SHORTNAME" -LOGFILE=@AGENTLOG@ -PROGNAME="CloudStack Agent" -CLASS="com.cloud.agent.AgentShell" -PROG="jsvc" -DAEMON="/usr/bin/jsvc" -SHUTDOWN_WAIT="30" - -unset OPTIONS -[ -r @SYSCONFDIR@/default/"$SHORTNAME" ] && source @SYSCONFDIR@/default/"$SHORTNAME" - -# The first existing directory is used for JAVA_HOME (if JAVA_HOME is not defined in $DEFAULT) -JDK_DIRS="/usr/lib/jvm/java-6-openjdk /usr/lib/jvm/java-6-openjdk-i386 /usr/lib/jvm/java-6-openjdk-amd64 /usr/lib/jvm/java-6-sun /usr/lib/jvm/java-1.5.0-sun /usr/lib/j2sdk1.5-sun /usr/lib/j2sdk1.5-ibm" - -for jdir in $JDK_DIRS; do - if [ -r "$jdir/bin/java" -a -z "${JAVA_HOME}" ]; then - JAVA_HOME="$jdir" - fi -done -export JAVA_HOME - -SCP="@SYSTEMCLASSPATH@" -DCP="@DEPSCLASSPATH@" -ACP="@AGENTCLASSPATH@" -JCP="/usr/share/java/commons-daemon.jar" - -# We need to append the JSVC daemon JAR to the classpath -# AgentShell implements the JSVC daemon methods -export CLASSPATH="$SCP:$DCP:$ACP:$JCP:@AGENTSYSCONFDIR@" - -wait_for_network() { - i=1 - while [ $i -lt 10 ] - do - # Under Ubuntu and Debian libvirt by default creates a bridge called virbr0. - # That's why we want more then 3 lines back from brctl, so that there is a manually created bridge - if [ "$(brctl show|wc -l)" -gt 2 ]; then - break - else - sleep 1 - let i=$i+1 - continue - fi - done -} - -start() { - if [ -s "$PIDFILE" ] && kill -0 $(cat "$PIDFILE") >/dev/null 2>&1; then - log_daemon_msg "$PROGNAME apparently already running" - log_end_msg 0 - exit 0 - fi - - log_daemon_msg "Starting $PROGNAME" "$SHORTNAME" - if hostname --fqdn >/dev/null 2>&1 ; then - true - else - log_failure_msg "The host name does not resolve properly to an IP address. Cannot start $PROGNAME" - log_end_msg 1 - exit 1 - fi - - wait_for_network - - if start_daemon -p $PIDFILE $DAEMON -cp "$CLASSPATH" -pidfile "$PIDFILE" -errfile SYSLOG $CLASS - RETVAL=$? - then - rc=0 - sleep 1 - if ! kill -0 $(cat "$PIDFILE") >/dev/null 2>&1; then - log_failure_msg "$PROG failed to start" - rc=1 - fi - else - rc=1 - fi - - if [ $rc -eq 0 ]; then - log_end_msg 0 - else - log_end_msg 1 - rm -f "$PIDFILE" - fi -} - -stop() { - count="0" - - log_daemon_msg "Stopping $PROGNAME" "$SHORTNAME" - killproc -p $PIDFILE $DAEMON - - until [ "$count" -gt "$SHUTDOWN_WAIT" ] - do - agentPid=$(ps aux|grep [j]svc|grep $SHORTNAME) - if [ "$?" -gt "0" ];then - break - fi - sleep 1 - let count="${count}+1" - done - - agentPid=$(ps aux|grep [j]svc|grep $SHORTNAME) - if [ "$?" -eq "0" ]; then - agentPid=$(ps aux|grep [j]svc|awk '{print $2}') - if [ "$agentPid" != "" ]; then - log_warning_msg "$PROG still running, forcing kill" - kill -9 $agentPid - fi - fi - - log_end_msg $? - rm -f "$PIDFILE" -} - -case "$1" in - start) - start - ;; - stop) - stop - ;; - status) - status_of_proc -p "$PIDFILE" "$PROG" "$SHORTNAME" - RETVAL=$? - ;; - restart | force-reload) - stop - sleep 3 - start - ;; - *) - echo "Usage: $0 {start|stop|restart|force-reload|status}" - RETVAL=3 -esac - -exit $RETVAL diff --git a/agent/src/main/java/com/cloud/agent/Agent.java b/agent/src/main/java/com/cloud/agent/Agent.java index e5fbdd7a2ede..7e5e2957f59c 100644 --- a/agent/src/main/java/com/cloud/agent/Agent.java +++ b/agent/src/main/java/com/cloud/agent/Agent.java @@ -292,8 +292,13 @@ public void start() { try { _connection.start(); } catch (final NioConnectionException e) { - s_logger.warn("NIO Connection Exception " + e); - s_logger.info("Attempted to connect to the server, but received an unexpected exception, trying again..."); + _connection.stop(); + try { + _connection.cleanUp(); + } catch (final IOException ex) { + s_logger.warn("Fail to clean up old connection. " + ex); + } + s_logger.info("Attempted to connect to the server, but received an unexpected exception, trying again...", e); } } _shell.updateConnectedHost(); @@ -516,8 +521,7 @@ protected void reconnect(final Link link) { try { _connection.start(); } catch (final NioConnectionException e) { - s_logger.warn("NIO Connection Exception " + e); - s_logger.info("Attempted to connect to the server, but received an unexpected exception, trying again..."); + s_logger.info("Attempted to re-connect to the server, but received an unexpected exception, trying again...", e); _connection.stop(); try { _connection.cleanUp(); diff --git a/agent/src/main/java/com/cloud/agent/resource/consoleproxy/ConsoleProxyResource.java b/agent/src/main/java/com/cloud/agent/resource/consoleproxy/ConsoleProxyResource.java index fb5e32771a3f..d150ea728c73 100644 --- a/agent/src/main/java/com/cloud/agent/resource/consoleproxy/ConsoleProxyResource.java +++ b/agent/src/main/java/com/cloud/agent/resource/consoleproxy/ConsoleProxyResource.java @@ -59,7 +59,6 @@ import com.cloud.resource.ServerResource; import com.cloud.resource.ServerResourceBase; import com.cloud.utils.NumbersUtil; -import com.cloud.utils.ReflectUtil; import com.cloud.utils.net.NetUtils; import com.cloud.utils.script.Script; import com.google.gson.Gson; @@ -317,14 +316,13 @@ public String getName() { private void launchConsoleProxy(final byte[] ksBits, final String ksPassword, final String encryptorPassword) { final Object resource = this; s_logger.info("Building class loader for com.cloud.consoleproxy.ConsoleProxy"); - final ClassLoader loader = ReflectUtil.getClassLoaderForName("console-proxy"); if (_consoleProxyMain == null) { s_logger.info("Running com.cloud.consoleproxy.ConsoleProxy with encryptor password=" + encryptorPassword); _consoleProxyMain = new Thread(new ManagedContextRunnable() { @Override protected void runInContext() { try { - Class consoleProxyClazz = loader.loadClass("com.cloud.consoleproxy.ConsoleProxy"); + Class consoleProxyClazz = Class.forName("com.cloud.consoleproxy.ConsoleProxy"); try { s_logger.info("Invoke startWithContext()"); Method method = consoleProxyClazz.getMethod("startWithContext", Properties.class, Object.class, byte[].class, String.class, String.class); @@ -357,7 +355,7 @@ protected void runInContext() { s_logger.info("com.cloud.consoleproxy.ConsoleProxy is already running"); try { - Class consoleProxyClazz = loader.loadClass("com.cloud.consoleproxy.ConsoleProxy"); + Class consoleProxyClazz = Class.forName("com.cloud.consoleproxy.ConsoleProxy"); Method methodSetup = consoleProxyClazz.getMethod("setEncryptorPassword", String.class); methodSetup.invoke(null, encryptorPassword); } catch (SecurityException e) { diff --git a/api/src/main/java/com/cloud/event/EventTypes.java b/api/src/main/java/com/cloud/event/EventTypes.java index a30518aaf176..33950f8f2784 100644 --- a/api/src/main/java/com/cloud/event/EventTypes.java +++ b/api/src/main/java/com/cloud/event/EventTypes.java @@ -19,6 +19,13 @@ import java.util.HashMap; import java.util.Map; +import org.apache.cloudstack.acl.Role; +import org.apache.cloudstack.acl.RolePermission; +import org.apache.cloudstack.annotation.Annotation; +import org.apache.cloudstack.config.Configuration; +import org.apache.cloudstack.ha.HAConfig; +import org.apache.cloudstack.usage.Usage; + import com.cloud.dc.DataCenter; import com.cloud.dc.Pod; import com.cloud.dc.StorageNetworkIpRange; @@ -69,12 +76,6 @@ import com.cloud.vm.Nic; import com.cloud.vm.NicSecondaryIp; import com.cloud.vm.VirtualMachine; -import org.apache.cloudstack.acl.Role; -import org.apache.cloudstack.acl.RolePermission; -import org.apache.cloudstack.annotation.Annotation; -import org.apache.cloudstack.config.Configuration; -import org.apache.cloudstack.ha.HAConfig; -import org.apache.cloudstack.usage.Usage; public class EventTypes { @@ -96,6 +97,7 @@ public class EventTypes { public static final String EVENT_VM_MOVE = "VM.MOVE"; public static final String EVENT_VM_RESTORE = "VM.RESTORE"; public static final String EVENT_VM_EXPUNGE = "VM.EXPUNGE"; + public static final String EVENT_VM_IMPORT = "VM.IMPORT"; // Domain Router public static final String EVENT_ROUTER_CREATE = "ROUTER.CREATE"; @@ -106,6 +108,7 @@ public class EventTypes { public static final String EVENT_ROUTER_HA = "ROUTER.HA"; public static final String EVENT_ROUTER_UPGRADE = "ROUTER.UPGRADE"; public static final String EVENT_ROUTER_DIAGNOSTICS = "ROUTER.DIAGNOSTICS"; + public static final String EVENT_ROUTER_HEALTH_CHECKS = "ROUTER.HEALTH.CHECKS"; // Console proxy public static final String EVENT_PROXY_CREATE = "PROXY.CREATE"; @@ -236,6 +239,8 @@ public class EventTypes { public static final String EVENT_VOLUME_DETAIL_ADD = "VOLUME.DETAIL.ADD"; public static final String EVENT_VOLUME_DETAIL_REMOVE = "VOLUME.DETAIL.REMOVE"; public static final String EVENT_VOLUME_UPDATE = "VOLUME.UPDATE"; + public static final String EVENT_VOLUME_DESTROY = "VOLUME.DESTROY"; + public static final String EVENT_VOLUME_RECOVER = "VOLUME.RECOVER"; // Domains public static final String EVENT_DOMAIN_CREATE = "DOMAIN.CREATE"; @@ -322,6 +327,7 @@ public class EventTypes { public static final String EVENT_SECURITY_GROUP_DELETE = "SG.DELETE"; public static final String EVENT_SECURITY_GROUP_ASSIGN = "SG.ASSIGN"; public static final String EVENT_SECURITY_GROUP_REMOVE = "SG.REMOVE"; + public static final String EVENT_SECURITY_GROUP_UPDATE = "SG.UPDATE"; // Host public static final String EVENT_HOST_RECONNECT = "HOST.RECONNECT"; @@ -594,6 +600,7 @@ public class EventTypes { entityEventDetails.put(EVENT_VM_MOVE, VirtualMachine.class); entityEventDetails.put(EVENT_VM_RESTORE, VirtualMachine.class); entityEventDetails.put(EVENT_VM_EXPUNGE, VirtualMachine.class); + entityEventDetails.put(EVENT_VM_IMPORT, VirtualMachine.class); entityEventDetails.put(EVENT_ROUTER_CREATE, VirtualRouter.class); entityEventDetails.put(EVENT_ROUTER_DESTROY, VirtualRouter.class); @@ -603,6 +610,7 @@ public class EventTypes { entityEventDetails.put(EVENT_ROUTER_HA, VirtualRouter.class); entityEventDetails.put(EVENT_ROUTER_UPGRADE, VirtualRouter.class); entityEventDetails.put(EVENT_ROUTER_DIAGNOSTICS, VirtualRouter.class); + entityEventDetails.put(EVENT_ROUTER_HEALTH_CHECKS, VirtualRouter.class); entityEventDetails.put(EVENT_PROXY_CREATE, VirtualMachine.class); entityEventDetails.put(EVENT_PROXY_DESTROY, VirtualMachine.class); @@ -701,6 +709,8 @@ public class EventTypes { entityEventDetails.put(EVENT_VOLUME_UPLOAD, Volume.class); entityEventDetails.put(EVENT_VOLUME_MIGRATE, Volume.class); entityEventDetails.put(EVENT_VOLUME_RESIZE, Volume.class); + entityEventDetails.put(EVENT_VOLUME_DESTROY, Volume.class); + entityEventDetails.put(EVENT_VOLUME_RECOVER, Volume.class); // Domains entityEventDetails.put(EVENT_DOMAIN_CREATE, Domain.class); diff --git a/api/src/main/java/com/cloud/network/Network.java b/api/src/main/java/com/cloud/network/Network.java index 2cabd0214189..28528f1b558d 100644 --- a/api/src/main/java/com/cloud/network/Network.java +++ b/api/src/main/java/com/cloud/network/Network.java @@ -21,6 +21,8 @@ import java.util.ArrayList; import java.util.List; +import com.cloud.exception.InvalidParameterValueException; +import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.builder.ToStringBuilder; import org.apache.commons.lang.builder.ToStringStyle; @@ -44,6 +46,24 @@ enum GuestType { Shared, Isolated, L2 } + enum PVlanType { + Community, Isolated, Promiscuous; + + static PVlanType fromValue(String type) { + if (StringUtils.isBlank(type)) { + return null; + } else if (type.equalsIgnoreCase("promiscuous") || type.equalsIgnoreCase("p")) { + return Promiscuous; + } else if (type.equalsIgnoreCase("community") || type.equalsIgnoreCase("c")) { + return Community; + } else if (type.equalsIgnoreCase("isolated") || type.equalsIgnoreCase("i")) { + return Isolated; + } else { + throw new InvalidParameterValueException("Unexpected Private VLAN type: " + type); + } + } + } + String updatingInSequence = "updatingInSequence"; String hideIpAddressUsage = "hideIpAddressUsage"; @@ -416,4 +436,6 @@ public void setIp6Address(String ip6Address) { boolean isStrechedL2Network(); String getExternalId(); + + PVlanType getPvlanType(); } diff --git a/api/src/main/java/com/cloud/network/NetworkProfile.java b/api/src/main/java/com/cloud/network/NetworkProfile.java index bf21c93c89f8..117f90e62a43 100644 --- a/api/src/main/java/com/cloud/network/NetworkProfile.java +++ b/api/src/main/java/com/cloud/network/NetworkProfile.java @@ -314,4 +314,9 @@ public String getExternalId() { return externalId; } + @Override + public PVlanType getPvlanType() { + return null; + } + } diff --git a/api/src/main/java/com/cloud/network/NetworkService.java b/api/src/main/java/com/cloud/network/NetworkService.java index 04f240b5e13e..f90c3d423b2b 100644 --- a/api/src/main/java/com/cloud/network/NetworkService.java +++ b/api/src/main/java/com/cloud/network/NetworkService.java @@ -72,7 +72,9 @@ IpAddress allocatePortableIP(Account ipOwner, int regionId, Long zoneId, Long ne boolean deleteNetwork(long networkId, boolean forced); - boolean restartNetwork(RestartNetworkCmd cmd, boolean cleanup, boolean makeRedundant) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException; + boolean restartNetwork(Long networkId, boolean cleanup, boolean makeRedundant, User user) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException; + + boolean restartNetwork(RestartNetworkCmd cmd) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException; int getActiveNicsInNetwork(long networkId); diff --git a/api/src/main/java/com/cloud/network/RouterHealthCheckResult.java b/api/src/main/java/com/cloud/network/RouterHealthCheckResult.java new file mode 100644 index 000000000000..eb65ae9088ec --- /dev/null +++ b/api/src/main/java/com/cloud/network/RouterHealthCheckResult.java @@ -0,0 +1,34 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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. + +package com.cloud.network; + +import java.util.Date; + +public interface RouterHealthCheckResult { + long getRouterId(); + + String getCheckName(); + + String getCheckType(); + + boolean getCheckResult(); + + Date getLastUpdateTime(); + + String getParsedCheckDetails(); +} diff --git a/api/src/main/java/com/cloud/network/VirtualNetworkApplianceService.java b/api/src/main/java/com/cloud/network/VirtualNetworkApplianceService.java index 815ae4d6ae31..98fb8be7c7a9 100644 --- a/api/src/main/java/com/cloud/network/VirtualNetworkApplianceService.java +++ b/api/src/main/java/com/cloud/network/VirtualNetworkApplianceService.java @@ -31,8 +31,7 @@ public interface VirtualNetworkApplianceService { /** * Starts domain router * - * @param cmd - * the command specifying router's id + * @param cmd the command specifying router's id * @return DomainRouter object */ VirtualRouter startRouter(long routerId, boolean reprogramNetwork) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException; @@ -51,10 +50,8 @@ public interface VirtualNetworkApplianceService { /** * Stops domain router * - * @param id - * of the router - * @param forced - * just do it. caller knows best. + * @param id of the router + * @param forced just do it. caller knows best. * @return router if successful, null otherwise * @throws ResourceUnavailableException * @throws ConcurrentOperationException @@ -68,4 +65,13 @@ public interface VirtualNetworkApplianceService { VirtualRouter findRouter(long routerId); List upgradeRouterTemplate(UpgradeRouterTemplateCmd cmd); + + /** + * Updates router with latest health checkdata, runs health checks and persists health checks on virtual router if feasible. + * Throws relevant exception if feature is disabled or failures occur. + * + * @param routerId id of the router + * @return + */ + boolean performRouterHealthChecks(long routerId); } diff --git a/api/src/main/java/com/cloud/network/security/SecurityGroupService.java b/api/src/main/java/com/cloud/network/security/SecurityGroupService.java index d8b3346f54a4..dce7b3d41fea 100644 --- a/api/src/main/java/com/cloud/network/security/SecurityGroupService.java +++ b/api/src/main/java/com/cloud/network/security/SecurityGroupService.java @@ -18,16 +18,17 @@ import java.util.List; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.exception.PermissionDeniedException; +import com.cloud.exception.ResourceInUseException; + import org.apache.cloudstack.api.command.user.securitygroup.AuthorizeSecurityGroupEgressCmd; import org.apache.cloudstack.api.command.user.securitygroup.AuthorizeSecurityGroupIngressCmd; import org.apache.cloudstack.api.command.user.securitygroup.CreateSecurityGroupCmd; import org.apache.cloudstack.api.command.user.securitygroup.DeleteSecurityGroupCmd; import org.apache.cloudstack.api.command.user.securitygroup.RevokeSecurityGroupEgressCmd; import org.apache.cloudstack.api.command.user.securitygroup.RevokeSecurityGroupIngressCmd; - -import com.cloud.exception.InvalidParameterValueException; -import com.cloud.exception.PermissionDeniedException; -import com.cloud.exception.ResourceInUseException; +import org.apache.cloudstack.api.command.user.securitygroup.UpdateSecurityGroupCmd; public interface SecurityGroupService { /** @@ -43,6 +44,8 @@ public interface SecurityGroupService { boolean deleteSecurityGroup(DeleteSecurityGroupCmd cmd) throws ResourceInUseException; + SecurityGroup updateSecurityGroup(UpdateSecurityGroupCmd cmd); + public List authorizeSecurityGroupIngress(AuthorizeSecurityGroupIngressCmd cmd); public List authorizeSecurityGroupEgress(AuthorizeSecurityGroupEgressCmd cmd); diff --git a/api/src/main/java/com/cloud/network/vpc/VpcService.java b/api/src/main/java/com/cloud/network/vpc/VpcService.java index 241e27b1552e..5fc339e64cb8 100644 --- a/api/src/main/java/com/cloud/network/vpc/VpcService.java +++ b/api/src/main/java/com/cloud/network/vpc/VpcService.java @@ -21,6 +21,7 @@ import org.apache.cloudstack.api.command.user.vpc.ListPrivateGatewaysCmd; import org.apache.cloudstack.api.command.user.vpc.ListStaticRoutesCmd; +import org.apache.cloudstack.api.command.user.vpc.RestartVPCCmd; import com.cloud.exception.ConcurrentOperationException; import com.cloud.exception.InsufficientAddressCapacityException; @@ -29,6 +30,7 @@ import com.cloud.exception.ResourceAllocationException; import com.cloud.exception.ResourceUnavailableException; import com.cloud.network.IpAddress; +import com.cloud.user.User; import com.cloud.utils.Pair; public interface VpcService { @@ -132,7 +134,9 @@ public Pair, Integer> listVpcs(Long id, String vpcName, Stri * @return * @throws InsufficientCapacityException */ - boolean restartVpc(long id, boolean cleanUp, boolean makeredundant) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException; + boolean restartVpc(RestartVPCCmd cmd) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException; + + boolean restartVpc(Long networkId, boolean cleanup, boolean makeRedundant, User user) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException; /** * Returns a Private gateway found in the VPC by id diff --git a/api/src/main/java/com/cloud/offering/NetworkOffering.java b/api/src/main/java/com/cloud/offering/NetworkOffering.java index 45450745df1b..8ae90c574224 100644 --- a/api/src/main/java/com/cloud/offering/NetworkOffering.java +++ b/api/src/main/java/com/cloud/offering/NetworkOffering.java @@ -38,7 +38,7 @@ public enum State { } public enum Detail { - InternalLbProvider, PublicLbProvider, servicepackageuuid, servicepackagedescription, PromiscuousMode, MacAddressChanges, ForgedTransmits, RelatedNetworkOffering, domainid, zoneid + InternalLbProvider, PublicLbProvider, servicepackageuuid, servicepackagedescription, PromiscuousMode, MacAddressChanges, ForgedTransmits, RelatedNetworkOffering, domainid, zoneid, pvlanType } public final static String SystemPublicNetwork = "System-Public-Network"; diff --git a/api/src/main/java/com/cloud/storage/Volume.java b/api/src/main/java/com/cloud/storage/Volume.java index 0e86ac016386..dde9d60a8482 100644 --- a/api/src/main/java/com/cloud/storage/Volume.java +++ b/api/src/main/java/com/cloud/storage/Volume.java @@ -124,6 +124,7 @@ public String getDescription() { s_fsm.addTransition(new StateMachine2.Transition(Ready, Event.AttachRequested, Attaching, null)); s_fsm.addTransition(new StateMachine2.Transition(Attaching, Event.OperationSucceeded, Ready, null)); s_fsm.addTransition(new StateMachine2.Transition(Attaching, Event.OperationFailed, Ready, null)); + s_fsm.addTransition(new StateMachine2.Transition(Destroy, Event.RecoverRequested, Ready, null)); } } @@ -143,6 +144,7 @@ enum Event { SnapshotRequested, RevertSnapshotRequested, DestroyRequested, + RecoverRequested, ExpungingRequested, ResizeRequested, AttachRequested, diff --git a/api/src/main/java/com/cloud/storage/VolumeApiService.java b/api/src/main/java/com/cloud/storage/VolumeApiService.java index aa6d8a664c8d..5c4130158cd8 100644 --- a/api/src/main/java/com/cloud/storage/VolumeApiService.java +++ b/api/src/main/java/com/cloud/storage/VolumeApiService.java @@ -148,4 +148,8 @@ Snapshot takeSnapshot(Long volumeId, Long policyId, Long snapshotId, Account acc * */ boolean doesTargetStorageSupportDiskOffering(StoragePool destPool, String diskOfferingTags); -} \ No newline at end of file + + Volume destroyVolume(long volumeId, Account caller, boolean expunge, boolean forceExpunge); + + Volume recoverVolume(long volumeId); +} diff --git a/api/src/main/java/com/cloud/vm/UserVmService.java b/api/src/main/java/com/cloud/vm/UserVmService.java index 99eb827c1227..50786d2e4936 100644 --- a/api/src/main/java/com/cloud/vm/UserVmService.java +++ b/api/src/main/java/com/cloud/vm/UserVmService.java @@ -396,7 +396,7 @@ UserVm createAdvancedVirtualMachine(DataCenter zone, ServiceOffering serviceOffe * @throws ResourceUnavailableException * if the resources required the deploy the VM is not currently available. */ - UserVm startVirtualMachine(DeployVMCmd cmd) throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException; + UserVm startVirtualMachine(DeployVMCmd cmd) throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException, ResourceAllocationException; /** * Creates a vm group. @@ -513,4 +513,8 @@ UserVm upgradeVirtualMachine(ScaleVMCmd cmd) throws ResourceUnavailableException void collectVmNetworkStatistics (UserVm userVm); + UserVm importVM(final DataCenter zone, final Host host, final VirtualMachineTemplate template, final String instanceName, final String displayName, final Account owner, final String userData, final Account caller, final Boolean isDisplayVm, final String keyboard, + final long accountId, final long userId, final ServiceOffering serviceOffering, final String sshPublicKey, + final String hostName, final HypervisorType hypervisorType, final Map customParameters, final VirtualMachine.PowerState powerState) throws InsufficientCapacityException; + } diff --git a/api/src/main/java/com/cloud/vm/VmDetailConstants.java b/api/src/main/java/com/cloud/vm/VmDetailConstants.java index 84de8c9ebac8..7c40a7ba421c 100644 --- a/api/src/main/java/com/cloud/vm/VmDetailConstants.java +++ b/api/src/main/java/com/cloud/vm/VmDetailConstants.java @@ -54,4 +54,12 @@ public interface VmDetailConstants { String SSH_PUBLIC_KEY = "SSH.PublicKey"; String PASSWORD = "password"; String ENCRYPTED_PASSWORD = "Encrypted.Password"; + + // VM import with nic, disk and custom params for custom compute offering + String NIC = "nic"; + String NETWORK = "network"; + String IP4_ADDRESS = "ip4Address"; + String IP6_ADDRESS = "ip6Address"; + String DISK = "disk"; + String DISK_OFFERING = "diskOffering"; } diff --git a/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java b/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java index b1ea142f7a6d..015061cd2d37 100644 --- a/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java +++ b/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java @@ -22,6 +22,7 @@ public class ApiConstants { public static final String ACCOUNT_TYPE = "accounttype"; public static final String ACCOUNT_ID = "accountid"; public static final String ACTIVITY = "activity"; + public static final String ADAPTER_TYPE = "adaptertype"; public static final String ADDRESS = "address"; public static final String ALGORITHM = "algorithm"; public static final String ALLOCATED_ONLY = "allocatedonly"; @@ -43,6 +44,7 @@ public class ApiConstants { public static final String BYTES_WRITE_RATE_MAX = "byteswriteratemax"; public static final String BYTES_WRITE_RATE_MAX_LENGTH = "byteswriteratemaxlength"; public static final String BYPASS_VLAN_OVERLAP_CHECK = "bypassvlanoverlapcheck"; + public static final String CAPACITY = "capacity"; public static final String CATEGORY = "category"; public static final String CAN_REVERT = "canrevert"; public static final String CA_CERTIFICATES = "cacertificates"; @@ -50,9 +52,15 @@ public class ApiConstants { public static final String CERTIFICATE_CHAIN = "certchain"; public static final String CERTIFICATE_FINGERPRINT = "fingerprint"; public static final String CERTIFICATE_ID = "certid"; + public static final String CONTROLLER = "controller"; + public static final String CONTROLLER_UNIT = "controllerunit"; public static final String COPY_IMAGE_TAGS = "copyimagetags"; public static final String CSR = "csr"; public static final String PRIVATE_KEY = "privatekey"; + public static final String DATASTORE_HOST = "datastorehost"; + public static final String DATASTORE_NAME = "datastorename"; + public static final String DATASTORE_PATH = "datastorepath"; + public static final String DATASTORE_TYPE = "datastoretype"; public static final String DOMAIN_SUFFIX = "domainsuffix"; public static final String DNS_SEARCH_ORDER = "dnssearchorder"; public static final String CHAIN_INFO = "chaininfo"; @@ -69,6 +77,7 @@ public class ApiConstants { public static final String COMMAND = "command"; public static final String CMD_EVENT_TYPE = "cmdeventtype"; public static final String COMPONENT = "component"; + public static final String CPU_CORE_PER_SOCKET = "cpucorepersocket"; public static final String CPU_NUMBER = "cpunumber"; public static final String CPU_SPEED = "cpuspeed"; public static final String CPU_LOAD_AVERAGE = "cpuloadaverage"; @@ -91,6 +100,7 @@ public class ApiConstants { public static final String DETAILS = "details"; public static final String DEVICE_ID = "deviceid"; public static final String DIRECT_DOWNLOAD = "directdownload"; + public static final String DISK = "disk"; public static final String DISK_OFFERING_ID = "diskofferingid"; public static final String NEW_DISK_OFFERING_ID = "newdiskofferingid"; public static final String DISK_KBS_READ = "diskkbsread"; @@ -170,6 +180,7 @@ public class ApiConstants { public static final String PREVIOUS_ACL_RULE_ID = "previousaclruleid"; public static final String NEXT_ACL_RULE_ID = "nextaclruleid"; public static final String MOVE_ACL_CONSISTENCY_HASH = "aclconsistencyhash"; + public static final String IMAGE_PATH = "imagepath"; public static final String INTERNAL_DNS1 = "internaldns1"; public static final String INTERNAL_DNS2 = "internaldns2"; public static final String INTERVAL_TYPE = "intervaltype"; @@ -181,6 +192,7 @@ public class ApiConstants { public static final String IOPS_WRITE_RATE_MAX = "iopswriteratemax"; public static final String IOPS_WRITE_RATE_MAX_LENGTH = "iopswriteratemaxlength"; public static final String IP_ADDRESS = "ipaddress"; + public static final String IP_ADDRESSES = "ipaddresses"; public static final String IP6_ADDRESS = "ip6address"; public static final String IP_ADDRESS_ID = "ipaddressid"; public static final String IS_ASYNC = "isasync"; @@ -224,6 +236,9 @@ public class ApiConstants { public static final String NETWORK_DOMAIN = "networkdomain"; public static final String NETMASK = "netmask"; public static final String NEW_NAME = "newname"; + public static final String NIC = "nic"; + public static final String NIC_NETWORK_LIST = "nicnetworklist"; + public static final String NIC_IP_ADDRESS_LIST = "nicipaddresslist"; public static final String NUM_RETRIES = "numretries"; public static final String OFFER_HA = "offerha"; public static final String IS_SYSTEM_OFFERING = "issystem"; @@ -231,6 +246,7 @@ public class ApiConstants { public static final String OLD_FORMAT = "oldformat"; public static final String OP = "op"; public static final String OS_CATEGORY_ID = "oscategoryid"; + public static final String OS_ID = "osid"; public static final String OS_TYPE_ID = "ostypeid"; public static final String OS_DISPLAY_NAME = "osdisplayname"; public static final String OS_NAME_FOR_HYPERVISOR = "osnameforhypervisor"; @@ -255,6 +271,7 @@ public class ApiConstants { public static final String PORTAL = "portal"; public static final String PORTABLE_IP_ADDRESS = "portableipaddress"; public static final String PORT_FORWARDING_SERVICE_ID = "portforwardingserviceid"; + public static final String POSITION = "position"; public static final String POST_URL = "postURL"; public static final String POWER_STATE = "powerstate"; public static final String PRIVATE_INTERFACE = "privateinterface"; @@ -360,6 +377,7 @@ public class ApiConstants { public static final String REMOVE_VLAN = "removevlan"; public static final String VLAN_ID = "vlanid"; public static final String ISOLATED_PVLAN = "isolatedpvlan"; + public static final String ISOLATED_PVLAN_TYPE = "isolatedpvlantype"; public static final String ISOLATION_URI = "isolationuri"; public static final String VM_AVAILABLE = "vmavailable"; public static final String VM_LIMIT = "vmlimit"; @@ -531,6 +549,7 @@ public class ApiConstants { public static final String CUSTOM_DISK_OFF_MAX_SIZE = "customdiskofferingmaxsize"; public static final String DEFAULT_ZONE_ID = "defaultzoneid"; public static final String LIVE_MIGRATE = "livemigrate"; + public static final String MIGRATE_ALLOWED = "migrateallowed"; public static final String MIGRATE_TO = "migrateto"; public static final String GUID = "guid"; public static final String VSWITCH_TYPE_GUEST_TRAFFIC = "guestvswitchtype"; @@ -727,6 +746,7 @@ public class ApiConstants { public static final String VIRTUAL_SIZE = "virtualsize"; public static final String NETSCALER_CONTROLCENTER_ID = "netscalercontrolcenterid"; public static final String NETSCALER_SERVICEPACKAGE_ID = "netscalerservicepackageid"; + public static final String FETCH_ROUTER_HEALTH_CHECK_RESULTS = "fetchhealthcheckresults"; public static final String ZONE_ID_LIST = "zoneids"; public static final String DESTINATION_ZONE_ID_LIST = "destzoneids"; @@ -748,6 +768,13 @@ public class ApiConstants { public static final String FILES = "files"; public static final String VOLUME_IDS = "volumeids"; + public static final String ROUTER_ID = "routerid"; + public static final String ROUTER_HEALTH_CHECKS = "healthchecks"; + public static final String ROUTER_CHECK_NAME = "checkname"; + public static final String ROUTER_CHECK_TYPE = "checktype"; + public static final String LAST_UPDATED = "lastupdated"; + public static final String PERFORM_FRESH_CHECKS = "performfreshchecks"; + public enum HostDetails { all, capacity, events, stats, min; } diff --git a/api/src/main/java/org/apache/cloudstack/api/ResponseGenerator.java b/api/src/main/java/org/apache/cloudstack/api/ResponseGenerator.java index 740ee468702f..510562bf54ae 100644 --- a/api/src/main/java/org/apache/cloudstack/api/ResponseGenerator.java +++ b/api/src/main/java/org/apache/cloudstack/api/ResponseGenerator.java @@ -22,6 +22,7 @@ import java.util.Map; import java.util.Set; +import org.apache.cloudstack.api.response.RouterHealthCheckResultResponse; import org.apache.cloudstack.management.ManagementServerHost; import org.apache.cloudstack.affinity.AffinityGroup; import org.apache.cloudstack.affinity.AffinityGroupResponse; @@ -146,6 +147,7 @@ import com.cloud.network.PhysicalNetworkServiceProvider; import com.cloud.network.PhysicalNetworkTrafficType; import com.cloud.network.RemoteAccessVpn; +import com.cloud.network.RouterHealthCheckResult; import com.cloud.network.Site2SiteCustomerGateway; import com.cloud.network.Site2SiteVpnConnection; import com.cloud.network.Site2SiteVpnGateway; @@ -466,4 +468,6 @@ List createTemplateResponses(ResponseView view, VirtualMachine SSHKeyPairResponse createSSHKeyPairResponse(SSHKeyPair sshkeyPair, boolean privatekey); ManagementServerResponse createManagementResponse(ManagementServerHost mgmt); + + List createHealthCheckResponse(VirtualMachine router, List healthCheckResults); } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/internallb/ListInternalLBVMsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/internallb/ListInternalLBVMsCmd.java index ba2054c3c24b..fd415858f564 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/internallb/ListInternalLBVMsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/internallb/ListInternalLBVMsCmd.java @@ -16,6 +16,7 @@ // under the License. package org.apache.cloudstack.api.command.admin.internallb; +import org.apache.commons.lang.BooleanUtils; import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; @@ -73,6 +74,11 @@ public class ListInternalLBVMsCmd extends BaseListProjectAndAccountResourcesCmd @Parameter(name = ApiConstants.FOR_VPC, type = CommandType.BOOLEAN, description = "if true is passed for this parameter, list only VPC Internal LB VMs") private Boolean forVpc; + + @Parameter(name = ApiConstants.FETCH_ROUTER_HEALTH_CHECK_RESULTS, type = CommandType.BOOLEAN, since = "4.14", + description = "if true is passed for this parameter, also fetch last executed health check results for the VM. Default is false") + private Boolean fetchHealthCheckResults; + ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -117,6 +123,10 @@ public String getRole() { return Role.INTERNAL_LB_VM.toString(); } + public boolean shouldFetchHealthCheckResults() { + return BooleanUtils.isTrue(fetchHealthCheckResults); + } + ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/management/ListMgmtsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/management/ListMgmtsCmd.java index 1be49193580f..c01019e6e879 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/management/ListMgmtsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/management/ListMgmtsCmd.java @@ -22,7 +22,6 @@ import org.apache.cloudstack.api.BaseCmd; import org.apache.cloudstack.api.BaseListCmd; import org.apache.cloudstack.api.Parameter; -import org.apache.cloudstack.api.response.HostResponse; import org.apache.cloudstack.api.response.ListResponse; import org.apache.cloudstack.api.response.ManagementServerResponse; import org.apache.log4j.Logger; @@ -38,7 +37,7 @@ public class ListMgmtsCmd extends BaseListCmd { //////////////// API parameters ///////////////////// ///////////////////////////////////////////////////// - @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = HostResponse.class, description = "the id of the management server") + @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = ManagementServerResponse.class, description = "the id of the management server") private Long id; @Parameter(name = ApiConstants.NAME, type = CommandType.STRING, description = "the name of the management server") diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/router/GetRouterHealthCheckResultsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/router/GetRouterHealthCheckResultsCmd.java new file mode 100644 index 000000000000..5efc6de9e948 --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/router/GetRouterHealthCheckResultsCmd.java @@ -0,0 +1,117 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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. + +package org.apache.cloudstack.api.command.admin.router; + +import java.util.List; + +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.BaseCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.response.DomainRouterResponse; +import org.apache.cloudstack.api.response.RouterHealthCheckResultResponse; +import org.apache.cloudstack.api.response.RouterHealthCheckResultsListResponse; +import org.apache.cloudstack.context.CallContext; +import org.apache.commons.lang.BooleanUtils; +import org.apache.log4j.Logger; + +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.exception.ResourceUnavailableException; +import com.cloud.network.router.VirtualRouter; +import com.cloud.user.Account; +import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.vm.VirtualMachine; + +@APICommand(name = GetRouterHealthCheckResultsCmd.APINAME, + responseObject = RouterHealthCheckResultsListResponse.class, + description = "Starts a router.", + entityType = {VirtualMachine.class}, + requestHasSensitiveInfo = false, + responseHasSensitiveInfo = false, + since = "4.14.0") +public class GetRouterHealthCheckResultsCmd extends BaseCmd { + public static final Logger s_logger = Logger.getLogger(GetRouterHealthCheckResultsCmd.class.getName()); + public static final String APINAME = "getRouterHealthCheckResults"; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name = ApiConstants.ROUTER_ID, type = CommandType.UUID, entityType = DomainRouterResponse.class, + required = true, description = "the ID of the router") + private Long routerId; + + @Parameter(name = ApiConstants.PERFORM_FRESH_CHECKS, type = CommandType.BOOLEAN, description = "if true is passed for this parameter, " + + "health checks are performed on the fly. Else last performed checks data is fetched") + private Boolean performFreshChecks; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public Long getRouterId() { + return routerId; + } + + public boolean shouldPerformFreshChecks() { + return BooleanUtils.isTrue(performFreshChecks); + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public String getCommandName() { + return APINAME.toLowerCase() + BaseCmd.RESPONSE_SUFFIX; + } + + @Override + public long getEntityOwnerId() { + VirtualRouter router = _entityMgr.findById(VirtualRouter.class, getRouterId()); + if (router != null) { + return router.getAccountId(); + } + + return Account.ACCOUNT_ID_SYSTEM; + } + + @Override + public void execute() throws ResourceUnavailableException, InvalidParameterValueException, ServerApiException { + CallContext.current().setEventDetails("Router Id: " + this._uuidMgr.getUuid(VirtualMachine.class, getRouterId())); + VirtualRouter router = _routerService.findRouter(getRouterId()); + if (router == null || router.getRole() != VirtualRouter.Role.VIRTUAL_ROUTER) { + throw new InvalidParameterValueException("Can't find router by routerId"); + } + + try { + List healthChecks = _queryService.listRouterHealthChecks(this); + RouterHealthCheckResultsListResponse routerResponse = new RouterHealthCheckResultsListResponse(); + routerResponse.setRouterId(router.getUuid()); + routerResponse.setHealthChecks(healthChecks); + routerResponse.setObjectName("routerhealthchecks"); + routerResponse.setResponseName(getCommandName()); + setResponseObject(routerResponse); + } catch (CloudRuntimeException ex){ + ex.printStackTrace(); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to execute command due to exception: " + ex.getLocalizedMessage()); + } + } +} diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/router/ListRoutersCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/router/ListRoutersCmd.java index 121fc5bc14d2..4fabcf5df768 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/router/ListRoutersCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/router/ListRoutersCmd.java @@ -16,6 +16,7 @@ // under the License. package org.apache.cloudstack.api.command.admin.router; +import org.apache.commons.lang.BooleanUtils; import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; @@ -80,6 +81,10 @@ public class ListRoutersCmd extends BaseListProjectAndAccountResourcesCmd { @Parameter(name = ApiConstants.VERSION, type = CommandType.STRING, description = "list virtual router elements by version") private String version; + @Parameter(name = ApiConstants.FETCH_ROUTER_HEALTH_CHECK_RESULTS, type = CommandType.BOOLEAN, since = "4.14", + description = "if true is passed for this parameter, also fetch last executed health check results for the router. Default is false") + private Boolean fetchHealthCheckResults; + ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -132,6 +137,11 @@ public String getRole() { return Role.VIRTUAL_ROUTER.toString(); } + public boolean shouldFetchHealthCheckResults() { + return BooleanUtils.isTrue(fetchHealthCheckResults); + } + + ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ImportUnmanagedInstanceCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ImportUnmanagedInstanceCmd.java new file mode 100644 index 000000000000..4b367f8f08c9 --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ImportUnmanagedInstanceCmd.java @@ -0,0 +1,300 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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. + +package org.apache.cloudstack.api.command.admin.vm; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +import javax.inject.Inject; + +import org.apache.cloudstack.acl.RoleType; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseAsyncCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.ResponseObject; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.response.ClusterResponse; +import org.apache.cloudstack.api.response.DomainResponse; +import org.apache.cloudstack.api.response.ProjectResponse; +import org.apache.cloudstack.api.response.ServiceOfferingResponse; +import org.apache.cloudstack.api.response.TemplateResponse; +import org.apache.cloudstack.api.response.UserVmResponse; +import org.apache.cloudstack.context.CallContext; +import org.apache.cloudstack.vm.VmImportService; +import org.apache.commons.collections.MapUtils; +import org.apache.log4j.Logger; + +import com.cloud.event.EventTypes; +import com.cloud.exception.ConcurrentOperationException; +import com.cloud.exception.InsufficientCapacityException; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.exception.NetworkRuleConflictException; +import com.cloud.exception.ResourceAllocationException; +import com.cloud.exception.ResourceUnavailableException; +import com.cloud.network.Network; +import com.cloud.offering.DiskOffering; +import com.cloud.user.Account; +import com.cloud.utils.net.NetUtils; +import com.cloud.vm.VmDetailConstants; +import com.google.common.base.Strings; + +@APICommand(name = ImportUnmanagedInstanceCmd.API_NAME, + description = "Import unmanaged virtual machine from a given cluster.", + responseObject = UserVmResponse.class, + responseView = ResponseObject.ResponseView.Full, + requestHasSensitiveInfo = false, + responseHasSensitiveInfo = true, + authorized = {RoleType.Admin}, + since = "4.14.0") +public class ImportUnmanagedInstanceCmd extends BaseAsyncCmd { + public static final Logger LOGGER = Logger.getLogger(ImportUnmanagedInstanceCmd.class); + public static final String API_NAME = "importUnmanagedInstance"; + + @Inject + public VmImportService vmImportService; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name = ApiConstants.CLUSTER_ID, + type = CommandType.UUID, + entityType = ClusterResponse.class, + required = true, + description = "the cluster ID") + private Long clusterId; + + @Parameter(name = ApiConstants.NAME, + type = CommandType.STRING, + required = true, + description = "the hypervisor name of the instance") + private String name; + + @Parameter(name = ApiConstants.DISPLAY_NAME, + type = CommandType.STRING, + description = "the display name of the instance") + private String displayName; + + @Parameter(name = ApiConstants.HOST_NAME, + type = CommandType.STRING, + description = "the host name of the instance") + private String hostName; + + @Parameter(name = ApiConstants.ACCOUNT, + type = CommandType.STRING, + description = "an optional account for the virtual machine. Must be used with domainId.") + private String accountName; + + @Parameter(name = ApiConstants.DOMAIN_ID, + type = CommandType.UUID, + entityType = DomainResponse.class, + description = "import instance to the domain specified") + private Long domainId; + + @Parameter(name = ApiConstants.PROJECT_ID, + type = CommandType.UUID, + entityType = ProjectResponse.class, + description = "import instance for the project") + private Long projectId; + + @Parameter(name = ApiConstants.TEMPLATE_ID, + type = CommandType.UUID, + entityType = TemplateResponse.class, + description = "the ID of the template for the virtual machine") + private Long templateId; + + @Parameter(name = ApiConstants.SERVICE_OFFERING_ID, + type = CommandType.UUID, + entityType = ServiceOfferingResponse.class, + required = true, + description = "the ID of the service offering for the virtual machine") + private Long serviceOfferingId; + + @Parameter(name = ApiConstants.NIC_NETWORK_LIST, + type = CommandType.MAP, + description = "VM nic to network id mapping using keys nic and network") + private Map nicNetworkList; + + @Parameter(name = ApiConstants.NIC_IP_ADDRESS_LIST, + type = CommandType.MAP, + description = "VM nic to ip address mapping using keys nic, ip4Address") + private Map nicIpAddressList; + + @Parameter(name = ApiConstants.DATADISK_OFFERING_LIST, + type = CommandType.MAP, + description = "datadisk template to disk-offering mapping using keys disk and diskOffering") + private Map dataDiskToDiskOfferingList; + + @Parameter(name = ApiConstants.DETAILS, + type = CommandType.MAP, + description = "used to specify the custom parameters.") + private Map details; + + @Parameter(name = ApiConstants.MIGRATE_ALLOWED, + type = CommandType.BOOLEAN, + description = "vm and its volumes are allowed to migrate to different host/pool when offerings passed are incompatible with current host/pool") + private Boolean migrateAllowed; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public Long getClusterId() { + return clusterId; + } + + public String getName() { + return name; + } + + public String getDisplayName() { + return displayName; + } + + public String getHostName() { + return hostName; + } + + public String getAccountName() { + return accountName; + } + + public Long getDomainId() { + return domainId; + } + + public Long getTemplateId() { + return templateId; + } + + public Long getProjectId() { + return projectId; + } + + public Long getServiceOfferingId() { + return serviceOfferingId; + } + + public Map getNicNetworkList() { + Map nicNetworkMap = new HashMap<>(); + if (MapUtils.isNotEmpty(nicNetworkList)) { + for (Map entry : (Collection>)nicNetworkList.values()) { + String nic = entry.get(VmDetailConstants.NIC); + String networkUuid = entry.get(VmDetailConstants.NETWORK); + if (Strings.isNullOrEmpty(nic) || Strings.isNullOrEmpty(networkUuid) || _entityMgr.findByUuid(Network.class, networkUuid) == null) { + throw new InvalidParameterValueException(String.format("Network ID: %s for NIC ID: %s is invalid", networkUuid, nic)); + } + nicNetworkMap.put(nic, _entityMgr.findByUuid(Network.class, networkUuid).getId()); + } + } + return nicNetworkMap; + } + + public Map getNicIpAddressList() { + Map nicIpAddressMap = new HashMap<>(); + if (MapUtils.isNotEmpty(nicIpAddressList)) { + for (Map entry : (Collection>)nicIpAddressList.values()) { + String nic = entry.get(VmDetailConstants.NIC); + String ipAddress = Strings.emptyToNull(entry.get(VmDetailConstants.IP4_ADDRESS)); + if (Strings.isNullOrEmpty(nic)) { + throw new InvalidParameterValueException(String.format("NIC ID: '%s' is invalid for IP address mapping", nic)); + } + if (Strings.isNullOrEmpty(ipAddress)) { + throw new InvalidParameterValueException(String.format("IP address '%s' for NIC ID: %s is invalid", ipAddress, nic)); + } + if (!Strings.isNullOrEmpty(ipAddress) && !ipAddress.equals("auto") && !NetUtils.isValidIp4(ipAddress)) { + throw new InvalidParameterValueException(String.format("IP address '%s' for NIC ID: %s is invalid", ipAddress, nic)); + } + Network.IpAddresses ipAddresses = new Network.IpAddresses(ipAddress, null); + nicIpAddressMap.put(nic, ipAddresses); + } + } + return nicIpAddressMap; + } + + public Map getDataDiskToDiskOfferingList() { + Map dataDiskToDiskOfferingMap = new HashMap<>(); + if (MapUtils.isNotEmpty(dataDiskToDiskOfferingList)) { + for (Map entry : (Collection>)dataDiskToDiskOfferingList.values()) { + String nic = entry.get(VmDetailConstants.DISK); + String offeringUuid = entry.get(VmDetailConstants.DISK_OFFERING); + if (Strings.isNullOrEmpty(nic) || Strings.isNullOrEmpty(offeringUuid) || _entityMgr.findByUuid(DiskOffering.class, offeringUuid) == null) { + throw new InvalidParameterValueException(String.format("Disk offering ID: %s for disk ID: %s is invalid", offeringUuid, nic)); + } + dataDiskToDiskOfferingMap.put(nic, _entityMgr.findByUuid(DiskOffering.class, offeringUuid).getId()); + } + } + return dataDiskToDiskOfferingMap; + } + + public Map getDetails() { + if (MapUtils.isEmpty(details)) { + return new HashMap(); + } + + Collection paramsCollection = details.values(); + Map params = (Map) (paramsCollection.toArray())[0]; + return params; + } + + public Boolean getMigrateAllowed() { + return migrateAllowed == Boolean.TRUE; + } + + @Override + public String getEventType() { + return EventTypes.EVENT_VM_IMPORT; + } + + @Override + public String getEventDescription() { + return "Importing unmanaged VM"; + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException { + UserVmResponse response = vmImportService.importUnmanagedInstance(this); + response.setResponseName(getCommandName()); + setResponseObject(response); + } + + @Override + public String getCommandName() { + return API_NAME.toLowerCase() + BaseAsyncCmd.RESPONSE_SUFFIX; + } + + @Override + public long getEntityOwnerId() { + Long accountId = _accountService.finalyzeAccountId(accountName, domainId, projectId, true); + if (accountId == null) { + Account account = CallContext.current().getCallingAccount(); + if (account != null) { + accountId = account.getId(); + } else { + accountId = Account.ACCOUNT_ID_SYSTEM; + } + } + return accountId; + } +} diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ListUnmanagedInstancesCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ListUnmanagedInstancesCmd.java new file mode 100644 index 000000000000..a991ef4e03d6 --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ListUnmanagedInstancesCmd.java @@ -0,0 +1,113 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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. + +package org.apache.cloudstack.api.command.admin.vm; + +import javax.inject.Inject; + +import org.apache.cloudstack.acl.RoleType; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseAsyncCmd; +import org.apache.cloudstack.api.BaseListCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.ResponseObject; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.response.ClusterResponse; +import org.apache.cloudstack.api.response.ListResponse; +import org.apache.cloudstack.api.response.UnmanagedInstanceResponse; +import org.apache.cloudstack.context.CallContext; +import org.apache.cloudstack.vm.UnmanagedInstanceTO; +import org.apache.cloudstack.vm.VmImportService; +import org.apache.log4j.Logger; + +import com.cloud.exception.ConcurrentOperationException; +import com.cloud.exception.InsufficientCapacityException; +import com.cloud.exception.NetworkRuleConflictException; +import com.cloud.exception.ResourceAllocationException; +import com.cloud.exception.ResourceUnavailableException; +import com.cloud.user.Account; + +@APICommand(name = ListUnmanagedInstancesCmd.API_NAME, + description = "Lists unmanaged virtual machines for a given cluster.", + responseObject = UnmanagedInstanceResponse.class, + responseView = ResponseObject.ResponseView.Full, + entityType = {UnmanagedInstanceTO.class}, + requestHasSensitiveInfo = false, + responseHasSensitiveInfo = true, + authorized = {RoleType.Admin}, + since = "4.14.0") +public class ListUnmanagedInstancesCmd extends BaseListCmd { + public static final Logger LOGGER = Logger.getLogger(ListUnmanagedInstancesCmd.class.getName()); + public static final String API_NAME = "listUnmanagedInstances"; + + @Inject + public VmImportService vmImportService; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name = ApiConstants.CLUSTER_ID, + type = CommandType.UUID, + entityType = ClusterResponse.class, + required = true, + description = "the cluster ID") + private Long clusterId; + + @Parameter(name = ApiConstants.NAME, + type = CommandType.STRING, + description = "the hypervisor name of the instance") + private String name; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public Long getClusterId() { + return clusterId; + } + + public String getName() { + return name; + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException { + ListResponse response = vmImportService.listUnmanagedInstances(this); + response.setResponseName(getCommandName()); + setResponseObject(response); + } + + @Override + public String getCommandName() { + return API_NAME.toLowerCase() + BaseAsyncCmd.RESPONSE_SUFFIX; + } + + @Override + public long getEntityOwnerId() { + Account account = CallContext.current().getCallingAccount(); + if (account != null) { + return account.getId(); + } + return Account.ACCOUNT_ID_SYSTEM; + } +} diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/volume/DestroyVolumeCmdByAdmin.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/volume/DestroyVolumeCmdByAdmin.java new file mode 100644 index 000000000000..44ce32f90c2f --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/volume/DestroyVolumeCmdByAdmin.java @@ -0,0 +1,54 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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. +package org.apache.cloudstack.api.command.admin.volume; + +import org.apache.log4j.Logger; + +import org.apache.cloudstack.acl.RoleType; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.ResponseObject.ResponseView; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.command.admin.AdminCmd; +import org.apache.cloudstack.api.command.user.volume.DestroyVolumeCmd; +import org.apache.cloudstack.api.response.VolumeResponse; +import org.apache.cloudstack.context.CallContext; + +import com.cloud.storage.Volume; + +@APICommand(name = "destroyVolume", description = "Destroys a Volume.", responseObject = VolumeResponse.class, responseView = ResponseView.Full, entityType = {Volume.class}, + since = "4.14.0", + authorized = {RoleType.Admin}, + requestHasSensitiveInfo = false, + responseHasSensitiveInfo = true) +public class DestroyVolumeCmdByAdmin extends DestroyVolumeCmd implements AdminCmd { + + public static final Logger s_logger = Logger.getLogger(DestroyVolumeCmdByAdmin.class.getName()); + + @Override + public void execute() { + CallContext.current().setEventDetails("Volume Id: " + getId()); + Volume result = _volumeService.destroyVolume(getId(), CallContext.current().getCallingAccount(), getExpunge(), false); + if (result != null) { + VolumeResponse response = _responseGenerator.createVolumeResponse(ResponseView.Full, result); + response.setResponseName(getCommandName()); + setResponseObject(response); + } else { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to destroy volume"); + } + } +} diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/volume/RecoverVolumeCmdByAdmin.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/volume/RecoverVolumeCmdByAdmin.java new file mode 100644 index 000000000000..f51aeec97197 --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/volume/RecoverVolumeCmdByAdmin.java @@ -0,0 +1,53 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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. +package org.apache.cloudstack.api.command.admin.volume; + +import org.apache.log4j.Logger; + +import org.apache.cloudstack.acl.RoleType; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.ResponseObject.ResponseView; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.command.admin.AdminCmd; +import org.apache.cloudstack.api.command.user.volume.RecoverVolumeCmd; +import org.apache.cloudstack.api.response.VolumeResponse; +import org.apache.cloudstack.context.CallContext; + +import com.cloud.storage.Volume; + +@APICommand(name = "recoverVolume", description = "Recovers a Destroy volume.", responseObject = VolumeResponse.class, responseView = ResponseView.Full, entityType = {Volume.class}, + since = "4.14.0", + authorized = {RoleType.Admin}, + requestHasSensitiveInfo = false, + responseHasSensitiveInfo = true) +public class RecoverVolumeCmdByAdmin extends RecoverVolumeCmd implements AdminCmd { + public static final Logger s_logger = Logger.getLogger(RecoverVolumeCmdByAdmin.class.getName()); + + @Override + public void execute() { + CallContext.current().setEventDetails("Volume Id: " + getId()); + Volume result = _volumeService.recoverVolume(getId()); + if (result != null) { + VolumeResponse response = _responseGenerator.createVolumeResponse(ResponseView.Full, result); + response.setResponseName(getCommandName()); + setResponseObject(response); + } else { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to recover volume"); + } + } +} diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/config/ListCapabilitiesCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/config/ListCapabilitiesCmd.java index 40d1a71e9662..3f1b9a23de3b 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/config/ListCapabilitiesCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/config/ListCapabilitiesCmd.java @@ -59,6 +59,7 @@ public void execute() { response.setKVMSnapshotEnabled((Boolean)capabilities.get("KVMSnapshotEnabled")); response.setAllowUserViewDestroyedVM((Boolean)capabilities.get("allowUserViewDestroyedVM")); response.setAllowUserExpungeRecoverVM((Boolean)capabilities.get("allowUserExpungeRecoverVM")); + response.setAllowUserExpungeRecoverVolume((Boolean)capabilities.get("allowUserExpungeRecoverVolume")); response.setAllowUserViewAllDomainAccounts((Boolean)capabilities.get("allowUserViewAllDomainAccounts")); if (capabilities.containsKey("apiLimitInterval")) { response.setApiLimitInterval((Integer)capabilities.get("apiLimitInterval")); diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/network/CreateNetworkCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/network/CreateNetworkCmd.java index d89205eb62d4..5dff7c9bf2bb 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/network/CreateNetworkCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/network/CreateNetworkCmd.java @@ -97,6 +97,10 @@ public class CreateNetworkCmd extends BaseCmd implements UserCmd { @Parameter(name = ApiConstants.ISOLATED_PVLAN, type = CommandType.STRING, description = "the isolated private VLAN for this network") private String isolatedPvlan; + @Parameter(name = ApiConstants.ISOLATED_PVLAN_TYPE, type = CommandType.STRING, + description = "the isolated private VLAN type for this network") + private String isolatedPvlanType; + @Parameter(name = ApiConstants.NETWORK_DOMAIN, type = CommandType.STRING, description = "network domain") private String networkDomain; @@ -217,6 +221,10 @@ public String getExternalId() { return externalId; } + public String getIsolatedPvlanType() { + return isolatedPvlanType; + } + @Override public boolean isDisplay() { if(displayNetwork == null) diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/network/RestartNetworkCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/network/RestartNetworkCmd.java index 645ae5aff8e3..d422966388cd 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/network/RestartNetworkCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/network/RestartNetworkCmd.java @@ -96,7 +96,7 @@ public static String getResultObjectName() { @Override public void execute() throws ResourceUnavailableException, ResourceAllocationException, ConcurrentOperationException, InsufficientCapacityException { - boolean result = _networkService.restartNetwork(this, getCleanup(), getMakeRedundant()); + boolean result = _networkService.restartNetwork(this); if (result) { SuccessResponse response = new SuccessResponse(getCommandName()); setResponseObject(response); diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/securitygroup/UpdateSecurityGroupCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/securitygroup/UpdateSecurityGroupCmd.java new file mode 100644 index 000000000000..154ae71d6e1e --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/securitygroup/UpdateSecurityGroupCmd.java @@ -0,0 +1,105 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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. +package org.apache.cloudstack.api.command.user.securitygroup; + +import org.apache.log4j.Logger; + +import org.apache.cloudstack.acl.RoleType; +import org.apache.cloudstack.acl.SecurityChecker.AccessType; +import org.apache.cloudstack.api.ACL; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.BaseCustomIdCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.response.SecurityGroupResponse; + +import com.cloud.network.security.SecurityGroup; +import com.cloud.user.Account; + +@APICommand(name = UpdateSecurityGroupCmd.APINAME, description = "Updates a security group", responseObject = SecurityGroupResponse.class, entityType = {SecurityGroup.class}, + requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, + since = "4.14.0.0", + authorized = {RoleType.Admin}) +public class UpdateSecurityGroupCmd extends BaseCustomIdCmd { + public static final String APINAME = "updateSecurityGroup"; + public static final Logger s_logger = Logger.getLogger(UpdateSecurityGroupCmd.class.getName()); + private static final String s_name = "updatesecuritygroupresponse"; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @ACL(accessType = AccessType.OperateEntry) + @Parameter(name = ApiConstants.ID, type = CommandType.UUID, required=true, description="The ID of the security group.", entityType=SecurityGroupResponse.class) + private Long id; + + @Parameter(name = ApiConstants.NAME, type = CommandType.STRING, description = "The new name of the security group.") + private String name; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public Long getId() { + return id; + } + + public String getName() { + return name; + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public String getCommandName() { + return s_name; + } + + @Override + public long getEntityOwnerId() { + SecurityGroup securityGroup = _entityMgr.findById(SecurityGroup.class, getId()); + if (securityGroup != null) { + return securityGroup.getAccountId(); + } + + return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this command to SYSTEM so ERROR events are tracked + } + + @Override + public void execute() { + SecurityGroup result = _securityGroupService.updateSecurityGroup(this); + if (result != null) { + SecurityGroupResponse response = _responseGenerator.createSecurityGroupResponse(result); + response.setResponseName(getCommandName()); + setResponseObject(response); + } else { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to update security group"); + } + } + + @Override + public void checkUuid() { + if (getCustomId() != null) { + _uuidMgr.checkUuid(getCustomId(), SecurityGroup.class); + } + } + +} diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/vm/DeployVMCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/vm/DeployVMCmd.java index c161897032ea..60b9f312a8ef 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/vm/DeployVMCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/vm/DeployVMCmd.java @@ -588,6 +588,9 @@ public void execute() { } catch (ResourceUnavailableException ex) { s_logger.warn("Exception: ", ex); throw new ServerApiException(ApiErrorCode.RESOURCE_UNAVAILABLE_ERROR, ex.getMessage()); + } catch (ResourceAllocationException ex) { + s_logger.warn("Exception: ", ex); + throw new ServerApiException(ApiErrorCode.RESOURCE_ALLOCATION_ERROR, ex.getMessage()); } catch (ConcurrentOperationException ex) { s_logger.warn("Exception: ", ex); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage()); diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/vm/StartVMCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/vm/StartVMCmd.java index 365d406b22ba..2a7f6d0316de 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/vm/StartVMCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/vm/StartVMCmd.java @@ -154,7 +154,7 @@ public Long getInstanceId() { } @Override - public void execute() throws ResourceUnavailableException, ResourceAllocationException { + public void execute() { try { CallContext.current().setEventDetails("Vm Id: " + this._uuidMgr.getUuid(VirtualMachine.class, getId())); @@ -177,6 +177,12 @@ public void execute() throws ResourceUnavailableException, ResourceAllocationExc } catch (ExecutionException ex) { s_logger.warn("Exception: ", ex); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage()); + } catch (ResourceUnavailableException ex) { + s_logger.warn("Exception: ", ex); + throw new ServerApiException(ApiErrorCode.RESOURCE_UNAVAILABLE_ERROR, ex.getMessage()); + } catch (ResourceAllocationException ex) { + s_logger.warn("Exception: ", ex); + throw new ServerApiException(ApiErrorCode.RESOURCE_ALLOCATION_ERROR, ex.getMessage()); } catch (InsufficientCapacityException ex) { StringBuilder message = new StringBuilder(ex.getMessage()); if (ex instanceof InsufficientServerCapacityException) { diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/volume/DeleteVolumeCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/volume/DeleteVolumeCmd.java index 070ec5fba745..678299c8b5a1 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/volume/DeleteVolumeCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/volume/DeleteVolumeCmd.java @@ -82,8 +82,8 @@ public long getEntityOwnerId() { @Override public void execute() throws ConcurrentOperationException { CallContext.current().setEventDetails("Volume Id: " + this._uuidMgr.getUuid(Volume.class, getId())); - boolean result = _volumeService.deleteVolume(id, CallContext.current().getCallingAccount()); - if (result) { + Volume result = _volumeService.destroyVolume(id, CallContext.current().getCallingAccount(), true, false); + if (result != null) { SuccessResponse response = new SuccessResponse(getCommandName()); setResponseObject(response); } else { diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/volume/DestroyVolumeCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/volume/DestroyVolumeCmd.java new file mode 100644 index 000000000000..ed8457893901 --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/volume/DestroyVolumeCmd.java @@ -0,0 +1,130 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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. +package org.apache.cloudstack.api.command.user.volume; + +import org.apache.log4j.Logger; + +import org.apache.cloudstack.acl.RoleType; +import org.apache.cloudstack.acl.SecurityChecker.AccessType; +import org.apache.cloudstack.api.ACL; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiCommandJobType; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.BaseAsyncCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.ResponseObject.ResponseView; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.response.VolumeResponse; +import org.apache.cloudstack.context.CallContext; + +import com.cloud.event.EventTypes; +import com.cloud.storage.Volume; +import com.cloud.user.Account; + +@APICommand(name = "destroyVolume", description = "Destroys a Volume.", responseObject = VolumeResponse.class, responseView = ResponseView.Restricted, entityType = {Volume.class}, + since = "4.14.0", + authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User}, + requestHasSensitiveInfo = false, + responseHasSensitiveInfo = true) +public class DestroyVolumeCmd extends BaseAsyncCmd { + public static final Logger s_logger = Logger.getLogger(DestroyVolumeCmd.class.getName()); + + private static final String s_name = "destroyvolumeresponse"; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @ACL(accessType = AccessType.OperateEntry) + @Parameter(name=ApiConstants.ID, type=CommandType.UUID, entityType=VolumeResponse.class, + required=true, description="The ID of the volume") + private Long id; + + @Parameter(name = ApiConstants.EXPUNGE, + type = CommandType.BOOLEAN, + description = "If true is passed, the volume is expunged immediately. False by default.", + since = "4.6.0") + private Boolean expunge; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public Long getId() { + return id; + } + + public boolean getExpunge() { + if (expunge == null) { + return false; + } + return expunge; + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public String getCommandName() { + return s_name; + } + + @Override + public long getEntityOwnerId() { + Volume volume = _entityMgr.findById(Volume.class, getId()); + if (volume != null) { + return volume.getAccountId(); + } + + return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this command to SYSTEM so ERROR events are tracked + } + + @Override + public String getEventType() { + return EventTypes.EVENT_VOLUME_DESTROY; + } + + @Override + public String getEventDescription() { + return "destroying volume: " + getId(); + } + + @Override + public ApiCommandJobType getInstanceType() { + return ApiCommandJobType.Volume; + } + + @Override + public Long getInstanceId() { + return getId(); + } + + @Override + public void execute() { + CallContext.current().setEventDetails("Volume Id: " + getId()); + Volume result = _volumeService.destroyVolume(getId(), CallContext.current().getCallingAccount(), getExpunge(), false); + if (result != null) { + VolumeResponse response = _responseGenerator.createVolumeResponse(ResponseView.Restricted, result); + response.setResponseName(getCommandName()); + setResponseObject(response); + } else { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to destroy volume"); + } + } +} diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/volume/ListVolumesCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/volume/ListVolumesCmd.java index aa40a24946e0..0b3e6dd5ce16 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/volume/ListVolumesCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/volume/ListVolumesCmd.java @@ -24,6 +24,7 @@ import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseListTaggedResourcesCmd; import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.BaseCmd.CommandType; import org.apache.cloudstack.api.ResponseObject.ResponseView; import org.apache.cloudstack.api.command.user.UserCmd; import org.apache.cloudstack.api.response.ClusterResponse; @@ -88,6 +89,9 @@ public class ListVolumesCmd extends BaseListTaggedResourcesCmd implements UserCm RoleType.Admin}) private Boolean display; + @Parameter(name = ApiConstants.STATE, type = CommandType.STRING, description = "state of the volume. Possible values are: Ready, Allocated, Destroy, Expunging, Expunged.") + private String state; + ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -139,6 +143,10 @@ public Boolean getDisplay() { } return super.getDisplay(); } + + public String getState() { + return state; + } ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/volume/RecoverVolumeCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/volume/RecoverVolumeCmd.java new file mode 100644 index 000000000000..f5bb1ddd676f --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/volume/RecoverVolumeCmd.java @@ -0,0 +1,91 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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. +package org.apache.cloudstack.api.command.user.volume; + +import org.apache.log4j.Logger; + +import org.apache.cloudstack.acl.RoleType; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.BaseCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.ResponseObject.ResponseView; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.response.VolumeResponse; +import org.apache.cloudstack.context.CallContext; + +import com.cloud.storage.Volume; +import com.cloud.user.Account; + +@APICommand(name = "recoverVolume", description = "Recovers a Destroy volume.", responseObject = VolumeResponse.class, responseView = ResponseView.Restricted, entityType = {Volume.class}, + since = "4.14.0", + authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User}, + requestHasSensitiveInfo = false, + responseHasSensitiveInfo = true) +public class RecoverVolumeCmd extends BaseCmd { + public static final Logger s_logger = Logger.getLogger(RecoverVolumeCmd.class.getName()); + + private static final String s_name = "recovervolumeresponse"; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = VolumeResponse.class, required = true, description = "The ID of the volume") + private Long id; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public Long getId() { + return id; + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public String getCommandName() { + return s_name; + } + + @Override + public long getEntityOwnerId() { + Volume volume = _entityMgr.findById(Volume.class, getId()); + if (volume != null) { + return volume.getAccountId(); + } + + return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this command to SYSTEM so ERROR events are tracked + } + + @Override + public void execute() { + CallContext.current().setEventDetails("Volume Id: " + getId()); + Volume result = _volumeService.recoverVolume(getId()); + if (result != null) { + VolumeResponse response = _responseGenerator.createVolumeResponse(ResponseView.Full, result); + response.setResponseName(getCommandName()); + setResponseObject(response); + } else { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to recover volume"); + } + } +} diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/vpc/RestartVPCCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/vpc/RestartVPCCmd.java index edfd93e785ec..8ed2ab26a225 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/vpc/RestartVPCCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/vpc/RestartVPCCmd.java @@ -91,7 +91,7 @@ public long getEntityOwnerId() { @Override public void execute() { try { - final boolean result = _vpcService.restartVpc(getId(), getCleanup(), getMakeredundant()); + final boolean result = _vpcService.restartVpc(this); if (result) { final SuccessResponse response = new SuccessResponse(getCommandName()); setResponseObject(response); diff --git a/api/src/main/java/org/apache/cloudstack/api/response/CapabilitiesResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/CapabilitiesResponse.java index 153d7dfca9ae..352f559125f5 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/CapabilitiesResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/CapabilitiesResponse.java @@ -84,6 +84,10 @@ public class CapabilitiesResponse extends BaseResponse { @Param(description = "true if the user can recover and expunge virtualmachines, false otherwise", since = "4.6.0") private boolean allowUserExpungeRecoverVM; + @SerializedName("allowuserexpungerecovervolume") + @Param(description = "true if the user can recover and expunge volumes, false otherwise", since = "4.14.0") + private boolean allowUserExpungeRecoverVolume; + @SerializedName("allowuserviewalldomainaccounts") @Param(description = "true if users can see all accounts within the same domain, false otherwise") private boolean allowUserViewAllDomainAccounts; @@ -148,7 +152,11 @@ public void setAllowUserExpungeRecoverVM(boolean allowUserExpungeRecoverVM) { this.allowUserExpungeRecoverVM = allowUserExpungeRecoverVM; } + public void setAllowUserExpungeRecoverVolume(boolean allowUserExpungeRecoverVolume) { + this.allowUserExpungeRecoverVolume = allowUserExpungeRecoverVolume; + } + public void setAllowUserViewAllDomainAccounts(boolean allowUserViewAllDomainAccounts) { this.allowUserViewAllDomainAccounts = allowUserViewAllDomainAccounts; } -} \ No newline at end of file +} diff --git a/api/src/main/java/org/apache/cloudstack/api/response/ClusterResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/ClusterResponse.java index d6ae70fd7a7d..c27ee3ded6b5 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/ClusterResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/ClusterResponse.java @@ -21,14 +21,13 @@ import java.util.List; import java.util.Map; -import com.google.gson.annotations.SerializedName; - import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseResponse; import org.apache.cloudstack.api.EntityReference; import com.cloud.org.Cluster; import com.cloud.serializer.Param; +import com.google.gson.annotations.SerializedName; @EntityReference(value = Cluster.class) public class ClusterResponse extends BaseResponse { @@ -216,4 +215,8 @@ public void setResourceDetails(Map details) { resourceDetails.remove("password"); } } + + public Map getResourceDetails() { + return resourceDetails; + } } diff --git a/api/src/main/java/org/apache/cloudstack/api/response/DomainRouterResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/DomainRouterResponse.java index 131e3e1de7ed..5bd57b449eee 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/DomainRouterResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/DomainRouterResponse.java @@ -18,10 +18,9 @@ import java.util.Date; import java.util.LinkedHashSet; +import java.util.List; import java.util.Set; -import com.google.gson.annotations.SerializedName; - import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseResponse; import org.apache.cloudstack.api.EntityReference; @@ -29,6 +28,7 @@ import com.cloud.serializer.Param; import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachine.State; +import com.google.gson.annotations.SerializedName; @EntityReference(value = VirtualMachine.class) @SuppressWarnings("unused") @@ -217,6 +217,14 @@ public class DomainRouterResponse extends BaseResponse implements ControlledView @Param(description = "true if the router template requires upgrader") private boolean requiresUpgrade; + @SerializedName("healthchecksfailed") + @Param(description = "true if any health checks had failed") + private boolean healthChecksFailed; + + @SerializedName("healthcheckresults") + @Param(description = "Last executed health check result for the router", responseObject = RouterHealthCheckResultResponse.class, since = "4.14") + List healthCheckResults; + public DomainRouterResponse() { nics = new LinkedHashSet(); } @@ -258,6 +266,10 @@ public void setGateway(String gateway) { this.gateway = gateway; } + public String getName() { + return name; + } + public void setName(String name) { this.name = name; } @@ -278,6 +290,14 @@ public String getHypervisor() { return hypervisor; } + public List getHealthCheckResults() { + return healthCheckResults; + } + + public boolean getHealthChecksFailed() { + return healthChecksFailed; + } + public void setHypervisor(String hypervisor) { this.hypervisor = hypervisor; } @@ -446,4 +466,12 @@ public boolean requiresUpgrade() { public void setRequiresUpgrade(boolean requiresUpgrade) { this.requiresUpgrade = requiresUpgrade; } + + public void setHealthChecksFailed(boolean healthChecksFailed) { + this.healthChecksFailed = healthChecksFailed; + } + + public void setHealthCheckResults(List healthCheckResults) { + this.healthCheckResults = healthCheckResults; + } } diff --git a/api/src/main/java/org/apache/cloudstack/api/response/HostResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/HostResponse.java index 08c3338a321b..cd70af1773a7 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/HostResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/HostResponse.java @@ -16,21 +16,22 @@ // under the License. package org.apache.cloudstack.api.response; -import com.cloud.host.Host; -import com.cloud.host.Status; -import com.cloud.hypervisor.Hypervisor.HypervisorType; -import com.cloud.serializer.Param; -import com.google.gson.annotations.SerializedName; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseResponse; import org.apache.cloudstack.api.EntityReference; import org.apache.cloudstack.ha.HAConfig; import org.apache.cloudstack.outofbandmanagement.OutOfBandManagement; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import com.cloud.host.Host; +import com.cloud.host.Status; +import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.serializer.Param; +import com.google.gson.annotations.SerializedName; @EntityReference(value = Host.class) public class HostResponse extends BaseResponse { @@ -243,11 +244,6 @@ public class HostResponse extends BaseResponse { @Param(description = "the admin that annotated this host", since = "4.11") private String username; - // Default visibility to support accessing the details from unit tests - Map getDetails() { - return details; - } - @Override public String getObjectId() { return this.getId(); @@ -361,7 +357,7 @@ public void setMemoryUsed(Long memoryUsed) { this.memoryUsed = memoryUsed; } - public void setGpuGroups(List gpuGroup) { + public void setGpuGroup(List gpuGroup) { this.gpuGroup = gpuGroup; } @@ -437,6 +433,10 @@ public void setHostHAResponse(final HAConfig config) { this.hostHAResponse = new HostHAResponse(config); } + public void setHostHAResponse(HostHAResponse hostHAResponse) { + this.hostHAResponse = hostHAResponse; + } + public OutOfBandManagementResponse getOutOfBandManagementResponse() { return outOfBandManagementResponse; } @@ -445,6 +445,10 @@ public void setOutOfBandManagementResponse(final OutOfBandManagement outOfBandMa this.outOfBandManagementResponse = new OutOfBandManagementResponse(outOfBandManagementConfig); } + public void setOutOfBandManagementResponse(OutOfBandManagementResponse outOfBandManagementResponse) { + this.outOfBandManagementResponse = outOfBandManagementResponse; + } + public String getResourceState() { return resourceState; } @@ -496,7 +500,10 @@ public void setDetails(Map details) { detailsCopy.remove("password"); this.details = detailsCopy; + } + public Map getDetails() { + return details; } public void setMemoryTotal(Long memoryTotal) { diff --git a/api/src/main/java/org/apache/cloudstack/api/response/NicResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/NicResponse.java index 5c3fd7a75a67..72a2bbcabfd5 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/NicResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/NicResponse.java @@ -16,14 +16,15 @@ // under the License. package org.apache.cloudstack.api.response; -import com.cloud.serializer.Param; -import com.cloud.vm.Nic; -import com.google.gson.annotations.SerializedName; +import java.util.List; + import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseResponse; import org.apache.cloudstack.api.EntityReference; -import java.util.List; +import com.cloud.serializer.Param; +import com.cloud.vm.Nic; +import com.google.gson.annotations.SerializedName; @SuppressWarnings("unused") @EntityReference(value = Nic.class) @@ -113,6 +114,26 @@ public class NicResponse extends BaseResponse { @Param(description = "Id of the NSX Logical Switch Port (if NSX based), null otherwise", since="4.6.0") private String nsxLogicalSwitchPort; + @SerializedName(ApiConstants.VLAN_ID) + @Param(description = "ID of the VLAN/VNI if available", since="4.14.0") + private Integer vlanId; + + @SerializedName(ApiConstants.ISOLATED_PVLAN) + @Param(description = "the isolated private VLAN if available", since="4.14.0") + private Integer isolatedPvlanId; + + @SerializedName(ApiConstants.ISOLATED_PVLAN_TYPE) + @Param(description = "the isolated private VLAN type if available", since="4.14.0") + private String isolatedPvlanType; + + @SerializedName(ApiConstants.ADAPTER_TYPE) + @Param(description = "Type of adapter if available", since="4.14.0") + private String adapterType; + + @SerializedName(ApiConstants.IP_ADDRESSES) + @Param(description = "IP addresses associated with NIC found for unmanaged VM", since="4.14.0") + private List ipAddresses; + public void setVmId(String vmId) { this.vmId = vmId; } @@ -303,4 +324,44 @@ public String getNsxLogicalSwitch() { public String getNsxLogicalSwitchPort() { return nsxLogicalSwitchPort; } + + public Integer getVlanId() { + return vlanId; + } + + public void setVlanId(Integer vlanId) { + this.vlanId = vlanId; + } + + public Integer getIsolatedPvlanId() { + return isolatedPvlanId; + } + + public void setIsolatedPvlanId(Integer isolatedPvlanId) { + this.isolatedPvlanId = isolatedPvlanId; + } + + public String getIsolatedPvlanType() { + return isolatedPvlanType; + } + + public void setIsolatedPvlanType(String isolatedPvlanType) { + this.isolatedPvlanType = isolatedPvlanType; + } + + public String getAdapterType() { + return adapterType; + } + + public void setAdapterType(String adapterType) { + this.adapterType = adapterType; + } + + public List getIpAddresses() { + return ipAddresses; + } + + public void setIpAddresses(List ipAddresses) { + this.ipAddresses = ipAddresses; + } } diff --git a/api/src/main/java/org/apache/cloudstack/api/response/RouterHealthCheckResultResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/RouterHealthCheckResultResponse.java new file mode 100644 index 000000000000..f98cf0acd5dd --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/response/RouterHealthCheckResultResponse.java @@ -0,0 +1,88 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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. + +package org.apache.cloudstack.api.response; + +import java.util.Date; + +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseResponse; + +import com.cloud.serializer.Param; +import com.google.gson.annotations.SerializedName; + +public class RouterHealthCheckResultResponse extends BaseResponse { + @SerializedName(ApiConstants.ROUTER_CHECK_NAME) + @Param(description = "the name of the health check on the router") + private String checkName; + + @SerializedName(ApiConstants.ROUTER_CHECK_TYPE) + @Param(description = "the type of the health check - basic or advanced") + private String checkType; + + @SerializedName(ApiConstants.RESULT) + @Param(description = "result of the health check") + private boolean result; + + @SerializedName(ApiConstants.LAST_UPDATED) + @Param(description = "the date this VPC was created") + private Date lastUpdated; + + @SerializedName(ApiConstants.DETAILS) + @Param(description = "detailed response generated on running health check") + private String details; + + public String getCheckName() { + return checkName; + } + + public String getCheckType() { + return checkType; + } + + public boolean getResult() { + return result; + } + + public Date getLastUpdated() { + return lastUpdated; + } + + public String getDetails() { + return details; + } + + public void setCheckName(String checkName) { + this.checkName = checkName; + } + + public void setCheckType(String checkType) { + this.checkType = checkType; + } + + public void setResult(boolean result) { + this.result = result; + } + + public void setLastUpdated(Date lastUpdated) { + this.lastUpdated = lastUpdated; + } + + public void setDetails(String details) { + this.details = details; + } +} diff --git a/api/src/main/java/org/apache/cloudstack/api/response/RouterHealthCheckResultsListResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/RouterHealthCheckResultsListResponse.java new file mode 100644 index 000000000000..e56f70d2c59c --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/response/RouterHealthCheckResultsListResponse.java @@ -0,0 +1,52 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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. + +package org.apache.cloudstack.api.response; + +import java.util.List; + +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseResponse; + +import com.cloud.serializer.Param; +import com.google.gson.annotations.SerializedName; + +public class RouterHealthCheckResultsListResponse extends BaseResponse { + @SerializedName(ApiConstants.ROUTER_ID) + @Param(description = "the id of the router") + private String routerId; + + @SerializedName(ApiConstants.ROUTER_HEALTH_CHECKS) + @Param(description = "the id of the router") + private List healthChecks; + + public String getRouterId() { + return routerId; + } + + public List getHealthChecks() { + return healthChecks; + } + + public void setRouterId(String routerId) { + this.routerId = routerId; + } + + public void setHealthChecks(List healthChecks) { + this.healthChecks = healthChecks; + } +} diff --git a/api/src/main/java/org/apache/cloudstack/api/response/SystemVmResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/SystemVmResponse.java index 49ab473a37a1..3fb17db75325 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/SystemVmResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/SystemVmResponse.java @@ -19,14 +19,14 @@ import java.util.Date; import java.util.List; -import com.google.gson.annotations.SerializedName; - import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseResponse; import org.apache.cloudstack.api.EntityReference; +import com.cloud.host.Status; import com.cloud.serializer.Param; import com.cloud.vm.VirtualMachine; +import com.google.gson.annotations.SerializedName; @EntityReference(value = VirtualMachine.class) public class SystemVmResponse extends BaseResponse { @@ -138,6 +138,10 @@ public class SystemVmResponse extends BaseResponse { @Param(description = "the state of the system VM") private String state; + @SerializedName("agentstate") + @Param(description = "the agent state of the system VM", since = "4.13.1") + private String agentState; + @SerializedName("activeviewersessions") @Param(description = "the number of active console sessions for the console proxy system vm") private Integer activeViewerSessions; @@ -150,6 +154,14 @@ public class SystemVmResponse extends BaseResponse { @Param(description = "public vlan range") private List publicVlan; + @SerializedName("disconnected") + @Param(description = "the last disconnected date of host", since = "4.13.1") + private Date disconnectedOn; + + @SerializedName("version") + @Param(description = "the systemvm agent version", since = "4.13.1") + private String version; + @Override public String getObjectId() { return this.getId(); @@ -331,6 +343,18 @@ public void setState(String state) { this.state = state; } + public String getAgentState() { + return agentState; + } + + public void setAgentState(Status agentState) { + if (agentState != null) { + this.agentState = agentState.toString(); + } else { + this.agentState = Status.Unknown.toString(); + } + } + public Integer getActiveViewerSessions() { return activeViewerSessions; } @@ -378,4 +402,20 @@ public List getPublicVlan() { public void setPublicVlan(List publicVlan) { this.publicVlan = publicVlan; } + + public Date getDisconnectedOn() { + return disconnectedOn; + } + + public void setDisconnectedOn(Date disconnectedOn) { + this.disconnectedOn = disconnectedOn; + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } } diff --git a/api/src/main/java/org/apache/cloudstack/api/response/UnmanagedInstanceDiskResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/UnmanagedInstanceDiskResponse.java new file mode 100644 index 000000000000..083c83fbf85a --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/response/UnmanagedInstanceDiskResponse.java @@ -0,0 +1,159 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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. + +package org.apache.cloudstack.api.response; + +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseResponse; + +import com.cloud.serializer.Param; +import com.google.gson.annotations.SerializedName; + +public class UnmanagedInstanceDiskResponse extends BaseResponse { + + @SerializedName(ApiConstants.ID) + @Param(description = "the ID of the disk") + private String diskId; + + @SerializedName(ApiConstants.LABEL) + @Param(description = "the label of the disk") + private String label; + + @SerializedName(ApiConstants.CAPACITY) + @Param(description = "the capacity of the disk in bytes") + private Long capacity; + + @SerializedName(ApiConstants.IMAGE_PATH) + @Param(description = "the file path of the disk image") + private String imagePath; + + @SerializedName(ApiConstants.CONTROLLER) + @Param(description = "the controller of the disk") + private String controller; + + @SerializedName(ApiConstants.CONTROLLER_UNIT) + @Param(description = "the controller unit of the disk") + private Integer controllerUnit; + + @SerializedName(ApiConstants.POSITION) + @Param(description = "the position of the disk") + private Integer position; + + @SerializedName(ApiConstants.DATASTORE_NAME) + @Param(description = "the controller of the disk") + private String datastoreName; + + @SerializedName(ApiConstants.DATASTORE_HOST) + @Param(description = "the controller of the disk") + private String datastoreHost; + + @SerializedName(ApiConstants.DATASTORE_PATH) + @Param(description = "the controller of the disk") + private String datastorePath; + + @SerializedName(ApiConstants.DATASTORE_TYPE) + @Param(description = "the controller of the disk") + private String datastoreType; + + public String getDiskId() { + return diskId; + } + + public void setDiskId(String diskId) { + this.diskId = diskId; + } + + public String getLabel() { + return label; + } + + public void setLabel(String label) { + this.label = label; + } + + public Long getCapacity() { + return capacity; + } + + public void setCapacity(Long capacity) { + this.capacity = capacity; + } + + public String getImagePath() { + return imagePath; + } + + public void setImagePath(String imagePath) { + this.imagePath = imagePath; + } + + public String getController() { + return controller; + } + + public void setController(String controller) { + this.controller = controller; + } + + public Integer getControllerUnit() { + return controllerUnit; + } + + public void setControllerUnit(Integer controllerUnit) { + this.controllerUnit = controllerUnit; + } + + public Integer getPosition() { + return position; + } + + public void setPosition(Integer position) { + this.position = position; + } + + public String getDatastoreName() { + return datastoreName; + } + + public void setDatastoreName(String datastoreName) { + this.datastoreName = datastoreName; + } + + public String getDatastoreHost() { + return datastoreHost; + } + + public void setDatastoreHost(String datastoreHost) { + this.datastoreHost = datastoreHost; + } + + public String getDatastorePath() { + return datastorePath; + } + + public void setDatastorePath(String datastorePath) { + this.datastorePath = datastorePath; + } + + public String getDatastoreType() { + return datastoreType; + } + + public void setDatastoreType(String datastoreType) { + this.datastoreType = datastoreType; + } +} diff --git a/api/src/main/java/org/apache/cloudstack/api/response/UnmanagedInstanceResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/UnmanagedInstanceResponse.java new file mode 100644 index 000000000000..5167f1788ce1 --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/response/UnmanagedInstanceResponse.java @@ -0,0 +1,190 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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. + +package org.apache.cloudstack.api.response; + +import java.util.LinkedHashSet; +import java.util.Set; + +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseResponse; +import org.apache.cloudstack.api.EntityReference; +import org.apache.cloudstack.vm.UnmanagedInstanceTO; + +import com.cloud.serializer.Param; +import com.google.gson.annotations.SerializedName; + +@EntityReference(value = UnmanagedInstanceTO.class) +public class UnmanagedInstanceResponse extends BaseResponse { + + @SerializedName(ApiConstants.NAME) + @Param(description = "the name of the virtual machine") + private String name; + + @SerializedName(ApiConstants.CLUSTER_ID) + @Param(description = "the ID of the cluster to which virtual machine belongs") + private String clusterId; + + @SerializedName(ApiConstants.HOST_ID) + @Param(description = "the ID of the host to which virtual machine belongs") + private String hostId; + + @SerializedName(ApiConstants.POWER_STATE) + @Param(description = "the power state of the virtual machine") + private String powerState; + + @SerializedName(ApiConstants.CPU_NUMBER) + @Param(description = "the CPU cores of the virtual machine") + private Integer cpuCores; + + @SerializedName(ApiConstants.CPU_CORE_PER_SOCKET) + @Param(description = "the CPU cores per socket for the virtual machine. VMware specific") + private Integer cpuCoresPerSocket; + + @SerializedName(ApiConstants.CPU_SPEED) + @Param(description = "the CPU speed of the virtual machine") + private Integer cpuSpeed; + + @SerializedName(ApiConstants.MEMORY) + @Param(description = "the memory of the virtual machine in MB") + private Integer memory; + + @SerializedName(ApiConstants.OS_ID) + @Param(description = "the operating system ID of the virtual machine") + private String operatingSystemId; + + @SerializedName(ApiConstants.OS_DISPLAY_NAME) + @Param(description = "the operating system of the virtual machine") + private String operatingSystem; + + @SerializedName(ApiConstants.DISK) + @Param(description = "the list of disks associated with the virtual machine", responseObject = UnmanagedInstanceDiskResponse.class) + private Set disks; + + @SerializedName(ApiConstants.NIC) + @Param(description = "the list of nics associated with the virtual machine", responseObject = NicResponse.class) + private Set nics; + + public UnmanagedInstanceResponse() { + disks = new LinkedHashSet(); + nics = new LinkedHashSet(); + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getClusterId() { + return clusterId; + } + + public void setClusterId(String clusterId) { + this.clusterId = clusterId; + } + + public String getHostId() { + return hostId; + } + + public void setHostId(String hostId) { + this.hostId = hostId; + } + + public String getPowerState() { + return powerState; + } + + public void setPowerState(String powerState) { + this.powerState = powerState; + } + + public Integer getCpuCores() { + return cpuCores; + } + + public void setCpuCores(Integer cpuCores) { + this.cpuCores = cpuCores; + } + + public Integer getCpuCoresPerSocket() { + return cpuCoresPerSocket; + } + + public void setCpuCoresPerSocket(Integer cpuCoresPerSocket) { + this.cpuCoresPerSocket = cpuCoresPerSocket; + } + + public Integer getCpuSpeed() { + return cpuSpeed; + } + + public void setCpuSpeed(Integer cpuSpeed) { + this.cpuSpeed = cpuSpeed; + } + + public Integer getMemory() { + return memory; + } + + public void setMemory(Integer memory) { + this.memory = memory; + } + + public String getOperatingSystemId() { + return operatingSystemId; + } + + public void setOperatingSystemId(String operatingSystemId) { + this.operatingSystemId = operatingSystemId; + } + + public String getOperatingSystem() { + return operatingSystem; + } + + public void setOperatingSystem(String operatingSystem) { + this.operatingSystem = operatingSystem; + } + + public Set getDisks() { + return disks; + } + + public void setDisks(Set disks) { + this.disks = disks; + } + + public void addDisk(UnmanagedInstanceDiskResponse disk) { + this.disks.add(disk); + } + + public Set getNics() { + return nics; + } + + public void setNics(Set nics) { + this.nics = nics; + } + + public void addNic(NicResponse nic) { + this.nics.add(nic); + } +} diff --git a/api/src/main/java/org/apache/cloudstack/api/response/VolumeResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/VolumeResponse.java index 01d2c9b3d8f1..1cdd69673cfb 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/VolumeResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/VolumeResponse.java @@ -262,19 +262,19 @@ public class VolumeResponse extends BaseResponseWithTagInformation implements Co @SerializedName(ApiConstants.CLUSTER_ID) @Param(description = "cluster id of the volume") - private String clusterid; + private String clusterId; @SerializedName(ApiConstants.CLUSTER_NAME) @Param(description = "cluster name where the volume is allocated") - private String clustername; + private String clusterName; @SerializedName(ApiConstants.POD_ID) @Param(description = "pod id of the volume") - private String podid; + private String podId; @SerializedName(ApiConstants.POD_NAME) @Param(description = "pod name of the volume") - private String podname; + private String podName; public String getPath() { return path; @@ -751,35 +751,34 @@ public void setUtilization(String utilization) { } public String getClusterId() { - return clusterid; + return clusterId; } - public void setClusterId(String clusterid) { - this.clusterid = clusterid; + public void setClusterId(String clusterId) { + this.clusterId = clusterId; } public String getClusterName() { - return clustername; + return clusterName; } - public void setClusterName(String clustername) { - this.clustername = clustername; + public void setClusterName(String clusterName) { + this.clusterName = clusterName; } public String getPodId() { - return podid; + return podId; } - public void setPodId(String podid) { - this.podid = podid; + public void setPodId(String podId) { + this.podId = podId; } public String getPodName() { - return podname; + return podName; } - public void setPodName(String podname) { - this.podname = podname; + public void setPodName(String podName) { + this.podName = podName; } - } diff --git a/api/src/main/java/org/apache/cloudstack/api/response/ZoneResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/ZoneResponse.java index efd3b79ed0a2..e95333fbd65a 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/ZoneResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/ZoneResponse.java @@ -173,7 +173,7 @@ public void setDomainId(String domainId) { this.domainId = domainId; } - public void setType(String networkType) { + public void setNetworkType(String networkType) { this.networkType = networkType; } diff --git a/api/src/main/java/org/apache/cloudstack/management/ManagementServerHost.java b/api/src/main/java/org/apache/cloudstack/management/ManagementServerHost.java index 11e1cae9bf6f..0159fb2e7919 100644 --- a/api/src/main/java/org/apache/cloudstack/management/ManagementServerHost.java +++ b/api/src/main/java/org/apache/cloudstack/management/ManagementServerHost.java @@ -16,15 +16,14 @@ // under the License. package org.apache.cloudstack.management; -public interface ManagementServerHost { +import org.apache.cloudstack.api.Identity; +import org.apache.cloudstack.api.InternalIdentity; + +public interface ManagementServerHost extends InternalIdentity, Identity { enum State { Up, Down } - long getId(); - - String getUuid(); - long getMsid(); State getState(); diff --git a/api/src/main/java/org/apache/cloudstack/query/QueryService.java b/api/src/main/java/org/apache/cloudstack/query/QueryService.java index c4dfe64c739b..0a400ed9ae3c 100644 --- a/api/src/main/java/org/apache/cloudstack/query/QueryService.java +++ b/api/src/main/java/org/apache/cloudstack/query/QueryService.java @@ -24,6 +24,7 @@ import org.apache.cloudstack.api.command.admin.host.ListHostsCmd; import org.apache.cloudstack.api.command.admin.internallb.ListInternalLBVMsCmd; import org.apache.cloudstack.api.command.admin.management.ListMgmtsCmd; +import org.apache.cloudstack.api.command.admin.router.GetRouterHealthCheckResultsCmd; import org.apache.cloudstack.api.command.admin.router.ListRoutersCmd; import org.apache.cloudstack.api.command.admin.storage.ListImageStoresCmd; import org.apache.cloudstack.api.command.admin.storage.ListSecondaryStagingStoresCmd; @@ -68,6 +69,7 @@ import org.apache.cloudstack.api.response.ProjectResponse; import org.apache.cloudstack.api.response.ResourceDetailResponse; import org.apache.cloudstack.api.response.ResourceTagResponse; +import org.apache.cloudstack.api.response.RouterHealthCheckResultResponse; import org.apache.cloudstack.api.response.SecurityGroupResponse; import org.apache.cloudstack.api.response.ServiceOfferingResponse; import org.apache.cloudstack.api.response.StoragePoolResponse; @@ -172,4 +174,6 @@ public interface QueryService { ListResponse listManagementServers(ListMgmtsCmd cmd); ListResponse listTemplateOVFProperties(ListTemplateOVFProperties cmd); + + List listRouterHealthChecks(GetRouterHealthCheckResultsCmd cmd); } diff --git a/api/src/main/java/org/apache/cloudstack/vm/UnmanagedInstanceTO.java b/api/src/main/java/org/apache/cloudstack/vm/UnmanagedInstanceTO.java new file mode 100644 index 000000000000..860ecdc3ba14 --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/vm/UnmanagedInstanceTO.java @@ -0,0 +1,353 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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. + +package org.apache.cloudstack.vm; + +import java.util.List; + +public class UnmanagedInstanceTO { + + public enum PowerState { + PowerUnknown, + PowerOn, + PowerOff + } + + private String name; + + private PowerState powerState; + + private Integer cpuCores; + + private Integer cpuCoresPerSocket; + + private Integer memory; + + private Integer cpuSpeed; + + private String operatingSystemId; + + private String operatingSystem; + + private List disks; + + private List nics; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public PowerState getPowerState() { + return powerState; + } + + public void setPowerState(PowerState powerState) { + this.powerState = powerState; + } + + public Integer getCpuCores() { + return cpuCores; + } + + public void setCpuCores(Integer cpuCores) { + this.cpuCores = cpuCores; + } + + public Integer getCpuCoresPerSocket() { + return cpuCoresPerSocket; + } + + public void setCpuCoresPerSocket(Integer cpuCoresPerSocket) { + this.cpuCoresPerSocket = cpuCoresPerSocket; + } + + public Integer getMemory() { + return memory; + } + + public void setMemory(Integer memory) { + this.memory = memory; + } + + public Integer getCpuSpeed() { + return cpuSpeed; + } + + public void setCpuSpeed(Integer cpuSpeed) { + this.cpuSpeed = cpuSpeed; + } + + public String getOperatingSystemId() { + return operatingSystemId; + } + + public void setOperatingSystemId(String operatingSystemId) { + this.operatingSystemId = operatingSystemId; + } + + public String getOperatingSystem() { + return operatingSystem; + } + + public void setOperatingSystem(String operatingSystem) { + this.operatingSystem = operatingSystem; + } + + public List getDisks() { + return disks; + } + + public void setDisks(List disks) { + this.disks = disks; + } + + public List getNics() { + return nics; + } + + public void setNics(List nics) { + this.nics = nics; + } + + public static class Disk { + private String diskId; + + private String label; + + private Long capacity; + + private String fileBaseName; + + private String imagePath; + + private String controller; + + private Integer controllerUnit; + + private Integer position; + + private String chainInfo; + + private String datastoreName; + + private String datastoreHost; + + private String datastorePath; + + private String datastoreType; + + public String getDiskId() { + return diskId; + } + + public void setDiskId(String diskId) { + this.diskId = diskId; + } + + public String getLabel() { + return label; + } + + public void setLabel(String label) { + this.label = label; + } + + public Long getCapacity() { + return capacity; + } + + public void setCapacity(Long capacity) { + this.capacity = capacity; + } + + public String getFileBaseName() { + return fileBaseName; + } + + public void setFileBaseName(String fileBaseName) { + this.fileBaseName = fileBaseName; + } + + public String getImagePath() { + return imagePath; + } + + public void setImagePath(String imagePath) { + this.imagePath = imagePath; + } + + public String getController() { + return controller; + } + + public void setController(String controller) { + this.controller = controller; + } + + public Integer getControllerUnit() { + return controllerUnit; + } + + public void setControllerUnit(Integer controllerUnit) { + this.controllerUnit = controllerUnit; + } + + public Integer getPosition() { + return position; + } + + public void setPosition(Integer position) { + this.position = position; + } + + public String getChainInfo() { + return chainInfo; + } + + public void setChainInfo(String chainInfo) { + this.chainInfo = chainInfo; + } + + public String getDatastoreName() { + return datastoreName; + } + + public void setDatastoreName(String datastoreName) { + this.datastoreName = datastoreName; + } + + public String getDatastoreHost() { + return datastoreHost; + } + + public void setDatastoreHost(String datastoreHost) { + this.datastoreHost = datastoreHost; + } + + public String getDatastorePath() { + return datastorePath; + } + + public void setDatastorePath(String datastorePath) { + this.datastorePath = datastorePath; + } + + public String getDatastoreType() { + return datastoreType; + } + + public void setDatastoreType(String datastoreType) { + this.datastoreType = datastoreType; + } + } + + public static class Nic { + private String nicId; + + private String adapterType; + + private String macAddress; + + private String network; + + private Integer vlan; + + private Integer pvlan; + + private String pvlanType; + + private List ipAddress; + + private String pciSlot; + + public String getNicId() { + return nicId; + } + + public void setNicId(String nicId) { + this.nicId = nicId; + } + + public String getAdapterType() { + return adapterType; + } + + public void setAdapterType(String adapterType) { + this.adapterType = adapterType; + } + + public String getMacAddress() { + return macAddress; + } + + public void setMacAddress(String macAddress) { + this.macAddress = macAddress; + } + + public String getNetwork() { + return network; + } + + public void setNetwork(String network) { + this.network = network; + } + + public Integer getVlan() { + return vlan; + } + + public void setVlan(Integer vlan) { + this.vlan = vlan; + } + + public Integer getPvlan() { + return pvlan; + } + + public void setPvlan(Integer pvlan) { + this.pvlan = pvlan; + } + + public String getPvlanType() { + return pvlanType; + } + + public void setPvlanType(String pvlanType) { + this.pvlanType = pvlanType; + } + + public List getIpAddress() { + return ipAddress; + } + + public void setIpAddress(List ipAddress) { + this.ipAddress = ipAddress; + } + + public String getPciSlot() { + return pciSlot; + } + + public void setPciSlot(String pciSlot) { + this.pciSlot = pciSlot; + } + } +} diff --git a/api/src/main/java/org/apache/cloudstack/vm/VmImportService.java b/api/src/main/java/org/apache/cloudstack/vm/VmImportService.java new file mode 100644 index 000000000000..783a5d295eed --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/vm/VmImportService.java @@ -0,0 +1,31 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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. + +package org.apache.cloudstack.vm; + +import org.apache.cloudstack.api.command.admin.vm.ImportUnmanagedInstanceCmd; +import org.apache.cloudstack.api.command.admin.vm.ListUnmanagedInstancesCmd; +import org.apache.cloudstack.api.response.ListResponse; +import org.apache.cloudstack.api.response.UnmanagedInstanceResponse; +import org.apache.cloudstack.api.response.UserVmResponse; + +import com.cloud.utils.component.PluggableService; + +public interface VmImportService extends PluggableService { + ListResponse listUnmanagedInstances(ListUnmanagedInstancesCmd cmd); + UserVmResponse importUnmanagedInstance(ImportUnmanagedInstanceCmd cmd); +} diff --git a/api/src/test/java/org/apache/cloudstack/api/command/test/AddSecondaryStorageCmdTest.java b/api/src/test/java/org/apache/cloudstack/api/command/test/AddSecondaryStorageCmdTest.java index d68cfb4ca679..da5bff27ec3f 100644 --- a/api/src/test/java/org/apache/cloudstack/api/command/test/AddSecondaryStorageCmdTest.java +++ b/api/src/test/java/org/apache/cloudstack/api/command/test/AddSecondaryStorageCmdTest.java @@ -16,29 +16,29 @@ // under the License. package org.apache.cloudstack.api.command.test; -import static org.mockito.Matchers.anyLong; -import static org.mockito.Matchers.anyObject; -import static org.mockito.Matchers.anyString; -import java.util.Map; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.ArgumentMatchers.anyObject; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.isNull; -import junit.framework.Assert; -import junit.framework.TestCase; +import java.util.Map; +import org.apache.cloudstack.api.ResponseGenerator; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.command.admin.storage.AddImageStoreCmd; +import org.apache.cloudstack.api.response.ImageStoreResponse; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import org.mockito.Mockito; -import org.apache.cloudstack.api.ResponseGenerator; -import org.apache.cloudstack.api.ServerApiException; -import org.apache.cloudstack.api.command.admin.storage.AddImageStoreCmd; -import org.apache.cloudstack.api.response.ImageStoreResponse; - import com.cloud.storage.ImageStore; import com.cloud.storage.StorageService; +import junit.framework.TestCase; + public class AddSecondaryStorageCmdTest extends TestCase { private AddImageStoreCmd addImageStoreCmd; @@ -62,25 +62,22 @@ public void testExecuteForResult() throws Exception { ImageStore store = Mockito.mock(ImageStore.class); - Mockito.when(resourceService.discoverImageStore(anyString(), anyString(), anyString(), anyLong(), (Map)anyObject())) - .thenReturn(store); - + Mockito.when(resourceService.discoverImageStore(isNull(), isNull(), isNull(), isNull(), isNull())).thenReturn(store); ResponseGenerator responseGenerator = Mockito.mock(ResponseGenerator.class); addImageStoreCmd._responseGenerator = responseGenerator; ImageStoreResponse responseHost = new ImageStoreResponse(); responseHost.setName("Test"); - Mockito.when(responseGenerator.createImageStoreResponse(store)).thenReturn(responseHost); + Mockito.doReturn(responseHost).when(responseGenerator).createImageStoreResponse(store); addImageStoreCmd.execute(); Mockito.verify(responseGenerator).createImageStoreResponse(store); ImageStoreResponse actualResponse = (ImageStoreResponse)addImageStoreCmd.getResponseObject(); - - Assert.assertEquals(responseHost, actualResponse); - Assert.assertEquals("addimagestoreresponse", actualResponse.getResponseName()); + assertEquals(responseHost, actualResponse); + assertEquals("addimagestoreresponse", actualResponse.getResponseName()); } @@ -96,7 +93,7 @@ public void testExecuteForNullResult() throws Exception { try { addImageStoreCmd.execute(); } catch (ServerApiException exception) { - Assert.assertEquals("Failed to add secondary storage", exception.getDescription()); + assertEquals("Failed to add secondary storage", exception.getDescription()); } } diff --git a/api/src/test/java/org/apache/cloudstack/api/command/test/AddVpnUserCmdTest.java b/api/src/test/java/org/apache/cloudstack/api/command/test/AddVpnUserCmdTest.java index c8d99a8a2452..8b933534cea2 100644 --- a/api/src/test/java/org/apache/cloudstack/api/command/test/AddVpnUserCmdTest.java +++ b/api/src/test/java/org/apache/cloudstack/api/command/test/AddVpnUserCmdTest.java @@ -16,24 +16,25 @@ // under the License. package org.apache.cloudstack.api.command.test; -import junit.framework.Assert; -import junit.framework.TestCase; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.ArgumentMatchers.isNull; +import static org.mockito.ArgumentMatchers.nullable; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.command.user.vpn.AddVpnUserCmd; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; -import org.mockito.Matchers; import org.mockito.Mockito; -import org.apache.cloudstack.api.ServerApiException; -import org.apache.cloudstack.api.command.user.vpn.AddVpnUserCmd; - import com.cloud.network.VpnUser; import com.cloud.network.vpn.RemoteAccessVpnService; import com.cloud.user.Account; import com.cloud.user.AccountService; +import junit.framework.Assert; +import junit.framework.TestCase; public class AddVpnUserCmdTest extends TestCase { private AddVpnUserCmd addVpnUserCmd; @@ -76,14 +77,15 @@ public void testCreateSuccess() { AccountService accountService = Mockito.mock(AccountService.class); Account account = Mockito.mock(Account.class); - Mockito.when(accountService.getAccount(Matchers.anyLong())).thenReturn(account); + Mockito.when(accountService.getAccount(nullable(Long.class))).thenReturn(account); addVpnUserCmd._accountService = accountService; RemoteAccessVpnService ravService = Mockito.mock(RemoteAccessVpnService.class); VpnUser vpnUser = Mockito.mock(VpnUser.class); - Mockito.when(ravService.addVpnUser(Matchers.anyLong(), Matchers.anyString(), Matchers.anyString())).thenReturn(vpnUser); + + Mockito.when(ravService.addVpnUser(anyLong(), isNull(), isNull())).thenReturn(vpnUser); addVpnUserCmd._ravService = ravService; @@ -96,12 +98,13 @@ public void testCreateFailure() { AccountService accountService = Mockito.mock(AccountService.class); Account account = Mockito.mock(Account.class); - Mockito.when(accountService.getAccount(Matchers.anyLong())).thenReturn(account); + Mockito.when(accountService.getAccount(nullable(Long.class))).thenReturn(account); addVpnUserCmd._accountService = accountService; RemoteAccessVpnService ravService = Mockito.mock(RemoteAccessVpnService.class); - Mockito.when(ravService.addVpnUser(Matchers.anyLong(), Matchers.anyString(), Matchers.anyString())).thenReturn(null); + + Mockito.when(ravService.addVpnUser(anyLong(), isNull(), isNull())).thenReturn(null); addVpnUserCmd._ravService = ravService; diff --git a/api/src/test/java/org/apache/cloudstack/api/command/test/CreateSnapshotCmdTest.java b/api/src/test/java/org/apache/cloudstack/api/command/test/CreateSnapshotCmdTest.java index 4739082cf644..0d3251a64dff 100644 --- a/api/src/test/java/org/apache/cloudstack/api/command/test/CreateSnapshotCmdTest.java +++ b/api/src/test/java/org/apache/cloudstack/api/command/test/CreateSnapshotCmdTest.java @@ -16,8 +16,7 @@ // under the License. package org.apache.cloudstack.api.command.test; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyBoolean; +import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.Matchers.anyLong; import static org.mockito.Matchers.anyObject; import static org.mockito.Matchers.anyString; @@ -92,8 +91,8 @@ public void testCreateSuccess() { VolumeApiService volumeApiService = Mockito.mock(VolumeApiService.class); Snapshot snapshot = Mockito.mock(Snapshot.class); try { - Mockito.when(volumeApiService.takeSnapshot(anyLong(), anyLong(), anyLong(), - any(Account.class), anyBoolean(), isNull(Snapshot.LocationType.class), anyBoolean(), anyObject())).thenReturn(snapshot); + Mockito.when(volumeApiService.takeSnapshot(nullable(Long.class), nullable(Long.class), isNull(), + nullable(Account.class), nullable(Boolean.class), nullable(Snapshot.LocationType.class), nullable(Boolean.class), nullable(Map.class))).thenReturn(snapshot); } catch (Exception e) { Assert.fail("Received exception when success expected " + e.getMessage()); @@ -125,8 +124,8 @@ public void testCreateFailure() { VolumeApiService volumeApiService = Mockito.mock(VolumeApiService.class); try { - Mockito.when(volumeApiService.takeSnapshot(anyLong(), anyLong(), anyLong(), - any(Account.class), anyBoolean(), isNull(Snapshot.LocationType.class), anyBoolean(), anyObject())).thenReturn(null); + Mockito.when(volumeApiService.takeSnapshot(nullable(Long.class), nullable(Long.class), nullable(Long.class), + nullable(Account.class), nullable(Boolean.class), nullable(Snapshot.LocationType.class), nullable(Boolean.class), anyObject())).thenReturn(null); } catch (Exception e) { Assert.fail("Received exception when success expected " + e.getMessage()); } diff --git a/api/src/test/java/org/apache/cloudstack/api/command/test/RegionCmdTest.java b/api/src/test/java/org/apache/cloudstack/api/command/test/RegionCmdTest.java index 10c3d85fa8e5..5410d1b8cd30 100644 --- a/api/src/test/java/org/apache/cloudstack/api/command/test/RegionCmdTest.java +++ b/api/src/test/java/org/apache/cloudstack/api/command/test/RegionCmdTest.java @@ -16,15 +16,9 @@ // under the License. package org.apache.cloudstack.api.command.test; -import junit.framework.Assert; -import junit.framework.TestCase; - -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.mockito.Matchers; -import org.mockito.Mockito; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.isNull; import org.apache.cloudstack.api.ResponseGenerator; import org.apache.cloudstack.api.ServerApiException; @@ -32,6 +26,13 @@ import org.apache.cloudstack.api.response.RegionResponse; import org.apache.cloudstack.region.Region; import org.apache.cloudstack.region.RegionService; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.mockito.Mockito; + +import junit.framework.TestCase; public class RegionCmdTest extends TestCase { @@ -66,7 +67,8 @@ public void testCreateSuccess() { RegionService regionService = Mockito.mock(RegionService.class); Region region = Mockito.mock(Region.class); - Mockito.when(regionService.addRegion(Matchers.anyInt(), Matchers.anyString(), Matchers.anyString())).thenReturn(region); + + Mockito.when(regionService.addRegion(anyInt(), anyString(), isNull())).thenReturn(region); addRegionCmd._regionService = regionService; responseGenerator = Mockito.mock(ResponseGenerator.class); @@ -86,14 +88,15 @@ public void testCreateFailure() { RegionService regionService = Mockito.mock(RegionService.class); Region region = Mockito.mock(Region.class); - Mockito.when(regionService.addRegion(Matchers.anyInt(), Matchers.anyString(), Matchers.anyString())).thenReturn(null); + + Mockito.when(regionService.addRegion(anyInt(), anyString(), isNull())).thenReturn(null); addRegionCmd._regionService = regionService; try { addRegionCmd.execute(); } catch (ServerApiException exception) { - Assert.assertEquals("Failed to add Region", exception.getDescription()); + assertEquals("Failed to add Region", exception.getDescription()); } } diff --git a/client/pom.xml b/client/pom.xml index 3f1e0763d05c..507101bf6310 100644 --- a/client/pom.xml +++ b/client/pom.xml @@ -30,7 +30,7 @@ juniper-contrail - http://juniper.github.io/contrail-maven/snapshots + https://juniper.github.io/contrail-maven/snapshots @@ -61,7 +61,6 @@ mysql mysql-connector-java - runtime org.apache.cloudstack @@ -537,9 +536,13 @@ + + jar + 0 9966 stop-jetty + 10 8080 @@ -548,11 +551,11 @@ ${project.build.directory}/classes/META-INF/webapp/WEB-INF/web.xml ${project.build.directory}/classes/META-INF/webapp/ - + /client - ${project.build.directory}/conf/;${project.build.directory}/common;${project.build.directory}/utilities/scripts/db/;${project.build.directory}/utilities/scripts/db/db/ + ${project.build.directory}/conf/;${project.build.directory}/common;${project.build.directory}/utilities/scripts/db/;${project.build.directory}/utilities/scripts/db/db/;${project.build.directory}/cloud-client-ui-${project.version}.jar .*/cloud.*jar$|.*/classes/.* - + log4j.configuration @@ -697,6 +700,12 @@ false ${project.build.directory}/pythonlibs + + mysql + mysql-connector-java + false + ${project.build.directory}/lib + org.bouncycastle bcprov-jdk15on @@ -737,7 +746,7 @@ org.mockito:mockito-all org.hamcrest:hamcrest-all org.powermock:powermock-module-junit4 - org.powermock:powermock-api-mockito + org.powermock:powermock-api-mockito2 org.springframework:spring-test org.apache.tomcat.embed:tomcat-embed-core org.apache.geronimo.specs:geronimo-servlet_3.0_spec diff --git a/core/src/main/java/com/cloud/agent/api/GetUnmanagedInstancesAnswer.java b/core/src/main/java/com/cloud/agent/api/GetUnmanagedInstancesAnswer.java new file mode 100644 index 000000000000..3c6118d426e6 --- /dev/null +++ b/core/src/main/java/com/cloud/agent/api/GetUnmanagedInstancesAnswer.java @@ -0,0 +1,58 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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. + +package com.cloud.agent.api; + +import java.util.HashMap; + +import org.apache.cloudstack.vm.UnmanagedInstanceTO; + +@LogLevel(LogLevel.Log4jLevel.Trace) +public class GetUnmanagedInstancesAnswer extends Answer { + + private String instanceName; + private HashMap unmanagedInstances; + + GetUnmanagedInstancesAnswer() { + } + + public GetUnmanagedInstancesAnswer(GetUnmanagedInstancesCommand cmd, String details, HashMap unmanagedInstances) { + super(cmd, true, details); + this.instanceName = cmd.getInstanceName(); + this.unmanagedInstances = unmanagedInstances; + } + + public String getInstanceName() { + return instanceName; + } + + public void setInstanceName(String instanceName) { + this.instanceName = instanceName; + } + + public HashMap getUnmanagedInstances() { + return unmanagedInstances; + } + + public void setUnmanagedInstances(HashMap unmanagedInstances) { + this.unmanagedInstances = unmanagedInstances; + } + + public String getString() { + return "GetUnmanagedInstancesAnswer [instanceName=" + instanceName + "]"; + } +} diff --git a/core/src/main/java/com/cloud/agent/api/GetUnmanagedInstancesCommand.java b/core/src/main/java/com/cloud/agent/api/GetUnmanagedInstancesCommand.java new file mode 100644 index 000000000000..968c58611bb7 --- /dev/null +++ b/core/src/main/java/com/cloud/agent/api/GetUnmanagedInstancesCommand.java @@ -0,0 +1,73 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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. + +package com.cloud.agent.api; + +import java.util.List; + +/** + * Unmanaged instances are those virtual machines which are present at hypervisor end but not available in CloudStack. + * Such virtual machines might have been created out of band, directly from hypervisor. + * Managed instances will be those virtual machines that are created from CloudStack or CloudStack have database record for them. + * All managed instances will be filtered while trying to find unmanaged instances. + */ + +@LogLevel(LogLevel.Log4jLevel.Trace) +public class GetUnmanagedInstancesCommand extends Command { + + String instanceName; + List managedInstancesNames; + + public GetUnmanagedInstancesCommand() { + } + + public GetUnmanagedInstancesCommand(String instanceName) { + this.instanceName = instanceName; + } + + public String getInstanceName() { + return instanceName; + } + + public void setInstanceName(String instanceName) { + this.instanceName = instanceName; + } + + public List getManagedInstancesNames() { + return managedInstancesNames; + } + + public void setManagedInstancesNames(List managedInstancesNames) { + this.managedInstancesNames = managedInstancesNames; + } + + public boolean hasManagedInstance(String name) { + if (managedInstancesNames!=null && !managedInstancesNames.isEmpty()) { + return managedInstancesNames.contains(name); + } + return false; + } + + @Override + public boolean executeInSequence() { + return false; + } + + public String getString() { + return "GetUnmanagedInstancesCommand [instanceName=" + instanceName + "]"; + } +} diff --git a/core/src/main/java/com/cloud/agent/api/RebootCommand.java b/core/src/main/java/com/cloud/agent/api/RebootCommand.java index eecf7f635d38..74ed76283514 100644 --- a/core/src/main/java/com/cloud/agent/api/RebootCommand.java +++ b/core/src/main/java/com/cloud/agent/api/RebootCommand.java @@ -19,8 +19,11 @@ package com.cloud.agent.api; +import com.cloud.agent.api.to.VirtualMachineTO; + public class RebootCommand extends Command { String vmName; + VirtualMachineTO vm; protected boolean executeInSequence = false; protected RebootCommand() { @@ -35,6 +38,14 @@ public String getVmName() { return this.vmName; } + public void setVirtualMachine(VirtualMachineTO vm) { + this.vm = vm; + } + + public VirtualMachineTO getVirtualMachine() { + return vm; + } + @Override public boolean executeInSequence() { return this.executeInSequence; diff --git a/core/src/main/java/com/cloud/agent/api/SecurityGroupRulesCmd.java b/core/src/main/java/com/cloud/agent/api/SecurityGroupRulesCmd.java index 1d3d15439927..ea4ab96c5a7c 100644 --- a/core/src/main/java/com/cloud/agent/api/SecurityGroupRulesCmd.java +++ b/core/src/main/java/com/cloud/agent/api/SecurityGroupRulesCmd.java @@ -30,12 +30,13 @@ import org.apache.log4j.Logger; import com.cloud.agent.api.LogLevel.Log4jLevel; +import com.cloud.agent.api.to.VirtualMachineTO; import com.cloud.utils.net.NetUtils; public class SecurityGroupRulesCmd extends Command { private static final String CIDR_LENGTH_SEPARATOR = "/"; - private static final char RULE_TARGET_SEPARATOR = ','; - private static final char RULE_COMMAND_SEPARATOR = ';'; + public static final char RULE_TARGET_SEPARATOR = ','; + public static final char RULE_COMMAND_SEPARATOR = ';'; protected static final String EGRESS_RULE = "E:"; protected static final String INGRESS_RULE = "I:"; private static final Logger LOGGER = Logger.getLogger(SecurityGroupRulesCmd.class); @@ -51,6 +52,7 @@ public class SecurityGroupRulesCmd extends Command { private List ingressRuleSet; private List egressRuleSet; private final List secIps; + private VirtualMachineTO vmTO; public static class IpPortAndProto { private final String proto; @@ -252,6 +254,14 @@ public Long getVmId() { return vmId; } + public void setVmTO(VirtualMachineTO vmTO) { + this.vmTO = vmTO; + } + + public VirtualMachineTO getVmTO() { + return vmTO; + } + /** * used for logging * @return the number of Cidrs in the in and egress rule sets for this security group rules command. diff --git a/core/src/main/java/com/cloud/agent/api/routing/GetRouterMonitorResultsAnswer.java b/core/src/main/java/com/cloud/agent/api/routing/GetRouterMonitorResultsAnswer.java new file mode 100644 index 000000000000..4db59dfac335 --- /dev/null +++ b/core/src/main/java/com/cloud/agent/api/routing/GetRouterMonitorResultsAnswer.java @@ -0,0 +1,46 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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. + +package com.cloud.agent.api.routing; + +import java.util.List; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.Command; + +public class GetRouterMonitorResultsAnswer extends Answer { + private List failingChecks; + private String monitoringResults; + + protected GetRouterMonitorResultsAnswer() { + super(); + } + + public GetRouterMonitorResultsAnswer(Command cmd, boolean success, List failingChecks, String monitoringResults) { + super(cmd, success, monitoringResults); + this.failingChecks = failingChecks; + this.monitoringResults = monitoringResults; + } + + public List getFailingChecks() { + return failingChecks; + } + + public String getMonitoringResults() { + return monitoringResults; + } +} diff --git a/core/src/main/java/com/cloud/agent/api/routing/GetRouterMonitorResultsCommand.java b/core/src/main/java/com/cloud/agent/api/routing/GetRouterMonitorResultsCommand.java new file mode 100644 index 000000000000..779a0f45a57f --- /dev/null +++ b/core/src/main/java/com/cloud/agent/api/routing/GetRouterMonitorResultsCommand.java @@ -0,0 +1,38 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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. + +package com.cloud.agent.api.routing; + +public class GetRouterMonitorResultsCommand extends NetworkElementCommand { + private boolean performFreshChecks; + + protected GetRouterMonitorResultsCommand() { + } + + public GetRouterMonitorResultsCommand(boolean performFreshChecks) { + this.performFreshChecks = performFreshChecks; + } + + @Override + public boolean isQuery() { + return true; + } + + public boolean shouldPerformFreshChecks() { + return performFreshChecks; + } +} \ No newline at end of file diff --git a/core/src/main/java/com/cloud/agent/api/routing/LoadRouterHealthChecksConfigCommand.java b/core/src/main/java/com/cloud/agent/api/routing/LoadRouterHealthChecksConfigCommand.java new file mode 100644 index 000000000000..b705a469e81b --- /dev/null +++ b/core/src/main/java/com/cloud/agent/api/routing/LoadRouterHealthChecksConfigCommand.java @@ -0,0 +1,41 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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. + +package com.cloud.agent.api.routing; + +import java.util.HashMap; +import java.util.Map; + +/** + * Loads new and updates old configuration details on VR for health checks. + */ +public class LoadRouterHealthChecksConfigCommand extends NetworkElementCommand { + + private Map details; + + protected LoadRouterHealthChecksConfigCommand() { + details = new HashMap<>(); + } + + public void addDetail(String key, String value) { + this.details.put(key, value); + } + + public Map getDetails() { + return details; + } +} diff --git a/core/src/main/java/com/cloud/agent/api/routing/NetworkElementCommand.java b/core/src/main/java/com/cloud/agent/api/routing/NetworkElementCommand.java index ae482ac71ec7..de3843e2b837 100644 --- a/core/src/main/java/com/cloud/agent/api/routing/NetworkElementCommand.java +++ b/core/src/main/java/com/cloud/agent/api/routing/NetworkElementCommand.java @@ -38,7 +38,6 @@ public abstract class NetworkElementCommand extends Command { public static final String GUEST_BRIDGE = "guest.bridge"; public static final String VPC_PRIVATE_GATEWAY = "vpc.gateway.private"; public static final String FIREWALL_EGRESS_DEFAULT = "firewall.egress.default"; - public static final String ROUTER_MONITORING_ENABLE = "router.monitor.enable"; public static final String NETWORK_PUB_LAST_IP = "network.public.last.ip"; private String routerAccessIp; diff --git a/core/src/main/java/com/cloud/agent/api/routing/SetMonitorServiceCommand.java b/core/src/main/java/com/cloud/agent/api/routing/SetMonitorServiceCommand.java index a5377039dd63..86fc14c88b79 100644 --- a/core/src/main/java/com/cloud/agent/api/routing/SetMonitorServiceCommand.java +++ b/core/src/main/java/com/cloud/agent/api/routing/SetMonitorServiceCommand.java @@ -20,6 +20,9 @@ package com.cloud.agent.api.routing; import java.util.List; +import java.util.Map; + +import org.apache.commons.collections.CollectionUtils; import com.cloud.agent.api.to.MonitorServiceTO; @@ -29,13 +32,24 @@ * how to access the components inside the command. */ public class SetMonitorServiceCommand extends NetworkElementCommand { - MonitorServiceTO[] services; + public static final String ROUTER_MONITORING_ENABLED = "router.monitor.enabled"; + public static final String ROUTER_HEALTH_CHECKS_ENABLED = "router.health.checks.enabled"; + public static final String ROUTER_HEALTH_CHECKS_BASIC_INTERVAL = "router.health.checks.basic.interval"; + public static final String ROUTER_HEALTH_CHECKS_ADVANCED_INTERVAL = "router.health.checks.advanced.interval"; + public static final String ROUTER_HEALTH_CHECKS_EXCLUDED = "router.health.checks.excluded"; + + private MonitorServiceTO[] services; + private Map healthChecksConfig; + private boolean reconfigureAfterUpdate; + private boolean deleteFromProcessedCache; protected SetMonitorServiceCommand() { } public SetMonitorServiceCommand(List services) { - this.services = services.toArray(new MonitorServiceTO[services.size()]); + if (CollectionUtils.isNotEmpty(services)) { + this.services = services.toArray(new MonitorServiceTO[services.size()]); + } } public MonitorServiceTO[] getRules() { @@ -43,7 +57,9 @@ public MonitorServiceTO[] getRules() { } public String getConfiguration() { - + if (services == null) { + return null; + } StringBuilder sb = new StringBuilder(); for (MonitorServiceTO service : services) { sb.append("[").append(service.getService()).append("]").append(":"); @@ -55,4 +71,28 @@ public String getConfiguration() { return sb.toString(); } + + public Map getHealthChecksConfig() { + return healthChecksConfig; + } + + public void setHealthChecksConfig(Map healthChecksConfig) { + this.healthChecksConfig = healthChecksConfig; + } + + public boolean shouldReconfigureAfterUpdate() { + return reconfigureAfterUpdate; + } + + public void setReconfigureAfterUpdate(boolean reconfigureAfterUpdate) { + this.reconfigureAfterUpdate = reconfigureAfterUpdate; + } + + public boolean shouldDeleteFromProcessedCache() { + return deleteFromProcessedCache; + } + + public void setDeleteFromProcessedCache(boolean deleteFromProcessedCache) { + this.deleteFromProcessedCache = deleteFromProcessedCache; + } } diff --git a/core/src/main/java/com/cloud/agent/resource/virtualnetwork/VRScripts.java b/core/src/main/java/com/cloud/agent/resource/virtualnetwork/VRScripts.java index b9d6487de561..f8cf6d451b84 100644 --- a/core/src/main/java/com/cloud/agent/resource/virtualnetwork/VRScripts.java +++ b/core/src/main/java/com/cloud/agent/resource/virtualnetwork/VRScripts.java @@ -47,6 +47,8 @@ public class VRScripts { // New scripts for use with chef public static final String UPDATE_CONFIG = "update_config.py"; + public static final String CONFIGURE = "configure.py"; + // Script still in use - mostly by HyperV public static final String S2SVPN_CHECK = "checkbatchs2svpn.sh"; @@ -66,6 +68,7 @@ public class VRScripts { public static final String VPC_STATIC_ROUTE = "vpc_staticroute.sh"; public static final String VPN_L2TP = "vpn_l2tp.sh"; public static final String UPDATE_HOST_PASSWD = "update_host_passwd.sh"; + public static final String ROUTER_MONITOR_RESULTS = "getRouterMonitorResults.sh"; public static final String VR_CFG = "vr_cfg.sh"; diff --git a/core/src/main/java/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java b/core/src/main/java/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java index 191a62263f36..f07b1b26bdeb 100644 --- a/core/src/main/java/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java +++ b/core/src/main/java/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java @@ -22,13 +22,6 @@ import java.io.IOException; import java.net.InetSocketAddress; import java.nio.channels.SocketChannel; - -import org.apache.cloudstack.diagnostics.DeleteFileInVrCommand; -import org.apache.cloudstack.diagnostics.DiagnosticsAnswer; -import org.apache.cloudstack.diagnostics.DiagnosticsCommand; -import org.apache.cloudstack.diagnostics.PrepareFilesAnswer; -import org.apache.cloudstack.diagnostics.PrepareFilesCommand; -import org.joda.time.Duration; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -45,8 +38,14 @@ import org.apache.cloudstack.ca.SetupCertificateCommand; import org.apache.cloudstack.ca.SetupKeyStoreCommand; import org.apache.cloudstack.ca.SetupKeystoreAnswer; +import org.apache.cloudstack.diagnostics.DeleteFileInVrCommand; +import org.apache.cloudstack.diagnostics.DiagnosticsAnswer; +import org.apache.cloudstack.diagnostics.DiagnosticsCommand; +import org.apache.cloudstack.diagnostics.PrepareFilesAnswer; +import org.apache.cloudstack.diagnostics.PrepareFilesCommand; import org.apache.cloudstack.utils.security.KeyStoreUtils; import org.apache.log4j.Logger; +import org.joda.time.Duration; import com.cloud.agent.api.Answer; import com.cloud.agent.api.CheckRouterAnswer; @@ -59,6 +58,8 @@ import com.cloud.agent.api.routing.AggregationControlCommand; import com.cloud.agent.api.routing.AggregationControlCommand.Action; import com.cloud.agent.api.routing.GetRouterAlertsCommand; +import com.cloud.agent.api.routing.GetRouterMonitorResultsAnswer; +import com.cloud.agent.api.routing.GetRouterMonitorResultsCommand; import com.cloud.agent.api.routing.GroupAnswer; import com.cloud.agent.api.routing.NetworkElementCommand; import com.cloud.agent.resource.virtualnetwork.facade.AbstractConfigItemFacade; @@ -204,6 +205,8 @@ private Answer executeQueryCommand(NetworkElementCommand cmd) { return execute((PrepareFilesCommand) cmd); } else if (cmd instanceof DeleteFileInVrCommand) { return execute((DeleteFileInVrCommand)cmd); + } else if (cmd instanceof GetRouterMonitorResultsCommand) { + return execute((GetRouterMonitorResultsCommand)cmd); } else { s_logger.error("Unknown query command in VirtualRoutingResource!"); return Answer.createUnsupportedCommandAnswer(cmd); @@ -225,10 +228,7 @@ private ExecutionResult applyConfigToVR(String routerAccessIp, ConfigItem c, Dur throw new CloudRuntimeException("Unable to apply unknown configitem of type " + c.getClass().getSimpleName()); } - private Answer applyConfig(NetworkElementCommand cmd, List cfg) { - - if (cfg.isEmpty()) { return new Answer(cmd, true, "Nothing to do"); } @@ -256,7 +256,6 @@ private Answer applyConfig(NetworkElementCommand cmd, List cfg) { s_logger.warn("Expected " + cmd.getAnswersCount() + " answers while executing " + cmd.getClass().getSimpleName() + " but received " + results.size()); } - if (results.size() == 1) { return new Answer(cmd, finalResult, results.get(0).getDetails()); } else { @@ -275,6 +274,60 @@ private CheckS2SVpnConnectionsAnswer execute(CheckS2SVpnConnectionsCommand cmd) return new CheckS2SVpnConnectionsAnswer(cmd, result.isSuccess(), result.getDetails()); } + private List getFailingChecks(String line) { + List failingChecks = new ArrayList<>(); + for (String w : line.split(",")) { + if (!w.trim().isEmpty()) { + failingChecks.add(w.trim()); + } + } + return failingChecks; + } + + private GetRouterMonitorResultsAnswer parseLinesForHealthChecks(GetRouterMonitorResultsCommand cmd, String executionResult) { + List failingChecks = new ArrayList<>(); + StringBuilder monitorResults = new StringBuilder(); + String[] lines = executionResult.trim().split("\n"); + boolean readingFailedChecks = false, readingMonitorResults = false; + for (String line : lines) { + line = line.trim(); + if (line.contains("FAILING CHECKS")) { // Toggle to reading failing checks from next line + readingFailedChecks = true; + readingMonitorResults = false; + } else if (line.contains("MONITOR RESULTS")) { // Toggle to reading monitor results from next line + readingFailedChecks = false; + readingMonitorResults = true; + } else if (readingFailedChecks && !readingMonitorResults) { // Reading failing checks section + failingChecks.addAll(getFailingChecks(line)); + } else if (!readingFailedChecks && readingMonitorResults) { // Reading monitor checks result + monitorResults.append(line); + } else { + s_logger.error("Unexpected lines reached while parsing health check response. Skipping line:- " + line); + } + } + + return new GetRouterMonitorResultsAnswer(cmd, true, failingChecks, monitorResults.toString()); + } + + private GetRouterMonitorResultsAnswer execute(GetRouterMonitorResultsCommand cmd) { + String routerIp = cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP); + String args = cmd.shouldPerformFreshChecks() ? "true" : "false"; + s_logger.info("Fetching health check result for " + routerIp + " and executing fresh checks: " + args); + ExecutionResult result = _vrDeployer.executeInVR(routerIp, VRScripts.ROUTER_MONITOR_RESULTS, args); + + if (!result.isSuccess()) { + s_logger.warn("Result of " + cmd + " failed with details: " + result.getDetails()); + return new GetRouterMonitorResultsAnswer(cmd, false, null, result.getDetails()); + } + + if (result.getDetails().isEmpty()) { + s_logger.warn("Result of " + cmd + " received no details."); + return new GetRouterMonitorResultsAnswer(cmd, false, null, "No results available."); + } + + return parseLinesForHealthChecks(cmd, result.getDetails()); + } + private GetRouterAlertsAnswer execute(GetRouterAlertsCommand cmd) { String routerIp = cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP); diff --git a/core/src/main/java/com/cloud/agent/resource/virtualnetwork/facade/AbstractConfigItemFacade.java b/core/src/main/java/com/cloud/agent/resource/virtualnetwork/facade/AbstractConfigItemFacade.java index a083012021ff..1042d23e7b0c 100644 --- a/core/src/main/java/com/cloud/agent/resource/virtualnetwork/facade/AbstractConfigItemFacade.java +++ b/core/src/main/java/com/cloud/agent/resource/virtualnetwork/facade/AbstractConfigItemFacade.java @@ -127,7 +127,10 @@ protected List generateConfigItems(final ConfigBase configuration) { final ConfigItem configFile = new FileConfigItem(VRScripts.CONFIG_PERSIST_LOCATION, remoteFilename, gson.toJson(configuration)); cfg.add(configFile); - final ConfigItem updateCommand = new ScriptConfigItem(VRScripts.UPDATE_CONFIG, remoteFilename); + // By default keep files in processed cache on VR + final String args = configuration.shouldDeleteFromProcessedCache() ? remoteFilename + " false" : remoteFilename; + + final ConfigItem updateCommand = new ScriptConfigItem(VRScripts.UPDATE_CONFIG, args); cfg.add(updateCommand); return cfg; diff --git a/core/src/main/java/com/cloud/agent/resource/virtualnetwork/facade/SetMonitorServiceConfigItem.java b/core/src/main/java/com/cloud/agent/resource/virtualnetwork/facade/SetMonitorServiceConfigItem.java index 2cf03e445fc1..8ddf17b15b9c 100644 --- a/core/src/main/java/com/cloud/agent/resource/virtualnetwork/facade/SetMonitorServiceConfigItem.java +++ b/core/src/main/java/com/cloud/agent/resource/virtualnetwork/facade/SetMonitorServiceConfigItem.java @@ -21,21 +21,56 @@ import java.util.List; +import org.apache.log4j.Logger; + import com.cloud.agent.api.routing.NetworkElementCommand; import com.cloud.agent.api.routing.SetMonitorServiceCommand; import com.cloud.agent.resource.virtualnetwork.ConfigItem; +import com.cloud.agent.resource.virtualnetwork.ScriptConfigItem; import com.cloud.agent.resource.virtualnetwork.VRScripts; import com.cloud.agent.resource.virtualnetwork.model.ConfigBase; import com.cloud.agent.resource.virtualnetwork.model.MonitorService; public class SetMonitorServiceConfigItem extends AbstractConfigItemFacade { + private static final Logger s_logger = Logger.getLogger(SetMonitorServiceConfigItem.class); @Override public List generateConfig(final NetworkElementCommand cmd) { final SetMonitorServiceCommand command = (SetMonitorServiceCommand) cmd; - final MonitorService monitorService = new MonitorService(command.getConfiguration(), cmd.getAccessDetail(NetworkElementCommand.ROUTER_MONITORING_ENABLE)); - return generateConfigItems(monitorService); + final MonitorService monitorService = new MonitorService( + command.getConfiguration(), + cmd.getAccessDetail(SetMonitorServiceCommand.ROUTER_MONITORING_ENABLED), + cmd.getAccessDetail(SetMonitorServiceCommand.ROUTER_HEALTH_CHECKS_ENABLED)); + + setupHealthChecksRelatedInfo(monitorService, command); + + monitorService.setDeleteFromProcessedCache(command.shouldDeleteFromProcessedCache()); + + List configItems = generateConfigItems(monitorService); + if (configItems != null && command.shouldReconfigureAfterUpdate()) { + configItems.add(new ScriptConfigItem(VRScripts.CONFIGURE, "monitor_service.json")); + } + return configItems; + } + + private void setupHealthChecksRelatedInfo(MonitorService monitorService, SetMonitorServiceCommand command) { + try { + monitorService.setHealthChecksBasicRunInterval(Integer.parseInt(command.getAccessDetail(SetMonitorServiceCommand.ROUTER_HEALTH_CHECKS_BASIC_INTERVAL))); + } catch (NumberFormatException exception) { + s_logger.error("Unexpected health check basic interval set" + command.getAccessDetail(SetMonitorServiceCommand.ROUTER_HEALTH_CHECKS_BASIC_INTERVAL) + + ". Exception: " + exception + "Will use default value"); + } + + try { + monitorService.setHealthChecksAdvancedRunInterval(Integer.parseInt(command.getAccessDetail(SetMonitorServiceCommand.ROUTER_HEALTH_CHECKS_ADVANCED_INTERVAL))); + } catch (NumberFormatException exception) { + s_logger.error("Unexpected health check advanced interval set" + command.getAccessDetail(SetMonitorServiceCommand.ROUTER_HEALTH_CHECKS_ADVANCED_INTERVAL) + + ". Exception: " + exception + "Will use default value"); + } + + monitorService.setExcludedHealthChecks(command.getAccessDetail(SetMonitorServiceCommand.ROUTER_HEALTH_CHECKS_EXCLUDED)); + monitorService.setHealthChecksConfig(command.getHealthChecksConfig()); } @Override diff --git a/core/src/main/java/com/cloud/agent/resource/virtualnetwork/model/ConfigBase.java b/core/src/main/java/com/cloud/agent/resource/virtualnetwork/model/ConfigBase.java index edc721178cbe..51424ea3115d 100644 --- a/core/src/main/java/com/cloud/agent/resource/virtualnetwork/model/ConfigBase.java +++ b/core/src/main/java/com/cloud/agent/resource/virtualnetwork/model/ConfigBase.java @@ -41,6 +41,10 @@ public abstract class ConfigBase { private String type = UNKNOWN; + // For use in update_config.py which by default persists files in /var/cache/cloud/processed + // If true we don't keep the file in cache. Useful for monitor service command to avoid space waste + protected boolean deleteFromProcessedCache; + private ConfigBase() { // Empty constructor for (de)serialization } @@ -57,4 +61,7 @@ public void setType(final String type) { this.type = type; } + public boolean shouldDeleteFromProcessedCache() { + return deleteFromProcessedCache; + } } diff --git a/core/src/main/java/com/cloud/agent/resource/virtualnetwork/model/MonitorService.java b/core/src/main/java/com/cloud/agent/resource/virtualnetwork/model/MonitorService.java index fdf9e473f35c..fe20476f076d 100644 --- a/core/src/main/java/com/cloud/agent/resource/virtualnetwork/model/MonitorService.java +++ b/core/src/main/java/com/cloud/agent/resource/virtualnetwork/model/MonitorService.java @@ -19,34 +19,84 @@ package com.cloud.agent.resource.virtualnetwork.model; +import java.util.Map; + public class MonitorService extends ConfigBase { public String config, disableMonitoring; + public Boolean healthChecksEnabled; + public Integer healthChecksBasicRunInterval; + public Integer healthChecksAdvancedRunInterval; + public String excludedHealthChecks; + public Map healthChecksConfig; public MonitorService() { super(ConfigBase.MONITORSERVICE); } - public MonitorService(String config, String disableMonitoring) { + public MonitorService(String config, String disableMonitoring, String healthChecksEnabled) { super(ConfigBase.MONITORSERVICE); this.config = config; this.disableMonitoring = disableMonitoring; + this.healthChecksEnabled = Boolean.parseBoolean(healthChecksEnabled); } public String getConfig() { return config; } - public void setConfig(String config) { - this.config = config; - } - public String getDisableMonitoring() { return disableMonitoring; } + public Boolean getHealthChecksEnabled() { + return healthChecksEnabled; + } + + public Integer getHealthChecksBasicRunInterval() { + return healthChecksBasicRunInterval; + } + + public Integer getHealthChecksAdvancedRunInterval() { + return healthChecksAdvancedRunInterval; + } + + public String getExcludedHealthChecks() { + return excludedHealthChecks; + } + + public Map getHealthChecksConfig() { + return healthChecksConfig; + } + + public void setConfig(String config) { + this.config = config; + } + public void setDisableMonitoring(String disableMonitoring) { this.disableMonitoring = disableMonitoring; } + public void setHealthChecksEnabled(Boolean healthChecksEnabled) { + this.healthChecksEnabled = healthChecksEnabled; + } + + public void setHealthChecksBasicRunInterval(Integer healthChecksBasicRunInterval) { + this.healthChecksBasicRunInterval = healthChecksBasicRunInterval; + } + + public void setHealthChecksAdvancedRunInterval(Integer healthChecksAdvancedRunInterval) { + this.healthChecksAdvancedRunInterval = healthChecksAdvancedRunInterval; + } + + public void setExcludedHealthChecks(String excludedHealthChecks) { + this.excludedHealthChecks = excludedHealthChecks; + } + public void setHealthChecksConfig(Map healthChecksConfig) { + this.healthChecksConfig = healthChecksConfig; + } + + public void setDeleteFromProcessedCache(boolean deleteFromProcessedCache) { + this.deleteFromProcessedCache = deleteFromProcessedCache; + } } diff --git a/core/src/test/java/com/cloud/storage/template/QCOW2ProcessorTest.java b/core/src/test/java/com/cloud/storage/template/QCOW2ProcessorTest.java index c268c413fc72..c8c6fb70e277 100644 --- a/core/src/test/java/com/cloud/storage/template/QCOW2ProcessorTest.java +++ b/core/src/test/java/com/cloud/storage/template/QCOW2ProcessorTest.java @@ -18,23 +18,26 @@ */ package com.cloud.storage.template; -import com.cloud.exception.InternalErrorException; -import com.cloud.storage.Storage; -import com.cloud.storage.StorageLayer; +import java.io.File; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.Mockito; -import org.mockito.runners.MockitoJUnitRunner; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; -import java.io.File; -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; +import com.cloud.exception.InternalErrorException; +import com.cloud.storage.Storage; +import com.cloud.storage.StorageLayer; -@RunWith(MockitoJUnitRunner.class) +@RunWith(PowerMockRunner.class) +@PrepareForTest(QCOW2Processor.class) public class QCOW2ProcessorTest { QCOW2Processor processor; diff --git a/core/src/test/java/com/cloud/storage/template/VhdProcessorTest.java b/core/src/test/java/com/cloud/storage/template/VhdProcessorTest.java index 3c695d7c250d..2be4353f793e 100644 --- a/core/src/test/java/com/cloud/storage/template/VhdProcessorTest.java +++ b/core/src/test/java/com/cloud/storage/template/VhdProcessorTest.java @@ -19,25 +19,28 @@ package com.cloud.storage.template; -import com.cloud.exception.InternalErrorException; -import com.cloud.storage.Storage; -import com.cloud.storage.StorageLayer; +import java.io.File; +import java.io.IOException; +import java.net.URLDecoder; +import java.nio.charset.Charset; +import java.util.HashMap; +import java.util.Map; + import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.Mockito; -import org.mockito.runners.MockitoJUnitRunner; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; -import java.io.File; -import java.io.IOException; -import java.net.URLDecoder; -import java.nio.charset.Charset; -import java.util.HashMap; -import java.util.Map; +import com.cloud.exception.InternalErrorException; +import com.cloud.storage.Storage; +import com.cloud.storage.StorageLayer; -@RunWith(MockitoJUnitRunner.class) +@RunWith(PowerMockRunner.class) +@PrepareForTest(VhdProcessor.class) public class VhdProcessorTest { VhdProcessor processor; diff --git a/debian/cloudstack-common.install b/debian/cloudstack-common.install index accc6fadfa22..9a9cf3bbc09f 100644 --- a/debian/cloudstack-common.install +++ b/debian/cloudstack-common.install @@ -26,6 +26,7 @@ /usr/share/cloudstack-common/scripts/vm/hypervisor/kvm/* /usr/share/cloudstack-common/scripts/vm/hypervisor/update_host_passwd.sh /usr/share/cloudstack-common/scripts/vm/hypervisor/versions.sh +/usr/share/cloudstack-common/scripts/vm/hypervisor/vmware/* /usr/share/cloudstack-common/scripts/vm/hypervisor/xenserver/* /usr/share/cloudstack-common/lib/* /usr/bin/cloudstack-set-guest-password diff --git a/debian/control b/debian/control index 3fde8d6d415c..9b2e912b14dd 100644 --- a/debian/control +++ b/debian/control @@ -2,7 +2,7 @@ Source: cloudstack Section: libs Priority: extra Maintainer: Wido den Hollander -Build-Depends: debhelper (>= 9), openjdk-8-jdk | java8-sdk | java8-jdk | openjdk-9-jdk, genisoimage, +Build-Depends: debhelper (>= 9), openjdk-11-jdk | java11-sdk | java11-jdk, genisoimage, python-mysql.connector, maven (>= 3) | maven3, python (>= 2.7), python3 (>= 3), lsb-release, dh-systemd, python-setuptools Standards-Version: 3.8.1 Homepage: http://www.cloudstack.org/ @@ -15,14 +15,14 @@ Description: A common package which contains files which are shared by several C Package: cloudstack-management Architecture: all -Depends: ${python:Depends}, openjdk-8-jre-headless | java8-runtime-headless | java8-runtime | openjdk-9-jre-headless, cloudstack-common (= ${source:Version}), sudo, python-mysql.connector, libmysql-java, augeas-tools, mysql-client, adduser, bzip2, ipmitool, file, gawk, iproute2, lsb-release, init-system-helpers (>= 1.14~), qemu-utils +Depends: ${python:Depends}, openjdk-11-jre-headless | java11-runtime-headless | java11-runtime | openjdk-11-jre-headless, cloudstack-common (= ${source:Version}), sudo, python-mysql.connector, augeas-tools, mysql-client | mariadb-client, adduser, bzip2, ipmitool, file, gawk, iproute2, qemu-utils, python-dnspython, lsb-release, init-system-helpers (>= 1.14~) Conflicts: cloud-server, cloud-client, cloud-client-ui Description: CloudStack server library The CloudStack management server Package: cloudstack-agent Architecture: all -Depends: ${python:Depends}, openjdk-8-jre-headless | java8-runtime-headless | java8-runtime | openjdk-9-jre-headless, cloudstack-common (= ${source:Version}), lsb-base (>= 9), openssh-client, qemu-kvm (>= 2.5), libvirt-bin (>= 1.3) | libvirt-daemon-system (>= 3.0), uuid-runtime, iproute2, ebtables, vlan, ipset, python3-libvirt, ethtool, iptables, lsb-release, aria2 +Depends: ${python:Depends}, openjdk-11-jre-headless | java11-runtime-headless | java11-runtime | openjdk-11-jre-headless, cloudstack-common (= ${source:Version}), lsb-base (>= 9), openssh-client, qemu-kvm (>= 2.5), libvirt-bin (>= 1.3) | libvirt-daemon-system (>= 3.0), uuid-runtime, iproute2, ebtables, vlan, ipset, python3-libvirt, ethtool, iptables, lsb-release, aria2 Recommends: init-system-helpers Conflicts: cloud-agent, cloud-agent-libs, cloud-agent-deps, cloud-agent-scripts Description: CloudStack agent @@ -32,7 +32,7 @@ Description: CloudStack agent Package: cloudstack-usage Architecture: all -Depends: openjdk-8-jre-headless | java8-runtime-headless | java8-runtime | openjdk-9-jre-headless, cloudstack-common (= ${source:Version}), libmysql-java, init-system-helpers +Depends: openjdk-11-jre-headless | java11-runtime-headless | java11-runtime | openjdk-11-jre-headless, cloudstack-common (= ${source:Version}), init-system-helpers Description: CloudStack usage monitor The CloudStack usage monitor provides usage accounting across the entire cloud for cloud operators to charge based on usage parameters. diff --git a/debian/rules b/debian/rules index 59f7e6f54eb6..4220a839eb56 100755 --- a/debian/rules +++ b/debian/rules @@ -110,7 +110,7 @@ override_dh_auto_install: install -D client/target/utilities/bin/cloud-sysvmadm $(DESTDIR)/usr/bin/cloudstack-sysvmadm install -D systemvm/dist/systemvm.iso $(DESTDIR)/usr/share/$(PACKAGE)-common/vms/systemvm.iso # We need jasypt for cloud-install-sys-tmplt, so this is a nasty hack to get it into the right place - install -D agent/target/dependencies/jasypt-1.9.2.jar $(DESTDIR)/usr/share/$(PACKAGE)-common/lib + install -D agent/target/dependencies/jasypt-1.9.3.jar $(DESTDIR)/usr/share/$(PACKAGE)-common/lib # cloudstack-python mkdir -p $(DESTDIR)/usr/share/pyshared @@ -122,6 +122,7 @@ override_dh_auto_install: mkdir $(DESTDIR)/usr/share/$(PACKAGE)-usage/plugins install -D usage/target/cloud-usage-$(VERSION).jar $(DESTDIR)/usr/share/$(PACKAGE)-usage/lib/$(PACKAGE)-usage.jar install -D usage/target/dependencies/* $(DESTDIR)/usr/share/$(PACKAGE)-usage/lib/ + cp client/target/lib/mysql*jar $(DESTDIR)/usr/share/$(PACKAGE)-usage/lib/ cp usage/target/transformed/db.properties $(DESTDIR)/$(SYSCONFDIR)/$(PACKAGE)/usage/ cp usage/target/transformed/log4j-cloud_usage.xml $(DESTDIR)/$(SYSCONFDIR)/$(PACKAGE)/usage/log4j-cloud.xml diff --git a/engine/api/pom.xml b/engine/api/pom.xml index 645683e18bba..f5550438850a 100644 --- a/engine/api/pom.xml +++ b/engine/api/pom.xml @@ -58,5 +58,20 @@ cloud-framework-config ${project.version} + + javax.xml.bind + jaxb-api + ${cs.jaxb.version} + + + com.sun.xml.bind + jaxb-core + ${cs.jaxb.version} + + + com.sun.xml.bind + jaxb-impl + ${cs.jaxb.version} + diff --git a/engine/api/src/main/java/com/cloud/vm/VirtualMachineManager.java b/engine/api/src/main/java/com/cloud/vm/VirtualMachineManager.java index 6041146b9de2..491adfd71a4e 100644 --- a/engine/api/src/main/java/com/cloud/vm/VirtualMachineManager.java +++ b/engine/api/src/main/java/com/cloud/vm/VirtualMachineManager.java @@ -58,6 +58,9 @@ public interface VirtualMachineManager extends Manager { ConfigKey VmConfigDriveOnPrimaryPool = new ConfigKey<>("Advanced", Boolean.class, "vm.configdrive.primarypool.enabled", "false", "If config drive need to be created and hosted on primary storage pool. Currently only supported for KVM.", true); + ConfigKey ResoureCountRunningVMsonly = new ConfigKey("Advanced", Boolean.class, "resource.count.running.vms.only", "false", + "Count the resources of only running VMs in resource limitation.", true); + interface Topics { String VM_POWER_STATE = "vm.powerstate"; } diff --git a/engine/api/src/main/java/org/apache/cloudstack/engine/orchestration/service/NetworkOrchestrationService.java b/engine/api/src/main/java/org/apache/cloudstack/engine/orchestration/service/NetworkOrchestrationService.java index 94a4259a6897..64c0e38613e6 100644 --- a/engine/api/src/main/java/org/apache/cloudstack/engine/orchestration/service/NetworkOrchestrationService.java +++ b/engine/api/src/main/java/org/apache/cloudstack/engine/orchestration/service/NetworkOrchestrationService.java @@ -23,6 +23,7 @@ import org.apache.cloudstack.acl.ControlledEntity.ACLType; import org.apache.cloudstack.framework.config.ConfigKey; import org.apache.cloudstack.framework.config.ConfigKey.Scope; + import com.cloud.deploy.DataCenterDeployment; import com.cloud.deploy.DeployDestination; import com.cloud.deploy.DeploymentPlan; @@ -179,7 +180,7 @@ void prepare(VirtualMachineProfile profile, DeployDestination dest, ReservationC Network createGuestNetwork(long networkOfferingId, String name, String displayText, String gateway, String cidr, String vlanId, boolean bypassVlanOverlapCheck, String networkDomain, Account owner, Long domainId, PhysicalNetwork physicalNetwork, long zoneId, ACLType aclType, Boolean subdomainAccess, Long vpcId, String ip6Gateway, String ip6Cidr, - Boolean displayNetworkEnabled, String isolatedPvlan, String externalId) throws ConcurrentOperationException, InsufficientCapacityException, ResourceAllocationException; + Boolean displayNetworkEnabled, String isolatedPvlan, Network.PVlanType isolatedPvlanType, String externalId) throws ConcurrentOperationException, InsufficientCapacityException, ResourceAllocationException; UserDataServiceProvider getPasswordResetProvider(Network network); @@ -313,4 +314,6 @@ void implementNetworkElementsAndResources(DeployDestination dest, ReservationCon * Remove entry from /etc/dhcphosts and /etc/hosts on virtual routers */ void cleanupNicDhcpDnsEntry(Network network, VirtualMachineProfile vmProfile, NicProfile nicProfile); + + Pair importNic(final String macAddress, int deviceId, final Network network, final Boolean isDefaultNic, final VirtualMachine vm, final Network.IpAddresses ipAddresses) throws InsufficientVirtualNetworkCapacityException, InsufficientAddressCapacityException; } diff --git a/engine/api/src/main/java/org/apache/cloudstack/engine/orchestration/service/VolumeOrchestrationService.java b/engine/api/src/main/java/org/apache/cloudstack/engine/orchestration/service/VolumeOrchestrationService.java index fa6f2c6fb9d4..a769a3428b5e 100644 --- a/engine/api/src/main/java/org/apache/cloudstack/engine/orchestration/service/VolumeOrchestrationService.java +++ b/engine/api/src/main/java/org/apache/cloudstack/engine/orchestration/service/VolumeOrchestrationService.java @@ -88,6 +88,8 @@ VolumeInfo moveVolume(VolumeInfo volume, long destPoolDcId, Long destPoolPodId, Volume migrateVolume(Volume volume, StoragePool destPool) throws StorageUnavailableException; + Volume liveMigrateVolume(Volume volume, StoragePool destPool); + void cleanupStorageJobs(); void destroyVolume(Volume volume); @@ -127,4 +129,24 @@ DiskProfile allocateTemplatedVolume(Type type, String name, DiskOffering offerin StoragePool findStoragePool(DiskProfile dskCh, DataCenter dc, Pod pod, Long clusterId, Long hostId, VirtualMachine vm, Set avoid); void updateVolumeDiskChain(long volumeId, String path, String chainInfo); + + /** + * Imports an existing volume for a VM into database. Useful while ingesting an unmanaged VM. + * @param type Type of the volume - ROOT, DATADISK, etc + * @param name Name of the volume + * @param offering DiskOffering for the volume + * @param size DiskOffering for the volume + * @param minIops minimum IOPS for the disk, if not passed DiskOffering value will be used + * @param maxIops maximum IOPS for the disk, if not passed DiskOffering value will be used + * @param vm VirtualMachine this volume is attached to + * @param template Template of the VM of the volume + * @param owner owner Account for the volume + * @param deviceId device ID of the virtual disk + * @param poolId ID of pool in which volume is stored + * @param path image path of the volume + * @param chainInfo chain info for the volume. Hypervisor specific. + * @return DiskProfile of imported volume + */ + DiskProfile importVolume(Type type, String name, DiskOffering offering, Long size, Long minIops, Long maxIops, VirtualMachine vm, VirtualMachineTemplate template, + Account owner, Long deviceId, Long poolId, String path, String chainInfo); } diff --git a/engine/components-api/src/main/java/com/cloud/agent/AgentManager.java b/engine/components-api/src/main/java/com/cloud/agent/AgentManager.java index c51970c85f76..1d8e5faf9d4a 100644 --- a/engine/components-api/src/main/java/com/cloud/agent/AgentManager.java +++ b/engine/components-api/src/main/java/com/cloud/agent/AgentManager.java @@ -152,4 +152,6 @@ public enum TapAgentsAction { void notifyMonitorsOfHostAboutToBeRemoved(long hostId); void notifyMonitorsOfRemovedHost(long hostId, long clusterId); + + void propagateChangeToAgents(); } diff --git a/server/src/main/java/com/cloud/network/security/SecurityGroupManager.java b/engine/components-api/src/main/java/com/cloud/network/security/SecurityGroupManager.java similarity index 95% rename from server/src/main/java/com/cloud/network/security/SecurityGroupManager.java rename to engine/components-api/src/main/java/com/cloud/network/security/SecurityGroupManager.java index 16d8ba617bca..ffca4bb013b6 100644 --- a/server/src/main/java/com/cloud/network/security/SecurityGroupManager.java +++ b/engine/components-api/src/main/java/com/cloud/network/security/SecurityGroupManager.java @@ -53,4 +53,6 @@ public interface SecurityGroupManager { SecurityGroup getSecurityGroup(String name, long accountId); boolean isVmMappedToDefaultSecurityGroup(long vmId); + + void scheduleRulesetUpdateToHosts(List affectedVms, boolean updateSeqno, Long delayMs); } diff --git a/engine/orchestration/src/main/java/com/cloud/agent/manager/AgentManagerImpl.java b/engine/orchestration/src/main/java/com/cloud/agent/manager/AgentManagerImpl.java index 2b80ec963c10..fe6d9d514f6f 100644 --- a/engine/orchestration/src/main/java/com/cloud/agent/manager/AgentManagerImpl.java +++ b/engine/orchestration/src/main/java/com/cloud/agent/manager/AgentManagerImpl.java @@ -1790,4 +1790,45 @@ public int getTimeout() { } + protected Map> getHostsPerZone() { + List allHosts = _resourceMgr.listAllHostsInAllZonesByType(Host.Type.Routing); + if (allHosts == null) { + return null; + } + Map> hostsByZone = new HashMap>(); + for (HostVO host : allHosts) { + if (host.getHypervisorType() == HypervisorType.KVM || host.getHypervisorType() == HypervisorType.LXC) { + Long zoneId = host.getDataCenterId(); + List hostIds = hostsByZone.get(zoneId); + if (hostIds == null) { + hostIds = new ArrayList(); + } + hostIds.add(host.getId()); + hostsByZone.put(zoneId, hostIds); + } + } + return hostsByZone; + } + + private void sendCommandToAgents(Map> hostsPerZone, Map params) { + SetHostParamsCommand cmds = new SetHostParamsCommand(params); + for (Long zoneId : hostsPerZone.keySet()) { + List hostIds = hostsPerZone.get(zoneId); + for (Long hostId : hostIds) { + Answer answer = easySend(hostId, cmds); + if (answer == null || !answer.getResult()) { + s_logger.error("Error sending parameters to agent " + hostId); + } + } + } + } + + @Override + public void propagateChangeToAgents() { + s_logger.debug("Propagating changes on host parameters to the agents"); + Map> hostsPerZone = getHostsPerZone(); + Map params = new HashMap(); + params.put("router.aggregation.command.each.timeout", _configDao.getValue("router.aggregation.command.each.timeout")); + sendCommandToAgents(hostsPerZone, params); + } } diff --git a/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java b/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java index 58eed4ee679f..8e52c38902cc 100755 --- a/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java +++ b/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java @@ -24,6 +24,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.Comparator; import java.util.Date; import java.util.HashMap; import java.util.LinkedHashMap; @@ -39,6 +40,8 @@ import javax.inject.Inject; import javax.naming.ConfigurationException; +import com.cloud.network.dao.NetworkDetailVO; +import com.cloud.network.dao.NetworkDetailsDao; import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.command.admin.vm.MigrateVMCmd; @@ -122,6 +125,7 @@ import com.cloud.agent.manager.allocator.HostAllocator; import com.cloud.alert.AlertManager; import com.cloud.capacity.CapacityManager; +import com.cloud.configuration.Resource.ResourceType; import com.cloud.dc.ClusterDetailsDao; import com.cloud.dc.ClusterDetailsVO; import com.cloud.dc.DataCenter; @@ -163,6 +167,7 @@ import com.cloud.network.dao.NetworkDao; import com.cloud.network.dao.NetworkVO; import com.cloud.network.router.VirtualRouter; +import com.cloud.network.security.SecurityGroupManager; import com.cloud.offering.DiskOffering; import com.cloud.offering.DiskOfferingInfo; import com.cloud.offering.NetworkOffering; @@ -191,6 +196,7 @@ import com.cloud.storage.dao.VolumeDao; import com.cloud.template.VirtualMachineTemplate; import com.cloud.user.Account; +import com.cloud.user.ResourceLimitService; import com.cloud.user.User; import com.cloud.utils.DateUtil; import com.cloud.utils.Journal; @@ -302,6 +308,8 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac @Inject private ResourceManager _resourceMgr; @Inject + private ResourceLimitService _resourceLimitMgr; + @Inject private VMSnapshotManager _vmSnapshotMgr; @Inject private ClusterDetailsDao _clusterDetailsDao; @@ -325,6 +333,10 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac private StorageManager storageMgr; @Inject private NetworkOfferingDetailsDao networkOfferingDetailsDao; + @Inject + private NetworkDetailsDao networkDetailsDao; + @Inject + private SecurityGroupManager _securityGroupManager; VmWorkJobHandlerProxy _jobHandlerProxy = new VmWorkJobHandlerProxy(this); @@ -970,6 +982,12 @@ public void orchestrateStart(final String vmUuid, final Map affectedVms = new ArrayList(); + affectedVms.add(vm.getId()); + _securityGroupManager.scheduleRulesetUpdateToHosts(affectedVms, true, null); + } return; } s_logger.info("Unable to reboot VM " + vm + " on " + dest.getHost() + " due to " + (rebootAnswer == null ? " no reboot answer" : rebootAnswer.getDetails())); @@ -3131,6 +3165,29 @@ private void orchestrateReboot(final String vmUuid, final Map nics = _nicsDao.listByVmId(profile.getId()); + Collections.sort(nics, new Comparator() { + @Override + public int compare(NicVO nic1, NicVO nic2) { + Long nicId1 = Long.valueOf(nic1.getDeviceId()); + Long nicId2 = Long.valueOf(nic2.getDeviceId()); + return nicId1.compareTo(nicId2); + } + }); + for (final NicVO nic : nics) { + final Network network = _networkModel.getNetwork(nic.getNetworkId()); + final NicProfile nicProfile = + new NicProfile(nic, network, nic.getBroadcastUri(), nic.getIsolationUri(), null, _networkModel.isSecurityGroupSupportedInNetwork(network), + _networkModel.getNetworkTag(profile.getHypervisorType(), network)); + profile.addNic(nicProfile); + } + final VirtualMachineTO to = toVmTO(profile); + return to; + } + public Command cleanup(final VirtualMachine vm, Map dpdkInterfaceMapping) { StopCommand cmd = new StopCommand(vm, getExecuteInSequence(vm.getHypervisorType()), false); cmd.setControlIp(getControlNicIpForVM(vm)); @@ -3647,7 +3704,7 @@ private boolean orchestrateRemoveNicFromVm(final VirtualMachine vm, final Nic ni //3) Remove the nic _networkMgr.removeNic(vmProfile, nic); - _nicsDao.expunge(nic.getId()); + _nicsDao.remove(nic.getId()); return true; } @@ -4040,6 +4097,13 @@ public boolean plugNic(final Network network, final NicTO nic, final VirtualMach final VMInstanceVO router = _vmDao.findById(vm.getId()); if (router.getState() == State.Running) { try { + NetworkDetailVO pvlanTypeDetail = networkDetailsDao.findDetail(network.getId(), ApiConstants.ISOLATED_PVLAN_TYPE); + if (pvlanTypeDetail != null) { + Map nicDetails = nic.getDetails() == null ? new HashMap<>() : nic.getDetails(); + s_logger.debug("Found PVLAN type: " + pvlanTypeDetail.getValue() + " on network details, adding it as part of the PlugNicCommand"); + nicDetails.putIfAbsent(NetworkOffering.Detail.pvlanType, pvlanTypeDetail.getValue()); + nic.setDetails(nicDetails); + } final PlugNicCommand plugNicCmd = new PlugNicCommand(nic, vm.getName(), vm.getType(), vm.getDetails()); final Commands cmds = new Commands(Command.OnError.Stop); cmds.addCommand("plugnic", plugNicCmd); @@ -4218,7 +4282,8 @@ public String getConfigComponentName() { public ConfigKey[] getConfigKeys() { return new ConfigKey[] {ClusterDeltaSyncInterval, StartRetry, VmDestroyForcestop, VmOpCancelInterval, VmOpCleanupInterval, VmOpCleanupWait, VmOpLockStateRetry, - VmOpWaitInterval, ExecuteInSequence, VmJobCheckInterval, VmJobTimeout, VmJobStateReportInterval, VmConfigDriveLabel, VmConfigDriveOnPrimaryPool, HaVmRestartHostUp}; + VmOpWaitInterval, ExecuteInSequence, VmJobCheckInterval, VmJobTimeout, VmJobStateReportInterval, VmConfigDriveLabel, VmConfigDriveOnPrimaryPool, HaVmRestartHostUp, + ResoureCountRunningVMsonly }; } public List getStoragePoolAllocators() { @@ -5338,4 +5403,17 @@ private VmWorkJobVO createPlaceHolderWork(final long instanceId) { return workJob; } + + protected void resourceCountIncrement (long accountId, Long cpu, Long memory) { + _resourceLimitMgr.incrementResourceCount(accountId, ResourceType.user_vm); + _resourceLimitMgr.incrementResourceCount(accountId, ResourceType.cpu, cpu); + _resourceLimitMgr.incrementResourceCount(accountId, ResourceType.memory, memory); + } + + protected void resourceCountDecrement (long accountId, Long cpu, Long memory) { + _resourceLimitMgr.decrementResourceCount(accountId, ResourceType.user_vm); + _resourceLimitMgr.decrementResourceCount(accountId, ResourceType.cpu, cpu); + _resourceLimitMgr.decrementResourceCount(accountId, ResourceType.memory, memory); + } + } diff --git a/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachinePowerStateSyncImpl.java b/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachinePowerStateSyncImpl.java index 7ff3f10d61f6..a8a71b4a44d0 100644 --- a/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachinePowerStateSyncImpl.java +++ b/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachinePowerStateSyncImpl.java @@ -24,12 +24,12 @@ import javax.inject.Inject; -import org.apache.log4j.Logger; -import com.cloud.configuration.ManagementServiceConfiguration; import org.apache.cloudstack.framework.messagebus.MessageBus; import org.apache.cloudstack.framework.messagebus.PublishScope; +import org.apache.log4j.Logger; import com.cloud.agent.api.HostVmStateReportEntry; +import com.cloud.configuration.ManagementServiceConfiguration; import com.cloud.utils.DateUtil; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.vm.dao.VMInstanceDao; diff --git a/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java b/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java index 80ee71eef9bf..6250905b4f80 100644 --- a/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java +++ b/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java @@ -38,7 +38,10 @@ import javax.inject.Inject; import javax.naming.ConfigurationException; +import com.cloud.network.dao.NetworkDetailVO; +import com.cloud.network.dao.NetworkDetailsDao; import org.apache.cloudstack.acl.ControlledEntity.ACLType; +import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.engine.cloud.entity.api.db.VMNetworkMapVO; import org.apache.cloudstack.engine.cloud.entity.api.db.dao.VMNetworkMapDao; @@ -222,6 +225,8 @@ import com.cloud.vm.dao.VMInstanceDao; import com.google.common.base.Strings; +import static org.apache.commons.lang.StringUtils.isNotBlank; + /** * NetworkManagerImpl implements NetworkManager. */ @@ -251,6 +256,8 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra @Inject NetworkDao _networksDao; @Inject + NetworkDetailsDao networkDetailsDao; + @Inject NicDao _nicDao; @Inject RulesManager _rulesMgr; @@ -698,6 +705,11 @@ public void doInTransactionWithoutResult(final TransactionStatus status) { finalizeServicesAndProvidersForNetwork(offering, plan.getPhysicalNetworkId())); networks.add(networkPersisted); + if (network.getPvlanType() != null) { + NetworkDetailVO detailVO = new NetworkDetailVO(networkPersisted.getId(), ApiConstants.ISOLATED_PVLAN_TYPE, network.getPvlanType().toString(), true); + networkDetailsDao.persist(detailVO); + } + if (predefined instanceof NetworkVO && guru instanceof NetworkGuruAdditionalFunctions){ final NetworkGuruAdditionalFunctions functions = (NetworkGuruAdditionalFunctions) guru; functions.finalizeNetworkDesign(networkPersisted.getId(), ((NetworkVO)predefined).getVlanIdAsUUID()); @@ -2168,7 +2180,7 @@ public void expungeNics(final VirtualMachineProfile vm) { public Network createGuestNetwork(final long networkOfferingId, final String name, final String displayText, final String gateway, final String cidr, String vlanId, boolean bypassVlanOverlapCheck, String networkDomain, final Account owner, final Long domainId, final PhysicalNetwork pNtwk, final long zoneId, final ACLType aclType, Boolean subdomainAccess, final Long vpcId, final String ip6Gateway, final String ip6Cidr, - final Boolean isDisplayNetworkEnabled, final String isolatedPvlan, String externalId) throws ConcurrentOperationException, InsufficientCapacityException, ResourceAllocationException { + final Boolean isDisplayNetworkEnabled, final String isolatedPvlan, Network.PVlanType isolatedPvlanType, String externalId) throws ConcurrentOperationException, InsufficientCapacityException, ResourceAllocationException { final NetworkOfferingVO ntwkOff = _networkOfferingDao.findById(networkOfferingId); final DataCenterVO zone = _dcDao.findById(zoneId); @@ -2280,16 +2292,25 @@ public Network createGuestNetwork(final long networkOfferingId, final String nam if (vlanSpecified) { URI uri = BroadcastDomainType.fromString(vlanId); + // Aux: generate secondary URI for secondary VLAN ID (if provided) for performing checks + URI secondaryUri = isNotBlank(isolatedPvlan) ? BroadcastDomainType.fromString(isolatedPvlan) : null; //don't allow to specify vlan tag used by physical network for dynamic vlan allocation if (!(bypassVlanOverlapCheck && ntwkOff.getGuestType() == GuestType.Shared) && _dcDao.findVnet(zoneId, pNtwk.getId(), BroadcastDomainType.getValue(uri)).size() > 0) { throw new InvalidParameterValueException("The VLAN tag " + vlanId + " is already being used for dynamic vlan allocation for the guest network in zone " + zone.getName()); } + if (secondaryUri != null && !(bypassVlanOverlapCheck && ntwkOff.getGuestType() == GuestType.Shared) && + _dcDao.findVnet(zoneId, pNtwk.getId(), BroadcastDomainType.getValue(secondaryUri)).size() > 0) { + throw new InvalidParameterValueException("The VLAN tag " + isolatedPvlan + " is already being used for dynamic vlan allocation for the guest network in zone " + + zone.getName()); + } if (! UuidUtils.validateUUID(vlanId)){ // For Isolated and L2 networks, don't allow to create network with vlan that already exists in the zone - if (ntwkOff.getGuestType() == GuestType.Isolated || !hasGuestBypassVlanOverlapCheck(bypassVlanOverlapCheck, ntwkOff)) { + if (ntwkOff.getGuestType() == GuestType.Isolated || ntwkOff.getGuestType() == GuestType.L2 || !hasGuestBypassVlanOverlapCheck(bypassVlanOverlapCheck, ntwkOff)) { if (_networksDao.listByZoneAndUriAndGuestType(zoneId, uri.toString(), null).size() > 0) { throw new InvalidParameterValueException("Network with vlan " + vlanId + " already exists or overlaps with other network vlans in zone " + zoneId); + } else if (secondaryUri != null && _networksDao.listByZoneAndUriAndGuestType(zoneId, secondaryUri.toString(), null).size() > 0) { + throw new InvalidParameterValueException("Network with vlan " + isolatedPvlan + " already exists or overlaps with other network vlans in zone " + zoneId); } else { final List dcVnets = _datacenterVnetDao.findVnet(zoneId, BroadcastDomainType.getValue(uri)); //for the network that is created as part of private gateway, @@ -2436,8 +2457,15 @@ public Network doInTransaction(final TransactionStatus status) { if (vlanIdFinal.equalsIgnoreCase(Vlan.UNTAGGED)) { throw new InvalidParameterValueException("Cannot support pvlan with untagged primary vlan!"); } - userNetwork.setBroadcastUri(NetUtils.generateUriForPvlan(vlanIdFinal, isolatedPvlan)); + URI uri = NetUtils.generateUriForPvlan(vlanIdFinal, isolatedPvlan); + if (_networksDao.listByPhysicalNetworkPvlan(physicalNetworkId, uri.toString(), isolatedPvlanType).size() > 0) { + throw new InvalidParameterValueException("Network with primary vlan " + vlanIdFinal + + " and secondary vlan " + isolatedPvlan + " type " + isolatedPvlanType + + " already exists or overlaps with other network pvlans in zone " + zoneId); + } + userNetwork.setBroadcastUri(uri); userNetwork.setBroadcastDomainType(BroadcastDomainType.Pvlan); + userNetwork.setPvlanType(isolatedPvlanType); } } @@ -2936,7 +2964,8 @@ public boolean startNetwork(final long networkId, final DeployDestination dest, @Override public boolean restartNetwork(final Long networkId, final Account callerAccount, final User callerUser, final boolean cleanup) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException { - + boolean status = true; + boolean restartRequired = false; final NetworkVO network = _networksDao.findById(networkId); s_logger.debug("Restarting network " + networkId + "..."); @@ -2947,16 +2976,17 @@ public boolean restartNetwork(final Long networkId, final Account callerAccount, if (cleanup) { if (!rollingRestartRouters(network, offering, dest, context)) { - setRestartRequired(network, true); - return false; + status = false; + restartRequired = true; } - return true; + setRestartRequired(network, restartRequired); + return status; } s_logger.debug("Implementing the network " + network + " elements and resources as a part of network restart without cleanup"); try { implementNetworkElementsAndResources(dest, context, network, offering); - setRestartRequired(network, true); + setRestartRequired(network, false); return true; } catch (final Exception ex) { s_logger.warn("Failed to implement network " + network + " elements and resources as a part of network restart due to ", ex); @@ -3950,6 +3980,71 @@ public NicVO savePlaceholderNic(final Network network, final String ip4Address, return _nicDao.persist(nic); } + @DB + @Override + public Pair importNic(final String macAddress, int deviceId, final Network network, final Boolean isDefaultNic, final VirtualMachine vm, final Network.IpAddresses ipAddresses) + throws ConcurrentOperationException, InsufficientVirtualNetworkCapacityException, InsufficientAddressCapacityException { + s_logger.debug("Allocating nic for vm " + vm.getUuid() + " in network " + network + " during import"); + String guestIp = null; + if (ipAddresses != null && !Strings.isNullOrEmpty(ipAddresses.getIp4Address())) { + if (ipAddresses.getIp4Address().equals("auto")) { + ipAddresses.setIp4Address(null); + } + if (network.getGuestType() != GuestType.L2) { + guestIp = _ipAddrMgr.acquireGuestIpAddress(network, ipAddresses.getIp4Address()); + } else { + guestIp = null; + } + if (guestIp == null && network.getGuestType() != GuestType.L2 && !_networkModel.listNetworkOfferingServices(network.getNetworkOfferingId()).isEmpty()) { + throw new InsufficientVirtualNetworkCapacityException("Unable to acquire Guest IP address for network " + network, DataCenter.class, + network.getDataCenterId()); + } + } + final String finalGuestIp = guestIp; + final NicVO vo = Transaction.execute(new TransactionCallback() { + @Override + public NicVO doInTransaction(TransactionStatus status) { + NicVO vo = new NicVO(network.getGuruName(), vm.getId(), network.getId(), vm.getType()); + vo.setMacAddress(macAddress); + vo.setAddressFormat(Networks.AddressFormat.Ip4); + if (NetUtils.isValidIp4(finalGuestIp) && !Strings.isNullOrEmpty(network.getGateway())) { + vo.setIPv4Address(finalGuestIp); + vo.setIPv4Gateway(network.getGateway()); + if (!Strings.isNullOrEmpty(network.getCidr())) { + vo.setIPv4Netmask(NetUtils.cidr2Netmask(network.getCidr())); + } + } + vo.setBroadcastUri(network.getBroadcastUri()); + vo.setMode(network.getMode()); + vo.setState(Nic.State.Reserved); + vo.setReservationStrategy(ReservationStrategy.Start); + vo.setReservationId(UUID.randomUUID().toString()); + vo.setIsolationUri(network.getBroadcastUri()); + vo.setDeviceId(deviceId); + vo.setDefaultNic(isDefaultNic); + vo = _nicDao.persist(vo); + + int count = 1; + if (vo.getVmType() == VirtualMachine.Type.User) { + s_logger.debug("Changing active number of nics for network id=" + network.getUuid() + " on " + count); + _networksDao.changeActiveNicsBy(network.getId(), count); + } + if (vo.getVmType() == VirtualMachine.Type.User + || vo.getVmType() == VirtualMachine.Type.DomainRouter && _networksDao.findById(network.getId()).getTrafficType() == TrafficType.Guest) { + _networksDao.setCheckForGc(network.getId()); + } + + return vo; + } + }); + + final Integer networkRate = _networkModel.getNetworkRate(network.getId(), vm.getId()); + final NicProfile vmNic = new NicProfile(vo, network, vo.getBroadcastUri(), vo.getIsolationUri(), networkRate, _networkModel.isSecurityGroupSupportedInNetwork(network), + _networkModel.getNetworkTag(vm.getHypervisorType(), network)); + + return new Pair(vmNic, Integer.valueOf(deviceId)); + } + @Override public String getConfigComponentName() { return NetworkOrchestrationService.class.getSimpleName(); diff --git a/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java b/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java index 6e71864c4473..9e2168e0bfd0 100644 --- a/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java +++ b/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java @@ -30,7 +30,6 @@ import javax.inject.Inject; import javax.naming.ConfigurationException; -import com.cloud.storage.VolumeApiService; import org.apache.cloudstack.api.command.admin.vm.MigrateVMCmd; import org.apache.cloudstack.api.command.admin.volume.MigrateVolumeCmdByAdmin; import org.apache.cloudstack.api.command.user.volume.MigrateVolumeCmd; @@ -106,6 +105,7 @@ import com.cloud.storage.VMTemplateStorageResourceAssoc; import com.cloud.storage.Volume; import com.cloud.storage.Volume.Type; +import com.cloud.storage.VolumeApiService; import com.cloud.storage.VolumeVO; import com.cloud.storage.dao.SnapshotDao; import com.cloud.storage.dao.VolumeDao; @@ -645,7 +645,7 @@ public boolean validateVolumeSizeRange(long size) { if (size < 0 || (size > 0 && size < (1024 * 1024 * 1024))) { throw new InvalidParameterValueException("Please specify a size of at least 1 GB."); } else if (size > (MaxVolumeSize.value() * 1024 * 1024 * 1024)) { - throw new InvalidParameterValueException("volume size " + size + ", but the maximum size allowed is " + MaxVolumeSize + " GB."); + throw new InvalidParameterValueException("volume size " + size + ", but the maximum size allowed is " + MaxVolumeSize.value() + " GB."); } return true; @@ -1005,10 +1005,12 @@ public Volume migrateVolume(Volume volume, StoragePool destPool) throws StorageU } } + @Override @DB - protected Volume liveMigrateVolume(Volume volume, StoragePool destPool) { + public Volume liveMigrateVolume(Volume volume, StoragePool destPool) { VolumeInfo vol = volFactory.getVolume(volume.getId()); - AsyncCallFuture future = volService.migrateVolume(vol, (DataStore)destPool); + DataStore dataStoreTarget = dataStoreMgr.getDataStore(destPool.getId(), DataStoreRole.Primary); + AsyncCallFuture future = volService.migrateVolume(vol, dataStoreTarget); try { VolumeApiResult result = future.get(); if (result.isFailed()) { @@ -1576,6 +1578,8 @@ public void destroyVolume(Volume volume) { if (volume.getState() == Volume.State.Allocated) { _volsDao.remove(volume.getId()); stateTransitTo(volume, Volume.Event.DestroyRequested); + _resourceLimitMgr.decrementResourceCount(volume.getAccountId(), ResourceType.volume, volume.isDisplay()); + _resourceLimitMgr.decrementResourceCount(volume.getAccountId(), ResourceType.primary_storage, volume.isDisplay(), new Long(volume.getSize())); } else { volService.destroyVolume(volume.getId()); } @@ -1583,8 +1587,6 @@ public void destroyVolume(Volume volume) { // publish usage event for the volume UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_DELETE, volume.getAccountId(), volume.getDataCenterId(), volume.getId(), volume.getName(), Volume.class.getName(), volume.getUuid(), volume.isDisplayVolume()); - _resourceLimitMgr.decrementResourceCount(volume.getAccountId(), ResourceType.volume, volume.isDisplay()); - _resourceLimitMgr.decrementResourceCount(volume.getAccountId(), ResourceType.primary_storage, volume.isDisplay(), new Long(volume.getSize())); } catch (Exception e) { s_logger.debug("Failed to destroy volume" + volume.getId(), e); throw new CloudRuntimeException("Failed to destroy volume" + volume.getId(), e); @@ -1626,4 +1628,56 @@ public void updateVolumeDiskChain(long volumeId, String path, String chainInfo) _volsDao.update(volumeId, vol); } } + + @Override + public DiskProfile importVolume(Type type, String name, DiskOffering offering, Long size, Long minIops, Long maxIops, + VirtualMachine vm, VirtualMachineTemplate template, Account owner, + Long deviceId, Long poolId, String path, String chainInfo) { + if (size == null) { + size = offering.getDiskSize(); + } else { + size = (size * 1024 * 1024 * 1024); + } + + minIops = minIops != null ? minIops : offering.getMinIops(); + maxIops = maxIops != null ? maxIops : offering.getMaxIops(); + + VolumeVO vol = new VolumeVO(type, name, vm.getDataCenterId(), owner.getDomainId(), owner.getId(), offering.getId(), offering.getProvisioningType(), size, minIops, maxIops, null); + if (vm != null) { + vol.setInstanceId(vm.getId()); + } + + if (deviceId != null) { + vol.setDeviceId(deviceId); + } else if (type.equals(Type.ROOT)) { + vol.setDeviceId(0l); + } else { + vol.setDeviceId(1l); + } + + if (template != null) { + if (ImageFormat.ISO.equals(template.getFormat())) { + vol.setIsoId(template.getId()); + } else if (Storage.TemplateType.DATADISK.equals(template.getTemplateType())) { + vol.setTemplateId(template.getId()); + } + if (type == Type.ROOT) { + vol.setTemplateId(template.getId()); + } + } + + // display flag matters only for the User vms + if (VirtualMachine.Type.User.equals(vm.getType())) { + UserVmVO userVm = _userVmDao.findById(vm.getId()); + vol.setDisplayVolume(userVm.isDisplayVm()); + } + + vol.setFormat(getSupportedImageFormatForCluster(vm.getHypervisorType())); + vol.setPoolId(poolId); + vol.setPath(path); + vol.setChainInfo(chainInfo); + vol.setState(Volume.State.Ready); + vol = _volsDao.persist(vol); + return toDiskProfile(vol, offering); + } } diff --git a/engine/schema/pom.xml b/engine/schema/pom.xml index b80be5456243..9c097fba12e3 100644 --- a/engine/schema/pom.xml +++ b/engine/schema/pom.xml @@ -48,5 +48,9 @@ cloud-framework-db ${project.version} + + mysql + mysql-connector-java + diff --git a/engine/schema/src/main/java/com/cloud/network/dao/NetworkDao.java b/engine/schema/src/main/java/com/cloud/network/dao/NetworkDao.java index 5091ebd75df0..ead57e660e5e 100644 --- a/engine/schema/src/main/java/com/cloud/network/dao/NetworkDao.java +++ b/engine/schema/src/main/java/com/cloud/network/dao/NetworkDao.java @@ -120,4 +120,8 @@ public interface NetworkDao extends GenericDao, StateDao listNetworkVO(List idset); + + List listByAccountIdNetworkName(long accountId, String name); + + List listByPhysicalNetworkPvlan(long physicalNetworkId, String broadcastUri, Network.PVlanType pVlanType); } diff --git a/engine/schema/src/main/java/com/cloud/network/dao/NetworkDaoImpl.java b/engine/schema/src/main/java/com/cloud/network/dao/NetworkDaoImpl.java index 23936cbdeab1..3476908fb9eb 100644 --- a/engine/schema/src/main/java/com/cloud/network/dao/NetworkDaoImpl.java +++ b/engine/schema/src/main/java/com/cloud/network/dao/NetworkDaoImpl.java @@ -26,7 +26,9 @@ import javax.inject.Inject; import javax.persistence.TableGenerator; +import com.cloud.utils.exception.CloudRuntimeException; import org.apache.cloudstack.acl.ControlledEntity.ACLType; +import org.apache.cloudstack.api.ApiConstants; import org.springframework.stereotype.Component; import com.cloud.network.Network; @@ -92,6 +94,8 @@ public class NetworkDaoImpl extends GenericDaoBaseimplements Ne NetworkOfferingDao _ntwkOffDao; @Inject NetworkOpDao _ntwkOpDao; + @Inject + NetworkDetailsDao networkDetailsDao; TableGenerator _tgMacAddress; @@ -104,6 +108,7 @@ public NetworkDaoImpl() { @PostConstruct protected void init() { AllFieldsSearch = createSearchBuilder(); + AllFieldsSearch.and("name", AllFieldsSearch.entity().getName(), Op.EQ); AllFieldsSearch.and("trafficType", AllFieldsSearch.entity().getTrafficType(), Op.EQ); AllFieldsSearch.and("cidr", AllFieldsSearch.entity().getCidr(), Op.EQ); AllFieldsSearch.and("broadcastType", AllFieldsSearch.entity().getBroadcastDomainType(), Op.EQ); @@ -697,4 +702,81 @@ public List listNetworkVO(List idset) { sc_2.addAnd("removed", SearchCriteria.Op.EQ, null); return this.search(sc_2, searchFilter_2); } + + @Override + public List listByAccountIdNetworkName(final long accountId, final String name) { + final SearchCriteria sc = AllFieldsSearch.create(); + sc.setParameters("account", accountId); + sc.setParameters("name", name); + + return listBy(sc, null); + } + + /** + * True when a requested PVLAN pair overlaps with any existing PVLAN pair within the same physical network, i.e when: + * - The requested exact PVLAN pair exists + * - The requested secondary VLAN ID is secondary VLAN ID of an existing PVLAN pair + * - The requested secondary VLAN ID is primary VLAN ID of an existing PVLAN pair + */ + protected boolean isNetworkOverlappingRequestedPvlan(Integer existingPrimaryVlan, Integer existingSecondaryVlan, Network.PVlanType existingPvlanType, + Integer requestedPrimaryVlan, Integer requestedSecondaryVlan, Network.PVlanType requestedPvlanType) { + if (existingPrimaryVlan == null || existingSecondaryVlan == null || requestedPrimaryVlan == null || requestedSecondaryVlan == null) { + throw new CloudRuntimeException(String.format("Missing VLAN ID while checking PVLAN pair (%s, %s)" + + " against existing pair (%s, %s)", existingPrimaryVlan, existingSecondaryVlan, requestedPrimaryVlan, requestedSecondaryVlan)); + } + boolean exactMatch = existingPrimaryVlan.equals(requestedPrimaryVlan) && existingSecondaryVlan.equals(requestedSecondaryVlan); + boolean secondaryVlanUsed = requestedPvlanType != Network.PVlanType.Promiscuous && requestedSecondaryVlan.equals(existingPrimaryVlan) || requestedSecondaryVlan.equals(existingSecondaryVlan); + boolean isolatedMax = false; + boolean promiscuousMax = false; + if (requestedPvlanType == Network.PVlanType.Isolated && existingPrimaryVlan.equals(requestedPrimaryVlan) && existingPvlanType.equals(Network.PVlanType.Isolated)) { + isolatedMax = true; + } else if (requestedPvlanType == Network.PVlanType.Promiscuous && existingPrimaryVlan.equals(requestedPrimaryVlan) && existingPvlanType == Network.PVlanType.Promiscuous) { + promiscuousMax = true; + } + return exactMatch || secondaryVlanUsed || isolatedMax || promiscuousMax; + } + + protected Network.PVlanType getNetworkPvlanType(long networkId, List existingPvlan) { + Network.PVlanType existingPvlanType = null; + NetworkDetailVO pvlanTypeDetail = networkDetailsDao.findDetail(networkId, ApiConstants.ISOLATED_PVLAN_TYPE); + if (pvlanTypeDetail != null) { + existingPvlanType = Network.PVlanType.valueOf(pvlanTypeDetail.getValue()); + } else { + existingPvlanType = existingPvlan.get(0).equals(existingPvlan.get(1)) ? Network.PVlanType.Promiscuous : Network.PVlanType.Isolated; + } + return existingPvlanType; + } + + @Override + public List listByPhysicalNetworkPvlan(long physicalNetworkId, String broadcastUri, Network.PVlanType pVlanType) { + final URI searchUri = BroadcastDomainType.fromString(broadcastUri); + if (!searchUri.getScheme().equalsIgnoreCase("pvlan")) { + throw new CloudRuntimeException("PVLAN requested but URI is not in the expected format: " + searchUri.toString()); + } + final String searchRange = BroadcastDomainType.getValue(searchUri); + final List searchVlans = UriUtils.expandPvlanUri(searchRange); + final List overlappingNetworks = new ArrayList<>(); + + final SearchCriteria sc = PhysicalNetworkSearch.create(); + sc.setParameters("physicalNetworkId", physicalNetworkId); + + for (final NetworkVO network : listBy(sc)) { + if (network.getBroadcastUri() == null || !network.getBroadcastUri().getScheme().equalsIgnoreCase("pvlan")) { + continue; + } + final String networkVlanRange = BroadcastDomainType.getValue(network.getBroadcastUri()); + if (networkVlanRange == null || networkVlanRange.isEmpty()) { + continue; + } + List existingPvlan = UriUtils.expandPvlanUri(networkVlanRange); + Network.PVlanType existingPvlanType = getNetworkPvlanType(network.getId(), existingPvlan); + if (isNetworkOverlappingRequestedPvlan(existingPvlan.get(0), existingPvlan.get(1), existingPvlanType, + searchVlans.get(0), searchVlans.get(1), pVlanType)) { + overlappingNetworks.add(network); + break; + } + } + + return overlappingNetworks; + } } diff --git a/engine/schema/src/main/java/com/cloud/network/dao/NetworkVO.java b/engine/schema/src/main/java/com/cloud/network/dao/NetworkVO.java index 0c0bd4de6a12..6d591675f827 100644 --- a/engine/schema/src/main/java/com/cloud/network/dao/NetworkVO.java +++ b/engine/schema/src/main/java/com/cloud/network/dao/NetworkVO.java @@ -181,6 +181,9 @@ public class NetworkVO implements Network { @Transient boolean rollingRestart = false; + @Transient + PVlanType pVlanType; + public NetworkVO() { uuid = UUID.randomUUID().toString(); } @@ -661,4 +664,12 @@ public boolean isRollingRestart() { public void setRollingRestart(boolean rollingRestart) { this.rollingRestart = rollingRestart; } + + public PVlanType getPvlanType() { + return pVlanType; + } + + public void setPvlanType(PVlanType pvlanType) { + this.pVlanType = pvlanType; + } } diff --git a/engine/schema/src/main/java/com/cloud/network/dao/RouterHealthCheckResultDao.java b/engine/schema/src/main/java/com/cloud/network/dao/RouterHealthCheckResultDao.java new file mode 100644 index 000000000000..66dcf68f81fd --- /dev/null +++ b/engine/schema/src/main/java/com/cloud/network/dao/RouterHealthCheckResultDao.java @@ -0,0 +1,49 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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. + +package com.cloud.network.dao; + +import java.util.List; + +import com.cloud.utils.db.GenericDao; + +public interface RouterHealthCheckResultDao extends GenericDao { + /** + * @param routerId + * @return Returns all the health checks in the database for the given router id + */ + List getHealthCheckResults(long routerId); + + boolean expungeHealthChecks(long routerId); + + /** + * @param routerId + * @return true if there are checks that have been marked failed in the database + */ + boolean hasFailingChecks(long routerId); + + /** + * For a router, we have only one (check name, check type) possible as we keep the most + * recent check result. This method finds that last check result. + * + * @param routerId + * @param checkName + * @param checkType + * @return returns the check result for the routerId, check type and the check name. + */ + RouterHealthCheckResultVO getRouterHealthCheckResult(long routerId, String checkName, String checkType); +} diff --git a/engine/schema/src/main/java/com/cloud/network/dao/RouterHealthCheckResultDaoImpl.java b/engine/schema/src/main/java/com/cloud/network/dao/RouterHealthCheckResultDaoImpl.java new file mode 100644 index 000000000000..991365b5f540 --- /dev/null +++ b/engine/schema/src/main/java/com/cloud/network/dao/RouterHealthCheckResultDaoImpl.java @@ -0,0 +1,84 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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. + +package com.cloud.network.dao; + +import java.util.List; + +import org.apache.log4j.Logger; +import org.springframework.stereotype.Component; + +import com.cloud.utils.db.GenericDaoBase; +import com.cloud.utils.db.SearchBuilder; +import com.cloud.utils.db.SearchCriteria; + +@Component +public class RouterHealthCheckResultDaoImpl extends GenericDaoBase implements RouterHealthCheckResultDao { + private final static Logger s_logger = Logger.getLogger(RouterHealthCheckResultDaoImpl.class); + + private SearchBuilder RouterChecksSearchBuilder; + private SearchBuilder IsRouterFailingSearchBuilder; + + protected RouterHealthCheckResultDaoImpl() { + super(); + RouterChecksSearchBuilder = createSearchBuilder(); + RouterChecksSearchBuilder.and("routerId", RouterChecksSearchBuilder.entity().getRouterId(), SearchCriteria.Op.EQ); + RouterChecksSearchBuilder.and("checkName", RouterChecksSearchBuilder.entity().getCheckName(), SearchCriteria.Op.EQ); + RouterChecksSearchBuilder.and("checkType", RouterChecksSearchBuilder.entity().getCheckType(), SearchCriteria.Op.EQ); + RouterChecksSearchBuilder.done(); + + IsRouterFailingSearchBuilder = createSearchBuilder(); + IsRouterFailingSearchBuilder.and("routerId", IsRouterFailingSearchBuilder.entity().getRouterId(), SearchCriteria.Op.EQ); + IsRouterFailingSearchBuilder.and("checkResult", IsRouterFailingSearchBuilder.entity().getCheckResult(), SearchCriteria.Op.EQ); + IsRouterFailingSearchBuilder.done(); + } + + @Override + public List getHealthCheckResults(long routerId) { + SearchCriteria sc = RouterChecksSearchBuilder.create(); + sc.setParameters("routerId", routerId); + return listBy(sc); + } + + @Override + public boolean expungeHealthChecks(long routerId) { + SearchCriteria sc = RouterChecksSearchBuilder.create(); + sc.setParameters("routerId", routerId); + return expunge(sc) > 0; + } + + @Override + public RouterHealthCheckResultVO getRouterHealthCheckResult(long routerId, String checkName, String checkType) { + SearchCriteria sc = RouterChecksSearchBuilder.create(); + sc.setParameters("routerId", routerId); + sc.setParameters("checkName", checkName); + sc.setParameters("checkType", checkType); + List checks = listBy(sc); + if (checks.size() > 1) { + s_logger.error("Found multiple entries for router Id: " + routerId + ", check name: " + checkName); + } + return checks.isEmpty() ? null : checks.get(0); + } + + @Override + public boolean hasFailingChecks(long routerId) { + SearchCriteria sc = IsRouterFailingSearchBuilder.create(); + sc.setParameters("routerId", routerId); + sc.setParameters("checkResult", false); + return !listBy(sc).isEmpty(); + } +} diff --git a/engine/schema/src/main/java/com/cloud/network/dao/RouterHealthCheckResultVO.java b/engine/schema/src/main/java/com/cloud/network/dao/RouterHealthCheckResultVO.java new file mode 100644 index 000000000000..9803ccb6a4bd --- /dev/null +++ b/engine/schema/src/main/java/com/cloud/network/dao/RouterHealthCheckResultVO.java @@ -0,0 +1,129 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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. + +package com.cloud.network.dao; + +import java.util.Date; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; +import javax.persistence.Temporal; +import javax.persistence.TemporalType; + +import com.cloud.network.RouterHealthCheckResult; +import com.cloud.utils.StringUtils; + +@Entity +@Table(name = "router_health_check") +public class RouterHealthCheckResultVO implements RouterHealthCheckResult { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id", updatable = false, nullable = false) + private long id; + + @Column(name = "router_id", updatable = false, nullable = false) + private long routerId; + + @Column(name = "check_name", updatable = false, nullable = false) + private String checkName; + + @Column(name = "check_type", updatable = false, nullable = false) + private String checkType; + + @Column(name = "check_result") + private boolean checkResult; + + @Temporal(TemporalType.TIMESTAMP) + @Column(name = "last_update", updatable = true, nullable = true) + private Date lastUpdateTime; + + @Column(name = "check_details", updatable = true, nullable = true) + private byte[] checkDetails; + + protected RouterHealthCheckResultVO() { + } + + public RouterHealthCheckResultVO(long routerId, String checkName, String checkType) { + this.routerId = routerId; + this.checkName = checkName; + this.checkType = checkType; + } + + public long getId() { + return id; + } + + @Override + public long getRouterId() { + return routerId; + } + + @Override + public String getCheckName() { + return checkName; + } + + @Override + public String getCheckType() { + return checkType; + } + + @Override + public boolean getCheckResult() { + return checkResult; + } + + @Override + public Date getLastUpdateTime() { + return lastUpdateTime; + } + + @Override + public String getParsedCheckDetails() { + return checkDetails != null ? new String(checkDetails, StringUtils.getPreferredCharset()) : ""; + } + + public byte[] getCheckDetails() { + return checkDetails; + } + + public void setCheckResult(boolean checkResult) { + this.checkResult = checkResult; + } + + public void setLastUpdateTime(Date lastUpdateTime) { + this.lastUpdateTime = lastUpdateTime; + } + + public void setCheckDetails(byte[] checkDetails) { + this.checkDetails = checkDetails; + } + + @Override + public String toString() { + return super.toString() + + "- check type: " + checkType + + ",check name: " + checkName + + ", check result: " + checkResult + + ", check last update: " + lastUpdateTime + + ", details: " + getParsedCheckDetails(); + } +} diff --git a/engine/schema/src/main/java/com/cloud/network/security/SecurityGroupVO.java b/engine/schema/src/main/java/com/cloud/network/security/SecurityGroupVO.java index 4a4c83ae74a3..3b7ceb8eb64b 100644 --- a/engine/schema/src/main/java/com/cloud/network/security/SecurityGroupVO.java +++ b/engine/schema/src/main/java/com/cloud/network/security/SecurityGroupVO.java @@ -70,6 +70,10 @@ public String getName() { return name; } + public void setName(String name) { + this.name = name; + } + @Override public String getDescription() { return description; diff --git a/engine/schema/src/main/java/com/cloud/network/vpc/dao/VpcGatewayDao.java b/engine/schema/src/main/java/com/cloud/network/vpc/dao/VpcGatewayDao.java index e6a72c870b0e..4417dfad0a4d 100644 --- a/engine/schema/src/main/java/com/cloud/network/vpc/dao/VpcGatewayDao.java +++ b/engine/schema/src/main/java/com/cloud/network/vpc/dao/VpcGatewayDao.java @@ -32,4 +32,6 @@ public interface VpcGatewayDao extends GenericDao { List listByAclIdAndType(long aclId, VpcGateway.Type type); List listByVpcId(long vpcId); + + VpcGatewayVO getVpcGatewayByNetworkId(long networkId); } diff --git a/engine/schema/src/main/java/com/cloud/network/vpc/dao/VpcGatewayDaoImpl.java b/engine/schema/src/main/java/com/cloud/network/vpc/dao/VpcGatewayDaoImpl.java index 39d33192a093..7d1fa897d2a8 100644 --- a/engine/schema/src/main/java/com/cloud/network/vpc/dao/VpcGatewayDaoImpl.java +++ b/engine/schema/src/main/java/com/cloud/network/vpc/dao/VpcGatewayDaoImpl.java @@ -89,4 +89,11 @@ public List listByVpcId(long vpcId) { sc.setParameters("vpcId", vpcId); return listBy(sc); } + + @Override + public VpcGatewayVO getVpcGatewayByNetworkId(long networkId) { + SearchCriteria sc = AllFieldsSearch.create(); + sc.setParameters("networkid", networkId); + return findOneBy(sc); + } } diff --git a/engine/schema/src/main/java/com/cloud/service/dao/ServiceOfferingDao.java b/engine/schema/src/main/java/com/cloud/service/dao/ServiceOfferingDao.java index 74728f826ce5..8ac44b99c1d5 100644 --- a/engine/schema/src/main/java/com/cloud/service/dao/ServiceOfferingDao.java +++ b/engine/schema/src/main/java/com/cloud/service/dao/ServiceOfferingDao.java @@ -48,7 +48,7 @@ List createSystemServiceOfferings(String name, String uniqueN boolean isDynamic(long serviceOfferingId); - ServiceOfferingVO getcomputeOffering(ServiceOfferingVO serviceOffering, Map customParameters); + ServiceOfferingVO getComputeOffering(ServiceOfferingVO serviceOffering, Map customParameters); ServiceOfferingVO findDefaultSystemOffering(String offeringName, Boolean useLocalStorage); } diff --git a/engine/schema/src/main/java/com/cloud/service/dao/ServiceOfferingDaoImpl.java b/engine/schema/src/main/java/com/cloud/service/dao/ServiceOfferingDaoImpl.java index 96b0c350a741..76e867b8f538 100644 --- a/engine/schema/src/main/java/com/cloud/service/dao/ServiceOfferingDaoImpl.java +++ b/engine/schema/src/main/java/com/cloud/service/dao/ServiceOfferingDaoImpl.java @@ -161,7 +161,7 @@ public ServiceOfferingVO findById(Long vmId, long serviceOfferingId) { throw new CloudRuntimeException("missing argument vmId"); } Map dynamicOffering = userVmDetailsDao.listDetailsKeyPairs(vmId); - return getcomputeOffering(offering, dynamicOffering); + return getComputeOffering(offering, dynamicOffering); } return offering; } @@ -175,7 +175,7 @@ public ServiceOfferingVO findByIdIncludingRemoved(Long vmId, long serviceOfferin throw new CloudRuntimeException("missing argument vmId"); } Map dynamicOffering = userVmDetailsDao.listDetailsKeyPairs(vmId); - return getcomputeOffering(offering, dynamicOffering); + return getComputeOffering(offering, dynamicOffering); } return offering; } @@ -187,7 +187,7 @@ public boolean isDynamic(long serviceOfferingId) { } @Override - public ServiceOfferingVO getcomputeOffering(ServiceOfferingVO serviceOffering, Map customParameters) { + public ServiceOfferingVO getComputeOffering(ServiceOfferingVO serviceOffering, Map customParameters) { ServiceOfferingVO dummyoffering = new ServiceOfferingVO(serviceOffering); dummyoffering.setDynamicFlag(true); if (customParameters.containsKey(UsageEventVO.DynamicParameters.cpuNumber.name())) { diff --git a/engine/schema/src/main/java/com/cloud/storage/VMTemplateVO.java b/engine/schema/src/main/java/com/cloud/storage/VMTemplateVO.java index 30440d3dc745..af04099f9a2a 100644 --- a/engine/schema/src/main/java/com/cloud/storage/VMTemplateVO.java +++ b/engine/schema/src/main/java/com/cloud/storage/VMTemplateVO.java @@ -230,6 +230,13 @@ public static VMTemplateVO createPreHostIso(Long id, String uniqueName, String n return template; } + public static VMTemplateVO createSystemIso(Long id, String uniqueName, String name, boolean isPublic, + String url, boolean requiresHvm, int bits, long accountId, String cksum, + String displayText, boolean enablePassword, long guestOSId) { + return new VMTemplateVO(id, uniqueName, name, ImageFormat.ISO, isPublic, false, TemplateType.SYSTEM, url, null, requiresHvm, bits, accountId, cksum, displayText, enablePassword, + guestOSId, false, null); + } + public VMTemplateVO(Long id, String uniqueName, String name, ImageFormat format, boolean isPublic, boolean featured, TemplateType type, String url, Date created, boolean requiresHvm, int bits, long accountId, String cksum, String displayText, boolean enablePassword, long guestOSId, boolean bootable, HypervisorType hyperType) { diff --git a/engine/schema/src/main/java/com/cloud/storage/dao/GuestOSHypervisorDao.java b/engine/schema/src/main/java/com/cloud/storage/dao/GuestOSHypervisorDao.java index a7775165265f..cd00703ce13e 100644 --- a/engine/schema/src/main/java/com/cloud/storage/dao/GuestOSHypervisorDao.java +++ b/engine/schema/src/main/java/com/cloud/storage/dao/GuestOSHypervisorDao.java @@ -29,4 +29,6 @@ public interface GuestOSHypervisorDao extends GenericDao guestOsSearch; protected final SearchBuilder mappingSearch; protected final SearchBuilder userDefinedMappingSearch; + protected final SearchBuilder guestOsNameSearch; protected GuestOSHypervisorDaoImpl() { guestOsSearch = createSearchBuilder(); @@ -51,6 +54,12 @@ protected GuestOSHypervisorDaoImpl() { userDefinedMappingSearch.and("hypervisor_version", userDefinedMappingSearch.entity().getHypervisorVersion(), SearchCriteria.Op.EQ); userDefinedMappingSearch.and("is_user_defined", userDefinedMappingSearch.entity().getIsUserDefined(), SearchCriteria.Op.EQ); userDefinedMappingSearch.done(); + + guestOsNameSearch = createSearchBuilder(); + guestOsNameSearch.and("guest_os_name", guestOsNameSearch.entity().getGuestOsName(), SearchCriteria.Op.EQ); + guestOsNameSearch.and("hypervisor_type", guestOsNameSearch.entity().getHypervisorType(), SearchCriteria.Op.EQ); + guestOsNameSearch.and("hypervisor_version", guestOsNameSearch.entity().getHypervisorVersion(), SearchCriteria.Op.EQ); + guestOsNameSearch.done(); } @Override @@ -97,4 +106,19 @@ public boolean removeGuestOsMapping(Long id) { return super.remove(id); } + @Override + public GuestOSHypervisorVO findByOsNameAndHypervisor(String guestOsName, String hypervisorType, String hypervisorVersion) { + SearchCriteria sc = guestOsNameSearch.create(); + String version = "default"; + if (!(hypervisorVersion == null || hypervisorVersion.isEmpty())) { + version = hypervisorVersion; + } + sc.setParameters("guest_os_name", guestOsName); + sc.setParameters("hypervisor_type", hypervisorType); + sc.setParameters("hypervisor_version", version); + final Filter filter = new Filter(GuestOSHypervisorVO.class, "guestOsId", true, null, null); + List results = listIncludingRemovedBy(sc, filter); + return CollectionUtils.isNotEmpty(results) ? results.get(0) : null; + } + } diff --git a/engine/schema/src/main/java/com/cloud/storage/dao/VolumeDao.java b/engine/schema/src/main/java/com/cloud/storage/dao/VolumeDao.java index 14f48ea06a86..2741307c0546 100644 --- a/engine/schema/src/main/java/com/cloud/storage/dao/VolumeDao.java +++ b/engine/schema/src/main/java/com/cloud/storage/dao/VolumeDao.java @@ -96,6 +96,8 @@ public interface VolumeDao extends GenericDao, StateDao listZoneWidePoolIdsByVolumeCount(long dcId, long accountId); + List findIncludingRemovedByZone(long zoneId); + /** * Gets the Total Primary Storage space allocated for an account * diff --git a/engine/schema/src/main/java/com/cloud/storage/dao/VolumeDaoImpl.java b/engine/schema/src/main/java/com/cloud/storage/dao/VolumeDaoImpl.java index e8ed3343831b..974d8e6f9cef 100644 --- a/engine/schema/src/main/java/com/cloud/storage/dao/VolumeDaoImpl.java +++ b/engine/schema/src/main/java/com/cloud/storage/dao/VolumeDaoImpl.java @@ -598,6 +598,13 @@ public List listZoneWidePoolIdsByVolumeCount(long dcId, long accountId) { } } + @Override + public List findIncludingRemovedByZone(long zoneId) { + SearchCriteria sc = AllFieldsSearch.create(); + sc.setParameters("dcId", zoneId); + return searchIncludingRemoved(sc, null, null, false); + } + @Override @DB() public Pair getNonDestroyedCountAndTotalByPool(long poolId) { diff --git a/engine/schema/src/main/java/com/cloud/upgrade/DatabaseUpgradeChecker.java b/engine/schema/src/main/java/com/cloud/upgrade/DatabaseUpgradeChecker.java index a7a18da9db1b..ee2b0cd803eb 100644 --- a/engine/schema/src/main/java/com/cloud/upgrade/DatabaseUpgradeChecker.java +++ b/engine/schema/src/main/java/com/cloud/upgrade/DatabaseUpgradeChecker.java @@ -189,6 +189,7 @@ public DatabaseUpgradeChecker() { .next("4.11.3.0", new Upgrade41120to41200()) .next("4.12.0.0", new Upgrade41200to41300()) .next("4.13.0.0", new Upgrade41300to41400()) + .next("4.13.1.0", new Upgrade41300to41400()) .build(); } diff --git a/engine/schema/src/main/java/com/cloud/upgrade/dao/Upgrade41200to41300.java b/engine/schema/src/main/java/com/cloud/upgrade/dao/Upgrade41200to41300.java index 2f6faf23c62d..2de8dc983587 100644 --- a/engine/schema/src/main/java/com/cloud/upgrade/dao/Upgrade41200to41300.java +++ b/engine/schema/src/main/java/com/cloud/upgrade/dao/Upgrade41200to41300.java @@ -19,23 +19,11 @@ import java.io.InputStream; import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import org.apache.log4j.Logger; - -import com.cloud.hypervisor.Hypervisor; import com.cloud.utils.exception.CloudRuntimeException; public class Upgrade41200to41300 implements DbUpgrade { - final static Logger LOG = Logger.getLogger(Upgrade41200to41300.class); - @Override public String[] getUpgradableVersionRange() { return new String[] {"4.12.0.0", "4.13.0.0"}; @@ -64,175 +52,6 @@ public InputStream[] getPrepareScripts() { @Override public void performDataMigration(Connection conn) { - updateSystemVmTemplates(conn); - } - - @SuppressWarnings("serial") - private void updateSystemVmTemplates(final Connection conn) { - LOG.debug("Updating System Vm template IDs"); - final Set hypervisorsListInUse = new HashSet(); - try (PreparedStatement pstmt = conn.prepareStatement("select distinct(hypervisor_type) from `cloud`.`cluster` where removed is null"); ResultSet rs = pstmt.executeQuery()) { - while (rs.next()) { - switch (Hypervisor.HypervisorType.getType(rs.getString(1))) { - case XenServer: - hypervisorsListInUse.add(Hypervisor.HypervisorType.XenServer); - break; - case KVM: - hypervisorsListInUse.add(Hypervisor.HypervisorType.KVM); - break; - case VMware: - hypervisorsListInUse.add(Hypervisor.HypervisorType.VMware); - break; - case Hyperv: - hypervisorsListInUse.add(Hypervisor.HypervisorType.Hyperv); - break; - case LXC: - hypervisorsListInUse.add(Hypervisor.HypervisorType.LXC); - break; - case Ovm3: - hypervisorsListInUse.add(Hypervisor.HypervisorType.Ovm3); - break; - default: - break; - } - } - } catch (final SQLException e) { - LOG.error("updateSystemVmTemplates: Exception caught while getting hypervisor types from clusters: " + e.getMessage()); - throw new CloudRuntimeException("updateSystemVmTemplates:Exception while getting hypervisor types from clusters", e); - } - - final Map NewTemplateNameList = new HashMap() { - { - put(Hypervisor.HypervisorType.KVM, "systemvm-kvm-4.11.3"); - put(Hypervisor.HypervisorType.VMware, "systemvm-vmware-4.11.3"); - put(Hypervisor.HypervisorType.XenServer, "systemvm-xenserver-4.11.3"); - put(Hypervisor.HypervisorType.Hyperv, "systemvm-hyperv-4.11.3"); - put(Hypervisor.HypervisorType.LXC, "systemvm-lxc-4.11.3"); - put(Hypervisor.HypervisorType.Ovm3, "systemvm-ovm3-4.11.3"); - } - }; - - final Map routerTemplateConfigurationNames = new HashMap() { - { - put(Hypervisor.HypervisorType.KVM, "router.template.kvm"); - put(Hypervisor.HypervisorType.VMware, "router.template.vmware"); - put(Hypervisor.HypervisorType.XenServer, "router.template.xenserver"); - put(Hypervisor.HypervisorType.Hyperv, "router.template.hyperv"); - put(Hypervisor.HypervisorType.LXC, "router.template.lxc"); - put(Hypervisor.HypervisorType.Ovm3, "router.template.ovm3"); - } - }; - - final Map newTemplateUrl = new HashMap() { - { - put(Hypervisor.HypervisorType.KVM, "https://download.cloudstack.org/systemvm/4.11/systemvmtemplate-4.11.3-kvm.qcow2.bz2"); - put(Hypervisor.HypervisorType.VMware, "https://download.cloudstack.org/systemvm/4.11/systemvmtemplate-4.11.3-vmware.ova"); - put(Hypervisor.HypervisorType.XenServer, "https://download.cloudstack.org/systemvm/4.11/systemvmtemplate-4.11.3-xen.vhd.bz2"); - put(Hypervisor.HypervisorType.Hyperv, "https://download.cloudstack.org/systemvm/4.11/systemvmtemplate-4.11.3-hyperv.vhd.zip"); - put(Hypervisor.HypervisorType.LXC, "https://download.cloudstack.org/systemvm/4.11/systemvmtemplate-4.11.3-kvm.qcow2.bz2"); - put(Hypervisor.HypervisorType.Ovm3, "https://download.cloudstack.org/systemvm/4.11/systemvmtemplate-4.11.3-ovm.raw.bz2"); - } - }; - - final Map newTemplateChecksum = new HashMap() { - { - put(Hypervisor.HypervisorType.KVM, "15ec268d0939a8fa0be1bc79f397a167"); - put(Hypervisor.HypervisorType.XenServer, "ae96f35fb746524edc4ebc9856719d71"); - put(Hypervisor.HypervisorType.VMware, "f50c82139430afce7e4e46d3a585abbd"); - put(Hypervisor.HypervisorType.Hyperv, "abf411f6cdd9139716b5d8172ab903a6"); - put(Hypervisor.HypervisorType.LXC, "15ec268d0939a8fa0be1bc79f397a167"); - put(Hypervisor.HypervisorType.Ovm3, "c71f143a477f4c7a0d5e8c82ccb00220"); - } - }; - - for (final Map.Entry hypervisorAndTemplateName : NewTemplateNameList.entrySet()) { - LOG.debug("Updating " + hypervisorAndTemplateName.getKey() + " System Vms"); - try (PreparedStatement pstmt = conn.prepareStatement("select id from `cloud`.`vm_template` where name = ? and removed is null order by id desc limit 1")) { - // Get 4.11 systemvm template id for corresponding hypervisor - long templateId = -1; - pstmt.setString(1, hypervisorAndTemplateName.getValue()); - try (ResultSet rs = pstmt.executeQuery()) { - if (rs.next()) { - templateId = rs.getLong(1); - } - } catch (final SQLException e) { - LOG.error("updateSystemVmTemplates: Exception caught while getting ids of templates: " + e.getMessage()); - throw new CloudRuntimeException("updateSystemVmTemplates: Exception caught while getting ids of templates", e); - } - - // change template type to SYSTEM - if (templateId != -1) { - try (PreparedStatement templ_type_pstmt = conn.prepareStatement("update `cloud`.`vm_template` set type='SYSTEM' where id = ?");) { - templ_type_pstmt.setLong(1, templateId); - templ_type_pstmt.executeUpdate(); - } catch (final SQLException e) { - LOG.error("updateSystemVmTemplates:Exception while updating template with id " + templateId + " to be marked as 'system': " + e.getMessage()); - throw new CloudRuntimeException("updateSystemVmTemplates:Exception while updating template with id " + templateId + " to be marked as 'system'", e); - } - // update template ID of system Vms - try (PreparedStatement update_templ_id_pstmt = conn - .prepareStatement("update `cloud`.`vm_instance` set vm_template_id = ? where type <> 'User' and hypervisor_type = ? and removed is NULL");) { - update_templ_id_pstmt.setLong(1, templateId); - update_templ_id_pstmt.setString(2, hypervisorAndTemplateName.getKey().toString()); - update_templ_id_pstmt.executeUpdate(); - } catch (final Exception e) { - LOG.error("updateSystemVmTemplates:Exception while setting template for " + hypervisorAndTemplateName.getKey().toString() + " to " + templateId - + ": " + e.getMessage()); - throw new CloudRuntimeException("updateSystemVmTemplates:Exception while setting template for " + hypervisorAndTemplateName.getKey().toString() + " to " - + templateId, e); - } - - // Change value of global configuration parameter - // router.template.* for the corresponding hypervisor - try (PreparedStatement update_pstmt = conn.prepareStatement("UPDATE `cloud`.`configuration` SET value = ? WHERE name = ?");) { - update_pstmt.setString(1, hypervisorAndTemplateName.getValue()); - update_pstmt.setString(2, routerTemplateConfigurationNames.get(hypervisorAndTemplateName.getKey())); - update_pstmt.executeUpdate(); - } catch (final SQLException e) { - LOG.error("updateSystemVmTemplates:Exception while setting " + routerTemplateConfigurationNames.get(hypervisorAndTemplateName.getKey()) + " to " - + hypervisorAndTemplateName.getValue() + ": " + e.getMessage()); - throw new CloudRuntimeException("updateSystemVmTemplates:Exception while setting " - + routerTemplateConfigurationNames.get(hypervisorAndTemplateName.getKey()) + " to " + hypervisorAndTemplateName.getValue(), e); - } - - // Change value of global configuration parameter - // minreq.sysvmtemplate.version for the ACS version - try (PreparedStatement update_pstmt = conn.prepareStatement("UPDATE `cloud`.`configuration` SET value = ? WHERE name = ?");) { - update_pstmt.setString(1, "4.11.3"); - update_pstmt.setString(2, "minreq.sysvmtemplate.version"); - update_pstmt.executeUpdate(); - } catch (final SQLException e) { - LOG.error("updateSystemVmTemplates:Exception while setting 'minreq.sysvmtemplate.version' to 4.11.3: " + e.getMessage()); - throw new CloudRuntimeException("updateSystemVmTemplates:Exception while setting 'minreq.sysvmtemplate.version' to 4.11.3", e); - } - } else { - if (hypervisorsListInUse.contains(hypervisorAndTemplateName.getKey())) { - throw new CloudRuntimeException(getUpgradedVersion() + hypervisorAndTemplateName.getKey() + " SystemVm template not found. Cannot upgrade system Vms"); - } else { - LOG.warn(getUpgradedVersion() + hypervisorAndTemplateName.getKey() + " SystemVm template not found. " + hypervisorAndTemplateName.getKey() - + " hypervisor is not used, so not failing upgrade"); - // Update the latest template URLs for corresponding - // hypervisor - try (PreparedStatement update_templ_url_pstmt = conn - .prepareStatement("UPDATE `cloud`.`vm_template` SET url = ? , checksum = ? WHERE hypervisor_type = ? AND type = 'SYSTEM' AND removed is null order by id desc limit 1");) { - update_templ_url_pstmt.setString(1, newTemplateUrl.get(hypervisorAndTemplateName.getKey())); - update_templ_url_pstmt.setString(2, newTemplateChecksum.get(hypervisorAndTemplateName.getKey())); - update_templ_url_pstmt.setString(3, hypervisorAndTemplateName.getKey().toString()); - update_templ_url_pstmt.executeUpdate(); - } catch (final SQLException e) { - LOG.error("updateSystemVmTemplates:Exception while updating 'url' and 'checksum' for hypervisor type " - + hypervisorAndTemplateName.getKey().toString() + ": " + e.getMessage()); - throw new CloudRuntimeException("updateSystemVmTemplates:Exception while updating 'url' and 'checksum' for hypervisor type " - + hypervisorAndTemplateName.getKey().toString(), e); - } - } - } - } catch (final SQLException e) { - LOG.error("updateSystemVmTemplates:Exception while getting ids of templates: " + e.getMessage()); - throw new CloudRuntimeException("updateSystemVmTemplates:Exception while getting ids of templates", e); - } - } - LOG.debug("Updating System Vm Template IDs Complete"); } @Override diff --git a/engine/schema/src/main/java/com/cloud/upgrade/dao/Upgrade41300to41400.java b/engine/schema/src/main/java/com/cloud/upgrade/dao/Upgrade41300to41400.java index 8cd36d2ac3bc..fc0ce74751b2 100644 --- a/engine/schema/src/main/java/com/cloud/upgrade/dao/Upgrade41300to41400.java +++ b/engine/schema/src/main/java/com/cloud/upgrade/dao/Upgrade41300to41400.java @@ -19,9 +19,17 @@ import java.io.InputStream; import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; import org.apache.log4j.Logger; +import com.cloud.hypervisor.Hypervisor; import com.cloud.utils.exception.CloudRuntimeException; public class Upgrade41300to41400 implements DbUpgrade { @@ -56,6 +64,175 @@ public InputStream[] getPrepareScripts() { @Override public void performDataMigration(Connection conn) { + updateSystemVmTemplates(conn); + } + + @SuppressWarnings("serial") + private void updateSystemVmTemplates(final Connection conn) { + LOG.debug("Updating System Vm template IDs"); + final Set hypervisorsListInUse = new HashSet(); + try (PreparedStatement pstmt = conn.prepareStatement("select distinct(hypervisor_type) from `cloud`.`cluster` where removed is null"); ResultSet rs = pstmt.executeQuery()) { + while (rs.next()) { + switch (Hypervisor.HypervisorType.getType(rs.getString(1))) { + case XenServer: + hypervisorsListInUse.add(Hypervisor.HypervisorType.XenServer); + break; + case KVM: + hypervisorsListInUse.add(Hypervisor.HypervisorType.KVM); + break; + case VMware: + hypervisorsListInUse.add(Hypervisor.HypervisorType.VMware); + break; + case Hyperv: + hypervisorsListInUse.add(Hypervisor.HypervisorType.Hyperv); + break; + case LXC: + hypervisorsListInUse.add(Hypervisor.HypervisorType.LXC); + break; + case Ovm3: + hypervisorsListInUse.add(Hypervisor.HypervisorType.Ovm3); + break; + default: + break; + } + } + } catch (final SQLException e) { + LOG.error("updateSystemVmTemplates: Exception caught while getting hypervisor types from clusters: " + e.getMessage()); + throw new CloudRuntimeException("updateSystemVmTemplates:Exception while getting hypervisor types from clusters", e); + } + + final Map NewTemplateNameList = new HashMap() { + { + put(Hypervisor.HypervisorType.KVM, "systemvm-kvm-4.14.0"); + put(Hypervisor.HypervisorType.VMware, "systemvm-vmware-4.14.0"); + put(Hypervisor.HypervisorType.XenServer, "systemvm-xenserver-4.14.0"); + put(Hypervisor.HypervisorType.Hyperv, "systemvm-hyperv-4.14.0"); + put(Hypervisor.HypervisorType.LXC, "systemvm-lxc-4.14.0"); + put(Hypervisor.HypervisorType.Ovm3, "systemvm-ovm3-4.14.0"); + } + }; + + final Map routerTemplateConfigurationNames = new HashMap() { + { + put(Hypervisor.HypervisorType.KVM, "router.template.kvm"); + put(Hypervisor.HypervisorType.VMware, "router.template.vmware"); + put(Hypervisor.HypervisorType.XenServer, "router.template.xenserver"); + put(Hypervisor.HypervisorType.Hyperv, "router.template.hyperv"); + put(Hypervisor.HypervisorType.LXC, "router.template.lxc"); + put(Hypervisor.HypervisorType.Ovm3, "router.template.ovm3"); + } + }; + + final Map newTemplateUrl = new HashMap() { + { + put(Hypervisor.HypervisorType.KVM, "https://download.cloudstack.org/systemvm/4.14/systemvmtemplate-4.14.0-kvm.qcow2.bz2"); + put(Hypervisor.HypervisorType.VMware, "https://download.cloudstack.org/systemvm/4.14/systemvmtemplate-4.14.0-vmware.ova"); + put(Hypervisor.HypervisorType.XenServer, "https://download.cloudstack.org/systemvm/4.14/systemvmtemplate-4.14.0-xen.vhd.bz2"); + put(Hypervisor.HypervisorType.Hyperv, "https://download.cloudstack.org/systemvm/4.14/systemvmtemplate-4.14.0-hyperv.vhd.zip"); + put(Hypervisor.HypervisorType.LXC, "https://download.cloudstack.org/systemvm/4.14/systemvmtemplate-4.14.0-kvm.qcow2.bz2"); + put(Hypervisor.HypervisorType.Ovm3, "https://download.cloudstack.org/systemvm/4.14/systemvmtemplate-4.14.0-ovm.raw.bz2"); + } + }; + + final Map newTemplateChecksum = new HashMap() { + { + put(Hypervisor.HypervisorType.KVM, "d15ed159be32151b07e3211caf9cb802"); + put(Hypervisor.HypervisorType.XenServer, "fcaf1abc9aa62e7ed75f62b3092a01a2"); + put(Hypervisor.HypervisorType.VMware, "eb39f8b5a556dfc93c6be23ae45f34e1"); + put(Hypervisor.HypervisorType.Hyperv, "b4e91c14958e0fca9470695b0be05f99"); + put(Hypervisor.HypervisorType.LXC, "d15ed159be32151b07e3211caf9cb802"); + put(Hypervisor.HypervisorType.Ovm3, "1f97f4beb30af8cda886f1e977514704"); + } + }; + + for (final Map.Entry hypervisorAndTemplateName : NewTemplateNameList.entrySet()) { + LOG.debug("Updating " + hypervisorAndTemplateName.getKey() + " System Vms"); + try (PreparedStatement pstmt = conn.prepareStatement("select id from `cloud`.`vm_template` where name = ? and removed is null order by id desc limit 1")) { + // Get 4.11 systemvm template id for corresponding hypervisor + long templateId = -1; + pstmt.setString(1, hypervisorAndTemplateName.getValue()); + try (ResultSet rs = pstmt.executeQuery()) { + if (rs.next()) { + templateId = rs.getLong(1); + } + } catch (final SQLException e) { + LOG.error("updateSystemVmTemplates: Exception caught while getting ids of templates: " + e.getMessage()); + throw new CloudRuntimeException("updateSystemVmTemplates: Exception caught while getting ids of templates", e); + } + + // change template type to SYSTEM + if (templateId != -1) { + try (PreparedStatement templ_type_pstmt = conn.prepareStatement("update `cloud`.`vm_template` set type='SYSTEM' where id = ?");) { + templ_type_pstmt.setLong(1, templateId); + templ_type_pstmt.executeUpdate(); + } catch (final SQLException e) { + LOG.error("updateSystemVmTemplates:Exception while updating template with id " + templateId + " to be marked as 'system': " + e.getMessage()); + throw new CloudRuntimeException("updateSystemVmTemplates:Exception while updating template with id " + templateId + " to be marked as 'system'", e); + } + // update template ID of system Vms + try (PreparedStatement update_templ_id_pstmt = conn + .prepareStatement("update `cloud`.`vm_instance` set vm_template_id = ? where type <> 'User' and hypervisor_type = ? and removed is NULL");) { + update_templ_id_pstmt.setLong(1, templateId); + update_templ_id_pstmt.setString(2, hypervisorAndTemplateName.getKey().toString()); + update_templ_id_pstmt.executeUpdate(); + } catch (final Exception e) { + LOG.error("updateSystemVmTemplates:Exception while setting template for " + hypervisorAndTemplateName.getKey().toString() + " to " + templateId + + ": " + e.getMessage()); + throw new CloudRuntimeException("updateSystemVmTemplates:Exception while setting template for " + hypervisorAndTemplateName.getKey().toString() + " to " + + templateId, e); + } + + // Change value of global configuration parameter + // router.template.* for the corresponding hypervisor + try (PreparedStatement update_pstmt = conn.prepareStatement("UPDATE `cloud`.`configuration` SET value = ? WHERE name = ?");) { + update_pstmt.setString(1, hypervisorAndTemplateName.getValue()); + update_pstmt.setString(2, routerTemplateConfigurationNames.get(hypervisorAndTemplateName.getKey())); + update_pstmt.executeUpdate(); + } catch (final SQLException e) { + LOG.error("updateSystemVmTemplates:Exception while setting " + routerTemplateConfigurationNames.get(hypervisorAndTemplateName.getKey()) + " to " + + hypervisorAndTemplateName.getValue() + ": " + e.getMessage()); + throw new CloudRuntimeException("updateSystemVmTemplates:Exception while setting " + + routerTemplateConfigurationNames.get(hypervisorAndTemplateName.getKey()) + " to " + hypervisorAndTemplateName.getValue(), e); + } + + // Change value of global configuration parameter + // minreq.sysvmtemplate.version for the ACS version + try (PreparedStatement update_pstmt = conn.prepareStatement("UPDATE `cloud`.`configuration` SET value = ? WHERE name = ?");) { + update_pstmt.setString(1, "4.14.0"); + update_pstmt.setString(2, "minreq.sysvmtemplate.version"); + update_pstmt.executeUpdate(); + } catch (final SQLException e) { + LOG.error("updateSystemVmTemplates:Exception while setting 'minreq.sysvmtemplate.version' to 4.14.0: " + e.getMessage()); + throw new CloudRuntimeException("updateSystemVmTemplates:Exception while setting 'minreq.sysvmtemplate.version' to 4.14.0", e); + } + } else { + if (hypervisorsListInUse.contains(hypervisorAndTemplateName.getKey())) { + throw new CloudRuntimeException(getUpgradedVersion() + hypervisorAndTemplateName.getKey() + " SystemVm template not found. Cannot upgrade system Vms"); + } else { + LOG.warn(getUpgradedVersion() + hypervisorAndTemplateName.getKey() + " SystemVm template not found. " + hypervisorAndTemplateName.getKey() + + " hypervisor is not used, so not failing upgrade"); + // Update the latest template URLs for corresponding + // hypervisor + try (PreparedStatement update_templ_url_pstmt = conn + .prepareStatement("UPDATE `cloud`.`vm_template` SET url = ? , checksum = ? WHERE hypervisor_type = ? AND type = 'SYSTEM' AND removed is null order by id desc limit 1");) { + update_templ_url_pstmt.setString(1, newTemplateUrl.get(hypervisorAndTemplateName.getKey())); + update_templ_url_pstmt.setString(2, newTemplateChecksum.get(hypervisorAndTemplateName.getKey())); + update_templ_url_pstmt.setString(3, hypervisorAndTemplateName.getKey().toString()); + update_templ_url_pstmt.executeUpdate(); + } catch (final SQLException e) { + LOG.error("updateSystemVmTemplates:Exception while updating 'url' and 'checksum' for hypervisor type " + + hypervisorAndTemplateName.getKey().toString() + ": " + e.getMessage()); + throw new CloudRuntimeException("updateSystemVmTemplates:Exception while updating 'url' and 'checksum' for hypervisor type " + + hypervisorAndTemplateName.getKey().toString(), e); + } + } + } + } catch (final SQLException e) { + LOG.error("updateSystemVmTemplates:Exception while getting ids of templates: " + e.getMessage()); + throw new CloudRuntimeException("updateSystemVmTemplates:Exception while getting ids of templates", e); + } + } + LOG.debug("Updating System Vm Template IDs Complete"); } @Override diff --git a/engine/schema/src/main/java/com/cloud/vm/dao/NicDao.java b/engine/schema/src/main/java/com/cloud/vm/dao/NicDao.java index df4fb06325f9..316c2dd53d72 100644 --- a/engine/schema/src/main/java/com/cloud/vm/dao/NicDao.java +++ b/engine/schema/src/main/java/com/cloud/vm/dao/NicDao.java @@ -50,6 +50,8 @@ public interface NicDao extends GenericDao { NicVO findDefaultNicForVM(long instanceId); + NicVO findFirstNicForVM(long instanceId); + /** * @param networkId * @param instanceId diff --git a/engine/schema/src/main/java/com/cloud/vm/dao/NicDaoImpl.java b/engine/schema/src/main/java/com/cloud/vm/dao/NicDaoImpl.java index c125d80c5342..6314ca0391ba 100644 --- a/engine/schema/src/main/java/com/cloud/vm/dao/NicDaoImpl.java +++ b/engine/schema/src/main/java/com/cloud/vm/dao/NicDaoImpl.java @@ -69,6 +69,7 @@ protected void init() { AllFieldsSearch.and("strategy", AllFieldsSearch.entity().getReservationStrategy(), Op.EQ); AllFieldsSearch.and("reserverName",AllFieldsSearch.entity().getReserver(),Op.EQ); AllFieldsSearch.and("macAddress", AllFieldsSearch.entity().getMacAddress(), Op.EQ); + AllFieldsSearch.and("deviceid", AllFieldsSearch.entity().getDeviceId(), Op.EQ); AllFieldsSearch.done(); IpSearch = createSearchBuilder(String.class); @@ -222,6 +223,14 @@ public NicVO findDefaultNicForVM(long instanceId) { return findOneBy(sc); } + @Override + public NicVO findFirstNicForVM(long instanceId) { + SearchCriteria sc = AllFieldsSearch.create(); + sc.setParameters("instance", instanceId); + sc.setParameters("deviceid", 0); + return findOneBy(sc); + } + @Override public NicVO getControlNicForVM(long vmId){ SearchCriteria sc = AllFieldsSearch.create(); diff --git a/engine/schema/src/main/java/com/cloud/vm/dao/UserVmDao.java b/engine/schema/src/main/java/com/cloud/vm/dao/UserVmDao.java index dfcc7f7fc333..0b1f9368e102 100644 --- a/engine/schema/src/main/java/com/cloud/vm/dao/UserVmDao.java +++ b/engine/schema/src/main/java/com/cloud/vm/dao/UserVmDao.java @@ -77,7 +77,7 @@ public interface UserVmDao extends GenericDao { List listPodIdsHavingVmsforAccount(long zoneId, long accountId); - public Long countAllocatedVMsForAccount(long accountId); + public Long countAllocatedVMsForAccount(long accountId, boolean runningVMsonly); Hashtable listVmDetails(Hashtable userVmData); diff --git a/engine/schema/src/main/java/com/cloud/vm/dao/UserVmDaoImpl.java b/engine/schema/src/main/java/com/cloud/vm/dao/UserVmDaoImpl.java index 5e22eb50208c..28940d7238e5 100644 --- a/engine/schema/src/main/java/com/cloud/vm/dao/UserVmDaoImpl.java +++ b/engine/schema/src/main/java/com/cloud/vm/dao/UserVmDaoImpl.java @@ -635,11 +635,14 @@ public String getQueryBatchAppender(int count) { } @Override - public Long countAllocatedVMsForAccount(long accountId) { + public Long countAllocatedVMsForAccount(long accountId, boolean runningVMsonly) { SearchCriteria sc = CountByAccount.create(); sc.setParameters("account", accountId); sc.setParameters("type", VirtualMachine.Type.User); - sc.setParameters("state", new Object[] {State.Destroyed, State.Error, State.Expunging}); + if (runningVMsonly) + sc.setParameters("state", new Object[] {State.Destroyed, State.Error, State.Expunging, State.Stopped}); + else + sc.setParameters("state", new Object[] {State.Destroyed, State.Error, State.Expunging}); sc.setParameters("displayVm", 1); return customSearch(sc, null).get(0); } diff --git a/engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDao.java b/engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDao.java index a7ed92252542..fad97478dc57 100755 --- a/engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDao.java +++ b/engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDao.java @@ -100,6 +100,8 @@ public interface VMInstanceDao extends GenericDao, StateDao< List listByLastHostId(Long hostId); + List listByLastHostIdAndStates(Long hostId, State... states); + List listByTypeAndState(VirtualMachine.Type type, State state); List listByAccountId(long accountId); diff --git a/engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDaoImpl.java b/engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDaoImpl.java index e4f5dba65eda..3af74ab00b42 100755 --- a/engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDaoImpl.java +++ b/engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDaoImpl.java @@ -94,6 +94,7 @@ public class VMInstanceDaoImpl extends GenericDaoBase implem protected SearchBuilder HostAndStateSearch; protected SearchBuilder StartingWithNoHostSearch; protected SearchBuilder NotMigratingSearch; + protected SearchBuilder LastHostAndStatesSearch; @Inject ResourceTagDao _tagsDao; @@ -286,6 +287,11 @@ protected void init() { NotMigratingSearch.and("lastHost", NotMigratingSearch.entity().getLastHostId(), Op.EQ); NotMigratingSearch.and("state", NotMigratingSearch.entity().getState(), Op.NEQ); NotMigratingSearch.done(); + + LastHostAndStatesSearch = createSearchBuilder(); + LastHostAndStatesSearch.and("lastHost", LastHostAndStatesSearch.entity().getLastHostId(), Op.EQ); + LastHostAndStatesSearch.and("states", LastHostAndStatesSearch.entity().getState(), Op.IN); + LastHostAndStatesSearch.done(); } @Override @@ -560,6 +566,14 @@ public List listByLastHostId(Long hostId) { return listBy(sc); } + @Override + public List listByLastHostIdAndStates(Long hostId, State... states) { + SearchCriteria sc = LastHostAndStatesSearch.create(); + sc.setParameters("lastHost", hostId); + sc.setParameters("states", (Object[])states); + return listBy(sc); + } + @Override public List findIdsOfAllocatedVirtualRoutersForAccount(long accountId) { SearchCriteria sc = FindIdsOfVirtualRoutersByAccount.create(); diff --git a/engine/schema/src/main/resources/META-INF/cloudstack/core/spring-engine-schema-core-daos-context.xml b/engine/schema/src/main/resources/META-INF/cloudstack/core/spring-engine-schema-core-daos-context.xml index 3e0d67b61a49..34c356dab342 100644 --- a/engine/schema/src/main/resources/META-INF/cloudstack/core/spring-engine-schema-core-daos-context.xml +++ b/engine/schema/src/main/resources/META-INF/cloudstack/core/spring-engine-schema-core-daos-context.xml @@ -288,4 +288,5 @@ + diff --git a/engine/schema/src/main/resources/META-INF/db/schema-41300to41400-cleanup.sql b/engine/schema/src/main/resources/META-INF/db/schema-41300to41400-cleanup.sql index fa631ef50fa5..7758f116dd7f 100644 --- a/engine/schema/src/main/resources/META-INF/db/schema-41300to41400-cleanup.sql +++ b/engine/schema/src/main/resources/META-INF/db/schema-41300to41400-cleanup.sql @@ -23,3 +23,6 @@ DELETE FROM `cloud`.`configuration` WHERE name = 'host.maintenance.retries'; -- Stop asking user (in the upgraded documentation) to remove a trailing slash for local KVM pool UPDATE `cloud`.`storage_pool` SET path="/var/lib/libvirt/images" WHERE path="/var/lib/libvirt/images/"; + +-- remove (one of) duplicate unique indexes from Region table +ALTER TABLE `region` DROP INDEX `id_3`; diff --git a/engine/schema/src/main/resources/META-INF/db/schema-41300to41400.sql b/engine/schema/src/main/resources/META-INF/db/schema-41300to41400.sql index 63fdbab3799f..ad257bc74e7f 100644 --- a/engine/schema/src/main/resources/META-INF/db/schema-41300to41400.sql +++ b/engine/schema/src/main/resources/META-INF/db/schema-41300to41400.sql @@ -22,6 +22,9 @@ -- KVM: enable storage data motion on KVM hypervisor_capabilities UPDATE `cloud`.`hypervisor_capabilities` SET `storage_motion_supported` = 1 WHERE `hypervisor_capabilities`.`hypervisor_type` = 'KVM'; +-- Use 'Other Linux 64-bit' as guest os for the default systemvmtemplate for XenServer +UPDATE `cloud`.`vm_template` SET guest_os_id=99 WHERE id=1; + -- #3659 Fix typo: the past tense of shutdown is shutdown, not shutdowned UPDATE `cloud`.`vm_instance` SET state='Shutdown' WHERE state='Shutdowned'; @@ -36,3 +39,18 @@ UPDATE `cloud`.`guest_os` SET `category_id`='4' WHERE `id`=283 AND display_name= UPDATE `cloud`.`guest_os` SET `category_id`='4' WHERE `id`=284 AND display_name="Red Hat Enterprise Linux 7.5"; UPDATE `cloud`.`guest_os` SET `category_id`='4' WHERE `id`=285 AND display_name="Red Hat Enterprise Linux 7.6"; UPDATE `cloud`.`guest_os` SET `category_id`='4' WHERE `id`=286 AND display_name="Red Hat Enterprise Linux 8.0"; + +-- Create table for router health checks. We only save last check result for each. +CREATE TABLE `cloud`.`router_health_check` ( + `id` bigint unsigned NOT NULL auto_increment, + `router_id` bigint unsigned NOT NULL COMMENT 'router id', + `check_name` varchar(255) NOT NULL COMMENT 'name of the health check', + `check_type` varchar(255) NOT NULL COMMENT 'type of the health check', + `last_update` DATETIME NULL COMMENT 'last check update time', + `check_result` boolean NOT NULL COMMENT 'check executions success or failure', + `check_details` BLOB NULL COMMENT 'check result detailed message', + PRIMARY KEY (`id`), + CONSTRAINT `fk_router_health_checks__router_id` FOREIGN KEY (`router_id`) REFERENCES `domain_router`(`id`) ON DELETE CASCADE, + UNIQUE `i_router_health_checks__router_id__check_name__check_type`(`router_id`, `check_name`, `check_type`), + INDEX `i_router_health_checks__router_id`(`router_id`) +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; diff --git a/engine/schema/src/test/java/com/cloud/upgrade/dao/DatabaseAccessObjectTest.java b/engine/schema/src/test/java/com/cloud/upgrade/dao/DatabaseAccessObjectTest.java index 9a2115e9629e..2b8b2bd8f1cd 100644 --- a/engine/schema/src/test/java/com/cloud/upgrade/dao/DatabaseAccessObjectTest.java +++ b/engine/schema/src/test/java/com/cloud/upgrade/dao/DatabaseAccessObjectTest.java @@ -34,8 +34,8 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.internal.util.reflection.Whitebox; import org.mockito.runners.MockitoJUnitRunner; +import org.powermock.reflect.Whitebox; @RunWith(MockitoJUnitRunner.class) public class DatabaseAccessObjectTest { @@ -53,7 +53,7 @@ public class DatabaseAccessObjectTest { @Before public void setup() { - Whitebox.setInternalState(dao, "s_logger", loggerMock); + Whitebox.setInternalState(dao.getClass(), "s_logger", loggerMock); } @Test diff --git a/engine/schema/src/test/java/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDaoImplTest.java b/engine/schema/src/test/java/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDaoImplTest.java index 2d195af0843f..471fc5216a0f 100755 --- a/engine/schema/src/test/java/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDaoImplTest.java +++ b/engine/schema/src/test/java/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDaoImplTest.java @@ -16,9 +16,12 @@ // under the License. package org.apache.cloudstack.storage.datastore.db; +import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.verify; +import java.io.IOException; +import java.sql.SQLException; import java.util.Arrays; import java.util.HashMap; import java.util.List; @@ -29,9 +32,9 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InjectMocks; -import org.mockito.Matchers; import org.mockito.Mock; import org.mockito.Spy; +import org.powermock.core.classloader.annotations.PowerMockIgnore; import org.powermock.modules.junit4.PowerMockRunner; import com.cloud.storage.ScopeType; @@ -41,6 +44,7 @@ import junit.framework.TestCase; @RunWith(PowerMockRunner.class) +@PowerMockIgnore("javax.management.*") public class PrimaryDataStoreDaoImplTest extends TestCase { @Mock @@ -77,12 +81,13 @@ public class PrimaryDataStoreDaoImplTest extends TestCase { private static final Long CLUSTER_ID = null; private static final ScopeType SCOPE = ScopeType.ZONE; + @Before - public void setup() { + public void setup() throws IOException, ClassNotFoundException, SQLException { STORAGE_POOL_DETAILS.put(DETAIL_KEY, DETAIL_VALUE); doReturn(Arrays.asList(storagePoolVO)).when(primaryDataStoreDao). - searchStoragePoolsPreparedStatement(Matchers.anyString(), Matchers.anyLong(), Matchers.anyLong(), Matchers.anyLong(), - Matchers.any(ScopeType.class), Matchers.anyInt()); + searchStoragePoolsPreparedStatement(nullable(String.class), nullable(Long.class), nullable(Long.class), nullable(Long.class), + nullable(ScopeType.class), nullable(Integer.class)); } @Test diff --git a/engine/storage/configdrive/src/test/java/org/apache/cloudstack/storage/configdrive/ConfigDriveBuilderTest.java b/engine/storage/configdrive/src/test/java/org/apache/cloudstack/storage/configdrive/ConfigDriveBuilderTest.java index 96032738edcb..50cab35e78d1 100644 --- a/engine/storage/configdrive/src/test/java/org/apache/cloudstack/storage/configdrive/ConfigDriveBuilderTest.java +++ b/engine/storage/configdrive/src/test/java/org/apache/cloudstack/storage/configdrive/ConfigDriveBuilderTest.java @@ -17,6 +17,9 @@ package org.apache.cloudstack.storage.configdrive; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.Mockito.times; import java.io.File; @@ -53,7 +56,7 @@ public void writeFileTest() throws Exception { ConfigDriveBuilder.writeFile(new File("folder"), "subfolder", "content"); - PowerMockito.verifyStatic(); + PowerMockito.verifyStatic(FileUtils.class); FileUtils.write(Mockito.any(File.class), Mockito.anyString(), Mockito.any(Charset.class), Mockito.eq(false)); } @@ -130,8 +133,10 @@ public void buildConfigDriveTestNoVmData() { public void buildConfigDriveTestIoException() throws Exception { PowerMockito.mockStatic(ConfigDriveBuilder.class); + Method method1 = ReflectionUtils.getMethods(ConfigDriveBuilder.class, ReflectionUtils.withName("writeFile")).iterator().next(); Method method = ReflectionUtils.getMethods(ConfigDriveBuilder.class, ReflectionUtils.withName("writeVendorAndNetworkEmptyJsonFile")).iterator().next(); - PowerMockito.when(ConfigDriveBuilder.class, method).withArguments(Mockito.any(File.class)).thenThrow(IOException.class); + + PowerMockito.when(ConfigDriveBuilder.class, method).withArguments(nullable(File.class)).thenThrow(CloudRuntimeException.class); //This is odd, but it was necessary to allow us to check if we catch the IOexception and re-throw as a CloudRuntimeException //We are mocking the class being tested; therefore, we needed to force the execution of the real method we want to test. @@ -165,7 +170,7 @@ public void buildConfigDriveTest() throws Exception { Assert.assertEquals("mockIsoDataBase64", returnedIsoData); - PowerMockito.verifyStatic(); + PowerMockito.verifyStatic(ConfigDriveBuilder.class); ConfigDriveBuilder.writeVendorAndNetworkEmptyJsonFile(Mockito.any(File.class)); ConfigDriveBuilder.writeVmMetadata(Mockito.anyListOf(String[].class), Mockito.anyString(), Mockito.any(File.class)); ConfigDriveBuilder.linkUserData(Mockito.anyString()); @@ -211,7 +216,7 @@ public void writeVendorAndNetworkEmptyJsonFileTestCreatingFolder() throws Except Mockito.verify(folderFileMock).exists(); Mockito.verify(folderFileMock).mkdirs(); - PowerMockito.verifyStatic(); + PowerMockito.verifyStatic(ConfigDriveBuilder.class); ConfigDriveBuilder.writeFile(Mockito.any(File.class), Mockito.eq("vendor_data.json"), Mockito.eq("{}")); ConfigDriveBuilder.writeFile(Mockito.any(File.class), Mockito.eq("network_data.json"), Mockito.eq("{}")); } @@ -228,15 +233,20 @@ public void writeVmMetadataTest() throws Exception { PowerMockito.mockStatic(ConfigDriveBuilder.class); Method method = getWriteVmMetadataMethod(); - PowerMockito.when(ConfigDriveBuilder.class, method).withArguments(new ArrayList<>(), "metadataFile", new File("folder")).thenCallRealMethod(); + PowerMockito.when(ConfigDriveBuilder.class, method).withArguments(Mockito.anyListOf(String[].class), anyString(), any(File.class)).thenCallRealMethod(); Method createJsonObjectWithVmDataMethod = ReflectionUtils.getMethods(ConfigDriveBuilder.class, ReflectionUtils.withName("createJsonObjectWithVmData")).iterator().next(); - PowerMockito.when(ConfigDriveBuilder.class, createJsonObjectWithVmDataMethod).withArguments(Mockito.anyListOf(String[].class), Mockito.any(File.class)).thenReturn(new JsonObject()); - ConfigDriveBuilder.writeVmMetadata(new ArrayList<>(), "metadataFile", new File("folder")); + PowerMockito.when(ConfigDriveBuilder.class, createJsonObjectWithVmDataMethod).withArguments(Mockito.anyListOf(String[].class), Mockito.anyString()).thenReturn(new JsonObject()); + + List vmData = new ArrayList<>(); + vmData.add(new String[] {"dataType", "fileName", "content"}); + vmData.add(new String[] {"dataType2", "fileName2", "content2"}); + + ConfigDriveBuilder.writeVmMetadata(vmData, "metadataFile", new File("folder")); - PowerMockito.verifyStatic(); - ConfigDriveBuilder.createJsonObjectWithVmData(Mockito.anyListOf(String[].class), Mockito.anyString()); + PowerMockito.verifyStatic(ConfigDriveBuilder.class); + ConfigDriveBuilder.createJsonObjectWithVmData(vmData, "metadataFile"); ConfigDriveBuilder.writeFile(Mockito.any(File.class), Mockito.eq("meta_data.json"), Mockito.eq("{}")); } @@ -306,7 +316,7 @@ public void generateAndRetrieveIsoAsBase64IsoTestGenIsoFailure() throws Exceptio Mockito.doReturn("scriptMessage").when(scriptMock).execute(); Method method = ReflectionUtils.getMethods(ConfigDriveBuilder.class, ReflectionUtils.withName("generateAndRetrieveIsoAsBase64Iso")).iterator().next(); - PowerMockito.when(ConfigDriveBuilder.class, method).withArguments(Mockito.any(File.class), Mockito.any(File.class), Mockito.any(File.class)).thenCallRealMethod(); + PowerMockito.when(ConfigDriveBuilder.class, method).withArguments(nullable(String.class), nullable(String.class), nullable(String.class)).thenCallRealMethod(); Method getProgramToGenerateIsoMethod = ReflectionUtils.getMethods(ConfigDriveBuilder.class, ReflectionUtils.withName("getProgramToGenerateIso")).iterator().next(); PowerMockito.when(ConfigDriveBuilder.class, getProgramToGenerateIsoMethod).withNoArguments().thenReturn("/usr/bin/genisoimage"); @@ -330,7 +340,7 @@ public void generateAndRetrieveIsoAsBase64IsoTestIsoTooBig() throws Exception { Mockito.doReturn(64L * 1024L * 1024L + 1l).when(fileMock).length(); Method method = ReflectionUtils.getMethods(ConfigDriveBuilder.class, ReflectionUtils.withName("generateAndRetrieveIsoAsBase64Iso")).iterator().next(); - PowerMockito.when(ConfigDriveBuilder.class, method).withArguments(Mockito.any(File.class), Mockito.any(File.class), Mockito.any(File.class)).thenCallRealMethod(); + PowerMockito.when(ConfigDriveBuilder.class, method).withArguments(nullable(String.class), nullable(String.class), nullable(String.class)).thenCallRealMethod(); Method getProgramToGenerateIsoMethod = ReflectionUtils.getMethods(ConfigDriveBuilder.class, ReflectionUtils.withName("getProgramToGenerateIso")).iterator().next(); PowerMockito.when(ConfigDriveBuilder.class, getProgramToGenerateIsoMethod).withNoArguments().thenReturn("/usr/bin/genisoimage"); @@ -355,7 +365,7 @@ public void generateAndRetrieveIsoAsBase64IsoTest() throws Exception { Mockito.doReturn(64L * 1024L * 1024L).when(fileMock).length(); Method method = ReflectionUtils.getMethods(ConfigDriveBuilder.class, ReflectionUtils.withName("generateAndRetrieveIsoAsBase64Iso")).iterator().next(); - PowerMockito.when(ConfigDriveBuilder.class, method).withArguments(Mockito.any(File.class), Mockito.any(File.class), Mockito.any(File.class)).thenCallRealMethod(); + PowerMockito.when(ConfigDriveBuilder.class, method).withArguments(nullable(String.class), nullable(String.class), nullable(String.class)).thenCallRealMethod(); Method getProgramToGenerateIsoMethod = ReflectionUtils.getMethods(ConfigDriveBuilder.class, ReflectionUtils.withName("getProgramToGenerateIso")).iterator().next(); PowerMockito.when(ConfigDriveBuilder.class, getProgramToGenerateIsoMethod).withNoArguments().thenReturn("/usr/bin/genisoimage"); @@ -376,8 +386,8 @@ public void generateAndRetrieveIsoAsBase64IsoTest() throws Exception { inOrder.verify(scriptMock).add("tempDirName"); inOrder.verify(scriptMock).execute(); - PowerMockito.verifyStatic(); - ConfigDriveBuilder.fileToBase64String(Mockito.any(File.class)); + PowerMockito.verifyStatic(ConfigDriveBuilder.class); + ConfigDriveBuilder.fileToBase64String(nullable(File.class)); } @@ -396,7 +406,7 @@ public void createJsonObjectWithVmDataTesT() throws Exception { ConfigDriveBuilder.createJsonObjectWithVmData(vmData, "tempDirName"); - PowerMockito.verifyStatic(Mockito.times(1)); + PowerMockito.verifyStatic(ConfigDriveBuilder.class, Mockito.times(1)); ConfigDriveBuilder.createFileInTempDirAnAppendOpenStackMetadataToJsonObject(Mockito.eq("tempDirName"), Mockito.any(JsonObject.class), Mockito.eq("dataType"), Mockito.eq("fileName"), Mockito.eq("content")); ConfigDriveBuilder.createFileInTempDirAnAppendOpenStackMetadataToJsonObject(Mockito.eq("tempDirName"), Mockito.any(JsonObject.class), Mockito.eq("dataType2"), Mockito.eq("fileName2"), @@ -494,4 +504,4 @@ public void getProgramToGenerateIsoTestMkIsoMac() throws Exception { Mockito.verify(mkIsoProgramInMacOsFileMock, Mockito.times(1)).canExecute(); Mockito.verify(mkIsoProgramInMacOsFileMock, Mockito.times(1)).getCanonicalPath(); } -} \ No newline at end of file +} diff --git a/engine/storage/datamotion/src/test/java/org/apache/cloudstack/storage/motion/KvmNonManagedStorageSystemDataMotionTest.java b/engine/storage/datamotion/src/test/java/org/apache/cloudstack/storage/motion/KvmNonManagedStorageSystemDataMotionTest.java index 3dfc4af409f5..6971444bcad0 100644 --- a/engine/storage/datamotion/src/test/java/org/apache/cloudstack/storage/motion/KvmNonManagedStorageSystemDataMotionTest.java +++ b/engine/storage/datamotion/src/test/java/org/apache/cloudstack/storage/motion/KvmNonManagedStorageSystemDataMotionTest.java @@ -19,6 +19,7 @@ package org.apache.cloudstack.storage.motion; import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.lenient; import static org.mockito.Mockito.when; import java.util.HashMap; @@ -270,7 +271,7 @@ private void configureAndTestSendCommandTest(Class exc sourceTemplate.setId(0l); TemplateObjectTO destTemplate = new TemplateObjectTO(); ImageStoreVO dataStoreVO = Mockito.mock(ImageStoreVO.class); - Mockito.when(dataStoreVO.getId()).thenReturn(0l); + Mockito.lenient().when(dataStoreVO.getId()).thenReturn(0l); ImageStoreEntity destDataStore = Mockito.mock(ImageStoreImpl.class); Mockito.doReturn(0l).when(destDataStore).getId(); @@ -299,7 +300,7 @@ private void configureAndTestSendCommandTest(Class exc @Test public void copyTemplateToTargetStorageIfNeededTestTemplateAlreadyOnTargetHost() throws AgentUnavailableException, OperationTimedoutException { Answer copyCommandAnswer = Mockito.mock(Answer.class); - Mockito.when(copyCommandAnswer.getResult()).thenReturn(true); + Mockito.lenient().when(copyCommandAnswer.getResult()).thenReturn(true); configureAndTestcopyTemplateToTargetStorageIfNeeded(new VMTemplateStoragePoolVO(0l, 0l), StoragePoolType.Filesystem, 0); } @@ -329,14 +330,14 @@ private void configureAndTestcopyTemplateToTargetStorageIfNeeded(VMTemplateStora StoragePool srcStoragePool = Mockito.mock(StoragePool.class); VolumeInfo destVolumeInfo = Mockito.mock(VolumeInfo.class); - Mockito.when(volumeDataFactory.getVolume(Mockito.anyLong(), Mockito.any(DataStore.class))).thenReturn(destVolumeInfo); + Mockito.lenient().when(volumeDataFactory.getVolume(Mockito.anyLong(), Mockito.any(DataStore.class))).thenReturn(destVolumeInfo); StoragePool destStoragePool = Mockito.mock(StoragePool.class); Mockito.when(destStoragePool.getId()).thenReturn(0l); Mockito.when(destStoragePool.getPoolType()).thenReturn(storagePoolType); DataStore sourceTemplateDataStore = Mockito.mock(DataStore.class); - Mockito.when(sourceTemplateDataStore.getName()).thenReturn("sourceTemplateName"); + Mockito.lenient().when(sourceTemplateDataStore.getName()).thenReturn("sourceTemplateName"); TemplateInfo sourceTemplateInfo = Mockito.mock(TemplateInfo.class); Mockito.when(sourceTemplateInfo.getInstallPath()).thenReturn("installPath"); @@ -357,7 +358,7 @@ private void configureAndTestcopyTemplateToTargetStorageIfNeeded(VMTemplateStora Mockito.when(templateDataFactory.getTemplate(Mockito.anyLong(), Mockito.eq(sourceTemplateDataStore))).thenReturn(sourceTemplateInfo); Mockito.when(templateDataFactory.getTemplate(Mockito.anyLong(), Mockito.eq(destDataStore))).thenReturn(sourceTemplateInfo); kvmNonManagedStorageDataMotionStrategy.copyTemplateToTargetFilesystemStorageIfNeeded(srcVolumeInfo, srcStoragePool, destDataStore, destStoragePool, destHost); - Mockito.doNothing().when(kvmNonManagedStorageDataMotionStrategy).updateTemplateReferenceIfSuccessfulCopy(Mockito.any(VolumeInfo.class), Mockito.any(StoragePool.class), + Mockito.lenient().doNothing().when(kvmNonManagedStorageDataMotionStrategy).updateTemplateReferenceIfSuccessfulCopy(Mockito.any(VolumeInfo.class), Mockito.any(StoragePool.class), Mockito.any(TemplateInfo.class), Mockito.any(DataStore.class)); InOrder verifyInOrder = Mockito.inOrder(vmTemplatePoolDao, dataStoreManagerImpl, templateDataFactory, kvmNonManagedStorageDataMotionStrategy); @@ -384,23 +385,23 @@ public void setUp() { when(volumeInfo1.getDataStore()).thenReturn(dataStore1); when(volumeInfo2.getPoolId()).thenReturn(POOL_1_ID); - when(volumeInfo2.getDataStore()).thenReturn(dataStore1); + lenient().when(volumeInfo2.getDataStore()).thenReturn(dataStore1); - when(dataStore1.getId()).thenReturn(POOL_1_ID); + lenient().when(dataStore1.getId()).thenReturn(POOL_1_ID); when(pool1.getPoolType()).thenReturn(Storage.StoragePoolType.NetworkFilesystem); when(pool2.getPoolType()).thenReturn(Storage.StoragePoolType.NetworkFilesystem); when(pool2.getScope()).thenReturn(ScopeType.CLUSTER); - when(dataStore3.getId()).thenReturn(POOL_3_ID); - when(primaryDataStoreDao.findById(POOL_3_ID)).thenReturn(pool3); - when(pool3.getPoolType()).thenReturn(Storage.StoragePoolType.NetworkFilesystem); - when(pool3.getScope()).thenReturn(ScopeType.CLUSTER); + lenient().when(dataStore3.getId()).thenReturn(POOL_3_ID); + lenient().when(primaryDataStoreDao.findById(POOL_3_ID)).thenReturn(pool3); + lenient().when(pool3.getPoolType()).thenReturn(Storage.StoragePoolType.NetworkFilesystem); + lenient().when(pool3.getScope()).thenReturn(ScopeType.CLUSTER); when(host1.getId()).thenReturn(HOST_1_ID); when(host1.getClusterId()).thenReturn(CLUSTER_ID); - when(host1.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.KVM); + lenient().when(host1.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.KVM); when(host2.getId()).thenReturn(HOST_2_ID); when(host2.getClusterId()).thenReturn(CLUSTER_ID); - when(host2.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.KVM); + lenient().when(host2.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.KVM); } @Test @@ -424,7 +425,7 @@ public void canHandleKVMLiveStorageMigration() { @Test public void canHandleKVMLiveStorageMigrationMultipleSources() { - when(volumeInfo1.getDataStore()).thenReturn(dataStore2); + lenient().when(volumeInfo1.getDataStore()).thenReturn(dataStore2); StrategyPriority priority = kvmNonManagedStorageDataMotionStrategy.canHandleKVMNonManagedLiveNFSStorageMigration(migrationMap, host1, host2); assertEquals(StrategyPriority.HYPERVISOR, priority); } @@ -438,7 +439,7 @@ public void canHandleKVMLiveStorageMigrationMultipleDestination() { @Test public void testCanHandleLiveMigrationUnmanagedStorage() { - when(pool2.isManaged()).thenReturn(false); + lenient().when(pool2.isManaged()).thenReturn(false); StrategyPriority priority = kvmNonManagedStorageDataMotionStrategy.canHandleKVMNonManagedLiveNFSStorageMigration(migrationMap, host1, host2); assertEquals(StrategyPriority.HYPERVISOR, priority); } @@ -463,7 +464,7 @@ public void testVerifyLiveMigrationMapForKVMNotExistingDest() { @Test(expected = CloudRuntimeException.class) public void testVerifyLiveMigrationMapForKVMMixedManagedUnmagedStorage() { when(pool1.isManaged()).thenReturn(true); - when(pool2.isManaged()).thenReturn(false); + lenient().when(pool2.isManaged()).thenReturn(false); kvmNonManagedStorageDataMotionStrategy.verifyLiveMigrationForKVM(migrationMap, host2); } } diff --git a/engine/storage/datamotion/src/test/java/org/apache/cloudstack/storage/motion/StorageSystemDataMotionStrategyTest.java b/engine/storage/datamotion/src/test/java/org/apache/cloudstack/storage/motion/StorageSystemDataMotionStrategyTest.java index 288243c85ba7..4e62c9477c05 100644 --- a/engine/storage/datamotion/src/test/java/org/apache/cloudstack/storage/motion/StorageSystemDataMotionStrategyTest.java +++ b/engine/storage/datamotion/src/test/java/org/apache/cloudstack/storage/motion/StorageSystemDataMotionStrategyTest.java @@ -20,6 +20,7 @@ import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.lenient; import static org.mockito.Mockito.mock; import static org.mockito.MockitoAnnotations.initMocks; @@ -85,9 +86,9 @@ public void setUp() throws Exception { @Test public void cantHandleSecondary() { - doReturn(sourceStore).when(volumeObjectSource).getDataStore(); + lenient().doReturn(sourceStore).when(volumeObjectSource).getDataStore(); doReturn(DataStoreRole.Primary).when(sourceStore).getRole(); - doReturn(destinationStore).when(dataObjectDestination).getDataStore(); + lenient().doReturn(destinationStore).when(dataObjectDestination).getDataStore(); doReturn(DataStoreRole.Image).when((DataStore)destinationStore).getRole(); doReturn(sourceStore).when(volumeObjectSource).getDataStore(); doReturn(destinationStore).when(dataObjectDestination).getDataStore(); @@ -199,7 +200,7 @@ public void shouldMigrateVolumeTest() { StoragePoolVO destStoragePool = new StoragePoolVO(); StoragePoolType[] storagePoolTypes = StoragePoolType.values(); for (int i = 0; i < storagePoolTypes.length; i++) { - Mockito.doReturn(storagePoolTypes[i]).when(sourceStoragePool).getPoolType(); + Mockito.lenient().doReturn(storagePoolTypes[i]).when(sourceStoragePool).getPoolType(); boolean result = strategy.shouldMigrateVolume(sourceStoragePool, destHost, destStoragePool); Assert.assertTrue(result); } @@ -244,7 +245,7 @@ public void isSourceAndDestinationPoolTypeOfNfsTestAnyAny() { private void configureAndVerifyIsSourceAndDestinationPoolTypeOfNfs(StoragePoolType destStoragePoolType, StoragePoolType sourceStoragePoolType, boolean expected) { VolumeInfo srcVolumeInfo = Mockito.mock(VolumeObject.class); - Mockito.when(srcVolumeInfo.getId()).thenReturn(0l); + Mockito.lenient().when(srcVolumeInfo.getId()).thenReturn(0l); DataStore destDataStore = Mockito.mock(PrimaryDataStoreImpl.class); Mockito.when(destDataStore.getId()).thenReturn(1l); diff --git a/engine/storage/image/src/main/java/org/apache/cloudstack/storage/image/TemplateServiceImpl.java b/engine/storage/image/src/main/java/org/apache/cloudstack/storage/image/TemplateServiceImpl.java index 097b85477daf..97ac7c9037d4 100644 --- a/engine/storage/image/src/main/java/org/apache/cloudstack/storage/image/TemplateServiceImpl.java +++ b/engine/storage/image/src/main/java/org/apache/cloudstack/storage/image/TemplateServiceImpl.java @@ -1052,6 +1052,10 @@ public AsyncCallFuture copyTemplate(TemplateInfo srcTemplate, DataObject templateOnStore = destStore.create(tmplForCopy); templateOnStore.processEvent(Event.CreateOnlyRequested); + if (templateOnStore instanceof TemplateObject) { + ((TemplateObject)templateOnStore).getImage().setChecksum(null); + } // else we don't know what to do. + if (s_logger.isDebugEnabled()) { s_logger.debug("Invoke datastore driver createAsync to create template on destination store"); } diff --git a/engine/storage/snapshot/src/test/java/org/apache/cloudstack/storage/snapshot/CephSnapshotStrategyTest.java b/engine/storage/snapshot/src/test/java/org/apache/cloudstack/storage/snapshot/CephSnapshotStrategyTest.java index b36aaac8c254..260a21d87a01 100644 --- a/engine/storage/snapshot/src/test/java/org/apache/cloudstack/storage/snapshot/CephSnapshotStrategyTest.java +++ b/engine/storage/snapshot/src/test/java/org/apache/cloudstack/storage/snapshot/CephSnapshotStrategyTest.java @@ -81,7 +81,7 @@ private void configureAndVerifyCanHandle(Date removed, boolean isSnapshotStoredO VolumeVO volumeVO = Mockito.mock(VolumeVO.class); Mockito.when(volumeVO.getRemoved()).thenReturn(removed); Mockito.when(volumeDao.findByIdIncludingRemoved(Mockito.anyLong())).thenReturn(volumeVO); - Mockito.doReturn(isSnapshotStoredOnRbdStoragePool).when(cephSnapshotStrategy).isSnapshotStoredOnRbdStoragePool(Mockito.any()); + Mockito.lenient().doReturn(isSnapshotStoredOnRbdStoragePool).when(cephSnapshotStrategy).isSnapshotStoredOnRbdStoragePool(Mockito.any()); for (int i = 0; i < snapshotOps.length - 1; i++) { StrategyPriority strategyPriority = cephSnapshotStrategy.canHandle(snapshot, snapshotOps[i]); @@ -105,7 +105,7 @@ public void revertSnapshotTest() { VolumeInfo volumeInfo = Mockito.mock(VolumeInfo.class); Mockito.when(snapshotInfo.getBaseVolume()).thenReturn(volumeInfo); Mockito.when(volumeInfo.getFormat()).thenReturn(imageFormatValues[i]); - Mockito.doNothing().when(cephSnapshotStrategy).executeRevertSnapshot(Mockito.any(), Mockito.any()); + Mockito.lenient().doNothing().when(cephSnapshotStrategy).executeRevertSnapshot(Mockito.any(), Mockito.any()); boolean revertResult = cephSnapshotStrategy.revertSnapshot(snapshotInfo); diff --git a/engine/storage/snapshot/src/test/java/org/apache/cloudstack/storage/snapshot/SnapshotDataFactoryImplTest.java b/engine/storage/snapshot/src/test/java/org/apache/cloudstack/storage/snapshot/SnapshotDataFactoryImplTest.java index aad339bb8ffa..25de9cd31a74 100644 --- a/engine/storage/snapshot/src/test/java/org/apache/cloudstack/storage/snapshot/SnapshotDataFactoryImplTest.java +++ b/engine/storage/snapshot/src/test/java/org/apache/cloudstack/storage/snapshot/SnapshotDataFactoryImplTest.java @@ -104,7 +104,7 @@ public void getSnapshotsByVolumeAndDataStoreTest() { Assert.assertEquals(dataStoreMock, snapshotInfo.getDataStore()); Assert.assertEquals(snapshotVoMock, ((SnapshotObject)snapshotInfo).getSnapshotVO()); - PowerMockito.verifyStatic(); + PowerMockito.verifyStatic(ComponentContext.class); ComponentContext.inject(SnapshotObject.class); } } diff --git a/engine/storage/volume/src/main/java/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java b/engine/storage/volume/src/main/java/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java index 2a642f02673a..92c8a93f515b 100644 --- a/engine/storage/volume/src/main/java/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java +++ b/engine/storage/volume/src/main/java/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java @@ -119,6 +119,7 @@ import com.cloud.utils.db.DB; import com.cloud.utils.db.GlobalLock; import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.vm.VirtualMachine; @Component public class VolumeServiceImpl implements VolumeService { @@ -325,7 +326,10 @@ public AsyncCallFuture expungeVolumeAsync(VolumeInfo volume) { VolumeDataStoreVO volumeStore = _volumeStoreDao.findByVolume(volume.getId()); if (volumeStore != null) { if (volumeStore.getDownloadState() == VMTemplateStorageResourceAssoc.Status.DOWNLOAD_IN_PROGRESS) { - s_logger.debug("Volume: " + volume.getName() + " is currently being uploaded; cant' delete it."); + String msg = "Volume: " + volume.getName() + " is currently being uploaded; cant' delete it."; + s_logger.debug(msg); + result.setSuccess(false); + result.setResult(msg); future.complete(result); return future; } @@ -1213,6 +1217,12 @@ public void destroyVolume(long volumeId) { snapshotMgr.deletePoliciesForVolume(volumeId); vol.stateTransit(Volume.Event.OperationSucceeded); + + if (vol.getAttachedVM() == null || vol.getAttachedVM().getType() == VirtualMachine.Type.User) { + // Decrement the resource count for volumes and primary storage belonging user VM's only + _resourceLimitMgr.decrementResourceCount(vol.getAccountId(), ResourceType.volume, vol.isDisplay()); + _resourceLimitMgr.decrementResourceCount(vol.getAccountId(), ResourceType.primary_storage, vol.isDisplay(), new Long(vol.getSize())); + } } @Override diff --git a/framework/agent-lb/src/main/java/org/apache/cloudstack/agent/lb/IndirectAgentLB.java b/framework/agent-lb/src/main/java/org/apache/cloudstack/agent/lb/IndirectAgentLB.java index 627a5ee5f50c..464c489af848 100644 --- a/framework/agent-lb/src/main/java/org/apache/cloudstack/agent/lb/IndirectAgentLB.java +++ b/framework/agent-lb/src/main/java/org/apache/cloudstack/agent/lb/IndirectAgentLB.java @@ -50,4 +50,7 @@ public interface IndirectAgentLB { * @return returns interval in seconds */ Long getLBPreferredHostCheckInterval(Long clusterId); -} \ No newline at end of file + + void propagateMSListToAgents(); + +} diff --git a/framework/db/src/main/java/com/cloud/utils/db/DriverLoader.java b/framework/db/src/main/java/com/cloud/utils/db/DriverLoader.java index 06c8da5c3552..14bd286aab27 100644 --- a/framework/db/src/main/java/com/cloud/utils/db/DriverLoader.java +++ b/framework/db/src/main/java/com/cloud/utils/db/DriverLoader.java @@ -16,14 +16,15 @@ // under the License. package com.cloud.utils.db; -import com.cloud.utils.exception.CloudRuntimeException; -import org.apache.log4j.Logger; - import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import org.apache.log4j.Logger; + +import com.cloud.utils.exception.CloudRuntimeException; + public class DriverLoader { private static final Logger LOGGER = Logger.getLogger(DriverLoader.class.getName()); @@ -32,7 +33,7 @@ public class DriverLoader { static { DRIVERS = new HashMap(); - DRIVERS.put("jdbc:mysql", "com.mysql.jdbc.Driver"); + DRIVERS.put("jdbc:mysql", "com.mysql.cj.jdbc.Driver"); DRIVERS.put("jdbc:postgresql", "org.postgresql.Driver"); DRIVERS.put("jdbc:h2", "org.h2.Driver"); diff --git a/framework/db/src/main/java/com/cloud/utils/db/GenericDaoBase.java b/framework/db/src/main/java/com/cloud/utils/db/GenericDaoBase.java index fb923c6f0683..13f94fcfc221 100644 --- a/framework/db/src/main/java/com/cloud/utils/db/GenericDaoBase.java +++ b/framework/db/src/main/java/com/cloud/utils/db/GenericDaoBase.java @@ -22,6 +22,7 @@ import java.lang.reflect.Field; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; +import java.math.BigInteger; import java.net.MalformedURLException; import java.net.URI; import java.net.URISyntaxException; @@ -1421,7 +1422,11 @@ public T persist(final T entity) { try { if (_idField != null) { if (id != null) { - _idField.set(entity, id); + if (id instanceof BigInteger) { + _idField.set(entity, ((BigInteger) id).longValue()); + } else { + _idField.set(entity, id); + } } else { id = (ID)_idField.get(entity); } diff --git a/framework/ipc/src/main/java/org/apache/cloudstack/framework/serializer/OnwireClassRegistry.java b/framework/ipc/src/main/java/org/apache/cloudstack/framework/serializer/OnwireClassRegistry.java index de7558734c3f..24ccfe42afc5 100644 --- a/framework/ipc/src/main/java/org/apache/cloudstack/framework/serializer/OnwireClassRegistry.java +++ b/framework/ipc/src/main/java/org/apache/cloudstack/framework/serializer/OnwireClassRegistry.java @@ -109,7 +109,7 @@ static Set> getClasses(ClassLoader loader, String packageName) { if (filePath != null) { // WINDOWS HACK if (filePath.indexOf("%20") > 0) - filePath = filePath.replaceAll("%20", " "); + filePath = filePath.replace("%20", " "); if ((filePath.indexOf("!") > 0) && (filePath.indexOf(".jar") > 0)) { String jarPath = filePath.substring(0, filePath.indexOf("!")).substring(filePath.indexOf(":") + 1); // WINDOWS HACK @@ -183,4 +183,4 @@ static Set> getFromJARFile(String jar, String packageName) throws IOExc static String stripFilenameExtension(String file) { return file.substring(0, file.lastIndexOf('.')); } -} \ No newline at end of file +} diff --git a/framework/jobs/src/main/java/org/apache/cloudstack/framework/jobs/impl/AsyncJobManagerImpl.java b/framework/jobs/src/main/java/org/apache/cloudstack/framework/jobs/impl/AsyncJobManagerImpl.java index 85ea0245d77b..b85780508f84 100644 --- a/framework/jobs/src/main/java/org/apache/cloudstack/framework/jobs/impl/AsyncJobManagerImpl.java +++ b/framework/jobs/src/main/java/org/apache/cloudstack/framework/jobs/impl/AsyncJobManagerImpl.java @@ -49,6 +49,7 @@ import org.apache.cloudstack.framework.jobs.AsyncJobExecutionContext; import org.apache.cloudstack.framework.jobs.AsyncJobManager; import org.apache.cloudstack.framework.jobs.dao.AsyncJobDao; +import org.apache.cloudstack.framework.jobs.dao.VmWorkJobDao; import org.apache.cloudstack.framework.jobs.dao.AsyncJobJoinMapDao; import org.apache.cloudstack.framework.jobs.dao.AsyncJobJournalDao; import org.apache.cloudstack.framework.jobs.dao.SyncQueueItemDao; @@ -131,6 +132,8 @@ public class AsyncJobManagerImpl extends ManagerBase implements AsyncJobManager, @Inject private VMInstanceDao _vmInstanceDao; @Inject + private VmWorkJobDao _vmWorkJobDao; + @Inject private VolumeDetailsDao _volumeDetailsDao; @Inject private VolumeDao _volsDao; @@ -898,6 +901,9 @@ protected void expungeAsyncJob(final AsyncJobVO job) { Transaction.execute(new TransactionCallbackNoReturn() { @Override public void doInTransactionWithoutResult(TransactionStatus status) { + if ("VmWork".equals(job.getType())) { + _vmWorkJobDao.expunge(job.getId()); + } _jobDao.expunge(job.getId()); // purge corresponding sync queue item _queueMgr.purgeAsyncJobQueueItemId(job.getId()); diff --git a/framework/quota/src/test/java/org/apache/cloudstack/quota/QuotaAlertManagerImplTest.java b/framework/quota/src/test/java/org/apache/cloudstack/quota/QuotaAlertManagerImplTest.java index bf7f126888d4..88485b90145e 100644 --- a/framework/quota/src/test/java/org/apache/cloudstack/quota/QuotaAlertManagerImplTest.java +++ b/framework/quota/src/test/java/org/apache/cloudstack/quota/QuotaAlertManagerImplTest.java @@ -101,7 +101,7 @@ public void testCheckAndSendQuotaAlertEmails() { // Don't test sendQuotaAlert yet Mockito.doNothing().when(quotaAlertManager).sendQuotaAlert(Mockito.any(QuotaAlertManagerImpl.DeferredQuotaEmail.class)); - Mockito.doReturn(true).when(quotaAlertManager).lockAccount(Mockito.anyLong()); + Mockito.lenient().doReturn(true).when(quotaAlertManager).lockAccount(Mockito.anyLong()); // call real method on send monthly statement Mockito.doCallRealMethod().when(quotaAlertManager).checkAndSendQuotaAlertEmails(); diff --git a/framework/quota/src/test/java/org/apache/cloudstack/quota/QuotaManagerImplTest.java b/framework/quota/src/test/java/org/apache/cloudstack/quota/QuotaManagerImplTest.java index c9f6dcd5a3c3..0253fc4ccbec 100644 --- a/framework/quota/src/test/java/org/apache/cloudstack/quota/QuotaManagerImplTest.java +++ b/framework/quota/src/test/java/org/apache/cloudstack/quota/QuotaManagerImplTest.java @@ -16,14 +16,18 @@ // under the License. package org.apache.cloudstack.quota; -import com.cloud.usage.UsageVO; -import com.cloud.usage.dao.UsageDao; -import com.cloud.user.Account; -import com.cloud.user.AccountVO; -import com.cloud.user.dao.AccountDao; -import com.cloud.utils.Pair; -import com.cloud.utils.db.TransactionLegacy; -import junit.framework.TestCase; +import static org.mockito.ArgumentMatchers.nullable; + +import java.lang.reflect.Field; +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.naming.ConfigurationException; + import org.apache.cloudstack.framework.config.dao.ConfigurationDao; import org.apache.cloudstack.quota.dao.QuotaAccountDao; import org.apache.cloudstack.quota.dao.QuotaBalanceDao; @@ -42,14 +46,15 @@ import org.mockito.Spy; import org.mockito.runners.MockitoJUnitRunner; -import javax.naming.ConfigurationException; -import java.lang.reflect.Field; -import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import com.cloud.usage.UsageVO; +import com.cloud.usage.dao.UsageDao; +import com.cloud.user.Account; +import com.cloud.user.AccountVO; +import com.cloud.user.dao.AccountDao; +import com.cloud.utils.Pair; +import com.cloud.utils.db.TransactionLegacy; + +import junit.framework.TestCase; @RunWith(MockitoJUnitRunner.class) public class QuotaManagerImplTest extends TestCase { @@ -163,7 +168,7 @@ public void testUpdateQuotaRecords() { QuotaTariffVO tariffVO = new QuotaTariffVO(); tariffVO.setCurrencyValue(new BigDecimal(1)); - Mockito.when(quotaTariffDao.findTariffPlanByUsageType(Mockito.anyInt(), Mockito.any(Date.class))).thenReturn(tariffVO); + Mockito.when(quotaTariffDao.findTariffPlanByUsageType(nullable(Integer.class), nullable(Date.class))).thenReturn(tariffVO); QuotaUsageVO qu = quotaManager.updateQuotaNetwork(usageVO, UsageTypes.NETWORK_BYTES_SENT); assertTrue(qu.getQuotaUsed().compareTo(BigDecimal.ZERO) > 0); diff --git a/framework/quota/src/test/java/org/apache/cloudstack/quota/QuotaStatementTest.java b/framework/quota/src/test/java/org/apache/cloudstack/quota/QuotaStatementTest.java index e2b5a0abe954..1b28f66b2bb9 100644 --- a/framework/quota/src/test/java/org/apache/cloudstack/quota/QuotaStatementTest.java +++ b/framework/quota/src/test/java/org/apache/cloudstack/quota/QuotaStatementTest.java @@ -16,10 +16,17 @@ // under the License. package org.apache.cloudstack.quota; -import com.cloud.user.AccountVO; -import com.cloud.user.dao.AccountDao; -import com.cloud.utils.db.TransactionLegacy; -import junit.framework.TestCase; +import java.io.UnsupportedEncodingException; +import java.lang.reflect.Field; +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; +import java.util.List; + +import javax.mail.MessagingException; +import javax.naming.ConfigurationException; + import org.apache.cloudstack.framework.config.dao.ConfigurationDao; import org.apache.cloudstack.quota.QuotaStatementImpl.QuotaStatementPeriods; import org.apache.cloudstack.quota.dao.QuotaAccountDao; @@ -33,16 +40,11 @@ import org.mockito.Spy; import org.mockito.runners.MockitoJUnitRunner; -import javax.mail.MessagingException; -import javax.naming.ConfigurationException; +import com.cloud.user.AccountVO; +import com.cloud.user.dao.AccountDao; +import com.cloud.utils.db.TransactionLegacy; -import java.io.UnsupportedEncodingException; -import java.lang.reflect.Field; -import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.Date; -import java.util.List; +import junit.framework.TestCase; @RunWith(MockitoJUnitRunner.class) public class QuotaStatementTest extends TestCase { @@ -230,16 +232,16 @@ public void testSendStatement() throws UnsupportedEncodingException, MessagingEx AccountVO accountVO = new AccountVO(); accountVO.setId(2L); accountVO.setDomainId(1L); - Mockito.when(accountDao.findById(Mockito.anyLong())).thenReturn(accountVO); + Mockito.lenient().when(accountDao.findById(Mockito.anyLong())).thenReturn(accountVO); QuotaAccountVO acc = new QuotaAccountVO(2L); acc.setQuotaBalance(new BigDecimal(404)); acc.setLastStatementDate(null); List accounts = new ArrayList<>(); accounts.add(acc); - Mockito.when(quotaAcc.listAllQuotaAccount()).thenReturn(accounts); + Mockito.lenient().when(quotaAcc.listAllQuotaAccount()).thenReturn(accounts); - Mockito.when(quotaUsage.findTotalQuotaUsage(Mockito.anyLong(), Mockito.anyLong(), Mockito.anyInt(), Mockito.any(Date.class), Mockito.any(Date.class))) + Mockito.lenient().when(quotaUsage.findTotalQuotaUsage(Mockito.anyLong(), Mockito.anyLong(), Mockito.anyInt(), Mockito.any(Date.class), Mockito.any(Date.class))) .thenReturn(new BigDecimal(100)); // call real method on send monthly statement diff --git a/framework/rest/pom.xml b/framework/rest/pom.xml index 384bbf354118..0b3c0964b62c 100644 --- a/framework/rest/pom.xml +++ b/framework/rest/pom.xml @@ -55,6 +55,21 @@ jackson-jaxrs-json-provider ${cs.jackson.version} + + javax.xml.bind + jaxb-api + ${cs.jaxb.version} + + + com.sun.xml.bind + jaxb-core + ${cs.jaxb.version} + + + com.sun.xml.bind + jaxb-impl + ${cs.jaxb.version} + org.apache.cxf cxf-rt-frontend-jaxrs diff --git a/packaging/centos7/cloud.spec b/packaging/centos7/cloud.spec index 2dbc5ec87800..3a0828922fbc 100644 --- a/packaging/centos7/cloud.spec +++ b/packaging/centos7/cloud.spec @@ -38,7 +38,7 @@ Group: System Environment/Libraries Source0: %{name}-%{_maventag}.tgz BuildRoot: %{_tmppath}/%{name}-%{_maventag}-%{release}-build -BuildRequires: java-1.8.0-openjdk-devel +BuildRequires: java-11-openjdk-devel BuildRequires: ws-commons-util BuildRequires: jpackage-utils BuildRequires: gcc @@ -54,7 +54,7 @@ intelligent IaaS cloud implementation. %package management Summary: CloudStack management server UI -Requires: java-1.8.0-openjdk +Requires: java-11-openjdk Requires: python Requires: python3 Requires: bash @@ -68,7 +68,6 @@ Requires: nfs-utils Requires: iproute Requires: wget Requires: mysql -Requires: mysql-connector-java Requires: sudo Requires: /sbin/service Requires: /sbin/chkconfig @@ -79,6 +78,7 @@ Requires: ipmitool Requires: %{name}-common = %{_ver} Requires: iptables-services Requires: qemu-img +Requires: python-dns Group: System Environment/Libraries %description management The CloudStack management server is the central point of coordination, @@ -98,7 +98,7 @@ The Apache CloudStack files shared between agent and management server %package agent Summary: CloudStack Agent for KVM hypervisors Requires: openssh-clients -Requires: java-1.8.0-openjdk +Requires: java-11-openjdk Requires: %{name}-common = %{_ver} Requires: libvirt Requires: bridge-utils @@ -131,8 +131,7 @@ The CloudStack baremetal agent %package usage Summary: CloudStack Usage calculation server -Requires: java-1.8.0-openjdk -Requires: mysql-connector-java +Requires: java-11-openjdk Group: System Environment/Libraries %description usage The CloudStack usage calculation service @@ -165,7 +164,6 @@ Apache CloudStack Marvin integration tests %if "%{_ossnoss}" == "noredist" %package mysql-ha Summary: Apache CloudStack Balancing Strategy for MySQL -Requires: mysql-connector-java Group: System Environmnet/Libraries %description mysql-ha Apache CloudStack Balancing Strategy for MySQL @@ -270,7 +268,7 @@ done ln -sf log4j-cloud.xml ${RPM_BUILD_ROOT}%{_sysconfdir}/%{name}/management/log4j.xml install python/bindir/cloud-external-ipallocator.py ${RPM_BUILD_ROOT}%{_bindir}/%{name}-external-ipallocator.py -install -D client/target/pythonlibs/jasypt-1.9.2.jar ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/lib/jasypt-1.9.2.jar +install -D client/target/pythonlibs/jasypt-1.9.3.jar ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/lib/jasypt-1.9.3.jar install -D packaging/centos7/cloud-ipallocator.rc ${RPM_BUILD_ROOT}%{_initrddir}/%{name}-ipallocator install -D packaging/centos7/cloud.limits ${RPM_BUILD_ROOT}%{_sysconfdir}/security/limits.d/cloud @@ -315,6 +313,7 @@ install -D usage/target/cloud-usage-%{_maventag}.jar ${RPM_BUILD_ROOT}%{_datadir install -D usage/target/transformed/db.properties ${RPM_BUILD_ROOT}%{_sysconfdir}/%{name}/usage/db.properties install -D usage/target/transformed/log4j-cloud_usage.xml ${RPM_BUILD_ROOT}%{_sysconfdir}/%{name}/usage/log4j-cloud.xml cp usage/target/dependencies/* ${RPM_BUILD_ROOT}%{_datadir}/%{name}-usage/lib/ +cp client/target/lib/mysql*jar ${RPM_BUILD_ROOT}%{_datadir}/%{name}-usage/lib/ install -D packaging/systemd/cloudstack-usage.service ${RPM_BUILD_ROOT}%{_unitdir}/%{name}-usage.service install -D packaging/systemd/cloudstack-usage.default ${RPM_BUILD_ROOT}%{_sysconfdir}/default/%{name}-usage mkdir -p ${RPM_BUILD_ROOT}%{_localstatedir}/log/%{name}/usage/ @@ -541,7 +540,7 @@ pip install --upgrade /usr/share/cloudstack-marvin/Marvin-*.tar.gz %attr(0644,root,root) %{python_sitearch}/cloud_utils.py %attr(0644,root,root) %{python_sitearch}/cloud_utils.pyc %attr(0644,root,root) %{python_sitearch}/cloudutils/* -%attr(0644, root, root) %{_datadir}/%{name}-common/lib/jasypt-1.9.2.jar +%attr(0644, root, root) %{_datadir}/%{name}-common/lib/jasypt-1.9.3.jar %{_defaultdocdir}/%{name}-common-%{version}/LICENSE %{_defaultdocdir}/%{name}-common-%{version}/NOTICE diff --git a/plugins/api/rate-limit/src/test/java/org/apache/cloudstack/ratelimit/integration/APITest.java b/plugins/api/rate-limit/src/test/java/org/apache/cloudstack/ratelimit/integration/APITest.java index bfe3468de667..efe8c53a51b1 100644 --- a/plugins/api/rate-limit/src/test/java/org/apache/cloudstack/ratelimit/integration/APITest.java +++ b/plugins/api/rate-limit/src/test/java/org/apache/cloudstack/ratelimit/integration/APITest.java @@ -28,12 +28,11 @@ import java.util.HashMap; import java.util.Iterator; -import com.google.gson.Gson; - import org.apache.cloudstack.api.response.SuccessResponse; import com.cloud.api.ApiGsonHelper; import com.cloud.utils.exception.CloudRuntimeException; +import com.google.gson.Gson; /** * Base class for API Test diff --git a/plugins/api/vmware-sioc/pom.xml b/plugins/api/vmware-sioc/pom.xml index 9dc5d7875877..e6d77c89e65c 100644 --- a/plugins/api/vmware-sioc/pom.xml +++ b/plugins/api/vmware-sioc/pom.xml @@ -33,6 +33,12 @@ cloud-plugin-hypervisor-vmware ${project.version} + + com.sun.xml.ws + jaxws-ri + ${cs.jaxws.version} + pom + diff --git a/plugins/ca/root-ca/src/test/java/org/apache/cloudstack/ca/provider/RootCAProviderTest.java b/plugins/ca/root-ca/src/test/java/org/apache/cloudstack/ca/provider/RootCAProviderTest.java index d5d64289da28..305d18fe8c4e 100644 --- a/plugins/ca/root-ca/src/test/java/org/apache/cloudstack/ca/provider/RootCAProviderTest.java +++ b/plugins/ca/root-ca/src/test/java/org/apache/cloudstack/ca/provider/RootCAProviderTest.java @@ -41,7 +41,7 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.runners.MockitoJUnitRunner; +import org.mockito.junit.MockitoJUnitRunner; @RunWith(MockitoJUnitRunner.class) public class RootCAProviderTest { @@ -135,7 +135,7 @@ public void testRevokeCertificate() throws Exception { public void testCreateSSLEngineWithoutAuthStrictness() throws Exception { overrideDefaultConfigValue(RootCAProvider.rootCAAuthStrictness, "_defaultValue", "false"); final SSLEngine e = provider.createSSLEngine(SSLUtils.getSSLContext(), "/1.2.3.4:5678", null); - Assert.assertFalse(e.getUseClientMode()); + Assert.assertTrue(e.getUseClientMode()); Assert.assertFalse(e.getNeedClientAuth()); } @@ -143,7 +143,7 @@ public void testCreateSSLEngineWithoutAuthStrictness() throws Exception { public void testCreateSSLEngineWithAuthStrictness() throws Exception { overrideDefaultConfigValue(RootCAProvider.rootCAAuthStrictness, "_defaultValue", "true"); final SSLEngine e = provider.createSSLEngine(SSLUtils.getSSLContext(), "/1.2.3.4:5678", null); - Assert.assertFalse(e.getUseClientMode()); + Assert.assertTrue(e.getUseClientMode()); Assert.assertTrue(e.getNeedClientAuth()); } diff --git a/plugins/database/mysql-ha/src/main/java/com/cloud/utils/db/StaticStrategy.java b/plugins/database/mysql-ha/src/main/java/com/cloud/utils/db/StaticStrategy.java index 6b0cb24878af..b3536523a06e 100644 --- a/plugins/database/mysql-ha/src/main/java/com/cloud/utils/db/StaticStrategy.java +++ b/plugins/database/mysql-ha/src/main/java/com/cloud/utils/db/StaticStrategy.java @@ -16,20 +16,20 @@ // under the License. package com.cloud.utils.db; +import java.lang.reflect.InvocationHandler; import java.sql.SQLException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Properties; import org.apache.log4j.Logger; -import com.mysql.jdbc.BalanceStrategy; -import com.mysql.jdbc.Connection; -import com.mysql.jdbc.ConnectionImpl; -import com.mysql.jdbc.LoadBalancingConnectionProxy; -import com.mysql.jdbc.SQLError; +import com.mysql.cj.jdbc.ConnectionImpl; +import com.mysql.cj.jdbc.JdbcConnection; +import com.mysql.cj.jdbc.exceptions.SQLError; +import com.mysql.cj.jdbc.ha.BalanceStrategy; +import com.mysql.cj.jdbc.ha.LoadBalancedConnectionProxy; public class StaticStrategy implements BalanceStrategy { private static final Logger s_logger = Logger.getLogger(StaticStrategy.class); @@ -38,18 +38,8 @@ public StaticStrategy() { } @Override - public void destroy() { - // we don't have anything to clean up - } - - @Override - public void init(Connection conn, Properties props) throws SQLException { - // we don't have anything to initialize - } - - @Override - public ConnectionImpl pickConnection(LoadBalancingConnectionProxy proxy, List configuredHosts, Map liveConnections, - long[] responseTimes, int numRetries) throws SQLException { + public JdbcConnection pickConnection(InvocationHandler proxy, List configuredHosts, Map liveConnections, + long[] responseTimes, int numRetries) throws SQLException { int numHosts = configuredHosts.size(); SQLException ex = null; @@ -57,7 +47,7 @@ public ConnectionImpl pickConnection(LoadBalancingConnectionProxy proxy, List whiteList = new ArrayList(numHosts); whiteList.addAll(configuredHosts); - Map blackList = proxy.getGlobalBlacklist(); + Map blackList = ((LoadBalancedConnectionProxy) proxy).getGlobalBlacklist(); whiteList.removeAll(blackList.keySet()); @@ -70,15 +60,15 @@ public ConnectionImpl pickConnection(LoadBalancingConnectionProxy proxy, List(numHosts); whiteList.addAll(configuredHosts); - blackList = proxy.getGlobalBlacklist(); + blackList = ((LoadBalancedConnectionProxy) proxy).getGlobalBlacklist(); whiteList.removeAll(blackList.keySet()); whiteListMap = this.getArrayIndexMap(whiteList); @@ -126,10 +116,9 @@ public ConnectionImpl pickConnection(LoadBalancingConnectionProxy proxy, List getArrayIndexMap(List l) { Map m = new HashMap(l.size()); for (int i = 0; i < l.size(); i++) { - m.put(l.get(i), Integer.valueOf(i)); + m.put(l.get(i), i); } return m; } - } \ No newline at end of file diff --git a/plugins/database/quota/src/test/java/org/apache/cloudstack/api/command/QuotaBalanceCmdTest.java b/plugins/database/quota/src/test/java/org/apache/cloudstack/api/command/QuotaBalanceCmdTest.java index 4369a8c9f0cd..07181c12cef5 100644 --- a/plugins/database/quota/src/test/java/org/apache/cloudstack/api/command/QuotaBalanceCmdTest.java +++ b/plugins/database/quota/src/test/java/org/apache/cloudstack/api/command/QuotaBalanceCmdTest.java @@ -16,7 +16,11 @@ // under the License. package org.apache.cloudstack.api.command; -import junit.framework.TestCase; +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + import org.apache.cloudstack.api.response.QuotaBalanceResponse; import org.apache.cloudstack.api.response.QuotaResponseBuilder; import org.apache.cloudstack.quota.vo.QuotaBalanceVO; @@ -26,10 +30,7 @@ import org.mockito.Mockito; import org.mockito.runners.MockitoJUnitRunner; -import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; +import junit.framework.TestCase; @RunWith(MockitoJUnitRunner.class) public class QuotaBalanceCmdTest extends TestCase { @@ -48,7 +49,7 @@ public void testQuotaBalanceCmd() throws NoSuchFieldException, IllegalAccessExce Mockito.when(responseBuilder.getQuotaBalance(Mockito.any(cmd.getClass()))).thenReturn(quotaBalanceVOList); Mockito.when(responseBuilder.createQuotaLastBalanceResponse(Mockito.eq(quotaBalanceVOList), Mockito.any(Date.class))).thenReturn(new QuotaBalanceResponse()); Mockito.when(responseBuilder.createQuotaBalanceResponse(Mockito.eq(quotaBalanceVOList), Mockito.any(Date.class), Mockito.any(Date.class))).thenReturn(new QuotaBalanceResponse()); - Mockito.when(responseBuilder.startOfNextDay(Mockito.any(Date.class))).thenReturn(new Date()); + Mockito.lenient().when(responseBuilder.startOfNextDay(Mockito.any(Date.class))).thenReturn(new Date()); // end date not specified cmd.setStartDate(new Date()); diff --git a/plugins/database/quota/src/test/java/org/apache/cloudstack/api/command/QuotaCreditsCmdTest.java b/plugins/database/quota/src/test/java/org/apache/cloudstack/api/command/QuotaCreditsCmdTest.java index 1f22508d81d2..06dd57ad41d3 100644 --- a/plugins/database/quota/src/test/java/org/apache/cloudstack/api/command/QuotaCreditsCmdTest.java +++ b/plugins/database/quota/src/test/java/org/apache/cloudstack/api/command/QuotaCreditsCmdTest.java @@ -16,10 +16,12 @@ // under the License. package org.apache.cloudstack.api.command; -import com.cloud.user.AccountService; -import com.cloud.user.AccountVO; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.anyDouble; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.ArgumentMatchers.nullable; -import junit.framework.TestCase; +import java.lang.reflect.Field; import org.apache.cloudstack.api.ApiErrorCode; import org.apache.cloudstack.api.BaseCmd; @@ -27,13 +29,17 @@ import org.apache.cloudstack.api.response.QuotaCreditsResponse; import org.apache.cloudstack.api.response.QuotaResponseBuilder; import org.apache.cloudstack.quota.QuotaService; +import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.Mockito; -import org.mockito.runners.MockitoJUnitRunner; +import org.mockito.junit.MockitoJUnitRunner; -import java.lang.reflect.Field; +import com.cloud.user.AccountService; +import com.cloud.user.AccountVO; + +import junit.framework.TestCase; @RunWith(MockitoJUnitRunner.class) public class QuotaCreditsCmdTest extends TestCase { @@ -44,9 +50,16 @@ public class QuotaCreditsCmdTest extends TestCase { @Mock AccountService accountService; + private QuotaCreditsCmd cmd; + + @Override + @Before + public void setUp() { + cmd = new QuotaCreditsCmd(); + } + @Test public void testQuotaCreditsCmd() throws NoSuchFieldException, IllegalAccessException { - QuotaCreditsCmd cmd = new QuotaCreditsCmd(); cmd.setAccountName("admin"); cmd.setMinBalance(200.0); @@ -64,8 +77,10 @@ public void testQuotaCreditsCmd() throws NoSuchFieldException, IllegalAccessExce AccountVO acc = new AccountVO(); acc.setId(2L); - Mockito.when(accountService.getActiveAccountByName(Mockito.anyString(), Mockito.anyLong())).thenReturn(acc); - Mockito.when(responseBuilder.addQuotaCredits(Mockito.anyLong(), Mockito.anyLong(), Mockito.anyDouble(), Mockito.anyLong(), Mockito.anyBoolean())).thenReturn(new QuotaCreditsResponse()); + + Mockito.when(accountService.getActiveAccountByName(nullable(String.class), nullable(Long.class))).thenReturn(acc); + + Mockito.when(responseBuilder.addQuotaCredits(nullable(Long.class), nullable(Long.class), nullable(Double.class), nullable(Long.class), nullable(Boolean.class))).thenReturn(new QuotaCreditsResponse()); // No value provided test try { @@ -77,11 +92,9 @@ public void testQuotaCreditsCmd() throws NoSuchFieldException, IllegalAccessExce // With value provided test cmd.setValue(11.80); cmd.execute(); - Mockito.verify(quotaService, Mockito.times(0)).setLockAccount(Mockito.anyLong(), Mockito.anyBoolean()); - Mockito.verify(quotaService, Mockito.times(1)).setMinBalance(Mockito.anyLong(), Mockito.anyDouble()); - Mockito.verify(responseBuilder, Mockito.times(1)).addQuotaCredits(Mockito.anyLong(), Mockito.anyLong(), Mockito.anyDouble(), Mockito.anyLong(), Mockito.anyBoolean()); - - + Mockito.verify(quotaService, Mockito.times(0)).setLockAccount(anyLong(), anyBoolean()); + Mockito.verify(quotaService, Mockito.times(1)).setMinBalance(anyLong(), anyDouble()); + Mockito.verify(responseBuilder, Mockito.times(1)).addQuotaCredits(nullable(Long.class), nullable(Long.class), nullable(Double.class), nullable(Long.class), nullable(Boolean.class)); } } diff --git a/plugins/database/quota/src/test/java/org/apache/cloudstack/api/response/QuotaResponseBuilderImplTest.java b/plugins/database/quota/src/test/java/org/apache/cloudstack/api/response/QuotaResponseBuilderImplTest.java index de961f63b208..7c304f01ce42 100644 --- a/plugins/database/quota/src/test/java/org/apache/cloudstack/api/response/QuotaResponseBuilderImplTest.java +++ b/plugins/database/quota/src/test/java/org/apache/cloudstack/api/response/QuotaResponseBuilderImplTest.java @@ -217,7 +217,7 @@ public void testCreateQuotaLastBalanceResponse() { entry.setCreditBalance(new BigDecimal(100)); quotaBalance.add(entry); quotaBalance.add(entry); - Mockito.when(quotaService.computeAdjustedTime(Mockito.any(Date.class))).thenReturn(new Date()); + Mockito.lenient().when(quotaService.computeAdjustedTime(Mockito.any(Date.class))).thenReturn(new Date()); QuotaBalanceResponse resp = quotaResponseBuilder.createQuotaLastBalanceResponse(quotaBalance, null); assertTrue(resp.getStartQuota().compareTo(new BigDecimal(200)) == 0); } diff --git a/plugins/dedicated-resources/src/test/java/org/apache/cloudstack/dedicated/manager/DedicatedApiUnitTest.java b/plugins/dedicated-resources/src/test/java/org/apache/cloudstack/dedicated/manager/DedicatedApiUnitTest.java index 12e71bac5872..c8fb258f2192 100644 --- a/plugins/dedicated-resources/src/test/java/org/apache/cloudstack/dedicated/manager/DedicatedApiUnitTest.java +++ b/plugins/dedicated-resources/src/test/java/org/apache/cloudstack/dedicated/manager/DedicatedApiUnitTest.java @@ -16,9 +16,9 @@ // under the License. package org.apache.cloudstack.dedicated.manager; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.Matchers.anyLong; -import static org.mockito.Matchers.anyObject; -import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.when; import java.io.IOException; @@ -26,10 +26,11 @@ import javax.inject.Inject; -import com.cloud.user.User; -import junit.framework.Assert; - +import org.apache.cloudstack.affinity.AffinityGroupService; +import org.apache.cloudstack.affinity.dao.AffinityGroupDao; +import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.dedicated.DedicatedResourceManagerImpl; +import org.apache.cloudstack.framework.config.dao.ConfigurationDao; import org.apache.cloudstack.test.utils.SpringUtils; import org.apache.log4j.Logger; import org.junit.After; @@ -49,11 +50,6 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.support.AnnotationConfigContextLoader; -import org.apache.cloudstack.affinity.AffinityGroupService; -import org.apache.cloudstack.affinity.dao.AffinityGroupDao; -import org.apache.cloudstack.context.CallContext; -import org.apache.cloudstack.framework.config.dao.ConfigurationDao; - import com.cloud.dc.DedicatedResourceVO; import com.cloud.dc.dao.ClusterDao; import com.cloud.dc.dao.DataCenterDao; @@ -66,12 +62,15 @@ import com.cloud.user.Account; import com.cloud.user.AccountManager; import com.cloud.user.AccountVO; +import com.cloud.user.User; import com.cloud.user.UserVO; import com.cloud.user.dao.AccountDao; import com.cloud.utils.component.ComponentContext; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.vm.dao.UserVmDao; +import junit.framework.Assert; + @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(loader = AnnotationConfigContextLoader.class) public class DedicatedApiUnitTest { @@ -122,7 +121,7 @@ public void setUp() { UserVO user = new UserVO(1, "testuser", "password", "firstname", "lastName", "email", "timezone", UUID.randomUUID().toString(), User.Source.UNKNOWN); CallContext.register(user, account); - when(_acctMgr.finalizeOwner((Account)anyObject(), anyString(), anyLong(), anyLong())).thenReturn(account); + when(_acctMgr.finalizeOwner(any(Account.class), nullable(String.class), nullable(Long.class), nullable(Long.class))).thenReturn(account); when(_accountDao.findByIdIncludingRemoved(0L)).thenReturn(account); when(_accountDao.findById(anyLong())).thenReturn(account); when(_domainDao.findById(domainId)).thenReturn(domain); diff --git a/plugins/hypervisors/baremetal/pom.xml b/plugins/hypervisors/baremetal/pom.xml index 66f468e2f8d5..c7537a909717 100755 --- a/plugins/hypervisors/baremetal/pom.xml +++ b/plugins/hypervisors/baremetal/pom.xml @@ -32,5 +32,20 @@ commons-lang commons-lang + + javax.xml.bind + jaxb-api + ${cs.jaxb.version} + + + com.sun.xml.bind + jaxb-core + ${cs.jaxb.version} + + + com.sun.xml.bind + jaxb-impl + ${cs.jaxb.version} + diff --git a/plugins/hypervisors/baremetal/src/main/java/com/cloud/baremetal/networkservice/BareMetalResourceBase.java b/plugins/hypervisors/baremetal/src/main/java/com/cloud/baremetal/networkservice/BareMetalResourceBase.java index 65fea0928935..74360fe9cb58 100644 --- a/plugins/hypervisors/baremetal/src/main/java/com/cloud/baremetal/networkservice/BareMetalResourceBase.java +++ b/plugins/hypervisors/baremetal/src/main/java/com/cloud/baremetal/networkservice/BareMetalResourceBase.java @@ -22,6 +22,17 @@ // Automatically generated by addcopyright.py at 04/03/2012 package com.cloud.baremetal.networkservice; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +import javax.naming.ConfigurationException; + +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.framework.config.dao.ConfigurationDao; +import org.apache.log4j.Logger; + import com.cloud.agent.IAgentControl; import com.cloud.agent.api.Answer; import com.cloud.agent.api.CheckNetworkAnswer; @@ -70,15 +81,6 @@ import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachine.PowerState; import com.cloud.vm.dao.VMInstanceDao; -import org.apache.cloudstack.api.ApiConstants; -import org.apache.cloudstack.framework.config.dao.ConfigurationDao; -import org.apache.log4j.Logger; - -import javax.naming.ConfigurationException; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.TimeUnit; public class BareMetalResourceBase extends ManagerBase implements ServerResource { private static final Logger s_logger = Logger.getLogger(BareMetalResourceBase.class); diff --git a/plugins/hypervisors/hyperv/src/main/java/com/cloud/hypervisor/hyperv/resource/HypervDirectConnectResource.java b/plugins/hypervisors/hyperv/src/main/java/com/cloud/hypervisor/hyperv/resource/HypervDirectConnectResource.java index 979be732f2bb..038661b58adf 100644 --- a/plugins/hypervisors/hyperv/src/main/java/com/cloud/hypervisor/hyperv/resource/HypervDirectConnectResource.java +++ b/plugins/hypervisors/hyperv/src/main/java/com/cloud/hypervisor/hyperv/resource/HypervDirectConnectResource.java @@ -2085,6 +2085,11 @@ protected Answer execute(final SetMonitorServiceCommand cmd) { final String controlIp = getRouterSshControlIp(cmd); final String config = cmd.getConfiguration(); + if (org.apache.commons.lang.StringUtils.isBlank(config)) { + s_logger.error("SetMonitorServiceCommand should have config for this case"); + return new Answer(cmd, false, "SetMonitorServiceCommand failed due to missing config"); + } + final String args = String.format(" %s %s", "-c", config); final String command = String.format("%s%s %s", "/opt/cloud/bin/", VRScripts.MONITOR_SERVICE, args); diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java index 76db243ee6b7..c7506f57c406 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java @@ -103,9 +103,11 @@ import com.cloud.agent.api.to.NfsTO; import com.cloud.agent.api.to.NicTO; import com.cloud.agent.api.to.VirtualMachineTO; +import com.cloud.agent.dao.impl.PropertiesStorage; import com.cloud.agent.resource.virtualnetwork.VRScripts; import com.cloud.agent.resource.virtualnetwork.VirtualRouterDeployer; import com.cloud.agent.resource.virtualnetwork.VirtualRoutingResource; +import com.cloud.agent.api.SecurityGroupRulesCmd; import com.cloud.dc.Vlan; import com.cloud.exception.InternalErrorException; import com.cloud.host.Host.Type; @@ -140,11 +142,13 @@ import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.WatchDogDef.WatchDogModel; import com.cloud.hypervisor.kvm.resource.wrapper.LibvirtRequestWrapper; import com.cloud.hypervisor.kvm.resource.wrapper.LibvirtUtilitiesHelper; +import com.cloud.hypervisor.kvm.storage.IscsiStorageCleanupMonitor; import com.cloud.hypervisor.kvm.storage.KVMPhysicalDisk; import com.cloud.hypervisor.kvm.storage.KVMStoragePool; import com.cloud.hypervisor.kvm.storage.KVMStoragePoolManager; import com.cloud.hypervisor.kvm.storage.KVMStorageProcessor; import com.cloud.network.Networks.BroadcastDomainType; +import com.cloud.network.Networks.IsolationType; import com.cloud.network.Networks.RouterPrivateIpStrategy; import com.cloud.network.Networks.TrafficType; import com.cloud.resource.RequestWrapper; @@ -1094,6 +1098,28 @@ public boolean configure(final String name, final Map params) th storageProcessor.configure(name, params); storageHandler = new StorageSubsystemCommandHandlerBase(storageProcessor); + IscsiStorageCleanupMonitor isciCleanupMonitor = new IscsiStorageCleanupMonitor(); + final Thread cleanupMonitor = new Thread(isciCleanupMonitor); + cleanupMonitor.start(); + + return true; + } + + public boolean configureHostParams(final Map params) { + final File file = PropertiesUtil.findConfigFile("agent.properties"); + if (file == null) { + s_logger.error("Unable to find the file agent.properties"); + return false; + } + // Save configurations in agent.properties + PropertiesStorage storage = new PropertiesStorage(); + storage.configure("Storage", new HashMap()); + if (params.get("router.aggregation.command.each.timeout") != null) { + String value = (String)params.get("router.aggregation.command.each.timeout"); + Integer intValue = NumbersUtil.parseInt(value, 600); + storage.persist("router.aggregation.command.each.timeout", String.valueOf(intValue)); + } + return true; } @@ -2962,7 +2988,7 @@ private HashMap getHostVmStateReport(final Conne return vmStates; } - public String rebootVM(final Connect conn, final String vmName) { + public String rebootVM(final Connect conn, final String vmName) throws LibvirtException{ Domain dm = null; String msg = null; try { @@ -2979,7 +3005,7 @@ public String rebootVM(final Connect conn, final String vmName) { final int vnetId = Integer.parseInt(nic.getBrName().replaceFirst("cloudVirBr", "")); final String pifName = getPif(_guestBridgeName); final String newBrName = "br" + pifName + "-" + vnetId; - vmDef = vmDef.replaceAll("'" + nic.getBrName() + "'", "'" + newBrName + "'"); + vmDef = vmDef.replace("'" + nic.getBrName() + "'", "'" + newBrName + "'"); s_logger.debug("VM bridge name is changed from " + nic.getBrName() + " to " + newBrName); } catch (final NumberFormatException e) { continue; @@ -3543,7 +3569,117 @@ public boolean destroyNetworkRulesForVM(final Connect conn, final String vmName) return true; } - public boolean defaultNetworkRules(final Connect conn, final String vmName, final NicTO nic, final Long vmId, final String secIpStr) { + /** + * Function to destroy the security group rules applied to the nic's + * @param conn + * @param vmName + * @param nic + * @return + * true : If success + * false : If failure + */ + public boolean destroyNetworkRulesForNic(final Connect conn, final String vmName, final NicTO nic) { + if (!_canBridgeFirewall) { + return false; + } + final List nicSecIps = nic.getNicSecIps(); + String secIpsStr; + final StringBuilder sb = new StringBuilder(); + if (nicSecIps != null) { + for (final String ip : nicSecIps) { + sb.append(ip).append(SecurityGroupRulesCmd.RULE_COMMAND_SEPARATOR); + } + secIpsStr = sb.toString(); + } else { + secIpsStr = "0" + SecurityGroupRulesCmd.RULE_COMMAND_SEPARATOR; + } + final List intfs = getInterfaces(conn, vmName); + if (intfs.size() == 0 || intfs.size() < nic.getDeviceId()) { + return false; + } + + final InterfaceDef intf = intfs.get(nic.getDeviceId()); + final String brname = intf.getBrName(); + final String vif = intf.getDevName(); + + final Script cmd = new Script(_securityGroupPath, _timeout, s_logger); + cmd.add("destroy_network_rules_for_vm"); + cmd.add("--vmname", vmName); + if (nic.getIp() != null) { + cmd.add("--vmip", nic.getIp()); + } + cmd.add("--vmmac", nic.getMac()); + cmd.add("--vif", vif); + cmd.add("--nicsecips", secIpsStr); + + final String result = cmd.execute(); + if (result != null) { + return false; + } + return true; + } + + /** + * Function to apply default network rules for a VM + * @param conn + * @param vm + * @param checkBeforeApply + * @return + */ + public boolean applyDefaultNetworkRules(final Connect conn, final VirtualMachineTO vm, final boolean checkBeforeApply) { + NicTO[] nicTOs = new NicTO[] {}; + if (vm != null && vm.getNics() != null) { + s_logger.debug("Checking default network rules for vm " + vm.getName()); + nicTOs = vm.getNics(); + } + for (NicTO nic : nicTOs) { + if (vm.getType() != VirtualMachine.Type.User) { + nic.setPxeDisable(true); + } + } + boolean isFirstNic = true; + for (final NicTO nic : nicTOs) { + if (nic.isSecurityGroupEnabled() || nic.getIsolationUri() != null && nic.getIsolationUri().getScheme().equalsIgnoreCase(IsolationType.Ec2.toString())) { + if (vm.getType() != VirtualMachine.Type.User) { + configureDefaultNetworkRulesForSystemVm(conn, vm.getName()); + break; + } + if (!applyDefaultNetworkRulesOnNic(conn, vm.getName(), vm.getId(), nic, isFirstNic, checkBeforeApply)) { + s_logger.error("Unable to apply default network rule for nic " + nic.getName() + " for VM " + vm.getName()); + return false; + } + isFirstNic = false; + } + } + return true; + } + + /** + * Function to apply default network rules for a NIC + * @param conn + * @param vmName + * @param vmId + * @param nic + * @param isFirstNic + * @param checkBeforeApply + * @return + */ + public boolean applyDefaultNetworkRulesOnNic(final Connect conn, final String vmName, final Long vmId, final NicTO nic, boolean isFirstNic, boolean checkBeforeApply) { + final List nicSecIps = nic.getNicSecIps(); + String secIpsStr; + final StringBuilder sb = new StringBuilder(); + if (nicSecIps != null) { + for (final String ip : nicSecIps) { + sb.append(ip).append(SecurityGroupRulesCmd.RULE_COMMAND_SEPARATOR); + } + secIpsStr = sb.toString(); + } else { + secIpsStr = "0" + SecurityGroupRulesCmd.RULE_COMMAND_SEPARATOR; + } + return defaultNetworkRules(conn, vmName, nic, vmId, secIpsStr, isFirstNic, checkBeforeApply); + } + + public boolean defaultNetworkRules(final Connect conn, final String vmName, final NicTO nic, final Long vmId, final String secIpStr, final boolean isFirstNic, final boolean checkBeforeApply) { if (!_canBridgeFirewall) { return false; } @@ -3571,6 +3707,12 @@ public boolean defaultNetworkRules(final Connect conn, final String vmName, fina cmd.add("--vif", vif); cmd.add("--brname", brname); cmd.add("--nicsecips", secIpStr); + if (isFirstNic) { + cmd.add("--isFirstNic"); + } + if (checkBeforeApply) { + cmd.add("--check"); + } final String result = cmd.execute(); if (result != null) { return false; @@ -3660,7 +3802,7 @@ public boolean addNetworkRules(final String vmName, final String vmId, final Str return true; } - public boolean configureNetworkRulesVMSecondaryIP(final Connect conn, final String vmName, final String secIp, final String action) { + public boolean configureNetworkRulesVMSecondaryIP(final Connect conn, final String vmName, final String vmMac, final String secIp, final String action) { if (!_canBridgeFirewall) { return false; @@ -3669,6 +3811,7 @@ public boolean configureNetworkRulesVMSecondaryIP(final Connect conn, final Stri final Script cmd = new Script(_securityGroupPath, _timeout, s_logger); cmd.add("network_rules_vmSecondaryIp"); cmd.add("--vmname", vmName); + cmd.add("--vmmac", vmMac); cmd.add("--nicsecips", secIp); cmd.add("--action=" + action); diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtNetworkRulesVmSecondaryIpCommandWrapper.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtNetworkRulesVmSecondaryIpCommandWrapper.java index 1ad5cb459cfb..07c091ee0eee 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtNetworkRulesVmSecondaryIpCommandWrapper.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtNetworkRulesVmSecondaryIpCommandWrapper.java @@ -41,11 +41,11 @@ public Answer execute(final NetworkRulesVmSecondaryIpCommand command, final Libv final LibvirtUtilitiesHelper libvirtUtilitiesHelper = libvirtComputingResource.getLibvirtUtilitiesHelper(); final Connect conn = libvirtUtilitiesHelper.getConnectionByVmName(command.getVmName()); - result = libvirtComputingResource.configureNetworkRulesVMSecondaryIP(conn, command.getVmName(), command.getVmSecIp(), command.getAction()); + result = libvirtComputingResource.configureNetworkRulesVMSecondaryIP(conn, command.getVmName(), command.getVmMac(), command.getVmSecIp(), command.getAction()); } catch (final LibvirtException e) { s_logger.debug("Could not configure VM secondary IP! => " + e.getLocalizedMessage()); } return new Answer(command, result, ""); } -} \ No newline at end of file +} diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtPlugNicCommandWrapper.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtPlugNicCommandWrapper.java index 1ef32afccbfc..553a71a30dfe 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtPlugNicCommandWrapper.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtPlugNicCommandWrapper.java @@ -29,6 +29,7 @@ import com.cloud.hypervisor.kvm.resource.VifDriver; import com.cloud.resource.CommandWrapper; import com.cloud.resource.ResourceWrapper; +import com.cloud.vm.VirtualMachine; import org.apache.log4j.Logger; import org.libvirt.Connect; import org.libvirt.Domain; @@ -45,6 +46,7 @@ public final class LibvirtPlugNicCommandWrapper extends CommandWrapper params = command.getParams(); boolean success = libvirtComputingResource.getVirtRouterResource().configureHostParams(params); + success = success && libvirtComputingResource.configureHostParams(params); if (!success) { return new Answer(command, false, "Failed to set host parameters"); diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtStartCommandWrapper.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtStartCommandWrapper.java index 9c97bd4770fc..068b24e3d54c 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtStartCommandWrapper.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtStartCommandWrapper.java @@ -20,7 +20,6 @@ package com.cloud.hypervisor.kvm.resource.wrapper; import java.net.URISyntaxException; -import java.util.List; import org.apache.log4j.Logger; import org.libvirt.Connect; @@ -37,7 +36,6 @@ import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource; import com.cloud.hypervisor.kvm.resource.LibvirtVMDef; import com.cloud.hypervisor.kvm.storage.KVMStoragePoolManager; -import com.cloud.network.Networks.IsolationType; import com.cloud.network.Networks.TrafficType; import com.cloud.resource.CommandWrapper; import com.cloud.resource.ResourceWrapper; @@ -83,32 +81,12 @@ public Answer execute(final StartCommand command, final LibvirtComputingResource s_logger.debug("starting " + vmName + ": " + vm.toString()); libvirtComputingResource.startVM(conn, vmName, vm.toString()); - for (final NicTO nic : nics) { - if (nic.isSecurityGroupEnabled() || nic.getIsolationUri() != null && nic.getIsolationUri().getScheme().equalsIgnoreCase(IsolationType.Ec2.toString())) { - if (vmSpec.getType() != VirtualMachine.Type.User) { - libvirtComputingResource.configureDefaultNetworkRulesForSystemVm(conn, vmName); - break; - } else { - final List nicSecIps = nic.getNicSecIps(); - String secIpsStr; - final StringBuilder sb = new StringBuilder(); - if (nicSecIps != null) { - for (final String ip : nicSecIps) { - sb.append(ip).append(";"); - } - secIpsStr = sb.toString(); - } else { - secIpsStr = "0;"; - } - libvirtComputingResource.defaultNetworkRules(conn, vmName, nic, vmSpec.getId(), secIpsStr); - } - } - } + libvirtComputingResource.applyDefaultNetworkRules(conn, vmSpec, false); // pass cmdline info to system vms if (vmSpec.getType() != VirtualMachine.Type.User) { String controlIp = null; - for (final NicTO nic : nics) { + for (final NicTO nic : vmSpec.getNics()) { if (nic.getType() == TrafficType.Control) { controlIp = nic.getIp(); break; diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtUnPlugNicCommandWrapper.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtUnPlugNicCommandWrapper.java index 57f4083c96ff..071352c5c9a0 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtUnPlugNicCommandWrapper.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtUnPlugNicCommandWrapper.java @@ -55,6 +55,9 @@ public Answer execute(final UnPlugNicCommand command, final LibvirtComputingReso for (final InterfaceDef pluggedNic : pluggedNics) { if (pluggedNic.getMacAddress().equalsIgnoreCase(nic.getMac())) { + if (nic.isSecurityGroupEnabled()) { + libvirtComputingResource.destroyNetworkRulesForNic(conn, vmName, nic); + } vm.detachDevice(pluggedNic.toString()); // We don't know which "traffic type" is associated with // each interface at this point, so inform all vif drivers @@ -79,4 +82,4 @@ public Answer execute(final UnPlugNicCommand command, final LibvirtComputingReso } } } -} \ No newline at end of file +} diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/IscsiStorageCleanupMonitor.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/IscsiStorageCleanupMonitor.java new file mode 100644 index 000000000000..e5ce6bbd9ac6 --- /dev/null +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/IscsiStorageCleanupMonitor.java @@ -0,0 +1,173 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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. +package com.cloud.hypervisor.kvm.storage; + +import com.cloud.hypervisor.kvm.resource.LibvirtConnection; +import com.cloud.hypervisor.kvm.resource.LibvirtDomainXMLParser; +import com.cloud.hypervisor.kvm.resource.LibvirtVMDef; +import org.apache.cloudstack.managed.context.ManagedContextRunnable; +import org.apache.log4j.Logger; +import org.libvirt.Connect; +import org.libvirt.Domain; +import org.libvirt.LibvirtException; + +import java.io.File; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class IscsiStorageCleanupMonitor implements Runnable{ + private static final Logger s_logger = Logger.getLogger(IscsiStorageCleanupMonitor.class); + private static final int CLEANUP_INTERVAL_SEC = 60; // check every X seconds + private static final String ISCSI_PATH_PREFIX = "/dev/disk/by-path"; + private static final String KEYWORD_ISCSI = "iscsi"; + private static final String KEYWORD_IQN = "iqn"; + + private IscsiAdmStorageAdaptor iscsiStorageAdaptor; + + private Map diskStatusMap; + + public IscsiStorageCleanupMonitor() { + diskStatusMap = new HashMap<>(); + s_logger.debug("Initialize cleanup thread"); + iscsiStorageAdaptor = new IscsiAdmStorageAdaptor(); + } + + + private class Monitor extends ManagedContextRunnable { + + @Override + protected void runInContext() { + Connect conn = null; + try { + conn = LibvirtConnection.getConnection(); + + //populate all the iscsi disks currently attached to this host + File[] iscsiVolumes = new File(ISCSI_PATH_PREFIX).listFiles(); + if (iscsiVolumes == null || iscsiVolumes.length == 0) { + s_logger.debug("No iscsi sessions found for cleanup"); + return; + } + + // set all status values to false + initializeDiskStatusMap(iscsiVolumes); + + // check if iscsi sessions belong to any VM + updateDiskStatusMapWithInactiveIscsiSessions(conn); + + // disconnect stale iscsi sessions + disconnectInactiveSessions(); + + } catch (LibvirtException e) { + s_logger.warn("[ignored] Error trying to cleanup ", e); + } + } + + private boolean isIscsiDisk(String path) { + return path.startsWith(ISCSI_PATH_PREFIX) && path.contains(KEYWORD_ISCSI) && path.contains(KEYWORD_IQN); + } + + /** + * for each volume if the volume is path is of type iscsi, add to diskstatusmap and set status to false. + * @param iscsiVolumes + */ + private void initializeDiskStatusMap(File[] iscsiVolumes){ + diskStatusMap.clear(); + for( File v : iscsiVolumes) { + if (isIscsiDisk(v.getAbsolutePath())) { + s_logger.debug("found iscsi disk by cleanup thread, marking inactive: " + v.getAbsolutePath()); + diskStatusMap.put(v.getAbsolutePath(), false); + } + } + } + + /** Loop over list of VMs or domains, get disks, if disk is in diskStatusMap, set status value to true. + * + * @param conn + */ + private void updateDiskStatusMapWithInactiveIscsiSessions(Connect conn){ + try { + int[] domains = conn.listDomains(); + s_logger.debug(String.format("found %d domains", domains.length)); + for (int domId : domains) { + Domain dm = conn.domainLookupByID(domId); + final String domXml = dm.getXMLDesc(0); + final LibvirtDomainXMLParser parser = new LibvirtDomainXMLParser(); + parser.parseDomainXML(domXml); + List disks = parser.getDisks(); + + //check the volume map. If an entry exists change the status to True + for (final LibvirtVMDef.DiskDef disk : disks) { + if (diskStatusMap.containsKey(disk.getDiskPath())) { + diskStatusMap.put(disk.getDiskPath(), true); + s_logger.debug("active disk found by cleanup thread" + disk.getDiskPath()); + } + } + } + } catch (LibvirtException e) { + s_logger.warn("[ignored] Error trying to cleanup ", e); + } + + } + + /** + * When the state is false, the iscsi sessions are stale. They may be + * removed. We go through each volume which is false, check iscsiadm, + * if the volume still exisits, logout of that volume and remove it from the map + + * XXX: It is possible that someone had manually added an iSCSI volume. + * we would not be able to detect that + */ + private void disconnectInactiveSessions(){ + + for (String diskPath : diskStatusMap.keySet()) { + if (!diskStatusMap.get(diskPath)) { + if (Files.exists(Paths.get(diskPath))) { + try { + s_logger.info("Cleaning up disk " + diskPath); + iscsiStorageAdaptor.disconnectPhysicalDiskByPath(diskPath); + } catch (Exception e) { + s_logger.warn("[ignored] Error cleaning up " + diskPath, e); + } + } + } + } + + } + } + + @Override + public void run() { + while(true) { + try { + Thread.sleep(CLEANUP_INTERVAL_SEC * 1000); + } catch (InterruptedException e) { + s_logger.debug("[ignored] interupted between heartbeats."); + } + + Thread monitorThread = new Thread(new Monitor()); + monitorThread.start(); + try { + monitorThread.join(); + } catch (InterruptedException e) { + s_logger.debug("[ignored] interupted joining monitor."); + } + } + } +} diff --git a/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java b/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java index 58d5ee64f63b..1bf27d06ef68 100644 --- a/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java +++ b/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java @@ -19,6 +19,19 @@ package com.cloud.hypervisor.kvm.resource; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import static org.mockito.ArgumentMatchers.nullable; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + import java.io.ByteArrayInputStream; import java.io.File; import java.io.IOException; @@ -41,9 +54,11 @@ import javax.xml.xpath.XPathExpressionException; import javax.xml.xpath.XPathFactory; -import com.cloud.agent.api.Command; -import com.cloud.agent.api.UnsupportedAnswer; -import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.CpuTuneDef; +import org.apache.cloudstack.storage.command.AttachAnswer; +import org.apache.cloudstack.storage.command.AttachCommand; +import org.apache.cloudstack.utils.linux.CPUStat; +import org.apache.cloudstack.utils.linux.MemStat; +import org.apache.cloudstack.utils.qemu.QemuImg.PhysicalDiskFormat; import org.apache.commons.lang.SystemUtils; import org.joda.time.Duration; import org.junit.Assert; @@ -61,22 +76,17 @@ import org.libvirt.NodeInfo; import org.libvirt.StorageVol; import org.libvirt.jna.virDomainMemoryStats; -import org.mockito.Matchers; +import org.mockito.BDDMockito; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.invocation.InvocationOnMock; import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PowerMockIgnore; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; import org.w3c.dom.Document; import org.xml.sax.SAXException; -import org.apache.cloudstack.storage.command.AttachAnswer; -import org.apache.cloudstack.storage.command.AttachCommand; -import org.apache.cloudstack.utils.linux.CPUStat; -import org.apache.cloudstack.utils.linux.MemStat; -import org.apache.cloudstack.utils.qemu.QemuImg.PhysicalDiskFormat; - import com.cloud.agent.api.Answer; import com.cloud.agent.api.AttachIsoCommand; import com.cloud.agent.api.BackupSnapshotCommand; @@ -87,6 +97,7 @@ import com.cloud.agent.api.CheckRouterCommand; import com.cloud.agent.api.CheckVirtualMachineCommand; import com.cloud.agent.api.CleanupNetworkRulesCmd; +import com.cloud.agent.api.Command; import com.cloud.agent.api.CreatePrivateTemplateFromSnapshotCommand; import com.cloud.agent.api.CreatePrivateTemplateFromVolumeCommand; import com.cloud.agent.api.CreateStoragePoolCommand; @@ -129,6 +140,7 @@ import com.cloud.agent.api.StartCommand; import com.cloud.agent.api.StopCommand; import com.cloud.agent.api.UnPlugNicCommand; +import com.cloud.agent.api.UnsupportedAnswer; import com.cloud.agent.api.UpdateHostPasswordCommand; import com.cloud.agent.api.UpgradeSnapshotCommand; import com.cloud.agent.api.VmStatsEntry; @@ -150,6 +162,7 @@ import com.cloud.exception.InternalErrorException; import com.cloud.hypervisor.kvm.resource.KVMHABase.NfsStoragePool; import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.ChannelDef; +import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.CpuTuneDef; import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.DiskDef; import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.InterfaceDef; import com.cloud.hypervisor.kvm.resource.wrapper.LibvirtRequestWrapper; @@ -177,20 +190,9 @@ import com.cloud.vm.VirtualMachine.PowerState; import com.cloud.vm.VirtualMachine.Type; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; -import static org.mockito.Matchers.any; -import static org.mockito.Mockito.doNothing; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - @RunWith(PowerMockRunner.class) @PrepareForTest(value = {MemStat.class}) +@PowerMockIgnore({"javax.xml.*", "org.w3c.dom.*", "org.apache.xerces.*"}) public class LibvirtComputingResourceTest { @Mock @@ -492,7 +494,8 @@ public void testGetVmStat() throws LibvirtException { nodeInfo.model = "Foo processor"; Mockito.when(connect.nodeInfo()).thenReturn(nodeInfo); // this is testing the interface stats, returns an increasing number of sent and received bytes - Mockito.when(domain.interfaceStats(Matchers.anyString())).thenAnswer(new org.mockito.stubbing.Answer() { + + Mockito.when(domain.interfaceStats(nullable(String.class))).thenAnswer(new org.mockito.stubbing.Answer() { // increment with less than a KB, so this should be less than 1 KB final static int increment = 1000; int rxBytes = 1000; @@ -509,7 +512,8 @@ public DomainInterfaceStats answer(final InvocationOnMock invocation) throws Thr }); - Mockito.when(domain.blockStats(Matchers.anyString())).thenAnswer(new org.mockito.stubbing.Answer() { + + Mockito.when(domain.blockStats(nullable(String.class))).thenAnswer(new org.mockito.stubbing.Answer() { // a little less than a KB final static int increment = 1000; @@ -1000,7 +1004,7 @@ public void testGetHostStatsCommand() { when(libvirtComputingResource.getCPUStat()).thenReturn(cpuStat); when(libvirtComputingResource.getMemStat()).thenReturn(memStat); - when(libvirtComputingResource.getNicStats(Mockito.anyString())).thenReturn(new Pair(1.0d, 1.0d)); + when(libvirtComputingResource.getNicStats(nullable(String.class))).thenReturn(new Pair(1.0d, 1.0d)); when(cpuStat.getCpuUsedPercent()).thenReturn(0.5d); when(memStat.getAvailable()).thenReturn(1500L); when(memStat.getTotal()).thenReturn(15000L); @@ -1247,7 +1251,7 @@ public void testPrepareForMigrationCommandInternalErrorException() { when(vm.getNics()).thenReturn(new NicTO[]{nicTO}); when(nicTO.getType()).thenReturn(TrafficType.Guest); - when(libvirtComputingResource.getVifDriver(nicTO.getType(), nicTO.getName())).thenThrow(InternalErrorException.class); + BDDMockito.given(libvirtComputingResource.getVifDriver(nicTO.getType(), nicTO.getName())).willAnswer(invocationOnMock -> {throw new InternalErrorException("Exception Occurred");}); when(libvirtComputingResource.getStoragePoolMgr()).thenReturn(storagePoolManager); try { when(libvirtComputingResource.getVolumePath(conn, volume)).thenReturn("/path"); @@ -1535,7 +1539,7 @@ public void testAttachIsoCommandURISyntaxException() { when(libvirtComputingResource.getLibvirtUtilitiesHelper()).thenReturn(libvirtUtilitiesHelper); try { - when(libvirtUtilitiesHelper.getConnectionByVmName(vmName)).thenThrow(URISyntaxException.class); + BDDMockito.given(libvirtUtilitiesHelper.getConnectionByVmName(vmName)).willAnswer(invocationOnMock -> {throw new URISyntaxException("Exception trying to get connection by VM name", vmName);}); } catch (final LibvirtException e) { fail(e.getMessage()); } @@ -1564,7 +1568,7 @@ public void testAttachIsoCommandInternalErrorException() { when(libvirtComputingResource.getLibvirtUtilitiesHelper()).thenReturn(libvirtUtilitiesHelper); try { - when(libvirtUtilitiesHelper.getConnectionByVmName(vmName)).thenThrow(InternalErrorException.class); + BDDMockito.given(libvirtUtilitiesHelper.getConnectionByVmName(vmName)).willAnswer(invocationOnMock -> {throw new InternalErrorException("Exception Occurred");}); } catch (final LibvirtException e) { fail(e.getMessage()); } @@ -2252,7 +2256,7 @@ public void testOvsVpcPhysicalTopologyConfigCommand() { } @SuppressWarnings("unchecked") - @Test + @Test(expected = Exception.class) public void testOvsVpcPhysicalTopologyConfigCommandFailure() { final Host[] hosts = null; final Tier[] tiers = null; @@ -2296,7 +2300,7 @@ public void testOvsVpcRoutingPolicyConfigCommand() { } @SuppressWarnings("unchecked") - @Test + @Test(expected = Exception.class) public void testOvsVpcRoutingPolicyConfigCommandFailure() { final String id = null; final String cidr = null; @@ -2409,7 +2413,7 @@ public void testNetworkRulesVmSecondaryIpCommand() { } catch (final LibvirtException e) { fail(e.getMessage()); } - when(libvirtComputingResource.configureNetworkRulesVMSecondaryIP(conn, command.getVmName(), command.getVmSecIp(), command.getAction())).thenReturn(true); + when(libvirtComputingResource.configureNetworkRulesVMSecondaryIP(conn, command.getVmName(), command.getVmMac(), command.getVmSecIp(), command.getAction())).thenReturn(true); final LibvirtRequestWrapper wrapper = LibvirtRequestWrapper.getInstance(); assertNotNull(wrapper); @@ -2423,7 +2427,7 @@ public void testNetworkRulesVmSecondaryIpCommand() { fail(e.getMessage()); } verify(libvirtComputingResource, times(1)).getLibvirtUtilitiesHelper(); - verify(libvirtComputingResource, times(1)).configureNetworkRulesVMSecondaryIP(conn, command.getVmName(), command.getVmSecIp(), command.getAction()); + verify(libvirtComputingResource, times(1)).configureNetworkRulesVMSecondaryIP(conn, command.getVmName(), command.getVmMac(), command.getVmSecIp(), command.getAction()); } @SuppressWarnings("unchecked") @@ -2702,7 +2706,7 @@ public void testOvsDestroyTunnelCommandFailure1() { } @SuppressWarnings("unchecked") - @Test + @Test(expected = Exception.class) public void testOvsDestroyTunnelCommandFailure2() { final String networkName = "Test"; final Long networkId = 1l; @@ -2802,7 +2806,7 @@ public void testOvsCreateTunnelCommandFailure1() { } @SuppressWarnings("unchecked") - @Test + @Test(expected = Exception.class) public void testOvsCreateTunnelCommandFailure2() { final String remoteIp = "127.0.0.1"; final Integer key = 1; @@ -3017,6 +3021,8 @@ public void testSecurityGroupRulesCmdTrue() { cidrs.add("0.0.0.0/0"); final SecurityGroupRulesCmd command = new SecurityGroupRulesCmd(guestIp, guestIp6, guestMac, vmName, vmId, signature, seqNum, ingressRuleSet, egressRuleSet, secIps); + final VirtualMachineTO vm = Mockito.mock(VirtualMachineTO.class); + command.setVmTO(vm); final LibvirtUtilitiesHelper libvirtUtilitiesHelper = Mockito.mock(LibvirtUtilitiesHelper.class); final Connect conn = Mockito.mock(Connect.class); @@ -3049,6 +3055,7 @@ public void testSecurityGroupRulesCmdTrue() { when(egressRuleSet[0].getEndPort()).thenReturn(22); when(egressRuleSet[0].getAllowedCidrs()).thenReturn(cidrs); + when(libvirtComputingResource.applyDefaultNetworkRules(conn, vm, true)).thenReturn(true); when(libvirtComputingResource.addNetworkRules(command.getVmName(), Long.toString(command.getVmId()), command.getGuestIp(), command.getGuestIp6(), command.getSignature(), Long.toString(command.getSeqNum()), command.getGuestMac(), command.stringifyRules(), vif, brname, command.getSecIpsString())).thenReturn(true); diff --git a/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtMigrateCommandWrapperTest.java b/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtMigrateCommandWrapperTest.java index 086808dbba1a..b5574bf7297f 100644 --- a/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtMigrateCommandWrapperTest.java +++ b/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtMigrateCommandWrapperTest.java @@ -22,22 +22,25 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; -import java.io.InputStream; import java.io.IOException; +import java.io.InputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.List; -import java.util.Scanner; -import org.apache.cloudstack.utils.linux.MemStat; import java.util.Map; -import org.apache.commons.io.IOUtils; +import java.util.Scanner; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.TransformerException; +import javax.xml.xpath.XPathExpressionException; +import javax.xml.xpath.XPathFactory; +import org.apache.cloudstack.utils.linux.MemStat; +import org.apache.commons.io.IOUtils; import org.junit.Assert; import org.junit.Before; -import com.cloud.agent.api.to.DpdkTO; import org.junit.Test; import org.junit.runner.RunWith; import org.libvirt.Connect; @@ -45,8 +48,10 @@ import org.mockito.InOrder; import org.mockito.Mockito; import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PowerMockIgnore; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; +import org.w3c.dom.Document; import org.xml.sax.SAXException; import com.cloud.agent.api.MigrateCommand; @@ -54,19 +59,15 @@ import com.cloud.agent.api.MigrateCommand.MigrateDiskInfo.DiskType; import com.cloud.agent.api.MigrateCommand.MigrateDiskInfo.DriverType; import com.cloud.agent.api.MigrateCommand.MigrateDiskInfo.Source; +import com.cloud.agent.api.to.DpdkTO; import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource; import com.cloud.hypervisor.kvm.resource.LibvirtConnection; import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.DiskDef; import com.cloud.utils.exception.CloudRuntimeException; -import org.w3c.dom.Document; - -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.xpath.XPathExpressionException; -import javax.xml.xpath.XPathFactory; @RunWith(PowerMockRunner.class) @PrepareForTest(value = {LibvirtConnection.class, LibvirtMigrateCommandWrapper.class, MemStat.class}) +@PowerMockIgnore({"javax.xml.*", "org.w3c.dom.*", "org.apache.xerces.*", "org.xml.*"}) public class LibvirtMigrateCommandWrapperTest { String fullfile = "\n" + @@ -648,7 +649,7 @@ public void deleteLocalVolumeTest() throws Exception { libvirtMigrateCmdWrapper.deleteLocalVolume("localPath"); - PowerMockito.verifyStatic(Mockito.times(1)); + PowerMockito.verifyStatic(LibvirtConnection.class, Mockito.times(1)); LibvirtConnection.getConnection(); InOrder inOrder = Mockito.inOrder(conn, storageVolLookupByPath); inOrder.verify(conn, Mockito.times(1)).storageVolLookupByPath("localPath"); diff --git a/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtNetworkElementCommandWrapperTest.java b/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtNetworkElementCommandWrapperTest.java index 29fb67bca29b..5a734908731f 100644 --- a/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtNetworkElementCommandWrapperTest.java +++ b/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtNetworkElementCommandWrapperTest.java @@ -19,12 +19,14 @@ package com.cloud.hypervisor.kvm.resource.wrapper; import static org.junit.Assert.assertEquals; -import static org.mockito.Matchers.anyString; +import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; +import java.util.Scanner; + import org.apache.cloudstack.utils.linux.MemStat; import org.junit.Before; import org.junit.Test; @@ -32,6 +34,10 @@ import org.libvirt.Connect; import org.libvirt.Domain; import org.libvirt.LibvirtException; +import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PowerMockIgnore; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; import com.cloud.agent.api.routing.IpAssocVpcCommand; import com.cloud.agent.api.routing.NetworkElementCommand; @@ -39,14 +45,10 @@ import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource; import com.cloud.network.Networks; import com.cloud.utils.ExecutionResult; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; - -import java.util.Scanner; @RunWith(PowerMockRunner.class) @PrepareForTest(value = {MemStat.class}) +@PowerMockIgnore({"javax.xml.*", "org.w3c.dom.*", "org.apache.xerces.*", "org.xml.*"}) public class LibvirtNetworkElementCommandWrapperTest { private static final String fullfile = "\n" + " r-3-VM\n" @@ -245,8 +247,8 @@ public void setUp() throws Exception { LibvirtUtilitiesHelper helper = mock(LibvirtUtilitiesHelper.class); when(_domain.getXMLDesc(0)).thenReturn(fullfile); - when(conn.domainLookupByName(anyString())).thenReturn(_domain); - when(helper.getConnectionByVmName(anyString())).thenReturn(conn); + when(conn.domainLookupByName(nullable(String.class))).thenReturn(_domain); + when(helper.getConnectionByVmName(nullable(String.class))).thenReturn(conn); doReturn(helper).when(res).getLibvirtUtilitiesHelper(); } diff --git a/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtReplugNicCommandWrapperTest.java b/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtReplugNicCommandWrapperTest.java index 9d47bfc94c05..2189e2a1df46 100644 --- a/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtReplugNicCommandWrapperTest.java +++ b/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtReplugNicCommandWrapperTest.java @@ -26,8 +26,10 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Scanner; @@ -39,7 +41,10 @@ import org.libvirt.Domain; import org.libvirt.LibvirtException; import org.mockito.BDDMockito; +import org.mockito.Mock; +import org.mockito.Mockito; import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PowerMockIgnore; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; @@ -48,6 +53,7 @@ import com.cloud.agent.api.to.NicTO; import com.cloud.hypervisor.kvm.resource.BridgeVifDriver; import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource; +import com.cloud.hypervisor.kvm.resource.LibvirtVMDef; import com.cloud.hypervisor.kvm.resource.OvsVifDriver; import com.cloud.network.Networks; import com.cloud.utils.script.Script; @@ -55,8 +61,12 @@ @RunWith(PowerMockRunner.class) @PrepareForTest(value = {Script.class, MemStat.class}) +@PowerMockIgnore({"javax.xml.*", "org.w3c.dom.*", "org.apache.xerces.*", "org.xml.*"}) public class LibvirtReplugNicCommandWrapperTest { + @Mock + private LibvirtComputingResource libvirtComputingResource; + private static final String part_1 = "\n" + " i-85-285-VM\n" @@ -276,6 +286,13 @@ public void testReplugNic() throws LibvirtException { + "
\n" + "\n"; + final LibvirtVMDef.InterfaceDef interfaceDef = Mockito.mock(LibvirtVMDef.InterfaceDef.class); + final List ifaces = new ArrayList(); + ifaces.add(interfaceDef); + + final Connect conn = Mockito.mock(Connect.class); + + when(libvirtComputingResource.getInterfaces(conn, "")).thenReturn(ifaces); final LibvirtReplugNicCommandWrapper wrapper = new LibvirtReplugNicCommandWrapper(); final NicTO nic = new NicTO(); nic.setType(Networks.TrafficType.Guest); diff --git a/plugins/hypervisors/kvm/src/test/java/org/apache/cloudstack/kvm/ha/KVMHostHATest.java b/plugins/hypervisors/kvm/src/test/java/org/apache/cloudstack/kvm/ha/KVMHostHATest.java index 26b7e6ae206b..b6b3fb7100c2 100644 --- a/plugins/hypervisors/kvm/src/test/java/org/apache/cloudstack/kvm/ha/KVMHostHATest.java +++ b/plugins/hypervisors/kvm/src/test/java/org/apache/cloudstack/kvm/ha/KVMHostHATest.java @@ -18,10 +18,13 @@ */ package org.apache.cloudstack.kvm.ha; -import com.cloud.exception.StorageUnavailableException; -import com.cloud.host.Host; -import com.cloud.hypervisor.Hypervisor.HypervisorType; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.lenient; +import static org.mockito.Mockito.when; + import org.apache.cloudstack.ha.provider.HACheckerException; +import org.joda.time.DateTime; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -29,11 +32,9 @@ import org.mockito.MockitoAnnotations; import org.mockito.runners.MockitoJUnitRunner; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.when; - -import org.joda.time.DateTime; +import com.cloud.exception.StorageUnavailableException; +import com.cloud.host.Host; +import com.cloud.hypervisor.Hypervisor.HypervisorType; @RunWith(MockitoJUnitRunner.class) public class KVMHostHATest { @@ -53,21 +54,21 @@ public void setup() { @Test public void testHostActivityForHealthyHost() throws HACheckerException, StorageUnavailableException { - when(host.getHypervisorType()).thenReturn(HypervisorType.KVM); + lenient().when(host.getHypervisorType()).thenReturn(HypervisorType.KVM); when(kvmHostActivityChecker.isHealthy(host)).thenReturn(true); assertTrue(kvmHAProvider.isHealthy(host)); } @Test public void testHostActivityForUnHealthyHost() throws HACheckerException, StorageUnavailableException { - when(host.getHypervisorType()).thenReturn(HypervisorType.KVM); + lenient().when(host.getHypervisorType()).thenReturn(HypervisorType.KVM); when(kvmHostActivityChecker.isHealthy(host)).thenReturn(false); assertFalse(kvmHAProvider.isHealthy(host)); } @Test public void testHostActivityForActiveHost() throws HACheckerException, StorageUnavailableException { - when(host.getHypervisorType()).thenReturn(HypervisorType.KVM); + lenient().when(host.getHypervisorType()).thenReturn(HypervisorType.KVM); DateTime dt = new DateTime(); when(kvmHostActivityChecker.isActive(host, dt)).thenReturn(true); assertTrue(kvmHAProvider.hasActivity(host, dt)); @@ -75,7 +76,7 @@ public void testHostActivityForActiveHost() throws HACheckerException, StorageUn @Test public void testHostActivityForDownHost() throws HACheckerException, StorageUnavailableException { - when(host.getHypervisorType()).thenReturn(HypervisorType.KVM); + lenient().when(host.getHypervisorType()).thenReturn(HypervisorType.KVM); DateTime dt = new DateTime(); when(kvmHostActivityChecker.isActive(host, dt)).thenReturn(false); assertFalse(kvmHAProvider.hasActivity(host, dt)); diff --git a/plugins/hypervisors/simulator/src/main/java/com/cloud/agent/manager/MockStorageManagerImpl.java b/plugins/hypervisors/simulator/src/main/java/com/cloud/agent/manager/MockStorageManagerImpl.java index de12f3b433ff..efa9510a8e1c 100644 --- a/plugins/hypervisors/simulator/src/main/java/com/cloud/agent/manager/MockStorageManagerImpl.java +++ b/plugins/hypervisors/simulator/src/main/java/com/cloud/agent/manager/MockStorageManagerImpl.java @@ -40,7 +40,6 @@ import org.apache.cloudstack.storage.command.UploadStatusAnswer; import org.apache.cloudstack.storage.command.UploadStatusAnswer.UploadStatus; import org.apache.cloudstack.storage.command.UploadStatusCommand; -import org.apache.cloudstack.storage.to.VolumeObjectTO; import com.cloud.agent.api.Answer; import com.cloud.agent.api.AttachIsoCommand; @@ -823,12 +822,7 @@ public Answer Delete(DeleteCommand cmd) { try { txn.start(); MockVolumeVO template = _mockVolumeDao.findByStoragePathAndType(cmd.getData().getPath()); - if (template == null) { - if(!((VolumeObjectTO)cmd.getData()).getName().startsWith("ROOT-")) { - return new Answer(cmd, false, "can't find object to delete:" + cmd.getData() - .getPath()); - } - } else { + if (template != null) { _mockVolumeDao.remove(template.getId()); } txn.commit(); diff --git a/plugins/hypervisors/vmware/pom.xml b/plugins/hypervisors/vmware/pom.xml index dbd2dcb1f280..9e52fd167937 100644 --- a/plugins/hypervisors/vmware/pom.xml +++ b/plugins/hypervisors/vmware/pom.xml @@ -55,6 +55,11 @@ ${cs.vmware.api.version} compile + + com.sun.org.apache.xml.internal + resolver + 20050927 + org.apache.axis axis diff --git a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/manager/VmwareStorageManagerImpl.java b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/manager/VmwareStorageManagerImpl.java index 97b5088ccae8..f17d613125c8 100644 --- a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/manager/VmwareStorageManagerImpl.java +++ b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/manager/VmwareStorageManagerImpl.java @@ -525,7 +525,7 @@ public Answer execute(VmwareHostService hostService, CreateVolumeFromSnapshotCom String details = null; boolean success = false; - String newVolumeName = UUID.randomUUID().toString().replaceAll("-", ""); + String newVolumeName = UUID.randomUUID().toString().replace("-", ""); VmwareContext context = hostService.getServiceContext(cmd); try { @@ -1053,7 +1053,7 @@ private Pair copyVolumeFromSecStorage(VmwareHypervisorHost hyper Integer nfsVersion) throws Exception { String volumeFolder = String.valueOf(volumeId) + "/"; - String newVolume = UUID.randomUUID().toString().replaceAll("-", ""); + String newVolume = UUID.randomUUID().toString().replace("-", ""); restoreVolumeFromSecStorage(hyperHost, dsMo, newVolume, secStorageUrl, "volumes/" + volumeFolder, exportName, nfsVersion); return new Pair(volumeFolder, newVolume); diff --git a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java index b5a1260a7230..7624f954e9db 100644 --- a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java +++ b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java @@ -44,19 +44,6 @@ import javax.naming.ConfigurationException; import javax.xml.datatype.XMLGregorianCalendar; -import com.cloud.agent.api.storage.OVFPropertyTO; -import com.cloud.utils.crypt.DBEncryptionUtil; -import com.vmware.vim25.ArrayUpdateOperation; -import com.vmware.vim25.VAppOvfSectionInfo; -import com.vmware.vim25.VAppOvfSectionSpec; -import com.vmware.vim25.VAppProductInfo; -import com.vmware.vim25.VAppProductSpec; -import com.vmware.vim25.VAppPropertyInfo; -import com.vmware.vim25.VAppPropertySpec; -import com.vmware.vim25.VmConfigInfo; -import com.vmware.vim25.VmConfigSpec; -import org.apache.commons.collections.CollectionUtils; - import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.storage.command.CopyCommand; import org.apache.cloudstack.storage.command.StorageSubSystemCommand; @@ -66,6 +53,8 @@ import org.apache.cloudstack.storage.to.TemplateObjectTO; import org.apache.cloudstack.storage.to.VolumeObjectTO; import org.apache.cloudstack.utils.volume.VirtualMachineDiskInfo; +import org.apache.cloudstack.vm.UnmanagedInstanceTO; +import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.math.NumberUtils; import org.apache.log4j.Logger; @@ -101,6 +90,8 @@ import com.cloud.agent.api.GetHostStatsCommand; import com.cloud.agent.api.GetStorageStatsAnswer; import com.cloud.agent.api.GetStorageStatsCommand; +import com.cloud.agent.api.GetUnmanagedInstancesAnswer; +import com.cloud.agent.api.GetUnmanagedInstancesCommand; import com.cloud.agent.api.GetVmDiskStatsAnswer; import com.cloud.agent.api.GetVmDiskStatsCommand; import com.cloud.agent.api.GetVmIpAddressCommand; @@ -184,6 +175,7 @@ import com.cloud.agent.api.storage.DestroyCommand; import com.cloud.agent.api.storage.MigrateVolumeAnswer; import com.cloud.agent.api.storage.MigrateVolumeCommand; +import com.cloud.agent.api.storage.OVFPropertyTO; import com.cloud.agent.api.storage.PrimaryStorageDownloadAnswer; import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand; import com.cloud.agent.api.storage.ResizeVolumeAnswer; @@ -217,6 +209,7 @@ import com.cloud.hypervisor.vmware.mo.DatastoreFile; import com.cloud.hypervisor.vmware.mo.DatastoreMO; import com.cloud.hypervisor.vmware.mo.DiskControllerType; +import com.cloud.hypervisor.vmware.mo.DistributedVirtualSwitchMO; import com.cloud.hypervisor.vmware.mo.FeatureKeyConstants; import com.cloud.hypervisor.vmware.mo.HostDatastoreSystemMO; import com.cloud.hypervisor.vmware.mo.HostMO; @@ -255,6 +248,7 @@ import com.cloud.utils.NumbersUtil; import com.cloud.utils.Pair; import com.cloud.utils.Ternary; +import com.cloud.utils.crypt.DBEncryptionUtil; import com.cloud.utils.db.DB; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.exception.ExceptionUtil; @@ -268,24 +262,30 @@ import com.cloud.vm.VirtualMachine.PowerState; import com.cloud.vm.VirtualMachineName; import com.cloud.vm.VmDetailConstants; +import com.google.common.base.Strings; import com.google.gson.Gson; import com.vmware.vim25.AboutInfo; +import com.vmware.vim25.ArrayUpdateOperation; import com.vmware.vim25.BoolPolicy; import com.vmware.vim25.ComputeResourceSummary; import com.vmware.vim25.CustomFieldStringValue; import com.vmware.vim25.DVPortConfigInfo; import com.vmware.vim25.DVPortConfigSpec; import com.vmware.vim25.DasVmPriority; +import com.vmware.vim25.DatastoreInfo; import com.vmware.vim25.DatastoreSummary; import com.vmware.vim25.DistributedVirtualPort; import com.vmware.vim25.DistributedVirtualSwitchPortConnection; import com.vmware.vim25.DistributedVirtualSwitchPortCriteria; import com.vmware.vim25.DynamicProperty; import com.vmware.vim25.GuestInfo; +import com.vmware.vim25.GuestNicInfo; import com.vmware.vim25.HostCapability; import com.vmware.vim25.HostHostBusAdapter; import com.vmware.vim25.HostInternetScsiHba; +import com.vmware.vim25.HostPortGroupSpec; import com.vmware.vim25.ManagedObjectReference; +import com.vmware.vim25.NasDatastoreInfo; import com.vmware.vim25.ObjectContent; import com.vmware.vim25.OptionValue; import com.vmware.vim25.PerfCounterInfo; @@ -297,18 +297,26 @@ import com.vmware.vim25.PerfQuerySpec; import com.vmware.vim25.RuntimeFaultFaultMsg; import com.vmware.vim25.ToolsUnavailableFaultMsg; +import com.vmware.vim25.VAppOvfSectionInfo; +import com.vmware.vim25.VAppOvfSectionSpec; +import com.vmware.vim25.VAppProductInfo; +import com.vmware.vim25.VAppProductSpec; +import com.vmware.vim25.VAppPropertyInfo; +import com.vmware.vim25.VAppPropertySpec; import com.vmware.vim25.VMwareDVSPortSetting; import com.vmware.vim25.VimPortType; import com.vmware.vim25.VirtualDevice; import com.vmware.vim25.VirtualDeviceBackingInfo; import com.vmware.vim25.VirtualDeviceConfigSpec; import com.vmware.vim25.VirtualDeviceConfigSpecOperation; +import com.vmware.vim25.VirtualDeviceFileBackingInfo; import com.vmware.vim25.VirtualDisk; import com.vmware.vim25.VirtualDiskFlatVer2BackingInfo; import com.vmware.vim25.VirtualEthernetCard; import com.vmware.vim25.VirtualEthernetCardDistributedVirtualPortBackingInfo; import com.vmware.vim25.VirtualEthernetCardNetworkBackingInfo; import com.vmware.vim25.VirtualEthernetCardOpaqueNetworkBackingInfo; +import com.vmware.vim25.VirtualIDEController; import com.vmware.vim25.VirtualMachineConfigSpec; import com.vmware.vim25.VirtualMachineFileInfo; import com.vmware.vim25.VirtualMachineFileLayoutEx; @@ -320,7 +328,15 @@ import com.vmware.vim25.VirtualMachineRuntimeInfo; import com.vmware.vim25.VirtualMachineToolsStatus; import com.vmware.vim25.VirtualMachineVideoCard; +import com.vmware.vim25.VirtualPCNet32; +import com.vmware.vim25.VirtualSCSIController; import com.vmware.vim25.VirtualUSBController; +import com.vmware.vim25.VirtualVmxnet2; +import com.vmware.vim25.VirtualVmxnet3; +import com.vmware.vim25.VmConfigInfo; +import com.vmware.vim25.VmConfigSpec; +import com.vmware.vim25.VmfsDatastoreInfo; +import com.vmware.vim25.VmwareDistributedVirtualSwitchPvlanSpec; import com.vmware.vim25.VmwareDistributedVirtualSwitchVlanIdSpec; public class VmwareResource implements StoragePoolResource, ServerResource, VmwareHostService, VirtualRouterDeployer { @@ -378,6 +394,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa protected VirtualRoutingResource _vrResource; protected final static HashMap s_powerStatesTable = new HashMap(); + static { s_powerStatesTable.put(VirtualMachinePowerState.POWERED_ON, PowerState.PowerOn); s_powerStatesTable.put(VirtualMachinePowerState.POWERED_OFF, PowerState.PowerOff); @@ -430,118 +447,120 @@ public Answer executeRequest(Command cmd) { Class clz = cmd.getClass(); if (cmd instanceof NetworkElementCommand) { - return _vrResource.executeRequest((NetworkElementCommand)cmd); + return _vrResource.executeRequest((NetworkElementCommand) cmd); } else if (clz == ReadyCommand.class) { - answer = execute((ReadyCommand)cmd); + answer = execute((ReadyCommand) cmd); } else if (clz == GetHostStatsCommand.class) { - answer = execute((GetHostStatsCommand)cmd); + answer = execute((GetHostStatsCommand) cmd); } else if (clz == GetVmStatsCommand.class) { - answer = execute((GetVmStatsCommand)cmd); + answer = execute((GetVmStatsCommand) cmd); } else if (clz == GetVmNetworkStatsCommand.class) { answer = execute((GetVmNetworkStatsCommand) cmd); } else if (clz == GetVmDiskStatsCommand.class) { - answer = execute((GetVmDiskStatsCommand)cmd); + answer = execute((GetVmDiskStatsCommand) cmd); } else if (cmd instanceof GetVolumeStatsCommand) { - return execute((GetVolumeStatsCommand)cmd); + return execute((GetVolumeStatsCommand) cmd); } else if (clz == CheckHealthCommand.class) { - answer = execute((CheckHealthCommand)cmd); + answer = execute((CheckHealthCommand) cmd); } else if (clz == StopCommand.class) { - answer = execute((StopCommand)cmd); + answer = execute((StopCommand) cmd); } else if (clz == RebootRouterCommand.class) { - answer = execute((RebootRouterCommand)cmd); + answer = execute((RebootRouterCommand) cmd); } else if (clz == RebootCommand.class) { - answer = execute((RebootCommand)cmd); + answer = execute((RebootCommand) cmd); } else if (clz == CheckVirtualMachineCommand.class) { - answer = execute((CheckVirtualMachineCommand)cmd); + answer = execute((CheckVirtualMachineCommand) cmd); } else if (clz == PrepareForMigrationCommand.class) { - answer = execute((PrepareForMigrationCommand)cmd); + answer = execute((PrepareForMigrationCommand) cmd); } else if (clz == MigrateCommand.class) { - answer = execute((MigrateCommand)cmd); + answer = execute((MigrateCommand) cmd); } else if (clz == MigrateVmToPoolCommand.class) { - answer = execute((MigrateVmToPoolCommand)cmd); + answer = execute((MigrateVmToPoolCommand) cmd); } else if (clz == MigrateWithStorageCommand.class) { - answer = execute((MigrateWithStorageCommand)cmd); + answer = execute((MigrateWithStorageCommand) cmd); } else if (clz == MigrateVolumeCommand.class) { - answer = execute((MigrateVolumeCommand)cmd); + answer = execute((MigrateVolumeCommand) cmd); } else if (clz == DestroyCommand.class) { - answer = execute((DestroyCommand)cmd); + answer = execute((DestroyCommand) cmd); } else if (clz == CreateStoragePoolCommand.class) { - return execute((CreateStoragePoolCommand)cmd); + return execute((CreateStoragePoolCommand) cmd); } else if (clz == ModifyTargetsCommand.class) { - answer = execute((ModifyTargetsCommand)cmd); + answer = execute((ModifyTargetsCommand) cmd); } else if (clz == ModifyStoragePoolCommand.class) { - answer = execute((ModifyStoragePoolCommand)cmd); + answer = execute((ModifyStoragePoolCommand) cmd); } else if (clz == DeleteStoragePoolCommand.class) { - answer = execute((DeleteStoragePoolCommand)cmd); + answer = execute((DeleteStoragePoolCommand) cmd); } else if (clz == CopyVolumeCommand.class) { - answer = execute((CopyVolumeCommand)cmd); + answer = execute((CopyVolumeCommand) cmd); } else if (clz == AttachIsoCommand.class) { - answer = execute((AttachIsoCommand)cmd); + answer = execute((AttachIsoCommand) cmd); } else if (clz == ValidateSnapshotCommand.class) { - answer = execute((ValidateSnapshotCommand)cmd); + answer = execute((ValidateSnapshotCommand) cmd); } else if (clz == ManageSnapshotCommand.class) { - answer = execute((ManageSnapshotCommand)cmd); + answer = execute((ManageSnapshotCommand) cmd); } else if (clz == BackupSnapshotCommand.class) { - answer = execute((BackupSnapshotCommand)cmd); + answer = execute((BackupSnapshotCommand) cmd); } else if (clz == CreateVolumeFromSnapshotCommand.class) { - answer = execute((CreateVolumeFromSnapshotCommand)cmd); + answer = execute((CreateVolumeFromSnapshotCommand) cmd); } else if (clz == CreatePrivateTemplateFromVolumeCommand.class) { - answer = execute((CreatePrivateTemplateFromVolumeCommand)cmd); + answer = execute((CreatePrivateTemplateFromVolumeCommand) cmd); } else if (clz == CreatePrivateTemplateFromSnapshotCommand.class) { - answer = execute((CreatePrivateTemplateFromSnapshotCommand)cmd); + answer = execute((CreatePrivateTemplateFromSnapshotCommand) cmd); } else if (clz == UpgradeSnapshotCommand.class) { - answer = execute((UpgradeSnapshotCommand)cmd); + answer = execute((UpgradeSnapshotCommand) cmd); } else if (clz == GetStorageStatsCommand.class) { - answer = execute((GetStorageStatsCommand)cmd); + answer = execute((GetStorageStatsCommand) cmd); } else if (clz == PrimaryStorageDownloadCommand.class) { - answer = execute((PrimaryStorageDownloadCommand)cmd); + answer = execute((PrimaryStorageDownloadCommand) cmd); } else if (clz == GetVncPortCommand.class) { - answer = execute((GetVncPortCommand)cmd); + answer = execute((GetVncPortCommand) cmd); } else if (clz == SetupCommand.class) { - answer = execute((SetupCommand)cmd); + answer = execute((SetupCommand) cmd); } else if (clz == MaintainCommand.class) { - answer = execute((MaintainCommand)cmd); + answer = execute((MaintainCommand) cmd); } else if (clz == PingTestCommand.class) { - answer = execute((PingTestCommand)cmd); + answer = execute((PingTestCommand) cmd); } else if (clz == CheckOnHostCommand.class) { - answer = execute((CheckOnHostCommand)cmd); + answer = execute((CheckOnHostCommand) cmd); } else if (clz == ModifySshKeysCommand.class) { - answer = execute((ModifySshKeysCommand)cmd); + answer = execute((ModifySshKeysCommand) cmd); } else if (clz == NetworkUsageCommand.class) { - answer = execute((NetworkUsageCommand)cmd); + answer = execute((NetworkUsageCommand) cmd); } else if (clz == StartCommand.class) { - answer = execute((StartCommand)cmd); + answer = execute((StartCommand) cmd); } else if (clz == CheckSshCommand.class) { - answer = execute((CheckSshCommand)cmd); + answer = execute((CheckSshCommand) cmd); } else if (clz == CheckNetworkCommand.class) { - answer = execute((CheckNetworkCommand)cmd); + answer = execute((CheckNetworkCommand) cmd); } else if (clz == PlugNicCommand.class) { - answer = execute((PlugNicCommand)cmd); + answer = execute((PlugNicCommand) cmd); } else if (clz == ReplugNicCommand.class) { - answer = execute((ReplugNicCommand)cmd); + answer = execute((ReplugNicCommand) cmd); } else if (clz == UnPlugNicCommand.class) { - answer = execute((UnPlugNicCommand)cmd); + answer = execute((UnPlugNicCommand) cmd); } else if (cmd instanceof CreateVMSnapshotCommand) { - return execute((CreateVMSnapshotCommand)cmd); + return execute((CreateVMSnapshotCommand) cmd); } else if (cmd instanceof DeleteVMSnapshotCommand) { - return execute((DeleteVMSnapshotCommand)cmd); + return execute((DeleteVMSnapshotCommand) cmd); } else if (cmd instanceof RevertToVMSnapshotCommand) { - return execute((RevertToVMSnapshotCommand)cmd); + return execute((RevertToVMSnapshotCommand) cmd); } else if (clz == ResizeVolumeCommand.class) { - return execute((ResizeVolumeCommand)cmd); + return execute((ResizeVolumeCommand) cmd); } else if (clz == UnregisterVMCommand.class) { - return execute((UnregisterVMCommand)cmd); + return execute((UnregisterVMCommand) cmd); } else if (cmd instanceof StorageSubSystemCommand) { - checkStorageProcessorAndHandlerNfsVersionAttribute((StorageSubSystemCommand)cmd); - return storageHandler.handleStorageCommands((StorageSubSystemCommand)cmd); + checkStorageProcessorAndHandlerNfsVersionAttribute((StorageSubSystemCommand) cmd); + return storageHandler.handleStorageCommands((StorageSubSystemCommand) cmd); } else if (clz == ScaleVmCommand.class) { - return execute((ScaleVmCommand)cmd); + return execute((ScaleVmCommand) cmd); } else if (clz == PvlanSetupCommand.class) { - return execute((PvlanSetupCommand)cmd); + return execute((PvlanSetupCommand) cmd); } else if (clz == GetVmIpAddressCommand.class) { - return execute((GetVmIpAddressCommand)cmd); + return execute((GetVmIpAddressCommand) cmd); } else if (clz == UnregisterNicCommand.class) { - answer = execute((UnregisterNicCommand)cmd); + answer = execute((UnregisterNicCommand) cmd); + } else if (clz == GetUnmanagedInstancesCommand.class) { + answer = execute((GetUnmanagedInstancesCommand) cmd); } else { answer = Answer.createUnsupportedCommandAnswer(cmd); } @@ -587,6 +606,7 @@ public Answer executeRequest(Command cmd) { * If _storageNfsVersion is not null -> nothing to do, version already set.
* If _storageNfsVersion is null -> examine StorageSubSystemCommand to get NFS version and set it * to the storage processor and storage handler. + * * @param cmd command to execute */ protected void checkStorageProcessorAndHandlerNfsVersionAttribute(StorageSubSystemCommand cmd) { @@ -595,18 +615,19 @@ protected void checkStorageProcessorAndHandlerNfsVersionAttribute(StorageSubSyst if (cmd instanceof CopyCommand) { EnumMap params = new EnumMap( VmwareStorageProcessorConfigurableFields.class); - examineStorageSubSystemCommandNfsVersion((CopyCommand)cmd, params); - params = examineStorageSubSystemCommandFullCloneFlagForVmware((CopyCommand)cmd, params); + examineStorageSubSystemCommandNfsVersion((CopyCommand) cmd, params); + params = examineStorageSubSystemCommandFullCloneFlagForVmware((CopyCommand) cmd, params); reconfigureProcessorByHandler(params); } } /** * Reconfigure processor by handler + * * @param params params */ protected void reconfigureProcessorByHandler(EnumMap params) { - VmwareStorageSubsystemCommandHandler handler = (VmwareStorageSubsystemCommandHandler)storageHandler; + VmwareStorageSubsystemCommandHandler handler = (VmwareStorageSubsystemCommandHandler) storageHandler; boolean success = handler.reconfigureStorageProcessor(params); if (success) { s_logger.info("VmwareStorageProcessor and VmwareStorageSubsystemCommandHandler successfully reconfigured"); @@ -617,7 +638,8 @@ protected void reconfigureProcessorByHandler(EnumMap examineStora if (hypervisor != null && hypervisor.equals(HypervisorType.VMware)) { DataStoreTO destDataStore = cmd.getDestTO().getDataStore(); if (destDataStore instanceof PrimaryDataStoreTO) { - PrimaryDataStoreTO dest = (PrimaryDataStoreTO)destDataStore; + PrimaryDataStoreTO dest = (PrimaryDataStoreTO) destDataStore; if (dest.isFullCloneFlag() != null) { paramsCopy.put(VmwareStorageProcessorConfigurableFields.FULL_CLONE_FLAG, dest.isFullCloneFlag().booleanValue()); } @@ -639,7 +661,8 @@ protected EnumMap examineStora /** * Examine StorageSubSystem command to get storage NFS version, if provided - * @param cmd command to execute + * + * @param cmd command to execute * @param params params */ protected void examineStorageSubSystemCommandNfsVersion(CopyCommand cmd, EnumMap params) { @@ -647,7 +670,7 @@ protected void examineStorageSubSystemCommandNfsVersion(CopyCommand cmd, EnumMap boolean nfsVersionFound = false; if (srcDataStore instanceof NfsTO) { - nfsVersionFound = getStorageNfsVersionFromNfsTO((NfsTO)srcDataStore); + nfsVersionFound = getStorageNfsVersionFromNfsTO((NfsTO) srcDataStore); } if (nfsVersionFound) { @@ -657,6 +680,7 @@ protected void examineStorageSubSystemCommandNfsVersion(CopyCommand cmd, EnumMap /** * Get storage NFS version from NfsTO + * * @param nfsTO nfsTO * @return true if NFS version was found and not null, false in other case */ @@ -743,7 +767,7 @@ private Answer execute(ResizeVolumeCommand cmd) { // OfflineVmwareMigration: 3. attach the disk to the worker vmdkDataStorePath = VmwareStorageLayoutHelper.getLegacyDatastorePathFromVmdkFileName(dsMo, path + VMDK_EXTENSION); - vmMo.attachDisk(new String[] { vmdkDataStorePath }, morDS); + vmMo.attachDisk(new String[]{vmdkDataStorePath}, morDS); } } @@ -773,7 +797,7 @@ private Answer execute(ResizeVolumeCommand cmd) { // IDE virtual disk cannot be re-sized if VM is running if (vdisk.second() != null && vdisk.second().contains("ide")) { throw new Exception("Re-sizing a virtual disk over an IDE controller is not supported in the VMware hypervisor. " + - "Please re-try when virtual disk is attached to a VM using a SCSI controller."); + "Please re-try when virtual disk is attached to a VM using a SCSI controller."); } if (cmd.isManaged()) { @@ -799,16 +823,14 @@ private Answer execute(ResizeVolumeCommand cmd) { _storageProcessor.expandDatastore(hostDatastoreSystem, dsMo); } - if (vdisk.second() != null && !vdisk.second().toLowerCase().startsWith("scsi")) - { - s_logger.error("Unsupported disk device bus "+ vdisk.second()); - throw new Exception("Unsupported disk device bus "+ vdisk.second()); + if (vdisk.second() != null && !vdisk.second().toLowerCase().startsWith("scsi")) { + s_logger.error("Unsupported disk device bus " + vdisk.second()); + throw new Exception("Unsupported disk device bus " + vdisk.second()); } VirtualDisk disk = vdisk.first(); - if ((VirtualDiskFlatVer2BackingInfo)disk.getBacking() != null && ((VirtualDiskFlatVer2BackingInfo)disk.getBacking()).getParent() != null) - { - s_logger.error("Resize is not supported because Disk device has Parent "+ ((VirtualDiskFlatVer2BackingInfo)disk.getBacking()).getParent().getUuid()); - throw new Exception("Resize is not supported because Disk device has Parent "+ ((VirtualDiskFlatVer2BackingInfo)disk.getBacking()).getParent().getUuid()); + if ((VirtualDiskFlatVer2BackingInfo) disk.getBacking() != null && ((VirtualDiskFlatVer2BackingInfo) disk.getBacking()).getParent() != null) { + s_logger.error("Resize is not supported because Disk device has Parent " + ((VirtualDiskFlatVer2BackingInfo) disk.getBacking()).getParent().getUuid()); + throw new Exception("Resize is not supported because Disk device has Parent " + ((VirtualDiskFlatVer2BackingInfo) disk.getBacking()).getParent().getUuid()); } String vmdkAbsFile = getAbsoluteVmdkFile(disk); @@ -946,15 +968,15 @@ public ExecutionResult prepareCommand(NetworkElementCommand cmd) { assert cmd.getRouterAccessIp() != null; if (cmd instanceof IpAssocVpcCommand) { - return prepareNetworkElementCommand((IpAssocVpcCommand)cmd); + return prepareNetworkElementCommand((IpAssocVpcCommand) cmd); } else if (cmd instanceof IpAssocCommand) { - return prepareNetworkElementCommand((IpAssocCommand)cmd); + return prepareNetworkElementCommand((IpAssocCommand) cmd); } else if (cmd instanceof SetSourceNatCommand) { - return prepareNetworkElementCommand((SetSourceNatCommand)cmd); + return prepareNetworkElementCommand((SetSourceNatCommand) cmd); } else if (cmd instanceof SetupGuestNetworkCommand) { - return prepareNetworkElementCommand((SetupGuestNetworkCommand)cmd); + return prepareNetworkElementCommand((SetupGuestNetworkCommand) cmd); } else if (cmd instanceof SetNetworkACLCommand) { - return prepareNetworkElementCommand((SetNetworkACLCommand)cmd); + return prepareNetworkElementCommand((SetNetworkACLCommand) cmd); } return new ExecutionResult(true, null); } @@ -1027,7 +1049,7 @@ private VirtualDevice findVirtualNicDevice(VirtualMachineMO vmMo, String mac) th VirtualDevice[] nics = vmMo.getNicDevices(); for (VirtualDevice nic : nics) { if (nic instanceof VirtualEthernetCard) { - if (((VirtualEthernetCard)nic).getMacAddress().equals(mac)) + if (((VirtualEthernetCard) nic).getMacAddress().equals(mac)) return nic; } } @@ -1125,7 +1147,7 @@ private PlugNicAnswer execute(PlugNicCommand cmd) { if (vmMo == null) { if (hyperHost instanceof HostMO) { - ClusterMO clusterMo = new ClusterMO(hyperHost.getContext(), ((HostMO)hyperHost).getParentMor()); + ClusterMO clusterMo = new ClusterMO(hyperHost.getContext(), ((HostMO) hyperHost).getParentMor()); vmMo = clusterMo.findVmOnHyperHost(vmName); } } @@ -1147,7 +1169,7 @@ private PlugNicAnswer execute(PlugNicCommand cmd) { VirtualEthernetCardType nicDeviceType = VirtualEthernetCardType.E1000; Map details = cmd.getDetails(); if (details != null) { - nicDeviceType = VirtualEthernetCardType.valueOf((String)details.get("nicAdapter")); + nicDeviceType = VirtualEthernetCardType.valueOf((String) details.get("nicAdapter")); } // find a usable device number in VMware environment @@ -1209,7 +1231,7 @@ private ReplugNicAnswer execute(ReplugNicCommand cmd) { if (vmMo == null) { if (hyperHost instanceof HostMO) { - ClusterMO clusterMo = new ClusterMO(hyperHost.getContext(), ((HostMO)hyperHost).getParentMor()); + ClusterMO clusterMo = new ClusterMO(hyperHost.getContext(), ((HostMO) hyperHost).getParentMor()); vmMo = clusterMo.findVmOnHyperHost(vmName); } } @@ -1288,7 +1310,7 @@ private UnPlugNicAnswer execute(UnPlugNicCommand cmd) { if (vmMo == null) { if (hyperHost instanceof HostMO) { - ClusterMO clusterMo = new ClusterMO(hyperHost.getContext(), ((HostMO)hyperHost).getParentMor()); + ClusterMO clusterMo = new ClusterMO(hyperHost.getContext(), ((HostMO) hyperHost).getParentMor()); vmMo = clusterMo.findVmOnHyperHost(vmName); } } @@ -1353,7 +1375,7 @@ private void plugPublicNic(VirtualMachineMO vmMo, final String vlanId, final IpA try { VirtualDevice[] nicDevices = vmMo.getNicDevices(); - VirtualEthernetCard device = (VirtualEthernetCard)nicDevices[nicIndex]; + VirtualEthernetCard device = (VirtualEthernetCard) nicDevices[nicIndex]; if (VirtualSwitchType.StandardVirtualSwitch == vSwitchType) { VirtualEthernetCardNetworkBackingInfo nicBacking = new VirtualEthernetCardNetworkBackingInfo(); @@ -1423,7 +1445,7 @@ private ExecutionResult prepareNetworkElementCommand(IpAssocCommand cmd) { // the check and will try to find it within cluster if (vmMo == null) { if (hyperHost instanceof HostMO) { - ClusterMO clusterMo = new ClusterMO(hyperHost.getContext(), ((HostMO)hyperHost).getParentMor()); + ClusterMO clusterMo = new ClusterMO(hyperHost.getContext(), ((HostMO) hyperHost).getParentMor()); vmMo = clusterMo.findVmOnHyperHost(routerName); } } @@ -1549,13 +1571,13 @@ private DiskTO[] validateDisks(DiskTO[] disks) { for (DiskTO vol : disks) { if (vol.getType() != Volume.Type.ISO) { - VolumeObjectTO volumeTO = (VolumeObjectTO)vol.getData(); + VolumeObjectTO volumeTO = (VolumeObjectTO) vol.getData(); DataStoreTO primaryStore = volumeTO.getDataStore(); if (primaryStore.getUuid() != null && !primaryStore.getUuid().isEmpty()) { validatedDisks.add(vol); } } else if (vol.getType() == Volume.Type.ISO) { - TemplateObjectTO templateTO = (TemplateObjectTO)vol.getData(); + TemplateObjectTO templateTO = (TemplateObjectTO) vol.getData(); if (templateTO.getPath() != null && !templateTO.getPath().isEmpty()) { validatedDisks.add(vol); } @@ -1612,7 +1634,7 @@ protected ScaleVmAnswer execute(ScaleVmCommand cmd) { // Check if license supports the feature VmwareHelper.isFeatureLicensed(hyperHost, FeatureKeyConstants.HOTPLUG); - VmwareHelper.setVmScaleUpConfig(vmConfigSpec, vmSpec.getCpus(), vmSpec.getMaxSpeed(), vmSpec.getMinSpeed(), (int)requestedMaxMemoryInMb, ramMb, + VmwareHelper.setVmScaleUpConfig(vmConfigSpec, vmSpec.getCpus(), vmSpec.getMaxSpeed(), vmSpec.getMinSpeed(), (int) requestedMaxMemoryInMb, ramMb, vmSpec.getLimitCpuUse()); if (!vmMo.configureVm(vmConfigSpec)) { @@ -1772,9 +1794,9 @@ protected StartAnswer execute(StartCommand cmd) { diskInfoBuilder = vmMo.getDiskInfoBuilder(); hasSnapshot = vmMo.hasSnapshot(); if (!hasSnapshot) - vmMo.tearDownDevices(new Class[] {VirtualDisk.class, VirtualEthernetCard.class}); + vmMo.tearDownDevices(new Class[]{VirtualDisk.class, VirtualEthernetCard.class}); else - vmMo.tearDownDevices(new Class[] {VirtualEthernetCard.class}); + vmMo.tearDownDevices(new Class[]{VirtualEthernetCard.class}); if (systemVm) { ensureScsiDiskControllers(vmMo, systemVmScsiControllerType.toString(), numScsiControllerForSystemVm, firstScsiControllerBusNum); } else { @@ -1798,9 +1820,9 @@ protected StartAnswer execute(StartCommand cmd) { diskInfoBuilder = vmMo.getDiskInfoBuilder(); hasSnapshot = vmMo.hasSnapshot(); if (!hasSnapshot) - vmMo.tearDownDevices(new Class[] {VirtualDisk.class, VirtualEthernetCard.class}); + vmMo.tearDownDevices(new Class[]{VirtualDisk.class, VirtualEthernetCard.class}); else - vmMo.tearDownDevices(new Class[] {VirtualEthernetCard.class}); + vmMo.tearDownDevices(new Class[]{VirtualEthernetCard.class}); if (systemVm) { // System volumes doesn't require more than 1 SCSI controller as there is no requirement for data volumes. @@ -1855,7 +1877,7 @@ protected StartAnswer execute(StartCommand cmd) { } tearDownVm(vmMo); } else if (!hyperHost.createBlankVm(vmNameOnVcenter, vmInternalCSName, vmSpec.getCpus(), vmSpec.getMaxSpeed().intValue(), getReservedCpuMHZ(vmSpec), - vmSpec.getLimitCpuUse(), (int)(vmSpec.getMaxRam() / ResourceType.bytesToMiB), getReservedMemoryMb(vmSpec), guestOsId, rootDiskDataStoreDetails.first(), false, + vmSpec.getLimitCpuUse(), (int) (vmSpec.getMaxRam() / ResourceType.bytesToMiB), getReservedMemoryMb(vmSpec), guestOsId, rootDiskDataStoreDetails.first(), false, controllerInfo, systemVm)) { throw new Exception("Failed to create VM. vmName: " + vmInternalCSName); } @@ -1881,7 +1903,7 @@ protected StartAnswer execute(StartCommand cmd) { VirtualMachineConfigSpec vmConfigSpec = new VirtualMachineConfigSpec(); - VmwareHelper.setBasicVmConfig(vmConfigSpec, vmSpec.getCpus(), vmSpec.getMaxSpeed(), getReservedCpuMHZ(vmSpec), (int)(vmSpec.getMaxRam() / (1024 * 1024)), + VmwareHelper.setBasicVmConfig(vmConfigSpec, vmSpec.getCpus(), vmSpec.getMaxSpeed(), getReservedCpuMHZ(vmSpec), (int) (vmSpec.getMaxRam() / (1024 * 1024)), getReservedMemoryMb(vmSpec), guestOsId, vmSpec.getLimitCpuUse()); // Check for multi-cores per socket settings @@ -1899,7 +1921,7 @@ protected StartAnswer execute(StartCommand cmd) { // Check for hotadd settings vmConfigSpec.setMemoryHotAddEnabled(vmMo.isMemoryHotAddSupported(guestOsId)); - String hostApiVersion = ((HostMO)hyperHost).getHostAboutInfo().getApiVersion(); + String hostApiVersion = ((HostMO) hyperHost).getHostAboutInfo().getApiVersion(); if (numCoresPerSocket > 1 && hostApiVersion.compareTo("5.0") < 0) { s_logger.warn("Dynamic scaling of CPU is not supported for Virtual Machines with multi-core vCPUs in case of ESXi hosts 4.1 and prior. Hence CpuHotAdd will not be" + " enabled for Virtual Machine: " + vmInternalCSName); @@ -2012,7 +2034,6 @@ protected StartAnswer execute(StartCommand cmd) { } - // // Setup ROOT/DATA disk devices // @@ -2051,7 +2072,7 @@ protected StartAnswer execute(StartCommand cmd) { if (!hasSnapshot) { deviceConfigSpecArray[i] = new VirtualDeviceConfigSpec(); - VolumeObjectTO volumeTO = (VolumeObjectTO)vol.getData(); + VolumeObjectTO volumeTO = (VolumeObjectTO) vol.getData(); DataStoreTO primaryStore = volumeTO.getDataStore(); Map details = vol.getDetails(); boolean managed = false; @@ -2097,7 +2118,7 @@ protected StartAnswer execute(StartCommand cmd) { // Setup USB devices // if (guestOsId.startsWith("darwin")) { //Mac OS - VirtualDevice[] devices = vmMo.getMatchedDevices(new Class[] {VirtualUSBController.class}); + VirtualDevice[] devices = vmMo.getMatchedDevices(new Class[]{VirtualUSBController.class}); if (devices.length == 0) { s_logger.debug("No USB Controller device on VM Start. Add USB Controller device for Mac OS VM " + vmInternalCSName); @@ -2140,7 +2161,7 @@ protected StartAnswer execute(StartCommand cmd) { for (int nicIndex = nics.length - extraPublicNics; nicIndex < nics.length; nicIndex++) { VirtualDevice nicDevice = peerVmMo.getNicDeviceByIndex(nics[nicIndex].getDeviceId()); if (nicDevice != null) { - String mac = ((VirtualEthernetCard)nicDevice).getMacAddress(); + String mac = ((VirtualEthernetCard) nicDevice).getMacAddress(); if (mac != null) { s_logger.info("Use same MAC as previous RvR, the MAC is " + mac + " for extra NIC with device id: " + nics[nicIndex].getDeviceId()); nics[nicIndex].setMac(mac); @@ -2413,8 +2434,8 @@ protected List copyVAppConfigProductSectionFromOVF(VmConfigInfo * and seting properties values from ovfProperties */ protected void copyVAppConfigsFromTemplate(VmConfigInfo vAppConfig, - List ovfProperties, - VirtualMachineConfigSpec vmConfig) throws Exception { + List ovfProperties, + VirtualMachineConfigSpec vmConfig) throws Exception { VmConfigSpec vmConfigSpec = new VmConfigSpec(); vmConfigSpec.getEula().addAll(vAppConfig.getEula()); vmConfigSpec.setInstallBootStopDelay(vAppConfig.getInstallBootStopDelay()); @@ -2437,10 +2458,10 @@ private String appendFileType(String path, String fileType) { private void resizeRootDiskOnVMStart(VirtualMachineMO vmMo, DiskTO rootDiskTO, VmwareHypervisorHost hyperHost, VmwareContext context) throws Exception { final Pair vdisk = getVirtualDiskInfo(vmMo, appendFileType(rootDiskTO.getPath(), VMDK_EXTENSION)); - assert(vdisk != null); + assert (vdisk != null); Long reqSize = 0L; - final VolumeObjectTO volumeTO = ((VolumeObjectTO)rootDiskTO.getData()); + final VolumeObjectTO volumeTO = ((VolumeObjectTO) rootDiskTO.getData()); if (volumeTO != null) { reqSize = volumeTO.getSize() / 1024; } @@ -2452,7 +2473,7 @@ private void resizeRootDiskOnVMStart(VirtualMachineMO vmMo, DiskTO rootDiskTO, V if (diskChain != null && diskChain.length > 1) { s_logger.warn("Disk chain length for the VM is greater than one, this is not supported"); - throw new CloudRuntimeException("Unsupported VM disk chain length: "+ diskChain.length); + throw new CloudRuntimeException("Unsupported VM disk chain length: " + diskChain.length); } boolean resizingSupported = false; @@ -2462,7 +2483,7 @@ private void resizeRootDiskOnVMStart(VirtualMachineMO vmMo, DiskTO rootDiskTO, V } if (!resizingSupported) { s_logger.warn("Resizing of root disk is only support for scsi device/bus, the provide VM's disk device bus name is " + diskInfo.getDiskDeviceBusName()); - throw new CloudRuntimeException("Unsupported VM root disk device bus: "+ diskInfo.getDiskDeviceBusName()); + throw new CloudRuntimeException("Unsupported VM root disk device bus: " + diskInfo.getDiskDeviceBusName()); } disk.setCapacityInKB(reqSize); @@ -2512,8 +2533,9 @@ protected String replaceNicsMacSequenceInBootArgs(String oldMacSequence, String * Sets video card memory to the one provided in detail svga.vramSize (if provided) on {@code vmConfigSpec}. * 64MB was always set before. * Size must be in KB. - * @param vmMo virtual machine mo - * @param vmSpec virtual machine specs + * + * @param vmMo virtual machine mo + * @param vmSpec virtual machine specs * @param vmConfigSpec virtual machine config spec * @throws Exception exception */ @@ -2531,14 +2553,15 @@ protected void configureVideoCard(VirtualMachineMO vmMo, VirtualMachineTO vmSpec /** * Search for vm video card iterating through vm device list - * @param vmMo virtual machine mo + * + * @param vmMo virtual machine mo * @param svgaVmramSize new svga vram size (in KB) - * @param vmConfigSpec virtual machine config spec + * @param vmConfigSpec virtual machine config spec */ protected void setNewVRamSizeVmVideoCard(VirtualMachineMO vmMo, long svgaVmramSize, VirtualMachineConfigSpec vmConfigSpec) throws Exception { for (VirtualDevice device : vmMo.getAllDeviceList()) { if (device instanceof VirtualMachineVideoCard) { - VirtualMachineVideoCard videoCard = (VirtualMachineVideoCard)device; + VirtualMachineVideoCard videoCard = (VirtualMachineVideoCard) device; modifyVmVideoCardVRamSize(videoCard, vmMo, svgaVmramSize, vmConfigSpec); } } @@ -2546,10 +2569,11 @@ protected void setNewVRamSizeVmVideoCard(VirtualMachineMO vmMo, long svgaVmramSi /** * Modifies vm vram size if it was set to a different size to the one provided in svga.vramSize (user_vm_details or template_vm_details) on {@code vmConfigSpec} - * @param videoCard vm's video card device - * @param vmMo virtual machine mo + * + * @param videoCard vm's video card device + * @param vmMo virtual machine mo * @param svgaVmramSize new svga vram size (in KB) - * @param vmConfigSpec virtual machine config spec + * @param vmConfigSpec virtual machine config spec */ protected void modifyVmVideoCardVRamSize(VirtualMachineVideoCard videoCard, VirtualMachineMO vmMo, long svgaVmramSize, VirtualMachineConfigSpec vmConfigSpec) { if (videoCard.getVideoRamSizeInKB().longValue() != svgaVmramSize) { @@ -2560,9 +2584,10 @@ protected void modifyVmVideoCardVRamSize(VirtualMachineVideoCard videoCard, Virt /** * Add edit spec on {@code vmConfigSpec} to modify svga vram size - * @param videoCard video card device to edit providing the svga vram size + * + * @param videoCard video card device to edit providing the svga vram size * @param svgaVmramSize new svga vram size (in KB) - * @param vmConfigSpec virtual machine spec + * @param vmConfigSpec virtual machine spec */ protected void configureSpecVideoCardNewVRamSize(VirtualMachineVideoCard videoCard, long svgaVmramSize, VirtualMachineConfigSpec vmConfigSpec) { videoCard.setVideoRamSizeInKB(svgaVmramSize); @@ -2583,15 +2608,15 @@ private void tearDownVm(VirtualMachineMO vmMo) throws Exception { boolean hasSnapshot = false; hasSnapshot = vmMo.hasSnapshot(); if (!hasSnapshot) - vmMo.tearDownDevices(new Class[] {VirtualDisk.class, VirtualEthernetCard.class}); + vmMo.tearDownDevices(new Class[]{VirtualDisk.class, VirtualEthernetCard.class}); else - vmMo.tearDownDevices(new Class[] {VirtualEthernetCard.class}); + vmMo.tearDownDevices(new Class[]{VirtualEthernetCard.class}); vmMo.ensureScsiDeviceController(); } int getReservedMemoryMb(VirtualMachineTO vmSpec) { if (vmSpec.getDetails().get(VMwareGuru.VmwareReserveMemory.key()).equalsIgnoreCase("true")) { - return (int)(vmSpec.getMinRam() / ResourceType.bytesToMiB); + return (int) (vmSpec.getMinRam() / ResourceType.bytesToMiB); } return 0; } @@ -2605,9 +2630,9 @@ int getReservedCpuMHZ(VirtualMachineTO vmSpec) { // return the finalized disk chain for startup, from top to bottom private String[] syncDiskChain(DatacenterMO dcMo, VirtualMachineMO vmMo, VirtualMachineTO vmSpec, DiskTO vol, VirtualMachineDiskInfo diskInfo, - HashMap> dataStoresDetails) throws Exception { + HashMap> dataStoresDetails) throws Exception { - VolumeObjectTO volumeTO = (VolumeObjectTO)vol.getData(); + VolumeObjectTO volumeTO = (VolumeObjectTO) vol.getData(); DataStoreTO primaryStore = volumeTO.getDataStore(); Map details = vol.getDetails(); boolean isManaged = false; @@ -2653,8 +2678,7 @@ private String[] syncDiskChain(DatacenterMO dcMo, VirtualMachineMO vmMo, Virtual } datastoreDiskPath = VmwareStorageLayoutHelper.syncVolumeToVmDefaultFolder(dcMo, vmMo.getName(), dsMo, vmdkPath); - } - else { + } else { if (vmdkPath == null) { vmdkPath = dsMo.getName(); } @@ -2669,7 +2693,7 @@ private String[] syncDiskChain(DatacenterMO dcMo, VirtualMachineMO vmMo, Virtual s_logger.warn("Volume " + volumeTO.getId() + " does not seem to exist on datastore, out of sync? path: " + datastoreDiskPath); } - return new String[] {datastoreDiskPath}; + return new String[]{datastoreDiskPath}; } // Pair @@ -2773,7 +2797,7 @@ private static void postNvpConfigBeforeStart(VirtualMachineMO vmMo, VirtualMachi VirtualDeviceBackingInfo backing = nicVirtualDevice.getBacking(); if (backing instanceof VirtualEthernetCardDistributedVirtualPortBackingInfo) { // This NIC is connected to a Distributed Virtual Switch - VirtualEthernetCardDistributedVirtualPortBackingInfo portInfo = (VirtualEthernetCardDistributedVirtualPortBackingInfo)backing; + VirtualEthernetCardDistributedVirtualPortBackingInfo portInfo = (VirtualEthernetCardDistributedVirtualPortBackingInfo) backing; DistributedVirtualSwitchPortConnection port = portInfo.getPort(); String portKey = port.getPortKey(); String portGroupKey = port.getPortgroupKey(); @@ -2797,8 +2821,8 @@ private static void postNvpConfigBeforeStart(VirtualMachineMO vmMo, VirtualMachi if (portKey.equals(dvPort.getKey())) { vmDvPort = dvPort; } - VMwareDVSPortSetting settings = (VMwareDVSPortSetting)dvPort.getConfig().getSetting(); - VmwareDistributedVirtualSwitchVlanIdSpec vlanId = (VmwareDistributedVirtualSwitchVlanIdSpec)settings.getVlan(); + VMwareDVSPortSetting settings = (VMwareDVSPortSetting) dvPort.getConfig().getSetting(); + VmwareDistributedVirtualSwitchVlanIdSpec vlanId = (VmwareDistributedVirtualSwitchVlanIdSpec) settings.getVlan(); s_logger.trace("Found port " + dvPort.getKey() + " with vlan " + vlanId.getVlanId()); if (vlanId.getVlanId() > 0 && vlanId.getVlanId() < 4095) { usedVlans.add(vlanId.getVlanId()); @@ -2810,9 +2834,9 @@ private static void postNvpConfigBeforeStart(VirtualMachineMO vmMo, VirtualMachi } DVPortConfigInfo dvPortConfigInfo = vmDvPort.getConfig(); - VMwareDVSPortSetting settings = (VMwareDVSPortSetting)dvPortConfigInfo.getSetting(); + VMwareDVSPortSetting settings = (VMwareDVSPortSetting) dvPortConfigInfo.getSetting(); - VmwareDistributedVirtualSwitchVlanIdSpec vlanId = (VmwareDistributedVirtualSwitchVlanIdSpec)settings.getVlan(); + VmwareDistributedVirtualSwitchVlanIdSpec vlanId = (VmwareDistributedVirtualSwitchVlanIdSpec) settings.getVlan(); BoolPolicy blocked = settings.getBlocked(); if (blocked.isValue() == Boolean.TRUE) { s_logger.trace("Port is blocked, set a vlanid and unblock"); @@ -2864,7 +2888,7 @@ private static void postNvpConfigBeforeStart(VirtualMachineMO vmMo, VirtualMachi private VirtualMachineDiskInfo getMatchingExistingDisk(VirtualMachineDiskInfoBuilder diskInfoBuilder, DiskTO vol, VmwareHypervisorHost hyperHost, VmwareContext context) throws Exception { if (diskInfoBuilder != null) { - VolumeObjectTO volume = (VolumeObjectTO)vol.getData(); + VolumeObjectTO volume = (VolumeObjectTO) vol.getData(); String dsName = null; String diskBackingFileBaseName = null; @@ -2993,14 +3017,14 @@ private String getDiskController(VirtualMachineMO vmMo, VirtualMachineDiskInfo m } private void postDiskConfigBeforeStart(VirtualMachineMO vmMo, VirtualMachineTO vmSpec, DiskTO[] sortedDisks, int ideControllerKey, - int scsiControllerKey, Map> iqnToData, VmwareHypervisorHost hyperHost, VmwareContext context) throws Exception { + int scsiControllerKey, Map> iqnToData, VmwareHypervisorHost hyperHost, VmwareContext context) throws Exception { VirtualMachineDiskInfoBuilder diskInfoBuilder = vmMo.getDiskInfoBuilder(); for (DiskTO vol : sortedDisks) { if (vol.getType() == Volume.Type.ISO) continue; - VolumeObjectTO volumeTO = (VolumeObjectTO)vol.getData(); + VolumeObjectTO volumeTO = (VolumeObjectTO) vol.getData(); VirtualMachineDiskInfo diskInfo = getMatchingExistingDisk(diskInfoBuilder, vol, hyperHost, context); assert (diskInfo != null); @@ -3185,14 +3209,14 @@ public String getVmdkPath(String path) { } private HashMap> inferDatastoreDetailsFromDiskInfo(VmwareHypervisorHost hyperHost, VmwareContext context, - DiskTO[] disks, Command cmd) throws Exception { + DiskTO[] disks, Command cmd) throws Exception { HashMap> mapIdToMors = new HashMap<>(); assert (hyperHost != null) && (context != null); for (DiskTO vol : disks) { if (vol.getType() != Volume.Type.ISO) { - VolumeObjectTO volumeTO = (VolumeObjectTO)vol.getData(); + VolumeObjectTO volumeTO = (VolumeObjectTO) vol.getData(); DataStoreTO primaryStore = volumeTO.getDataStore(); String poolUuid = primaryStore.getUuid(); @@ -3227,8 +3251,7 @@ private HashMap> inferDatastor if (vmdkPath != null) { datastoreVolumePath = dsMo.getDatastorePath(vmdkPath + VMDK_EXTENSION); - } - else { + } else { datastoreVolumePath = dsMo.getDatastorePath(dsMo.getName() + VMDK_EXTENSION); } @@ -3237,8 +3260,7 @@ private HashMap> inferDatastor } mapIdToMors.put(datastoreName, new Pair<>(morDatastore, new DatastoreMO(context, morDatastore))); - } - else { + } else { ManagedObjectReference morDatastore = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, poolUuid); if (morDatastore == null) { @@ -3350,8 +3372,7 @@ private Pair prepareNetworkFromNicInfo(HostMO ho networkInfo = HypervisorHostHelper.prepareNetwork(switchName, namePrefix, hostMo, getVlanInfo(nicTo, vlanToken), nicTo.getNetworkRateMbps(), nicTo.getNetworkRateMulticastMbps(), _opsTimeout, true, nicTo.getBroadcastType(), nicTo.getUuid(), nicTo.getDetails()); - } - else { + } else { String vlanId = getVlanInfo(nicTo, vlanToken); String svlanId = null; boolean pvlannetwork = (getPvlanInfo(nicTo) == null) ? false : true; @@ -3372,7 +3393,7 @@ private Pair prepareNetworkFromNicInfo(HostMO ho // return Ternary private Ternary getTargetSwitch(NicTO nicTo) throws CloudException { - TrafficType[] supportedTrafficTypes = new TrafficType[] {TrafficType.Guest, TrafficType.Public, TrafficType.Control, TrafficType.Management, TrafficType.Storage}; + TrafficType[] supportedTrafficTypes = new TrafficType[]{TrafficType.Guest, TrafficType.Public, TrafficType.Control, TrafficType.Management, TrafficType.Storage}; TrafficType trafficType = nicTo.getType(); if (!Arrays.asList(supportedTrafficTypes).contains(trafficType)) { @@ -3471,7 +3492,7 @@ private Pair getIsoDatastoreInfo(VmwareHyperviso int templateRootPos = isoUrl.indexOf("template/tmpl"); templateRootPos = (templateRootPos < 0 ? isoUrl.indexOf(ConfigDrive.CONFIGDRIVEDIR) : templateRootPos); - if (templateRootPos < 0 ) { + if (templateRootPos < 0) { throw new Exception("Invalid ISO path info"); } @@ -3653,7 +3674,7 @@ protected Answer execute(GetVmDiskStatsCommand cmd) { if (!(perfValue instanceof PerfEntityMetric)) { continue; } - final List values = ((PerfEntityMetric)perfValue).getValue(); + final List values = ((PerfEntityMetric) perfValue).getValue(); if (values == null || values.isEmpty()) { continue; } @@ -3661,7 +3682,7 @@ protected Answer execute(GetVmDiskStatsCommand cmd) { if (!(value instanceof PerfMetricIntSeries) || !value.getId().getInstance().equals(diskBusName)) { continue; } - final List perfStats = ((PerfMetricIntSeries)value).getValue(); + final List perfStats = ((PerfMetricIntSeries) value).getValue(); if (perfStats.size() > 0) { long sum = 0; for (long val : perfStats) { @@ -3711,7 +3732,7 @@ protected GetVolumeStatsAnswer execute(GetVolumeStatsCommand cmd) { DatacenterMO dcMo = new DatacenterMO(getServiceContext(), dcMor); HashMap statEntry = new HashMap(); - for (String chainInfo : cmd.getVolumeUuids()){ + for (String chainInfo : cmd.getVolumeUuids()) { if (chainInfo != null) { VirtualMachineDiskInfo infoInChain = _gson.fromJson(chainInfo, VirtualMachineDiskInfo.class); if (infoInChain != null) { @@ -3838,7 +3859,7 @@ protected Answer execute(RebootRouterCommand cmd) { s_logger.info("Executing resource RebootRouterCommand: " + _gson.toJson(cmd)); } - RebootAnswer answer = (RebootAnswer)execute((RebootCommand)cmd); + RebootAnswer answer = (RebootAnswer) execute((RebootCommand) cmd); if (answer.getResult()) { String connectResult = connect(cmd.getVmName(), cmd.getPrivateIpAddress()); @@ -4037,7 +4058,7 @@ protected Answer execute(MigrateVmToPoolCommand cmd) { return new Answer(cmd, (Exception) e); } if (s_logger.isDebugEnabled()) { - s_logger.debug("problem" , e); + s_logger.debug("problem", e); } s_logger.error(e.getLocalizedMessage()); return new Answer(cmd, false, "unknown problem: " + e.getLocalizedMessage()); @@ -4051,7 +4072,7 @@ private Answer migrateAndAnswer(VirtualMachineMO vmMo, String poolUuid, VmwareHy // OfflineVmwareMigration: getVolumesFromCommand(cmd); Map volumeDeviceKey = getVolumesFromCommand(vmMo, cmd); if (s_logger.isTraceEnabled()) { - for (Integer diskId: volumeDeviceKey.keySet()) { + for (Integer diskId : volumeDeviceKey.keySet()) { s_logger.trace(String.format("disk to migrate has disk id %d and volumeId %d", diskId, volumeDeviceKey.get(diskId))); } } @@ -4071,12 +4092,12 @@ private Answer migrateAndAnswer(VirtualMachineMO vmMo, String poolUuid, VmwareHy } catch (Exception e) { String msg = "change data store for VM " + vmMo.getVmName() + " failed"; s_logger.error(msg + ": " + e.getLocalizedMessage()); - throw new CloudRuntimeException(msg,e); + throw new CloudRuntimeException(msg, e); } } Answer createAnswerForCmd(VirtualMachineMO vmMo, String poolUuid, Command cmd, Map volumeDeviceKey) throws Exception { - List volumeToList = new ArrayList<>(); + List volumeToList = new ArrayList<>(); VirtualMachineDiskInfoBuilder diskInfoBuilder = vmMo.getDiskInfoBuilder(); VirtualDisk[] disks = vmMo.getAllDiskDevice(); Answer answer; @@ -4099,7 +4120,7 @@ Answer createAnswerForCmd(VirtualMachineMO vmMo, String poolUuid, Command cmd, M newVol.setChainInfo(_gson.toJson(diskInfo)); volumeToList.add(newVol); } - return new MigrateVmToPoolAnswer((MigrateVmToPoolCommand)cmd, volumeToList); + return new MigrateVmToPoolAnswer((MigrateVmToPoolCommand) cmd, volumeToList); } return new Answer(cmd, false, null); } @@ -4107,12 +4128,12 @@ Answer createAnswerForCmd(VirtualMachineMO vmMo, String poolUuid, Command cmd, M private Map getVolumesFromCommand(VirtualMachineMO vmMo, Command cmd) throws Exception { Map volumeDeviceKey = new HashMap(); if (cmd instanceof MigrateVmToPoolCommand) { - MigrateVmToPoolCommand mcmd = (MigrateVmToPoolCommand)cmd; + MigrateVmToPoolCommand mcmd = (MigrateVmToPoolCommand) cmd; for (VolumeTO volume : mcmd.getVolumes()) { addVolumeDiskmapping(vmMo, volumeDeviceKey, volume.getPath(), volume.getId()); } } else if (cmd instanceof MigrateVolumeCommand) { - MigrateVolumeCommand mcmd = (MigrateVolumeCommand)cmd; + MigrateVolumeCommand mcmd = (MigrateVolumeCommand) cmd; addVolumeDiskmapping(vmMo, volumeDeviceKey, mcmd.getVolumePath(), mcmd.getVolumeId()); } return volumeDeviceKey; @@ -4134,7 +4155,7 @@ private void addVolumeDiskmapping(VirtualMachineMO vmMo, Map volu private ManagedObjectReference getTargetDatastoreMOReference(String destinationPool, VmwareHypervisorHost hyperHost) { ManagedObjectReference morDs; try { - if(s_logger.isDebugEnabled()) { + if (s_logger.isDebugEnabled()) { s_logger.debug(String.format("finding datastore %s", destinationPool)); } morDs = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, destinationPool); @@ -4262,7 +4283,7 @@ protected Answer execute(MigrateWithStorageCommand cmd) { throw new CloudRuntimeException(msg); } VmwareManager mgr = tgtHyperHost.getContext().getStockObject(VmwareManager.CONTEXT_STOCK_NAME); - String srcHostApiVersion = ((HostMO)srcHyperHost).getHostAboutInfo().getApiVersion(); + String srcHostApiVersion = ((HostMO) srcHyperHost).getHostAboutInfo().getApiVersion(); // find VM through datacenter (VM is not at the target host yet) vmMo = srcHyperHost.findVmOnPeerHyperHost(vmName); @@ -4449,7 +4470,7 @@ protected Answer execute(MigrateWithStorageCommand cmd) { String msg = "MigrationCommand failed due to " + VmwareHelper.getExceptionMessage(e); s_logger.warn(msg, e); - return new MigrateWithStorageAnswer(cmd, (Exception)e); + return new MigrateWithStorageAnswer(cmd, (Exception) e); } finally { // Cleanup datastores mounted on source host for (String mountedDatastore : mountedDatastoresAtSource) { @@ -4482,15 +4503,15 @@ private Answer migrateVolume(MigrateVolumeCommand cmd) { // we need to spawn a worker VM to attach the volume to and move it vmName = getWorkerName(getServiceContext(), cmd, 0); - // OfflineVmwareMigration: refactor for re-use - // OfflineVmwareMigration: 1. find data(store) + // OfflineVmwareMigration: refactor for re-use + // OfflineVmwareMigration: 1. find data(store) // OfflineVmwareMigration: more robust would be to find the store given the volume as it might have been moved out of band or due to error // example: DatastoreMO existingVmDsMo = new DatastoreMO(dcMo.getContext(), dcMo.findDatastore(fileInDatastore.getDatastoreName())); morSourceDS = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, cmd.getSourcePool().getUuid()); dsMo = new DatastoreMO(hyperHost.getContext(), morSourceDS); s_logger.info("Create worker VM " + vmName); - // OfflineVmwareMigration: 2. create the worker with access to the data(store) + // OfflineVmwareMigration: 2. create the worker with access to the data(store) vmMo = HypervisorHostHelper.createWorkerVM(hyperHost, dsMo, vmName); if (vmMo == null) { // OfflineVmwareMigration: don't throw a general Exception but think of a specific one @@ -4502,21 +4523,21 @@ private Answer migrateVolume(MigrateVolumeCommand cmd) { String vmdkFileName = path + VMDK_EXTENSION; vmdkDataStorePath = VmwareStorageLayoutHelper.getLegacyDatastorePathFromVmdkFileName(dsMo, vmdkFileName); if (!dsMo.fileExists(vmdkDataStorePath)) { - if(s_logger.isDebugEnabled()) { + if (s_logger.isDebugEnabled()) { s_logger.debug(String.format("path not found (%s), trying under '%s'", vmdkFileName, path)); } vmdkDataStorePath = VmwareStorageLayoutHelper.getVmwareDatastorePathFromVmdkFileName(dsMo, path, vmdkFileName); } if (!dsMo.fileExists(vmdkDataStorePath)) { - if(s_logger.isDebugEnabled()) { + if (s_logger.isDebugEnabled()) { s_logger.debug(String.format("path not found (%s), trying under '%s'", vmdkFileName, vmName)); } vmdkDataStorePath = VmwareStorageLayoutHelper.getVmwareDatastorePathFromVmdkFileName(dsMo, vmName, vmdkFileName); } - if(s_logger.isDebugEnabled()) { + if (s_logger.isDebugEnabled()) { s_logger.debug(String.format("attaching %s to %s for migration", vmdkDataStorePath, vmMo.getVmName())); } - vmMo.attachDisk(new String[] { vmdkDataStorePath }, morSourceDS); + vmMo.attachDisk(new String[]{vmdkDataStorePath}, morSourceDS); } // OfflineVmwareMigration: 4. find the (worker-) VM @@ -4532,7 +4553,7 @@ private Answer migrateVolume(MigrateVolumeCommand cmd) { VirtualDisk[] disks = vmMo.getAllDiskDevice(); String format = "disk %d is attached as %s"; for (VirtualDisk disk : disks) { - s_logger.trace(String.format(format,disk.getKey(),vmMo.getVmdkFileBaseName(disk))); + s_logger.trace(String.format(format, disk.getKey(), vmMo.getVmdkFileBaseName(disk))); } } @@ -4579,7 +4600,7 @@ private Answer migrateVolume(MigrateVolumeCommand cmd) { } } if (answer instanceof MigrateVolumeAnswer) { - String newPath = ((MigrateVolumeAnswer)answer).getVolumePath(); + String newPath = ((MigrateVolumeAnswer) answer).getVolumePath(); String vmdkFileName = newPath + VMDK_EXTENSION; try { VmwareStorageLayoutHelper.syncVolumeToRootFolder(dsMo.getOwnerDatacenter().first(), dsMo, newPath, vmName); @@ -4726,7 +4747,7 @@ private VmwareHypervisorHost getTargetHyperHost(DatacenterMO dcMo, String destIp VmwareManager mgr = dcMo.getContext().getStockObject(VmwareManager.CONTEXT_STOCK_NAME); - List ocs = dcMo.getHostPropertiesOnDatacenterHostFolder(new String[] {"name", "parent"}); + List ocs = dcMo.getHostPropertiesOnDatacenterHostFolder(new String[]{"name", "parent"}); if (ocs != null && ocs.size() > 0) { for (ObjectContent oc : ocs) { HostMO hostMo = new HostMO(dcMo.getContext(), oc.getObj()); @@ -4774,15 +4795,13 @@ protected Answer execute(ModifyTargetsCommand cmd) { hostMOs.add(hostMO); } - } - catch (Exception ex) { + } catch (Exception ex) { s_logger.error(ex.getMessage(), ex); throw new CloudRuntimeException(ex.getMessage(), ex); } - } - else { - hostMOs.add((HostMO)hyperHost); + } else { + hostMOs.add((HostMO) hyperHost); } handleTargets(cmd.getAdd(), cmd.getTargetTypeToRemove(), cmd.isRemoveAsync(), cmd.getTargets(), hostMOs); @@ -4844,8 +4863,7 @@ private void handleTargets(boolean add, ModifyTargetsCommand.TargetTypeToRemove if (targets != null && targets.size() > 0) { try { _storageProcessor.handleTargets(add, targetTypeToRemove, isRemoveAsync, targets, hosts); - } - catch (Exception ex) { + } catch (Exception ex) { s_logger.warn(ex.getMessage()); } } @@ -5262,7 +5280,7 @@ protected Answer execute(GetVncPortCommand cmd) { } } - Pair portInfo = vmMo.getVncPort(mgr.getManagementPortGroupByHost((HostMO)hyperHost)); + Pair portInfo = vmMo.getVncPort(mgr.getManagementPortGroupByHost((HostMO) hyperHost)); if (s_logger.isTraceEnabled()) { s_logger.trace("Found vnc port info. vm: " + cmd.getName() + " host: " + portInfo.first() + ", vnc port: " + portInfo.second()); @@ -5317,7 +5335,7 @@ protected Answer execute(PingTestCommand cmd) { VmwareHypervisorHost hyperHost = getHyperHost(context); try { - HostMO hostMo = (HostMO)hyperHost; + HostMO hostMo = (HostMO) hyperHost; ClusterMO clusterMo = new ClusterMO(context, hostMo.getHyperHostCluster()); VmwareManager mgr = context.getStockObject(VmwareManager.CONTEXT_STOCK_NAME); @@ -5419,7 +5437,7 @@ public PrimaryStorageDownloadAnswer execute(PrimaryStorageDownloadCommand cmd) { try { VmwareContext context = getServiceContext(); VmwareManager mgr = context.getStockObject(VmwareManager.CONTEXT_STOCK_NAME); - return (PrimaryStorageDownloadAnswer)mgr.getStorageManager().execute(this, cmd); + return (PrimaryStorageDownloadAnswer) mgr.getStorageManager().execute(this, cmd); } catch (Throwable e) { if (e instanceof RemoteException) { s_logger.warn("Encounter remote exception to vCenter, invalidate VMware session context"); @@ -5512,7 +5530,7 @@ protected Answer execute(UnregisterNicCommand cmd) { // Get a list of all the hosts in this cluster @SuppressWarnings("unchecked") - List hosts = (List)context.getVimClient().getDynamicProperty(clusterMO, "host"); + List hosts = (List) context.getVimClient().getDynamicProperty(clusterMO, "host"); if (hosts == null) { return new Answer(cmd, false, "No hosts in cluster, which is pretty weird"); } @@ -5557,7 +5575,7 @@ public CopyVolumeAnswer execute(CopyVolumeCommand cmd) { try { VmwareContext context = getServiceContext(); VmwareManager mgr = context.getStockObject(VmwareManager.CONTEXT_STOCK_NAME); - return (CopyVolumeAnswer)mgr.getStorageManager().execute(this, cmd); + return (CopyVolumeAnswer) mgr.getStorageManager().execute(this, cmd); } catch (Throwable e) { if (e instanceof RemoteException) { s_logger.warn("Encounter remote exception to vCenter, invalidate VMware session context"); @@ -5611,13 +5629,13 @@ private void gcAndKillHungWorkerVMs() { s_logger.info("Scan hung worker VM to recycle"); - int workerKey = ((HostMO)hyperHost).getCustomFieldKey("VirtualMachine", CustomFieldConstants.CLOUD_WORKER); - int workerTagKey = ((HostMO)hyperHost).getCustomFieldKey("VirtualMachine", CustomFieldConstants.CLOUD_WORKER_TAG); + int workerKey = ((HostMO) hyperHost).getCustomFieldKey("VirtualMachine", CustomFieldConstants.CLOUD_WORKER); + int workerTagKey = ((HostMO) hyperHost).getCustomFieldKey("VirtualMachine", CustomFieldConstants.CLOUD_WORKER_TAG); String workerPropName = String.format("value[%d]", workerKey); String workerTagPropName = String.format("value[%d]", workerTagKey); // GC worker that has been running for too long - ObjectContent[] ocs = hyperHost.getVmPropertiesOnHyperHost(new String[] {"name", "config.template", workerPropName, workerTagPropName,}); + ObjectContent[] ocs = hyperHost.getVmPropertiesOnHyperHost(new String[]{"name", "config.template", workerPropName, workerTagPropName,}); if (ocs != null) { for (ObjectContent oc : ocs) { List props = oc.getPropSet(); @@ -5628,13 +5646,13 @@ private void gcAndKillHungWorkerVMs() { for (DynamicProperty prop : props) { if (prop.getName().equals("config.template")) { - template = (Boolean)prop.getVal(); + template = (Boolean) prop.getVal(); } else if (prop.getName().equals(workerPropName)) { - CustomFieldStringValue val = (CustomFieldStringValue)prop.getVal(); + CustomFieldStringValue val = (CustomFieldStringValue) prop.getVal(); if (val != null && val.getValue() != null && val.getValue().equalsIgnoreCase("true")) isWorker = true; } else if (prop.getName().equals(workerTagPropName)) { - CustomFieldStringValue val = (CustomFieldStringValue)prop.getVal(); + CustomFieldStringValue val = (CustomFieldStringValue) prop.getVal(); workerTag = val.getValue(); } } @@ -5680,14 +5698,14 @@ public StartupCommand[] initialize() { try { VmwareHypervisorHost hyperHost = getHyperHost(context); assert (hyperHost instanceof HostMO); - if (!((HostMO)hyperHost).isHyperHostConnected()) { + if (!((HostMO) hyperHost).isHyperHostConnected()) { s_logger.info("Host " + hyperHost.getHyperHostName() + " is not in connected state"); return null; } - ((HostMO)hyperHost).enableVncOnHostFirewall(); + ((HostMO) hyperHost).enableVncOnHostFirewall(); - AboutInfo aboutInfo = ((HostMO)hyperHost).getHostAboutInfo(); + AboutInfo aboutInfo = ((HostMO) hyperHost).getHostAboutInfo(); hostApiVersion = aboutInfo.getApiVersion(); } catch (Exception e) { @@ -5723,7 +5741,7 @@ private List initializeLocalStorage() { try { VmwareHypervisorHost hyperHost = getHyperHost(context); if (hyperHost instanceof HostMO) { - HostMO hostMo = (HostMO)hyperHost; + HostMO hostMo = (HostMO) hyperHost; List> dsList = hostMo.getLocalDatastoreOnHost(); for (Pair dsPair : dsList) { @@ -5804,15 +5822,15 @@ private String getIqn() { VmwareHypervisorHost hyperHost = getHyperHost(getServiceContext()); if (hyperHost instanceof HostMO) { - HostMO host = (HostMO)hyperHost; + HostMO host = (HostMO) hyperHost; HostStorageSystemMO hostStorageSystem = host.getHostStorageSystemMO(); for (HostHostBusAdapter hba : hostStorageSystem.getStorageDeviceInfo().getHostBusAdapter()) { if (hba instanceof HostInternetScsiHba) { - HostInternetScsiHba hostInternetScsiHba = (HostInternetScsiHba)hba; + HostInternetScsiHba hostInternetScsiHba = (HostInternetScsiHba) hba; if (hostInternetScsiHba.isIsSoftwareBased()) { - return ((HostInternetScsiHba)hba).getIScsiName(); + return ((HostInternetScsiHba) hba).getIScsiName(); } } } @@ -5837,7 +5855,7 @@ private void fillHostHardwareInfo(VmwareContext serviceContext, StartupRoutingCo cmd.setDom0MinMemory(0); cmd.setSpeed(summary.getCpuSpeed()); cmd.setCpuSockets(summary.getCpuSockets()); - cmd.setCpus((int)summary.getCpuCount()); + cmd.setCpus((int) summary.getCpuCount()); cmd.setMemory(summary.getMemoryBytes()); } @@ -5849,7 +5867,7 @@ private void fillHostNetworkInfo(VmwareContext serviceContext, StartupRoutingCom assert (hyperHost instanceof HostMO); VmwareManager mgr = hyperHost.getContext().getStockObject(VmwareManager.CONTEXT_STOCK_NAME); - VmwareHypervisorHostNetworkSummary summary = hyperHost.getHyperHostNetworkSummary(mgr.getManagementPortGroupByHost((HostMO)hyperHost)); + VmwareHypervisorHostNetworkSummary summary = hyperHost.getHyperHostNetworkSummary(mgr.getManagementPortGroupByHost((HostMO) hyperHost)); if (summary == null) { throw new Exception("No ESX(i) host found"); } @@ -5994,7 +6012,7 @@ private VirtualMachineGuestOsIdentifier translateGuestOsIdentifier(String cpuArc private HashMap getHostVmStateReport() throws Exception { VmwareHypervisorHost hyperHost = getHyperHost(getServiceContext()); - int key = ((HostMO)hyperHost).getCustomFieldKey("VirtualMachine", CustomFieldConstants.CLOUD_VM_INTERNAL_NAME); + int key = ((HostMO) hyperHost).getCustomFieldKey("VirtualMachine", CustomFieldConstants.CLOUD_VM_INTERNAL_NAME); if (key == 0) { s_logger.warn("Custom field " + CustomFieldConstants.CLOUD_VM_INTERNAL_NAME + " is not registered ?!"); } @@ -6002,7 +6020,7 @@ private HashMap getHostVmStateReport() throws Ex // CLOUD_VM_INTERNAL_NAME stores the internal CS generated vm name. This was earlier stored in name. Now, name can be either the hostname or // the internal CS name, but the custom field CLOUD_VM_INTERNAL_NAME always stores the internal CS name. - ObjectContent[] ocs = hyperHost.getVmPropertiesOnHyperHost(new String[] {"name", "runtime.powerState", "config.template", instanceNameCustomField}); + ObjectContent[] ocs = hyperHost.getVmPropertiesOnHyperHost(new String[]{"name", "runtime.powerState", "config.template", instanceNameCustomField}); HashMap newStates = new HashMap(); if (ocs != null && ocs.length > 0) { @@ -6020,12 +6038,12 @@ private HashMap getHostVmStateReport() throws Ex isTemplate = true; } } else if (objProp.getName().equals("runtime.powerState")) { - powerState = (VirtualMachinePowerState)objProp.getVal(); + powerState = (VirtualMachinePowerState) objProp.getVal(); } else if (objProp.getName().equals("name")) { - name = (String)objProp.getVal(); + name = (String) objProp.getVal(); } else if (objProp.getName().contains(instanceNameCustomField)) { if (objProp.getVal() != null) - VMInternalCSName = ((CustomFieldStringValue)objProp.getVal()).getValue(); + VMInternalCSName = ((CustomFieldStringValue) objProp.getVal()).getValue(); } else { assert (false); } @@ -6046,7 +6064,7 @@ private HashMap getHostVmStateReport() throws Ex private HashMap getVmStates() throws Exception { VmwareHypervisorHost hyperHost = getHyperHost(getServiceContext()); - int key = ((HostMO)hyperHost).getCustomFieldKey("VirtualMachine", CustomFieldConstants.CLOUD_VM_INTERNAL_NAME); + int key = ((HostMO) hyperHost).getCustomFieldKey("VirtualMachine", CustomFieldConstants.CLOUD_VM_INTERNAL_NAME); if (key == 0) { s_logger.warn("Custom field " + CustomFieldConstants.CLOUD_VM_INTERNAL_NAME + " is not registered ?!"); } @@ -6054,7 +6072,7 @@ private HashMap getVmStates() throws Exception { // CLOUD_VM_INTERNAL_NAME stores the internal CS generated vm name. This was earlier stored in name. Now, name can be either the hostname or // the internal CS name, but the custom field CLOUD_VM_INTERNAL_NAME always stores the internal CS name. - ObjectContent[] ocs = hyperHost.getVmPropertiesOnHyperHost(new String[] {"name", "runtime.powerState", "config.template", instanceNameCustomField}); + ObjectContent[] ocs = hyperHost.getVmPropertiesOnHyperHost(new String[]{"name", "runtime.powerState", "config.template", instanceNameCustomField}); HashMap newStates = new HashMap(); if (ocs != null && ocs.length > 0) { @@ -6072,12 +6090,12 @@ private HashMap getVmStates() throws Exception { isTemplate = true; } } else if (objProp.getName().equals("runtime.powerState")) { - powerState = (VirtualMachinePowerState)objProp.getVal(); + powerState = (VirtualMachinePowerState) objProp.getVal(); } else if (objProp.getName().equals("name")) { - name = (String)objProp.getVal(); + name = (String) objProp.getVal(); } else if (objProp.getName().contains(instanceNameCustomField)) { if (objProp.getVal() != null) - VMInternalCSName = ((CustomFieldStringValue)objProp.getVal()).getValue(); + VMInternalCSName = ((CustomFieldStringValue) objProp.getVal()).getValue(); } else { assert (false); } @@ -6138,7 +6156,7 @@ private HashMap getVmStats(List vmNames) throws Ex } } - int key = ((HostMO)hyperHost).getCustomFieldKey("VirtualMachine", CustomFieldConstants.CLOUD_VM_INTERNAL_NAME); + int key = ((HostMO) hyperHost).getCustomFieldKey("VirtualMachine", CustomFieldConstants.CLOUD_VM_INTERNAL_NAME); if (key == 0) { s_logger.warn("Custom field " + CustomFieldConstants.CLOUD_VM_INTERNAL_NAME + " is not registered ?!"); } @@ -6151,8 +6169,8 @@ private HashMap getVmStats(List vmNames) throws Ex final String memMbStr = "config.hardware.memoryMB"; final String allocatedCpuStr = "summary.runtime.maxCpuUsage"; - ObjectContent[] ocs = hyperHost.getVmPropertiesOnHyperHost(new String[] { - "name", numCpuStr, cpuUseStr, guestMemUseStr, memLimitStr, memMbStr,allocatedCpuStr, instanceNameCustomField + ObjectContent[] ocs = hyperHost.getVmPropertiesOnHyperHost(new String[]{ + "name", numCpuStr, cpuUseStr, guestMemUseStr, memLimitStr, memMbStr, allocatedCpuStr, instanceNameCustomField }); if (ocs != null && ocs.length > 0) { @@ -6173,7 +6191,7 @@ private HashMap getVmStats(List vmNames) throws Ex vmNameOnVcenter = objProp.getVal().toString(); } else if (objProp.getName().contains(instanceNameCustomField)) { if (objProp.getVal() != null) - vmInternalCSName = ((CustomFieldStringValue)objProp.getVal()).getValue(); + vmInternalCSName = ((CustomFieldStringValue) objProp.getVal()).getValue(); } else if (objProp.getName().equals(guestMemUseStr)) { guestMemusage = objProp.getVal().toString(); } else if (objProp.getName().equals(numCpuStr)) { @@ -6184,12 +6202,12 @@ private HashMap getVmStats(List vmNames) throws Ex memlimit = objProp.getVal().toString(); } else if (objProp.getName().equals(memMbStr)) { memkb = objProp.getVal().toString(); - } else if (objProp.getName().equals(allocatedCpuStr)){ - allocatedCpu = NumberUtils.toDouble(objProp.getVal().toString()); + } else if (objProp.getName().equals(allocatedCpuStr)) { + allocatedCpu = NumberUtils.toDouble(objProp.getVal().toString()); } } - maxCpuUsage = (maxCpuUsage/allocatedCpu)*100; + maxCpuUsage = (maxCpuUsage / allocatedCpu) * 100; if (vmInternalCSName != null) { name = vmInternalCSName; } else { @@ -6276,7 +6294,7 @@ private HashMap getVmStats(List vmNames) throws Ex } } - final VmStatsEntry vmStats = new VmStatsEntry( NumberUtils.toDouble(memkb)*1024,NumberUtils.toDouble(guestMemusage)*1024,NumberUtils.toDouble(memlimit)*1024, + final VmStatsEntry vmStats = new VmStatsEntry(NumberUtils.toDouble(memkb) * 1024, NumberUtils.toDouble(guestMemusage) * 1024, NumberUtils.toDouble(memlimit) * 1024, maxCpuUsage, networkReadKBs, networkWriteKBs, NumberUtils.toInt(numberCPUs), "vm"); vmStats.setDiskReadIOs(diskReadIops); vmStats.setDiskWriteIOs(diskWriteIops); @@ -6401,7 +6419,7 @@ private static HostStatsEntry getHyperHostStats(VmwareHypervisorHost hyperHost) HostStatsEntry entry = new HostStatsEntry(); entry.setEntityType("host"); - double cpuUtilization = ((double)(hardwareSummary.getTotalCpu() - hardwareSummary.getEffectiveCpu()) / (double)hardwareSummary.getTotalCpu() * 100); + double cpuUtilization = ((double) (hardwareSummary.getTotalCpu() - hardwareSummary.getEffectiveCpu()) / (double) hardwareSummary.getTotalCpu() * 100); entry.setCpuUtilization(cpuUtilization); entry.setTotalMemoryKBs(hardwareSummary.getTotalMemory() / 1024); entry.setFreeMemoryKBs(hardwareSummary.getEffectiveMemory() * 1024); @@ -6435,14 +6453,14 @@ public boolean configure(String name, Map params) throws Configu try { _name = name; - _url = (String)params.get("url"); - _username = (String)params.get("username"); - _password = (String)params.get("password"); - _dcId = (String)params.get("zone"); - _pod = (String)params.get("pod"); - _cluster = (String)params.get("cluster"); + _url = (String) params.get("url"); + _username = (String) params.get("username"); + _password = (String) params.get("password"); + _dcId = (String) params.get("zone"); + _pod = (String) params.get("pod"); + _cluster = (String) params.get("cluster"); - _guid = (String)params.get("guid"); + _guid = (String) params.get("guid"); String[] tokens = _guid.split("@"); _vCenterAddress = tokens[1]; _morHyperHost = new ManagedObjectReference(); @@ -6450,8 +6468,8 @@ public boolean configure(String name, Map params) throws Configu _morHyperHost.setType(hostTokens[0]); _morHyperHost.setValue(hostTokens[1]); - _guestTrafficInfo = (VmwareTrafficLabel)params.get("guestTrafficInfo"); - _publicTrafficInfo = (VmwareTrafficLabel)params.get("publicTrafficInfo"); + _guestTrafficInfo = (VmwareTrafficLabel) params.get("guestTrafficInfo"); + _publicTrafficInfo = (VmwareTrafficLabel) params.get("publicTrafficInfo"); VmwareContext context = getServiceContext(); VmwareManager mgr = context.getStockObject(VmwareManager.CONTEXT_STOCK_NAME); if (mgr == null) { @@ -6482,14 +6500,14 @@ public boolean configure(String name, Map params) throws Configu } if (_privateNetworkVSwitchName == null) { - _privateNetworkVSwitchName = (String)params.get("private.network.vswitch.name"); + _privateNetworkVSwitchName = (String) params.get("private.network.vswitch.name"); } - String value = (String)params.get("vmware.recycle.hung.wokervm"); + String value = (String) params.get("vmware.recycle.hung.wokervm"); if (value != null && value.equalsIgnoreCase("true")) _recycleHungWorker = true; - value = (String)params.get("vmware.root.disk.controller"); + value = (String) params.get("vmware.root.disk.controller"); if (value != null && value.equalsIgnoreCase("scsi")) _rootDiskController = DiskControllerType.scsi; else if (value != null && value.equalsIgnoreCase("ide")) @@ -6497,7 +6515,7 @@ else if (value != null && value.equalsIgnoreCase("ide")) else _rootDiskController = DiskControllerType.osdefault; - Integer intObj = (Integer)params.get("ports.per.dvportgroup"); + Integer intObj = (Integer) params.get("ports.per.dvportgroup"); if (intObj != null) _portsPerDvPortGroup = intObj.intValue(); @@ -6505,25 +6523,25 @@ else if (value != null && value.equalsIgnoreCase("ide")) + _publicTrafficInfo.getVirtualSwitchType() + " : " + _publicTrafficInfo.getVirtualSwitchName() + ", guest traffic over " + _guestTrafficInfo.getVirtualSwitchType() + " : " + _guestTrafficInfo.getVirtualSwitchName()); - Boolean boolObj = (Boolean)params.get("vmware.create.full.clone"); + Boolean boolObj = (Boolean) params.get("vmware.create.full.clone"); if (boolObj != null && boolObj.booleanValue()) { _fullCloneFlag = true; } else { _fullCloneFlag = false; } - boolObj = (Boolean)params.get("vm.instancename.flag"); + boolObj = (Boolean) params.get("vm.instancename.flag"); if (boolObj != null && boolObj.booleanValue()) { _instanceNameFlag = true; } else { _instanceNameFlag = false; } - value = (String)params.get("scripts.timeout"); + value = (String) params.get("scripts.timeout"); int timeout = NumbersUtil.parseInt(value, 1440) * 1000; storageNfsVersion = NfsSecondaryStorageResource.retrieveNfsVersionFromParams(params); - _storageProcessor = new VmwareStorageProcessor((VmwareHostService)this, _fullCloneFlag, (VmwareStorageMount)mgr, timeout, this, _shutdownWaitMs, null, + _storageProcessor = new VmwareStorageProcessor((VmwareHostService) this, _fullCloneFlag, (VmwareStorageMount) mgr, timeout, this, _shutdownWaitMs, null, storageNfsVersion); storageHandler = new VmwareStorageSubsystemCommandHandler(_storageProcessor, storageNfsVersion); @@ -6717,11 +6735,12 @@ public Answer execute(DestroyCommand cmd) { /** * Use data center to look for vm, instead of randomly picking up a cluster
* (in multiple cluster environments vm could not be found if wrong cluster was chosen) - * @param context vmware context + * + * @param context vmware context * @param hyperHost vmware hv host - * @param vol volume + * @param vol volume * @return a virtualmachinemo if could be found on datacenter. - * @throws Exception if there is an error while finding vm + * @throws Exception if there is an error while finding vm * @throws CloudRuntimeException if datacenter cannot be found */ protected VirtualMachineMO findVmOnDatacenter(VmwareContext context, VmwareHypervisorHost hyperHost, VolumeTO vol) throws Exception { @@ -6738,7 +6757,7 @@ public String getAbsoluteVmdkFile(VirtualDisk disk) { String vmdkAbsFile = null; VirtualDeviceBackingInfo backingInfo = disk.getBacking(); if (backingInfo instanceof VirtualDiskFlatVer2BackingInfo) { - VirtualDiskFlatVer2BackingInfo diskBackingInfo = (VirtualDiskFlatVer2BackingInfo)backingInfo; + VirtualDiskFlatVer2BackingInfo diskBackingInfo = (VirtualDiskFlatVer2BackingInfo) backingInfo; vmdkAbsFile = diskBackingInfo.getFileName(); } return vmdkAbsFile; @@ -6777,4 +6796,298 @@ private static File fetchSystemVmKeyFile() { } return keyFile; } + + private List getUnmanageInstanceDisks(VirtualMachineMO vmMo) { + List instanceDisks = new ArrayList<>(); + VirtualDisk[] disks = null; + try { + disks = vmMo.getAllDiskDevice(); + } catch (Exception e) { + s_logger.info("Unable to retrieve unmanaged instance disks. " + e.getMessage()); + } + if (disks != null) { + for (VirtualDevice diskDevice : disks) { + try { + if (diskDevice instanceof VirtualDisk) { + UnmanagedInstanceTO.Disk instanceDisk = new UnmanagedInstanceTO.Disk(); + VirtualDisk disk = (VirtualDisk) diskDevice; + instanceDisk.setDiskId(disk.getDiskObjectId()); + instanceDisk.setLabel(disk.getDeviceInfo() != null ? disk.getDeviceInfo().getLabel() : ""); + instanceDisk.setFileBaseName(vmMo.getVmdkFileBaseName(disk)); + instanceDisk.setImagePath(getAbsoluteVmdkFile(disk)); + instanceDisk.setCapacity(disk.getCapacityInBytes()); + instanceDisk.setPosition(diskDevice.getUnitNumber()); + DatastoreFile file = new DatastoreFile(getAbsoluteVmdkFile(disk)); + if (!Strings.isNullOrEmpty(file.getFileBaseName()) && !Strings.isNullOrEmpty(file.getDatastoreName())) { + VirtualMachineDiskInfo diskInfo = vmMo.getDiskInfoBuilder().getDiskInfoByBackingFileBaseName(file.getFileBaseName(), file.getDatastoreName()); + instanceDisk.setChainInfo(getGson().toJson(diskInfo)); + } + for (VirtualDevice device : vmMo.getAllDeviceList()) { + if (diskDevice.getControllerKey() == device.getKey()) { + if (device instanceof VirtualIDEController) { + instanceDisk.setController(DiskControllerType.getType(device.getClass().getSimpleName()).toString()); + instanceDisk.setControllerUnit(((VirtualIDEController) device).getBusNumber()); + } else if (device instanceof VirtualSCSIController) { + instanceDisk.setController(DiskControllerType.getType(device.getClass().getSimpleName()).toString()); + instanceDisk.setControllerUnit(((VirtualSCSIController) device).getBusNumber()); + } else { + instanceDisk.setController(DiskControllerType.none.toString()); + } + break; + } + } + if (disk.getBacking() instanceof VirtualDeviceFileBackingInfo) { + VirtualDeviceFileBackingInfo diskBacking = (VirtualDeviceFileBackingInfo) disk.getBacking(); + ManagedObjectReference morDs = diskBacking.getDatastore(); + DatastoreInfo info = (DatastoreInfo)vmMo.getContext().getVimClient().getDynamicProperty(diskBacking.getDatastore(), "info"); + if (info instanceof NasDatastoreInfo) { + NasDatastoreInfo dsInfo = (NasDatastoreInfo) info; + instanceDisk.setDatastoreName(dsInfo.getName()); + if (dsInfo.getNas() != null) { + instanceDisk.setDatastoreHost(dsInfo.getNas().getRemoteHost()); + instanceDisk.setDatastorePath(dsInfo.getNas().getRemotePath()); + instanceDisk.setDatastoreType(dsInfo.getNas().getType()); + } + } else if (info instanceof VmfsDatastoreInfo) { + VmfsDatastoreInfo dsInfo = (VmfsDatastoreInfo) info; + instanceDisk.setDatastoreName(dsInfo.getVmfs().getName()); + instanceDisk.setDatastoreType(dsInfo.getVmfs().getType()); + } else { + String msg = String.format("Unmanaged instance disk: %s is on unsupported datastore %s", instanceDisk.getDiskId(), info.getClass().getSimpleName()); + s_logger.error(msg); + throw new Exception(msg); + } + } + s_logger.info(vmMo.getName() + " " + disk.getDeviceInfo().getLabel() + " " + disk.getDeviceInfo().getSummary() + " " + disk.getDiskObjectId() + " " + disk.getCapacityInKB() + " " + instanceDisk.getController()); + instanceDisks.add(instanceDisk); + } + } catch (Exception e) { + s_logger.info("Unable to retrieve unmanaged instance disk info. " + e.getMessage()); + } + } + Collections.sort(instanceDisks, new Comparator() { + @Override + public int compare(final UnmanagedInstanceTO.Disk disk1, final UnmanagedInstanceTO.Disk disk2) { + return extractInt(disk1) - extractInt(disk2); + } + + int extractInt(UnmanagedInstanceTO.Disk disk) { + String num = disk.getLabel().replaceAll("\\D", ""); + // return 0 if no digits found + return num.isEmpty() ? 0 : Integer.parseInt(num); + } + }); + } + return instanceDisks; + } + + private List getUnmanageInstanceNics(VmwareHypervisorHost hyperHost, VirtualMachineMO vmMo) { + List instanceNics = new ArrayList<>(); + + HashMap> guestNicMacIPAddressMap = new HashMap<>(); + try { + GuestInfo guestInfo = vmMo.getGuestInfo(); + if (guestInfo.getToolsStatus() == VirtualMachineToolsStatus.TOOLS_OK) { + for (GuestNicInfo nicInfo: guestInfo.getNet()) { + if (CollectionUtils.isNotEmpty(nicInfo.getIpAddress())) { + List ipAddresses = new ArrayList<>(); + for (String ipAddress : nicInfo.getIpAddress()) { + if (NetUtils.isValidIp4(ipAddress)) { + ipAddresses.add(ipAddress); + } + } + guestNicMacIPAddressMap.put(nicInfo.getMacAddress(), ipAddresses); + } + } + } else { + s_logger.info(String.format("Unable to retrieve guest nics for instance: %s from VMware tools as tools status: %s", vmMo.getName(), guestInfo.getToolsStatus().toString())); + } + } catch (Exception e) { + s_logger.info("Unable to retrieve guest nics for instance from VMware tools. " + e.getMessage()); + } + VirtualDevice[] nics = null; + try { + nics = vmMo.getNicDevices(); + } catch (Exception e) { + s_logger.info("Unable to retrieve unmanaged instance nics. " + e.getMessage()); + } + if (nics != null) { + for (VirtualDevice nic : nics) { + try { + VirtualEthernetCard ethCardDevice = (VirtualEthernetCard) nic; + s_logger.error(nic.getClass().getCanonicalName() + " " + nic.getBacking().getClass().getCanonicalName() + " " + ethCardDevice.getMacAddress()); + UnmanagedInstanceTO.Nic instanceNic = new UnmanagedInstanceTO.Nic(); + instanceNic.setNicId(ethCardDevice.getDeviceInfo().getLabel()); + if (ethCardDevice instanceof VirtualPCNet32) { + instanceNic.setAdapterType(VirtualEthernetCardType.PCNet32.toString()); + } else if (ethCardDevice instanceof VirtualVmxnet2) { + instanceNic.setAdapterType(VirtualEthernetCardType.Vmxnet2.toString()); + } else if (ethCardDevice instanceof VirtualVmxnet3) { + instanceNic.setAdapterType(VirtualEthernetCardType.Vmxnet3.toString()); + } else { + instanceNic.setAdapterType(VirtualEthernetCardType.E1000.toString()); + } + instanceNic.setMacAddress(ethCardDevice.getMacAddress()); + if (guestNicMacIPAddressMap.containsKey(instanceNic.getMacAddress())) { + instanceNic.setIpAddress(guestNicMacIPAddressMap.get(instanceNic.getMacAddress())); + } + if (ethCardDevice.getSlotInfo() != null) { + instanceNic.setPciSlot(ethCardDevice.getSlotInfo().toString()); + } + VirtualDeviceBackingInfo backing = ethCardDevice.getBacking(); + if (backing instanceof VirtualEthernetCardDistributedVirtualPortBackingInfo) { + VirtualEthernetCardDistributedVirtualPortBackingInfo backingInfo = (VirtualEthernetCardDistributedVirtualPortBackingInfo) backing; + DistributedVirtualSwitchPortConnection port = backingInfo.getPort(); + String portKey = port.getPortKey(); + String portGroupKey = port.getPortgroupKey(); + String dvSwitchUuid = port.getSwitchUuid(); + + s_logger.debug("NIC " + nic.toString() + " is connected to dvSwitch " + dvSwitchUuid + " pg " + portGroupKey + " port " + portKey); + + ManagedObjectReference dvSwitchManager = vmMo.getContext().getVimClient().getServiceContent().getDvSwitchManager(); + ManagedObjectReference dvSwitch = vmMo.getContext().getVimClient().getService().queryDvsByUuid(dvSwitchManager, dvSwitchUuid); + + // Get all ports + DistributedVirtualSwitchPortCriteria criteria = new DistributedVirtualSwitchPortCriteria(); + criteria.setInside(true); + criteria.getPortgroupKey().add(portGroupKey); + List dvPorts = vmMo.getContext().getVimClient().getService().fetchDVPorts(dvSwitch, criteria); + + for (DistributedVirtualPort dvPort : dvPorts) { + // Find the port for this NIC by portkey + if (portKey.equals(dvPort.getKey())) { + VMwareDVSPortSetting settings = (VMwareDVSPortSetting) dvPort.getConfig().getSetting(); + if (settings.getVlan() instanceof VmwareDistributedVirtualSwitchVlanIdSpec) { + VmwareDistributedVirtualSwitchVlanIdSpec vlanId = (VmwareDistributedVirtualSwitchVlanIdSpec) settings.getVlan(); + s_logger.trace("Found port " + dvPort.getKey() + " with vlan " + vlanId.getVlanId()); + if (vlanId.getVlanId() > 0 && vlanId.getVlanId() < 4095) { + instanceNic.setVlan(vlanId.getVlanId()); + } + } else if (settings.getVlan() instanceof VmwareDistributedVirtualSwitchPvlanSpec) { + VmwareDistributedVirtualSwitchPvlanSpec pvlanSpec = (VmwareDistributedVirtualSwitchPvlanSpec) settings.getVlan(); + s_logger.trace("Found port " + dvPort.getKey() + " with pvlan " + pvlanSpec.getPvlanId()); + if (pvlanSpec.getPvlanId() > 0 && pvlanSpec.getPvlanId() < 4095) { + DistributedVirtualSwitchMO dvSwitchMo = new DistributedVirtualSwitchMO(vmMo.getContext(), dvSwitch); + Pair vlanDetails = dvSwitchMo.retrieveVlanFromPvlan(pvlanSpec.getPvlanId(), dvSwitch); + if (vlanDetails != null && vlanDetails.first() != null && vlanDetails.second() != null) { + instanceNic.setVlan(vlanDetails.first()); + instanceNic.setPvlan(pvlanSpec.getPvlanId()); + instanceNic.setPvlanType(vlanDetails.second().toString()); + } + } + } + break; + } + } + } else if (backing instanceof VirtualEthernetCardNetworkBackingInfo) { + VirtualEthernetCardNetworkBackingInfo backingInfo = (VirtualEthernetCardNetworkBackingInfo) backing; + instanceNic.setNetwork(backingInfo.getDeviceName()); + if (hyperHost instanceof HostMO) { + HostMO hostMo = (HostMO) hyperHost; + HostPortGroupSpec portGroupSpec = hostMo.getHostPortGroupSpec(backingInfo.getDeviceName()); + instanceNic.setVlan(portGroupSpec.getVlanId()); + } + } + instanceNics.add(instanceNic); + } catch (Exception e) { + s_logger.info("Unable to retrieve unmanaged instance nic info. " + e.getMessage()); + } + } + Collections.sort(instanceNics, new Comparator() { + @Override + public int compare(final UnmanagedInstanceTO.Nic nic1, final UnmanagedInstanceTO.Nic nic2) { + return extractInt(nic1) - extractInt(nic2); + } + + int extractInt(UnmanagedInstanceTO.Nic nic) { + String num = nic.getNicId().replaceAll("\\D", ""); + // return 0 if no digits found + return num.isEmpty() ? 0 : Integer.parseInt(num); + } + }); + } + return instanceNics; + } + + private UnmanagedInstanceTO getUnmanagedInstance(VmwareHypervisorHost hyperHost, VirtualMachineMO vmMo) { + UnmanagedInstanceTO instance = null; + try { + instance = new UnmanagedInstanceTO(); + instance.setName(vmMo.getVmName()); + instance.setCpuCores(vmMo.getConfigSummary().getNumCpu()); + instance.setCpuCoresPerSocket(vmMo.getCoresPerSocket()); + instance.setCpuSpeed(vmMo.getConfigSummary().getCpuReservation()); + instance.setMemory(vmMo.getConfigSummary().getMemorySizeMB()); + instance.setOperatingSystemId(vmMo.getVmGuestInfo().getGuestId()); + if (Strings.isNullOrEmpty(instance.getOperatingSystemId())) { + instance.setOperatingSystemId(vmMo.getConfigSummary().getGuestId()); + } + VirtualMachineGuestOsIdentifier osIdentifier = VirtualMachineGuestOsIdentifier.OTHER_GUEST; + try { + osIdentifier = VirtualMachineGuestOsIdentifier.fromValue(instance.getOperatingSystemId()); + } catch (IllegalArgumentException iae) { + if (!Strings.isNullOrEmpty(instance.getOperatingSystemId()) && instance.getOperatingSystemId().contains("64")) { + osIdentifier = VirtualMachineGuestOsIdentifier.OTHER_GUEST_64; + } + } + instance.setOperatingSystem(vmMo.getGuestInfo().getGuestFullName()); + if (Strings.isNullOrEmpty(instance.getOperatingSystem())) { + instance.setOperatingSystem(vmMo.getConfigSummary().getGuestFullName()); + } + UnmanagedInstanceTO.PowerState powerState = UnmanagedInstanceTO.PowerState.PowerUnknown; + if (vmMo.getPowerState().toString().equalsIgnoreCase("POWERED_ON")) { + powerState = UnmanagedInstanceTO.PowerState.PowerOn; + } + if (vmMo.getPowerState().toString().equalsIgnoreCase("POWERED_OFF")) { + powerState = UnmanagedInstanceTO.PowerState.PowerOff; + } + instance.setPowerState(powerState); + instance.setDisks(getUnmanageInstanceDisks(vmMo)); + instance.setNics(getUnmanageInstanceNics(hyperHost, vmMo)); + } catch (Exception e) { + s_logger.info("Unable to retrieve unmanaged instance info. " + e.getMessage()); + } + + return instance; + } + + private Answer execute(GetUnmanagedInstancesCommand cmd) { + if (s_logger.isInfoEnabled()) { + s_logger.info("Executing resource GetUnmanagedInstancesCommand " + _gson.toJson(cmd)); + } + + VmwareContext context = getServiceContext(); + HashMap unmanagedInstances = new HashMap<>(); + try { + VmwareHypervisorHost hyperHost = getHyperHost(context); + + String vmName = cmd.getInstanceName(); + List vmMos = hyperHost.listVmsOnHyperHost(vmName); + + for (VirtualMachineMO vmMo : vmMos) { + if (vmMo == null) { + continue; + } + if (vmMo.isTemplate()) { + continue; + } + // Filter managed instances + if (cmd.hasManagedInstance(vmMo.getName())) { + continue; + } + // Filter instance if answer is requested for a particular instance name + if (!Strings.isNullOrEmpty(cmd.getInstanceName()) && + !cmd.getInstanceName().equals(vmMo.getVmName())) { + continue; + } + UnmanagedInstanceTO instance = getUnmanagedInstance(hyperHost, vmMo); + if (instance != null) { + unmanagedInstances.put(instance.getName(), instance); + } + } + } catch (Exception e) { + s_logger.info("GetUnmanagedInstancesCommand failed due to " + VmwareHelper.getExceptionMessage(e)); + } + return new GetUnmanagedInstancesAnswer(cmd, "", unmanagedInstances); + } } diff --git a/plugins/hypervisors/vmware/src/main/java/com/cloud/storage/resource/VmwareStorageProcessor.java b/plugins/hypervisors/vmware/src/main/java/com/cloud/storage/resource/VmwareStorageProcessor.java index 420ac440d670..f67b242ff1c3 100644 --- a/plugins/hypervisors/vmware/src/main/java/com/cloud/storage/resource/VmwareStorageProcessor.java +++ b/plugins/hypervisors/vmware/src/main/java/com/cloud/storage/resource/VmwareStorageProcessor.java @@ -34,40 +34,7 @@ import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; -import com.vmware.vim25.VmConfigInfo; import org.apache.cloudstack.agent.directdownload.DirectDownloadCommand; -import org.apache.commons.lang.StringUtils; -import org.apache.log4j.Logger; - -import com.google.common.base.Strings; -import com.google.gson.Gson; -import com.vmware.vim25.DatastoreHostMount; -import com.vmware.vim25.HostHostBusAdapter; -import com.vmware.vim25.HostInternetScsiHba; -import com.vmware.vim25.HostInternetScsiHbaAuthenticationProperties; -import com.vmware.vim25.HostInternetScsiHbaSendTarget; -import com.vmware.vim25.HostInternetScsiHbaStaticTarget; -import com.vmware.vim25.HostInternetScsiTargetTransport; -import com.vmware.vim25.HostResignatureRescanResult; -import com.vmware.vim25.HostUnresolvedVmfsResignatureSpec; -import com.vmware.vim25.HostScsiDisk; -import com.vmware.vim25.HostScsiTopology; -import com.vmware.vim25.HostScsiTopologyInterface; -import com.vmware.vim25.HostScsiTopologyLun; -import com.vmware.vim25.HostScsiTopologyTarget; -import com.vmware.vim25.HostUnresolvedVmfsExtent; -import com.vmware.vim25.HostUnresolvedVmfsVolume; -import com.vmware.vim25.InvalidStateFaultMsg; -import com.vmware.vim25.ManagedObjectReference; -import com.vmware.vim25.VirtualDeviceBackingInfo; -import com.vmware.vim25.VirtualDeviceConfigSpec; -import com.vmware.vim25.VirtualDeviceConfigSpecOperation; -import com.vmware.vim25.VirtualMachineConfigSpec; -import com.vmware.vim25.VirtualDisk; -import com.vmware.vim25.VirtualDiskFlatVer2BackingInfo; -import com.vmware.vim25.VmfsDatastoreExpandSpec; -import com.vmware.vim25.VmfsDatastoreOption; - import org.apache.cloudstack.storage.command.AttachAnswer; import org.apache.cloudstack.storage.command.AttachCommand; import org.apache.cloudstack.storage.command.CopyCmdAnswer; @@ -87,6 +54,8 @@ import org.apache.cloudstack.storage.to.TemplateObjectTO; import org.apache.cloudstack.storage.to.VolumeObjectTO; import org.apache.cloudstack.utils.volume.VirtualMachineDiskInfo; +import org.apache.commons.lang.StringUtils; +import org.apache.log4j.Logger; import com.cloud.agent.api.Answer; import com.cloud.agent.api.Command; @@ -127,6 +96,35 @@ import com.cloud.utils.script.Script; import com.cloud.vm.VirtualMachine.PowerState; import com.cloud.vm.VmDetailConstants; +import com.google.common.base.Strings; +import com.google.gson.Gson; +import com.vmware.vim25.DatastoreHostMount; +import com.vmware.vim25.HostHostBusAdapter; +import com.vmware.vim25.HostInternetScsiHba; +import com.vmware.vim25.HostInternetScsiHbaAuthenticationProperties; +import com.vmware.vim25.HostInternetScsiHbaSendTarget; +import com.vmware.vim25.HostInternetScsiHbaStaticTarget; +import com.vmware.vim25.HostInternetScsiTargetTransport; +import com.vmware.vim25.HostResignatureRescanResult; +import com.vmware.vim25.HostScsiDisk; +import com.vmware.vim25.HostScsiTopology; +import com.vmware.vim25.HostScsiTopologyInterface; +import com.vmware.vim25.HostScsiTopologyLun; +import com.vmware.vim25.HostScsiTopologyTarget; +import com.vmware.vim25.HostUnresolvedVmfsExtent; +import com.vmware.vim25.HostUnresolvedVmfsResignatureSpec; +import com.vmware.vim25.HostUnresolvedVmfsVolume; +import com.vmware.vim25.InvalidStateFaultMsg; +import com.vmware.vim25.ManagedObjectReference; +import com.vmware.vim25.VirtualDeviceBackingInfo; +import com.vmware.vim25.VirtualDeviceConfigSpec; +import com.vmware.vim25.VirtualDeviceConfigSpecOperation; +import com.vmware.vim25.VirtualDisk; +import com.vmware.vim25.VirtualDiskFlatVer2BackingInfo; +import com.vmware.vim25.VirtualMachineConfigSpec; +import com.vmware.vim25.VmConfigInfo; +import com.vmware.vim25.VmfsDatastoreExpandSpec; +import com.vmware.vim25.VmfsDatastoreOption; public class VmwareStorageProcessor implements StorageProcessor { @@ -3527,9 +3525,9 @@ public Answer forgetObject(ForgetObjectCmd cmd) { private static String deriveTemplateUuidOnHost(VmwareHypervisorHost hyperHost, String storeIdentifier, String templateName) { String templateUuid; - try{ + try { templateUuid = UUID.nameUUIDFromBytes((templateName + "@" + storeIdentifier + "-" + hyperHost.getMor().getValue()).getBytes("UTF-8")).toString(); - }catch(UnsupportedEncodingException e){ + } catch(UnsupportedEncodingException e){ s_logger.warn("unexpected encoding error, using default Charset: " + e.getLocalizedMessage()); templateUuid = UUID.nameUUIDFromBytes((templateName + "@" + storeIdentifier + "-" + hyperHost.getMor().getValue()).getBytes(Charset.defaultCharset())) .toString(); diff --git a/plugins/hypervisors/vmware/src/test/java/com/cloud/hypervisor/vmware/manager/VmwareManagerImplTest.java b/plugins/hypervisors/vmware/src/test/java/com/cloud/hypervisor/vmware/manager/VmwareManagerImplTest.java index 499ed2460286..8aa92f7d9c4d 100644 --- a/plugins/hypervisors/vmware/src/test/java/com/cloud/hypervisor/vmware/manager/VmwareManagerImplTest.java +++ b/plugins/hypervisors/vmware/src/test/java/com/cloud/hypervisor/vmware/manager/VmwareManagerImplTest.java @@ -102,7 +102,7 @@ public void updateVmwareDatacenterNormalUpdate() { host.setDataCenterId(1); host.setHypervisorType(Hypervisor.HypervisorType.VMware); Mockito.doReturn(Collections.singletonList(host)).when(hostDao).listAllHostsByZoneAndHypervisorType(Mockito.anyLong(), Mockito.any()); - Mockito.doReturn(hostDetails).when(hostDetailsDao).findDetails(Mockito.anyLong()); + Mockito.lenient().doReturn(hostDetails).when(hostDetailsDao).findDetails(Mockito.anyLong()); Mockito.doReturn("some-old-guid").when(hostDetails).get("guid"); Mockito.doReturn(hostDetails).when(hostDetailsDao).findDetails(Mockito.anyLong()); diff --git a/plugins/hypervisors/vmware/src/test/java/com/cloud/hypervisor/vmware/resource/VmwareResourceTest.java b/plugins/hypervisors/vmware/src/test/java/com/cloud/hypervisor/vmware/resource/VmwareResourceTest.java index c2b3f363883f..7cebaf119106 100644 --- a/plugins/hypervisors/vmware/src/test/java/com/cloud/hypervisor/vmware/resource/VmwareResourceTest.java +++ b/plugins/hypervisors/vmware/src/test/java/com/cloud/hypervisor/vmware/resource/VmwareResourceTest.java @@ -16,20 +16,19 @@ // under the License. package com.cloud.hypervisor.vmware.resource; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; +import static org.mockito.Matchers.eq; import static org.mockito.Mockito.any; +import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.never; -import static org.mockito.Matchers.eq; import static org.mockito.Mockito.times; - -import java.util.ArrayList; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import static org.powermock.api.mockito.PowerMockito.whenNew; +import java.util.ArrayList; import java.util.Arrays; import java.util.EnumMap; import java.util.HashMap; @@ -51,14 +50,6 @@ import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; -import com.vmware.vim25.HostCapability; -import com.vmware.vim25.ManagedObjectReference; -import com.vmware.vim25.VimPortType; -import com.vmware.vim25.VirtualDevice; -import com.vmware.vim25.VirtualDeviceConfigSpec; -import com.vmware.vim25.VirtualMachineConfigSpec; -import com.vmware.vim25.VirtualMachineVideoCard; - import com.cloud.agent.api.Command; import com.cloud.agent.api.ScaleVmAnswer; import com.cloud.agent.api.ScaleVmCommand; @@ -67,19 +58,25 @@ import com.cloud.agent.api.to.NicTO; import com.cloud.agent.api.to.VirtualMachineTO; import com.cloud.agent.api.to.VolumeTO; -import com.cloud.hypervisor.vmware.mo.DatacenterMO; import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.hypervisor.vmware.mo.DatacenterMO; import com.cloud.hypervisor.vmware.mo.HostMO; import com.cloud.hypervisor.vmware.mo.VirtualMachineMO; import com.cloud.hypervisor.vmware.mo.VmwareHypervisorHost; import com.cloud.hypervisor.vmware.util.VmwareClient; import com.cloud.hypervisor.vmware.util.VmwareContext; -import com.cloud.vm.VmDetailConstants; import com.cloud.storage.resource.VmwareStorageProcessor; -import com.cloud.storage.resource.VmwareStorageSubsystemCommandHandler; import com.cloud.storage.resource.VmwareStorageProcessor.VmwareStorageProcessorConfigurableFields; - +import com.cloud.storage.resource.VmwareStorageSubsystemCommandHandler; import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.vm.VmDetailConstants; +import com.vmware.vim25.HostCapability; +import com.vmware.vim25.ManagedObjectReference; +import com.vmware.vim25.VimPortType; +import com.vmware.vim25.VirtualDevice; +import com.vmware.vim25.VirtualDeviceConfigSpec; +import com.vmware.vim25.VirtualMachineConfigSpec; +import com.vmware.vim25.VirtualMachineVideoCard; @RunWith(PowerMockRunner.class) @PrepareForTest({CopyCommand.class, DatacenterMO.class, VmwareResource.class}) @@ -399,7 +396,7 @@ public void checkStorageProcessorAndHandlerNfsVersionAttributeVersionSet(){ verify(_resource, never()).examineStorageSubSystemCommandNfsVersion(Matchers.eq(storageCmd), any(EnumMap.class)); } - @Test(expected=CloudRuntimeException.class) + @Test(expected= CloudRuntimeException.class) public void testFindVmOnDatacenterNullHyperHostReference() throws Exception { when(hyperHost.getMor()).thenReturn(null); _resource.findVmOnDatacenter(context, hyperHost, volume); diff --git a/plugins/hypervisors/xenserver/src/test/java/com/cloud/hypervisor/XenServerGuruTest.java b/plugins/hypervisors/xenserver/src/test/java/com/cloud/hypervisor/XenServerGuruTest.java index a9d01436479e..84ce99b1cc8a 100644 --- a/plugins/hypervisors/xenserver/src/test/java/com/cloud/hypervisor/XenServerGuruTest.java +++ b/plugins/hypervisors/xenserver/src/test/java/com/cloud/hypervisor/XenServerGuruTest.java @@ -82,11 +82,11 @@ public void beforeTest() { Mockito.when(copyCommandMock.getDestTO()).thenReturn(destinationDataMock); Mockito.when(changedHost.getId()).thenReturn(changedHostId); - Mockito.when(defaultHost.getId()).thenReturn(defaultHostId); + Mockito.lenient().when(defaultHost.getId()).thenReturn(defaultHostId); Mockito.when(defaultHost.getDataCenterId()).thenReturn(zoneId); Mockito.when(hostDaoMock.findById(defaultHostId)).thenReturn(defaultHost); - Mockito.when(hostDaoMock.findById(changedHostId)).thenReturn(changedHost); + Mockito.lenient().when(hostDaoMock.findById(changedHostId)).thenReturn(changedHost); } @Test diff --git a/plugins/hypervisors/xenserver/src/test/java/com/cloud/hypervisor/xenserver/resource/Xenserver625StorageProcessorTest.java b/plugins/hypervisors/xenserver/src/test/java/com/cloud/hypervisor/xenserver/resource/Xenserver625StorageProcessorTest.java index 0cf99b6a6004..7022e6d4b672 100644 --- a/plugins/hypervisors/xenserver/src/test/java/com/cloud/hypervisor/xenserver/resource/Xenserver625StorageProcessorTest.java +++ b/plugins/hypervisors/xenserver/src/test/java/com/cloud/hypervisor/xenserver/resource/Xenserver625StorageProcessorTest.java @@ -21,6 +21,7 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.Mockito.times; import java.util.HashSet; @@ -177,7 +178,7 @@ public void retrieveAlreadyConfiguredSrTestNoSrFound() throws XenAPIException, X SR sr = xenserver625StorageProcessor.retrieveAlreadyConfiguredSr(connectionMock, pathMock); - PowerMockito.verifyStatic(); + PowerMockito.verifyStatic(SR.class); SR.getByNameLabel(connectionMock, pathMock); Assert.assertNull(sr); } @@ -337,7 +338,7 @@ private void prepareAndExecuteTestcreateNewFileSrTestThrowingException(Class org.jvnet.jaxb2.maven2 maven-jaxb2-plugin - 0.7.1 + 0.14.0 interface diff --git a/plugins/network-elements/elastic-loadbalancer/src/test/java/com/cloud/network/lb/ElasticLoadBalancerManagerImplTest.java b/plugins/network-elements/elastic-loadbalancer/src/test/java/com/cloud/network/lb/ElasticLoadBalancerManagerImplTest.java index 8928fd99979d..04f59bb54937 100644 --- a/plugins/network-elements/elastic-loadbalancer/src/test/java/com/cloud/network/lb/ElasticLoadBalancerManagerImplTest.java +++ b/plugins/network-elements/elastic-loadbalancer/src/test/java/com/cloud/network/lb/ElasticLoadBalancerManagerImplTest.java @@ -25,8 +25,8 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InjectMocks; -import org.mockito.internal.util.reflection.Whitebox; import org.mockito.runners.MockitoJUnitRunner; +import org.powermock.reflect.Whitebox; import com.cloud.agent.api.check.CheckSshAnswer; import com.cloud.agent.manager.Commands; diff --git a/plugins/network-elements/elastic-loadbalancer/src/test/java/com/cloud/network/lb/LoadBalanceRuleHandlerTest.java b/plugins/network-elements/elastic-loadbalancer/src/test/java/com/cloud/network/lb/LoadBalanceRuleHandlerTest.java index 17bae635687c..cde56c19d1e8 100644 --- a/plugins/network-elements/elastic-loadbalancer/src/test/java/com/cloud/network/lb/LoadBalanceRuleHandlerTest.java +++ b/plugins/network-elements/elastic-loadbalancer/src/test/java/com/cloud/network/lb/LoadBalanceRuleHandlerTest.java @@ -36,8 +36,8 @@ import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.Mock; -import org.mockito.internal.util.reflection.Whitebox; import org.mockito.runners.MockitoJUnitRunner; +import org.powermock.reflect.Whitebox; import com.cloud.dc.PodVlanMapVO; import com.cloud.dc.dao.PodVlanMapDao; diff --git a/plugins/network-elements/internal-loadbalancer/src/test/java/org/apache/cloudstack/internallbvmmgr/InternalLBVMManagerTest.java b/plugins/network-elements/internal-loadbalancer/src/test/java/org/apache/cloudstack/internallbvmmgr/InternalLBVMManagerTest.java index b24d51101eaa..103fcd9cf31a 100644 --- a/plugins/network-elements/internal-loadbalancer/src/test/java/org/apache/cloudstack/internallbvmmgr/InternalLBVMManagerTest.java +++ b/plugins/network-elements/internal-loadbalancer/src/test/java/org/apache/cloudstack/internallbvmmgr/InternalLBVMManagerTest.java @@ -16,6 +16,8 @@ // under the License. package org.apache.cloudstack.internallbvmmgr; +import static org.mockito.ArgumentMatchers.nullable; + import java.lang.reflect.Field; import java.net.URI; import java.net.URISyntaxException; @@ -124,14 +126,13 @@ public void setUp() { List list = new ArrayList(); list.add(off); list.add(off); - Mockito.when(_svcOffDao.createSystemServiceOfferings(Matchers.anyString(), Matchers.anyString(), Matchers.anyInt(), Matchers.anyInt(), Matchers.anyInt(), - Matchers.anyInt(), Matchers.anyInt(), Matchers.anyBoolean(), Matchers.anyString(), Matchers.any(ProvisioningType.class), Matchers.anyBoolean(), - Matchers.anyString(), Matchers.anyBoolean(), Matchers.any(VirtualMachine.Type.class), Matchers.anyBoolean())).thenReturn(list); + Mockito.when(_svcOffDao.createSystemServiceOfferings(nullable(String.class), nullable(String.class), nullable(Integer.class), nullable(Integer.class), nullable(Integer.class), + nullable(Integer.class), nullable(Integer.class), nullable(Boolean.class), nullable(String.class), nullable(ProvisioningType.class), nullable(Boolean.class), + nullable(String.class), nullable(Boolean.class), nullable(VirtualMachine.Type.class), nullable(Boolean.class))).thenReturn(list); ComponentContext.initComponentsLifeCycle(); - vm = - new DomainRouterVO(1L, off.getId(), 1, "alena", 1, HypervisorType.XenServer, 1, 1, 1, 1, false, null, false, false, + vm = new DomainRouterVO(1L, off.getId(), 1, "alena", 1, HypervisorType.XenServer, 1, 1, 1, 1, false, null, false, false, VirtualMachine.Type.InternalLoadBalancerVm, null); vm.setRole(Role.INTERNAL_LB_VM); vm = setId(vm, 1); @@ -154,7 +155,7 @@ public void setUp() { answers[0] = answer; try { - Mockito.when(_agentMgr.send(Matchers.anyLong(), Matchers.any(Commands.class))).thenReturn(answers); + Mockito.when(_agentMgr.send(nullable(Long.class), nullable(Commands.class))).thenReturn(answers); } catch (final AgentUnavailableException e) { // TODO Auto-generated catch block e.printStackTrace(); diff --git a/plugins/network-elements/internal-loadbalancer/src/test/java/org/apache/cloudstack/internallbvmmgr/InternalLBVMServiceTest.java b/plugins/network-elements/internal-loadbalancer/src/test/java/org/apache/cloudstack/internallbvmmgr/InternalLBVMServiceTest.java index 84c5f1ba6abb..898b7e5121be 100644 --- a/plugins/network-elements/internal-loadbalancer/src/test/java/org/apache/cloudstack/internallbvmmgr/InternalLBVMServiceTest.java +++ b/plugins/network-elements/internal-loadbalancer/src/test/java/org/apache/cloudstack/internallbvmmgr/InternalLBVMServiceTest.java @@ -16,14 +16,14 @@ // under the License. package org.apache.cloudstack.internallbvmmgr; +import static org.mockito.ArgumentMatchers.nullable; + import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List; import javax.inject.Inject; -import junit.framework.TestCase; - import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.network.lb.InternalLoadBalancerVMService; import org.junit.After; @@ -57,6 +57,8 @@ import com.cloud.vm.VirtualMachineManager; import com.cloud.vm.dao.DomainRouterDao; +import junit.framework.TestCase; + /** * Set of unittests for InternalLoadBalancerVMService * @@ -96,9 +98,9 @@ public void setUp() { List list = new ArrayList(); list.add(off); list.add(off); - Mockito.when(_svcOffDao.createSystemServiceOfferings(Matchers.anyString(), Matchers.anyString(), Matchers.anyInt(), Matchers.anyInt(), Matchers.anyInt(), - Matchers.anyInt(), Matchers.anyInt(), Matchers.anyBoolean(), Matchers.anyString(), Matchers.any(ProvisioningType.class), Matchers.anyBoolean(), - Matchers.anyString(), Matchers.anyBoolean(), Matchers.any(VirtualMachine.Type.class), Matchers.anyBoolean())).thenReturn(list); + Mockito.when(_svcOffDao.createSystemServiceOfferings(nullable(String.class), nullable(String.class), nullable(Integer.class), nullable(Integer.class), nullable(Integer.class), + nullable(Integer.class), nullable(Integer.class), nullable(Boolean.class), nullable(String.class), nullable(ProvisioningType.class), nullable(Boolean.class), + nullable(String.class), nullable(Boolean.class), nullable(VirtualMachine.Type.class), nullable(Boolean.class))).thenReturn(list); ComponentContext.initComponentsLifeCycle(); diff --git a/plugins/network-elements/internal-loadbalancer/src/test/resources/lb_element.xml b/plugins/network-elements/internal-loadbalancer/src/test/resources/lb_element.xml index 9ed5a317390b..0529392384e1 100644 --- a/plugins/network-elements/internal-loadbalancer/src/test/resources/lb_element.xml +++ b/plugins/network-elements/internal-loadbalancer/src/test/resources/lb_element.xml @@ -20,10 +20,10 @@ http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> - + + + - - @@ -37,10 +37,10 @@ - - - - - - + + + + + + diff --git a/plugins/network-elements/juniper-contrail/pom.xml b/plugins/network-elements/juniper-contrail/pom.xml index a3b294a8ce8d..7f1dd58fc772 100644 --- a/plugins/network-elements/juniper-contrail/pom.xml +++ b/plugins/network-elements/juniper-contrail/pom.xml @@ -30,7 +30,7 @@ juniper-contrail - http://juniper.github.io/contrail-maven/snapshots + https://juniper.github.io/contrail-maven/snapshots diff --git a/plugins/network-elements/juniper-contrail/src/test/java/org/apache/cloudstack/network/contrail/management/NetworkProviderTest.java b/plugins/network-elements/juniper-contrail/src/test/java/org/apache/cloudstack/network/contrail/management/NetworkProviderTest.java index 95204900f72f..f9a478713c74 100644 --- a/plugins/network-elements/juniper-contrail/src/test/java/org/apache/cloudstack/network/contrail/management/NetworkProviderTest.java +++ b/plugins/network-elements/juniper-contrail/src/test/java/org/apache/cloudstack/network/contrail/management/NetworkProviderTest.java @@ -24,30 +24,6 @@ import javax.inject.Inject; -import junit.framework.TestCase; -import net.juniper.contrail.api.ApiConnector; -import net.juniper.contrail.api.ApiConnectorFactory; -import net.juniper.contrail.api.ApiConnectorMock; -import net.juniper.contrail.api.types.InstanceIp; -import net.juniper.contrail.api.types.NetworkIpam; -import net.juniper.contrail.api.types.Project; -import net.juniper.contrail.api.types.SubnetType; -import net.juniper.contrail.api.types.VirtualMachine; -import net.juniper.contrail.api.types.VirtualMachineInterface; -import net.juniper.contrail.api.types.VirtualNetwork; -import net.juniper.contrail.api.types.VnSubnetsType; - -import org.apache.log4j.Logger; -import org.junit.After; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.context.support.AbstractApplicationContext; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseCmd; import org.apache.cloudstack.api.command.user.address.AssociateIPAddrCmd; @@ -58,6 +34,16 @@ import org.apache.cloudstack.api.command.user.project.DeleteProjectCmd; import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.utils.identity.ManagementServerNode; +import org.apache.log4j.Logger; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.context.support.AbstractApplicationContext; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import com.cloud.agent.AgentManager; import com.cloud.dc.DataCenter; @@ -84,6 +70,19 @@ import com.cloud.utils.mgmt.JmxUtil; import com.cloud.vm.VirtualMachineManager; +import junit.framework.TestCase; +import net.juniper.contrail.api.ApiConnector; +import net.juniper.contrail.api.ApiConnectorFactory; +import net.juniper.contrail.api.ApiConnectorMock; +import net.juniper.contrail.api.types.InstanceIp; +import net.juniper.contrail.api.types.NetworkIpam; +import net.juniper.contrail.api.types.Project; +import net.juniper.contrail.api.types.SubnetType; +import net.juniper.contrail.api.types.VirtualMachine; +import net.juniper.contrail.api.types.VirtualMachineInterface; +import net.juniper.contrail.api.types.VirtualNetwork; +import net.juniper.contrail.api.types.VnSubnetsType; + @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "classpath:/providerContext.xml") /** diff --git a/plugins/network-elements/nicira-nvp/src/test/java/com/cloud/network/element/NiciraNvpElementTest.java b/plugins/network-elements/nicira-nvp/src/test/java/com/cloud/network/element/NiciraNvpElementTest.java index 858e908f52bb..a694f7a862d6 100644 --- a/plugins/network-elements/nicira-nvp/src/test/java/com/cloud/network/element/NiciraNvpElementTest.java +++ b/plugins/network-elements/nicira-nvp/src/test/java/com/cloud/network/element/NiciraNvpElementTest.java @@ -259,11 +259,8 @@ public void applyIpTest() throws ResourceUnavailableException { verify(agentManager, atLeast(1)).easySend(eq(NETWORK_ID), argThat(new ArgumentMatcher() { @Override - public boolean matches(final Object argument) { - final ConfigurePublicIpsOnLogicalRouterCommand command = (ConfigurePublicIpsOnLogicalRouterCommand)argument; - if (command.getPublicCidrs().size() == 1) - return true; - return false; + public boolean matches(final ConfigurePublicIpsOnLogicalRouterCommand command) { + return command.getPublicCidrs().size() == 1; } })); } diff --git a/plugins/network-elements/nicira-nvp/src/test/java/com/cloud/network/nicira/NiciraNvpApiIT.java b/plugins/network-elements/nicira-nvp/src/test/java/com/cloud/network/nicira/NiciraNvpApiIT.java index a95a8d673cff..60c521ae3606 100644 --- a/plugins/network-elements/nicira-nvp/src/test/java/com/cloud/network/nicira/NiciraNvpApiIT.java +++ b/plugins/network-elements/nicira-nvp/src/test/java/com/cloud/network/nicira/NiciraNvpApiIT.java @@ -45,11 +45,11 @@ public void setup() throws Exception { final String user = System.getProperty("nvp.admin.user"); final String pass = System.getProperty("nvp.admin.pwd"); api = NiciraNvpApi.create() - .host(host) - .username(user) - .password(pass) - .httpClient(HttpClientHelper.createHttpClient(5)) - .build(); + .host(host) + .username(user) + .password(pass) + .httpClient(HttpClientHelper.createHttpClient(5)) + .build(); } @Test @@ -209,7 +209,7 @@ public void testCRUDLogicalSwitch() throws Exception { api.updateLogicalSwitchPortAttachment(logicalSwitch.getUuid(), logicalSwitchPort.getUuid(), vifAttachment); assertEquals("Read a LogicalSwitchPort by vifAttachment different than expected", - api.findLogicalSwitchPortUuidByVifAttachmentUuid(logicalSwitch.getUuid(), vifAttachment.getVifUuid()), logicalSwitchPort.getUuid()); + api.findLogicalSwitchPortUuidByVifAttachmentUuid(logicalSwitch.getUuid(), vifAttachment.getVifUuid()), logicalSwitchPort.getUuid()); api.deleteLogicalSwitchPort(logicalSwitch.getUuid(), logicalSwitchPort.getUuid()); @@ -225,7 +225,7 @@ public void testCRUDLogicalRouter() { logicalRouter.setNatSynchronizationEnabled(true); logicalRouter.setReplicationMode(LogicalRouter.REPLICATION_MODE_SERVICE); final RoutingConfig routingConfig = new SingleDefaultRouteImplicitRoutingConfig( - new RouterNextHop("192.168.10.20")); + new RouterNextHop("192.168.10.20")); logicalRouter.setRoutingConfig(routingConfig); // In the creation we don't get to specify UUID, href or schema: they don't exist yet @@ -312,7 +312,7 @@ public void testGetControlClusterStatus() throws NiciraNvpApiException { final ControlClusterStatus controlClusterStatus = api.getControlClusterStatus(); final String clusterStatus = controlClusterStatus.getClusterStatus(); final boolean correctStatus = clusterStatus.equalsIgnoreCase("stable") || - clusterStatus.equalsIgnoreCase("joining") || clusterStatus.equalsIgnoreCase("unstable"); + clusterStatus.equalsIgnoreCase("joining") || clusterStatus.equalsIgnoreCase("unstable"); assertTrue("Not recognizable cluster status", correctStatus); } diff --git a/plugins/network-elements/nicira-nvp/src/test/java/com/cloud/network/nicira/NiciraRestClientTest.java b/plugins/network-elements/nicira-nvp/src/test/java/com/cloud/network/nicira/NiciraRestClientTest.java index 3c5160cf9580..d23c4dcb5deb 100644 --- a/plugins/network-elements/nicira-nvp/src/test/java/com/cloud/network/nicira/NiciraRestClientTest.java +++ b/plugins/network-elements/nicira-nvp/src/test/java/com/cloud/network/nicira/NiciraRestClientTest.java @@ -47,6 +47,7 @@ import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; +import org.powermock.core.classloader.annotations.PowerMockIgnore; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; @@ -57,6 +58,7 @@ @RunWith(PowerMockRunner.class) @PrepareForTest(NiciraRestClient.class) +@PowerMockIgnore({"javax.xml.*", "org.w3c.dom.*", "org.apache.xerces.*", "org.apache.log4j.*"}) public class NiciraRestClientTest { private static final int HTTPS_PORT = 443; diff --git a/plugins/network-elements/nicira-nvp/src/test/java/com/cloud/network/resource/NiciraNvpResourceTest.java b/plugins/network-elements/nicira-nvp/src/test/java/com/cloud/network/resource/NiciraNvpResourceTest.java index c0dedd284457..417a8468a562 100644 --- a/plugins/network-elements/nicira-nvp/src/test/java/com/cloud/network/resource/NiciraNvpResourceTest.java +++ b/plugins/network-elements/nicira-nvp/src/test/java/com/cloud/network/resource/NiciraNvpResourceTest.java @@ -21,9 +21,9 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.argThat; -import static org.mockito.Matchers.eq; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.argThat; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.atLeast; import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.doThrow; @@ -465,8 +465,8 @@ public void testConfigureStaticNatRulesOnLogicalRouter() throws ConfigurationExc assertTrue(a.getResult()); verify(nvpApi, atLeast(2)).createLogicalRouterNatRule(eq("aaaaa"), argThat(new ArgumentMatcher() { @Override - public boolean matches(final Object argument) { - final NatRule rule = (NatRule) argument; + public boolean matches(final NatRule argument) { + final NatRule rule = argument; if (rule.getType().equals("DestinationNatRule") && ((DestinationNatRule) rule).getToDestinationIpAddress().equals("10.10.10.10")) { return true; } @@ -508,8 +508,8 @@ public void testConfigureStaticNatRulesOnLogicalRouterExistingRules() throws Con assertTrue(a.getResult()); verify(nvpApi, never()).createLogicalRouterNatRule(eq("aaaaa"), argThat(new ArgumentMatcher() { @Override - public boolean matches(final Object argument) { - final NatRule rule = (NatRule) argument; + public boolean matches(final NatRule argument) { + final NatRule rule = argument; if (rule.getType().equals("DestinationNatRule") && ((DestinationNatRule) rule).getToDestinationIpAddress().equals("10.10.10.10")) { return true; } @@ -553,8 +553,7 @@ public void testConfigureStaticNatRulesOnLogicalRouterRemoveRules() throws Confi assertTrue(a.getResult()); verify(nvpApi, atLeast(2)).deleteLogicalRouterNatRule(eq("aaaaa"), argThat(new ArgumentMatcher() { @Override - public boolean matches(final Object argument) { - final UUID uuid = (UUID) argument; + public boolean matches(final UUID uuid) { if (rule0Uuid.equals(uuid) || rule1Uuid.equals(uuid)) { return true; } @@ -626,8 +625,7 @@ public void testConfigurePortForwardingRulesOnLogicalRouter() throws Configurati assertTrue(a.getResult()); verify(nvpApi, atLeast(2)).createLogicalRouterNatRule(eq("aaaaa"), argThat(new ArgumentMatcher() { @Override - public boolean matches(final Object argument) { - final NatRule rule = (NatRule) argument; + public boolean matches(final NatRule rule) { if (rule.getType().equals("DestinationNatRule") && ((DestinationNatRule) rule).getToDestinationIpAddress().equals("10.10.10.10")) { return true; } @@ -669,8 +667,7 @@ public void testConfigurePortForwardingRulesOnLogicalRouterExistingRules() throw assertTrue(a.getResult()); verify(nvpApi, never()).createLogicalRouterNatRule(eq("aaaaa"), argThat(new ArgumentMatcher() { @Override - public boolean matches(final Object argument) { - final NatRule rule = (NatRule) argument; + public boolean matches(final NatRule rule) { if (rule.getType().equals("DestinationNatRule") && ((DestinationNatRule) rule).getToDestinationIpAddress().equals("10.10.10.10")) { return true; } @@ -714,8 +711,7 @@ public void testConfigurePortForwardingRulesOnLogicalRouterRemoveRules() throws assertTrue(a.getResult()); verify(nvpApi, atLeast(2)).deleteLogicalRouterNatRule(eq("aaaaa"), argThat(new ArgumentMatcher() { @Override - public boolean matches(final Object argument) { - final UUID uuid = (UUID) argument; + public boolean matches(final UUID uuid) { if (rule0Uuid.equals(uuid) || rule1Uuid.equals(uuid)) { return true; } diff --git a/plugins/network-elements/nicira-nvp/src/test/resources/config.properties b/plugins/network-elements/nicira-nvp/src/test/resources/config.properties index 4006e38d64ec..04cf76b805eb 100644 --- a/plugins/network-elements/nicira-nvp/src/test/resources/config.properties +++ b/plugins/network-elements/nicira-nvp/src/test/resources/config.properties @@ -17,7 +17,6 @@ # under the License. # - -nvp.host=${nvp-host} -nvp.admin.user=${nvp-admin-user} -nvp.admin.pwd=${nvp-admin-pwd} +nvp.host=localhost +nvp.admin.user=admin +nvp.admin.pwd=adminpassword diff --git a/plugins/storage/volume/datera/src/main/java/org/apache/cloudstack/storage/datastore/provider/DateraHostListener.java b/plugins/storage/volume/datera/src/main/java/org/apache/cloudstack/storage/datastore/provider/DateraHostListener.java index 2cb4e8cc6721..8639db6cfca5 100644 --- a/plugins/storage/volume/datera/src/main/java/org/apache/cloudstack/storage/datastore/provider/DateraHostListener.java +++ b/plugins/storage/volume/datera/src/main/java/org/apache/cloudstack/storage/datastore/provider/DateraHostListener.java @@ -18,6 +18,23 @@ */ package org.apache.cloudstack.storage.datastore.provider; +import java.io.UnsupportedEncodingException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.inject.Inject; + +import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; +import org.apache.cloudstack.engine.subsystem.api.storage.HypervisorHostListener; +import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; +import org.apache.cloudstack.storage.datastore.db.StoragePoolDetailsDao; +import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; +import org.apache.cloudstack.storage.datastore.util.DateraObject; +import org.apache.cloudstack.storage.datastore.util.DateraUtil; +import org.apache.log4j.Logger; + import com.cloud.agent.AgentManager; import com.cloud.agent.api.Answer; import com.cloud.agent.api.ModifyStoragePoolAnswer; @@ -41,21 +58,6 @@ import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.vm.VMInstanceVO; import com.cloud.vm.dao.VMInstanceDao; -import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; -import org.apache.cloudstack.engine.subsystem.api.storage.HypervisorHostListener; -import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; -import org.apache.cloudstack.storage.datastore.db.StoragePoolDetailsDao; -import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; -import org.apache.cloudstack.storage.datastore.util.DateraObject; -import org.apache.cloudstack.storage.datastore.util.DateraUtil; -import org.apache.log4j.Logger; - -import javax.inject.Inject; -import java.io.UnsupportedEncodingException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; public class DateraHostListener implements HypervisorHostListener { private static final Logger s_logger = Logger.getLogger(DateraHostListener.class); diff --git a/plugins/storage/volume/solidfire/src/main/java/org/apache/cloudstack/storage/datastore/driver/SolidFirePrimaryDataStoreDriver.java b/plugins/storage/volume/solidfire/src/main/java/org/apache/cloudstack/storage/datastore/driver/SolidFirePrimaryDataStoreDriver.java index 19b678e4aeb4..aa277cd4dab5 100644 --- a/plugins/storage/volume/solidfire/src/main/java/org/apache/cloudstack/storage/datastore/driver/SolidFirePrimaryDataStoreDriver.java +++ b/plugins/storage/volume/solidfire/src/main/java/org/apache/cloudstack/storage/datastore/driver/SolidFirePrimaryDataStoreDriver.java @@ -24,6 +24,33 @@ import javax.inject.Inject; +import org.apache.cloudstack.engine.subsystem.api.storage.ChapInfo; +import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult; +import org.apache.cloudstack.engine.subsystem.api.storage.CreateCmdResult; +import org.apache.cloudstack.engine.subsystem.api.storage.DataObject; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreCapabilities; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; +import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine; +import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreDriver; +import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo; +import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo; +import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory; +import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; +import org.apache.cloudstack.framework.async.AsyncCompletionCallback; +import org.apache.cloudstack.storage.command.CommandResult; +import org.apache.cloudstack.storage.command.CreateObjectAnswer; +import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; +import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreDao; +import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreVO; +import org.apache.cloudstack.storage.datastore.db.StoragePoolDetailVO; +import org.apache.cloudstack.storage.datastore.db.StoragePoolDetailsDao; +import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; +import org.apache.cloudstack.storage.datastore.util.SolidFireUtil; +import org.apache.cloudstack.storage.to.SnapshotObjectTO; +import org.apache.commons.lang.StringUtils; +import org.apache.log4j.Logger; + import com.cloud.agent.api.Answer; import com.cloud.agent.api.to.DataObjectType; import com.cloud.agent.api.to.DataStoreTO; @@ -39,12 +66,12 @@ import com.cloud.storage.ResizeVolumePayload; import com.cloud.storage.Snapshot.State; import com.cloud.storage.SnapshotVO; +import com.cloud.storage.Storage.StoragePoolType; import com.cloud.storage.StoragePool; import com.cloud.storage.VMTemplateStoragePoolVO; import com.cloud.storage.Volume; import com.cloud.storage.VolumeDetailVO; import com.cloud.storage.VolumeVO; -import com.cloud.storage.Storage.StoragePoolType; import com.cloud.storage.dao.SnapshotDao; import com.cloud.storage.dao.SnapshotDetailsDao; import com.cloud.storage.dao.SnapshotDetailsVO; @@ -57,36 +84,8 @@ import com.cloud.user.dao.AccountDao; import com.cloud.utils.db.GlobalLock; import com.cloud.utils.exception.CloudRuntimeException; - import com.google.common.base.Preconditions; -import org.apache.cloudstack.engine.subsystem.api.storage.ChapInfo; -import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult; -import org.apache.cloudstack.engine.subsystem.api.storage.CreateCmdResult; -import org.apache.cloudstack.engine.subsystem.api.storage.DataObject; -import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; -import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreCapabilities; -import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; -import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreDriver; -import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo; -import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo; -import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory; -import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; -import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine; -import org.apache.cloudstack.framework.async.AsyncCompletionCallback; -import org.apache.cloudstack.storage.command.CommandResult; -import org.apache.cloudstack.storage.command.CreateObjectAnswer; -import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; -import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreDao; -import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreVO; -import org.apache.cloudstack.storage.datastore.db.StoragePoolDetailVO; -import org.apache.cloudstack.storage.datastore.db.StoragePoolDetailsDao; -import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; -import org.apache.cloudstack.storage.datastore.util.SolidFireUtil; -import org.apache.cloudstack.storage.to.SnapshotObjectTO; -import org.apache.commons.lang.StringUtils; -import org.apache.log4j.Logger; - public class SolidFirePrimaryDataStoreDriver implements PrimaryDataStoreDriver { private static final Logger LOGGER = Logger.getLogger(SolidFirePrimaryDataStoreDriver.class); private static final int LOWEST_HYPERVISOR_SNAPSHOT_RESERVE = 10; diff --git a/plugins/user-authenticators/ldap/pom.xml b/plugins/user-authenticators/ldap/pom.xml index fefaba0617d9..b46e3c71e52f 100644 --- a/plugins/user-authenticators/ldap/pom.xml +++ b/plugins/user-authenticators/ldap/pom.xml @@ -46,6 +46,7 @@ ${gmaven.version} 1.7 + @@ -147,9 +148,20 @@
org.mockito - mockito-all + mockito-core ${cs.mockito.version} compile + + + net.bytebuddy + byte-buddy + + + + + net.bytebuddy + byte-buddy + 1.10.5 junit diff --git a/plugins/user-authenticators/ldap/src/test/java/org/apache/cloudstack/api/command/LdapCreateAccountCmdTest.java b/plugins/user-authenticators/ldap/src/test/java/org/apache/cloudstack/api/command/LdapCreateAccountCmdTest.java index 55d7f624b530..5e7728ba0d83 100644 --- a/plugins/user-authenticators/ldap/src/test/java/org/apache/cloudstack/api/command/LdapCreateAccountCmdTest.java +++ b/plugins/user-authenticators/ldap/src/test/java/org/apache/cloudstack/api/command/LdapCreateAccountCmdTest.java @@ -27,11 +27,11 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.runners.MockitoJUnitRunner; +import org.mockito.junit.MockitoJUnitRunner; import static org.junit.Assert.fail; -import static org.mockito.Matchers.anyString; -import static org.mockito.Matchers.isNull; +import static org.mockito.ArgumentMatchers.isNull; +import static org.mockito.ArgumentMatchers.nullable; import static org.powermock.api.mockito.PowerMockito.spy; import static org.powermock.api.mockito.PowerMockito.when; @@ -56,7 +56,7 @@ public void setUp() throws NoSuchFieldException, IllegalAccessException { @Test(expected = ServerApiException.class) public void failureToRetrieveLdapUser() throws Exception { // We have an LdapManager, AccountService and LdapCreateAccountCmd and LDAP user that doesn't exist - when(ldapManager.getUser(anyString(), isNull(Long.class))).thenThrow(NoLdapUserMatchingQueryException.class); + when(ldapManager.getUser(nullable(String.class), isNull())).thenThrow(NoLdapUserMatchingQueryException.class); ldapCreateAccountCmd.execute(); fail("An exception should have been thrown: " + ServerApiException.class); } @@ -65,7 +65,7 @@ public void failureToRetrieveLdapUser() throws Exception { public void failedCreationDueToANullResponseFromCloudstackAccountCreator() throws Exception { // We have an LdapManager, AccountService and LdapCreateAccountCmd LdapUser mrMurphy = new LdapUser("rmurphy", "rmurphy@cloudstack.org", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org", "engineering", false, null); - when(ldapManager.getUser(anyString(), isNull(Long.class))).thenReturn(mrMurphy).thenReturn(mrMurphy); + when(ldapManager.getUser(nullable(String.class), isNull())).thenReturn(mrMurphy).thenReturn(mrMurphy); ldapCreateAccountCmd.execute(); fail("An exception should have been thrown: " + ServerApiException.class); } diff --git a/plugins/user-authenticators/ldap/src/test/java/org/apache/cloudstack/api/command/LdapImportUsersCmdTest.java b/plugins/user-authenticators/ldap/src/test/java/org/apache/cloudstack/api/command/LdapImportUsersCmdTest.java index 8db267332106..dd871df0a18f 100644 --- a/plugins/user-authenticators/ldap/src/test/java/org/apache/cloudstack/api/command/LdapImportUsersCmdTest.java +++ b/plugins/user-authenticators/ldap/src/test/java/org/apache/cloudstack/api/command/LdapImportUsersCmdTest.java @@ -27,10 +27,10 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.runners.MockitoJUnitRunner; import org.apache.cloudstack.api.response.LdapUserResponse; import org.apache.cloudstack.ldap.LdapManager; import org.apache.cloudstack.ldap.LdapUser; +import org.mockito.junit.MockitoJUnitRunner; import java.util.ArrayList; import java.util.List; diff --git a/plugins/user-authenticators/ldap/src/test/java/org/apache/cloudstack/api/command/LdapListUsersCmdTest.java b/plugins/user-authenticators/ldap/src/test/java/org/apache/cloudstack/api/command/LdapListUsersCmdTest.java index d84e73aae47e..001265df3f17 100644 --- a/plugins/user-authenticators/ldap/src/test/java/org/apache/cloudstack/api/command/LdapListUsersCmdTest.java +++ b/plugins/user-authenticators/ldap/src/test/java/org/apache/cloudstack/api/command/LdapListUsersCmdTest.java @@ -36,6 +36,7 @@ import org.junit.runner.RunWith; import org.mockito.Mock; import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PowerMockIgnore; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; @@ -47,9 +48,8 @@ import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyBoolean; -import static org.mockito.Matchers.anyLong; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.powermock.api.mockito.PowerMockito.doReturn; @@ -59,6 +59,7 @@ @RunWith(PowerMockRunner.class) @PrepareForTest(CallContext.class) +@PowerMockIgnore({"javax.xml.*", "org.w3c.dom.*", "org.apache.xerces.*", "org.xml.*"}) public class LdapListUsersCmdTest implements LdapConfigurationChanger { public static final String LOCAL_DOMAIN_ID = "12345678-90ab-cdef-fedc-ba0987654321"; @@ -133,7 +134,7 @@ public void successfulResponseFromExecute() throws NoLdapUserMatchingQueryExcept ldapListUsersCmd.execute(); - verify(queryService, times(1)).searchForUsers(anyLong(), anyBoolean()); + verify(queryService, times(1)).searchForUsers(nullable(Long.class), nullable(Boolean.class)); assertNotEquals(0, ((ListResponse)ldapListUsersCmd.getResponseObject()).getResponses().size()); } @@ -174,7 +175,7 @@ public void isACloudstackUser() { */ @Test public void isNotACloudstackUser() { - doReturn(new ListResponse()).when(queryService).searchForUsers(anyLong(), anyBoolean()); + doReturn(new ListResponse()).when(queryService).searchForUsers(nullable(Long.class), nullable(Boolean.class)); LdapUser ldapUser = new LdapUser("rmurphy", "rmurphy@cloudstack.org", "Ryan", "Murphy", "cn=rmurphy,dc=cloudstack,dc=org", null, false, null); @@ -413,7 +414,7 @@ private DomainVO useDomain(String domainName, long domainId) { domainVO.setName(domainName); domainVO.setId(domainId); domainVO.setUuid(LOCAL_DOMAIN_ID); - when(domainService.getDomain(anyLong())).thenReturn(domainVO); + when(domainService.getDomain(nullable(Long.class))).thenReturn(domainVO); return domainVO; } @@ -430,7 +431,7 @@ private void mockACSUserSearch() { ListResponse queryServiceResponse = new ListResponse<>(); queryServiceResponse.setResponses(responses); - doReturn(queryServiceResponse).when(queryService).searchForUsers(anyLong(), anyBoolean()); + doReturn(queryServiceResponse).when(queryService).searchForUsers(nullable(Long.class), nullable(Boolean.class)); } private UserResponse createMockUserResponse(String uid, User.Source source) { diff --git a/plugins/user-authenticators/ldap/src/test/java/org/apache/cloudstack/ldap/ADLdapUserManagerImplTest.java b/plugins/user-authenticators/ldap/src/test/java/org/apache/cloudstack/ldap/ADLdapUserManagerImplTest.java index c2fc7ee4b5e9..bf9d7437446e 100644 --- a/plugins/user-authenticators/ldap/src/test/java/org/apache/cloudstack/ldap/ADLdapUserManagerImplTest.java +++ b/plugins/user-authenticators/ldap/src/test/java/org/apache/cloudstack/ldap/ADLdapUserManagerImplTest.java @@ -20,13 +20,14 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.runners.MockitoJUnitRunner; +import org.mockito.junit.MockitoJUnitRunner; import javax.naming.directory.SearchControls; import javax.naming.ldap.LdapContext; import static org.junit.Assert.assertTrue; import static org.mockito.Matchers.any; +import static org.mockito.Mockito.lenient; import static org.mockito.Mockito.when; @RunWith(MockitoJUnitRunner.class) @@ -78,9 +79,9 @@ public void testGenerateADSearchFilterWithNestedGroupsDisabled() { @Test(expected = IllegalArgumentException.class) public void testGetUsersInGroupUsingNullGroup() throws Exception { String[] returnAttributes = {"username", "firstname", "lastname", "email"}; - when(ldapConfiguration.getScope()).thenReturn(SearchControls.SUBTREE_SCOPE); - when(ldapConfiguration.getReturnAttributes(null)).thenReturn(returnAttributes); - when(ldapConfiguration.getBaseDn(any())).thenReturn(null).thenReturn(null).thenReturn("DC=cloud,DC=citrix,DC=com"); + lenient().when(ldapConfiguration.getScope()).thenReturn(SearchControls.SUBTREE_SCOPE); + lenient().when(ldapConfiguration.getReturnAttributes(null)).thenReturn(returnAttributes); + lenient().when(ldapConfiguration.getBaseDn(any())).thenReturn(null).thenReturn(null).thenReturn("DC=cloud,DC=citrix,DC=com"); LdapContext context = ldapContext; String [] groups = {null, "group", null}; diff --git a/plugins/user-authenticators/ldap/src/test/java/org/apache/cloudstack/ldap/LdapAuthenticatorTest.java b/plugins/user-authenticators/ldap/src/test/java/org/apache/cloudstack/ldap/LdapAuthenticatorTest.java index 4c0519de2568..2e5758025e3d 100644 --- a/plugins/user-authenticators/ldap/src/test/java/org/apache/cloudstack/ldap/LdapAuthenticatorTest.java +++ b/plugins/user-authenticators/ldap/src/test/java/org/apache/cloudstack/ldap/LdapAuthenticatorTest.java @@ -30,7 +30,7 @@ import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.Mock; -import org.mockito.runners.MockitoJUnitRunner; +import org.mockito.junit.MockitoJUnitRunner; import java.util.ArrayList; import java.util.List; @@ -41,6 +41,7 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.mockito.Matchers.anyLong; +import static org.mockito.Mockito.lenient; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; @@ -73,7 +74,7 @@ public void authenticateAsNativeUser() throws Exception { final UserAccountVO user = new UserAccountVO(); user.setSource(User.Source.NATIVE); - when(userAccountDao.getUserAccount(username, domainId)).thenReturn(user); + lenient().when(userAccountDao.getUserAccount(username, domainId)).thenReturn(user); Pair rc; rc = ldapAuthenticator.authenticate(username, "password", domainId, (Map)null); assertFalse("authentication succeeded when it should have failed", rc.first()); diff --git a/plugins/user-authenticators/ldap/src/test/java/org/apache/cloudstack/ldap/LdapDirectoryServerConnectionTest.java b/plugins/user-authenticators/ldap/src/test/java/org/apache/cloudstack/ldap/LdapDirectoryServerConnectionTest.java index f3a17fae36cd..2d2690f8e3a4 100644 --- a/plugins/user-authenticators/ldap/src/test/java/org/apache/cloudstack/ldap/LdapDirectoryServerConnectionTest.java +++ b/plugins/user-authenticators/ldap/src/test/java/org/apache/cloudstack/ldap/LdapDirectoryServerConnectionTest.java @@ -38,7 +38,7 @@ import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.Mock; -import org.mockito.runners.MockitoJUnitRunner; +import org.mockito.junit.MockitoJUnitRunner; import java.io.IOException; import java.util.ArrayList; @@ -51,7 +51,7 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; -import static org.mockito.Mockito.when; +import static org.mockito.Mockito.lenient; @RunWith(MockitoJUnitRunner.class) public class LdapDirectoryServerConnectionTest { @@ -82,15 +82,15 @@ public static void start() throws Exception { @Before public void setup() throws Exception { LdapConfigurationVO configurationVO = new LdapConfigurationVO("localhost",10389,null); - when(configurationDao.find("localhost",10389,null)).thenReturn(configurationVO); + lenient().when(configurationDao.find("localhost",10389,null)).thenReturn(configurationVO); ldapTestConfigTool.overrideConfigValue(configuration, "ldapBaseDn", "ou=system"); ldapTestConfigTool.overrideConfigValue(configuration, "ldapBindPassword", "secret"); ldapTestConfigTool.overrideConfigValue(configuration, "ldapBindPrincipal", "uid=admin,ou=system"); ldapTestConfigTool.overrideConfigValue(configuration, "ldapMemberOfAttribute", "memberOf"); - when(userManagerFactory.getInstance(LdapUserManager.Provider.OPENLDAP)).thenReturn(new OpenLdapUserManagerImpl(configuration)); + lenient().when(userManagerFactory.getInstance(LdapUserManager.Provider.OPENLDAP)).thenReturn(new OpenLdapUserManagerImpl(configuration)); // construct an ellaborate structure around a single object Pair, Integer> vos = new Pair, Integer>( Collections.singletonList(configurationVO),1); - when(configurationDao.searchConfigurations(null, 0, 1L)).thenReturn(vos); + lenient().when(configurationDao.searchConfigurations(null, 0, 1L)).thenReturn(vos); contextFactory = new LdapContextFactory(configuration); ldapManager = new LdapManagerImpl(configurationDao, contextFactory, userManagerFactory, configuration); diff --git a/plugins/user-authenticators/saml2/src/test/java/org/apache/cloudstack/SAML2AuthManagerImplTest.java b/plugins/user-authenticators/saml2/src/test/java/org/apache/cloudstack/SAML2AuthManagerImplTest.java index b06a1372a87c..94bf3f066960 100644 --- a/plugins/user-authenticators/saml2/src/test/java/org/apache/cloudstack/SAML2AuthManagerImplTest.java +++ b/plugins/user-authenticators/saml2/src/test/java/org/apache/cloudstack/SAML2AuthManagerImplTest.java @@ -19,11 +19,8 @@ package org.apache.cloudstack; -import com.cloud.user.DomainManager; -import com.cloud.user.User; -import com.cloud.user.UserVO; -import com.cloud.user.dao.UserDao; -import junit.framework.TestCase; +import java.lang.reflect.Field; + import org.apache.cloudstack.framework.security.keystore.KeystoreDao; import org.apache.cloudstack.saml.SAML2AuthManagerImpl; import org.apache.cloudstack.saml.SAMLTokenDao; @@ -35,7 +32,12 @@ import org.mockito.Mockito; import org.mockito.runners.MockitoJUnitRunner; -import java.lang.reflect.Field; +import com.cloud.user.DomainManager; +import com.cloud.user.User; +import com.cloud.user.UserVO; +import com.cloud.user.dao.UserDao; + +import junit.framework.TestCase; @RunWith(MockitoJUnitRunner.class) public class SAML2AuthManagerImplTest extends TestCase { @@ -164,7 +166,7 @@ public void testGetCommands() { assertTrue(saml2AuthManager.getCommands().size() == 0); assertTrue(saml2AuthManager.getAuthCommands().size() == 0); // Re-enable the plugin - Mockito.doReturn(true).when(saml2AuthManager).isSAMLPluginEnabled(); + Mockito.lenient().doReturn(true).when(saml2AuthManager).isSAMLPluginEnabled(); } @Test diff --git a/plugins/user-authenticators/saml2/src/test/java/org/apache/cloudstack/SAML2UserAuthenticatorTest.java b/plugins/user-authenticators/saml2/src/test/java/org/apache/cloudstack/SAML2UserAuthenticatorTest.java index 5b3738856033..c0f61d729df2 100644 --- a/plugins/user-authenticators/saml2/src/test/java/org/apache/cloudstack/SAML2UserAuthenticatorTest.java +++ b/plugins/user-authenticators/saml2/src/test/java/org/apache/cloudstack/SAML2UserAuthenticatorTest.java @@ -19,24 +19,25 @@ package org.apache.cloudstack; -import com.cloud.server.auth.UserAuthenticator.ActionOnFailedAuthentication; -import com.cloud.user.UserAccountVO; -import com.cloud.user.UserVO; -import com.cloud.user.dao.UserAccountDao; -import com.cloud.user.dao.UserDao; -import com.cloud.utils.Pair; -import org.apache.cloudstack.saml.SAMLPluginConstants; +import java.lang.reflect.Field; +import java.util.HashMap; +import java.util.Map; + import org.apache.cloudstack.saml.SAML2UserAuthenticator; +import org.apache.cloudstack.saml.SAMLPluginConstants; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.Mockito; -import org.mockito.runners.MockitoJUnitRunner; +import org.mockito.junit.MockitoJUnitRunner; -import java.lang.reflect.Field; -import java.util.HashMap; -import java.util.Map; +import com.cloud.server.auth.UserAuthenticator.ActionOnFailedAuthentication; +import com.cloud.user.UserAccountVO; +import com.cloud.user.UserVO; +import com.cloud.user.dao.UserAccountDao; +import com.cloud.user.dao.UserDao; +import com.cloud.utils.Pair; @RunWith(MockitoJUnitRunner.class) public class SAML2UserAuthenticatorTest { @@ -69,7 +70,7 @@ public void authenticate() throws NoSuchFieldException, SecurityException, Illeg UserVO user = new UserVO(); Mockito.when(userAccountDao.getUserAccount(Mockito.anyString(), Mockito.anyLong())).thenReturn(account); - Mockito.when(userDao.getUser(Mockito.anyLong())).thenReturn(user); + Mockito.lenient().when(userDao.getUser(Mockito.anyLong())).thenReturn(user); Pair pair; Map params = new HashMap(); diff --git a/plugins/user-authenticators/saml2/src/test/java/org/apache/cloudstack/api/command/ListAndSwitchSAMLAccountCmdTest.java b/plugins/user-authenticators/saml2/src/test/java/org/apache/cloudstack/api/command/ListAndSwitchSAMLAccountCmdTest.java index 8985a0fbf3fa..5c902b272089 100644 --- a/plugins/user-authenticators/saml2/src/test/java/org/apache/cloudstack/api/command/ListAndSwitchSAMLAccountCmdTest.java +++ b/plugins/user-authenticators/saml2/src/test/java/org/apache/cloudstack/api/command/ListAndSwitchSAMLAccountCmdTest.java @@ -19,17 +19,18 @@ package org.apache.cloudstack.api.command; -import com.cloud.domain.DomainVO; -import com.cloud.domain.dao.DomainDao; -import com.cloud.user.Account; -import com.cloud.user.AccountService; -import com.cloud.user.User; -import com.cloud.user.UserAccountVO; -import com.cloud.user.UserVO; -import com.cloud.user.dao.UserAccountDao; -import com.cloud.user.dao.UserDao; -import com.cloud.utils.HttpUtils; -import junit.framework.TestCase; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.nullable; + +import java.lang.reflect.Field; +import java.net.InetAddress; +import java.util.HashMap; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; import org.apache.cloudstack.api.ApiServerService; @@ -45,13 +46,18 @@ import org.mockito.Mockito; import org.mockito.runners.MockitoJUnitRunner; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpSession; -import java.lang.reflect.Field; -import java.net.InetAddress; -import java.util.HashMap; -import java.util.Map; +import com.cloud.domain.DomainVO; +import com.cloud.domain.dao.DomainDao; +import com.cloud.user.Account; +import com.cloud.user.AccountService; +import com.cloud.user.User; +import com.cloud.user.UserAccountVO; +import com.cloud.user.UserVO; +import com.cloud.user.dao.UserAccountDao; +import com.cloud.user.dao.UserDao; +import com.cloud.utils.HttpUtils; + +import junit.framework.TestCase; @RunWith(MockitoJUnitRunner.class) public class ListAndSwitchSAMLAccountCmdTest extends TestCase { @@ -91,8 +97,8 @@ public void testListAndSwitchSAMLAccountCmd() throws Exception { Mockito.when(session.getAttribute("userid")).thenReturn(2L); params.put(ApiConstants.USER_ID, new String[]{"2"}); params.put(ApiConstants.DOMAIN_ID, new String[]{"1"}); - Mockito.when(userDao.findByUuid(Mockito.anyString())).thenReturn(new UserVO(2L)); - Mockito.when(domainDao.findByUuid(Mockito.anyString())).thenReturn(new DomainVO()); + Mockito.when(userDao.findByUuid(anyString())).thenReturn(new UserVO(2L)); + Mockito.when(domainDao.findByUuid(anyString())).thenReturn(new DomainVO()); // Mock/field setup ListAndSwitchSAMLAccountCmd cmd = new ListAndSwitchSAMLAccountCmd(); @@ -181,8 +187,9 @@ public void testListAndSwitchSAMLAccountCmd() throws Exception { loginCmdResponse.setFirstName("firstName"); loginCmdResponse.setLastName("lastName"); loginCmdResponse.setSessionKey("newSessionKeyString"); - Mockito.when(apiServer.loginUser(Mockito.any(HttpSession.class), Mockito.anyString(), Mockito.anyString(), - Mockito.anyLong(), Mockito.anyString(), Mockito.any(InetAddress.class), Mockito.anyMap())).thenReturn(loginCmdResponse); + Mockito.when(apiServer.loginUser(nullable(HttpSession.class), nullable(String.class), nullable(String.class), + nullable(Long.class), nullable(String.class), nullable(InetAddress.class), nullable(Map.class))).thenReturn(loginCmdResponse); + Mockito.doNothing().when(resp).sendRedirect(nullable(String.class)); try { cmd.authenticate("command", params, session, null, HttpUtils.RESPONSE_TYPE_JSON, new StringBuilder(), req, resp); } catch (ServerApiException exception) { @@ -190,7 +197,7 @@ public void testListAndSwitchSAMLAccountCmd() throws Exception { } finally { // accountService should have been called 4 times by now, for this case twice and 2 for cases above Mockito.verify(accountService, Mockito.times(4)).getUserAccountById(Mockito.anyLong()); - Mockito.verify(resp, Mockito.times(1)).sendRedirect(Mockito.anyString()); + Mockito.verify(resp, Mockito.times(1)).sendRedirect(anyString()); } } diff --git a/plugins/user-authenticators/saml2/src/test/java/org/apache/cloudstack/api/command/SAML2LoginAPIAuthenticatorCmdTest.java b/plugins/user-authenticators/saml2/src/test/java/org/apache/cloudstack/api/command/SAML2LoginAPIAuthenticatorCmdTest.java index cc45cbb987da..39c8c231bf01 100644 --- a/plugins/user-authenticators/saml2/src/test/java/org/apache/cloudstack/api/command/SAML2LoginAPIAuthenticatorCmdTest.java +++ b/plugins/user-authenticators/saml2/src/test/java/org/apache/cloudstack/api/command/SAML2LoginAPIAuthenticatorCmdTest.java @@ -20,6 +20,7 @@ package org.apache.cloudstack.api.command; import static org.junit.Assert.assertFalse; +import static org.mockito.ArgumentMatchers.nullable; import java.io.IOException; import java.lang.reflect.Field; @@ -51,7 +52,7 @@ import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.Spy; -import org.mockito.runners.MockitoJUnitRunner; +import org.mockito.junit.MockitoJUnitRunner; import org.opensaml.common.SAMLVersion; import org.opensaml.saml2.core.Assertion; import org.opensaml.saml2.core.AttributeStatement; @@ -178,16 +179,16 @@ public void testAuthenticate() throws Exception { providerMetadata.setSsoUrl("http://test.local"); providerMetadata.setSloUrl("http://test.local"); - Mockito.when(session.getAttribute(Mockito.anyString())).thenReturn(null); + Mockito.lenient().when(session.getAttribute(Mockito.anyString())).thenReturn(null); - Mockito.when(domain.getId()).thenReturn(1L); - Mockito.when(domainMgr.getDomain(Mockito.anyString())).thenReturn(domain); + Mockito.lenient().when(domain.getId()).thenReturn(1L); + Mockito.lenient().when(domainMgr.getDomain(Mockito.anyString())).thenReturn(domain); UserAccountVO user = new UserAccountVO(); user.setId(1000L); - Mockito.when(userAccountDao.getUserAccount(Mockito.anyString(), Mockito.anyLong())).thenReturn(user); - Mockito.when(apiServer.verifyUser(Mockito.anyLong())).thenReturn(false); + Mockito.lenient().when(userAccountDao.getUserAccount(Mockito.anyString(), Mockito.anyLong())).thenReturn(user); + Mockito.lenient().when(apiServer.verifyUser(nullable(Long.class))).thenReturn(false); Mockito.when(samlAuthManager.getSPMetadata()).thenReturn(providerMetadata); - Mockito.when(samlAuthManager.getIdPMetadata(Mockito.anyString())).thenReturn(providerMetadata); + Mockito.when(samlAuthManager.getIdPMetadata(nullable(String.class))).thenReturn(providerMetadata); Map params = new HashMap(); @@ -197,7 +198,7 @@ public void testAuthenticate() throws Exception { // SSO SAMLResponse verification test, this should throw ServerApiException for auth failure params.put(SAMLPluginConstants.SAML_RESPONSE, new String[]{"Some String"}); - Mockito.stub(cmd.processSAMLResponse(Mockito.anyString())).toReturn(buildMockResponse()); + Mockito.when(cmd.processSAMLResponse(Mockito.anyString())).thenReturn(buildMockResponse()); boolean failing = true; try { cmd.authenticate("command", params, session, InetAddress.getByName("127.0.0.1"), HttpUtils.RESPONSE_TYPE_JSON, new StringBuilder(), req, resp); @@ -272,7 +273,7 @@ public void whenFailToAuthenticateThrowExceptionOrRedirectToUrlTestSaml2FailedLo private UserAccountVO configureTestWhenFailToAuthenticateThrowExceptionOrRedirectToUrl(String entity, String configurationValue, Boolean isUserAuthorized) throws IOException { - Mockito.when(samlAuthManager.isUserAuthorized(Mockito.anyLong(), Mockito.anyString())).thenReturn(isUserAuthorized); + Mockito.when(samlAuthManager.isUserAuthorized(nullable(Long.class), nullable(String.class))).thenReturn(isUserAuthorized); SAML2LoginAPIAuthenticatorCmd.saml2FailedLoginRedirectUrl = new ConfigKey("Advanced", String.class, "saml2.failed.login.redirect.url", configurationValue, "The URL to redirect the SAML2 login failed message (the default vaulue is empty).", true); UserAccountVO userAccount = new UserAccountVO(); diff --git a/pom.xml b/pom.xml index 9a438bd60695..28cd1c4f98d7 100644 --- a/pom.xml +++ b/pom.xml @@ -51,26 +51,26 @@ UTF-8 - 1.8 + 11 target build/replace.properties 1.8 3.0.0 - 3.0.0 + 3.1.0 2.7 - 3.7.0 - 3.1.0 - 2.21.0 + 3.8.1 + 3.1.1 + 2.22.2 3.0.5 - 3.1.0 - 3.9.0 - 2.9 + 3.2.0 + 3.12.0 + 3.0.0 2.5.3 3.1.0 - 3.7.1 - 2.21.0 + 3.8.2 + 2.22.2 1.2.17 @@ -78,95 +78,98 @@ 1.1.1 - 1.11 - 4.1 - 1.15 + 1.14 + 4.4 + 1.19 1.3 - 1.3.3 + 1.4 3.1 2.6 - 3.6 + 3.9 3.6 1.6 1.10 - 1.1.0 - 2.2.0 + 1.2.2 + 2.7.0 0.5 2.6 - 2.4.3 + 2.7.0 2.5.4 1.3 - 4.12 + 4.13 1.13.1 18.0 - 1.10.19 - 1.6.4 + 3.2.4 + 2.0.5 1.0-20081010.060147 1.0.1 - 6.1.1 + 7.1.0 2.11.0 2.11.0 - 5.1.1 + 5.8.0 1.0.9 - 1.7.1 - 1.11.213 + 1.9.5 + 1.11.717 1.2.8 1.4 1.5.6 - 1.9.1 - 1.59 - 3.2.5 - 8.7 + 1.12 + 1.64 + 3.3.0 + 8.18 3.2.0 2.6.11 - 0.0.23 - 2.4.12 + 0.0.27 + 2.4.17 1.7.2 - 23.6-jre - 4.5.4 - 4.4.8 - 2.15 + 28.2-jre + 4.5.11 + 4.4.13 + 2.17 2.9.2 - 1.9.2 - 0.16 - 3.22.0-GA - 2.10.3 + 1.9.3 + 0.17 + 3.26.0-GA + 3.1.1 + 1.3.2 + 2.3.0 + 2.3.2 1.19.4 - 9.4.8.v20171121 - 9.2.22.v20170606 + 9.4.26.v20200117 + 9.4.26.v20200117 4.0.0 2.8.1 - 2.2.0 - 0.1.54 + 2.2.1 + 0.1.55 20090211 1.2 1.2.1 - 0.11.0.1 + 0.11.0.3 0.5.1 1.5.0-b01 - 5.1.34 + 8.0.19 2.0.4 10.1 2.6.4 0.5.0 1.5.1 - 0.9.11 - 2.5.8_1 - 4.0.0 - 8.0.30 - 1.0.0-build221 + 0.9.12 + 3.3.3_1 + 4.0.1 + 8.5.47 + 1.0.0-build222 6.7 6.2.0-3.1 1.4.01 3.1.3 - 1.4.10 - 1.7.22 - 5.0.2.RELEASE + 1.4.11.1 + 1.7.29 + 5.2.3.RELEASE @@ -419,7 +422,7 @@ mysql mysql-connector-java ${cs.mysql.version} - provided,test + test net.sf.ehcache @@ -645,7 +648,7 @@ org.mockito - mockito-all + mockito-core ${cs.mockito.version} test @@ -673,14 +676,21 @@ ${cs.junit.dataprovider.version} test + + org.powermock + powermock-core + ${cs.powermock.version} + test + org.powermock powermock-module-junit4 ${cs.powermock.version} + test org.powermock - powermock-api-mockito + powermock-api-mockito2 ${cs.powermock.version} test @@ -1002,7 +1012,12 @@ true 128m 512m - -XDignore.symbol.file=true + + -XDignore.symbol.file=true + --add-opens=java.base/java.lang=ALL-UNNAMED + --add-exports=java.base/sun.security.x509=ALL-UNNAMED + --add-exports=java.base/sun.security.provider=ALL-UNNAMED + diff --git a/scripts/storage/secondary/cloud-install-sys-tmplt b/scripts/storage/secondary/cloud-install-sys-tmplt index b900f8f30223..cc4435475d15 100755 --- a/scripts/storage/secondary/cloud-install-sys-tmplt +++ b/scripts/storage/secondary/cloud-install-sys-tmplt @@ -55,7 +55,7 @@ dbHost="localhost" dbUser="root" dbPassword= dbPort=3306 -jasypt='/usr/share/cloudstack-common/lib/jasypt-1.9.2.jar' +jasypt='/usr/share/cloudstack-common/lib/jasypt-1.9.3.jar' # check if first parameter is not a dash (-) then print the usage block if [[ ! $@ =~ ^\-.+ ]]; then @@ -275,4 +275,4 @@ echo "$ext.virtualsize=$vrtmpltsize" >> $destdir/template.properties echo "virtualsize=$vrtmpltsize" >> $destdir/template.properties echo "$ext.size=$tmpltsize" >> $destdir/template.properties -echo "Successfully installed system VM template $tmpltimg and template.properties to $destdir" \ No newline at end of file +echo "Successfully installed system VM template $tmpltimg and template.properties to $destdir" diff --git a/scripts/util/keystore-cert-import b/scripts/util/keystore-cert-import index 459f8366ee46..a2b57bff07e2 100755 --- a/scripts/util/keystore-cert-import +++ b/scripts/util/keystore-cert-import @@ -56,6 +56,11 @@ for caChain in $(ls cloudca.*); do done rm -f cloudca.* +# Stop cloud service in systemvm +if [ "$MODE" == "ssh" ] && [ -f $SYSTEM_FILE ]; then + systemctl stop cloud > /dev/null 2>&1 +fi + # Import private key if available if [ ! -z "${PRIVKEY// }" ]; then echo "$PRIVKEY" > "$PRIVKEY_FILE" @@ -93,6 +98,11 @@ if [ -f "$SYSTEM_FILE" ]; then chmod 755 /usr/local/share/ca-certificates/cloudstack chmod 644 /usr/local/share/ca-certificates/cloudstack/ca.crt update-ca-certificates > /dev/null 2>&1 || true + + # Ensure cloud service is running in systemvm + if [ "$MODE" == "ssh" ]; then + systemctl start cloud > /dev/null 2>&1 + fi fi # Fix file permission diff --git a/scripts/vm/hypervisor/vmware/discover_networks.py b/scripts/vm/hypervisor/vmware/discover_networks.py new file mode 100755 index 000000000000..d19e7847a41c --- /dev/null +++ b/scripts/vm/hypervisor/vmware/discover_networks.py @@ -0,0 +1,288 @@ +#!/usr/bin/env python3 +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. + +from __future__ import print_function +from pyVim.connect import SmartConnect, SmartConnectNoSSL, Disconnect +from pyVmomi import vim +import atexit +import sys +import argparse +import json + +isDebugLogs = False +hostClusterNameDict = {} +pgHostNameDict = {} +networksDict = {} + +def log_message(msg): + if isDebugLogs == True: + print(msg) + +def get_clusters(content, cluster=None): + if cluster is not None: + log_message("Getting clusters (name=" + cluster + ") ...") + else: + log_message("Getting clusters ...") + cluster_view = content.viewManager.CreateContainerView(content.rootFolder, + [vim.ClusterComputeResource], + True) + clusters = [] + if cluster is not None: + for c in cluster_view.view: + if c.name == cluster: + clusters.append(c) + hosts = c.host + for host in hosts: + hostClusterNameDict[host.name] = c.name + break + else: + for c in cluster_view.view: + clusters.append(c) + hosts = c.host + for host in hosts: + hostClusterNameDict[host.name] = c.name + cluster_view.Destroy() + log_message('\t{} cluster(s) found'.format(len(clusters))) + for c in clusters: + log_message('\t' + c.name) + return clusters + + +def get_vm_hosts(clusters): + log_message("Getting ESX hosts ...") + hosts = [] + for cluster in clusters: + hosts.extend(cluster.host) + log_message('\t{} host(s) found'.format(len(hosts))) + for host in hosts: + log_message('\t' + host.name) + return hosts + + +def get_vms(content): + log_message("Getting VMs ...") + vm_view = content.viewManager.CreateContainerView(content.rootFolder, + [vim.VirtualMachine], + True) + obj = [vm for vm in vm_view.view] + vm_view.Destroy() + return obj + + +def get_hosts_port_groups(hosts): + log_message("Collecting portGroups on hosts. This may take a while ...") + hostPgDict = {} + for host in hosts: + pgs = host.config.network.portgroup + hostPgDict[host] = pgs + for pg in pgs: + pgHostNameDict[pg.spec.name] = host.name + log_message("\tHost {} done.".format(host.name)) + log_message("\tPortgroup collection complete.") + return hostPgDict + + +def get_vm_info(vm, hostPgDict): + vmPowerState = vm.runtime.powerState + log_message('\tVM: ' + vm.name + '(' + vmPowerState + ')') + get_vm_nics(vm, hostPgDict) + + +def get_vm_nics(vm, hostPgDict): + try: + for dev in vm.config.hardware.device: + if isinstance(dev, vim.vm.device.VirtualEthernetCard): + dev_backing = dev.backing + portGroup = None + vlanId = None + isolatedPvlan = None + isolatedPvlanType = None + vSwitch = None + if hasattr(dev_backing, 'port'): + portGroupKey = dev.backing.port.portgroupKey + dvsUuid = dev.backing.port.switchUuid + try: + dvs = content.dvSwitchManager.QueryDvsByUuid(dvsUuid) + except: + log_message('\tError: Unable retrieve details for distributed vSwitch ' + dvsUuid) + portGroup = '' + vlanId = '' + vSwitch = '' + else: + pgObj = dvs.LookupDvPortGroup(portGroupKey) + portGroup = pgObj.config.name + try: + if isinstance(pgObj.config.defaultPortConfig.vlan, vim.dvs.VmwareDistributedVirtualSwitch.PvlanSpec): + for pvlanConfig in dvs.config.pvlanConfig: + if pvlanConfig.secondaryVlanId == pgObj.config.defaultPortConfig.vlan.pvlanId: + vlanId = str(pvlanConfig.primaryVlanId) + isolatedPvlanType = pvlanConfig.pvlanType + isolatedPvlan = str(pgObj.config.defaultPortConfig.vlan.pvlanId) + break + else: + vlanId = str(pgObj.config.defaultPortConfig.vlan.vlanId) + except AttributeError: + log_message('\tError: Unable retrieve details for portgroup ' + portGroup) + vlanId = '' + vSwitch = str(dvs.name) + else: + portGroup = dev.backing.network.name + vmHost = vm.runtime.host + # global variable hostPgDict stores portGroups per host + pgs = hostPgDict[vmHost] + for p in pgs: + if portGroup in p.key: + vlanId = str(p.spec.vlanId) + vSwitch = str(p.spec.vswitchName) + if portGroup is None: + portGroup = '' + if vlanId is None: + vlanId = '' + vmHostName = None + vmClusterName = None + try: + vmHostName = vm.runtime.host.name + except AttributeError: + vmHostName = '' + try: + vmClusterName = vm.runtime.host.parent.name + except AttributeError: + vmClusterName = '' + add_network(portGroup, vlanId, isolatedPvlanType, isolatedPvlan, vSwitch, vm.name, dev.deviceInfo.label, dev.macAddress, vmClusterName, vmHostName) + log_message('\t\t' + dev.deviceInfo.label + '->' + dev.macAddress + + ' @ ' + vSwitch + '->' + portGroup + + ' (VLAN ' + vlanId + ')') + except AttributeError: + log_message('\tError: Unable retrieve details for ' + vm.name) + +def add_network(portGroup, vlanId, isolatedPvlanType, isolatedPvlan, vSwitch, vmName, vmDeviceLabel, vmMacAddress, vmClusterName, vmHostName): + key = vSwitch + '->' + portGroup + ' (VLAN ' + vlanId + ')' + device = {"label": vmDeviceLabel, "macaddress": vmMacAddress} + vm = {"name":vmName, "device": device} + if key in networksDict: + network = networksDict[key] + network["virtualmachines"].append(vm) + networksDict[key] = network + else: + vms = [vm] + try: + host = pgHostNameDict[portGroup] + except KeyError: + host = vmHostName + try: + cluster = hostClusterNameDict[host] + except KeyError: + cluster = vmClusterName + + network = {"portgroup": portGroup, "cluster": cluster, "host": host, "switch": vSwitch, "virtualmachines": vms} + if vlanId != '': + network["vlanid"] = vlanId + if isolatedPvlan is not None: + network["isolatedpvlan"] = isolatedPvlan + if isolatedPvlanType is not None: + network["isolatedpvlantype"] = isolatedPvlanType + networksDict[key] = network + + +def get_args(): + parser = argparse.ArgumentParser( + description='Arguments for talking to vCenter') + + parser.add_argument('-s', '--host', + required=True, + action='store', + help='vSpehre service to connect to') + + parser.add_argument('-o', '--port', + type=int, + default=443, + action='store', + help='Port to connect on') + + parser.add_argument('-u', '--user', + required=True, + action='store', + help='User name to use') + + parser.add_argument('-p', '--password', + required=False, + action='store', + help='Password to use') + + parser.add_argument('-c', '--cluster', + required=False, + action='store', + help='Cluster for which discover networks') + + parser.add_argument('-S', '--disable_ssl_verification', + required=False, + action='store_true', + help='Disable ssl host certificate verification') + + parser.add_argument('-d', '--debug', + required=False, + action='store_true', + help='Debug log messages') + + args = parser.parse_args() + return args + + +def main(): + global content, isDebugLogs, hostClusterNameDict, pgHostNameDict, networksDict + args = get_args() + if args.password: + password = args.password + else: + password = getpass.getpass(prompt='Enter password for host %s and ' + 'user %s: ' % (args.host, args.user)) + if args.debug: + isDebugLogs = True + if args.disable_ssl_verification: + serviceInstance = SmartConnectNoSSL(host=args.host, + user=args.user, + pwd=password, + port=int(args.port)) + else: + serviceInstance = SmartConnect(host=args.host, + user=args.user, + pwd=password, + port=int(args.port)) + + atexit.register(Disconnect, serviceInstance) + content = serviceInstance.RetrieveContent() + if args.cluster: + clusters = get_clusters(content, args.cluster) + else: + clusters = get_clusters(content) + hosts = [] + if len(clusters) > 0: + hosts = get_vm_hosts(clusters) + if len(hosts) > 0: + hostPgDict = get_hosts_port_groups(hosts) + vms = get_vms(content) + log_message('\t{} VM(s) found'.format(len(vms))) + for vm in vms: + get_vm_info(vm, hostPgDict) + networks = list(networksDict.values()) + response = {"count": len(networks), "networks": networks} + print(json.dumps(response, indent=2, sort_keys=True)) + +# Main section +if __name__ == "__main__": + sys.exit(main()) diff --git a/scripts/vm/network/security_group.py b/scripts/vm/network/security_group.py index 2ca7ba82a4e7..680177e69549 100755 --- a/scripts/vm/network/security_group.py +++ b/scripts/vm/network/security_group.py @@ -145,6 +145,44 @@ def split_ips_by_family(ips): ip6s.append(ip) return ip4s, ip6s +def destroy_network_rules_for_nic(vm_name, vm_ip, vm_mac, vif, sec_ips): + try: + rules = execute("""iptables-save -t filter | awk '/ %s / { sub(/-A/, "-D", $1) ; print }'""" % vif ).split("\n") + for rule in filter(None, rules): + try: + execute("iptables " + rule) + except: + logging.debug("Ignoring failure to delete rule: " + rule) + except: + pass + + try: + dnats = execute("""iptables-save -t nat | awk '/ %s / { sub(/-A/, "-D", $1) ; print }'""" % vif ).split("\n") + for dnat in filter(None, dnats): + try: + execute("iptables -t nat " + dnat) + except: + logging.debug("Ignoring failure to delete dnat: " + dnat) + except: + pass + + ips = sec_ips.split(';') + ips.pop() + ips.append(vm_ip) + add_to_ipset(vm_name, ips, "-D") + ebtables_rules_vmip(vm_name, vm_mac, ips, "-D") + + vmchain_in = vm_name + "-in" + vmchain_out = vm_name + "-out" + vmchain_in_src = vm_name + "-in-src" + vmchain_out_dst = vm_name + "-out-dst" + try: + execute("ebtables -t nat -D " + vmchain_in_src + " -s " + vm_mac + " -j RETURN") + execute("ebtables -t nat -D " + vmchain_out_dst + " -p ARP --arp-op Reply --arp-mac-dst " + vm_mac + " -j RETURN") + execute("ebtables -t nat -D PREROUTING -i " + vif + " -j " + vmchain_in) + execute("ebtables -t nat -D POSTROUTING -o " + vif + " -j " + vmchain_out) + except: + logging.debug("Ignoring failure to delete ebtable rules for vm: " + vm_name) def get_bridge_physdev(brname): physdev = execute("bridge -o link show | awk '/master %s / && !/^[0-9]+: vnet/ {print $2}' | head -1" % brname) @@ -158,6 +196,9 @@ def destroy_network_rules_for_vm(vm_name, vif=None): vm_ipsetname=ipset_chain_name(vm_name) delete_rules_for_vm_in_bridge_firewall_chain(vm_name) + if 1 in [vm_name.startswith(c) for c in ['r-', 's-', 'v-']]: + return True + if vm_name.startswith('i-'): vmchain_default = '-'.join(vm_name.split('-')[:-1]) + "-def" @@ -198,9 +239,6 @@ def destroy_network_rules_for_vm(vm_name, vif=None): remove_rule_log_for_vm(vm_name) remove_secip_log_for_vm(vm_name) - if 1 in [vm_name.startswith(c) for c in ['r-', 's-', 'v-']]: - return True - return True @@ -228,7 +266,7 @@ def destroy_ebtables_rules(vm_name, vif): execute("ebtables -t nat " + cmd) except: logging.debug("Ignoring failure to delete ebtables rules for vm " + vm_name) - chains = [eb_vm_chain+"-in", eb_vm_chain+"-out", eb_vm_chain+"-in-ips", eb_vm_chain+"-out-ips"] + chains = [eb_vm_chain+"-in", eb_vm_chain+"-out", eb_vm_chain+"-in-ips", eb_vm_chain+"-out-ips", eb_vm_chain+"-in-src", eb_vm_chain+"-out-dst"] for chain in chains: try: execute("ebtables -t nat -F " + chain) @@ -237,14 +275,33 @@ def destroy_ebtables_rules(vm_name, vif): logging.debug("Ignoring failure to delete ebtables chain for vm " + vm_name) -def default_ebtables_rules(vm_name, vm_ip, vm_mac, vif): +def default_ebtables_rules(vm_name, vm_ip, vm_mac, vif, is_first_nic=False): eb_vm_chain=ebtables_chain_name(vm_name) vmchain_in = eb_vm_chain + "-in" vmchain_out = eb_vm_chain + "-out" vmchain_in_ips = eb_vm_chain + "-in-ips" vmchain_out_ips = eb_vm_chain + "-out-ips" + vmchain_in_src = eb_vm_chain + "-in-src" + vmchain_out_dst = eb_vm_chain + "-out-dst" - for chain in [vmchain_in, vmchain_out, vmchain_in_ips, vmchain_out_ips]: + if not is_first_nic: + try: + execute("ebtables -t nat -A PREROUTING -i " + vif + " -j " + vmchain_in) + execute("ebtables -t nat -A POSTROUTING -o " + vif + " -j " + vmchain_out) + execute("ebtables -t nat -I " + vmchain_in_src + " -s " + vm_mac + " -j RETURN") + if vm_ip: + execute("ebtables -t nat -I " + vmchain_in_ips + " -p ARP -s " + vm_mac + " --arp-mac-src " + vm_mac + " --arp-ip-src " + vm_ip + " -j RETURN") + execute("ebtables -t nat -I " + vmchain_out_dst + " -p ARP --arp-op Reply --arp-mac-dst " + vm_mac + " -j RETURN") + if vm_ip: + execute("ebtables -t nat -I " + vmchain_out_ips + " -p ARP --arp-ip-dst " + vm_ip + " -j RETURN") + except: + logging.debug("Failed to program rules for additional nic " + vif) + return False + return + + destroy_ebtables_rules(vm_name, vif) + + for chain in [vmchain_in, vmchain_out, vmchain_in_ips, vmchain_out_ips, vmchain_in_src, vmchain_out_dst]: try: execute("ebtables -t nat -N " + chain) except: @@ -256,17 +313,19 @@ def default_ebtables_rules(vm_name, vm_ip, vm_mac, vif): execute("ebtables -t nat -A POSTROUTING -o " + vif + " -j " + vmchain_out) execute("ebtables -t nat -A " + vmchain_in_ips + " -j DROP") execute("ebtables -t nat -A " + vmchain_out_ips + " -j DROP") + execute("ebtables -t nat -A " + vmchain_in_src + " -j DROP") + execute("ebtables -t nat -A " + vmchain_out_dst + " -p ARP --arp-op Reply -j DROP") + except: logging.debug("Failed to program default rules") return False try: - execute("ebtables -t nat -A " + vmchain_in + " -s ! " + vm_mac + " -j DROP") - execute("ebtables -t nat -A " + vmchain_in + " -p ARP -s ! " + vm_mac + " -j DROP") - execute("ebtables -t nat -A " + vmchain_in + " -p ARP --arp-mac-src ! " + vm_mac + " -j DROP") + execute("ebtables -t nat -A " + vmchain_in + " -j " + vmchain_in_src) + execute("ebtables -t nat -I " + vmchain_in_src + " -s " + vm_mac + " -j RETURN") + execute("ebtables -t nat -A " + vmchain_in + " -p ARP -j " + vmchain_in_ips) if vm_ip: - execute("ebtables -t nat -A " + vmchain_in + " -p ARP -j " + vmchain_in_ips) - execute("ebtables -t nat -I " + vmchain_in_ips + " -p ARP --arp-ip-src " + vm_ip + " -j RETURN") + execute("ebtables -t nat -I " + vmchain_in_ips + " -p ARP -s " + vm_mac + " --arp-mac-src " + vm_mac + " --arp-ip-src " + vm_ip + " -j RETURN") execute("ebtables -t nat -A " + vmchain_in + " -p ARP --arp-op Request -j ACCEPT") execute("ebtables -t nat -A " + vmchain_in + " -p ARP --arp-op Reply -j ACCEPT") execute("ebtables -t nat -A " + vmchain_in + " -p ARP -j DROP") @@ -275,9 +334,10 @@ def default_ebtables_rules(vm_name, vm_ip, vm_mac, vif): return False try: - execute("ebtables -t nat -A " + vmchain_out + " -p ARP --arp-op Reply --arp-mac-dst ! " + vm_mac + " -j DROP") + execute("ebtables -t nat -A " + vmchain_out + " -p ARP --arp-op Reply -j " + vmchain_out_dst) + execute("ebtables -t nat -I " + vmchain_out_dst + " -p ARP --arp-op Reply --arp-mac-dst " + vm_mac + " -j RETURN") + execute("ebtables -t nat -A " + vmchain_out + " -p ARP -j " + vmchain_out_ips ) if vm_ip: - execute("ebtables -t nat -A " + vmchain_out + " -p ARP -j " + vmchain_out_ips ) execute("ebtables -t nat -I " + vmchain_out_ips + " -p ARP --arp-ip-dst " + vm_ip + " -j RETURN") execute("ebtables -t nat -A " + vmchain_out + " -p ARP --arp-op Request -j ACCEPT") execute("ebtables -t nat -A " + vmchain_out + " -p ARP --arp-op Reply -j ACCEPT") @@ -286,6 +346,28 @@ def default_ebtables_rules(vm_name, vm_ip, vm_mac, vif): logging.debug("Failed to program default ebtables OUT rules") return False +def refactor_ebtable_rules(vm_name): + vmchain_in = vm_name + "-in" + vmchain_in_ips = vm_name + "-in-ips" + vmchain_in_src = vm_name + "-in-src" + + try: + execute("ebtables -t nat -L " + vmchain_in_src) + logging.debug("Chain '" + vmchain_in_src + "' exists, ebtables rules have newer version, skip refactoring") + return True + except: + logging.debug("Chain '" + vmchain_in_src + "' does not exist, ebtables rules have old version, start refactoring") + + vif = execute("ebtables -t nat -L PREROUTING | grep " + vmchain_in + " | awk '{print $2}'").strip() + vm_mac = execute("ebtables -t nat -L " + vmchain_in + " | grep arp-mac-src | awk '{print $5}'").strip() + vm_ips = execute("ebtables -t nat -L " + vmchain_in_ips + " | grep arp-ip-src | awk '{print $4}'").split('\n') + + destroy_ebtables_rules(vm_name, vif) + default_ebtables_rules(vm_name, None, vm_mac, vif, True) + ebtables_rules_vmip(vm_name, vm_mac, vm_ips, "-A") + + logging.debug("Refactoring ebtables rules for vm " + vm_name + " is done") + return True def default_network_rules_systemvm(vm_name, localbrname): bridges = get_bridges(vm_name) @@ -382,8 +464,9 @@ def add_to_ipset(ipsetname, ips, action): return result -def network_rules_vmSecondaryIp(vm_name, ip_secondary, action): +def network_rules_vmSecondaryIp(vm_name, vm_mac, ip_secondary, action): logging.debug("vmName = "+ vm_name) + logging.debug("vmMac = " + vm_mac) logging.debug("action = "+ action) vmchain = vm_name @@ -393,16 +476,16 @@ def network_rules_vmSecondaryIp(vm_name, ip_secondary, action): add_to_ipset(vmchain, ip4s, action) - #add ebtables rules for the secondary ips - ebtables_rules_vmip(vm_name, ip4s, action) - #add ipv6 addresses to ipv6 ipset add_to_ipset(vmchain6, ip6s, action) - return True + #add ebtables rules for the secondary ip + refactor_ebtable_rules(vm_name) + ebtables_rules_vmip(vm_name, vm_mac, [ip_secondary], action) + return True -def ebtables_rules_vmip (vmname, ips, action): +def ebtables_rules_vmip (vmname, vmmac, ips, action): eb_vm_chain=ebtables_chain_name(vmname) vmchain_inips = eb_vm_chain + "-in-ips" vmchain_outips = eb_vm_chain + "-out-ips" @@ -415,46 +498,75 @@ def ebtables_rules_vmip (vmname, ips, action): if ip == 0 or ip == "0": continue try: - execute("ebtables -t nat " + action + " " + vmchain_inips + " -p ARP --arp-ip-src " + ip + " -j RETURN") + execute("ebtables -t nat " + action + " " + vmchain_inips + " -p ARP -s " + vmmac + " --arp-mac-src " + vmmac + " --arp-ip-src " + ip + " -j RETURN") execute("ebtables -t nat " + action + " " + vmchain_outips + " -p ARP --arp-ip-dst " + ip + " -j RETURN") except: logging.debug("Failed to program ebtables rules for secondary ip %s for vm %s with action %s" % (ip, vmname, action)) +def check_default_network_rules(vm_name, vm_id, vm_ip, vm_ip6, vm_mac, vif, brname, sec_ips, is_first_nic=False): + brfw = get_br_fw(brname) + vmchain_default = '-'.join(vm_name.split('-')[:-1]) + "-def" + try: + rules = execute("iptables-save |grep -w %s |grep -w %s |grep -w %s" % (brfw, vif, vmchain_default)) + except: + rules = None + if rules is None or rules is "": + logging.debug("iptables rules do not exist, programming default rules for %s %s" % (vm_name,vif)) + default_network_rules(vm_name, vm_id, vm_ip, vm_ip6, vm_mac, vif, brname, sec_ips, is_first_nic) + else: + vmchain_in = vm_name + "-in" + try: + rules = execute("ebtables -t nat -L PREROUTING | grep %s |grep -w %s" % (vmchain_in, vif)) + except: + rules = None + if rules is None or rules is "": + logging.debug("ebtables rules do not exist, programming default ebtables rules for %s %s" % (vm_name,vif)) + default_ebtables_rules(vm_name, vm_ip, vm_mac, vif, is_first_nic) + ips = sec_ips.split(';') + ips.pop() + ebtables_rules_vmip(vm_name, vm_mac, ips, "-I") + return True -def default_network_rules(vm_name, vm_id, vm_ip, vm_ip6, vm_mac, vif, brname, sec_ips): +def default_network_rules(vm_name, vm_id, vm_ip, vm_ip6, vm_mac, vif, brname, sec_ips, is_first_nic=False): if not add_fw_framework(brname): return False vmName = vm_name brfw = get_br_fw(brname) domID = get_vm_id(vm_name) - delete_rules_for_vm_in_bridge_firewall_chain(vmName) + vmchain = iptables_chain_name(vm_name) vmchain_egress = egress_chain_name(vm_name) vmchain_default = '-'.join(vmchain.split('-')[:-1]) + "-def" ipv6_link_local = ipv6_link_local_addr(vm_mac) - destroy_ebtables_rules(vm_name, vif) - - for chain in [vmchain, vmchain_egress, vmchain_default]: - try: - execute('iptables -N ' + chain) - except: - execute('iptables -F ' + chain) - - try: - execute('ip6tables -N ' + chain) - except: - execute('ip6tables -F ' + chain) - action = "-A" vmipsetName = ipset_chain_name(vm_name) vmipsetName6 = vmipsetName + '-6' - #create ipset and add vm ips to that ip set - if not create_ipset_forvm(vmipsetName): - logging.debug("failed to create ipset for rule %s", vmipsetName) - return False + if is_first_nic: + delete_rules_for_vm_in_bridge_firewall_chain(vmName) + destroy_ebtables_rules(vmName, vif) + + for chain in [vmchain, vmchain_egress, vmchain_default]: + try: + execute('iptables -N ' + chain) + except: + execute('iptables -F ' + chain) + + try: + execute('ip6tables -N ' + chain) + except: + execute('ip6tables -F ' + chain) + + #create ipset and add vm ips to that ip set + if not create_ipset_forvm(vmipsetName): + logging.debug("failed to create ipset for rule %s", vmipsetName) + return False + + if not create_ipset_forvm(vmipsetName6, family='inet6', type='hash:net'): + logging.debug("failed to create ivp6 ipset for rule %s", vmipsetName6) + return False #add primary nic ip to ipset if not add_to_ipset(vmipsetName, [vm_ip], action ): @@ -487,31 +599,30 @@ def default_network_rules(vm_name, vm_id, vm_ip, vm_ip6, vm_mac, vif, brname, se #allow dhcp execute("iptables -A " + vmchain_default + " -m physdev --physdev-is-bridged --physdev-in " + vif + " -p udp --dport 67 --sport 68 -j ACCEPT") execute("iptables -A " + vmchain_default + " -m physdev --physdev-is-bridged --physdev-out " + vif + " -p udp --dport 68 --sport 67 -j ACCEPT") + execute("iptables -A " + vmchain_default + " -m physdev --physdev-is-bridged --physdev-in " + vif + " -p udp --sport 67 -j DROP") #don't let vm spoof its ip address if vm_ip: execute("iptables -A " + vmchain_default + " -m physdev --physdev-is-bridged --physdev-in " + vif + " -m set ! --match-set " + vmipsetName + " src -j DROP") + execute("iptables -A " + vmchain_default + " -m physdev --physdev-is-bridged --physdev-out " + vif + " -m set ! --match-set " + vmipsetName + " dst -j DROP") execute("iptables -A " + vmchain_default + " -m physdev --physdev-is-bridged --physdev-in " + vif + " -m set --match-set " + vmipsetName + " src -p udp --dport 53 -j RETURN ") execute("iptables -A " + vmchain_default + " -m physdev --physdev-is-bridged --physdev-in " + vif + " -m set --match-set " + vmipsetName + " src -p tcp --dport 53 -j RETURN ") execute("iptables -A " + vmchain_default + " -m physdev --physdev-is-bridged --physdev-in " + vif + " -m set --match-set " + vmipsetName + " src -j " + vmchain_egress) + execute("iptables -A " + vmchain_default + " -m physdev --physdev-is-bridged --physdev-out " + vif + " -j " + vmchain) execute("iptables -A " + vmchain + " -j DROP") except: logging.debug("Failed to program default rules for vm " + vm_name) return False - default_ebtables_rules(vm_name, vm_ip, vm_mac, vif) + default_ebtables_rules(vmchain, vm_ip, vm_mac, vif, is_first_nic) #default ebtables rules for vm secondary ips - ebtables_rules_vmip(vm_name, ip4s, "-I") + ebtables_rules_vmip(vm_name, vm_mac, ip4s, "-I") - if vm_ip: + if vm_ip and is_first_nic: if not write_rule_log_for_vm(vmName, vm_id, vm_ip, domID, '_initial_', '-1'): logging.debug("Failed to log default network rules, ignoring") - if not create_ipset_forvm(vmipsetName6, family='inet6', type='hash:net'): - logging.debug(" failed to create ivp6 ipset for rule " + str(tokens)) - return False - vm_ip6_addr = [ipv6_link_local] try: ip6 = ipaddress.ip_address(vm_ip6) @@ -763,7 +874,8 @@ def get_rule_logs_for_vms(): name = name.rstrip() if 1 not in [name.startswith(c) for c in ['r-', 's-', 'v-', 'i-'] ]: continue - network_rules_for_rebooted_vm(name) + # Move actions on rebooted vm to java code + # network_rules_for_rebooted_vm(name) if name.startswith('i-'): log = get_rule_log_for_vm(name) result.append(log) @@ -992,8 +1104,10 @@ def add_network_rules(vm_name, vm_id, vm_ip, vm_ip6, signature, seqno, vmMac, ru logging.debug("Rules already programmed for vm " + vm_name) return True - if changes[0] or changes[1] or changes[2] or changes[3]: - default_network_rules(vmName, vm_id, vm_ip, vm_ip6, vmMac, vif, brname, sec_ips) + if rules == "" or rules == None: + lines = [] + else: + lines = rules.split(';')[:-1] logging.debug("programming network rules for IP: " + vm_ip + " vmname=%s", vm_name) @@ -1007,7 +1121,7 @@ def add_network_rules(vm_name, vm_id, vm_ip, vm_ip6, signature, seqno, vmMac, ru execute('ip6tables -F ' + chain) except: logging.debug("Error flushing iptables rules for " + vm_name + ". Presuming firewall rules deleted, re-initializing." ) - default_network_rules(vm_name, vm_id, vm_ip, vm_ip6, vmMac, vif, brname, sec_ips) + default_network_rules(vm_name, vm_id, vm_ip, vm_ip6, vmMac, vif, brname, sec_ips, True) egressrule_v4 = 0 egressrule_v6 = 0 @@ -1162,6 +1276,11 @@ def get_br_fw(brname): def add_fw_framework(brname): + try: + execute("modprobe br_netfilter") + except: + logging.debug("failed to load kernel module br_netfilter") + try: execute("sysctl -w net.bridge.bridge-nf-call-arptables=1") execute("sysctl -w net.bridge.bridge-nf-call-iptables=1") @@ -1239,6 +1358,236 @@ def add_fw_framework(brname): return False return False +def verify_network_rules(vm_name, vm_id, vm_ip, vm_ip6, vm_mac, vif, brname, sec_ips): + if vm_name is None or vm_ip is None or vm_mac is None: + print("vm_name, vm_ip and vm_mac must be specifed") + sys.exit(1) + + if vm_id is None: + vm_id = vm_name.split("-")[-2] + + if brname is None: + brname = execute("virsh domiflist %s |grep -w '%s' |tr -s ' '|cut -d ' ' -f3" % (vm_name, vm_mac)).strip() + if brname is None or brname == "": + print("Cannot find bridge") + sys.exit(1) + + if vif is None: + vif = execute("virsh domiflist %s |grep -w '%s' |tr -s ' '|cut -d ' ' -f1" % (vm_name, vm_mac)).strip() + if vif is None or vif == "": + print("Cannot find vif") + sys.exit(1) + + #vm_name = "i-2-55-VM" + #vm_id = 55 + #vm_ip = "10.11.118.128" + #vm_ip6 = "fe80::1c00:b4ff:fe00:5" + #vm_mac = "1e:00:b4:00:00:05" + #vif = "vnet11" + #brname = "cloudbr0" + #sec_ips = "10.11.118.133;10.11.118.135;10.11.118.138;" # end with ";" and seperated by ";" + + vm_ips = [] + if sec_ips is not None: + vm_ips = sec_ips.split(';') + vm_ips.pop() + vm_ips.reverse() + vm_ips.append(vm_ip) + + if not verify_ipset_for_vm(vm_name, vm_id, vm_ips, vm_ip6): + sys.exit(2) + if not verify_iptables_rules_for_bridge(brname): + sys.exit(3) + if not verify_default_iptables_rules_for_vm(vm_name, vm_id, vm_ips, vm_ip6, vm_mac, vif, brname): + sys.exit(4) + if not verify_ebtables_rules_for_vm(vm_name, vm_id, vm_ips, vm_ip6, vm_mac, vif, brname): + sys.exit(5) + + sys.exit(0) + +def verify_ipset_for_vm(vm_name, vm_id, vm_ips, vm_ip6): + vmipsetName = ipset_chain_name(vm_name) + vmipsetName6 = vmipsetName + '-6' + + rules = [] + for rule in execute("ipset list %s" % vmipsetName).split('\n'): + rules.append(rule) + + # Check if all vm ips and ip6 exist + for vm_ip in vm_ips: + found = False + for rule in rules: + if rule == vm_ip: + found = True + break + if not found: + print("vm ip %s is not found" % vm_ip) + return False + + rules = [] + for rule in execute("ipset list %s" % vmipsetName6).split('\n'): + rules.append(rule) + + if vm_ip6 is not None: + found = False + for rule in rules: + if rule == vm_ip6: + found = True + break + if not found: + print("vm ipv6 %s is not found" % vm_ip6) + return False + + return True + +def verify_iptables_rules_for_bridge(brname): + brfw = get_br_fw(brname) + brfwin = brfw + "-IN" + brfwout = brfw + "-OUT" + + expected_rules = [] + expected_rules.append("-A FORWARD -o %s -m physdev --physdev-is-bridged -j %s" % (brname, brfw)) + expected_rules.append("-A FORWARD -i %s -m physdev --physdev-is-bridged -j %s" % (brname, brfw)) + expected_rules.append("-A %s -m state --state RELATED,ESTABLISHED -j ACCEPT" % (brfw)) + expected_rules.append("-A %s -m physdev --physdev-is-in --physdev-is-bridged -j %s" % (brfw, brfwin)) + expected_rules.append("-A %s -m physdev --physdev-is-out --physdev-is-bridged -j %s" % (brfw, brfwout)) + phydev = execute("brctl show | awk '/^%s[ \t]/ {print $4}'" % brname ).strip() + expected_rules.append("-A %s -m physdev --physdev-out %s --physdev-is-bridged -j ACCEPT" % (brfw, phydev)) + + rules = execute("iptables-save |grep -w %s |grep -v \"^:\"" % brfw).split('\n') + + return verify_expected_rules_exist(expected_rules, rules) + +def verify_default_iptables_rules_for_vm(vm_name, vm_id, vm_ips, vm_ip6, vm_mac, vif, brname): + brfw = get_br_fw(brname) + brfwin = brfw + "-IN" + brfwout = brfw + "-OUT" + vmchain = iptables_chain_name(vm_name) + vmchain_egress = egress_chain_name(vm_name) + vm_def = '-'.join(vm_name.split('-')[:-1]) + "-def" + + expected_rules = [] + expected_rules.append("-A %s -m physdev --physdev-in %s --physdev-is-bridged -j %s" % (brfwin, vif, vm_def)) + expected_rules.append("-A %s -m physdev --physdev-out %s --physdev-is-bridged -j %s" % (brfwout, vif, vm_def)) + expected_rules.append("-A %s -m state --state RELATED,ESTABLISHED -j ACCEPT" % (vm_def)) + expected_rules.append("-A %s -p udp -m physdev --physdev-in %s --physdev-is-bridged -m udp --sport 68 --dport 67 -j ACCEPT" % (vm_def, vif)) + expected_rules.append("-A %s -p udp -m physdev --physdev-out %s --physdev-is-bridged -m udp --sport 67 --dport 68 -j ACCEPT" % (vm_def, vif)) + expected_rules.append("-A %s -p udp -m physdev --physdev-in %s --physdev-is-bridged -m udp --sport 67 -j DROP" % (vm_def, vif)) + expected_rules.append("-A %s -m physdev --physdev-in %s --physdev-is-bridged -m set ! --match-set %s src -j DROP" % (vm_def, vif, vm_name)) + expected_rules.append("-A %s -m physdev --physdev-out %s --physdev-is-bridged -m set ! --match-set %s dst -j DROP" % (vm_def, vif, vm_name)) + expected_rules.append("-A %s -p udp -m physdev --physdev-in %s --physdev-is-bridged -m set --match-set %s src -m udp --dport 53 -j RETURN" % (vm_def, vif, vm_name)) + expected_rules.append("-A %s -p tcp -m physdev --physdev-in %s --physdev-is-bridged -m set --match-set %s src -m tcp --dport 53 -j RETURN" % (vm_def, vif, vm_name)) + expected_rules.append("-A %s -m physdev --physdev-in %s --physdev-is-bridged -m set --match-set %s src -j %s" % (vm_def, vif, vm_name, vmchain_egress)) + expected_rules.append("-A %s -m physdev --physdev-out %s --physdev-is-bridged -j %s" % (vm_def, vif, vmchain)) + + rules = execute("iptables-save |grep -E \"%s|%s\" |grep -v \"^:\"" % (vm_name, vm_def)).split('\n') + + return verify_expected_rules_in_order(expected_rules, rules) + +def verify_ebtables_rules_for_vm(vm_name, vm_id, vm_ips, vm_ip6, vm_mac, vif, brname): + vmchain_in = vm_name + "-in" + vmchain_out = vm_name + "-out" + vmchain_in_ips = vm_name + "-in-ips" + vmchain_out_ips = vm_name + "-out-ips" + vmchain_in_src = vm_name + "-in-src" + vmchain_out_dst = vm_name + "-out-dst" + + new_mac = trim_mac_address(vm_mac) + + # PREROUTING/POSTROUTING + expected_rules = [] + expected_rules.append("-A PREROUTING -i %s -j %s" % (vif, vmchain_in)) + expected_rules.append("-A POSTROUTING -o %s -j %s" % (vif, vmchain_out)) + rules = execute("ebtables-save |grep -E \"PREROUTING|POSTROUTING\" | grep %s" % vm_name).split('\n') + if not verify_expected_rules_exist(expected_rules, rules): + return False + + rules = execute("ebtables-save | grep %s" % vm_name).split('\n') + + # vmchain_in + expected_rules = [] + expected_rules.append("-A %s -j %s" % (vmchain_in, vmchain_in_src)) + expected_rules.append("-A %s -p ARP -j %s" % (vmchain_in, vmchain_in_ips)) + expected_rules.append("-A %s -p ARP --arp-op Request -j ACCEPT" % (vmchain_in)) + expected_rules.append("-A %s -p ARP --arp-op Reply -j ACCEPT" % (vmchain_in)) + expected_rules.append("-A %s -p ARP -j DROP" % (vmchain_in)) + if not verify_expected_rules_in_order(expected_rules, rules): + return False + + # vmchain_in_src + expected_rules = [] + expected_rules.append("-A %s -s %s -j RETURN" % (vmchain_in_src, new_mac)) + expected_rules.append("-A %s -j DROP" % (vmchain_in_src)) + if not verify_expected_rules_in_order(expected_rules, rules): + return False + + # vmchain_in_ips + expected_rules = [] + for vm_ip in vm_ips: + expected_rules.append("-A %s -p ARP -s %s --arp-ip-src %s --arp-mac-src %s -j RETURN" % (vmchain_in_ips, new_mac, vm_ip, new_mac)) + expected_rules.append("-A %s -j DROP" % (vmchain_in_ips)) + if not verify_expected_rules_in_order(expected_rules, rules): + return False + + # vmchain_out + expected_rules = [] + expected_rules.append("-A %s -p ARP --arp-op Reply -j %s" % (vmchain_out, vmchain_out_dst)) + expected_rules.append("-A %s -p ARP -j %s" % (vmchain_out, vmchain_out_ips)) + expected_rules.append("-A %s -p ARP --arp-op Request -j ACCEPT" % (vmchain_out)) + expected_rules.append("-A %s -p ARP --arp-op Reply -j ACCEPT" % (vmchain_out)) + expected_rules.append("-A %s -p ARP -j DROP" % (vmchain_out)) + if not verify_expected_rules_in_order(expected_rules, rules): + return False + + # vmchain_out_dst + expected_rules = [] + expected_rules.append("-A %s -p ARP --arp-op Reply --arp-mac-dst %s -j RETURN" % (vmchain_out_dst, new_mac)) + expected_rules.append("-A %s -p ARP --arp-op Reply -j DROP" % (vmchain_out_dst)) + if not verify_expected_rules_in_order(expected_rules, rules): + return False + + # vmchain_out_ips + expected_rules = [] + for vm_ip in vm_ips: + expected_rules.append("-A %s -p ARP --arp-ip-dst %s -j RETURN" % (vmchain_out_ips, vm_ip)) + expected_rules.append("-A %s -j DROP" % (vmchain_out_ips)) + if not verify_expected_rules_in_order(expected_rules, rules): + return False + + return True + +def trim_mac_address(vm_mac): + new_mac = "" + for mac in vm_mac.split(":"): + if mac.startswith("0"): + new_mac += ":" + mac[1:] + else: + new_mac += ":" + mac + return new_mac[1:] + +def verify_expected_rules_exist(expected_rules, rules): + # Check if expected rules exist + for expected_rule in expected_rules: + found = False + for rule in rules: + if rule == expected_rule: + found = True + break + if not found: + print("Rule '%s' is not found" % expected_rule) + return False + return True + +def verify_expected_rules_in_order(expected_rules, rules): + # Check if expected rules exist in order (!!!) + i = 0 + for rule in rules: + if i < len(expected_rules) and rule == expected_rules[i]: + i += 1 + if i != len(expected_rules): + print("Cannot find rule '%s'" % expected_rules[i]) + return False + return True if __name__ == '__main__': logging.basicConfig(filename="/var/log/cloudstack/agent/security_group.log", format="%(asctime)s - %(message)s", level=logging.DEBUG) @@ -1261,6 +1610,8 @@ def add_fw_framework(brname): parser.add_argument("--nicsecips", dest="nicSecIps") parser.add_argument("--action", dest="action") parser.add_argument("--privnic", dest="privnic") + parser.add_argument("--isFirstNic", action="store_true", dest="isFirstNic") + parser.add_argument("--check", action="store_true", dest="check") args = parser.parse_args() cmd = args.command logging.debug("Executing command: %s", cmd) @@ -1274,10 +1625,15 @@ def add_fw_framework(brname): if cmd == "can_bridge_firewall": can_bridge_firewall(args.privnic) - elif cmd == "default_network_rules": - default_network_rules(args.vmName, args.vmID, args.vmIP, args.vmIP6, args.vmMAC, args.vif, args.brname, args.nicSecIps) + elif cmd == "default_network_rules" and args.check: + check_default_network_rules(args.vmName, args.vmID, args.vmIP, args.vmIP6, args.vmMAC, args.vif, args.brname, args.nicSecIps, args.isFirstNic) + elif cmd == "default_network_rules" and not args.check: + default_network_rules(args.vmName, args.vmID, args.vmIP, args.vmIP6, args.vmMAC, args.vif, args.brname, args.nicSecIps, args.isFirstNic) elif cmd == "destroy_network_rules_for_vm": - destroy_network_rules_for_vm(args.vmName, args.vif) + if args.vmIP is None: + destroy_network_rules_for_vm(args.vmName, args.vif) + else: + destroy_network_rules_for_nic(args.vmName, args.vmIP, args.vmMAC, args.vif, args.nicSecIps) elif cmd == "default_network_rules_systemvm": default_network_rules_systemvm(args.vmName, args.localbrname) elif cmd == "get_rule_logs_for_vms": @@ -1285,11 +1641,13 @@ def add_fw_framework(brname): elif cmd == "add_network_rules": add_network_rules(args.vmName, args.vmID, args.vmIP, args.vmIP6, args.sig, args.seq, args.vmMAC, args.rules, args.vif, args.brname, args.nicSecIps) elif cmd == "network_rules_vmSecondaryIp": - network_rules_vmSecondaryIp(args.vmName, args.nicSecIps, args.action) + network_rules_vmSecondaryIp(args.vmName, args.vmMAC, args.nicSecIps, args.action) elif cmd == "cleanup_rules": cleanup_rules() elif cmd == "post_default_network_rules": post_default_network_rules(args.vmName, args.vmID, args.vmIP, args.vmMAC, args.vif, args.brname, args.dhcpSvr, args.hostIp, args.hostMacAddr) + elif cmd == "verify_network_rules": + verify_network_rules(args.vmName, args.vmID, args.vmIP, args.vmIP6, args.vmMAC, args.vif, args.brname, args.nicSecIps) else: logging.debug("Unknown command: " + cmd) sys.exit(1) diff --git a/server/pom.xml b/server/pom.xml index 1320ed35d740..deadd28a1dc3 100644 --- a/server/pom.xml +++ b/server/pom.xml @@ -27,6 +27,10 @@ 4.14.0.0-SNAPSHOT + + mysql + mysql-connector-java + commons-io commons-io diff --git a/server/src/main/java/com/cloud/api/ApiDBUtils.java b/server/src/main/java/com/cloud/api/ApiDBUtils.java index acd73622642b..74579813c3d3 100644 --- a/server/src/main/java/com/cloud/api/ApiDBUtils.java +++ b/server/src/main/java/com/cloud/api/ApiDBUtils.java @@ -1039,6 +1039,10 @@ public static HostVO findHostById(Long hostId) { return s_hostDao.findByIdIncludingRemoved(hostId); } + public static HostVO findHostByTypeNameAndZoneId(Long zoneId, String name, Host.Type type) { + return s_hostDao.findByTypeNameAndZoneId(zoneId, name, type); + } + public static IPAddressVO findIpAddressById(long addressId) { return s_ipAddressDao.findById(addressId); } diff --git a/server/src/main/java/com/cloud/api/ApiResponseHelper.java b/server/src/main/java/com/cloud/api/ApiResponseHelper.java index b8e60325ea22..c6744074ae30 100644 --- a/server/src/main/java/com/cloud/api/ApiResponseHelper.java +++ b/server/src/main/java/com/cloud/api/ApiResponseHelper.java @@ -31,8 +31,6 @@ import javax.inject.Inject; -import com.cloud.vm.snapshot.VMSnapshotVO; -import com.cloud.vm.snapshot.dao.VMSnapshotDao; import org.apache.cloudstack.acl.ControlledEntity; import org.apache.cloudstack.acl.ControlledEntity.ACLType; import org.apache.cloudstack.affinity.AffinityGroup; @@ -63,6 +61,7 @@ import org.apache.cloudstack.api.response.CreateSSHKeyPairResponse; import org.apache.cloudstack.api.response.DiskOfferingResponse; import org.apache.cloudstack.api.response.DomainResponse; +import org.apache.cloudstack.api.response.RouterHealthCheckResultResponse; import org.apache.cloudstack.api.response.DomainRouterResponse; import org.apache.cloudstack.api.response.EventResponse; import org.apache.cloudstack.api.response.ExtractResponse; @@ -235,6 +234,7 @@ import com.cloud.network.PhysicalNetworkServiceProvider; import com.cloud.network.PhysicalNetworkTrafficType; import com.cloud.network.RemoteAccessVpn; +import com.cloud.network.RouterHealthCheckResult; import com.cloud.network.Site2SiteCustomerGateway; import com.cloud.network.Site2SiteVpnConnection; import com.cloud.network.Site2SiteVpnGateway; @@ -336,6 +336,8 @@ import com.cloud.vm.dao.NicExtraDhcpOptionDao; import com.cloud.vm.dao.NicSecondaryIpVO; import com.cloud.vm.snapshot.VMSnapshot; +import com.cloud.vm.snapshot.VMSnapshotVO; +import com.cloud.vm.snapshot.dao.VMSnapshotDao; public class ApiResponseHelper implements ResponseGenerator { @@ -1349,6 +1351,7 @@ public DomainRouterResponse createDomainRouterResponse(VirtualRouter router) { return listVrs.get(0); } + @Override public SystemVmResponse createSystemVmResponse(VirtualMachine vm) { SystemVmResponse vmResponse = new SystemVmResponse(); @@ -1378,6 +1381,16 @@ public SystemVmResponse createSystemVmResponse(VirtualMachine vm) { } } + if (vm.getType() == Type.SecondaryStorageVm || vm.getType() == Type.ConsoleProxy) { + Host systemVmHost = ApiDBUtils.findHostByTypeNameAndZoneId(vm.getDataCenterId(), vm.getHostName(), + Type.SecondaryStorageVm.equals(vm.getType()) ? Host.Type.SecondaryStorageVM : Host.Type.ConsoleProxy); + if (systemVmHost != null) { + vmResponse.setAgentState(systemVmHost.getStatus()); + vmResponse.setDisconnectedOn(systemVmHost.getDisconnectedOn()); + vmResponse.setVersion(systemVmHost.getVersion()); + } + } + if (vm.getState() != null) { vmResponse.setState(vm.getState().toString()); } @@ -4205,4 +4218,20 @@ public ManagementServerResponse createManagementResponse(ManagementServerHost mg response.setState(mgmt.getState()); return response; } + + @Override + public List createHealthCheckResponse(VirtualMachine router, List healthCheckResults) { + List responses = new ArrayList<>(healthCheckResults.size()); + for (RouterHealthCheckResult hcResult : healthCheckResults) { + RouterHealthCheckResultResponse healthCheckResponse = new RouterHealthCheckResultResponse(); + healthCheckResponse.setObjectName("routerhealthchecks"); + healthCheckResponse.setCheckName(hcResult.getCheckName()); + healthCheckResponse.setCheckType(hcResult.getCheckType()); + healthCheckResponse.setResult(hcResult.getCheckResult()); + healthCheckResponse.setLastUpdated(hcResult.getLastUpdateTime()); + healthCheckResponse.setDetails(hcResult.getParsedCheckDetails()); + responses.add(healthCheckResponse); + } + return responses; + } } diff --git a/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java b/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java index 81a0ba669413..fcd50e56bbc2 100644 --- a/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java +++ b/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java @@ -31,9 +31,6 @@ import javax.inject.Inject; -import com.cloud.agent.api.storage.OVFProperty; -import com.cloud.storage.TemplateOVFPropertyVO; -import com.cloud.storage.dao.TemplateOVFPropertiesDao; import org.apache.cloudstack.acl.ControlledEntity.ACLType; import org.apache.cloudstack.affinity.AffinityGroupDomainMapVO; import org.apache.cloudstack.affinity.AffinityGroupResponse; @@ -42,6 +39,7 @@ import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao; import org.apache.cloudstack.api.BaseListProjectAndAccountResourcesCmd; import org.apache.cloudstack.api.ResourceDetail; +import org.apache.cloudstack.api.ResponseGenerator; import org.apache.cloudstack.api.ResponseObject.ResponseView; import org.apache.cloudstack.api.command.admin.account.ListAccountsCmdByAdmin; import org.apache.cloudstack.api.command.admin.domain.ListDomainsCmd; @@ -51,6 +49,7 @@ import org.apache.cloudstack.api.command.admin.internallb.ListInternalLBVMsCmd; import org.apache.cloudstack.api.command.admin.iso.ListIsosCmdByAdmin; import org.apache.cloudstack.api.command.admin.management.ListMgmtsCmd; +import org.apache.cloudstack.api.command.admin.router.GetRouterHealthCheckResultsCmd; import org.apache.cloudstack.api.command.admin.router.ListRoutersCmd; import org.apache.cloudstack.api.command.admin.storage.ListImageStoresCmd; import org.apache.cloudstack.api.command.admin.storage.ListSecondaryStagingStoresCmd; @@ -98,6 +97,7 @@ import org.apache.cloudstack.api.response.ProjectResponse; import org.apache.cloudstack.api.response.ResourceDetailResponse; import org.apache.cloudstack.api.response.ResourceTagResponse; +import org.apache.cloudstack.api.response.RouterHealthCheckResultResponse; import org.apache.cloudstack.api.response.SecurityGroupResponse; import org.apache.cloudstack.api.response.ServiceOfferingResponse; import org.apache.cloudstack.api.response.StoragePoolResponse; @@ -123,6 +123,7 @@ import org.apache.log4j.Logger; import org.springframework.stereotype.Component; +import com.cloud.agent.api.storage.OVFProperty; import com.cloud.api.query.dao.AccountJoinDao; import com.cloud.api.query.dao.AffinityGroupJoinDao; import com.cloud.api.query.dao.AsyncJobJoinDao; @@ -182,6 +183,10 @@ import com.cloud.ha.HighAvailabilityManager; import com.cloud.hypervisor.Hypervisor; import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.network.RouterHealthCheckResult; +import com.cloud.network.VpcVirtualNetworkApplianceService; +import com.cloud.network.dao.RouterHealthCheckResultDao; +import com.cloud.network.router.VirtualNetworkApplianceManager; import com.cloud.network.security.SecurityGroupVMMapVO; import com.cloud.network.security.dao.SecurityGroupVMMapDao; import com.cloud.org.Grouping; @@ -206,9 +211,11 @@ import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.Storage.TemplateType; import com.cloud.storage.StoragePoolTagVO; +import com.cloud.storage.TemplateOVFPropertyVO; import com.cloud.storage.VMTemplateVO; import com.cloud.storage.Volume; import com.cloud.storage.dao.StoragePoolTagsDao; +import com.cloud.storage.dao.TemplateOVFPropertiesDao; import com.cloud.storage.dao.VMTemplateDao; import com.cloud.tags.ResourceTagVO; import com.cloud.tags.dao.ResourceTagDao; @@ -395,6 +402,15 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q @Inject TemplateOVFPropertiesDao templateOVFPropertiesDao; + @Inject + public VpcVirtualNetworkApplianceService routerService; + + @Inject + private ResponseGenerator responseGenerator; + + @Inject + private RouterHealthCheckResultDao routerHealthCheckResultDao; + /* * (non-Javadoc) * @@ -1198,8 +1214,17 @@ public ListResponse searchForRouters(ListRoutersCmd cmd) { Pair, Integer> result = searchForRoutersInternal(cmd, cmd.getId(), cmd.getRouterName(), cmd.getState(), cmd.getZoneId(), cmd.getPodId(), cmd.getClusterId(), cmd.getHostId(), cmd.getKeyword(), cmd.getNetworkId(), cmd.getVpcId(), cmd.getForVpc(), cmd.getRole(), cmd.getVersion()); ListResponse response = new ListResponse(); - List routerResponses = ViewResponseHelper.createDomainRouterResponse(result.first().toArray(new DomainRouterJoinVO[result.first().size()])); + if (VirtualNetworkApplianceManager.RouterHealthChecksEnabled.value()) { + for (DomainRouterResponse res : routerResponses) { + DomainRouterVO resRouter = _routerDao.findByUuid(res.getId()); + res.setHealthChecksFailed(routerHealthCheckResultDao.hasFailingChecks(resRouter.getId())); + if (cmd.shouldFetchHealthCheckResults()) { + res.setHealthCheckResults(responseGenerator.createHealthCheckResponse(resRouter, + new ArrayList<>(routerHealthCheckResultDao.getHealthCheckResults(resRouter.getId())))); + } + } + } response.setResponses(routerResponses, result.second()); return response; } @@ -1209,8 +1234,18 @@ public ListResponse searchForInternalLbVms(ListInternalLBV Pair, Integer> result = searchForRoutersInternal(cmd, cmd.getId(), cmd.getRouterName(), cmd.getState(), cmd.getZoneId(), cmd.getPodId(), null, cmd.getHostId(), cmd.getKeyword(), cmd.getNetworkId(), cmd.getVpcId(), cmd.getForVpc(), cmd.getRole(), null); ListResponse response = new ListResponse(); - List routerResponses = ViewResponseHelper.createDomainRouterResponse(result.first().toArray(new DomainRouterJoinVO[result.first().size()])); + if (VirtualNetworkApplianceManager.RouterHealthChecksEnabled.value()) { + for (DomainRouterResponse res : routerResponses) { + DomainRouterVO resRouter = _routerDao.findByUuid(res.getId()); + res.setHealthChecksFailed(routerHealthCheckResultDao.hasFailingChecks(resRouter.getId())); + if (cmd.shouldFetchHealthCheckResults()) { + res.setHealthCheckResults(responseGenerator.createHealthCheckResponse(resRouter, + new ArrayList<>(routerHealthCheckResultDao.getHealthCheckResults(resRouter.getId())))); + } + } + } + response.setResponses(routerResponses, result.second()); return response; } @@ -1774,6 +1809,7 @@ private Pair, Integer> searchForVolumesInternal(ListVolumesCm Long clusterId = cmd.getClusterId(); Long diskOffId = cmd.getDiskOfferingId(); Boolean display = cmd.getDisplay(); + String state = cmd.getState(); Long zoneId = cmd.getZoneId(); Long podId = cmd.getPodId(); @@ -1809,8 +1845,8 @@ private Pair, Integer> searchForVolumesInternal(ListVolumesCm sb.and("storageId", sb.entity().getPoolUuid(), SearchCriteria.Op.EQ); sb.and("diskOfferingId", sb.entity().getDiskOfferingId(), SearchCriteria.Op.EQ); sb.and("display", sb.entity().isDisplayVolume(), SearchCriteria.Op.EQ); - // Only return volumes that are not destroyed - sb.and("state", sb.entity().getState(), SearchCriteria.Op.NEQ); + sb.and("state", sb.entity().getState(), SearchCriteria.Op.EQ); + sb.and("stateNEQ", sb.entity().getState(), SearchCriteria.Op.NEQ); sb.and("systemUse", sb.entity().isSystemUse(), SearchCriteria.Op.NEQ); // display UserVM volumes only sb.and().op("type", sb.entity().getVmType(), SearchCriteria.Op.NIN); @@ -1825,6 +1861,7 @@ private Pair, Integer> searchForVolumesInternal(ListVolumesCm SearchCriteria ssc = _volumeJoinDao.createSearchCriteria(); ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%"); ssc.addOr("volumeType", SearchCriteria.Op.LIKE, "%" + keyword + "%"); + ssc.addOr("state", SearchCriteria.Op.LIKE, "%" + keyword + "%"); sc.addAnd("name", SearchCriteria.Op.SC, ssc); } @@ -1883,8 +1920,11 @@ private Pair, Integer> searchForVolumesInternal(ListVolumesCm // Don't return DomR and ConsoleProxy volumes sc.setParameters("type", VirtualMachine.Type.ConsoleProxy, VirtualMachine.Type.SecondaryStorageVm, VirtualMachine.Type.DomainRouter); - // Only return volumes that are not destroyed - sc.setParameters("state", Volume.State.Destroy); + if (state != null) { + sc.setParameters("state", state); + } else if (!_accountMgr.isAdmin(caller.getId())) { + sc.setParameters("stateNEQ", Volume.State.Expunged); + } // search Volume details by ids Pair, Integer> uniqueVolPair = _volumeJoinDao.searchAndCount(sc, searchFilter); @@ -3868,20 +3908,43 @@ protected ResourceDetailResponse createResourceDetailsResponse(ResourceDetail re @Override public ListResponse listManagementServers(ListMgmtsCmd cmd) { ListResponse response = new ListResponse<>(); - List result = new ArrayList<>(); - for (ManagementServerHostVO mgmt : managementServerHostDao.listAll()) { - ManagementServerResponse mgmtResponse = new ManagementServerResponse(); - mgmtResponse.setId(mgmt.getUuid()); - mgmtResponse.setName(mgmt.getName()); - mgmtResponse.setState(mgmt.getState()); - mgmtResponse.setVersion(mgmt.getVersion()); - mgmtResponse.setObjectName("managementserver"); - result.add(mgmtResponse); + Pair, Integer> result = listManagementServersInternal(cmd); + List hostResponses = new ArrayList<>(); + + for (ManagementServerHostVO host : result.first()) { + ManagementServerResponse hostResponse = createManagementServerResponse(host); + hostResponses.add(hostResponse); } - response.setResponses(result); + + response.setResponses(hostResponses); return response; } + protected Pair, Integer> listManagementServersInternal(ListMgmtsCmd cmd) { + Long id = cmd.getId(); + String name = cmd.getHostName(); + + SearchBuilder sb = managementServerHostDao.createSearchBuilder(); + SearchCriteria sc = sb.create(); + if (id != null) { + sc.addAnd("id", SearchCriteria.Op.EQ, id); + } + if (name != null) { + sc.addAnd("name", SearchCriteria.Op.EQ, name); + } + return managementServerHostDao.searchAndCount(sc, null); + } + + protected ManagementServerResponse createManagementServerResponse(ManagementServerHostVO mgmt) { + ManagementServerResponse mgmtResponse = new ManagementServerResponse(); + mgmtResponse.setId(mgmt.getUuid()); + mgmtResponse.setName(mgmt.getName()); + mgmtResponse.setState(mgmt.getState()); + mgmtResponse.setVersion(mgmt.getVersion()); + mgmtResponse.setObjectName("managementserver"); + return mgmtResponse; + } + @Override public ListResponse listTemplateOVFProperties(ListTemplateOVFProperties cmd) { ListResponse response = new ListResponse<>(); @@ -3905,6 +3968,27 @@ public ListResponse listTemplateOVFProperties(ListT return response; } + @Override + public List listRouterHealthChecks(GetRouterHealthCheckResultsCmd cmd) { + s_logger.info("Executing health check command " + cmd); + long routerId = cmd.getRouterId(); + if (!VirtualNetworkApplianceManager.RouterHealthChecksEnabled.value()) { + throw new CloudRuntimeException("Router health checks are not enabled for router " + routerId); + } + + if (cmd.shouldPerformFreshChecks() && !routerService.performRouterHealthChecks(routerId)) { + throw new CloudRuntimeException("Unable to perform fresh checks on router."); + } + + List result = new ArrayList<>(routerHealthCheckResultDao.getHealthCheckResults(routerId)); + if (result == null || result.size() == 0) { + throw new CloudRuntimeException("Database had no entries for health checks for router. This could happen for " + + "a newly created router. Please wait for periodic results to populate or manually call for checks to execute."); + } + + return responseGenerator.createHealthCheckResponse(_routerDao.findById(routerId), result); + } + @Override public String getConfigComponentName() { return QueryService.class.getSimpleName(); diff --git a/server/src/main/java/com/cloud/api/query/dao/DataCenterJoinDaoImpl.java b/server/src/main/java/com/cloud/api/query/dao/DataCenterJoinDaoImpl.java index ffc75307182d..cfe2e31a371f 100644 --- a/server/src/main/java/com/cloud/api/query/dao/DataCenterJoinDaoImpl.java +++ b/server/src/main/java/com/cloud/api/query/dao/DataCenterJoinDaoImpl.java @@ -90,7 +90,7 @@ public ZoneResponse newDataCenterResponse(ResponseView view, DataCenterJoinVO da zoneResponse.setDomainId(dataCenter.getDomainUuid()); zoneResponse.setDomainName(dataCenter.getDomainName()); - zoneResponse.setType(dataCenter.getNetworkType().toString()); + zoneResponse.setNetworkType(dataCenter.getNetworkType().toString()); zoneResponse.setAllocationState(dataCenter.getAllocationState().toString()); zoneResponse.setZoneToken(dataCenter.getZoneToken()); zoneResponse.setDhcpProvider(dataCenter.getDhcpProvider()); diff --git a/server/src/main/java/com/cloud/api/query/dao/HostJoinDaoImpl.java b/server/src/main/java/com/cloud/api/query/dao/HostJoinDaoImpl.java index 35dc89887d96..ff5d254e9b73 100644 --- a/server/src/main/java/com/cloud/api/query/dao/HostJoinDaoImpl.java +++ b/server/src/main/java/com/cloud/api/query/dao/HostJoinDaoImpl.java @@ -138,7 +138,7 @@ public HostResponse newHostResponse(HostJoinVO host, EnumSet detail } gpus.add(gpuResponse); } - hostResponse.setGpuGroups(gpus); + hostResponse.setGpuGroup(gpus); } if (details.contains(HostDetails.all) || details.contains(HostDetails.capacity) || details.contains(HostDetails.stats) || details.contains(HostDetails.events)) { diff --git a/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java b/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java index 1f8655d40c93..be01b9f83259 100755 --- a/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java +++ b/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java @@ -16,6 +16,7 @@ // under the License. package com.cloud.configuration; +import com.cloud.agent.AgentManager; import com.cloud.alert.AlertManager; import com.cloud.api.ApiDBUtils; import com.cloud.api.query.dao.NetworkOfferingJoinDao; @@ -161,6 +162,8 @@ import org.apache.cloudstack.affinity.AffinityGroup; import org.apache.cloudstack.affinity.AffinityGroupService; import org.apache.cloudstack.affinity.dao.AffinityGroupDao; +import org.apache.cloudstack.agent.lb.IndirectAgentLB; +import org.apache.cloudstack.agent.lb.IndirectAgentLBServiceImpl; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.command.admin.config.UpdateCfgCmd; import org.apache.cloudstack.api.command.admin.network.CreateManagementNetworkIpRangeCmd; @@ -187,6 +190,7 @@ import org.apache.cloudstack.api.command.admin.zone.DeleteZoneCmd; import org.apache.cloudstack.api.command.admin.zone.UpdateZoneCmd; import org.apache.cloudstack.api.command.user.network.ListNetworkOfferingsCmd; +import org.apache.cloudstack.config.ApiServiceConfiguration; import org.apache.cloudstack.config.Configuration; import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService; @@ -198,6 +202,7 @@ import org.apache.cloudstack.framework.config.dao.ConfigurationDao; import org.apache.cloudstack.framework.config.impl.ConfigurationVO; import org.apache.cloudstack.framework.messagebus.MessageBus; +import org.apache.cloudstack.framework.messagebus.MessageSubscriber; import org.apache.cloudstack.framework.messagebus.PublishScope; import org.apache.cloudstack.region.PortableIp; import org.apache.cloudstack.region.PortableIpDao; @@ -372,6 +377,10 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati ImageStoreDetailsDao _imageStoreDetailsDao; @Inject MessageBus messageBus; + @Inject + AgentManager _agentManager; + @Inject + IndirectAgentLB _indirectAgentLB; // FIXME - why don't we have interface for DataCenterLinkLocalIpAddressDao? @@ -404,6 +413,7 @@ public boolean configure(final String name, final Map params) th populateConfigValuesForValidationSet(); weightBasedParametersForValidation(); overProvisioningFactorsForValidation(); + initMessageBusListener(); return true; } @@ -461,6 +471,24 @@ private void overProvisioningFactorsForValidation() { overprovisioningFactorsForValidation.add(CapacityManager.StorageOverprovisioningFactor.key()); } + private void initMessageBusListener() { + messageBus.subscribe(EventTypes.EVENT_CONFIGURATION_VALUE_EDIT, new MessageSubscriber() { + @Override + public void onPublishMessage(String serderAddress, String subject, Object args) { + String globalSettingUpdated = (String) args; + if (Strings.isNullOrEmpty(globalSettingUpdated)) { + return; + } + if (globalSettingUpdated.equals(ApiServiceConfiguration.ManagementServerAddresses.key()) || + globalSettingUpdated.equals(IndirectAgentLBServiceImpl.IndirectAgentLBAlgorithm.key())) { + _indirectAgentLB.propagateMSListToAgents(); + } else if (globalSettingUpdated.equals(Config.RouterAggregationCommandEachTimeout.toString())) { + _agentManager.propagateChangeToAgents(); + } + } + }); + } + @Override public boolean start() { diff --git a/server/src/main/java/com/cloud/hypervisor/HypervisorGuruBase.java b/server/src/main/java/com/cloud/hypervisor/HypervisorGuruBase.java index b79097884890..d26b5ee80700 100644 --- a/server/src/main/java/com/cloud/hypervisor/HypervisorGuruBase.java +++ b/server/src/main/java/com/cloud/hypervisor/HypervisorGuruBase.java @@ -22,6 +22,8 @@ import javax.inject.Inject; +import com.cloud.network.dao.NetworkDetailVO; +import com.cloud.network.dao.NetworkDetailsDao; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService; import org.apache.commons.collections.CollectionUtils; @@ -77,6 +79,8 @@ public abstract class HypervisorGuruBase extends AdapterBase implements Hypervis protected ServiceOfferingDetailsDao _serviceOfferingDetailsDao; @Inject private ServiceOfferingDao _serviceOfferingDao; + @Inject + private NetworkDetailsDao networkDetailsDao; @Override public NicTO toNicTO(NicProfile profile) { @@ -182,6 +186,10 @@ protected VirtualMachineTO toVirtualMachineTO(VirtualMachineProfile vmProfile) { details.putIfAbsent(NetworkOffering.Detail.MacAddressChanges, NetworkOrchestrationService.MacAddressChanges.value().toString()); details.putIfAbsent(NetworkOffering.Detail.ForgedTransmits, NetworkOrchestrationService.ForgedTransmits.value().toString()); } + NetworkDetailVO pvlantypeDetail = networkDetailsDao.findDetail(network.getId(), ApiConstants.ISOLATED_PVLAN_TYPE); + if (pvlantypeDetail != null) { + details.putIfAbsent(NetworkOffering.Detail.pvlanType, pvlantypeDetail.getValue()); + } nicTo.setDetails(details); } nics[i++] = nicTo; diff --git a/server/src/main/java/com/cloud/hypervisor/KVMGuru.java b/server/src/main/java/com/cloud/hypervisor/KVMGuru.java index 2b84ff9b04df..cf29a1a55a93 100644 --- a/server/src/main/java/com/cloud/hypervisor/KVMGuru.java +++ b/server/src/main/java/com/cloud/hypervisor/KVMGuru.java @@ -132,7 +132,7 @@ public VirtualMachineTO implement(VirtualMachineProfile vm) { guestOsMapping = _guestOsHypervisorDao.findByOsIdAndHypervisor(guestOS.getId(), getHypervisorType().toString(), host.getHypervisorVersion()); } if (guestOsMapping == null || host == null) { - to.setPlatformEmulator("Other"); + to.setPlatformEmulator(guestOS.getDisplayName() == null ? "Other" : guestOS.getDisplayName()); } else { to.setPlatformEmulator(guestOsMapping.getGuestOsName()); } diff --git a/server/src/main/java/com/cloud/network/IpAddressManagerImpl.java b/server/src/main/java/com/cloud/network/IpAddressManagerImpl.java index 55981e809547..409b88f53c4f 100644 --- a/server/src/main/java/com/cloud/network/IpAddressManagerImpl.java +++ b/server/src/main/java/com/cloud/network/IpAddressManagerImpl.java @@ -1693,7 +1693,7 @@ public Ternary, Network> doInTransaction(Transa s_logger.debug("Creating network for account " + owner + " from the network offering id=" + requiredOfferings.get(0).getId() + " as a part of createVlanIpRange process"); guestNetwork = _networkMgr.createGuestNetwork(requiredOfferings.get(0).getId(), owner.getAccountName() + "-network", owner.getAccountName() - + "-network", null, null, null, false, null, owner, null, physicalNetwork, zoneId, ACLType.Account, null, null, null, null, true, null, null); + + "-network", null, null, null, false, null, owner, null, physicalNetwork, zoneId, ACLType.Account, null, null, null, null, true, null, null, null); if (guestNetwork == null) { s_logger.warn("Failed to create default Virtual network for the account " + accountId + "in zone " + zoneId); throw new CloudRuntimeException("Failed to create a Guest Isolated Networks with SourceNAT " diff --git a/server/src/main/java/com/cloud/network/NetworkModelImpl.java b/server/src/main/java/com/cloud/network/NetworkModelImpl.java index b8bd2c38d0d9..031b84331657 100644 --- a/server/src/main/java/com/cloud/network/NetworkModelImpl.java +++ b/server/src/main/java/com/cloud/network/NetworkModelImpl.java @@ -94,7 +94,9 @@ import com.cloud.network.rules.FirewallRule.Purpose; import com.cloud.network.rules.FirewallRuleVO; import com.cloud.network.rules.dao.PortForwardingRulesDao; +import com.cloud.network.vpc.VpcGatewayVO; import com.cloud.network.vpc.dao.PrivateIpDao; +import com.cloud.network.vpc.dao.VpcGatewayDao; import com.cloud.offering.NetworkOffering; import com.cloud.offering.NetworkOffering.Detail; import com.cloud.offerings.NetworkOfferingServiceMapVO; @@ -158,6 +160,8 @@ public class NetworkModelImpl extends ManagerBase implements NetworkModel, Confi NicDao _nicDao = null; @Inject PodVlanMapDao _podVlanMapDao; + @Inject + VpcGatewayDao _vpcGatewayDao; private List networkElements; @@ -1780,8 +1784,8 @@ public List getPhysicalNtwksSupportingTrafficType(lon @Override public boolean isPrivateGateway(long ntwkId) { - Network network = getNetwork(ntwkId); - if (network.getTrafficType() != TrafficType.Guest || network.getNetworkOfferingId() != s_privateOfferingId.longValue()) { + final VpcGatewayVO gateway = _vpcGatewayDao.getVpcGatewayByNetworkId(ntwkId); + if (gateway == null) { return false; } return true; diff --git a/server/src/main/java/com/cloud/network/NetworkServiceImpl.java b/server/src/main/java/com/cloud/network/NetworkServiceImpl.java index 1e9eb2d325f5..3ebd38407ca8 100644 --- a/server/src/main/java/com/cloud/network/NetworkServiceImpl.java +++ b/server/src/main/java/com/cloud/network/NetworkServiceImpl.java @@ -38,6 +38,7 @@ import javax.inject.Inject; import javax.naming.ConfigurationException; +import com.cloud.network.Network.PVlanType; import org.apache.cloudstack.acl.ControlledEntity.ACLType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ApiConstants; @@ -55,6 +56,8 @@ import org.apache.cloudstack.api.response.AcquirePodIpCmdResponse; import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService; +import org.apache.cloudstack.framework.config.ConfigKey; +import org.apache.cloudstack.framework.config.Configurable; import org.apache.cloudstack.framework.config.dao.ConfigurationDao; import org.apache.cloudstack.framework.messagebus.MessageBus; import org.apache.cloudstack.framework.messagebus.PublishScope; @@ -107,6 +110,7 @@ import com.cloud.network.dao.IPAddressDao; import com.cloud.network.dao.IPAddressVO; import com.cloud.network.dao.LoadBalancerDao; +import com.cloud.network.dao.NetworkAccountDao; import com.cloud.network.dao.NetworkDao; import com.cloud.network.dao.NetworkDetailVO; import com.cloud.network.dao.NetworkDetailsDao; @@ -197,12 +201,20 @@ import com.cloud.vm.dao.UserVmDao; import com.cloud.vm.dao.VMInstanceDao; +import static org.apache.commons.lang.StringUtils.isBlank; +import static org.apache.commons.lang.StringUtils.isNotBlank; + /** * NetworkServiceImpl implements NetworkService. */ -public class NetworkServiceImpl extends ManagerBase implements NetworkService { +public class NetworkServiceImpl extends ManagerBase implements NetworkService, Configurable { private static final Logger s_logger = Logger.getLogger(NetworkServiceImpl.class); + private static final ConfigKey AllowDuplicateNetworkName = new ConfigKey("Advanced", Boolean.class, + "allow.duplicate.networkname", "true", "Allow creating networks with same name in account", true, ConfigKey.Scope.Account); + private static final ConfigKey AllowEmptyStartEndIpAddress = new ConfigKey("Advanced", Boolean.class, + "allow.empty.start.end.ipaddress", "true", "Allow creating network without mentioning start and end IP address", + true, ConfigKey.Scope.Account); private static final long MIN_VLAN_ID = 0L; private static final long MAX_VLAN_ID = 4095L; // 2^12 - 1 private static final long MIN_GRE_KEY = 0L; @@ -313,6 +325,8 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { VpcOfferingDao _vpcOfferingDao; @Inject AccountService _accountService; + @Inject + NetworkAccountDao _networkAccountDao; int _cidrLimit; boolean _allowSubdomainNetworkAccess; @@ -1052,6 +1066,7 @@ public Network createGuestNetwork(CreateNetworkCmd cmd) throws InsufficientCapac Long aclId = cmd.getAclId(); String isolatedPvlan = cmd.getIsolatedPvlan(); String externalId = cmd.getExternalId(); + String isolatedPvlanType = cmd.getIsolatedPvlanType(); // Validate network offering NetworkOfferingVO ntwkOff = _networkOfferingDao.findById(networkOfferingId); @@ -1164,6 +1179,18 @@ public Network createGuestNetwork(CreateNetworkCmd cmd) throws InsufficientCapac throw new InvalidParameterValueException("Parameter subDomainAccess can be specified only with aclType=Domain"); } + if (aclType == ACLType.Domain) { + owner = _accountDao.findById(Account.ACCOUNT_ID_SYSTEM); + } + + // The network name is unique under the account + if (!AllowDuplicateNetworkName.valueIn(owner.getAccountId())) { + List existingNetwork = _networksDao.listByAccountIdNetworkName(owner.getId(), name); + if (!existingNetwork.isEmpty()) { + throw new InvalidParameterValueException("Another network with same name already exists within account: " + owner.getAccountName()); + } + } + boolean ipv4 = true, ipv6 = false; if (startIP != null) { ipv4 = true; @@ -1188,6 +1215,15 @@ public Network createGuestNetwork(CreateNetworkCmd cmd) throws InsufficientCapac } } + // Start and end IP address are mandatory for shared networks. + if (ntwkOff.getGuestType() == GuestType.Shared && vpcId == null) { + if (!AllowEmptyStartEndIpAddress.valueIn(owner.getAccountId()) && + (startIP == null && endIP == null) && + (startIPv6 == null && endIPv6 == null)) { + throw new InvalidParameterValueException("Either IPv4 or IPv6 start and end address are mandatory"); + } + } + String cidr = null; if (ipv4) { // if end ip is not specified, default it to startIp @@ -1239,14 +1275,24 @@ public Network createGuestNetwork(CreateNetworkCmd cmd) throws InsufficientCapac } } - if (isolatedPvlan != null && (zone.getNetworkType() != NetworkType.Advanced || ntwkOff.getGuestType() != Network.GuestType.Shared)) { - throw new InvalidParameterValueException("Can only support create Private VLAN network with advance shared network!"); + if (isNotBlank(isolatedPvlan) && (zone.getNetworkType() != NetworkType.Advanced || ntwkOff.getGuestType() == GuestType.Isolated)) { + throw new InvalidParameterValueException("Can only support create Private VLAN network with advanced shared or L2 network!"); } - if (isolatedPvlan != null && ipv6) { + if (isNotBlank(isolatedPvlan) && ipv6) { throw new InvalidParameterValueException("Can only support create Private VLAN network with IPv4!"); } + Pair pvlanPair = getPrivateVlanPair(isolatedPvlan, isolatedPvlanType, vlanId); + String secondaryVlanId = pvlanPair.first(); + PVlanType privateVlanType = pvlanPair.second(); + + if ((isNotBlank(secondaryVlanId) || privateVlanType != null) && isBlank(vlanId)) { + throw new InvalidParameterValueException("VLAN ID has to be set in order to configure a Private VLAN"); + } + + performBasicPrivateVlanChecks(vlanId, secondaryVlanId, privateVlanType); + // Regular user can create Guest Isolated Source Nat enabled network only if (_accountMgr.isNormalUser(caller.getId()) && (ntwkOff.getTrafficType() != TrafficType.Guest || ntwkOff.getGuestType() != Network.GuestType.Isolated && areServicesSupportedByNetworkOffering(ntwkOff.getId(), Service.SourceNat))) { @@ -1278,7 +1324,7 @@ public Network createGuestNetwork(CreateNetworkCmd cmd) throws InsufficientCapac throw new InvalidParameterValueException("Cannot support IPv6 on network offering with external devices!"); } - if (isolatedPvlan != null && providersConfiguredForExternalNetworking(ntwkProviders)) { + if (isNotBlank(secondaryVlanId) && providersConfiguredForExternalNetworking(ntwkProviders)) { throw new InvalidParameterValueException("Cannot support private vlan on network offering with external devices!"); } @@ -1314,7 +1360,7 @@ public Network createGuestNetwork(CreateNetworkCmd cmd) throws InsufficientCapac } Network network = commitNetwork(networkOfferingId, gateway, startIP, endIP, netmask, networkDomain, vlanId, bypassVlanOverlapCheck, name, displayText, caller, physicalNetworkId, zoneId, - domainId, isDomainSpecific, subdomainAccess, vpcId, startIPv6, endIPv6, ip6Gateway, ip6Cidr, displayNetwork, aclId, isolatedPvlan, ntwkOff, pNtwk, aclType, owner, cidr, createVlan, + domainId, isDomainSpecific, subdomainAccess, vpcId, startIPv6, endIPv6, ip6Gateway, ip6Cidr, displayNetwork, aclId, secondaryVlanId, privateVlanType, ntwkOff, pNtwk, aclType, owner, cidr, createVlan, externalId); if (hideIpAddressUsage) { @@ -1348,11 +1394,54 @@ public Network createGuestNetwork(CreateNetworkCmd cmd) throws InsufficientCapac return network; } + /** + * Retrieve information (if set) for private VLAN when creating the network + */ + protected Pair getPrivateVlanPair(String pvlanId, String pvlanTypeStr, String vlanId) { + String secondaryVlanId = pvlanId; + PVlanType type = null; + + if (isNotBlank(pvlanTypeStr)) { + PVlanType providedType = PVlanType.fromValue(pvlanTypeStr); + type = providedType; + } else if (isNotBlank(vlanId) && isNotBlank(secondaryVlanId)) { + // Preserve the existing functionality + type = vlanId.equals(secondaryVlanId) ? PVlanType.Promiscuous : PVlanType.Isolated; + } + + if (isBlank(secondaryVlanId) && type == PVlanType.Promiscuous) { + secondaryVlanId = vlanId; + } + + if (isNotBlank(secondaryVlanId)) { + try { + Integer.parseInt(secondaryVlanId); + } catch (NumberFormatException e) { + throw new CloudRuntimeException("The secondary VLAN ID: " + secondaryVlanId + " is not in numeric format", e); + } + } + + return new Pair<>(secondaryVlanId, type); + } + + /** + * Basic checks for setting up private VLANs, considering the VLAN ID, secondary VLAN ID and private VLAN type + */ + protected void performBasicPrivateVlanChecks(String vlanId, String secondaryVlanId, PVlanType privateVlanType) { + if (isNotBlank(vlanId) && isBlank(secondaryVlanId) && privateVlanType != null && privateVlanType != PVlanType.Promiscuous) { + throw new InvalidParameterValueException("Private VLAN ID has not been set, therefore Promiscuous type is expected"); + } else if (isNotBlank(vlanId) && isNotBlank(secondaryVlanId) && !vlanId.equalsIgnoreCase(secondaryVlanId) && privateVlanType == PVlanType.Promiscuous) { + throw new InvalidParameterValueException("Private VLAN type is set to Promiscuous, but VLAN ID and Secondary VLAN ID differ"); + } else if (isNotBlank(vlanId) && isNotBlank(secondaryVlanId) && privateVlanType != null && privateVlanType != PVlanType.Promiscuous && vlanId.equalsIgnoreCase(secondaryVlanId)) { + throw new InvalidParameterValueException("Private VLAN type is set to " + privateVlanType + ", but VLAN ID and Secondary VLAN ID are equal"); + } + } + private Network commitNetwork(final Long networkOfferingId, final String gateway, final String startIP, final String endIP, final String netmask, final String networkDomain, final String vlanId, - final Boolean bypassVlanOverlapCheck, final String name, final String displayText, final Account caller, final Long physicalNetworkId, final Long zoneId, final Long domainId, - final boolean isDomainSpecific, final Boolean subdomainAccessFinal, final Long vpcId, final String startIPv6, final String endIPv6, final String ip6Gateway, final String ip6Cidr, - final Boolean displayNetwork, final Long aclId, final String isolatedPvlan, final NetworkOfferingVO ntwkOff, final PhysicalNetwork pNtwk, final ACLType aclType, final Account ownerFinal, - final String cidr, final boolean createVlan, final String externalId) throws InsufficientCapacityException, ResourceAllocationException { + final Boolean bypassVlanOverlapCheck, final String name, final String displayText, final Account caller, final Long physicalNetworkId, final Long zoneId, final Long domainId, + final boolean isDomainSpecific, final Boolean subdomainAccessFinal, final Long vpcId, final String startIPv6, final String endIPv6, final String ip6Gateway, final String ip6Cidr, + final Boolean displayNetwork, final Long aclId, final String isolatedPvlan, final PVlanType isolatedPvlanType, final NetworkOfferingVO ntwkOff, final PhysicalNetwork pNtwk, final ACLType aclType, final Account ownerFinal, + final String cidr, final boolean createVlan, final String externalId) throws InsufficientCapacityException, ResourceAllocationException { try { Network network = Transaction.execute(new TransactionCallbackWithException() { @Override @@ -1407,7 +1496,7 @@ public Network doInTransaction(TransactionStatus status) throws InsufficientCapa } network = _networkMgr.createGuestNetwork(networkOfferingId, name, displayText, gateway, cidr, vlanId, bypassVlanOverlapCheck, networkDomain, owner, sharedDomainId, pNtwk, - zoneId, aclType, subdomainAccess, vpcId, ip6Gateway, ip6Cidr, displayNetwork, isolatedPvlan, externalId); + zoneId, aclType, subdomainAccess, vpcId, ip6Gateway, ip6Cidr, displayNetwork, isolatedPvlan, isolatedPvlanType, externalId); } if (_accountMgr.isRootAdmin(caller.getId()) && createVlan && network != null) { @@ -1861,14 +1950,7 @@ public boolean deleteNetwork(long networkId, boolean forced) { @Override @ActionEvent(eventType = EventTypes.EVENT_NETWORK_RESTART, eventDescription = "restarting network", async = true) - public boolean restartNetwork(RestartNetworkCmd cmd, boolean cleanup, boolean makeRedundant) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException { - // This method restarts all network elements belonging to the network and re-applies all the rules - Long networkId = cmd.getNetworkId(); - - User callerUser = _accountMgr.getActiveUser(CallContext.current().getCallingUserId()); - Account callerAccount = _accountMgr.getActiveAccountById(callerUser.getAccountId()); - - // Check if network exists + public boolean restartNetwork(Long networkId, boolean cleanup, boolean makeRedundant, User user) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException { NetworkVO network = _networksDao.findById(networkId); if (network == null) { throwInvalidIdException("Network with specified id doesn't exist", networkId.toString(), "networkId"); @@ -1888,8 +1970,8 @@ public boolean restartNetwork(RestartNetworkCmd cmd, boolean cleanup, boolean ma throw new InvalidParameterException("Unable to restart a running SDN network."); } + Account callerAccount = _accountMgr.getActiveAccountById(user.getAccountId()); _accountMgr.checkAccess(callerAccount, null, true, network); - if (!network.isRedundant() && makeRedundant) { network.setRedundant(true); if (!_networksDao.update(network.getId(), network)) { @@ -1898,8 +1980,7 @@ public boolean restartNetwork(RestartNetworkCmd cmd, boolean cleanup, boolean ma cleanup = true; } - boolean success = _networkMgr.restartNetwork(networkId, callerAccount, callerUser, cleanup); - + boolean success = _networkMgr.restartNetwork(networkId, callerAccount, user, cleanup); if (success) { s_logger.debug("Network id=" + networkId + " is restarted successfully."); } else { @@ -1909,6 +1990,17 @@ public boolean restartNetwork(RestartNetworkCmd cmd, boolean cleanup, boolean ma return success; } + @Override + @ActionEvent(eventType = EventTypes.EVENT_NETWORK_RESTART, eventDescription = "restarting network", async = true) + public boolean restartNetwork(RestartNetworkCmd cmd) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException { + // This method restarts all network elements belonging to the network and re-applies all the rules + Long networkId = cmd.getNetworkId(); + boolean cleanup = cmd.getCleanup(); + boolean makeRedundant = cmd.getMakeRedundant(); + User callerUser = _accountMgr.getActiveUser(CallContext.current().getCallingUserId()); + return restartNetwork(networkId, cleanup, makeRedundant, callerUser); + } + @Override public int getActiveNicsInNetwork(long networkId) { return _networksDao.getActiveNicsIn(networkId); @@ -4381,7 +4473,7 @@ public Network doInTransaction(TransactionStatus status) throws ResourceAllocati if (privateNetwork == null) { //create Guest network privateNetwork = _networkMgr.createGuestNetwork(ntwkOffFinal.getId(), networkName, displayText, gateway, cidr, uriString, false, null, owner, null, pNtwk, - pNtwk.getDataCenterId(), ACLType.Account, null, vpcId, null, null, true, null, null); + pNtwk.getDataCenterId(), ACLType.Account, null, vpcId, null, null, true, null, null,null); if (privateNetwork != null) { s_logger.debug("Successfully created guest network " + privateNetwork); } else { @@ -4534,4 +4626,14 @@ public boolean releasePodIp(ReleasePodIpCmdByAdmin ip) throws CloudRuntimeExcept return true; } + @Override + public String getConfigComponentName() { + return NetworkService.class.getSimpleName(); + } + + @Override + public ConfigKey[] getConfigKeys() { + return new ConfigKey[] {AllowDuplicateNetworkName, AllowEmptyStartEndIpAddress}; + } + } diff --git a/server/src/main/java/com/cloud/network/as/AutoScaleManagerImpl.java b/server/src/main/java/com/cloud/network/as/AutoScaleManagerImpl.java index 1b936e10d822..c71054951619 100644 --- a/server/src/main/java/com/cloud/network/as/AutoScaleManagerImpl.java +++ b/server/src/main/java/com/cloud/network/as/AutoScaleManagerImpl.java @@ -1376,6 +1376,9 @@ private boolean startNewVM(long vmId) { } catch (final ResourceUnavailableException ex) { s_logger.warn("Exception: ", ex); throw new ServerApiException(ApiErrorCode.RESOURCE_UNAVAILABLE_ERROR, ex.getMessage()); + } catch (ResourceAllocationException ex) { + s_logger.warn("Exception: ", ex); + throw new ServerApiException(ApiErrorCode.RESOURCE_ALLOCATION_ERROR, ex.getMessage()); } catch (ConcurrentOperationException ex) { s_logger.warn("Exception: ", ex); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage()); diff --git a/server/src/main/java/com/cloud/network/firewall/FirewallManagerImpl.java b/server/src/main/java/com/cloud/network/firewall/FirewallManagerImpl.java index efab0e255689..56814daeef25 100644 --- a/server/src/main/java/com/cloud/network/firewall/FirewallManagerImpl.java +++ b/server/src/main/java/com/cloud/network/firewall/FirewallManagerImpl.java @@ -18,23 +18,21 @@ import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; -import java.util.Collections; import javax.inject.Inject; import javax.naming.ConfigurationException; -import com.cloud.network.dao.FirewallRulesDcidrsDao; -import org.apache.log4j.Logger; -import org.springframework.stereotype.Component; - import org.apache.cloudstack.api.command.user.firewall.IListFirewallRulesCmd; import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService; import org.apache.cloudstack.framework.config.dao.ConfigurationDao; +import org.apache.log4j.Logger; +import org.springframework.stereotype.Component; import com.cloud.configuration.Config; import com.cloud.domain.dao.DomainDao; @@ -55,6 +53,7 @@ import com.cloud.network.NetworkRuleApplier; import com.cloud.network.dao.FirewallRulesCidrsDao; import com.cloud.network.dao.FirewallRulesDao; +import com.cloud.network.dao.FirewallRulesDcidrsDao; import com.cloud.network.dao.IPAddressDao; import com.cloud.network.dao.IPAddressVO; import com.cloud.network.dao.NetworkDao; diff --git a/server/src/main/java/com/cloud/network/guru/DirectNetworkGuru.java b/server/src/main/java/com/cloud/network/guru/DirectNetworkGuru.java index 21538a8a5281..22811dadf435 100644 --- a/server/src/main/java/com/cloud/network/guru/DirectNetworkGuru.java +++ b/server/src/main/java/com/cloud/network/guru/DirectNetworkGuru.java @@ -201,6 +201,10 @@ public Network design(NetworkOffering offering, DeploymentPlan plan, Network use if (userSpecified.getBroadcastDomainType() != null) { config.setBroadcastDomainType(userSpecified.getBroadcastDomainType()); } + + if (userSpecified.getPvlanType() != null) { + config.setPvlanType(userSpecified.getPvlanType()); + } } boolean isSecurityGroupEnabled = _networkModel.areServicesSupportedByNetworkOffering(offering.getId(), Service.SecurityGroup); diff --git a/server/src/main/java/com/cloud/network/guru/GuestNetworkGuru.java b/server/src/main/java/com/cloud/network/guru/GuestNetworkGuru.java index 9cd337447f9a..19927752ee07 100644 --- a/server/src/main/java/com/cloud/network/guru/GuestNetworkGuru.java +++ b/server/src/main/java/com/cloud/network/guru/GuestNetworkGuru.java @@ -214,6 +214,10 @@ public Network design(final NetworkOffering offering, final DeploymentPlan plan, if (offering.isSpecifyVlan()) { network.setBroadcastUri(userSpecified.getBroadcastUri()); network.setState(State.Setup); + if (userSpecified.getPvlanType() != null) { + network.setBroadcastDomainType(BroadcastDomainType.Pvlan); + network.setPvlanType(userSpecified.getPvlanType()); + } } } else { final String guestNetworkCidr = dc.getGuestNetworkCidr(); diff --git a/server/src/main/java/com/cloud/network/router/CommandSetupHelper.java b/server/src/main/java/com/cloud/network/router/CommandSetupHelper.java index f9ffeb99d67c..0fe9dc32c8b5 100644 --- a/server/src/main/java/com/cloud/network/router/CommandSetupHelper.java +++ b/server/src/main/java/com/cloud/network/router/CommandSetupHelper.java @@ -104,7 +104,9 @@ import com.cloud.network.vpc.StaticRouteProfile; import com.cloud.network.vpc.Vpc; import com.cloud.network.vpc.VpcGateway; +import com.cloud.network.vpc.VpcGatewayVO; import com.cloud.network.vpc.dao.VpcDao; +import com.cloud.network.vpc.dao.VpcGatewayDao; import com.cloud.offering.NetworkOffering; import com.cloud.offerings.NetworkOfferingVO; import com.cloud.offerings.dao.NetworkOfferingDao; @@ -170,6 +172,8 @@ public class CommandSetupHelper { @Inject private VpcDao _vpcDao; @Inject + private VpcGatewayDao _vpcGatewayDao; + @Inject private VlanDao _vlanDao; @Inject private IPAddressDao _ipAddressDao; @@ -707,7 +711,7 @@ public int compare(final PublicIpAddress o1, final PublicIpAddress o2) { final IpAddressTO ip = new IpAddressTO(ipAddr.getAccountId(), ipAddr.getAddress().addr(), add, firstIP, sourceNat, BroadcastDomainType.fromString(ipAddr.getVlanTag()).toString(), ipAddr.getGateway(), ipAddr.getNetmask(), macAddress, networkRate, ipAddr.isOneToOneNat()); - ip.setTrafficType(network.getTrafficType()); + ip.setTrafficType(getNetworkTrafficType(network)); ip.setNetworkName(_networkModel.getNetworkTag(router.getHypervisorType(), network)); ipsToSend[i++] = ip; if (ipAddr.isSourceNat()) { @@ -823,7 +827,7 @@ public int compare(final PublicIpAddress o1, final PublicIpAddress o2) { final IpAddressTO ip = new IpAddressTO(ipAddr.getAccountId(), ipAddr.getAddress().addr(), add, firstIP, sourceNat, vlanId, vlanGateway, vlanNetmask, vifMacAddress, networkRate, ipAddr.isOneToOneNat()); - ip.setTrafficType(network.getTrafficType()); + ip.setTrafficType(getNetworkTrafficType(network)); ip.setNetworkName(_networkModel.getNetworkTag(router.getHypervisorType(), network)); ipsToSend[i++] = ip; /* @@ -948,7 +952,7 @@ public void createVpcAssociatePrivateIPCommands(final VirtualRouter router, fina final IpAddressTO ip = new IpAddressTO(Account.ACCOUNT_ID_SYSTEM, ipAddr.getIpAddress(), add, false, ipAddr.getSourceNat(), ipAddr.getBroadcastUri(), ipAddr.getGateway(), ipAddr.getNetmask(), ipAddr.getMacAddress(), null, false); - ip.setTrafficType(network.getTrafficType()); + ip.setTrafficType(getNetworkTrafficType(network)); ip.setNetworkName(_networkModel.getNetworkTag(router.getHypervisorType(), network)); ipsToSend[i++] = ip; @@ -1101,4 +1105,14 @@ protected String getGuestDhcpRange(final NicProfile guestNic, final Network gues } return dhcpRange; } + + private TrafficType getNetworkTrafficType(Network network) { + final VpcGatewayVO gateway = _vpcGatewayDao.getVpcGatewayByNetworkId(network.getId()); + if (gateway != null) { + s_logger.debug("network " + network.getId() + " (name: " + network.getName() + " ) is a vpc private gateway, set traffic type to Public"); + return TrafficType.Public; + } else { + return network.getTrafficType(); + } + } } diff --git a/server/src/main/java/com/cloud/network/router/NetworkHelperImpl.java b/server/src/main/java/com/cloud/network/router/NetworkHelperImpl.java index da07bb5dff5d..a549adbc6b3e 100644 --- a/server/src/main/java/com/cloud/network/router/NetworkHelperImpl.java +++ b/server/src/main/java/com/cloud/network/router/NetworkHelperImpl.java @@ -154,6 +154,8 @@ public class NetworkHelperImpl implements NetworkHelper { protected IpAddressManager _ipAddrMgr; @Inject ConfigurationDao _configDao; + @Inject + VpcVirtualNetworkApplianceManager _vpcRouterMgr; protected final Map> hypervisorsMap = new HashMap<>(); @@ -258,7 +260,7 @@ public VirtualRouter destroyRouter(final long routerId, final Account caller, fi @Override public boolean checkRouterVersion(final VirtualRouter router) { - if (!VirtualNetworkApplianceManagerImpl.routerVersionCheckEnabled.value()) { + if (!VirtualNetworkApplianceManager.RouterVersionCheckEnabled.value()) { // Router version check is disabled. return true; } @@ -288,7 +290,7 @@ protected DomainRouterVO start(DomainRouterVO router, final User user, final Acc // only after router start successfully final Long vpcId = router.getVpcId(); if (vpcId != null) { - _s2sVpnMgr.reconnectDisconnectedVpnByVpc(vpcId); + _vpcRouterMgr.startSite2SiteVpn(_routerDao.findById(router.getId())); } return _routerDao.findById(router.getId()); } diff --git a/server/src/main/java/com/cloud/network/router/VirtualNetworkApplianceManager.java b/server/src/main/java/com/cloud/network/router/VirtualNetworkApplianceManager.java index a291b3590b25..eba23f3fe3df 100644 --- a/server/src/main/java/com/cloud/network/router/VirtualNetworkApplianceManager.java +++ b/server/src/main/java/com/cloud/network/router/VirtualNetworkApplianceManager.java @@ -45,6 +45,10 @@ public interface VirtualNetworkApplianceManager extends Manager, VirtualNetworkA static final String SetServiceMonitorCK = "network.router.EnableServiceMonitoring"; static final String RouterAlertsCheckIntervalCK = "router.alerts.check.interval"; + static final String RouterHealthChecksConfigRefreshIntervalCK = "router.health.checks.config.refresh.interval"; + static final String RouterHealthChecksResultFetchIntervalCK = "router.health.checks.results.fetch.interval"; + static final String RouterHealthChecksFailuresToRecreateVrCK = "router.health.checks.failures.to.recreate.vr"; + static final ConfigKey RouterTemplateXen = new ConfigKey(String.class, RouterTemplateXenCK, "Advanced", "SystemVM Template (XenServer)", "Name of the default router template on Xenserver.", true, ConfigKey.Scope.Zone, null); static final ConfigKey RouterTemplateKvm = new ConfigKey(String.class, RouterTemplateKvmCK, "Advanced", "SystemVM Template (KVM)", @@ -63,11 +67,48 @@ public interface VirtualNetworkApplianceManager extends Manager, VirtualNetworkA static final ConfigKey RouterAlertsCheckInterval = new ConfigKey(Integer.class, RouterAlertsCheckIntervalCK, "Advanced", "1800", "Interval (in seconds) to check for alerts in Virtual Router.", false, ConfigKey.Scope.Global, null); - static final ConfigKey routerVersionCheckEnabled = new ConfigKey("Advanced", Boolean.class, "router.version.check", "true", + static final ConfigKey RouterVersionCheckEnabled = new ConfigKey("Advanced", Boolean.class, "router.version.check", "true", "If true, router minimum required version is checked before sending command", false); static final ConfigKey UseExternalDnsServers = new ConfigKey(Boolean.class, "use.external.dns", "Advanced", "false", "Bypass internal dns, use external dns1 and dns2", true, ConfigKey.Scope.Zone, null); + // Health checks + static final ConfigKey RouterHealthChecksEnabled = new ConfigKey(Boolean.class, "router.health.checks.enabled", "Advanced", "true", + "If true, router health checks are allowed to be executed and read. If false, all scheduled checks and API calls for on demand checks are disabled.", + true, ConfigKey.Scope.Global, null); + static final ConfigKey RouterHealthChecksBasicInterval = new ConfigKey(Integer.class, "router.health.checks.basic.interval", "Advanced", "3", + "Interval in minutes at which basic router health checks are performed. If set to 0, no tests are scheduled.", + true, ConfigKey.Scope.Global, null); + static final ConfigKey RouterHealthChecksAdvancedInterval = new ConfigKey(Integer.class, "router.health.checks.advanced.interval", "Advanced", "10", + "Interval in minutes at which advanced router health checks are performed. If set to 0, no tests are scheduled.", + true, ConfigKey.Scope.Global, null); + static final ConfigKey RouterHealthChecksConfigRefreshInterval = new ConfigKey(Integer.class, RouterHealthChecksConfigRefreshIntervalCK, "Advanced", "10", + "Interval in minutes at which router health checks config - such as scheduling intervals, excluded checks, etc is updated on virtual routers by the management server. This value should" + + " be sufficiently high (like 2x) from the router.health.checks.basic.interval and router.health.checks.advanced.interval so that there is time between new results generation and results generation for passed data.", + false, ConfigKey.Scope.Global, null); + static final ConfigKey RouterHealthChecksResultFetchInterval = new ConfigKey(Integer.class, RouterHealthChecksResultFetchIntervalCK, "Advanced", "10", + "Interval in minutes at which router health checks results are fetched by management server. On each result fetch, management server evaluates need to recreate VR as per configuration of " + RouterHealthChecksFailuresToRecreateVrCK + + "This value should be sufficiently high (like 2x) from the router.health.checks.basic.interval and router.health.checks.advanced.interval so that there is time between new results generation and fetch.", + false, ConfigKey.Scope.Global, null); + static final ConfigKey RouterHealthChecksFailuresToRecreateVr = new ConfigKey(String.class, RouterHealthChecksFailuresToRecreateVrCK, "Advanced", "", + "Health checks failures defined by this config are the checks that should cause router recreation. If empty the recreate is not attempted for any health check failure. Possible values are comma separated script names " + + "from systemvm’s /root/health_scripts/ (namely - cpu_usage_check.py, dhcp_check.py, disk_space_check.py, dns_check.py, gateways_check.py, haproxy_check.py, iptables_check.py, memory_usage_check.py, router_version_check.py), connectivity.test " + + " or services (namely - loadbalancing.service, webserver.service, dhcp.service) ", + true, ConfigKey.Scope.Zone, null); + static final ConfigKey RouterHealthChecksToExclude = new ConfigKey(String.class, "router.health.checks.to.exclude", "Advanced", "", + "Health checks that should be excluded when executing scheduled checks on the router. This can be a comma separated list of script names placed in the '/root/health_checks/' folder. Currently the following scripts are " + + "placed in default systemvm template - cpu_usage_check.py, disk_space_check.py, gateways_check.py, iptables_check.py, router_version_check.py, dhcp_check.py, dns_check.py, haproxy_check.py, memory_usage_check.py.", + true, ConfigKey.Scope.Zone, null); + static final ConfigKey RouterHealthChecksFreeDiskSpaceThreshold = new ConfigKey(Double.class, "router.health.checks.free.disk.space.threshold", + "Advanced", "100", "Free disk space threshold (in MB) on VR below which the check is considered a failure.", + true, ConfigKey.Scope.Zone, null); + static final ConfigKey RouterHealthChecksMaxCpuUsageThreshold = new ConfigKey(Double.class, "router.health.checks.max.cpu.usage.threshold", + "Advanced", "100", " Max CPU Usage threshold as % above which check is considered a failure.", + true, ConfigKey.Scope.Zone, null); + static final ConfigKey RouterHealthChecksMaxMemoryUsageThreshold = new ConfigKey(Double.class, "router.health.checks.max.memory.usage.threshold", + "Advanced", "100", "Max Memory Usage threshold as % above which check is considered a failure.", + true, ConfigKey.Scope.Zone, null); + public static final int DEFAULT_ROUTER_VM_RAMSIZE = 256; // 256M public static final int DEFAULT_ROUTER_CPU_MHZ = 500; // 500 MHz public static final boolean USE_POD_VLAN = false; diff --git a/server/src/main/java/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java b/server/src/main/java/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java index c8ea47b31db1..50cd8a4876f2 100644 --- a/server/src/main/java/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java +++ b/server/src/main/java/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java @@ -17,6 +17,7 @@ package com.cloud.network.router; +import java.lang.reflect.Type; import java.math.BigInteger; import java.nio.charset.Charset; import java.security.MessageDigest; @@ -24,7 +25,9 @@ import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Arrays; import java.util.Calendar; +import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.HashSet; @@ -42,11 +45,6 @@ import javax.inject.Inject; import javax.naming.ConfigurationException; -import org.apache.log4j.Logger; -import org.cloud.network.router.deployment.RouterDeploymentDefinitionBuilder; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; - import org.apache.cloudstack.alert.AlertService; import org.apache.cloudstack.alert.AlertService.AlertType; import org.apache.cloudstack.api.command.admin.router.RebootRouterCmd; @@ -61,11 +59,18 @@ import org.apache.cloudstack.framework.config.dao.ConfigurationDao; import org.apache.cloudstack.framework.jobs.AsyncJobManager; import org.apache.cloudstack.framework.jobs.impl.AsyncJobVO; +import org.apache.cloudstack.lb.ApplicationLoadBalancerRuleVO; +import org.apache.cloudstack.lb.dao.ApplicationLoadBalancerRuleDao; import org.apache.cloudstack.managed.context.ManagedContextRunnable; import org.apache.cloudstack.network.topology.NetworkTopology; import org.apache.cloudstack.network.topology.NetworkTopologyContext; import org.apache.cloudstack.utils.identity.ManagementServerNode; import org.apache.cloudstack.utils.usage.UsageUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.log4j.Logger; +import org.cloud.network.router.deployment.RouterDeploymentDefinitionBuilder; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; import com.cloud.agent.AgentManager; import com.cloud.agent.Listener; @@ -87,6 +92,9 @@ import com.cloud.agent.api.routing.AggregationControlCommand; import com.cloud.agent.api.routing.AggregationControlCommand.Action; import com.cloud.agent.api.routing.GetRouterAlertsCommand; +import com.cloud.agent.api.routing.GetRouterMonitorResultsAnswer; +import com.cloud.agent.api.routing.GetRouterMonitorResultsCommand; +import com.cloud.agent.api.routing.GroupAnswer; import com.cloud.agent.api.routing.IpAliasTO; import com.cloud.agent.api.routing.NetworkElementCommand; import com.cloud.agent.api.routing.SetMonitorServiceCommand; @@ -95,6 +103,10 @@ import com.cloud.alert.AlertManager; import com.cloud.api.ApiAsyncJobDispatcher; import com.cloud.api.ApiGsonHelper; +import com.cloud.api.query.dao.DomainRouterJoinDao; +import com.cloud.api.query.dao.UserVmJoinDao; +import com.cloud.api.query.vo.DomainRouterJoinVO; +import com.cloud.api.query.vo.UserVmJoinVO; import com.cloud.cluster.ManagementServerHostVO; import com.cloud.cluster.dao.ManagementServerHostDao; import com.cloud.configuration.Config; @@ -109,7 +121,9 @@ import com.cloud.dc.dao.HostPodDao; import com.cloud.dc.dao.VlanDao; import com.cloud.deploy.DeployDestination; +import com.cloud.domain.Domain; import com.cloud.event.ActionEvent; +import com.cloud.event.ActionEventUtils; import com.cloud.event.EventTypes; import com.cloud.exception.AgentUnavailableException; import com.cloud.exception.ConcurrentOperationException; @@ -135,6 +149,7 @@ import com.cloud.network.Networks.TrafficType; import com.cloud.network.PublicIpAddress; import com.cloud.network.RemoteAccessVpn; +import com.cloud.network.RouterHealthCheckResult; import com.cloud.network.Site2SiteCustomerGateway; import com.cloud.network.Site2SiteVpnConnection; import com.cloud.network.SshKeysDistriMonitor; @@ -144,8 +159,11 @@ import com.cloud.network.dao.FirewallRulesDao; import com.cloud.network.dao.IPAddressDao; import com.cloud.network.dao.IPAddressVO; +import com.cloud.network.dao.LBStickinessPolicyDao; +import com.cloud.network.dao.LBStickinessPolicyVO; import com.cloud.network.dao.LoadBalancerDao; import com.cloud.network.dao.LoadBalancerVMMapDao; +import com.cloud.network.dao.LoadBalancerVMMapVO; import com.cloud.network.dao.LoadBalancerVO; import com.cloud.network.dao.MonitoringServiceDao; import com.cloud.network.dao.MonitoringServiceVO; @@ -155,6 +173,8 @@ import com.cloud.network.dao.OpRouterMonitorServiceVO; import com.cloud.network.dao.PhysicalNetworkServiceProviderDao; import com.cloud.network.dao.RemoteAccessVpnDao; +import com.cloud.network.dao.RouterHealthCheckResultDao; +import com.cloud.network.dao.RouterHealthCheckResultVO; import com.cloud.network.dao.Site2SiteCustomerGatewayDao; import com.cloud.network.dao.Site2SiteVpnConnectionDao; import com.cloud.network.dao.Site2SiteVpnConnectionVO; @@ -175,12 +195,14 @@ import com.cloud.network.rules.FirewallRuleVO; import com.cloud.network.rules.LoadBalancerContainer.Scheme; import com.cloud.network.rules.PortForwardingRule; +import com.cloud.network.rules.PortForwardingRuleVO; import com.cloud.network.rules.RulesManager; import com.cloud.network.rules.StaticNat; import com.cloud.network.rules.StaticNatImpl; import com.cloud.network.rules.StaticNatRule; import com.cloud.network.rules.dao.PortForwardingRulesDao; import com.cloud.network.vpc.Vpc; +import com.cloud.network.vpc.VpcService; import com.cloud.network.vpc.dao.VpcDao; import com.cloud.network.vpn.Site2SiteVpnManager; import com.cloud.offering.NetworkOffering; @@ -188,6 +210,7 @@ import com.cloud.offerings.NetworkOfferingVO; import com.cloud.offerings.dao.NetworkOfferingDao; import com.cloud.resource.ResourceManager; +import com.cloud.serializer.GsonHelper; import com.cloud.server.ConfigurationServer; import com.cloud.service.ServiceOfferingVO; import com.cloud.service.dao.ServiceOfferingDao; @@ -214,6 +237,7 @@ import com.cloud.utils.db.Filter; import com.cloud.utils.db.GlobalLock; import com.cloud.utils.db.QueryBuilder; +import com.cloud.utils.db.SearchBuilder; import com.cloud.utils.db.SearchCriteria; import com.cloud.utils.db.Transaction; import com.cloud.utils.db.TransactionCallbackNoReturn; @@ -243,6 +267,8 @@ import com.cloud.vm.dao.UserVmDao; import com.cloud.vm.dao.UserVmDetailsDao; import com.cloud.vm.dao.VMInstanceDao; +import com.google.gson.JsonSyntaxException; +import com.google.gson.reflect.TypeToken; /** * VirtualNetworkApplianceManagerImpl manages the different types of virtual @@ -251,6 +277,7 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements VirtualNetworkApplianceManager, VirtualNetworkApplianceService, VirtualMachineGuru, Listener, Configurable, StateListener { private static final Logger s_logger = Logger.getLogger(VirtualNetworkApplianceManagerImpl.class); + private static final String CONNECTIVITY_TEST = "connectivity.test"; @Inject private EntityManager _entityMgr; @Inject private DataCenterDao _dcDao; @@ -272,12 +299,12 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V @Inject private AccountManager _accountMgr; @Inject private ConfigurationManager _configMgr; @Inject private ConfigurationServer _configServer; - @Inject private ServiceOfferingDao _serviceOfferingDao; + @Inject protected ServiceOfferingDao _serviceOfferingDao; @Inject private UserVmDao _userVmDao; @Inject private VMInstanceDao _vmDao; @Inject private NetworkOfferingDao _networkOfferingDao; @Inject private GuestOSDao _guestOSDao; - @Inject private NetworkOrchestrationService _networkMgr; + @Inject protected NetworkOrchestrationService _networkMgr; @Inject protected NetworkModel _networkModel; @Inject protected VirtualMachineManager _itMgr; @Inject private VpnUserDao _vpnUsersDao; @@ -303,7 +330,7 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V @Inject private NetworkService _networkSvc; @Inject private IpAddressManager _ipAddrMgr; @Inject private ConfigDepot _configDepot; - @Inject private MonitoringServiceDao _monitorServiceDao; + @Inject protected MonitoringServiceDao _monitorServiceDao; @Inject private AsyncJobManager _asyncMgr; @Inject protected VpcDao _vpcDao; @Inject protected ApiAsyncJobDispatcher _asyncDispatcher; @@ -311,6 +338,16 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V @Inject protected NetworkTopologyContext _networkTopologyContext; + @Inject private UserVmJoinDao userVmJoinDao; + @Inject private DomainRouterJoinDao domainRouterJoinDao; + @Inject private PortForwardingRulesDao portForwardingDao; + @Inject private ApplicationLoadBalancerRuleDao applicationLoadBalancerRuleDao; + @Inject private RouterHealthCheckResultDao routerHealthCheckResultDao; + @Inject private LBStickinessPolicyDao lbStickinessPolicyDao; + + @Inject private NetworkService networkService; + @Inject private VpcService vpcService; + @Autowired @Qualifier("networkHelper") protected NetworkHelper _nwHelper; @@ -496,12 +533,6 @@ public VirtualRouter rebootRouter(final long routerId, final boolean reprogramNe } } - static final ConfigKey UseExternalDnsServers = new ConfigKey(Boolean.class, "use.external.dns", "Advanced", "false", - "Bypass internal dns, use external dns1 and dns2", true, ConfigKey.Scope.Zone, null); - - static final ConfigKey routerVersionCheckEnabled = new ConfigKey("Advanced", Boolean.class, "router.version.check", "true", - "If true, router minimum required version is checked before sending command", false); - @Override public boolean configure(final String name, final Map params) throws ConfigurationException { @@ -658,7 +689,21 @@ public boolean start() { if (routerAlertsCheckInterval > 0) { _checkExecutor.scheduleAtFixedRate(new CheckRouterAlertsTask(), routerAlertsCheckInterval, routerAlertsCheckInterval, TimeUnit.SECONDS); } else { - s_logger.debug("router.alerts.check.interval - " + routerAlertsCheckInterval + " so not scheduling the router alerts checking thread"); + s_logger.debug(RouterAlertsCheckIntervalCK + "=" + routerAlertsCheckInterval + " so not scheduling the router alerts checking thread"); + } + + final int routerHealthCheckConfigRefreshInterval = RouterHealthChecksConfigRefreshInterval.value(); + if (routerHealthCheckConfigRefreshInterval > 0) { + _checkExecutor.scheduleAtFixedRate(new UpdateRouterHealthChecksConfigTask(), routerHealthCheckConfigRefreshInterval, routerHealthCheckConfigRefreshInterval, TimeUnit.MINUTES); + } else { + s_logger.debug(RouterHealthChecksConfigRefreshIntervalCK + "=" + routerHealthCheckConfigRefreshInterval + " so not scheduling the router health check data thread"); + } + + final int routerHealthChecksFetchInterval = RouterHealthChecksResultFetchInterval.value(); + if (routerHealthChecksFetchInterval > 0) { + _checkExecutor.scheduleAtFixedRate(new FetchRouterHealthChecksResultTask(), routerHealthChecksFetchInterval, routerHealthChecksFetchInterval, TimeUnit.MINUTES); + } else { + s_logger.debug(RouterHealthChecksResultFetchIntervalCK + "=" + routerHealthChecksFetchInterval + " so not scheduling the router checks fetching thread"); } return true; @@ -840,6 +885,10 @@ public void doInTransactionWithoutResult(final TransactionStatus status) { @DB protected void updateSite2SiteVpnConnectionState(final List routers) { for (final DomainRouterVO router : routers) { + if (router.getRole() == Role.INTERNAL_LB_VM) { + continue; + } + final List conns = _s2sVpnMgr.getConnectionsForRouter(router); if (conns == null || conns.isEmpty()) { continue; @@ -1186,6 +1235,599 @@ protected void pushToUpdateQueue(final List networks) throws Interrup } } + protected class FetchRouterHealthChecksResultTask extends ManagedContextRunnable { + public FetchRouterHealthChecksResultTask() { + } + + @Override + protected void runInContext() { + try { + final List routers = _routerDao.listByStateAndManagementServer(VirtualMachine.State.Running, mgmtSrvrId); + s_logger.info("Found " + routers.size() + " running routers. Fetching, analysing and updating DB for the health checks."); + if (!RouterHealthChecksEnabled.value()) { + s_logger.debug("Skipping fetching of router health check results as router.health.checks.enabled is disabled"); + return; + } + + for (final DomainRouterVO router : routers) { + GetRouterMonitorResultsAnswer answer = fetchAndUpdateRouterHealthChecks(router, false); + List failingChecks = getFailingChecks(router, answer); + handleFailingChecks(router, failingChecks); + } + } catch (final Exception ex) { + s_logger.error("Fail to complete the FetchRouterHealthChecksResultTask! ", ex); + ex.printStackTrace(); + } + } + + private List getFailingChecks(DomainRouterVO router, GetRouterMonitorResultsAnswer answer) { + + if (answer == null) { + s_logger.warn("Unable to fetch monitor results for router " + router); + resetRouterHealthChecksAndConnectivity(router.getId(), false, "Communication failed"); + return Arrays.asList(CONNECTIVITY_TEST); + } else if (!answer.getResult()) { + s_logger.warn("Failed to fetch monitor results from router " + router + " with details: " + answer.getDetails()); + resetRouterHealthChecksAndConnectivity(router.getId(), false, "Failed to fetch results with details: " + answer.getDetails()); + return Arrays.asList(CONNECTIVITY_TEST); + } else { + resetRouterHealthChecksAndConnectivity(router.getId(), true, "Successfully fetched data"); + updateDbHealthChecksFromRouterResponse(router.getId(), answer.getMonitoringResults()); + return answer.getFailingChecks(); + } + } + + private void handleFailingChecks(DomainRouterVO router, List failingChecks) { + if (failingChecks == null || failingChecks.size() == 0) { + return; + } + + String alertMessage = "Health checks failed: " + failingChecks.size() + " failing checks on router " + router.getUuid(); + _alertMgr.sendAlert(AlertType.ALERT_TYPE_DOMAIN_ROUTER, router.getDataCenterId(), router.getPodIdToDeployIn(), + alertMessage, alertMessage); + s_logger.warn(alertMessage + ". Checking failed health checks to see if router needs recreate"); + + String checkFailsToRecreateVr = RouterHealthChecksFailuresToRecreateVr.valueIn(router.getDataCenterId()); + StringBuilder failingChecksEvent = new StringBuilder(); + boolean recreateRouter = false; + for (int i = 0; i < failingChecks.size(); i++) { + String failedCheck = failingChecks.get(i); + if (i == 0) { + failingChecksEvent.append("Router ") + .append(router.getUuid()) + .append(" has failing checks: "); + } + + failingChecksEvent.append(failedCheck); + if (i < failingChecks.size() - 1) { + failingChecksEvent.append(", "); + } + + if (StringUtils.isNotBlank(checkFailsToRecreateVr) && checkFailsToRecreateVr.contains(failedCheck)) { + recreateRouter = true; + } + } + + ActionEventUtils.onActionEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, + Domain.ROOT_DOMAIN, EventTypes.EVENT_ROUTER_HEALTH_CHECKS, failingChecksEvent.toString()); + + if (recreateRouter) { + s_logger.warn("Health Check Alert: Found failing checks in " + + RouterHealthChecksFailuresToRecreateVrCK + ", attempting recreating router."); + recreateRouter(router.getId()); + } + } + } + + private DomainRouterJoinVO getAnyRouterJoinWithVpc(long routerId) { + List routerJoinVOs = domainRouterJoinDao.searchByIds(routerId); + for (DomainRouterJoinVO router : routerJoinVOs) { + if (router.getRemoved() == null && router.getVpcId() != 0) { + return router; + } + } + return null; + } + + private boolean restartVpcInDomainRouter(DomainRouterJoinVO router, User user) { + try { + s_logger.debug("Attempting restart VPC " + router.getVpcName() + " for router recreation " + router.getUuid()); + ActionEventUtils.onActionEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, + Domain.ROOT_DOMAIN, EventTypes.EVENT_ROUTER_HEALTH_CHECKS, + "Recreating router " + router.getUuid() + " by restarting VPC " + router.getVpcUuid()); + return vpcService.restartVpc(router.getVpcId(), true, false, user); + } catch (Exception e) { + s_logger.error("Failed to restart VPC for router recreation " + + router.getVpcName() + " ,router " + router.getUuid(), e); + return false; + } + } + + private DomainRouterJoinVO getAnyRouterJoinWithGuestTraffic(long routerId) { + List routerJoinVOs = domainRouterJoinDao.searchByIds(routerId); + for (DomainRouterJoinVO router : routerJoinVOs) { + if (router.getRemoved() == null && router.getTrafficType() == TrafficType.Guest) { + return router; + } + } + return null; + } + + private boolean restartGuestNetworkInDomainRouter(DomainRouterJoinVO router, User user) { + try { + s_logger.info("Attempting restart network " + router.getNetworkName() + " for router recreation " + router.getUuid()); + ActionEventUtils.onActionEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, + Domain.ROOT_DOMAIN, EventTypes.EVENT_ROUTER_HEALTH_CHECKS, + "Recreating router " + router.getUuid() + " by restarting network " + router.getNetworkUuid()); + return networkService.restartNetwork(router.getNetworkId(), true, false, user); + } catch (Exception e) { + s_logger.error("Failed to restart network " + router.getNetworkName() + + " for router recreation " + router.getNetworkName(), e); + return false; + } + } + + /** + * Attempts recreation of router by restarting with cleanup a VPC if any or a guest network associated in case no VPC. + * @param routerId - the id of the router to be recreated. + * @return true if successfully restart is attempted else false. + */ + private boolean recreateRouter(long routerId) { + User systemUser = _userDao.getUser(User.UID_SYSTEM); + + // Find any VPC containing router join VO, restart it and return + DomainRouterJoinVO routerJoinToRestart = getAnyRouterJoinWithVpc(routerId); + if (routerJoinToRestart != null) { + return restartVpcInDomainRouter(routerJoinToRestart, systemUser); + } + + // If no VPC containing router join VO was found we look for a guest network traffic containing join VO and restart that. + routerJoinToRestart = getAnyRouterJoinWithGuestTraffic(routerId); + if (routerJoinToRestart != null) { + return restartGuestNetworkInDomainRouter(routerJoinToRestart, systemUser); + } + + s_logger.warn("Unable to find a valid guest network or VPC to restart for recreating router id " + routerId); + return false; + } + + private Map> getHealthChecksFromDb(long routerId) { + List healthChecksList = routerHealthCheckResultDao.getHealthCheckResults(routerId); + Map> healthCheckResults = new HashMap<>(); + if (healthChecksList.isEmpty()) { + return healthCheckResults; + } + + for (RouterHealthCheckResultVO healthCheck : healthChecksList) { + if (!healthCheckResults.containsKey(healthCheck.getCheckType())) { + healthCheckResults.put(healthCheck.getCheckType(), new HashMap<>()); + } + healthCheckResults.get(healthCheck.getCheckType()).put(healthCheck.getCheckName(), healthCheck); + } + + return healthCheckResults; + } + + private RouterHealthCheckResultVO resetRouterHealthChecksAndConnectivity(final long routerId, boolean connected, String message) { + routerHealthCheckResultDao.expungeHealthChecks(routerId); + boolean newEntry = false; + RouterHealthCheckResultVO connectivityVO = routerHealthCheckResultDao.getRouterHealthCheckResult(routerId, CONNECTIVITY_TEST, "basic"); + if (connectivityVO == null) { + connectivityVO = new RouterHealthCheckResultVO(routerId, CONNECTIVITY_TEST, "basic"); + newEntry = true; + } + + connectivityVO.setCheckResult(connected); + connectivityVO.setLastUpdateTime(new Date()); + if (StringUtils.isNotEmpty(message)) { + connectivityVO.setCheckDetails(message.getBytes(com.cloud.utils.StringUtils.getPreferredCharset())); + } + + if (newEntry) { + routerHealthCheckResultDao.persist(connectivityVO); + } else { + routerHealthCheckResultDao.update(connectivityVO.getId(), connectivityVO); + } + + return routerHealthCheckResultDao.getRouterHealthCheckResult(routerId, CONNECTIVITY_TEST, "basic"); + } + + private RouterHealthCheckResultVO parseHealthCheckVOFromJson(final long routerId, + final String checkName, final String checkType, final Map checkData, + final Map> checksInDb) { + boolean success = Boolean.parseBoolean(checkData.get("success")); + Date lastUpdate = new Date(Long.parseLong(checkData.get("lastUpdate"))); + double lastRunDuration = Double.parseDouble(checkData.get("lastRunDuration")); + String message = checkData.get("message"); + final RouterHealthCheckResultVO hcVo; + boolean newEntry = false; + if (checksInDb.containsKey(checkType) && checksInDb.get(checkType).containsKey(checkName)) { + hcVo = checksInDb.get(checkType).get(checkName); + } else { + hcVo = new RouterHealthCheckResultVO(routerId, checkName, checkType); + newEntry = true; + } + + hcVo.setCheckResult(success); + hcVo.setLastUpdateTime(lastUpdate); + if (StringUtils.isNotEmpty(message)) { + hcVo.setCheckDetails(message.getBytes(com.cloud.utils.StringUtils.getPreferredCharset())); + } + + if (newEntry) { + routerHealthCheckResultDao.persist(hcVo); + } else { + routerHealthCheckResultDao.update(hcVo.getId(), hcVo); + } + s_logger.info("Found health check " + hcVo + " which took running duration (ms) " + lastRunDuration); + return hcVo; + } + + /** + * + * @param checksJson JSON expected is + * { + * checkType1: { + * checkName1: { + * success: true/false, + * lastUpdate: date string, + * lastRunDuration: ms spent on test, + * message: detailed message from check execution + * }, + * checkType2: ..... + * }, + * checkType2: ...... + * } + * @return converts the above JSON into list of RouterHealthCheckResult. + */ + private List parseHealthCheckResults( + final Map>> checksJson, final long routerId) { + final Map> checksInDb = getHealthChecksFromDb(routerId); + List healthChecks = new ArrayList<>(); + final String lastRunKey = "lastRun"; + for (String checkType : checksJson.keySet()) { + if (checksJson.get(checkType).containsKey(lastRunKey)) { // Log last run of this check type run info + Map lastRun = checksJson.get(checkType).get(lastRunKey); + s_logger.info("Found check types executed on VR " + checkType + ", start: " + lastRun.get("start") + + ", end: " + lastRun.get("end") + ", duration: " + lastRun.get("duration")); + } + + for (String checkName : checksJson.get(checkType).keySet()) { + if (lastRunKey.equals(checkName)) { + continue; + } + + try { + final RouterHealthCheckResultVO hcVo = parseHealthCheckVOFromJson( + routerId, checkName, checkType, checksJson.get(checkType).get(checkName), checksInDb); + healthChecks.add(hcVo); + } catch (Exception ex) { + s_logger.error("Skipping health check: Exception while parsing check result data for router id " + routerId + + ", check type: " + checkType + ", check name: " + checkName + ":" + ex.getLocalizedMessage(), ex); + } + } + } + return healthChecks; + } + + private List updateDbHealthChecksFromRouterResponse(final long routerId, final String monitoringResult) { + if (StringUtils.isBlank(monitoringResult)) { + s_logger.warn("Attempted parsing empty monitoring results string for router " + routerId); + return Collections.emptyList(); + } + + try { + s_logger.debug("Parsing and updating DB health check data for router: " + routerId + " with data: " + monitoringResult) ; + final Type t = new TypeToken>>>() {}.getType(); + final Map>> checks = GsonHelper.getGson().fromJson(monitoringResult, t); + return parseHealthCheckResults(checks, routerId); + } catch (JsonSyntaxException ex) { + s_logger.error("Unable to parse the result of health checks due to " + ex.getLocalizedMessage(), ex); + } + + return Collections.emptyList(); + } + + private GetRouterMonitorResultsAnswer fetchAndUpdateRouterHealthChecks(DomainRouterVO router, boolean performFreshChecks) { + if (!RouterHealthChecksEnabled.value()) { + return null; + } + + String controlIP = getRouterControlIP(router); + if (StringUtils.isNotBlank(controlIP) && !controlIP.equals("0.0.0.0")) { + final GetRouterMonitorResultsCommand command = new GetRouterMonitorResultsCommand(performFreshChecks); + command.setAccessDetail(NetworkElementCommand.ROUTER_IP, controlIP); + command.setAccessDetail(NetworkElementCommand.ROUTER_NAME, router.getInstanceName()); + try { + final Answer answer = _agentMgr.easySend(router.getHostId(), command); + + if (answer == null) { + s_logger.warn("Unable to fetch monitoring results data from router " + router.getHostName()); + return null; + } + if (answer instanceof GetRouterMonitorResultsAnswer) { + return (GetRouterMonitorResultsAnswer) answer; + } else { + s_logger.warn("Unable to fetch health checks results to router " + router.getHostName() + " Received answer " + answer.getDetails()); + return new GetRouterMonitorResultsAnswer(command, false, null, answer.getDetails()); + } + } catch (final Exception e) { + s_logger.warn("Error while collecting alerts from router: " + router.getInstanceName(), e); + return null; + } + } + + return null; + } + + @Override + public boolean performRouterHealthChecks(long routerId) { + DomainRouterVO router = _routerDao.findById(routerId); + + if (router == null) { + throw new CloudRuntimeException("Unable to find router with id " + routerId); + } + + if (!RouterHealthChecksEnabled.value()) { + throw new CloudRuntimeException("Router health checks are not enabled for router: " + router); + } + + s_logger.info("Running health check results for router " + router.getUuid()); + + final GetRouterMonitorResultsAnswer answer; + boolean success = true; + // Step 1: Update health check data on router and perform and retrieve health checks on router + if (!updateRouterHealthChecksConfig(router)) { + s_logger.warn("Unable to update health check config for fresh run successfully for router: " + router + ", so trying to fetch last result."); + success = false; + answer = fetchAndUpdateRouterHealthChecks(router, false); + } else { + s_logger.info("Successfully updated health check config for fresh run successfully for router: " + router); + answer = fetchAndUpdateRouterHealthChecks(router, true); + } + + // Step 2: Update health checks values in database. We do this irrespective of new health check config. + if (answer == null || !answer.getResult()) { + success = false; + resetRouterHealthChecksAndConnectivity(routerId, false, + answer == null ? "Communication failed " : "Failed to fetch results with details: " + answer.getDetails()); + } else { + resetRouterHealthChecksAndConnectivity(routerId, true, "Successfully fetched data"); + updateDbHealthChecksFromRouterResponse(routerId, answer.getMonitoringResults()); + } + + return success; + } + + protected class UpdateRouterHealthChecksConfigTask extends ManagedContextRunnable { + public UpdateRouterHealthChecksConfigTask() { + } + + @Override + protected void runInContext() { + try { + final List routers = _routerDao.listByStateAndManagementServer(VirtualMachine.State.Running, mgmtSrvrId); + s_logger.debug("Found " + routers.size() + " running routers. "); + + for (final DomainRouterVO router : routers) { + updateRouterHealthChecksConfig(router); + } + } catch (final Exception ex) { + s_logger.error("Fail to complete the UpdateRouterHealthChecksConfigTask! ", ex); + } + } + } + + private SetMonitorServiceCommand createMonitorServiceCommand(DomainRouterVO router, List services, + boolean reconfigure, boolean deleteFromProcessedCache) { + final SetMonitorServiceCommand command = new SetMonitorServiceCommand(services); + command.setAccessDetail(NetworkElementCommand.ROUTER_IP, getRouterControlIP(router)); + command.setAccessDetail(NetworkElementCommand.ROUTER_NAME, router.getInstanceName()); + command.setAccessDetail(SetMonitorServiceCommand.ROUTER_HEALTH_CHECKS_ENABLED, RouterHealthChecksEnabled.value().toString()); + command.setAccessDetail(SetMonitorServiceCommand.ROUTER_HEALTH_CHECKS_BASIC_INTERVAL, RouterHealthChecksBasicInterval.value().toString()); + command.setAccessDetail(SetMonitorServiceCommand.ROUTER_HEALTH_CHECKS_ADVANCED_INTERVAL, RouterHealthChecksAdvancedInterval.value().toString()); + command.setAccessDetail(SetMonitorServiceCommand.ROUTER_HEALTH_CHECKS_EXCLUDED, RouterHealthChecksToExclude.valueIn(router.getDataCenterId())); + command.setHealthChecksConfig(getRouterHealthChecksConfig(router)); + command.setReconfigureAfterUpdate(reconfigure); + command.setDeleteFromProcessedCache(deleteFromProcessedCache); // As part of updating + return command; + } + + /** + * Updates router health check config to the virtual router that it uses for health checks. + * @param router - the router ID that data needs to be sent to. + * @return success of whether data was sent or not + */ + private boolean updateRouterHealthChecksConfig(DomainRouterVO router) { + if (!RouterHealthChecksEnabled.value()) { + return false; + } + + SetMonitorServiceCommand command = createMonitorServiceCommand(router, null,true, true); + String controlIP = getRouterControlIP(router); + if (StringUtils.isBlank(controlIP) || controlIP.equals("0.0.0.0")) { + s_logger.debug("Skipping update data on router " + router.getUuid() + " because controlIp is not correct."); + return false; + } + + s_logger.info("Updating data for router health checks for router " + router.getUuid()); + Answer origAnswer = null; + try { + origAnswer = _agentMgr.easySend(router.getHostId(), command); + } catch (final Exception e) { + s_logger.error("Error while sending update data for health check to router: " + router.getInstanceName(), e); + return false; + } + + if (origAnswer == null) { + s_logger.error("Unable to update health checks data to router " + router.getHostName()); + return false; + } + + GroupAnswer answer = null; + if (origAnswer instanceof GroupAnswer) { + answer = (GroupAnswer) origAnswer; + } else { + s_logger.error("Unable to update health checks data to router " + router.getHostName() + " Received answer " + origAnswer.getDetails()); + return false; + } + + if (!answer.getResult()) { + s_logger.error("Unable to update health checks data to router " + router.getHostName() + ", details : " + answer.getDetails()); + } + + return answer.getResult(); + } + + private String getSystemThresholdsHealthChecksData(final DomainRouterVO router) { + return new StringBuilder() + .append("minDiskNeeded=" + RouterHealthChecksFreeDiskSpaceThreshold.valueIn(router.getDataCenterId())) + .append(",maxCpuUsage=" + RouterHealthChecksMaxCpuUsageThreshold.valueIn(router.getDataCenterId())) + .append(",maxMemoryUsage=" + RouterHealthChecksMaxMemoryUsageThreshold.valueIn(router.getDataCenterId()) + ";") + .toString(); + } + + private String getRouterVersionHealthChecksData(final DomainRouterVO router) { + if (router.getTemplateVersion() != null && router.getScriptsVersion() != null) { + StringBuilder routerVersion = new StringBuilder() + .append("templateVersion=" + router.getTemplateVersion()) + .append(",scriptsVersion=" + router.getScriptsVersion()); + return routerVersion.toString(); + } + return null; + } + + private void updateWithPortForwardingRules(final DomainRouterJoinVO routerJoinVO, final UserVmJoinVO vm, final StringBuilder portData) { + SearchBuilder sbpf = portForwardingDao.createSearchBuilder(); + sbpf.and("networkId", sbpf.entity().getNetworkId(), SearchCriteria.Op.EQ); + sbpf.and("instanceId", sbpf.entity().getVirtualMachineId(), SearchCriteria.Op.EQ); + SearchCriteria scpf = sbpf.create(); + scpf.setParameters("networkId", routerJoinVO.getNetworkId()); + scpf.setParameters("instanceId", vm.getId()); + List portForwardingRules = portForwardingDao.search(scpf, null); + for (PortForwardingRuleVO portForwardingRule : portForwardingRules) { + portData.append("sourceIp=").append(_ipAddressDao.findById(portForwardingRule.getSourceIpAddressId()).getAddress().toString()) + .append(",sourcePortStart=").append(portForwardingRule.getSourcePortStart()) + .append(",sourcePortEnd=").append(portForwardingRule.getSourcePortEnd()) + .append(",destIp=").append(portForwardingRule.getDestinationIpAddress()) + .append(",destPortStart=").append(portForwardingRule.getDestinationPortStart()) + .append(",destPortEnd=").append(portForwardingRule.getDestinationPortEnd()).append(";"); + } + } + + private String getStickinessPolicies(long loadBalancingRuleId) { + List stickinessPolicyVOs = lbStickinessPolicyDao.listByLoadBalancerId(loadBalancingRuleId, false); + if (stickinessPolicyVOs != null && stickinessPolicyVOs.size() > 0) { + StringBuilder stickiness = new StringBuilder(); + for (LBStickinessPolicyVO stickinessVO : stickinessPolicyVOs) { + stickiness.append(stickinessVO.getMethodName()).append(" "); + } + return stickiness.toString().trim(); + } + return "None"; + } + + private void updateWithLbRules(final DomainRouterJoinVO routerJoinVO, final StringBuilder loadBalancingData) { + List loadBalancerVOs = this.getLBRules(routerJoinVO); + for (FirewallRuleVO firewallRuleVO : loadBalancerVOs) { + List vmMapVOs = _loadBalancerVMMapDao.listByLoadBalancerId(firewallRuleVO.getId(), false); + if (vmMapVOs.size() > 0) { + + final NetworkOffering offering = _networkOfferingDao.findById(_networkDao.findById(routerJoinVO.getNetworkId()).getNetworkOfferingId()); + if (offering.getConcurrentConnections() == null) { + loadBalancingData.append("maxconn=").append(_configDao.getValue(Config.NetworkLBHaproxyMaxConn.key())); + } else { + loadBalancingData.append("maxconn=").append(offering.getConcurrentConnections().toString()); + } + + loadBalancingData.append(",sourcePortStart=").append(firewallRuleVO.getSourcePortStart()) + .append(",sourcePortEnd=").append(firewallRuleVO.getSourcePortEnd()); + if (firewallRuleVO instanceof LoadBalancerVO) { + LoadBalancerVO loadBalancerVO = (LoadBalancerVO) firewallRuleVO; + loadBalancingData.append(",sourceIp=").append(_ipAddressDao.findById(loadBalancerVO.getSourceIpAddressId()).getAddress().toString()) + .append(",destPortStart=").append(loadBalancerVO.getDefaultPortStart()) + .append(",destPortEnd=").append(loadBalancerVO.getDefaultPortEnd()) + .append(",algorithm=").append(loadBalancerVO.getAlgorithm()) + .append(",protocol=").append(loadBalancerVO.getLbProtocol()); + } else if (firewallRuleVO instanceof ApplicationLoadBalancerRuleVO) { + ApplicationLoadBalancerRuleVO appLoadBalancerVO = (ApplicationLoadBalancerRuleVO) firewallRuleVO; + loadBalancingData.append(",sourceIp=").append(appLoadBalancerVO.getSourceIp()) + .append(",destPortStart=").append(appLoadBalancerVO.getDefaultPortStart()) + .append(",destPortEnd=").append(appLoadBalancerVO.getDefaultPortEnd()) + .append(",algorithm=").append(appLoadBalancerVO.getAlgorithm()) + .append(",protocol=").append(appLoadBalancerVO.getLbProtocol()); + } + loadBalancingData.append(",stickiness=").append(getStickinessPolicies(firewallRuleVO.getId())); + loadBalancingData.append(",keepAliveEnabled=").append(offering.isKeepAliveEnabled()).append(",vmIps="); + for (LoadBalancerVMMapVO vmMapVO : vmMapVOs) { + loadBalancingData.append(vmMapVO.getInstanceIp()).append(" "); + } + loadBalancingData.setCharAt(loadBalancingData.length() - 1, ';'); + } + } + } + + private Map getRouterHealthChecksConfig(final DomainRouterVO router) { + Map data = new HashMap<>(); + List routerJoinVOs = domainRouterJoinDao.searchByIds(router.getId()); + StringBuilder vmsData = new StringBuilder(); + StringBuilder portData = new StringBuilder(); + StringBuilder loadBalancingData = new StringBuilder(); + StringBuilder gateways = new StringBuilder(); + gateways.append("gatewaysIps="); + for (DomainRouterJoinVO routerJoinVO : routerJoinVOs) { + if (StringUtils.isNotBlank(routerJoinVO.getGateway())) { + gateways.append(routerJoinVO.getGateway() + " "); + } + SearchBuilder sbvm = userVmJoinDao.createSearchBuilder(); + sbvm.and("networkId", sbvm.entity().getNetworkId(), SearchCriteria.Op.EQ); + SearchCriteria scvm = sbvm.create(); + scvm.setParameters("networkId", routerJoinVO.getNetworkId()); + List vms = userVmJoinDao.search(scvm, null); + for (UserVmJoinVO vm : vms) { + if (vm.getState() != VirtualMachine.State.Running) { + continue; + } + + vmsData.append("vmName=").append(vm.getName()) + .append(",macAddress=").append(vm.getMacAddress()) + .append(",ip=").append(vm.getIpAddress()).append(";"); + updateWithPortForwardingRules(routerJoinVO, vm, portData); + } + updateWithLbRules(routerJoinVO, loadBalancingData); + } + + String routerVersion = getRouterVersionHealthChecksData(router); + data.put("virtualMachines", vmsData.toString()); + data.put("gateways", gateways.toString()); + data.put("portForwarding", portData.toString()); + data.put("haproxyData", loadBalancingData.toString()); + data.put("systemThresholds", getSystemThresholdsHealthChecksData(router)); + if (routerVersion != null) { + data.put("routerVersion", routerVersion); + } + return data; + } + + private List getLBRules(final DomainRouterJoinVO router) { + if (router.getRole() == Role.VIRTUAL_ROUTER) { + SearchBuilder sblb = _loadBalancerDao.createSearchBuilder(); + sblb.and("networkId", sblb.entity().getNetworkId(), SearchCriteria.Op.EQ); + sblb.and("sourceIpAddressId", sblb.entity().getSourceIpAddressId(), SearchCriteria.Op.NNULL); + SearchCriteria sclb = sblb.create(); + sclb.setParameters("networkId", router.getNetworkId()); + return _loadBalancerDao.search(sclb, null); + } else if (router.getRole() == Role.INTERNAL_LB_VM) { + SearchBuilder sbalb = applicationLoadBalancerRuleDao.createSearchBuilder(); + sbalb.and("networkId", sbalb.entity().getNetworkId(), SearchCriteria.Op.EQ); + sbalb.and("sourceIpAddress", sbalb.entity().getSourceIp(), SearchCriteria.Op.NNULL); + SearchCriteria sclb = sbalb.create(); + sclb.setParameters("networkId", router.getNetworkId()); + return applicationLoadBalancerRuleDao.search(sclb, null); + } + return Collections.emptyList(); + } + protected class CheckRouterAlertsTask extends ManagedContextRunnable { public CheckRouterAlertsTask() { } @@ -1205,12 +1847,11 @@ protected void getRouterAlerts() { final List routers = _routerDao.listByStateAndManagementServer(VirtualMachine.State.Running, mgmtSrvrId); s_logger.debug("Found " + routers.size() + " running routers. "); - for (final DomainRouterVO router : routers) { final String serviceMonitoringFlag = SetServiceMonitor.valueIn(router.getDataCenterId()); // Skip the routers in VPC network or skip the routers where // Monitor service is not enabled in the corresponding Zone - if (!Boolean.parseBoolean(serviceMonitoringFlag) || router.getVpcId() != null) { + if (!Boolean.parseBoolean(serviceMonitoringFlag)) { continue; } String controlIP = getRouterControlIP(router); @@ -1253,7 +1894,7 @@ protected void getRouterAlerts() { final String alerts[] = answer.getAlerts(); if (alerts != null) { final String lastAlertTimeStamp = answer.getTimeStamp(); - final SimpleDateFormat sdfrmt = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); + final SimpleDateFormat sdfrmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); sdfrmt.setLenient(false); try { sdfrmt.parse(lastAlertTimeStamp); @@ -1667,19 +2308,7 @@ public boolean finalizeCommandsOnStart(final Commands cmds, final VirtualMachine if (reprogramGuestNtwks) { finalizeIpAssocForNetwork(cmds, router, provider, guestNetworkId, null); finalizeNetworkRulesForNetwork(cmds, router, provider, guestNetworkId); - - final NetworkOffering offering = _networkOfferingDao.findById(_networkDao.findById(guestNetworkId).getNetworkOfferingId()); - // service monitoring is currently not added in RVR - if (!offering.isRedundantRouter()) { - final String serviceMonitringSet = _configDao.getValue(Config.EnableServiceMonitoring.key()); - - if (serviceMonitringSet != null && serviceMonitringSet.equalsIgnoreCase("true")) { - finalizeMonitorServiceOnStrat(cmds, profile, router, provider, guestNetworkId, true); - } else { - finalizeMonitorServiceOnStrat(cmds, profile, router, provider, guestNetworkId, false); - } - } - + finalizeMonitorService(cmds, profile, router, provider, guestNetworkId, true); } finalizeUserDataAndDhcpOnStart(cmds, router, provider, guestNetworkId); @@ -1692,31 +2321,38 @@ public boolean finalizeCommandsOnStart(final Commands cmds, final VirtualMachine return true; } - private void finalizeMonitorServiceOnStrat(final Commands cmds, final VirtualMachineProfile profile, final DomainRouterVO router, final Provider provider, - final long networkId, final Boolean add) { + protected void finalizeMonitorService(final Commands cmds, final VirtualMachineProfile profile, final DomainRouterVO router, final Provider provider, + final long networkId, boolean onStart) { + final NetworkOffering offering = _networkOfferingDao.findById(_networkDao.findById(networkId).getNetworkOfferingId()); + if (offering.isRedundantRouter()) { + // service monitoring is currently not added in RVR + return; + } + final String serviceMonitoringSet = _configDao.getValue(Config.EnableServiceMonitoring.key()); + final Boolean isMonitoringServicesEnabled = serviceMonitoringSet != null && serviceMonitoringSet.equalsIgnoreCase("true"); final NetworkVO network = _networkDao.findById(networkId); s_logger.debug("Creating monitoring services on " + router + " start..."); // get the list of sevices for this network to monitor final List services = new ArrayList(); - if (_networkModel.isProviderSupportServiceInNetwork(network.getId(), Service.Dhcp, Provider.VirtualRouter) - || _networkModel.isProviderSupportServiceInNetwork(network.getId(), Service.Dns, Provider.VirtualRouter)) { + if (_networkModel.isProviderSupportServiceInNetwork(network.getId(), Service.Dhcp, provider) + || _networkModel.isProviderSupportServiceInNetwork(network.getId(), Service.Dns, provider)) { final MonitoringServiceVO dhcpService = _monitorServiceDao.getServiceByName(MonitoringService.Service.Dhcp.toString()); if (dhcpService != null) { services.add(dhcpService); } } - if (_networkModel.isProviderSupportServiceInNetwork(network.getId(), Service.Lb, Provider.VirtualRouter)) { + if (_networkModel.isProviderSupportServiceInNetwork(network.getId(), Service.Lb, provider)) { final MonitoringServiceVO lbService = _monitorServiceDao.getServiceByName(MonitoringService.Service.LoadBalancing.toString()); if (lbService != null) { services.add(lbService); } } - final List defaultServices = _monitorServiceDao.listDefaultServices(true); - services.addAll(defaultServices); + + services.addAll(getDefaultServicesToMonitor(network)); final List servicesTO = new ArrayList(); for (final MonitoringServiceVO service : services) { @@ -1734,17 +2370,21 @@ private void finalizeMonitorServiceOnStrat(final Commands cmds, final VirtualMac if (controlNic == null) { throw new CloudRuntimeException("VirtualMachine " + profile.getInstanceName() + " doesn't have a control interface"); } - final SetMonitorServiceCommand command = new SetMonitorServiceCommand(servicesTO); - command.setAccessDetail(NetworkElementCommand.ROUTER_IP, controlNic.getIPv4Address()); - command.setAccessDetail(NetworkElementCommand.ROUTER_GUEST_IP, _routerControlHelper.getRouterIpInNetwork(networkId, router.getId())); - command.setAccessDetail(NetworkElementCommand.ROUTER_NAME, router.getInstanceName()); - if (!add) { - command.setAccessDetail(NetworkElementCommand.ROUTER_MONITORING_ENABLE, add.toString()); + // As part of aggregate command we don't need to reconfigure if onStart and persist in processed cache. Subsequent updates are not needed. + SetMonitorServiceCommand command = createMonitorServiceCommand(router, servicesTO, !onStart, false); + command.setAccessDetail(NetworkElementCommand.ROUTER_GUEST_IP, _routerControlHelper.getRouterIpInNetwork(networkId, router.getId())); + if (!isMonitoringServicesEnabled) { + command.setAccessDetail(SetMonitorServiceCommand.ROUTER_MONITORING_ENABLED, isMonitoringServicesEnabled.toString()); } + cmds.addCommand("monitor", command); } + protected List getDefaultServicesToMonitor(final NetworkVO network) { + return _monitorServiceDao.listDefaultServices(true); + } + protected NicProfile getControlNic(final VirtualMachineProfile profile) { final DomainRouterVO router = _routerDao.findById(profile.getId()); final DataCenterVO dcVo = _dcDao.findById(router.getDataCenterId()); @@ -2599,7 +3239,22 @@ public String getConfigComponentName() { @Override public ConfigKey[] getConfigKeys() { - return new ConfigKey[] { UseExternalDnsServers, routerVersionCheckEnabled, SetServiceMonitor, RouterAlertsCheckInterval }; + return new ConfigKey[] { + UseExternalDnsServers, + RouterVersionCheckEnabled, + SetServiceMonitor, + RouterAlertsCheckInterval, + RouterHealthChecksEnabled, + RouterHealthChecksBasicInterval, + RouterHealthChecksAdvancedInterval, + RouterHealthChecksConfigRefreshInterval, + RouterHealthChecksResultFetchInterval, + RouterHealthChecksFailuresToRecreateVr, + RouterHealthChecksToExclude, + RouterHealthChecksFreeDiskSpaceThreshold, + RouterHealthChecksMaxCpuUsageThreshold, + RouterHealthChecksMaxMemoryUsageThreshold + }; } @Override diff --git a/server/src/main/java/com/cloud/network/router/VpcVirtualNetworkApplianceManager.java b/server/src/main/java/com/cloud/network/router/VpcVirtualNetworkApplianceManager.java index c6181e9851ae..8c661c798a4c 100644 --- a/server/src/main/java/com/cloud/network/router/VpcVirtualNetworkApplianceManager.java +++ b/server/src/main/java/com/cloud/network/router/VpcVirtualNetworkApplianceManager.java @@ -74,4 +74,11 @@ public interface VpcVirtualNetworkApplianceManager extends VirtualNetworkApplian * @throws ResourceUnavailableException */ boolean stopRemoteAccessVpn(RemoteAccessVpn vpn, VirtualRouter router) throws ResourceUnavailableException; -} \ No newline at end of file + + /** + * @param router + * @return + * @throws ResourceUnavailableException + */ + boolean startSite2SiteVpn(DomainRouterVO router) throws ResourceUnavailableException; +} diff --git a/server/src/main/java/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImpl.java b/server/src/main/java/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImpl.java index 80b1797e8485..e9d32a2152b1 100644 --- a/server/src/main/java/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImpl.java +++ b/server/src/main/java/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImpl.java @@ -18,6 +18,7 @@ import java.net.URI; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.Iterator; import java.util.List; @@ -26,6 +27,9 @@ import javax.inject.Inject; import javax.naming.ConfigurationException; +import org.apache.log4j.Logger; +import org.springframework.stereotype.Component; + import com.cloud.agent.api.Answer; import com.cloud.agent.api.Command; import com.cloud.agent.api.Command.OnError; @@ -34,6 +38,7 @@ import com.cloud.agent.api.SetupGuestNetworkCommand; import com.cloud.agent.api.routing.AggregationControlCommand; import com.cloud.agent.api.routing.AggregationControlCommand.Action; +import com.cloud.agent.api.to.VirtualMachineTO; import com.cloud.agent.manager.Commands; import com.cloud.dc.DataCenter; import com.cloud.deploy.DeployDestination; @@ -42,7 +47,11 @@ import com.cloud.exception.InsufficientCapacityException; import com.cloud.exception.OperationTimedoutException; import com.cloud.exception.ResourceUnavailableException; +import com.cloud.hypervisor.Hypervisor; +import com.cloud.hypervisor.HypervisorGuru; +import com.cloud.hypervisor.HypervisorGuruManager; import com.cloud.network.IpAddress; +import com.cloud.network.MonitoringService; import com.cloud.network.Network; import com.cloud.network.Network.Provider; import com.cloud.network.Network.Service; @@ -54,7 +63,10 @@ import com.cloud.network.VirtualRouterProvider; import com.cloud.network.addr.PublicIp; import com.cloud.network.dao.IPAddressVO; +import com.cloud.network.dao.MonitoringServiceVO; +import com.cloud.network.dao.NetworkVO; import com.cloud.network.dao.RemoteAccessVpnVO; +import com.cloud.network.dao.Site2SiteVpnConnectionVO; import com.cloud.network.vpc.NetworkACLItemDao; import com.cloud.network.vpc.NetworkACLItemVO; import com.cloud.network.vpc.NetworkACLManager; @@ -72,6 +84,9 @@ import com.cloud.network.vpc.dao.StaticRouteDao; import com.cloud.network.vpc.dao.VpcGatewayDao; import com.cloud.network.vpn.Site2SiteVpnManager; +import com.cloud.service.ServiceOfferingVO; +import com.cloud.template.VirtualMachineTemplate; +import com.cloud.user.Account; import com.cloud.user.UserStatisticsVO; import com.cloud.utils.Pair; import com.cloud.utils.db.EntityManager; @@ -87,14 +102,8 @@ import com.cloud.vm.VirtualMachine.State; import com.cloud.vm.VirtualMachineProfile; import com.cloud.vm.VirtualMachineProfile.Param; +import com.cloud.vm.VirtualMachineProfileImpl; import com.cloud.vm.dao.VMInstanceDao; -import com.cloud.agent.api.to.VirtualMachineTO; -import com.cloud.hypervisor.Hypervisor; -import com.cloud.hypervisor.HypervisorGuru; -import com.cloud.hypervisor.HypervisorGuruManager; - -import org.apache.log4j.Logger; -import org.springframework.stereotype.Component; @Component public class VpcVirtualNetworkApplianceManagerImpl extends VirtualNetworkApplianceManagerImpl implements VpcVirtualNetworkApplianceManager { @@ -151,8 +160,9 @@ public boolean addVpcRouterToGuestNetwork(final VirtualRouter router, final Netw result = false; } // 3) apply networking rules - if (result && params.get(Param.ReProgramGuestNetworks) != null && (Boolean) params.get(Param.ReProgramGuestNetworks) == true) { - sendNetworkRulesToRouter(router.getId(), network.getId()); + if (result) { + boolean reprogramNetwork = params != null && params.get(Param.ReProgramGuestNetworks) != null && (Boolean) params.get(Param.ReProgramGuestNetworks) == true; + sendNetworkRulesToRouter(router.getId(), network.getId(), reprogramNetwork); } } catch (final Exception ex) { s_logger.warn("Failed to add router " + router + " to network " + network + " due to ", ex); @@ -454,19 +464,25 @@ public boolean finalizeCommandsOnStart(final Commands cmds, final VirtualMachine throw new CloudRuntimeException("Cannot find related provider of virtual router provider: " + vrProvider.getType().toString()); } + if (reprogramGuestNtwks && publicNics.size() > 0) { + finalizeMonitorService(cmds, profile, domainRouterVO, provider, publicNics.get(0).second().getId(), true); + } + for (final Pair nicNtwk : guestNics) { final Nic guestNic = nicNtwk.first(); + final long guestNetworkId = guestNic.getNetworkId(); final AggregationControlCommand startCmd = new AggregationControlCommand(Action.Start, domainRouterVO.getInstanceName(), controlNic.getIPv4Address(), _routerControlHelper.getRouterIpInNetwork( - guestNic.getNetworkId(), domainRouterVO.getId())); + guestNetworkId, domainRouterVO.getId())); cmds.addCommand(startCmd); if (reprogramGuestNtwks) { - finalizeIpAssocForNetwork(cmds, domainRouterVO, provider, guestNic.getNetworkId(), vlanMacAddress); - finalizeNetworkRulesForNetwork(cmds, domainRouterVO, provider, guestNic.getNetworkId()); + finalizeIpAssocForNetwork(cmds, domainRouterVO, provider, guestNetworkId, vlanMacAddress); + finalizeNetworkRulesForNetwork(cmds, domainRouterVO, provider, guestNetworkId); + finalizeMonitorService(cmds, profile, domainRouterVO, provider, guestNetworkId, true); } - finalizeUserDataAndDhcpOnStart(cmds, domainRouterVO, provider, guestNic.getNetworkId()); + finalizeUserDataAndDhcpOnStart(cmds, domainRouterVO, provider, guestNetworkId); final AggregationControlCommand finishCmd = new AggregationControlCommand(Action.Finish, domainRouterVO.getInstanceName(), controlNic.getIPv4Address(), _routerControlHelper.getRouterIpInNetwork( - guestNic.getNetworkId(), domainRouterVO.getId())); + guestNetworkId, domainRouterVO.getId())); cmds.addCommand(finishCmd); } @@ -476,6 +492,14 @@ public boolean finalizeCommandsOnStart(final Commands cmds, final VirtualMachine return true; } + @Override + protected List getDefaultServicesToMonitor(NetworkVO network) { + if (network.getTrafficType() == TrafficType.Public) { + return Arrays.asList(_monitorServiceDao.getServiceByName(MonitoringService.Service.Ssh.toString())); + } + return super.getDefaultServicesToMonitor(network); + } + @Override protected void finalizeNetworkRulesForNetwork(final Commands cmds, final DomainRouterVO domainRouterVO, final Provider provider, final Long guestNetworkId) { @@ -495,7 +519,7 @@ protected void finalizeNetworkRulesForNetwork(final Commands cmds, final DomainR } } - protected boolean sendNetworkRulesToRouter(final long routerId, final long networkId) throws ResourceUnavailableException { + protected boolean sendNetworkRulesToRouter(final long routerId, final long networkId, final boolean reprogramNetwork) throws ResourceUnavailableException { final DomainRouterVO router = _routerDao.findById(routerId); final Commands cmds = new Commands(OnError.Continue); @@ -508,10 +532,26 @@ protected boolean sendNetworkRulesToRouter(final long routerId, final long netwo throw new CloudRuntimeException("Cannot find related provider of virtual router provider: " + vrProvider.getType().toString()); } - finalizeNetworkRulesForNetwork(cmds, router, provider, networkId); + if (reprogramNetwork) { + finalizeNetworkRulesForNetwork(cmds, router, provider, networkId); + } + + finalizeMonitorService(cmds, getVirtualMachineProfile(router), router, provider, networkId, false); + return _nwHelper.sendCommandsToRouter(router, cmds); } + private VirtualMachineProfile getVirtualMachineProfile(DomainRouterVO router) { + final ServiceOfferingVO offering = _serviceOfferingDao.findById(router.getId(), router.getServiceOfferingId()); + final VirtualMachineTemplate template = _entityMgr.findByIdIncludingRemoved(VirtualMachineTemplate.class, router.getTemplateId()); + final Account owner = _entityMgr.findById(Account.class, router.getAccountId()); + final VirtualMachineProfileImpl profile = new VirtualMachineProfileImpl(router, template, offering, owner, null); + for (final NicProfile nic : _networkMgr.getNicProfiles(router)) { + profile.addNic(nic); + } + return profile; + } + /** * @param router * @param add @@ -617,6 +657,17 @@ public boolean startSite2SiteVpn(final Site2SiteVpnConnection conn, final Virtua return applySite2SiteVpn(true, router, conn); } + @Override + public boolean startSite2SiteVpn(DomainRouterVO router) throws ResourceUnavailableException { + boolean result = true; + List conns = _s2sVpnMgr.getConnectionsForRouter(router); + for (Site2SiteVpnConnectionVO conn : conns) { + result = result && startSite2SiteVpn(conn, router); + } + + return result; + } + @Override public boolean stopSite2SiteVpn(final Site2SiteVpnConnection conn, final VirtualRouter router) throws ResourceUnavailableException { if (router.getState() != State.Running) { diff --git a/server/src/main/java/com/cloud/network/rules/RulesManagerImpl.java b/server/src/main/java/com/cloud/network/rules/RulesManagerImpl.java index 9dc7a3d3fba4..aea24a49ee5c 100644 --- a/server/src/main/java/com/cloud/network/rules/RulesManagerImpl.java +++ b/server/src/main/java/com/cloud/network/rules/RulesManagerImpl.java @@ -500,6 +500,7 @@ private boolean enableStaticNat(long ipId, long vmId, long networkId, boolean is s_logger.debug("The ip is not associated with the VPC network id=" + networkId + ", so assigning"); try { ipAddress = _ipAddrMgr.associateIPToGuestNetwork(ipId, networkId, false); + performedIpAssoc = true; } catch (Exception ex) { s_logger.warn("Failed to associate ip id=" + ipId + " to VPC network id=" + networkId + " as " + "a part of enable static nat"); return false; diff --git a/server/src/main/java/com/cloud/network/security/SecurityGroupManagerImpl.java b/server/src/main/java/com/cloud/network/security/SecurityGroupManagerImpl.java index a0c828588c00..5bb7767252ad 100644 --- a/server/src/main/java/com/cloud/network/security/SecurityGroupManagerImpl.java +++ b/server/src/main/java/com/cloud/network/security/SecurityGroupManagerImpl.java @@ -44,6 +44,7 @@ import org.apache.cloudstack.api.command.user.securitygroup.DeleteSecurityGroupCmd; import org.apache.cloudstack.api.command.user.securitygroup.RevokeSecurityGroupEgressCmd; import org.apache.cloudstack.api.command.user.securitygroup.RevokeSecurityGroupIngressCmd; +import org.apache.cloudstack.api.command.user.securitygroup.UpdateSecurityGroupCmd; import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService; import org.apache.cloudstack.framework.config.dao.ConfigurationDao; @@ -58,6 +59,7 @@ import com.cloud.agent.api.NetworkRulesVmSecondaryIpCommand; import com.cloud.agent.api.SecurityGroupRulesCmd; import com.cloud.agent.api.SecurityGroupRulesCmd.IpPortAndProto; +import com.cloud.agent.api.to.VirtualMachineTO; import com.cloud.agent.manager.Commands; import com.cloud.api.query.dao.SecurityGroupJoinDao; import com.cloud.configuration.Config; @@ -113,6 +115,8 @@ import com.cloud.vm.VirtualMachine.Event; import com.cloud.vm.VirtualMachine.State; import com.cloud.vm.VirtualMachineManager; +import com.cloud.vm.VirtualMachineProfile; +import com.cloud.vm.VirtualMachineProfileImpl; import com.cloud.vm.dao.NicDao; import com.cloud.vm.dao.NicSecondaryIpDao; import com.cloud.vm.dao.UserVmDao; @@ -377,6 +381,7 @@ public void handleVmStarted(VMInstanceVO vm) { } @DB + @Override public void scheduleRulesetUpdateToHosts(final List affectedVms, final boolean updateSeqno, Long delayMs) { if (affectedVms.size() == 0) { return; @@ -513,8 +518,35 @@ protected SecurityGroupRulesCmd generateRulesetCmd(String vmName, String guestIp egressResult.add(ipPortAndProto); } } - return new SecurityGroupRulesCmd(guestIp, guestIp6, guestMac, vmName, vmId, signature, seqnum, ingressResult.toArray(new IpPortAndProto[ingressResult.size()]), + SecurityGroupRulesCmd cmd = new SecurityGroupRulesCmd(guestIp, guestIp6, guestMac, vmName, vmId, signature, seqnum, ingressResult.toArray(new IpPortAndProto[ingressResult.size()]), egressResult.toArray(new IpPortAndProto[egressResult.size()]), secIps); + + final VirtualMachineTO to = getVmTO(vmId); + cmd.setVmTO(to); + return cmd; + } + + protected VirtualMachineTO getVmTO(Long vmId) { + final VMInstanceVO vm = _vmDao.findById(vmId); + final VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm); + final List nics = _nicDao.listByVmId(profile.getId()); + Collections.sort(nics, new Comparator() { + @Override + public int compare(NicVO nic1, NicVO nic2) { + Long nicId1 = Long.valueOf(nic1.getDeviceId()); + Long nicId2 = Long.valueOf(nic2.getDeviceId()); + return nicId1.compareTo(nicId2); + } + }); + for (final NicVO nic : nics) { + final Network network = _networkModel.getNetwork(nic.getNetworkId()); + final NicProfile nicProfile = + new NicProfile(nic, network, nic.getBroadcastUri(), nic.getIsolationUri(), null, _networkModel.isSecurityGroupSupportedInNetwork(network), + _networkModel.getNetworkTag(profile.getHypervisorType(), network)); + profile.addNic(nicProfile); + } + final VirtualMachineTO to = _itMgr.toVmTO(profile); + return to; } protected void handleVmStopped(VMInstanceVO vm) { @@ -879,6 +911,10 @@ public SecurityGroupVO createSecurityGroup(CreateSecurityGroupCmd cmd) throws Pe Account caller = CallContext.current().getCallingAccount(); Account owner = _accountMgr.finalizeOwner(caller, cmd.getAccountName(), cmd.getDomainId(), cmd.getProjectId()); + if (StringUtils.isBlank(name)) { + throw new InvalidParameterValueException("Security group name cannot be empty"); + } + if (_securityGroupDao.isNameInUse(owner.getId(), owner.getDomainId(), cmd.getSecurityGroupName())) { throw new InvalidParameterValueException("Unable to create security group, a group with name " + name + " already exists."); } @@ -1014,16 +1050,17 @@ public void doInTransactionWithoutResult(TransactionStatus status) { agentId = vm.getHostId(); if (agentId != null) { // get nic secondary ip address - String privateIp = vm.getPrivateIpAddress(); - NicVO nic = _nicDao.findByIp4AddressAndVmId(privateIp, vm.getId()); + NicVO nic = _nicDao.findFirstNicForVM(vm.getId()); List nicSecIps = null; if (nic != null) { if (nic.getSecondaryIp()) { //get secondary ips of the vm nicSecIps = _nicSecIpDao.getSecondaryIpAddressesForNic(nic.getId()); } + } else { + return; } - SecurityGroupRulesCmd cmd = generateRulesetCmd(vm.getInstanceName(), nic.getIPv6Address(), vm.getPrivateIpAddress(), vm.getPrivateMacAddress(), vm.getId(), + SecurityGroupRulesCmd cmd = generateRulesetCmd(vm.getInstanceName(), nic.getIPv4Address(), nic.getIPv6Address(), vm.getPrivateMacAddress(), vm.getId(), generateRulesetSignature(ingressRules, egressRules), seqnum, ingressRules, egressRules, nicSecIps); Commands cmds = new Commands(cmd); try { @@ -1117,6 +1154,60 @@ public void doInTransactionWithoutResult(TransactionStatus status) { s_logger.debug("Security group mappings are removed successfully for vm id=" + userVmId); } + @DB + @Override + @ActionEvent(eventType = EventTypes.EVENT_SECURITY_GROUP_UPDATE, eventDescription = "updating security group") + public SecurityGroup updateSecurityGroup(UpdateSecurityGroupCmd cmd) { + final Long groupId = cmd.getId(); + final String newName = cmd.getName(); + Account caller = CallContext.current().getCallingAccount(); + + SecurityGroupVO group = _securityGroupDao.findById(groupId); + if (group == null) { + throw new InvalidParameterValueException("Unable to find security group: " + groupId + "; failed to update security group."); + } + + if (newName == null) { + s_logger.debug("security group name is not changed. id=" + groupId); + return group; + } + + if (StringUtils.isBlank(newName)) { + throw new InvalidParameterValueException("Security group name cannot be empty"); + } + + // check permissions + _accountMgr.checkAccess(caller, null, true, group); + + return Transaction.execute(new TransactionCallback() { + @Override + public SecurityGroupVO doInTransaction(TransactionStatus status) { + SecurityGroupVO group = _securityGroupDao.lockRow(groupId, true); + if (group == null) { + throw new InvalidParameterValueException("Unable to find security group by id " + groupId); + } + + if (newName.equals(group.getName())) { + s_logger.debug("security group name is not changed. id=" + groupId); + return group; + } else if (newName.equalsIgnoreCase(SecurityGroupManager.DEFAULT_GROUP_NAME)) { + throw new InvalidParameterValueException("The security group name " + SecurityGroupManager.DEFAULT_GROUP_NAME + " is reserved"); + } + + if (group.getName().equalsIgnoreCase(SecurityGroupManager.DEFAULT_GROUP_NAME)) { + throw new InvalidParameterValueException("The default security group cannot be renamed"); + } + + group.setName(newName); + _securityGroupDao.update(groupId, group); + + s_logger.debug("Updated security group id=" + groupId); + + return group; + } + }); + } + @DB @Override @ActionEvent(eventType = EventTypes.EVENT_SECURITY_GROUP_DELETE, eventDescription = "deleting security group") @@ -1357,7 +1448,7 @@ public boolean securityGroupRulesForVmSecIp(long nicId, String secondaryIp, bool return true; } - String vmMac = vm.getPrivateMacAddress(); + String vmMac = nic.getMacAddress(); String vmName = vm.getInstanceName(); if (vmMac == null || vmName == null) { throw new InvalidParameterValueException("vm name or vm mac can't be null"); diff --git a/server/src/main/java/com/cloud/network/security/SecurityGroupManagerImpl2.java b/server/src/main/java/com/cloud/network/security/SecurityGroupManagerImpl2.java index 2d0ec61d09c2..5b4b85fc70c2 100644 --- a/server/src/main/java/com/cloud/network/security/SecurityGroupManagerImpl2.java +++ b/server/src/main/java/com/cloud/network/security/SecurityGroupManagerImpl2.java @@ -177,16 +177,17 @@ public void sendRulesetUpdates(SecurityGroupWork work) { Map> egressRules = generateRulesForVM(userVmId, SecurityRuleType.EgressRule); Long agentId = vm.getHostId(); if (agentId != null) { - String privateIp = vm.getPrivateIpAddress(); - NicVO nic = _nicDao.findByIp4AddressAndVmId(privateIp, vm.getId()); + NicVO nic = _nicDao.findFirstNicForVM(vm.getId()); List nicSecIps = null; if (nic != null) { if (nic.getSecondaryIp()) { nicSecIps = _nicSecIpDao.getSecondaryIpAddressesForNic(nic.getId()); } + } else { + return; } SecurityGroupRulesCmd cmd = - generateRulesetCmd(vm.getInstanceName(), vm.getPrivateIpAddress(), nic.getIPv6Address(), vm.getPrivateMacAddress(), vm.getId(), null, work.getLogsequenceNumber(), + generateRulesetCmd(vm.getInstanceName(), nic.getIPv4Address(), nic.getIPv6Address(), vm.getPrivateMacAddress(), vm.getId(), null, work.getLogsequenceNumber(), ingressRules, egressRules, nicSecIps); cmd.setMsId(_serverId); if (s_logger.isDebugEnabled()) { diff --git a/server/src/main/java/com/cloud/network/vpc/VpcManagerImpl.java b/server/src/main/java/com/cloud/network/vpc/VpcManagerImpl.java index b1b1059c1236..64c6f9ce4ebf 100644 --- a/server/src/main/java/com/cloud/network/vpc/VpcManagerImpl.java +++ b/server/src/main/java/com/cloud/network/vpc/VpcManagerImpl.java @@ -46,6 +46,7 @@ import org.apache.cloudstack.api.command.user.vpc.ListPrivateGatewaysCmd; import org.apache.cloudstack.api.command.user.vpc.ListStaticRoutesCmd; import org.apache.cloudstack.api.command.user.vpc.ListVPCOfferingsCmd; +import org.apache.cloudstack.api.command.user.vpc.RestartVPCCmd; import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService; import org.apache.cloudstack.framework.config.dao.ConfigurationDao; @@ -1697,16 +1698,21 @@ public boolean cleanupVpcResources(final long vpcId, final Account caller, final return success; } + @Override @ActionEvent(eventType = EventTypes.EVENT_VPC_RESTART, eventDescription = "restarting vpc") - public boolean restartVpc(final long vpcId, final boolean cleanUp, final boolean makeRedundant) throws ConcurrentOperationException, ResourceUnavailableException, + public boolean restartVpc(final RestartVPCCmd cmd) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException { - - final Account callerAccount = CallContext.current().getCallingAccount(); + final long vpcId = cmd.getId(); + final boolean cleanUp = cmd.getCleanup(); + final boolean makeRedundant = cmd.getMakeredundant(); final User callerUser = _accountMgr.getActiveUser(CallContext.current().getCallingUserId()); - final ReservationContext context = new ReservationContextImpl(null, null, callerUser, callerAccount); + return restartVpc(vpcId, cleanUp, makeRedundant, callerUser); + } - // Verify input parameters + @Override + @ActionEvent(eventType = EventTypes.EVENT_VPC_RESTART, eventDescription = "restarting vpc") + public boolean restartVpc(Long vpcId, boolean cleanUp, boolean makeRedundant, User user) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException { Vpc vpc = getActiveVpc(vpcId); if (vpc == null) { final InvalidParameterValueException ex = new InvalidParameterValueException("Unable to find Enabled VPC by id specified"); @@ -1714,6 +1720,8 @@ public boolean restartVpc(final long vpcId, final boolean cleanUp, final boolean throw ex; } + Account callerAccount = _accountMgr.getActiveAccountById(user.getAccountId()); + final ReservationContext context = new ReservationContextImpl(null, null, user, callerAccount); _accountMgr.checkAccess(callerAccount, null, false, vpc); s_logger.debug("Restarting VPC " + vpc); @@ -2561,7 +2569,7 @@ public Network createVpcGuestNetwork(final long ntwkOffId, final String name, fi // 2) Create network final Network guestNetwork = _ntwkMgr.createGuestNetwork(ntwkOffId, name, displayText, gateway, cidr, vlanId, false, networkDomain, owner, domainId, pNtwk, zoneId, aclType, - subdomainAccess, vpcId, null, null, isDisplayNetworkEnabled, null, externalId); + subdomainAccess, vpcId, null, null, isDisplayNetworkEnabled, null, null, externalId); if (guestNetwork != null) { guestNetwork.setNetworkACLId(aclId); diff --git a/server/src/main/java/com/cloud/resourcelimit/ResourceLimitManagerImpl.java b/server/src/main/java/com/cloud/resourcelimit/ResourceLimitManagerImpl.java index 417ccfc6f647..fbc8a99f1b31 100644 --- a/server/src/main/java/com/cloud/resourcelimit/ResourceLimitManagerImpl.java +++ b/server/src/main/java/com/cloud/resourcelimit/ResourceLimitManagerImpl.java @@ -44,6 +44,8 @@ import org.springframework.stereotype.Component; import com.cloud.alert.AlertManager; +import com.cloud.api.query.dao.UserVmJoinDao; +import com.cloud.api.query.vo.UserVmJoinVO; import com.cloud.configuration.Config; import com.cloud.configuration.Resource; import com.cloud.configuration.Resource.ResourceOwnerType; @@ -100,6 +102,8 @@ import com.cloud.utils.db.TransactionCallbackWithExceptionNoReturn; import com.cloud.utils.db.TransactionStatus; import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.vm.VirtualMachineManager; +import com.cloud.vm.VirtualMachine.State; import com.cloud.vm.dao.UserVmDao; import com.cloud.vm.dao.VMInstanceDao; @@ -151,6 +155,8 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim private VlanDao _vlanDao; @Inject private SnapshotDataStoreDao _snapshotDataStoreDao; + @Inject + private UserVmJoinDao _userVmJoinDao; protected GenericSearchBuilder templateSizeSearch; protected GenericSearchBuilder snapshotSizeSearch; @@ -872,7 +878,7 @@ public Long doInTransaction(TransactionStatus status) { protected long recalculateAccountResourceCount(final long accountId, final ResourceType type) { final Long newCount; if (type == Resource.ResourceType.user_vm) { - newCount = _userVmDao.countAllocatedVMsForAccount(accountId); + newCount = _userVmDao.countAllocatedVMsForAccount(accountId, VirtualMachineManager.ResoureCountRunningVMsonly.value()); } else if (type == Resource.ResourceType.volume) { long virtualRouterCount = _vmDao.findIdsOfAllocatedVirtualRoutersForAccount(accountId).size(); newCount = _volumeDao.countAllocatedVolumesForAccount(accountId) - virtualRouterCount; // don't count the volumes of virtual router @@ -929,11 +935,51 @@ public void doInTransactionWithoutResult(TransactionStatus status) { } public long countCpusForAccount(long accountId) { - return _resourceCountDao.countCpuNumberAllocatedToAccount(accountId); + long cputotal = 0; + // user vms + SearchBuilder userVmSearch = _userVmJoinDao.createSearchBuilder(); + userVmSearch.and("accountId", userVmSearch.entity().getAccountId(), Op.EQ); + userVmSearch.and("state", userVmSearch.entity().getState(), SearchCriteria.Op.NIN); + userVmSearch.and("displayVm", userVmSearch.entity().isDisplayVm(), Op.EQ); + userVmSearch.groupBy(userVmSearch.entity().getId()); // select distinct + userVmSearch.done(); + + SearchCriteria sc1 = userVmSearch.create(); + sc1.setParameters("accountId", accountId); + if (VirtualMachineManager.ResoureCountRunningVMsonly.value()) + sc1.setParameters("state", new Object[] {State.Destroyed, State.Error, State.Expunging, State.Stopped}); + else + sc1.setParameters("state", new Object[] {State.Destroyed, State.Error, State.Expunging}); + sc1.setParameters("displayVm", 1); + List userVms = _userVmJoinDao.search(sc1,null); + for (UserVmJoinVO vm : userVms) { + cputotal += Long.valueOf(vm.getCpu()); + } + return cputotal; } public long calculateMemoryForAccount(long accountId) { - return _resourceCountDao.countMemoryAllocatedToAccount(accountId); + long ramtotal = 0; + // user vms + SearchBuilder userVmSearch = _userVmJoinDao.createSearchBuilder(); + userVmSearch.and("accountId", userVmSearch.entity().getAccountId(), Op.EQ); + userVmSearch.and("state", userVmSearch.entity().getState(), SearchCriteria.Op.NIN); + userVmSearch.and("displayVm", userVmSearch.entity().isDisplayVm(), Op.EQ); + userVmSearch.groupBy(userVmSearch.entity().getId()); // select distinct + userVmSearch.done(); + + SearchCriteria sc1 = userVmSearch.create(); + sc1.setParameters("accountId", accountId); + if (VirtualMachineManager.ResoureCountRunningVMsonly.value()) + sc1.setParameters("state", new Object[] {State.Destroyed, State.Error, State.Expunging, State.Stopped}); + else + sc1.setParameters("state", new Object[] {State.Destroyed, State.Error, State.Expunging}); + sc1.setParameters("displayVm", 1); + List userVms = _userVmJoinDao.search(sc1,null); + for (UserVmJoinVO vm : userVms) { + ramtotal += Long.valueOf(vm.getRamSize()); + } + return ramtotal; } public long calculateSecondaryStorageForAccount(long accountId) { diff --git a/server/src/main/java/com/cloud/server/ManagementServerImpl.java b/server/src/main/java/com/cloud/server/ManagementServerImpl.java index 147c527b2739..ac3460c22e1f 100644 --- a/server/src/main/java/com/cloud/server/ManagementServerImpl.java +++ b/server/src/main/java/com/cloud/server/ManagementServerImpl.java @@ -171,6 +171,7 @@ import org.apache.cloudstack.api.command.admin.router.ConfigureVirtualRouterElementCmd; import org.apache.cloudstack.api.command.admin.router.CreateVirtualRouterElementCmd; import org.apache.cloudstack.api.command.admin.router.DestroyRouterCmd; +import org.apache.cloudstack.api.command.admin.router.GetRouterHealthCheckResultsCmd; import org.apache.cloudstack.api.command.admin.router.ListOvsElementsCmd; import org.apache.cloudstack.api.command.admin.router.ListRoutersCmd; import org.apache.cloudstack.api.command.admin.router.ListVirtualRouterElementsCmd; @@ -264,9 +265,11 @@ import org.apache.cloudstack.api.command.admin.vmsnapshot.RevertToVMSnapshotCmdByAdmin; import org.apache.cloudstack.api.command.admin.volume.AttachVolumeCmdByAdmin; import org.apache.cloudstack.api.command.admin.volume.CreateVolumeCmdByAdmin; +import org.apache.cloudstack.api.command.admin.volume.DestroyVolumeCmdByAdmin; import org.apache.cloudstack.api.command.admin.volume.DetachVolumeCmdByAdmin; import org.apache.cloudstack.api.command.admin.volume.ListVolumesCmdByAdmin; import org.apache.cloudstack.api.command.admin.volume.MigrateVolumeCmdByAdmin; +import org.apache.cloudstack.api.command.admin.volume.RecoverVolumeCmdByAdmin; import org.apache.cloudstack.api.command.admin.volume.ResizeVolumeCmdByAdmin; import org.apache.cloudstack.api.command.admin.volume.UpdateVolumeCmdByAdmin; import org.apache.cloudstack.api.command.admin.volume.UploadVolumeCmdByAdmin; @@ -422,6 +425,7 @@ import org.apache.cloudstack.api.command.user.securitygroup.ListSecurityGroupsCmd; import org.apache.cloudstack.api.command.user.securitygroup.RevokeSecurityGroupEgressCmd; import org.apache.cloudstack.api.command.user.securitygroup.RevokeSecurityGroupIngressCmd; +import org.apache.cloudstack.api.command.user.securitygroup.UpdateSecurityGroupCmd; import org.apache.cloudstack.api.command.user.snapshot.ArchiveSnapshotCmd; import org.apache.cloudstack.api.command.user.snapshot.CreateSnapshotCmd; import org.apache.cloudstack.api.command.user.snapshot.CreateSnapshotFromVMSnapshotCmd; @@ -482,12 +486,14 @@ import org.apache.cloudstack.api.command.user.volume.AttachVolumeCmd; import org.apache.cloudstack.api.command.user.volume.CreateVolumeCmd; import org.apache.cloudstack.api.command.user.volume.DeleteVolumeCmd; +import org.apache.cloudstack.api.command.user.volume.DestroyVolumeCmd; import org.apache.cloudstack.api.command.user.volume.DetachVolumeCmd; import org.apache.cloudstack.api.command.user.volume.ExtractVolumeCmd; import org.apache.cloudstack.api.command.user.volume.GetUploadParamsForVolumeCmd; import org.apache.cloudstack.api.command.user.volume.ListResourceDetailsCmd; import org.apache.cloudstack.api.command.user.volume.ListVolumesCmd; import org.apache.cloudstack.api.command.user.volume.MigrateVolumeCmd; +import org.apache.cloudstack.api.command.user.volume.RecoverVolumeCmd; import org.apache.cloudstack.api.command.user.volume.RemoveResourceDetailCmd; import org.apache.cloudstack.api.command.user.volume.ResizeVolumeCmd; import org.apache.cloudstack.api.command.user.volume.UpdateVolumeCmd; @@ -642,6 +648,7 @@ import com.cloud.storage.StorageManager; import com.cloud.storage.StoragePool; import com.cloud.storage.Volume; +import com.cloud.storage.VolumeApiServiceImpl; import com.cloud.storage.VolumeVO; import com.cloud.storage.dao.DiskOfferingDao; import com.cloud.storage.dao.GuestOSCategoryDao; @@ -2889,6 +2896,7 @@ public List> getCommands() { cmdList.add(ListSecurityGroupsCmd.class); cmdList.add(RevokeSecurityGroupEgressCmd.class); cmdList.add(RevokeSecurityGroupIngressCmd.class); + cmdList.add(UpdateSecurityGroupCmd.class); cmdList.add(CreateSnapshotCmd.class); cmdList.add(CreateSnapshotFromVMSnapshotCmd.class); cmdList.add(DeleteSnapshotCmd.class); @@ -2947,6 +2955,8 @@ public List> getCommands() { cmdList.add(MigrateVolumeCmd.class); cmdList.add(ResizeVolumeCmd.class); cmdList.add(UploadVolumeCmd.class); + cmdList.add(DestroyVolumeCmd.class); + cmdList.add(RecoverVolumeCmd.class); cmdList.add(CreateStaticRouteCmd.class); cmdList.add(CreateVPCCmd.class); cmdList.add(DeleteStaticRouteCmd.class); @@ -3092,6 +3102,8 @@ public List> getCommands() { cmdList.add(UpdateVolumeCmdByAdmin.class); cmdList.add(UploadVolumeCmdByAdmin.class); cmdList.add(ListVolumesCmdByAdmin.class); + cmdList.add(DestroyVolumeCmdByAdmin.class); + cmdList.add(RecoverVolumeCmdByAdmin.class); cmdList.add(AssociateIPAddrCmdByAdmin.class); cmdList.add(ListPublicIpAddressesCmdByAdmin.class); cmdList.add(CreateNetworkCmdByAdmin.class); @@ -3115,6 +3127,7 @@ public List> getCommands() { cmdList.add(ListMgmtsCmd.class); cmdList.add(GetUploadParamsForIsoCmd.class); cmdList.add(ListTemplateOVFProperties.class); + cmdList.add(GetRouterHealthCheckResultsCmd.class); // Out-of-band management APIs for admins cmdList.add(EnableOutOfBandManagementForHostCmd.class); @@ -3499,6 +3512,7 @@ public Map listCapabilities(final ListCapabilitiesCmd cmd) { final boolean allowUserViewDestroyedVM = (QueryService.AllowUserViewDestroyedVM.valueIn(caller.getId()) | _accountService.isAdmin(caller.getId())); final boolean allowUserExpungeRecoverVM = (UserVmManager.AllowUserExpungeRecoverVm.valueIn(caller.getId()) | _accountService.isAdmin(caller.getId())); + final boolean allowUserExpungeRecoverVolume = (VolumeApiServiceImpl.AllowUserExpungeRecoverVolume.valueIn(caller.getId()) | _accountService.isAdmin(caller.getId())); final boolean allowUserViewAllDomainAccounts = (QueryService.AllowUserViewAllDomainAccounts.valueIn(caller.getDomainId())); @@ -3521,6 +3535,7 @@ public Map listCapabilities(final ListCapabilitiesCmd cmd) { capabilities.put("KVMSnapshotEnabled", KVMSnapshotEnabled); capabilities.put("allowUserViewDestroyedVM", allowUserViewDestroyedVM); capabilities.put("allowUserExpungeRecoverVM", allowUserExpungeRecoverVM); + capabilities.put("allowUserExpungeRecoverVolume", allowUserExpungeRecoverVolume); capabilities.put("allowUserViewAllDomainAccounts", allowUserViewAllDomainAccounts); if (apiLimitEnabled) { capabilities.put("apiLimitInterval", apiLimitInterval); @@ -4080,7 +4095,7 @@ private VirtualMachine upgradeStoppedSystemVm(final Long systemVmId, final Long if (newServiceOffering.isDynamic()) { newServiceOffering.setDynamicFlag(true); _userVmMgr.validateCustomParameters(newServiceOffering, customparameters); - newServiceOffering = _offeringDao.getcomputeOffering(newServiceOffering, customparameters); + newServiceOffering = _offeringDao.getComputeOffering(newServiceOffering, customparameters); } _itMgr.checkIfCanUpgrade(systemVm, newServiceOffering); diff --git a/server/src/main/java/com/cloud/server/StatsCollector.java b/server/src/main/java/com/cloud/server/StatsCollector.java index b2f244229e32..14a9084124f1 100644 --- a/server/src/main/java/com/cloud/server/StatsCollector.java +++ b/server/src/main/java/com/cloud/server/StatsCollector.java @@ -928,13 +928,7 @@ protected void runInContext() { List volumes = _volsDao.findByPoolId(pool.getId(), null); List volumeLocators = new ArrayList(); for (VolumeVO volume : volumes) { - if (volume.getFormat() == ImageFormat.QCOW2) { - if (pool.isManaged()) { - volumeLocators.add(volume.getPath()); - } else { - volumeLocators.add(volume.getUuid()); - } - } else if (volume.getFormat() == ImageFormat.VHD) { + if (volume.getFormat() == ImageFormat.QCOW2 || volume.getFormat() == ImageFormat.VHD) { volumeLocators.add(volume.getPath()); } else if (volume.getFormat() == ImageFormat.OVA) { volumeLocators.add(volume.getChainInfo()); diff --git a/server/src/main/java/com/cloud/storage/ImageStoreUploadMonitorImpl.java b/server/src/main/java/com/cloud/storage/ImageStoreUploadMonitorImpl.java index 2b39518f8b8d..a2f97e841278 100755 --- a/server/src/main/java/com/cloud/storage/ImageStoreUploadMonitorImpl.java +++ b/server/src/main/java/com/cloud/storage/ImageStoreUploadMonitorImpl.java @@ -55,6 +55,8 @@ import com.cloud.agent.api.Command; import com.cloud.agent.api.StartupCommand; import com.cloud.alert.AlertManager; +import com.cloud.api.query.dao.TemplateJoinDao; +import com.cloud.api.query.vo.TemplateJoinVO; import com.cloud.configuration.Resource; import com.cloud.event.EventTypes; import com.cloud.event.UsageEventUtils; @@ -111,6 +113,8 @@ public class ImageStoreUploadMonitorImpl extends ManagerBase implements ImageSto private TemplateDataFactory templateFactory; @Inject private TemplateService templateService; + @Inject + private TemplateJoinDao templateJoinDao; private long _nodeId; private ScheduledExecutorService _executor = null; @@ -322,7 +326,7 @@ public void doInTransactionWithoutResult(TransactionStatus status) { // publish usage events UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_UPLOAD, tmpVolume.getAccountId(), - tmpVolumeDataStore.getDataStoreId(), tmpVolume.getId(), tmpVolume.getName(), + tmpVolume.getDataCenterId(), tmpVolume.getId(), tmpVolume.getName(), null, null, tmpVolumeDataStore.getPhysicalSize(), tmpVolumeDataStore.getSize(), Volume.class.getName(), tmpVolume.getUuid()); @@ -425,7 +429,9 @@ public void doInTransactionWithoutResult(TransactionStatus status) { if (tmpTemplate.getFormat() == Storage.ImageFormat.ISO) { etype = EventTypes.EVENT_ISO_CREATE; } - UsageEventUtils.publishUsageEvent(etype, tmpTemplate.getAccountId(), tmpTemplateDataStore.getDataStoreId(), tmpTemplate.getId(), tmpTemplate.getName(), null, null, + TemplateJoinVO vo = templateJoinDao.findById(tmpTemplate.getId()); + assert (vo != null) : "Couldn't find the template view for given template ID"; + UsageEventUtils.publishUsageEvent(etype, tmpTemplate.getAccountId(), vo.getDataCenterId(), tmpTemplate.getId(), tmpTemplate.getName(), null, null, tmpTemplateDataStore.getPhysicalSize(), tmpTemplateDataStore.getSize(), VirtualMachineTemplate.class.getName(), tmpTemplate.getUuid()); if (s_logger.isDebugEnabled()) { diff --git a/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java b/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java index ddd84137ad9b..15e32208b0f3 100644 --- a/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java +++ b/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java @@ -275,6 +275,9 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic static final ConfigKey VolumeUrlCheck = new ConfigKey("Advanced", Boolean.class, "volume.url.check", "true", "Check the url for a volume before downloading it from the management server. Set to false when you managment has no internet access.", true); + public static final ConfigKey AllowUserExpungeRecoverVolume = new ConfigKey("Advanced", Boolean.class, "allow.user.expunge.recover.volume", "true", + "Determines whether users can expunge or recover their volume", true, ConfigKey.Scope.Account); + private long _maxVolumeSizeInGb; private final StateMachine2 _volStateMachine; @@ -673,8 +676,6 @@ public VolumeVO allocVolume(CreateVolumeCmd cmd) throws ResourceAllocationExcept zoneId = snapshotCheck.getDataCenterId(); } - _configMgr.checkDiskOfferingAccess(null, diskOffering, _dcDao.findById(zoneId)); - if (diskOffering == null) { // Pure snapshot is being used to create volume. diskOfferingId = snapshotCheck.getDiskOfferingId(); diskOffering = _diskOfferingDao.findById(diskOfferingId); @@ -689,6 +690,8 @@ public VolumeVO allocVolume(CreateVolumeCmd cmd) throws ResourceAllocationExcept } } + _configMgr.checkDiskOfferingAccess(null, diskOffering, _dcDao.findById(zoneId)); + // check snapshot permissions _accountMgr.checkAccess(caller, null, true, snapshotCheck); @@ -1261,20 +1264,17 @@ private VolumeVO orchestrateResizeVolume(long volumeId, long currentSize, long n * Otherwise, after the removal in the database, we will try to remove the volume from both primary and secondary storage. */ public boolean deleteVolume(long volumeId, Account caller) throws ConcurrentOperationException { - VolumeVO volume = retrieveAndValidateVolume(volumeId, caller); + Volume volume = destroyVolume(volumeId, caller, true, true); + return (volume != null); + } + + private boolean deleteVolumeFromStorage(VolumeVO volume, Account caller) throws ConcurrentOperationException { try { - destroyVolumeIfPossible(volume); - // Mark volume as removed if volume has not been created on primary or secondary - if (volume.getState() == Volume.State.Allocated) { - _volsDao.remove(volumeId); - stateTransitTo(volume, Volume.Event.DestroyRequested); - return true; - } expungeVolumesInPrimaryStorageIfNeeded(volume); expungeVolumesInSecondaryStorageIfNeeded(volume); cleanVolumesCache(volume); return true; - } catch (InterruptedException | ExecutionException | NoTransitionException e) { + } catch (InterruptedException | ExecutionException e) { s_logger.warn("Failed to expunge volume: " + volume.getUuid(), e); return false; } @@ -1301,7 +1301,7 @@ protected VolumeVO retrieveAndValidateVolume(long volumeId, Account caller) { if (!_snapshotMgr.canOperateOnVolume(volume)) { throw new InvalidParameterValueException("There are snapshot operations in progress on the volume, unable to delete it"); } - if (volume.getInstanceId() != null) { + if (volume.getInstanceId() != null && volume.getState() != Volume.State.Expunged) { throw new InvalidParameterValueException("Please specify a volume that is not attached to any VM."); } if (volume.getState() == Volume.State.UploadOp) { @@ -1334,12 +1334,8 @@ protected VolumeVO retrieveAndValidateVolume(long volumeId, Account caller) { * The volume is destroyed via {@link VolumeService#destroyVolume(long)} method. */ protected void destroyVolumeIfPossible(VolumeVO volume) { - if (volume.getState() != Volume.State.Destroy && volume.getState() != Volume.State.Expunging && volume.getState() != Volume.State.Expunged) { + if (volume.getState() != Volume.State.Destroy && volume.getState() != Volume.State.Expunging && volume.getState() != Volume.State.Expunged && volume.getState() != Volume.State.Allocated && volume.getState() != Volume.State.Uploaded) { volService.destroyVolume(volume.getId()); - - // Decrement the resource count for volumes and primary storage belonging user VM's only - _resourceLimitMgr.decrementResourceCount(volume.getAccountId(), ResourceType.volume, volume.isDisplayVolume()); - _resourceLimitMgr.decrementResourceCount(volume.getAccountId(), ResourceType.primary_storage, volume.isDisplayVolume(), volume.getSize()); } } @@ -1389,6 +1385,89 @@ protected boolean stateTransitTo(Volume vol, Volume.Event event) throws NoTransi return _volStateMachine.transitTo(vol, event, null, _volsDao); } + @Override + @ActionEvent(eventType = EventTypes.EVENT_VOLUME_DESTROY, eventDescription = "destroying a volume") + public Volume destroyVolume(long volumeId, Account caller, boolean expunge, boolean forceExpunge) { + VolumeVO volume = retrieveAndValidateVolume(volumeId, caller); + + if (expunge) { + // When trying to expunge, permission is denied when the caller is not an admin and the AllowUserExpungeRecoverVolume is false for the caller. + final Long userId = caller.getAccountId(); + if (!forceExpunge && !_accountMgr.isAdmin(userId) && !AllowUserExpungeRecoverVolume.valueIn(userId)) { + throw new PermissionDeniedException("Expunging a volume can only be done by an Admin. Or when the allow.user.expunge.recover.volume key is set."); + } + } else if (volume.getState() == Volume.State.Allocated || volume.getState() == Volume.State.Uploaded) { + throw new InvalidParameterValueException("The volume in Allocated/Uploaded state can only be expunged not destroyed/recovered"); + } + + destroyVolumeIfPossible(volume); + + if (expunge) { + // Mark volume as removed if volume has not been created on primary or secondary + if (volume.getState() == Volume.State.Allocated) { + _volsDao.remove(volume.getId()); + try { + stateTransitTo(volume, Volume.Event.DestroyRequested); + } catch (NoTransitionException e) { + s_logger.debug("Failed to destroy volume" + volume.getId(), e); + return null; + } + _resourceLimitMgr.decrementResourceCount(volume.getAccountId(), ResourceType.volume, volume.isDisplay()); + _resourceLimitMgr.decrementResourceCount(volume.getAccountId(), ResourceType.primary_storage, volume.isDisplay(), new Long(volume.getSize())); + return volume; + } + if (!deleteVolumeFromStorage(volume, caller)) { + s_logger.warn("Failed to expunge volume: " + volumeId); + return null; + } + } + + return volume; + } + + @Override + @ActionEvent(eventType = EventTypes.EVENT_VOLUME_RECOVER, eventDescription = "recovering a volume in Destroy state") + public Volume recoverVolume(long volumeId) { + Account caller = CallContext.current().getCallingAccount(); + final Long userId = caller.getAccountId(); + + // Verify input parameters + final VolumeVO volume = _volsDao.findById(volumeId); + + if (volume == null) { + throw new InvalidParameterValueException("Unable to find a volume with id " + volume); + } + + // When trying to expunge, permission is denied when the caller is not an admin and the AllowUserExpungeRecoverVolume is false for the caller. + if (!_accountMgr.isAdmin(userId) && !AllowUserExpungeRecoverVolume.valueIn(userId)) { + throw new PermissionDeniedException("Recovering a volume can only be done by an Admin. Or when the allow.user.expunge.recover.volume key is set."); + } + + _accountMgr.checkAccess(caller, null, true, volume); + + if (volume.getState() != Volume.State.Destroy) { + throw new InvalidParameterValueException("Please specify a volume in Destroy state."); + } + + try { + _resourceLimitMgr.checkResourceLimit(_accountMgr.getAccount(volume.getAccountId()), ResourceType.primary_storage, volume.isDisplayVolume(), volume.getSize()); + } catch (ResourceAllocationException e) { + s_logger.error("primary storage resource limit check failed", e); + throw new InvalidParameterValueException(e.getMessage()); + } + + try { + stateTransitTo(volume, Volume.Event.RecoverRequested); + } catch (NoTransitionException e) { + s_logger.debug("Failed to recover volume" + volume.getId(), e); + throw new CloudRuntimeException("Failed to recover volume" + volume.getId(), e); + } + _resourceLimitMgr.incrementResourceCount(volume.getAccountId(), ResourceType.volume, volume.isDisplay()); + _resourceLimitMgr.incrementResourceCount(volume.getAccountId(), ResourceType.primary_storage, volume.isDisplay(), new Long(volume.getSize())); + + return volume; + } + @Override @ActionEvent(eventType = EventTypes.EVENT_VOLUME_ATTACH, eventDescription = "attaching volume", async = true) public Volume attachVolumeToVM(AttachVolumeCmd command) { @@ -3409,6 +3488,6 @@ public String getConfigComponentName() { @Override public ConfigKey[] getConfigKeys() { - return new ConfigKey[] {ConcurrentMigrationsThresholdPerDatastore}; + return new ConfigKey[] {ConcurrentMigrationsThresholdPerDatastore, AllowUserExpungeRecoverVolume}; } } diff --git a/server/src/main/java/com/cloud/storage/download/DownloadMonitorImpl.java b/server/src/main/java/com/cloud/storage/download/DownloadMonitorImpl.java index 68be52d842fb..1954cdea6879 100644 --- a/server/src/main/java/com/cloud/storage/download/DownloadMonitorImpl.java +++ b/server/src/main/java/com/cloud/storage/download/DownloadMonitorImpl.java @@ -53,29 +53,21 @@ import com.cloud.storage.RegisterVolumePayload; import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.VMTemplateStorageResourceAssoc.Status; -import com.cloud.storage.Volume; -import com.cloud.storage.dao.VMTemplateDao; -import com.cloud.storage.dao.VolumeDao; import com.cloud.storage.template.TemplateConstants; import com.cloud.storage.upload.UploadListener; -import com.cloud.template.VirtualMachineTemplate; import com.cloud.utils.component.ComponentContext; import com.cloud.utils.component.ManagerBase; import com.cloud.utils.exception.CloudRuntimeException; @Component public class DownloadMonitorImpl extends ManagerBase implements DownloadMonitor { - static final Logger s_logger = Logger.getLogger(DownloadMonitorImpl.class); + static final Logger LOGGER = Logger.getLogger(DownloadMonitorImpl.class); @Inject private TemplateDataStoreDao _vmTemplateStoreDao; @Inject - private VolumeDao _volumeDao; - @Inject private VolumeDataStoreDao _volumeStoreDao; @Inject - private final VMTemplateDao _templateDao = null; - @Inject private AgentManager _agentMgr; @Inject private ConfigurationDao _configDao; @@ -94,7 +86,7 @@ public boolean configure(String name, Map params) { String cert = configs.get("secstorage.ssl.cert.domain"); if (!"realhostip.com".equalsIgnoreCase(cert)) { - s_logger.warn("Only realhostip.com ssl cert is supported, ignoring self-signed and other certs"); + LOGGER.warn("Only realhostip.com ssl cert is supported, ignoring self-signed and other certs"); } _copyAuthPasswd = configs.get("secstorage.copy.password"); @@ -125,7 +117,7 @@ public boolean isTemplateUpdateable(Long templateId, Long storeId) { private void initiateTemplateDownload(DataObject template, AsyncCompletionCallback callback) { boolean downloadJobExists = false; - TemplateDataStoreVO vmTemplateStore = null; + TemplateDataStoreVO vmTemplateStore; DataStore store = template.getDataStore(); vmTemplateStore = _vmTemplateStoreDao.findByStoreTemplate(store.getId(), template.getId()); @@ -141,7 +133,6 @@ private void initiateTemplateDownload(DataObject template, AsyncCompletionCallba Long maxTemplateSizeInBytes = getMaxTemplateSizeInBytes(); if (vmTemplateStore != null) { start(); - VirtualMachineTemplate tmpl = _templateDao.findById(template.getId()); DownloadCommand dcmd = new DownloadCommand((TemplateObjectTO)(template.getTO()), maxTemplateSizeInBytes); dcmd.setProxy(getHttpProxy()); if (downloadJobExists) { @@ -153,7 +144,7 @@ private void initiateTemplateDownload(DataObject template, AsyncCompletionCallba EndPoint ep = _epSelector.select(template); if (ep == null) { String errMsg = "There is no secondary storage VM for downloading template to image store " + store.getName(); - s_logger.warn(errMsg); + LOGGER.warn(errMsg); throw new CloudRuntimeException(errMsg); } DownloadListener dl = new DownloadListener(ep, store, template, _timer, this, dcmd, callback); @@ -164,14 +155,14 @@ private void initiateTemplateDownload(DataObject template, AsyncCompletionCallba // DownloadListener to use // new ObjectInDataStore.State transition. TODO: fix this later // to be able to remove downloadState from template_store_ref. - s_logger.info("found existing download job"); + LOGGER.info("found existing download job"); dl.setCurrState(vmTemplateStore.getDownloadState()); } try { ep.sendMessageAsync(dcmd, new UploadListener.Callback(ep.getId(), dl)); } catch (Exception e) { - s_logger.warn("Unable to start /resume download of template " + template.getId() + " to " + store.getName(), e); + LOGGER.warn("Unable to start /resume download of template " + template.getId() + " to " + store.getName(), e); dl.setDisconnected(); dl.scheduleStatusCheck(RequestType.GET_OR_RESTART); } @@ -187,12 +178,12 @@ public void downloadTemplateToStorage(DataObject template, AsyncCompletionCallba if (template.getUri() != null) { initiateTemplateDownload(template, callback); } else { - s_logger.info("Template url is null, cannot download"); + LOGGER.info("Template url is null, cannot download"); DownloadAnswer ans = new DownloadAnswer("Template url is null", Status.UNKNOWN); callback.complete(ans); } } else { - s_logger.info("Template download is already in progress or already downloaded"); + LOGGER.info("Template download is already in progress or already downloaded"); DownloadAnswer ans = new DownloadAnswer("Template download is already in progress or already downloaded", Status.UNKNOWN); callback.complete(ans); @@ -203,7 +194,7 @@ public void downloadTemplateToStorage(DataObject template, AsyncCompletionCallba @Override public void downloadVolumeToStorage(DataObject volume, AsyncCompletionCallback callback) { boolean downloadJobExists = false; - VolumeDataStoreVO volumeHost = null; + VolumeDataStoreVO volumeHost; DataStore store = volume.getDataStore(); VolumeInfo volInfo = (VolumeInfo)volume; RegisterVolumePayload payload = (RegisterVolumePayload)volInfo.getpayload(); @@ -214,7 +205,7 @@ public void downloadVolumeToStorage(DataObject volume, AsyncCompletionCallback 2)) { downloadJobExists = true; } else { @@ -225,35 +216,32 @@ public void downloadVolumeToStorage(DataObject volume, AsyncCompletionCallback failedZones.size())){ diff --git a/server/src/main/java/com/cloud/user/AccountManagerImpl.java b/server/src/main/java/com/cloud/user/AccountManagerImpl.java index 20d769f09efa..f40b888808a7 100644 --- a/server/src/main/java/com/cloud/user/AccountManagerImpl.java +++ b/server/src/main/java/com/cloud/user/AccountManagerImpl.java @@ -132,7 +132,6 @@ import com.cloud.server.auth.UserAuthenticator; import com.cloud.server.auth.UserAuthenticator.ActionOnFailedAuthentication; import com.cloud.storage.VMTemplateVO; -import com.cloud.storage.Volume; import com.cloud.storage.VolumeApiService; import com.cloud.storage.VolumeVO; import com.cloud.storage.dao.VMTemplateDao; @@ -782,13 +781,11 @@ protected boolean cleanupAccount(AccountVO account, long callerUserId, Account c // Mark the account's volumes as destroyed List volumes = _volumeDao.findDetachedByAccount(accountId); for (VolumeVO volume : volumes) { - if (!volume.getState().equals(Volume.State.Destroy)) { - try { - volumeService.deleteVolume(volume.getId(), caller); - } catch (Exception ex) { - s_logger.warn("Failed to cleanup volumes as a part of account id=" + accountId + " cleanup due to Exception: ", ex); - accountCleanupNeeded = true; - } + try { + volumeService.deleteVolume(volume.getId(), caller); + } catch (Exception ex) { + s_logger.warn("Failed to cleanup volumes as a part of account id=" + accountId + " cleanup due to Exception: ", ex); + accountCleanupNeeded = true; } } @@ -2328,9 +2325,9 @@ public UserAccount authenticateUser(final String username, final String password // Block when is not in the list of allowed IPs if (!NetUtils.isIpInCidrList(loginIpAddress, accessAllowedCidrs.split(","))) { - s_logger.warn("Request by account '" + account.toString() + "' was denied since " + loginIpAddress.toString().replaceAll("/", "") + " does not match " + accessAllowedCidrs); + s_logger.warn("Request by account '" + account.toString() + "' was denied since " + loginIpAddress.toString().replace("/", "") + " does not match " + accessAllowedCidrs); throw new CloudAuthenticationException("Failed to authenticate user '" + username + "' in domain '" + domain.getPath() + "' from ip " - + loginIpAddress.toString().replaceAll("/", "") + "; please provide valid credentials"); + + loginIpAddress.toString().replace("/", "") + "; please provide valid credentials"); } } @@ -2912,4 +2909,4 @@ public String getConfigComponentName() { public ConfigKey[] getConfigKeys() { return new ConfigKey[] {UseSecretKeyInResponse}; } -} \ No newline at end of file +} diff --git a/server/src/main/java/com/cloud/vm/UserVmManager.java b/server/src/main/java/com/cloud/vm/UserVmManager.java index 717ff5a0fd2e..f37fcd8dd359 100644 --- a/server/src/main/java/com/cloud/vm/UserVmManager.java +++ b/server/src/main/java/com/cloud/vm/UserVmManager.java @@ -30,6 +30,7 @@ import com.cloud.exception.ConcurrentOperationException; import com.cloud.exception.InsufficientCapacityException; import com.cloud.exception.ManagementServerException; +import com.cloud.exception.ResourceAllocationException; import com.cloud.exception.ResourceUnavailableException; import com.cloud.exception.VirtualMachineMigrationException; import com.cloud.offering.ServiceOffering; @@ -99,10 +100,10 @@ public interface UserVmManager extends UserVmService { boolean expunge(UserVmVO vm, long callerUserId, Account caller); Pair> startVirtualMachine(long vmId, Long hostId, Map additionalParams, String deploymentPlannerToUse) - throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException; + throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException, ResourceAllocationException; Pair> startVirtualMachine(long vmId, Long podId, Long clusterId, Long hostId, Map additionalParams, String deploymentPlannerToUse) - throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException; + throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException, ResourceAllocationException; boolean upgradeVirtualMachine(Long id, Long serviceOfferingId, Map customParameters) throws ResourceUnavailableException, ConcurrentOperationException, ManagementServerException, diff --git a/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java b/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java index 52339662cb6d..3f28f1283d8a 100644 --- a/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java @@ -572,16 +572,20 @@ private void resourceLimitCheck(Account owner, Boolean displayVm, Long cpu, Long _resourceLimitMgr.checkResourceLimit(owner, ResourceType.memory, displayVm, memory); } - private void resourceCountIncrement(long accountId, Boolean displayVm, Long cpu, Long memory) { - _resourceLimitMgr.incrementResourceCount(accountId, ResourceType.user_vm, displayVm); - _resourceLimitMgr.incrementResourceCount(accountId, ResourceType.cpu, displayVm, cpu); - _resourceLimitMgr.incrementResourceCount(accountId, ResourceType.memory, displayVm, memory); + protected void resourceCountIncrement(long accountId, Boolean displayVm, Long cpu, Long memory) { + if (! VirtualMachineManager.ResoureCountRunningVMsonly.value()) { + _resourceLimitMgr.incrementResourceCount(accountId, ResourceType.user_vm, displayVm); + _resourceLimitMgr.incrementResourceCount(accountId, ResourceType.cpu, displayVm, cpu); + _resourceLimitMgr.incrementResourceCount(accountId, ResourceType.memory, displayVm, memory); + } } - private void resourceCountDecrement(long accountId, Boolean displayVm, Long cpu, Long memory) { - _resourceLimitMgr.decrementResourceCount(accountId, ResourceType.user_vm, displayVm); - _resourceLimitMgr.decrementResourceCount(accountId, ResourceType.cpu, displayVm, cpu); - _resourceLimitMgr.decrementResourceCount(accountId, ResourceType.memory, displayVm, memory); + protected void resourceCountDecrement(long accountId, Boolean displayVm, Long cpu, Long memory) { + if (! VirtualMachineManager.ResoureCountRunningVMsonly.value()) { + _resourceLimitMgr.decrementResourceCount(accountId, ResourceType.user_vm, displayVm); + _resourceLimitMgr.decrementResourceCount(accountId, ResourceType.cpu, displayVm, cpu); + _resourceLimitMgr.decrementResourceCount(accountId, ResourceType.memory, displayVm, memory); + } } public class VmAndCountDetails { @@ -1006,7 +1010,7 @@ public UserVm upgradeVirtualMachine(UpgradeVMCmd cmd) throws ResourceAllocationE if (newServiceOffering.isDynamic()) { newServiceOffering.setDynamicFlag(true); validateCustomParameters(newServiceOffering, cmd.getDetails()); - newServiceOffering = _offeringDao.getcomputeOffering(newServiceOffering, customParameters); + newServiceOffering = _offeringDao.getComputeOffering(newServiceOffering, customParameters); } ServiceOfferingVO currentServiceOffering = _offeringDao.findByIdIncludingRemoved(vmInstance.getId(), vmInstance.getServiceOfferingId()); @@ -1016,11 +1020,13 @@ public UserVm upgradeVirtualMachine(UpgradeVMCmd cmd) throws ResourceAllocationE int currentMemory = currentServiceOffering.getRamSize(); Account owner = _accountMgr.getActiveAccountById(vmInstance.getAccountId()); - if (newCpu > currentCpu) { - _resourceLimitMgr.checkResourceLimit(owner, ResourceType.cpu, newCpu - currentCpu); - } - if (newMemory > currentMemory) { - _resourceLimitMgr.checkResourceLimit(owner, ResourceType.memory, newMemory - currentMemory); + if (! VirtualMachineManager.ResoureCountRunningVMsonly.value()) { + if (newCpu > currentCpu) { + _resourceLimitMgr.checkResourceLimit(owner, ResourceType.cpu, newCpu - currentCpu); + } + if (newMemory > currentMemory) { + _resourceLimitMgr.checkResourceLimit(owner, ResourceType.memory, newMemory - currentMemory); + } } // Check that the specified service offering ID is valid @@ -1036,15 +1042,17 @@ public UserVm upgradeVirtualMachine(UpgradeVMCmd cmd) throws ResourceAllocationE } // Increment or decrement CPU and Memory count accordingly. - if (newCpu > currentCpu) { - _resourceLimitMgr.incrementResourceCount(owner.getAccountId(), ResourceType.cpu, new Long(newCpu - currentCpu)); - } else if (currentCpu > newCpu) { - _resourceLimitMgr.decrementResourceCount(owner.getAccountId(), ResourceType.cpu, new Long(currentCpu - newCpu)); - } - if (newMemory > currentMemory) { - _resourceLimitMgr.incrementResourceCount(owner.getAccountId(), ResourceType.memory, new Long(newMemory - currentMemory)); - } else if (currentMemory > newMemory) { - _resourceLimitMgr.decrementResourceCount(owner.getAccountId(), ResourceType.memory, new Long(currentMemory - newMemory)); + if (! VirtualMachineManager.ResoureCountRunningVMsonly.value()) { + if (newCpu > currentCpu) { + _resourceLimitMgr.incrementResourceCount(owner.getAccountId(), ResourceType.cpu, new Long(newCpu - currentCpu)); + } else if (currentCpu > newCpu) { + _resourceLimitMgr.decrementResourceCount(owner.getAccountId(), ResourceType.cpu, new Long(currentCpu - newCpu)); + } + if (newMemory > currentMemory) { + _resourceLimitMgr.incrementResourceCount(owner.getAccountId(), ResourceType.memory, new Long(newMemory - currentMemory)); + } else if (currentMemory > newMemory) { + _resourceLimitMgr.decrementResourceCount(owner.getAccountId(), ResourceType.memory, new Long(currentMemory - newMemory)); + } } // Generate usage event for VM upgrade @@ -1113,7 +1121,7 @@ private UserVm upgradeStoppedVirtualMachine(Long vmId, Long svcOffId, Map currentCpu) { - _resourceLimitMgr.checkResourceLimit(owner, ResourceType.cpu, newCpu - currentCpu); - } - if (newMemory > currentMemory) { - _resourceLimitMgr.checkResourceLimit(owner, ResourceType.memory, newMemory - currentMemory); + if (! VirtualMachineManager.ResoureCountRunningVMsonly.value()) { + if (newCpu > currentCpu) { + _resourceLimitMgr.checkResourceLimit(owner, ResourceType.cpu, newCpu - currentCpu); + } + if (newMemory > currentMemory) { + _resourceLimitMgr.checkResourceLimit(owner, ResourceType.memory, newMemory - currentMemory); + } } // Check that the specified service offering ID is valid @@ -1161,15 +1171,17 @@ private UserVm upgradeStoppedVirtualMachine(Long vmId, Long svcOffId, Map currentCpu) { - _resourceLimitMgr.incrementResourceCount(owner.getAccountId(), ResourceType.cpu, new Long(newCpu - currentCpu)); - } else if (currentCpu > newCpu) { - _resourceLimitMgr.decrementResourceCount(owner.getAccountId(), ResourceType.cpu, new Long(currentCpu - newCpu)); - } - if (newMemory > currentMemory) { - _resourceLimitMgr.incrementResourceCount(owner.getAccountId(), ResourceType.memory, new Long(newMemory - currentMemory)); - } else if (currentMemory > newMemory) { - _resourceLimitMgr.decrementResourceCount(owner.getAccountId(), ResourceType.memory, new Long(currentMemory - newMemory)); + if (! VirtualMachineManager.ResoureCountRunningVMsonly.value()) { + if (newCpu > currentCpu) { + _resourceLimitMgr.incrementResourceCount(owner.getAccountId(), ResourceType.cpu, new Long(newCpu - currentCpu)); + } else if (currentCpu > newCpu) { + _resourceLimitMgr.decrementResourceCount(owner.getAccountId(), ResourceType.cpu, new Long(currentCpu - newCpu)); + } + if (newMemory > currentMemory) { + _resourceLimitMgr.incrementResourceCount(owner.getAccountId(), ResourceType.memory, new Long(newMemory - currentMemory)); + } else if (currentMemory > newMemory) { + _resourceLimitMgr.decrementResourceCount(owner.getAccountId(), ResourceType.memory, new Long(currentMemory - newMemory)); + } } return _vmDao.findById(vmInstance.getId()); @@ -1759,7 +1771,7 @@ private boolean upgradeRunningVirtualMachine(Long vmId, Long newServiceOfferingI if (newServiceOffering.isDynamic()) { newServiceOffering.setDynamicFlag(true); validateCustomParameters(newServiceOffering, customParameters); - newServiceOffering = _offeringDao.getcomputeOffering(newServiceOffering, customParameters); + newServiceOffering = _offeringDao.getComputeOffering(newServiceOffering, customParameters); } // Check that the specified service offering ID is valid @@ -2057,7 +2069,9 @@ public UserVm recoverVirtualMachine(RecoverVMCmd cmd) throws ResourceAllocationE // First check that the maximum number of UserVMs, CPU and Memory limit for the given // accountId will not be exceeded - resourceLimitCheck(account, vm.isDisplayVm(), new Long(serviceOffering.getCpu()), new Long(serviceOffering.getRamSize())); + if (! VirtualMachineManager.ResoureCountRunningVMsonly.value()) { + resourceLimitCheck(account, vm.isDisplayVm(), new Long(serviceOffering.getCpu()), new Long(serviceOffering.getRamSize())); + } _haMgr.cancelDestroy(vm, vm.getHostId()); @@ -2220,11 +2234,6 @@ public boolean expunge(UserVmVO vm, long callerUserId, Account caller) { List rootVol = _volsDao.findByInstanceAndType(vm.getId(), Volume.Type.ROOT); // expunge the vm _itMgr.advanceExpunge(vm.getUuid()); - // Update Resource count - if (vm.getAccountId() != Account.ACCOUNT_ID_SYSTEM && !rootVol.isEmpty()) { - _resourceLimitMgr.decrementResourceCount(vm.getAccountId(), ResourceType.volume); - _resourceLimitMgr.decrementResourceCount(vm.getAccountId(), ResourceType.primary_storage, new Long(rootVol.get(0).getSize())); - } // Only if vm is not expunged already, cleanup it's resources if (vm.getRemoved() == null) { @@ -2549,9 +2558,11 @@ protected void updateDisplayVmFlag(Boolean isDisplayVm, Long id, UserVmVO vmInst // Resource limit changes ServiceOffering offering = _serviceOfferingDao.findByIdIncludingRemoved(vmInstance.getId(), vmInstance.getServiceOfferingId()); - _resourceLimitMgr.changeResourceCount(vmInstance.getAccountId(), ResourceType.user_vm, isDisplayVm); - _resourceLimitMgr.changeResourceCount(vmInstance.getAccountId(), ResourceType.cpu, isDisplayVm, new Long(offering.getCpu())); - _resourceLimitMgr.changeResourceCount(vmInstance.getAccountId(), ResourceType.memory, isDisplayVm, new Long(offering.getRamSize())); + if (isDisplayVm) { + resourceCountIncrement(vmInstance.getAccountId(), true, new Long(offering.getCpu()), new Long(offering.getRamSize())); + } else { + resourceCountDecrement(vmInstance.getAccountId(), true, new Long(offering.getCpu()), new Long(offering.getRamSize())); + } // Usage saveUsageEvent(vmInstance); @@ -2823,7 +2834,7 @@ protected boolean applyUserData(HypervisorType hyperVisorType, UserVm vm, Nic ni @Override @ActionEvent(eventType = EventTypes.EVENT_VM_START, eventDescription = "starting Vm", async = true) - public UserVm startVirtualMachine(StartVMCmd cmd) throws ExecutionException, ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException { + public UserVm startVirtualMachine(StartVMCmd cmd) throws ExecutionException, ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException, ResourceAllocationException { return startVirtualMachine(cmd.getId(), cmd.getPodId(), cmd.getClusterId(), cmd.getHostId(), null, cmd.getDeploymentPlanner()).first(); } @@ -3214,21 +3225,23 @@ public UserVm createAdvancedSecurityGroupVirtualMachine(DataCenter zone, Service throw new InvalidParameterValueException("Security group feature is not supported for vmWare hypervisor"); } // Only one network can be specified, and it should be security group enabled - if (networkIdList.size() > 1) { + if (networkIdList.size() > 1 && template.getHypervisorType() != HypervisorType.KVM && hypervisor != HypervisorType.KVM) { throw new InvalidParameterValueException("Only support one network per VM if security group enabled"); } - NetworkVO network = _networkDao.findById(networkIdList.get(0)); + for (Long networkId : networkIdList) { + NetworkVO network = _networkDao.findById(networkId); - if (network == null) { - throw new InvalidParameterValueException("Unable to find network by id " + networkIdList.get(0).longValue()); - } + if (network == null) { + throw new InvalidParameterValueException("Unable to find network by id " + networkId); + } - if (!_networkModel.isSecurityGroupSupportedInNetwork(network)) { - throw new InvalidParameterValueException("Network is not security group enabled: " + network.getId()); - } + if (!_networkModel.isSecurityGroupSupportedInNetwork(network)) { + throw new InvalidParameterValueException("Network is not security group enabled: " + network.getId()); + } - networkList.add(network); + networkList.add(network); + } isSecurityGroupEnabledNetworkUsed = true; } else { @@ -3242,10 +3255,6 @@ public UserVm createAdvancedSecurityGroupVirtualMachine(DataCenter zone, Service boolean isSecurityGroupEnabled = _networkModel.isSecurityGroupSupportedInNetwork(network); if (isSecurityGroupEnabled) { - if (networkIdList.size() > 1) { - throw new InvalidParameterValueException("Can't create a vm with multiple networks one of" + " which is Security Group enabled"); - } - isSecurityGroupEnabledNetworkUsed = true; } @@ -3343,7 +3352,7 @@ public UserVm createAdvancedVirtualMachine(DataCenter zone, ServiceOffering serv } s_logger.debug("Creating network for account " + owner + " from the network offering id=" + requiredOfferings.get(0).getId() + " as a part of deployVM process"); Network newNetwork = _networkMgr.createGuestNetwork(requiredOfferings.get(0).getId(), owner.getAccountName() + "-network", owner.getAccountName() + "-network", - null, null, null, false, null, owner, null, physicalNetwork, zone.getId(), ACLType.Account, null, null, null, null, true, null, + null, null, null, false, null, owner, null, physicalNetwork, zone.getId(), ACLType.Account, null, null, null, null, true, null, null, null); if (newNetwork != null) { defaultNetwork = _networkDao.findById(newNetwork.getId()); @@ -3482,7 +3491,7 @@ private UserVm createVirtualMachine(DataCenter zone, ServiceOffering serviceOffe if (offering.isDynamic()) { offering.setDynamicFlag(true); validateCustomParameters(offering, customParameters); - offering = _offeringDao.getcomputeOffering(offering, customParameters); + offering = _offeringDao.getComputeOffering(offering, customParameters); } // check if account/domain is with in resource limits to create a new vm boolean isIso = Storage.ImageFormat.ISO == template.getFormat(); @@ -3522,7 +3531,9 @@ private UserVm createVirtualMachine(DataCenter zone, ServiceOffering serviceOffe } size += _diskOfferingDao.findById(diskOfferingId).getDiskSize(); } - resourceLimitCheck(owner, isDisplayVm, new Long(offering.getCpu()), new Long(offering.getRamSize())); + if (! VirtualMachineManager.ResoureCountRunningVMsonly.value()) { + resourceLimitCheck(owner, isDisplayVm, new Long(offering.getCpu()), new Long(offering.getRamSize())); + } _resourceLimitMgr.checkResourceLimit(owner, ResourceType.volume, (isIso || diskOfferingId == null ? 1 : 2)); _resourceLimitMgr.checkResourceLimit(owner, ResourceType.primary_storage, size); @@ -3851,12 +3862,12 @@ private String generateHostName(String uuidName) { return _instance + "-" + uuidName; } - private UserVmVO commitUserVm(final DataCenter zone, final VirtualMachineTemplate template, final String hostName, final String displayName, final Account owner, - final Long diskOfferingId, final Long diskSize, final String userData, final Account caller, final Boolean isDisplayVm, final String keyboard, - final long accountId, final long userId, final ServiceOfferingVO offering, final boolean isIso, final String sshPublicKey, final LinkedHashMap networkNicMap, - final long id, final String instanceName, final String uuidName, final HypervisorType hypervisorType, final Map customParameters, final Map> extraDhcpOptionMap, final Map dataDiskTemplateToDiskOfferingMap, - Map userVmOVFPropertiesMap) throws InsufficientCapacityException { + private UserVmVO commitUserVm(final boolean isImport, final DataCenter zone, final Host host, final Host lastHost, final VirtualMachineTemplate template, final String hostName, final String displayName, final Account owner, + final Long diskOfferingId, final Long diskSize, final String userData, final Account caller, final Boolean isDisplayVm, final String keyboard, + final long accountId, final long userId, final ServiceOffering offering, final boolean isIso, final String sshPublicKey, final LinkedHashMap networkNicMap, + final long id, final String instanceName, final String uuidName, final HypervisorType hypervisorType, final Map customParameters, + final Map> extraDhcpOptionMap, final Map dataDiskTemplateToDiskOfferingMap, + final Map userVmOVFPropertiesMap, final VirtualMachine.PowerState powerState) throws InsufficientCapacityException { return Transaction.execute(new TransactionCallbackWithException() { @Override public UserVmVO doInTransaction(TransactionStatus status) throws InsufficientCapacityException { @@ -3878,7 +3889,7 @@ public UserVmVO doInTransaction(TransactionStatus status) throws InsufficientCap vm.setDetail(VmDetailConstants.KEYBOARD, keyboard); } - if (isIso) { + if (!isImport && isIso) { vm.setIsoId(template.getId()); } Long rootDiskSize = null; @@ -3930,9 +3941,21 @@ public UserVmVO doInTransaction(TransactionStatus status) throws InsufficientCap } } + if (isImport) { + vm.setDataCenterId(zone.getId()); + vm.setHostId(host.getId()); + if (lastHost != null) { + vm.setLastHostId(lastHost.getId()); + } + vm.setPowerState(powerState); + if (powerState == VirtualMachine.PowerState.PowerOn) { + vm.setState(State.Running); + } + } + _vmDao.persist(vm); for (String key : customParameters.keySet()) { - if( key.equalsIgnoreCase(VmDetailConstants.CPU_NUMBER) || + if (key.equalsIgnoreCase(VmDetailConstants.CPU_NUMBER) || key.equalsIgnoreCase(VmDetailConstants.CPU_SPEED) || key.equalsIgnoreCase(VmDetailConstants.MEMORY)) { // handle double byte strings. @@ -3966,45 +3989,62 @@ public UserVmVO doInTransaction(TransactionStatus status) throws InsufficientCap } _vmDao.saveDetails(vm); + if (!isImport) { + s_logger.debug("Allocating in the DB for vm"); + DataCenterDeployment plan = new DataCenterDeployment(zone.getId()); - s_logger.debug("Allocating in the DB for vm"); - DataCenterDeployment plan = new DataCenterDeployment(zone.getId()); - - List computeTags = new ArrayList(); - computeTags.add(offering.getHostTag()); + List computeTags = new ArrayList(); + computeTags.add(offering.getHostTag()); - List rootDiskTags = new ArrayList(); - rootDiskTags.add(offering.getTags()); + List rootDiskTags = new ArrayList(); + rootDiskTags.add(offering.getTags()); - if (isIso) { - _orchSrvc.createVirtualMachineFromScratch(vm.getUuid(), Long.toString(owner.getAccountId()), vm.getIsoId().toString(), hostName, displayName, - hypervisorType.name(), guestOSCategory.getName(), offering.getCpu(), offering.getSpeed(), offering.getRamSize(), diskSize, computeTags, rootDiskTags, - networkNicMap, plan, extraDhcpOptionMap); - } else { - _orchSrvc.createVirtualMachine(vm.getUuid(), Long.toString(owner.getAccountId()), Long.toString(template.getId()), hostName, displayName, hypervisorType.name(), - offering.getCpu(), offering.getSpeed(), offering.getRamSize(), diskSize, computeTags, rootDiskTags, networkNicMap, plan, rootDiskSize, extraDhcpOptionMap, dataDiskTemplateToDiskOfferingMap); - } + if (isIso) { + _orchSrvc.createVirtualMachineFromScratch(vm.getUuid(), Long.toString(owner.getAccountId()), vm.getIsoId().toString(), hostName, displayName, + hypervisorType.name(), guestOSCategory.getName(), offering.getCpu(), offering.getSpeed(), offering.getRamSize(), diskSize, computeTags, rootDiskTags, + networkNicMap, plan, extraDhcpOptionMap); + } else { + _orchSrvc.createVirtualMachine(vm.getUuid(), Long.toString(owner.getAccountId()), Long.toString(template.getId()), hostName, displayName, hypervisorType.name(), + offering.getCpu(), offering.getSpeed(), offering.getRamSize(), diskSize, computeTags, rootDiskTags, networkNicMap, plan, rootDiskSize, extraDhcpOptionMap, dataDiskTemplateToDiskOfferingMap); + } - if (s_logger.isDebugEnabled()) { - s_logger.debug("Successfully allocated DB entry for " + vm); + if (s_logger.isDebugEnabled()) { + s_logger.debug("Successfully allocated DB entry for " + vm); + } } CallContext.current().setEventDetails("Vm Id: " + vm.getUuid()); - if (!offering.isDynamic()) { - UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VM_CREATE, accountId, zone.getId(), vm.getId(), vm.getHostName(), offering.getId(), template.getId(), - hypervisorType.toString(), VirtualMachine.class.getName(), vm.getUuid(), vm.isDisplayVm()); - } else { - UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VM_CREATE, accountId, zone.getId(), vm.getId(), vm.getHostName(), offering.getId(), template.getId(), - hypervisorType.toString(), VirtualMachine.class.getName(), vm.getUuid(), customParameters, vm.isDisplayVm()); - } + if (!isImport) { + if (!offering.isDynamic()) { + UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VM_CREATE, accountId, zone.getId(), vm.getId(), vm.getHostName(), offering.getId(), template.getId(), + hypervisorType.toString(), VirtualMachine.class.getName(), vm.getUuid(), vm.isDisplayVm()); + } else { + UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VM_CREATE, accountId, zone.getId(), vm.getId(), vm.getHostName(), offering.getId(), template.getId(), + hypervisorType.toString(), VirtualMachine.class.getName(), vm.getUuid(), customParameters, vm.isDisplayVm()); + } - //Update Resource Count for the given account - resourceCountIncrement(accountId, isDisplayVm, new Long(offering.getCpu()), new Long(offering.getRamSize())); + //Update Resource Count for the given account + resourceCountIncrement(accountId, isDisplayVm, new Long(offering.getCpu()), new Long(offering.getRamSize())); + } return vm; } }); } + private UserVmVO commitUserVm(final DataCenter zone, final VirtualMachineTemplate template, final String hostName, final String displayName, final Account owner, + final Long diskOfferingId, final Long diskSize, final String userData, final Account caller, final Boolean isDisplayVm, final String keyboard, + final long accountId, final long userId, final ServiceOfferingVO offering, final boolean isIso, final String sshPublicKey, final LinkedHashMap networkNicMap, + final long id, final String instanceName, final String uuidName, final HypervisorType hypervisorType, final Map customParameters, final Map> extraDhcpOptionMap, final Map dataDiskTemplateToDiskOfferingMap, + Map userVmOVFPropertiesMap) throws InsufficientCapacityException { + return commitUserVm(false, zone, null, null, template, hostName, displayName, owner, + diskOfferingId, diskSize, userData, caller, isDisplayVm, keyboard, + accountId, userId, offering, isIso, sshPublicKey, networkNicMap, + id, instanceName, uuidName, hypervisorType, customParameters, + extraDhcpOptionMap, dataDiskTemplateToDiskOfferingMap, + userVmOVFPropertiesMap, null); + } + public void validateRootDiskResize(final HypervisorType hypervisorType, Long rootDiskSize, VMTemplateVO templateVO, UserVmVO vm, final Map customParameters) throws InvalidParameterValueException { // rootdisksize must be larger than template. @@ -4237,7 +4277,7 @@ protected String validateUserData(String userData, HTTPMethod httpmethod) { @Override @ActionEvent(eventType = EventTypes.EVENT_VM_CREATE, eventDescription = "starting Vm", async = true) - public UserVm startVirtualMachine(DeployVMCmd cmd) throws ResourceUnavailableException, InsufficientCapacityException, ConcurrentOperationException { + public UserVm startVirtualMachine(DeployVMCmd cmd) throws ResourceUnavailableException, InsufficientCapacityException, ConcurrentOperationException, ResourceAllocationException { long vmId = cmd.getEntityId(); Long podId = null; Long clusterId = null; @@ -4253,7 +4293,7 @@ public UserVm startVirtualMachine(DeployVMCmd cmd) throws ResourceUnavailableExc private UserVm startVirtualMachine(long vmId, Long podId, Long clusterId, Long hostId, Map diskOfferingMap, Map additonalParams, String deploymentPlannerToUse) throws ResourceUnavailableException, - InsufficientCapacityException, ConcurrentOperationException { + InsufficientCapacityException, ConcurrentOperationException, ResourceAllocationException { UserVmVO vm = _vmDao.findById(vmId); Pair> vmParamPair = null; @@ -4581,13 +4621,13 @@ public void finalizeStop(VirtualMachineProfile profile, Answer answer) { @Override public Pair> startVirtualMachine(long vmId, Long hostId, Map additionalParams, String deploymentPlannerToUse) - throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException { + throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException, ResourceAllocationException { return startVirtualMachine(vmId, null, null, hostId, additionalParams, deploymentPlannerToUse); } @Override public Pair> startVirtualMachine(long vmId, Long podId, Long clusterId, Long hostId, Map additionalParams, String deploymentPlannerToUse) - throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException { + throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException, ResourceAllocationException { // Input validation final Account callerAccount = CallContext.current().getCallingAccount(); UserVO callerUser = _userDao.findById(CallContext.current().getCallingUserId()); @@ -4613,6 +4653,11 @@ public Pair> startVirtualMach if (owner.getState() == Account.State.disabled) { throw new PermissionDeniedException("The owner of " + vm + " is disabled: " + vm.getAccountId()); } + if (VirtualMachineManager.ResoureCountRunningVMsonly.value()) { + // check if account/domain is with in resource limits to start a new vm + ServiceOfferingVO offering = _serviceOfferingDao.findById(vm.getId(), vm.getServiceOfferingId()); + resourceLimitCheck(owner, vm.isDisplayVm(), new Long(offering.getCpu()), new Long(offering.getRamSize())); + } // check if vm is security group enabled if (_securityGroupMgr.isVmSecurityGroupEnabled(vmId) && _securityGroupMgr.getSecurityGroupsForVm(vmId).isEmpty() @@ -6123,7 +6168,9 @@ public UserVm moveVMToUser(final AssignVMCmd cmd) throws ResourceAllocationExcep removeInstanceFromInstanceGroup(cmd.getVmId()); // VV 2: check if account/domain is with in resource limits to create a new vm - resourceLimitCheck(newAccount, vm.isDisplayVm(), new Long(offering.getCpu()), new Long(offering.getRamSize())); + if (! VirtualMachineManager.ResoureCountRunningVMsonly.value()) { + resourceLimitCheck(newAccount, vm.isDisplayVm(), new Long(offering.getCpu()), new Long(offering.getRamSize())); + } // VV 3: check if volumes and primary storage space are with in resource limits _resourceLimitMgr.checkResourceLimit(newAccount, ResourceType.volume, _volsDao.findByInstance(cmd.getVmId()).size()); @@ -6134,7 +6181,10 @@ public UserVm moveVMToUser(final AssignVMCmd cmd) throws ResourceAllocationExcep _resourceLimitMgr.checkResourceLimit(newAccount, ResourceType.primary_storage, totalVolumesSize); // VV 4: Check if new owner can use the vm template - VirtualMachineTemplate template = _templateDao.findById(vm.getTemplateId()); + VirtualMachineTemplate template = _templateDao.findByIdIncludingRemoved(vm.getTemplateId()); + if (template == null) { + throw new InvalidParameterValueException(String.format("Template for VM: %s cannot be found", vm.getUuid())); + } if (!template.isPublicTemplate()) { Account templateOwner = _accountMgr.getAccount(template.getAccountId()); _accountMgr.checkAccess(newAccount, null, true, templateOwner); @@ -6176,7 +6226,9 @@ public void doInTransactionWithoutResult(TransactionStatus status) { } //update resource count of new account - resourceCountIncrement(newAccount.getAccountId(), vm.isDisplayVm(), new Long(offering.getCpu()), new Long(offering.getRamSize())); + if (! VirtualMachineManager.ResoureCountRunningVMsonly.value()) { + resourceCountIncrement(newAccount.getAccountId(), vm.isDisplayVm(), new Long(offering.getCpu()), new Long(offering.getRamSize())); + } //generate usage events to account for this change UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VM_CREATE, vm.getAccountId(), vm.getDataCenterId(), vm.getId(), @@ -6457,7 +6509,7 @@ public void doInTransactionWithoutResult(TransactionStatus status) { Network newNetwork = _networkMgr.createGuestNetwork(requiredOfferings.get(0).getId(), newAccount.getAccountName() + "-network", newAccount.getAccountName() + "-network", null, null, null, false, null, newAccount, null, physicalNetwork, zone.getId(), ACLType.Account, null, null, - null, null, true, null, null); + null, null, true, null, null, null); // if the network offering has persistent set to true, implement the network if (requiredOfferings.get(0).isPersistent()) { DeployDestination dest = new DeployDestination(zone, null, null, null); @@ -7018,4 +7070,32 @@ private void deleteVolumesFromVm(List volumes) { } } } -} + + @Override + public UserVm importVM(final DataCenter zone, final Host host, final VirtualMachineTemplate template, final String instanceName, final String displayName, + final Account owner, final String userData, final Account caller, final Boolean isDisplayVm, final String keyboard, + final long accountId, final long userId, final ServiceOffering serviceOffering, final String sshPublicKey, + final String hostName, final HypervisorType hypervisorType, final Map customParameters, final VirtualMachine.PowerState powerState) throws InsufficientCapacityException { + if (zone == null) { + throw new InvalidParameterValueException("Unable to import virtual machine with invalid zone"); + } + if (host == null) { + throw new InvalidParameterValueException("Unable to import virtual machine with invalid host"); + } + + final long id = _vmDao.getNextInSequence(Long.class, "id"); + + if (hostName != null) { + // Check is hostName is RFC compliant + checkNameForRFCCompliance(hostName); + } + + final String uuidName = _uuidMgr.generateUuid(UserVm.class, null); + final Host lastHost = powerState != VirtualMachine.PowerState.PowerOn ? host : null; + return commitUserVm(true, zone, host, lastHost, template, hostName, displayName, owner, + null, null, userData, caller, isDisplayVm, keyboard, + accountId, userId, serviceOffering, template.getFormat().equals(ImageFormat.ISO), sshPublicKey, null, + id, instanceName, uuidName, hypervisorType, customParameters, + null, null, null, powerState); + } +} \ No newline at end of file diff --git a/server/src/main/java/org/apache/cloudstack/agent/lb/IndirectAgentLBServiceImpl.java b/server/src/main/java/org/apache/cloudstack/agent/lb/IndirectAgentLBServiceImpl.java index 0e9b32cb5dd7..8742e2dfe6f3 100644 --- a/server/src/main/java/org/apache/cloudstack/agent/lb/IndirectAgentLBServiceImpl.java +++ b/server/src/main/java/org/apache/cloudstack/agent/lb/IndirectAgentLBServiceImpl.java @@ -34,13 +34,10 @@ import org.apache.cloudstack.config.ApiServiceConfiguration; import org.apache.cloudstack.framework.config.ConfigKey; import org.apache.cloudstack.framework.config.Configurable; -import org.apache.cloudstack.framework.messagebus.MessageBus; -import org.apache.cloudstack.framework.messagebus.MessageSubscriber; import org.apache.log4j.Logger; import com.cloud.agent.AgentManager; import com.cloud.agent.api.Answer; -import com.cloud.event.EventTypes; import com.cloud.host.Host; import com.cloud.host.HostVO; import com.cloud.host.dao.HostDao; @@ -68,8 +65,6 @@ public class IndirectAgentLBServiceImpl extends ComponentLifecycleBase implement @Inject private HostDao hostDao; @Inject - private MessageBus messageBus; - @Inject private AgentManager agentManager; ////////////////////////////////////////////////////// @@ -208,7 +203,8 @@ private org.apache.cloudstack.agent.lb.IndirectAgentLBAlgorithm getAgentMSLBAlgo /////////////// Agent MSLB Configuration /////////////////// //////////////////////////////////////////////////////////// - private void propagateMSListToAgents() { + @Override + public void propagateMSListToAgents() { LOG.debug("Propagating management server list update to agents"); final String lbAlgorithm = getLBAlgorithmName(); final Map> dcOrderedHostsMap = new HashMap<>(); @@ -227,22 +223,6 @@ private void propagateMSListToAgents() { } } - private void configureMessageBusListener() { - messageBus.subscribe(EventTypes.EVENT_CONFIGURATION_VALUE_EDIT, new MessageSubscriber() { - @Override - public void onPublishMessage(final String senderAddress, String subject, Object args) { - final String globalSettingUpdated = (String) args; - if (Strings.isNullOrEmpty(globalSettingUpdated)) { - return; - } - if (globalSettingUpdated.equals(ApiServiceConfiguration.ManagementServerAddresses.key()) || - globalSettingUpdated.equals(IndirectAgentLBAlgorithm.key())) { - propagateMSListToAgents(); - } - } - }); - } - private void configureAlgorithmMap() { final List algorithms = new ArrayList<>(); algorithms.add(new IndirectAgentLBStaticAlgorithm()); @@ -258,7 +238,6 @@ private void configureAlgorithmMap() { public boolean configure(final String name, final Map params) throws ConfigurationException { super.configure(name, params); configureAlgorithmMap(); - configureMessageBusListener(); return true; } @@ -274,4 +253,4 @@ public ConfigKey[] getConfigKeys() { IndirectAgentLBCheckInterval }; } -} \ No newline at end of file +} diff --git a/server/src/main/java/org/apache/cloudstack/storage/NfsMountManagerImpl.java b/server/src/main/java/org/apache/cloudstack/storage/NfsMountManagerImpl.java index 50ef13654512..479ee12a5fa9 100644 --- a/server/src/main/java/org/apache/cloudstack/storage/NfsMountManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/storage/NfsMountManagerImpl.java @@ -163,16 +163,16 @@ private void deleteMountPath(String localRootPath) { private boolean mountExists(String localRootPath) { Script script = new Script(true, "mount", timeout, s_logger); - ZfsPathParser parser = new ZfsPathParser(localRootPath); + PathParser parser = new PathParser(localRootPath); script.execute(parser); return parser.getPaths().stream().filter(s -> s.contains(localRootPath)).findAny().map(s -> true).orElse(false); } - public static class ZfsPathParser extends OutputInterpreter { + public static class PathParser extends OutputInterpreter { String _parent; List paths = new ArrayList<>(); - public ZfsPathParser(String parent) { + public PathParser(String parent) { _parent = parent; } diff --git a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java new file mode 100644 index 000000000000..1856a125661e --- /dev/null +++ b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java @@ -0,0 +1,1216 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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. + +package org.apache.cloudstack.vm; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import javax.inject.Inject; + +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.ResponseGenerator; +import org.apache.cloudstack.api.ResponseObject; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.command.admin.vm.ImportUnmanagedInstanceCmd; +import org.apache.cloudstack.api.command.admin.vm.ListUnmanagedInstancesCmd; +import org.apache.cloudstack.api.response.ListResponse; +import org.apache.cloudstack.api.response.NicResponse; +import org.apache.cloudstack.api.response.UnmanagedInstanceDiskResponse; +import org.apache.cloudstack.api.response.UnmanagedInstanceResponse; +import org.apache.cloudstack.api.response.UserVmResponse; +import org.apache.cloudstack.context.CallContext; +import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService; +import org.apache.cloudstack.engine.orchestration.service.VolumeOrchestrationService; +import org.apache.cloudstack.framework.config.dao.ConfigurationDao; +import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; +import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; +import org.apache.cloudstack.utils.volume.VirtualMachineDiskInfo; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections.MapUtils; +import org.apache.log4j.Logger; + +import com.cloud.agent.AgentManager; +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.GetUnmanagedInstancesAnswer; +import com.cloud.agent.api.GetUnmanagedInstancesCommand; +import com.cloud.capacity.CapacityManager; +import com.cloud.configuration.Config; +import com.cloud.configuration.Resource; +import com.cloud.dc.DataCenter; +import com.cloud.dc.dao.ClusterDao; +import com.cloud.dc.dao.DataCenterDao; +import com.cloud.deploy.DataCenterDeployment; +import com.cloud.deploy.DeployDestination; +import com.cloud.deploy.DeploymentPlanner; +import com.cloud.deploy.DeploymentPlanningManager; +import com.cloud.event.EventTypes; +import com.cloud.event.UsageEventUtils; +import com.cloud.exception.InsufficientAddressCapacityException; +import com.cloud.exception.InsufficientCapacityException; +import com.cloud.exception.InsufficientVirtualNetworkCapacityException; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.exception.PermissionDeniedException; +import com.cloud.exception.ResourceAllocationException; +import com.cloud.host.Host; +import com.cloud.host.HostVO; +import com.cloud.host.Status; +import com.cloud.host.dao.HostDao; +import com.cloud.hypervisor.Hypervisor; +import com.cloud.network.Network; +import com.cloud.network.NetworkModel; +import com.cloud.network.Networks; +import com.cloud.network.dao.NetworkDao; +import com.cloud.network.dao.NetworkVO; +import com.cloud.offering.DiskOffering; +import com.cloud.offering.ServiceOffering; +import com.cloud.org.Cluster; +import com.cloud.resource.ResourceManager; +import com.cloud.serializer.GsonHelper; +import com.cloud.server.ManagementService; +import com.cloud.service.ServiceOfferingVO; +import com.cloud.service.dao.ServiceOfferingDao; +import com.cloud.storage.GuestOS; +import com.cloud.storage.GuestOSHypervisor; +import com.cloud.storage.Storage; +import com.cloud.storage.StoragePool; +import com.cloud.storage.VMTemplateStoragePoolVO; +import com.cloud.storage.VMTemplateVO; +import com.cloud.storage.Volume; +import com.cloud.storage.VolumeApiService; +import com.cloud.storage.VolumeVO; +import com.cloud.storage.dao.DiskOfferingDao; +import com.cloud.storage.dao.GuestOSDao; +import com.cloud.storage.dao.GuestOSHypervisorDao; +import com.cloud.storage.dao.VMTemplateDao; +import com.cloud.storage.dao.VMTemplatePoolDao; +import com.cloud.storage.dao.VolumeDao; +import com.cloud.template.VirtualMachineTemplate; +import com.cloud.user.Account; +import com.cloud.user.AccountService; +import com.cloud.user.ResourceLimitService; +import com.cloud.user.UserVO; +import com.cloud.user.dao.UserDao; +import com.cloud.uservm.UserVm; +import com.cloud.utils.Pair; +import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.utils.net.NetUtils; +import com.cloud.vm.DiskProfile; +import com.cloud.vm.NicProfile; +import com.cloud.vm.UserVmManager; +import com.cloud.vm.VMInstanceVO; +import com.cloud.vm.VirtualMachine; +import com.cloud.vm.VirtualMachineManager; +import com.cloud.vm.VirtualMachineProfile; +import com.cloud.vm.VirtualMachineProfileImpl; +import com.cloud.vm.VmDetailConstants; +import com.cloud.vm.dao.NicDao; +import com.cloud.vm.dao.VMInstanceDao; +import com.google.common.base.Strings; +import com.google.gson.Gson; + +public class VmImportManagerImpl implements VmImportService { + public static final String VM_IMPORT_DEFAULT_TEMPLATE_NAME = "system-default-vm-import-dummy-template.iso"; + private static final Logger LOGGER = Logger.getLogger(VmImportManagerImpl.class); + + @Inject + private AgentManager agentManager; + @Inject + private DataCenterDao dataCenterDao; + @Inject + private ClusterDao clusterDao; + @Inject + private HostDao hostDao; + @Inject + private AccountService accountService; + @Inject + private UserDao userDao; + @Inject + private VMTemplateDao templateDao; + @Inject + private VMTemplatePoolDao templatePoolDao; + @Inject + private ServiceOfferingDao serviceOfferingDao; + @Inject + private DiskOfferingDao diskOfferingDao; + @Inject + private ResourceManager resourceManager; + @Inject + private ResourceLimitService resourceLimitService; + @Inject + private UserVmManager userVmManager; + @Inject + private ResponseGenerator responseGenerator; + @Inject + private VolumeOrchestrationService volumeManager; + @Inject + private VolumeDao volumeDao; + @Inject + private PrimaryDataStoreDao primaryDataStoreDao; + @Inject + private NetworkDao networkDao; + @Inject + private NetworkOrchestrationService networkOrchestrationService; + @Inject + private VMInstanceDao vmDao; + @Inject + private CapacityManager capacityManager; + @Inject + private VolumeApiService volumeApiService; + @Inject + private DeploymentPlanningManager deploymentPlanningManager; + @Inject + private VirtualMachineManager virtualMachineManager; + @Inject + private ManagementService managementService; + @Inject + private NicDao nicDao; + @Inject + private NetworkModel networkModel; + @Inject + private ConfigurationDao configurationDao; + @Inject + private GuestOSDao guestOSDao; + @Inject + private GuestOSHypervisorDao guestOSHypervisorDao; + + protected Gson gson; + + public VmImportManagerImpl() { + gson = GsonHelper.getGsonLogger(); + } + + private VMTemplateVO createDefaultDummyVmImportTemplate() { + VMTemplateVO template = null; + try { + template = VMTemplateVO.createSystemIso(templateDao.getNextInSequence(Long.class, "id"), VM_IMPORT_DEFAULT_TEMPLATE_NAME, VM_IMPORT_DEFAULT_TEMPLATE_NAME, true, + "", true, 64, Account.ACCOUNT_ID_SYSTEM, "", + "VM Import Default Template", false, 1); + template.setState(VirtualMachineTemplate.State.Inactive); + template = templateDao.persist(template); + if (template == null) { + return null; + } + templateDao.remove(template.getId()); + template = templateDao.findByName(VM_IMPORT_DEFAULT_TEMPLATE_NAME); + } catch (Exception e) { + LOGGER.error("Unable to create default dummy template for VM import", e); + } + return template; + } + + private UnmanagedInstanceResponse createUnmanagedInstanceResponse(UnmanagedInstanceTO instance, Cluster cluster, Host host) { + UnmanagedInstanceResponse response = new UnmanagedInstanceResponse(); + response.setName(instance.getName()); + if (cluster != null) { + response.setClusterId(cluster.getUuid()); + } + if (host != null) { + response.setHostId(host.getUuid()); + } + response.setPowerState(instance.getPowerState().toString()); + response.setCpuCores(instance.getCpuCores()); + response.setCpuSpeed(instance.getCpuSpeed()); + response.setCpuCoresPerSocket(instance.getCpuCoresPerSocket()); + response.setMemory(instance.getMemory()); + response.setOperatingSystemId(instance.getOperatingSystemId()); + response.setOperatingSystem(instance.getOperatingSystem()); + response.setObjectName("unmanagedinstance"); + + if (instance.getDisks() != null) { + for (UnmanagedInstanceTO.Disk disk : instance.getDisks()) { + UnmanagedInstanceDiskResponse diskResponse = new UnmanagedInstanceDiskResponse(); + diskResponse.setDiskId(disk.getDiskId()); + if (!Strings.isNullOrEmpty(disk.getLabel())) { + diskResponse.setLabel(disk.getLabel()); + } + diskResponse.setCapacity(disk.getCapacity()); + diskResponse.setController(disk.getController()); + diskResponse.setControllerUnit(disk.getControllerUnit()); + diskResponse.setPosition(disk.getPosition()); + diskResponse.setImagePath(disk.getImagePath()); + diskResponse.setDatastoreName(disk.getDatastoreName()); + diskResponse.setDatastoreHost(disk.getDatastoreHost()); + diskResponse.setDatastorePath(disk.getDatastorePath()); + diskResponse.setDatastoreType(disk.getDatastoreType()); + response.addDisk(diskResponse); + } + } + + if (instance.getNics() != null) { + for (UnmanagedInstanceTO.Nic nic : instance.getNics()) { + NicResponse nicResponse = new NicResponse(); + nicResponse.setId(nic.getNicId()); + nicResponse.setNetworkName(nic.getNetwork()); + nicResponse.setMacAddress(nic.getMacAddress()); + if (!Strings.isNullOrEmpty(nic.getAdapterType())) { + nicResponse.setAdapterType(nic.getAdapterType()); + } + if (!CollectionUtils.isEmpty(nic.getIpAddress())) { + nicResponse.setIpAddresses(nic.getIpAddress()); + } + nicResponse.setVlanId(nic.getVlan()); + nicResponse.setIsolatedPvlanId(nic.getPvlan()); + nicResponse.setIsolatedPvlanType(nic.getPvlanType()); + response.addNic(nicResponse); + } + } + return response; + } + + private List getAdditionalNameFilters(Cluster cluster) { + List additionalNameFilter = new ArrayList<>(); + if (cluster == null) { + return additionalNameFilter; + } + if (cluster.getHypervisorType() == Hypervisor.HypervisorType.VMware) { + // VMWare considers some templates as VM and they are not filtered by VirtualMachineMO.isTemplate() + List templates = templatePoolDao.listAll(); + for (VMTemplateStoragePoolVO template : templates) { + additionalNameFilter.add(template.getInstallPath()); + } + + // VMWare considers some removed volumes as VM + List volumes = volumeDao.findIncludingRemovedByZone(cluster.getDataCenterId()); + for (VolumeVO volumeVO : volumes) { + if (volumeVO.getRemoved() == null) { + continue; + } + if (Strings.isNullOrEmpty(volumeVO.getChainInfo())) { + continue; + } + List volumeFileNames = new ArrayList<>(); + try { + VirtualMachineDiskInfo diskInfo = gson.fromJson(volumeVO.getChainInfo(), VirtualMachineDiskInfo.class); + String[] files = diskInfo.getDiskChain(); + if (files.length == 1) { + continue; + } + boolean firstFile = true; + for (final String file : files) { + if (firstFile) { + firstFile = false; + continue; + } + String path = file; + String[] split = path.split(" "); + path = split[split.length - 1]; + split = path.split("/"); + ; + path = split[split.length - 1]; + split = path.split("\\."); + path = split[0]; + if (!Strings.isNullOrEmpty(path)) { + if (!additionalNameFilter.contains(path)) { + volumeFileNames.add(path); + } + if (path.contains("-")) { + split = path.split("-"); + path = split[0]; + if (!Strings.isNullOrEmpty(path) && !path.equals("ROOT") && !additionalNameFilter.contains(path)) { + volumeFileNames.add(path); + } + } + } + } + } catch (Exception e) { + LOGGER.warn(String.format("Unable to find volume file name for volume ID: %s while adding filters unmanaged VMs", volumeVO.getUuid()), e); + } + if (!volumeFileNames.isEmpty()) { + additionalNameFilter.addAll(volumeFileNames); + } + } + } + return additionalNameFilter; + } + + private List getHostManagedVms(Host host) { + List managedVms = new ArrayList<>(); + List instances = vmDao.listByHostId(host.getId()); + for (VMInstanceVO instance : instances) { + managedVms.add(instance.getInstanceName()); + } + instances = vmDao.listByLastHostIdAndStates(host.getId(), + VirtualMachine.State.Stopped, VirtualMachine.State.Destroyed, + VirtualMachine.State.Expunging, VirtualMachine.State.Error, + VirtualMachine.State.Unknown, VirtualMachine.State.Shutdown); + for (VMInstanceVO instance : instances) { + managedVms.add(instance.getInstanceName()); + } + return managedVms; + } + + private boolean hostSupportsServiceOffering(HostVO host, ServiceOffering serviceOffering) { + if (host == null) { + return false; + } + if (serviceOffering == null) { + return false; + } + if (Strings.isNullOrEmpty(serviceOffering.getHostTag())) { + return true; + } + hostDao.loadHostTags(host); + return host.getHostTags() != null && host.getHostTags().contains(serviceOffering.getHostTag()); + } + + private boolean storagePoolSupportsDiskOffering(StoragePool pool, DiskOffering diskOffering) { + if (pool == null) { + return false; + } + if (diskOffering == null) { + return false; + } + return volumeApiService.doesTargetStorageSupportDiskOffering(pool, diskOffering.getTags()); + } + + private boolean storagePoolSupportsServiceOffering(StoragePool pool, ServiceOffering serviceOffering) { + if (pool == null) { + return false; + } + if (serviceOffering == null) { + return false; + } + return volumeApiService.doesTargetStorageSupportDiskOffering(pool, serviceOffering.getTags()); + } + + private ServiceOfferingVO getUnmanagedInstanceServiceOffering(final UnmanagedInstanceTO instance, ServiceOfferingVO serviceOffering, final Account owner, final DataCenter zone, final Map details) + throws ServerApiException, PermissionDeniedException, ResourceAllocationException { + if (instance == null) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM is not valid")); + } + if (serviceOffering == null) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Service offering is not valid")); + } + accountService.checkAccess(owner, serviceOffering, zone); + final Integer cpu = instance.getCpuCores(); + final Integer memory = instance.getMemory(); + Integer cpuSpeed = instance.getCpuSpeed() == null ? 0 : instance.getCpuSpeed(); + if (cpu == null || cpu == 0) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("CPU cores for VM not valid")); + } + if (memory == null || memory == 0) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Memory for VM not valid", instance.getName())); + } + if (serviceOffering.isDynamic()) { + if (details.containsKey(VmDetailConstants.CPU_SPEED)) { + try { + cpuSpeed = Integer.parseInt(details.get(VmDetailConstants.CPU_SPEED)); + } catch (Exception e) { + } + } + Map parameters = new HashMap<>(); + parameters.put(VmDetailConstants.CPU_NUMBER, String.valueOf(cpu)); + parameters.put(VmDetailConstants.MEMORY, String.valueOf(memory)); + if (serviceOffering.getSpeed() == null && cpuSpeed > 0) { + parameters.put(VmDetailConstants.CPU_SPEED, String.valueOf(cpuSpeed)); + } + serviceOffering.setDynamicFlag(true); + userVmManager.validateCustomParameters(serviceOffering, parameters); + serviceOffering = serviceOfferingDao.getComputeOffering(serviceOffering, parameters); + } else { + if (!cpu.equals(serviceOffering.getCpu()) && !instance.getPowerState().equals(UnmanagedInstanceTO.PowerState.PowerOff)) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Service offering (%s) %d CPU cores does not matches VM CPU cores %d and VM is not in powered off state (Power state: %s)", serviceOffering.getUuid(), serviceOffering.getCpu(), cpu, instance.getPowerState())); + } + if (!memory.equals(serviceOffering.getRamSize()) && !instance.getPowerState().equals(UnmanagedInstanceTO.PowerState.PowerOff)) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Service offering (%s) %dMB memory does not matches VM memory %dMB and VM is not in powered off state (Power state: %s)", serviceOffering.getUuid(), serviceOffering.getRamSize(), memory, instance.getPowerState())); + } + if (cpuSpeed != null && cpuSpeed > 0 && !cpuSpeed.equals(serviceOffering.getSpeed()) && !instance.getPowerState().equals(UnmanagedInstanceTO.PowerState.PowerOff)) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Service offering (%s) %dMHz CPU speed does not matches VM CPU speed %dMHz and VM is not in powered off state (Power state: %s)", serviceOffering.getUuid(), serviceOffering.getSpeed(), cpuSpeed, instance.getPowerState())); + } + } + resourceLimitService.checkResourceLimit(owner, Resource.ResourceType.cpu, new Long(serviceOffering.getCpu())); + resourceLimitService.checkResourceLimit(owner, Resource.ResourceType.memory, new Long(serviceOffering.getRamSize())); + return serviceOffering; + } + + private Map getNicIpAddresses(final List nics, final Map callerNicIpAddressMap) { + Map nicIpAddresses = new HashMap<>(); + for (UnmanagedInstanceTO.Nic nic : nics) { + Network.IpAddresses ipAddresses = null; + if (MapUtils.isNotEmpty(callerNicIpAddressMap) && callerNicIpAddressMap.containsKey(nic.getNicId())) { + ipAddresses = callerNicIpAddressMap.get(nic.getNicId()); + } + // If IP is set to auto-assign, check NIC doesn't have more that one IP from SDK + if (ipAddresses != null && ipAddresses.getIp4Address() != null && ipAddresses.getIp4Address().equals("auto") && !CollectionUtils.isEmpty(nic.getIpAddress())) { + if (nic.getIpAddress().size() > 1) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Multiple IP addresses (%s, %s) present for nic ID: %s. IP address cannot be assigned automatically, only single IP address auto-assigning supported", nic.getIpAddress().get(0), nic.getIpAddress().get(1), nic.getNicId())); + } + String address = nic.getIpAddress().get(0); + if (NetUtils.isValidIp4(address)) { + ipAddresses.setIp4Address(address); + } + } + if (ipAddresses != null) { + nicIpAddresses.put(nic.getNicId(), ipAddresses); + } + } + return nicIpAddresses; + } + + private StoragePool getStoragePool(final UnmanagedInstanceTO.Disk disk, final DataCenter zone, final Cluster cluster) { + StoragePool storagePool = null; + final String dsHost = disk.getDatastoreHost(); + final String dsPath = disk.getDatastorePath(); + final String dsType = disk.getDatastoreType(); + final String dsName = disk.getDatastoreName(); + if (dsType.equals("VMFS")) { + List pools = primaryDataStoreDao.listPoolsByCluster(cluster.getId()); + pools.addAll(primaryDataStoreDao.listByDataCenterId(zone.getId())); + for (StoragePool pool : pools) { + if (pool.getPoolType() != Storage.StoragePoolType.VMFS) { + continue; + } + if (pool.getPath().endsWith(dsName)) { + storagePool = pool; + break; + } + } + } else { + List pools = primaryDataStoreDao.listPoolByHostPath(dsHost, dsPath); + for (StoragePool pool : pools) { + if (pool.getDataCenterId() == zone.getId() && + (pool.getClusterId() == null || pool.getClusterId().equals(cluster.getId()))) { + storagePool = pool; + break; + } + } + } + if (storagePool == null) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Storage pool for disk %s(%s) with datastore: %s not found in zone ID: %s", disk.getLabel(), disk.getDiskId(), disk.getDatastoreName(), zone.getUuid())); + } + return storagePool; + } + + private void checkUnmanagedDiskAndOfferingForImport(UnmanagedInstanceTO.Disk disk, DiskOffering diskOffering, ServiceOffering serviceOffering, final Account owner, final DataCenter zone, final Cluster cluster, final boolean migrateAllowed) + throws ServerApiException, PermissionDeniedException, ResourceAllocationException { + if (serviceOffering == null && diskOffering == null) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Disk offering for disk ID: %s not found during VM import", disk.getDiskId())); + } + if (diskOffering != null) { + accountService.checkAccess(owner, diskOffering, zone); + } + resourceLimitService.checkResourceLimit(owner, Resource.ResourceType.volume); + if (disk.getCapacity() == null || disk.getCapacity() == 0) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Size of disk(ID: %s) is found invalid during VM import", disk.getDiskId())); + } + if (diskOffering != null && !diskOffering.isCustomized() && diskOffering.getDiskSize() == 0) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Size of fixed disk offering(ID: %s) is found invalid during VM import", diskOffering.getUuid())); + } + if (diskOffering != null && !diskOffering.isCustomized() && diskOffering.getDiskSize() < disk.getCapacity()) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Size of disk offering(ID: %s) %dGB is found less than the size of disk(ID: %s) %dGB during VM import", diskOffering.getUuid(), (diskOffering.getDiskSize() / Resource.ResourceType.bytesToGiB), disk.getDiskId(), (disk.getCapacity() / (Resource.ResourceType.bytesToGiB)))); + } + StoragePool storagePool = getStoragePool(disk, zone, cluster); + if (diskOffering != null && !migrateAllowed && !storagePoolSupportsDiskOffering(storagePool, diskOffering)) { + throw new InvalidParameterValueException(String.format("Disk offering: %s is not compatible with storage pool: %s of unmanaged disk: %s", diskOffering.getUuid(), storagePool.getUuid(), disk.getDiskId())); + } + if (serviceOffering != null && !migrateAllowed && !storagePoolSupportsServiceOffering(storagePool, serviceOffering)) { + throw new InvalidParameterValueException(String.format("Service offering: %s is not compatible with storage pool: %s of unmanaged disk: %s", serviceOffering.getUuid(), storagePool.getUuid(), disk.getDiskId())); + } + } + + private void checkUnmanagedDiskAndOfferingForImport(List disks, final Map diskOfferingMap, final Account owner, final DataCenter zone, final Cluster cluster, final boolean migrateAllowed) + throws ServerApiException, PermissionDeniedException, ResourceAllocationException { + String diskController = null; + for (UnmanagedInstanceTO.Disk disk : disks) { + if (disk == null) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Unable to retrieve disk details for VM")); + } + if (!diskOfferingMap.containsKey(disk.getDiskId())) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Disk offering for disk ID: %s not found during VM import", disk.getDiskId())); + } + if (Strings.isNullOrEmpty(diskController)) { + diskController = disk.getController(); + } else { + if (!diskController.equals(disk.getController())) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Multiple data disk controllers of different type (%s, %s) are not supported for import. Please make sure that all data disk controllers are of the same type", diskController, disk.getController())); + } + } + checkUnmanagedDiskAndOfferingForImport(disk, diskOfferingDao.findById(diskOfferingMap.get(disk.getDiskId())), null, owner, zone, cluster, migrateAllowed); + } + } + + private void checkUnmanagedNicAndNetworkForImport(UnmanagedInstanceTO.Nic nic, Network network, final DataCenter zone, final Account owner, final boolean autoAssign) throws ServerApiException { + if (nic == null) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Unable to retrieve NIC details during VM import")); + } + if (network == null) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Network for nic ID: %s not found during VM import", nic.getNicId())); + } + if (network.getDataCenterId() != zone.getId()) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Network(ID: %s) for nic(ID: %s) belongs to a different zone than VM to be imported", network.getUuid(), nic.getNicId())); + } + networkModel.checkNetworkPermissions(owner, network); + if (!autoAssign && network.getGuestType().equals(Network.GuestType.Isolated)) { + return; + } + + String networkBroadcastUri = network.getBroadcastUri() == null ? null : network.getBroadcastUri().toString(); + if (nic.getVlan() != null && nic.getVlan() != 0 && nic.getPvlan() == null && + (Strings.isNullOrEmpty(networkBroadcastUri) || + !networkBroadcastUri.equals(String.format("vlan://%d", nic.getVlan())))) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VLAN of network(ID: %s) %s is found different from the VLAN of nic(ID: %s) vlan://%d during VM import", network.getUuid(), networkBroadcastUri, nic.getNicId(), nic.getVlan())); + } + if (nic.getVlan() != null && nic.getVlan() != 0 && nic.getPvlan() != null && nic.getPvlan() != 0 && + (Strings.isNullOrEmpty(network.getBroadcastUri().toString()) || + !networkBroadcastUri.equals(String.format("pvlan://%d-i%d", nic.getVlan(), nic.getPvlan())))) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("PVLAN of network(ID: %s) %s is found different from the VLAN of nic(ID: %s) pvlan://%d-i%d during VM import", network.getUuid(), networkBroadcastUri, nic.getNicId(), nic.getVlan(), nic.getPvlan())); + } + } + + private void checkUnmanagedNicAndNetworkHostnameForImport(UnmanagedInstanceTO.Nic nic, Network network, final String hostName) throws ServerApiException { + if (nic == null) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Unable to retrieve NIC details during VM import")); + } + if (network == null) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Network for nic ID: %s not found during VM import", nic.getNicId())); + } + // Check for duplicate hostname in network, get all vms hostNames in the network + List hostNames = vmDao.listDistinctHostNames(network.getId()); + if (CollectionUtils.isNotEmpty(hostNames) && hostNames.contains(hostName)) { + throw new InvalidParameterValueException("The vm with hostName " + hostName + " already exists in the network domain: " + network.getNetworkDomain() + "; network=" + + network); + } + } + + private void checkUnmanagedNicIpAndNetworkForImport(UnmanagedInstanceTO.Nic nic, Network network, final Network.IpAddresses ipAddresses) throws ServerApiException { + if (nic == null) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Unable to retrieve NIC details during VM import")); + } + if (network == null) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Network for nic ID: %s not found during VM import", nic.getNicId())); + } + // Check IP is assigned for non L2 networks + if (!network.getGuestType().equals(Network.GuestType.L2) && (ipAddresses == null || Strings.isNullOrEmpty(ipAddresses.getIp4Address()))) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("NIC(ID: %s) needs a valid IP address for it to be associated with network(ID: %s). %s parameter of API can be used for this", nic.getNicId(), network.getUuid(), ApiConstants.NIC_IP_ADDRESS_LIST)); + } + // If network is non L2, IP v4 is assigned and not set to auto-assign, check it is available for network + if (!network.getGuestType().equals(Network.GuestType.L2) && ipAddresses != null && !Strings.isNullOrEmpty(ipAddresses.getIp4Address()) && !ipAddresses.getIp4Address().equals("auto")) { + Set ips = networkModel.getAvailableIps(network, ipAddresses.getIp4Address()); + if (CollectionUtils.isEmpty(ips) || !ips.contains(NetUtils.ip2Long(ipAddresses.getIp4Address()))) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("IP address %s for NIC(ID: %s) is not available in network(ID: %s)", ipAddresses.getIp4Address(), nic.getNicId(), network.getUuid())); + } + } + } + + private Map getUnmanagedNicNetworkMap(List nics, final Map callerNicNetworkMap, final Map callerNicIpAddressMap, final DataCenter zone, final String hostName, final Account owner) throws ServerApiException { + Map nicNetworkMap = new HashMap<>(); + String nicAdapter = null; + for (UnmanagedInstanceTO.Nic nic : nics) { + if (Strings.isNullOrEmpty(nicAdapter)) { + nicAdapter = nic.getAdapterType(); + } else { + if (!nicAdapter.equals(nic.getAdapterType())) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Multiple network adapter of different type (%s, %s) are not supported for import. Please make sure that all network adapters are of the same type", nicAdapter, nic.getAdapterType())); + } + } + Network network = null; + Network.IpAddresses ipAddresses = null; + if (MapUtils.isNotEmpty(callerNicIpAddressMap) && callerNicIpAddressMap.containsKey(nic.getNicId())) { + ipAddresses = callerNicIpAddressMap.get(nic.getNicId()); + } + if (!callerNicNetworkMap.containsKey(nic.getNicId())) { + if (nic.getVlan() != null && nic.getVlan() != 0) { + // Find a suitable network + List networks = networkDao.listByZone(zone.getId()); + for (NetworkVO networkVO : networks) { + if (networkVO.getTrafficType() == Networks.TrafficType.None || Networks.TrafficType.isSystemNetwork(networkVO.getTrafficType())) { + continue; + } + try { + checkUnmanagedNicAndNetworkForImport(nic, networkVO, zone, owner, true); + network = networkVO; + } catch (Exception e) { + } + if (network != null) { + checkUnmanagedNicAndNetworkHostnameForImport(nic, network, hostName); + checkUnmanagedNicIpAndNetworkForImport(nic, network, ipAddresses); + break; + } + } + } + } else { + network = networkDao.findById(callerNicNetworkMap.get(nic.getNicId())); + checkUnmanagedNicAndNetworkForImport(nic, network, zone, owner, false); + checkUnmanagedNicAndNetworkHostnameForImport(nic, network, hostName); + checkUnmanagedNicIpAndNetworkForImport(nic, network, ipAddresses); + } + if (network == null) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Suitable network for nic(ID: %s) not found during VM import", nic.getNicId())); + } + nicNetworkMap.put(nic.getNicId(), network.getId()); + } + return nicNetworkMap; + } + + private Pair importDisk(UnmanagedInstanceTO.Disk disk, VirtualMachine vm, Cluster cluster, DiskOffering diskOffering, + Volume.Type type, String name, Long diskSize, Long minIops, Long maxIops, VirtualMachineTemplate template, + Account owner, Long deviceId) { + final DataCenter zone = dataCenterDao.findById(vm.getDataCenterId()); + final String path = Strings.isNullOrEmpty(disk.getFileBaseName()) ? disk.getImagePath() : disk.getFileBaseName(); + String chainInfo = disk.getChainInfo(); + if (Strings.isNullOrEmpty(chainInfo)) { + VirtualMachineDiskInfo diskInfo = new VirtualMachineDiskInfo(); + diskInfo.setDiskDeviceBusName(String.format("%s%d:%d", disk.getController(), disk.getControllerUnit(), disk.getPosition())); + diskInfo.setDiskChain(new String[]{disk.getImagePath()}); + chainInfo = gson.toJson(diskInfo); + } + StoragePool storagePool = getStoragePool(disk, zone, cluster); + DiskProfile profile = volumeManager.importVolume(type, name, diskOffering, diskSize, + minIops, maxIops, vm, template, owner, deviceId, storagePool.getId(), path, chainInfo); + + return new Pair(profile, storagePool); + } + + private NicProfile importNic(UnmanagedInstanceTO.Nic nic, VirtualMachine vm, Network network, Network.IpAddresses ipAddresses, boolean isDefaultNic) throws InsufficientVirtualNetworkCapacityException, InsufficientAddressCapacityException { + Pair result = networkOrchestrationService.importNic(nic.getMacAddress(), 0, network, isDefaultNic, vm, ipAddresses); + if (result == null) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("NIC ID: %s import failed", nic.getNicId())); + } + return result.first(); + } + + private void cleanupFailedImportVM(final UserVm userVm) { + if (userVm == null) { + return; + } + VirtualMachineProfile profile = new VirtualMachineProfileImpl(userVm); + // Remove all volumes + volumeDao.deleteVolumesByInstance(userVm.getId()); + // Remove all nics + try { + networkOrchestrationService.release(profile, true); + } catch (Exception e) { + LOGGER.error(String.format("Unable to release NICs for unsuccessful import unmanaged VM: %s", userVm.getInstanceName()), e); + nicDao.removeNicsForInstance(userVm.getId()); + } + // Remove vm + vmDao.remove(userVm.getId()); + } + + private UserVm migrateImportedVM(HostVO sourceHost, VirtualMachineTemplate template, ServiceOfferingVO serviceOffering, UserVm userVm, final Account owner, List> diskProfileStoragePoolList) { + UserVm vm = userVm; + if (vm == null) { + LOGGER.error(String.format("Failed to check migrations need during VM import")); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to check migrations need during VM import")); + } + if (sourceHost == null || serviceOffering == null || diskProfileStoragePoolList == null) { + LOGGER.error(String.format("Failed to check migrations need during import, VM: %s", userVm.getInstanceName())); + cleanupFailedImportVM(vm); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to check migrations need during import, VM: %s", userVm.getInstanceName())); + } + if (!hostSupportsServiceOffering(sourceHost, serviceOffering)) { + LOGGER.debug(String.format("VM %s needs to be migrated", vm.getUuid())); + final VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm, template, serviceOffering, owner, null); + DeploymentPlanner.ExcludeList excludeList = new DeploymentPlanner.ExcludeList(); + excludeList.addHost(sourceHost.getId()); + final DataCenterDeployment plan = new DataCenterDeployment(sourceHost.getDataCenterId(), sourceHost.getPodId(), sourceHost.getClusterId(), null, null, null); + DeployDestination dest = null; + try { + dest = deploymentPlanningManager.planDeployment(profile, plan, excludeList, null); + } catch (Exception e) { + LOGGER.warn(String.format("VM import failed for unmanaged vm: %s during vm migration, finding deployment destination", vm.getInstanceName()), e); + cleanupFailedImportVM(vm); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM import failed for unmanaged vm: %s during vm migration, finding deployment destination", vm.getInstanceName())); + } + if (dest != null) { + if (LOGGER.isDebugEnabled()) { + LOGGER.debug(" Found " + dest + " for migrating the vm to"); + } + } + if (dest == null) { + cleanupFailedImportVM(vm); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM import failed for unmanaged vm: %s during vm migration, no deployment destination found", vm.getInstanceName())); + } + try { + if (vm.getState().equals(VirtualMachine.State.Stopped)) { + VMInstanceVO vmInstanceVO = vmDao.findById(userVm.getId()); + vmInstanceVO.setHostId(dest.getHost().getId()); + vmInstanceVO.setLastHostId(dest.getHost().getId()); + vmDao.update(vmInstanceVO.getId(), vmInstanceVO); + } else { + virtualMachineManager.migrate(vm.getUuid(), sourceHost.getId(), dest); + } + vm = userVmManager.getUserVm(vm.getId()); + } catch (Exception e) { + LOGGER.error(String.format("VM import failed for unmanaged vm: %s during vm migration", vm.getInstanceName()), e); + cleanupFailedImportVM(vm); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM import failed for unmanaged vm: %s during vm migration. %s", userVm.getInstanceName(), e.getMessage())); + } + } + for (Pair diskProfileStoragePool : diskProfileStoragePoolList) { + if (diskProfileStoragePool == null || + diskProfileStoragePool.first() == null || + diskProfileStoragePool.second() == null) { + continue; + } + DiskProfile profile = diskProfileStoragePool.first(); + DiskOffering dOffering = diskOfferingDao.findById(profile.getDiskOfferingId()); + if (dOffering == null) { + continue; + } + VolumeVO volumeVO = volumeDao.findById(profile.getVolumeId()); + if (volumeVO == null) { + continue; + } + boolean poolSupportsOfferings = storagePoolSupportsDiskOffering(diskProfileStoragePool.second(), dOffering); + if (poolSupportsOfferings && profile.getType() == Volume.Type.ROOT) { + poolSupportsOfferings = storagePoolSupportsServiceOffering(diskProfileStoragePool.second(), serviceOffering); + } + if (poolSupportsOfferings) { + continue; + } + LOGGER.debug(String.format("Volume %s needs to be migrated", volumeVO.getUuid())); + Pair, List> poolsPair = managementService.listStoragePoolsForMigrationOfVolume(profile.getVolumeId()); + if (CollectionUtils.isEmpty(poolsPair.first()) && CollectionUtils.isEmpty(poolsPair.second())) { + cleanupFailedImportVM(vm); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM import failed for unmanaged vm: %s during volume ID: %s migration as no suitable pool(s) found", userVm.getInstanceName(), volumeVO.getUuid())); + } + List storagePools = poolsPair.second(); + StoragePool storagePool = null; + if (CollectionUtils.isNotEmpty(storagePools)) { + for (StoragePool pool : storagePools) { + if (diskProfileStoragePool.second().getId() != pool.getId() && + storagePoolSupportsDiskOffering(pool, dOffering) && + (!profile.getType().equals(Volume.Type.ROOT) || + profile.getType().equals(Volume.Type.ROOT) && storagePoolSupportsServiceOffering(pool, serviceOffering))) { + storagePool = pool; + break; + } + } + } + // For zone-wide pools, at times, suitable storage pools are not returned therefore consider all pools. + if (storagePool == null && CollectionUtils.isNotEmpty(poolsPair.first())) { + storagePools = poolsPair.first(); + for (StoragePool pool : storagePools) { + if (diskProfileStoragePool.second().getId() != pool.getId() && + storagePoolSupportsDiskOffering(pool, dOffering) && + (!profile.getType().equals(Volume.Type.ROOT) || + profile.getType().equals(Volume.Type.ROOT) && storagePoolSupportsServiceOffering(pool, serviceOffering))) { + storagePool = pool; + break; + } + } + } + if (storagePool == null) { + cleanupFailedImportVM(vm); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM import failed for unmanaged vm: %s during volume ID: %s migration as no suitable pool found", userVm.getInstanceName(), volumeVO.getUuid())); + } else { + LOGGER.debug(String.format("Found storage pool %s(%s) for migrating the volume %s to", storagePool.getName(), storagePool.getUuid(), volumeVO.getUuid())); + } + try { + Volume volume = null; + if (vm.getState().equals(VirtualMachine.State.Running)) { + volume = volumeManager.liveMigrateVolume(volumeVO, storagePool); + } else { + volume = volumeManager.migrateVolume(volumeVO, storagePool); + } + if (volume == null) { + String msg = ""; + if (vm.getState().equals(VirtualMachine.State.Running)) { + msg = String.format("Live migration for volume ID: %s to destination pool ID: %s failed", volumeVO.getUuid(), storagePool.getUuid()); + } else { + msg = String.format("Migration for volume ID: %s to destination pool ID: %s failed", volumeVO.getUuid(), storagePool.getUuid()); + } + LOGGER.error(msg); + throw new CloudRuntimeException(msg); + } + } catch (Exception e) { + LOGGER.error(String.format("VM import failed for unmanaged vm: %s during volume migration", vm.getInstanceName()), e); + cleanupFailedImportVM(vm); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM import failed for unmanaged vm: %s during volume migration. %s", userVm.getInstanceName(), Strings.nullToEmpty(e.getMessage()))); + } + } + return userVm; + } + + private void publishVMUsageUpdateResourceCount(final UserVm userVm, ServiceOfferingVO serviceOfferingVO) { + if (userVm == null || serviceOfferingVO == null) { + LOGGER.error("Failed to publish usage records during VM import"); + cleanupFailedImportVM(userVm); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM import failed for unmanaged vm during publishing usage records")); + } + try { + if (!serviceOfferingVO.isDynamic()) { + UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VM_IMPORT, userVm.getAccountId(), userVm.getDataCenterId(), userVm.getId(), userVm.getHostName(), serviceOfferingVO.getId(), userVm.getTemplateId(), + userVm.getHypervisorType().toString(), VirtualMachine.class.getName(), userVm.getUuid(), userVm.isDisplayVm()); + } else { + UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VM_IMPORT, userVm.getAccountId(), userVm.getAccountId(), userVm.getDataCenterId(), userVm.getHostName(), serviceOfferingVO.getId(), userVm.getTemplateId(), + userVm.getHypervisorType().toString(), VirtualMachine.class.getName(), userVm.getUuid(), userVm.getDetails(), userVm.isDisplayVm()); + } + } catch (Exception e) { + LOGGER.error(String.format("Failed to publish usage records during VM import for unmanaged vm %s", userVm.getInstanceName()), e); + cleanupFailedImportVM(userVm); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM import failed for unmanaged vm %s during publishing usage records", userVm.getInstanceName())); + } + resourceLimitService.incrementResourceCount(userVm.getAccountId(), Resource.ResourceType.user_vm, userVm.isDisplayVm()); + resourceLimitService.incrementResourceCount(userVm.getAccountId(), Resource.ResourceType.cpu, userVm.isDisplayVm(), new Long(serviceOfferingVO.getCpu())); + resourceLimitService.incrementResourceCount(userVm.getAccountId(), Resource.ResourceType.memory, userVm.isDisplayVm(), new Long(serviceOfferingVO.getRamSize())); + // Save usage event and update resource count for user vm volumes + List volumes = volumeDao.findByInstance(userVm.getId()); + for (VolumeVO volume : volumes) { + try { + UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_CREATE, volume.getAccountId(), volume.getDataCenterId(), volume.getId(), volume.getName(), volume.getDiskOfferingId(), null, volume.getSize(), + Volume.class.getName(), volume.getUuid(), volume.isDisplayVolume()); + } catch (Exception e) { + LOGGER.error(String.format("Failed to publish volume ID: %s usage records during VM import", volume.getUuid()), e); + } + resourceLimitService.incrementResourceCount(userVm.getAccountId(), Resource.ResourceType.volume, volume.isDisplayVolume()); + resourceLimitService.incrementResourceCount(userVm.getAccountId(), Resource.ResourceType.primary_storage, volume.isDisplayVolume(), volume.getSize()); + } + } + + private UserVm importVirtualMachineInternal(final UnmanagedInstanceTO unmanagedInstance, final String instanceName, final DataCenter zone, final Cluster cluster, final HostVO host, + final VirtualMachineTemplate template, final String displayName, final String hostName, final Account caller, final Account owner, final Long userId, + final ServiceOfferingVO serviceOffering, final Map dataDiskOfferingMap, + final Map nicNetworkMap, final Map callerNicIpAddressMap, + final Map details, final boolean migrateAllowed) { + UserVm userVm = null; + + ServiceOfferingVO validatedServiceOffering = null; + try { + validatedServiceOffering = getUnmanagedInstanceServiceOffering(unmanagedInstance, serviceOffering, owner, zone, details); + } catch (Exception e) { + LOGGER.error("Service offering for VM import not compatible", e); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to import VM: %s. %s", unmanagedInstance.getName(), Strings.nullToEmpty(e.getMessage()))); + } + + Map allDetails = new HashMap<>(details); + if (validatedServiceOffering.isDynamic()) { + allDetails.put(VmDetailConstants.CPU_NUMBER, String.valueOf(validatedServiceOffering.getCpu())); + allDetails.put(VmDetailConstants.MEMORY, String.valueOf(validatedServiceOffering.getRamSize())); + if (serviceOffering.getSpeed() == null) { + allDetails.put(VmDetailConstants.CPU_SPEED, String.valueOf(validatedServiceOffering.getSpeed())); + } + } + + if (!migrateAllowed && !hostSupportsServiceOffering(host, validatedServiceOffering)) { + throw new InvalidParameterValueException(String.format("Service offering: %s is not compatible with host: %s of unmanaged VM: %s", serviceOffering.getUuid(), host.getUuid(), instanceName)); + } + // Check disks and supplied disk offerings + List unmanagedInstanceDisks = unmanagedInstance.getDisks(); + if (CollectionUtils.isEmpty(unmanagedInstanceDisks)) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("No attached disks found for the unmanaged VM: %s", instanceName)); + } + final UnmanagedInstanceTO.Disk rootDisk = unmanagedInstance.getDisks().get(0); + if (rootDisk == null || Strings.isNullOrEmpty(rootDisk.getController())) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM import failed. Unable to retrieve root disk details for VM: %s ", instanceName)); + } + allDetails.put(VmDetailConstants.ROOT_DISK_CONTROLLER, rootDisk.getController()); + List dataDisks = new ArrayList<>(); + try { + checkUnmanagedDiskAndOfferingForImport(rootDisk, null, validatedServiceOffering, owner, zone, cluster, migrateAllowed); + if (unmanagedInstanceDisks.size() > 1) { // Data disk(s) present + dataDisks.addAll(unmanagedInstanceDisks); + dataDisks.remove(0); + checkUnmanagedDiskAndOfferingForImport(dataDisks, dataDiskOfferingMap, owner, zone, cluster, migrateAllowed); + allDetails.put(VmDetailConstants.DATA_DISK_CONTROLLER, dataDisks.get(0).getController()); + } + resourceLimitService.checkResourceLimit(owner, Resource.ResourceType.volume, unmanagedInstanceDisks.size()); + } catch (ResourceAllocationException e) { + LOGGER.error(String.format("Volume resource allocation error for owner: %s", owner.getUuid()), e); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Volume resource allocation error for owner: %s. %s", owner.getUuid(), Strings.nullToEmpty(e.getMessage()))); + } + // Check NICs and supplied networks + Map nicIpAddressMap = getNicIpAddresses(unmanagedInstance.getNics(), callerNicIpAddressMap); + Map allNicNetworkMap = getUnmanagedNicNetworkMap(unmanagedInstance.getNics(), nicNetworkMap, nicIpAddressMap, zone, hostName, owner); + if (!CollectionUtils.isEmpty(unmanagedInstance.getNics())) { + allDetails.put(VmDetailConstants.NIC_ADAPTER, unmanagedInstance.getNics().get(0).getAdapterType()); + } + VirtualMachine.PowerState powerState = VirtualMachine.PowerState.PowerOff; + if (unmanagedInstance.getPowerState().equals(UnmanagedInstanceTO.PowerState.PowerOn)) { + powerState = VirtualMachine.PowerState.PowerOn; + } + try { + userVm = userVmManager.importVM(zone, host, template, instanceName, displayName, owner, + null, caller, true, null, owner.getAccountId(), userId, + validatedServiceOffering, null, hostName, + cluster.getHypervisorType(), allDetails, powerState); + } catch (InsufficientCapacityException ice) { + LOGGER.error(String.format("Failed to import vm name: %s", instanceName), ice); + throw new ServerApiException(ApiErrorCode.INSUFFICIENT_CAPACITY_ERROR, ice.getMessage()); + } + if (userVm == null) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to import vm name: %s", instanceName)); + } + List> diskProfileStoragePoolList = new ArrayList<>(); + try { + if (rootDisk.getCapacity() == null || rootDisk.getCapacity() == 0) { + throw new InvalidParameterValueException(String.format("Root disk ID: %s size is invalid", rootDisk.getDiskId())); + } + Long minIops = null; + if (details.containsKey("minIops")) { + minIops = Long.parseLong(details.get("minIops")); + } + Long maxIops = null; + if (details.containsKey("maxIops")) { + maxIops = Long.parseLong(details.get("maxIops")); + } + diskProfileStoragePoolList.add(importDisk(rootDisk, userVm, cluster, serviceOffering, Volume.Type.ROOT, String.format("ROOT-%d", userVm.getId()), + (rootDisk.getCapacity() / Resource.ResourceType.bytesToGiB), minIops, maxIops, + template, owner, null)); + for (UnmanagedInstanceTO.Disk disk : dataDisks) { + if (disk.getCapacity() == null || disk.getCapacity() == 0) { + throw new InvalidParameterValueException(String.format("Disk ID: %s size is invalid", rootDisk.getDiskId())); + } + DiskOffering offering = diskOfferingDao.findById(dataDiskOfferingMap.get(disk.getDiskId())); + diskProfileStoragePoolList.add(importDisk(disk, userVm, cluster, offering, Volume.Type.DATADISK, String.format("DATA-%d-%s", userVm.getId(), disk.getDiskId()), + (disk.getCapacity() / Resource.ResourceType.bytesToGiB), offering.getMinIops(), offering.getMaxIops(), + template, owner, null)); + } + } catch (Exception e) { + LOGGER.error(String.format("Failed to import volumes while importing vm: %s", instanceName), e); + cleanupFailedImportVM(userVm); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to import volumes while importing vm: %s. %s", instanceName, Strings.nullToEmpty(e.getMessage()))); + } + try { + boolean firstNic = true; + for (UnmanagedInstanceTO.Nic nic : unmanagedInstance.getNics()) { + Network network = networkDao.findById(allNicNetworkMap.get(nic.getNicId())); + Network.IpAddresses ipAddresses = nicIpAddressMap.get(nic.getNicId()); + importNic(nic, userVm, network, ipAddresses, firstNic); + firstNic = false; + } + } catch (Exception e) { + LOGGER.error(String.format("Failed to import NICs while importing vm: %s", instanceName), e); + cleanupFailedImportVM(userVm); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to import NICs while importing vm: %s. %s", instanceName, Strings.nullToEmpty(e.getMessage()))); + } + if (migrateAllowed) { + userVm = migrateImportedVM(host, template, validatedServiceOffering, userVm, owner, diskProfileStoragePoolList); + } + publishVMUsageUpdateResourceCount(userVm, validatedServiceOffering); + return userVm; + } + + @Override + public ListResponse listUnmanagedInstances(ListUnmanagedInstancesCmd cmd) { + final Account caller = CallContext.current().getCallingAccount(); + if (caller.getType() != Account.ACCOUNT_TYPE_ADMIN) { + throw new PermissionDeniedException(String.format("Cannot perform this operation, Calling account is not root admin: %s", caller.getUuid())); + } + final Long clusterId = cmd.getClusterId(); + if (clusterId == null) { + throw new InvalidParameterValueException(String.format("Cluster ID cannot be null")); + } + final Cluster cluster = clusterDao.findById(clusterId); + if (cluster == null) { + throw new InvalidParameterValueException(String.format("Cluster ID: %d cannot be found", clusterId)); + } + if (cluster.getHypervisorType() != Hypervisor.HypervisorType.VMware) { + throw new InvalidParameterValueException(String.format("VM ingestion is currently not supported for hypervisor: %s", cluster.getHypervisorType().toString())); + } + List hosts = resourceManager.listHostsInClusterByStatus(clusterId, Status.Up); + List additionalNameFilters = getAdditionalNameFilters(cluster); + List responses = new ArrayList<>(); + for (HostVO host : hosts) { + if (host.isInMaintenanceStates()) { + continue; + } + List managedVms = new ArrayList<>(); + managedVms.addAll(additionalNameFilters); + managedVms.addAll(getHostManagedVms(host)); + + GetUnmanagedInstancesCommand command = new GetUnmanagedInstancesCommand(); + command.setInstanceName(cmd.getName()); + command.setManagedInstancesNames(managedVms); + Answer answer = agentManager.easySend(host.getId(), command); + if (!(answer instanceof GetUnmanagedInstancesAnswer)) { + continue; + } + GetUnmanagedInstancesAnswer unmanagedInstancesAnswer = (GetUnmanagedInstancesAnswer) answer; + HashMap unmanagedInstances = new HashMap<>(); + unmanagedInstances.putAll(unmanagedInstancesAnswer.getUnmanagedInstances()); + Set keys = unmanagedInstances.keySet(); + for (String key : keys) { + responses.add(createUnmanagedInstanceResponse(unmanagedInstances.get(key), cluster, host)); + } + } + ListResponse listResponses = new ListResponse<>(); + listResponses.setResponses(responses, responses.size()); + return listResponses; + } + + @Override + public UserVmResponse importUnmanagedInstance(ImportUnmanagedInstanceCmd cmd) { + final Account caller = CallContext.current().getCallingAccount(); + if (caller.getType() != Account.ACCOUNT_TYPE_ADMIN) { + throw new PermissionDeniedException(String.format("Cannot perform this operation, Calling account is not root admin: %s", caller.getUuid())); + } + final Long clusterId = cmd.getClusterId(); + if (clusterId == null) { + throw new InvalidParameterValueException(String.format("Cluster ID cannot be null")); + } + final Cluster cluster = clusterDao.findById(clusterId); + if (cluster == null) { + throw new InvalidParameterValueException(String.format("Cluster ID: %d cannot be found", clusterId)); + } + if (cluster.getHypervisorType() != Hypervisor.HypervisorType.VMware) { + throw new InvalidParameterValueException(String.format("VM import is currently not supported for hypervisor: %s", cluster.getHypervisorType().toString())); + } + final DataCenter zone = dataCenterDao.findById(cluster.getDataCenterId()); + final String instanceName = cmd.getName(); + if (Strings.isNullOrEmpty(instanceName)) { + throw new InvalidParameterValueException(String.format("Instance name cannot be empty")); + } + if (cmd.getDomainId() != null && Strings.isNullOrEmpty(cmd.getAccountName())) { + throw new InvalidParameterValueException("domainid parameter must be specified with account parameter"); + } + final Account owner = accountService.getActiveAccountById(cmd.getEntityOwnerId()); + long userId = CallContext.current().getCallingUserId(); + List userVOs = userDao.listByAccount(owner.getAccountId()); + if (CollectionUtils.isNotEmpty(userVOs)) { + userId = userVOs.get(0).getId(); + } + VMTemplateVO template = null; + final Long templateId = cmd.getTemplateId(); + if (templateId == null) { + template = templateDao.findByName(VM_IMPORT_DEFAULT_TEMPLATE_NAME); + if (template == null) { + template = createDefaultDummyVmImportTemplate(); + if (template == null) { + throw new InvalidParameterValueException(String.format("Default VM import template with unique name: %s for hypervisor: %s cannot be created. Please use templateid paramter for import", VM_IMPORT_DEFAULT_TEMPLATE_NAME, cluster.getHypervisorType().toString())); + } + } + } else { + template = templateDao.findById(templateId); + } + if (template == null) { + throw new InvalidParameterValueException(String.format("Template ID: %d cannot be found", templateId)); + } + final Long serviceOfferingId = cmd.getServiceOfferingId(); + if (serviceOfferingId == null) { + throw new InvalidParameterValueException(String.format("Service offering ID cannot be null")); + } + final ServiceOfferingVO serviceOffering = serviceOfferingDao.findById(serviceOfferingId); + if (serviceOffering == null) { + throw new InvalidParameterValueException(String.format("Service offering ID: %d cannot be found", serviceOfferingId)); + } + accountService.checkAccess(owner, serviceOffering, zone); + try { + resourceLimitService.checkResourceLimit(owner, Resource.ResourceType.user_vm, 1); + } catch (ResourceAllocationException e) { + LOGGER.error(String.format("VM resource allocation error for account: %s", owner.getUuid()), e); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM resource allocation error for account: %s. %s", owner.getUuid(), Strings.nullToEmpty(e.getMessage()))); + } + String displayName = cmd.getDisplayName(); + if (Strings.isNullOrEmpty(displayName)) { + displayName = instanceName; + } + String hostName = cmd.getHostName(); + if (Strings.isNullOrEmpty(hostName)) { + if (!NetUtils.verifyDomainNameLabel(instanceName, true)) { + throw new InvalidParameterValueException(String.format("Please provide hostname for the VM. VM name contains unsupported characters for it to be used as hostname")); + } + hostName = instanceName; + } + if (!NetUtils.verifyDomainNameLabel(hostName, true)) { + throw new InvalidParameterValueException("Invalid VM hostname. VM hostname can contain ASCII letters 'a' through 'z', the digits '0' through '9', " + + "and the hyphen ('-'), must be between 1 and 63 characters long, and can't start or end with \"-\" and can't start with digit"); + } + if (cluster.getHypervisorType().equals(Hypervisor.HypervisorType.VMware) && + Boolean.parseBoolean(configurationDao.getValue(Config.SetVmInternalNameUsingDisplayName.key()))) { + // If global config vm.instancename.flag is set to true, then CS will set guest VM's name as it appears on the hypervisor, to its hostname. + // In case of VMware since VM name must be unique within a DC, check if VM with the same hostname already exists in the zone. + VMInstanceVO vmByHostName = vmDao.findVMByHostNameInZone(hostName, zone.getId()); + if (vmByHostName != null && vmByHostName.getState() != VirtualMachine.State.Expunging) { + throw new InvalidParameterValueException(String.format("Failed to import VM: %s. There already exists a VM by the hostname: %s in zone: %s", instanceName, hostName, zone.getUuid())); + } + } + final Map nicNetworkMap = cmd.getNicNetworkList(); + final Map nicIpAddressMap = cmd.getNicIpAddressList(); + final Map dataDiskOfferingMap = cmd.getDataDiskToDiskOfferingList(); + final Map details = cmd.getDetails(); + List hosts = resourceManager.listHostsInClusterByStatus(clusterId, Status.Up); + UserVm userVm = null; + List additionalNameFilters = getAdditionalNameFilters(cluster); + for (HostVO host : hosts) { + if (host.isInMaintenanceStates()) { + continue; + } + List managedVms = new ArrayList<>(); + managedVms.addAll(additionalNameFilters); + managedVms.addAll(getHostManagedVms(host)); + GetUnmanagedInstancesCommand command = new GetUnmanagedInstancesCommand(instanceName); + command.setManagedInstancesNames(managedVms); + Answer answer = agentManager.easySend(host.getId(), command); + if (!(answer instanceof GetUnmanagedInstancesAnswer)) { + continue; + } + GetUnmanagedInstancesAnswer unmanagedInstancesAnswer = (GetUnmanagedInstancesAnswer) answer; + HashMap unmanagedInstances = unmanagedInstancesAnswer.getUnmanagedInstances(); + if (MapUtils.isEmpty(unmanagedInstances)) { + continue; + } + Set names = unmanagedInstances.keySet(); + for (String name : names) { + if (instanceName.equals(name)) { + UnmanagedInstanceTO unmanagedInstance = unmanagedInstances.get(name); + if (unmanagedInstance == null) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Unable to retrieve details for unmanaged VM: %s", name)); + } + if (template.getName().equals(VM_IMPORT_DEFAULT_TEMPLATE_NAME)) { + String osName = unmanagedInstance.getOperatingSystem(); + GuestOS guestOS = null; + if (!Strings.isNullOrEmpty(osName)) { + guestOS = guestOSDao.listByDisplayName(osName); + } + GuestOSHypervisor guestOSHypervisor = null; + if (guestOS != null) { + guestOSHypervisor = guestOSHypervisorDao.findByOsIdAndHypervisor(guestOS.getId(), host.getHypervisorType().toString(), host.getHypervisorVersion()); + } + if (guestOSHypervisor == null && !Strings.isNullOrEmpty(unmanagedInstance.getOperatingSystemId())) { + guestOSHypervisor = guestOSHypervisorDao.findByOsNameAndHypervisor(unmanagedInstance.getOperatingSystemId(), host.getHypervisorType().toString(), host.getHypervisorVersion()); + } + if (guestOSHypervisor == null) { + if (guestOS != null) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Unable to find hypervisor guest OS ID: %s details for unmanaged VM: %s for hypervisor: %s version: %s. templateid parameter can be used to assign template for VM", guestOS.getUuid(), name, host.getHypervisorType().toString(), host.getHypervisorVersion())); + } + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Unable to retrieve guest OS details for unmanaged VM: %s with OS name: %s, OS ID: %s for hypervisor: %s version: %s. templateid parameter can be used to assign template for VM", name, osName, unmanagedInstance.getOperatingSystemId(), host.getHypervisorType().toString(), host.getHypervisorVersion())); + } + template.setGuestOSId(guestOSHypervisor.getGuestOsId()); + } + userVm = importVirtualMachineInternal(unmanagedInstance, instanceName, zone, cluster, host, + template, displayName, hostName, caller, owner, userId, + serviceOffering, dataDiskOfferingMap, + nicNetworkMap, nicIpAddressMap, + details, cmd.getMigrateAllowed()); + break; + } + } + if (userVm != null) { + break; + } + } + if (userVm == null) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to find unmanaged vm with name: %s in cluster: %s", instanceName, cluster.getUuid())); + } + return responseGenerator.createUserVmResponse(ResponseObject.ResponseView.Full, "virtualmachine", userVm).get(0); + } + + @Override + public List> getCommands() { + final List> cmdList = new ArrayList>(); + cmdList.add(ListUnmanagedInstancesCmd.class); + cmdList.add(ImportUnmanagedInstanceCmd.class); + return cmdList; + } +} diff --git a/server/src/main/resources/META-INF/cloudstack/server-compute/spring-server-compute-context.xml b/server/src/main/resources/META-INF/cloudstack/server-compute/spring-server-compute-context.xml index 38fb61971224..ca707a03ba6d 100644 --- a/server/src/main/resources/META-INF/cloudstack/server-compute/spring-server-compute-context.xml +++ b/server/src/main/resources/META-INF/cloudstack/server-compute/spring-server-compute-context.xml @@ -35,4 +35,6 @@ + + diff --git a/server/src/test/java/com/cloud/api/ApiResponseHelperTest.java b/server/src/test/java/com/cloud/api/ApiResponseHelperTest.java index 2809005a7053..69ac86de8765 100644 --- a/server/src/test/java/com/cloud/api/ApiResponseHelperTest.java +++ b/server/src/test/java/com/cloud/api/ApiResponseHelperTest.java @@ -16,10 +16,16 @@ // under the License. package com.cloud.api; -import com.cloud.domain.DomainVO; -import com.cloud.usage.UsageVO; -import com.cloud.user.AccountVO; -import com.cloud.vm.NicSecondaryIp; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.mockito.Matchers.anyLong; +import static org.mockito.Mockito.when; + +import java.lang.reflect.Field; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.TimeZone; import org.apache.cloudstack.api.response.NicSecondaryIpResponse; import org.apache.cloudstack.api.response.UsageRecordResponse; @@ -33,16 +39,10 @@ import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; -import java.lang.reflect.Field; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.TimeZone; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.mockito.Matchers.anyLong; -import static org.mockito.Mockito.when; +import com.cloud.domain.DomainVO; +import com.cloud.usage.UsageVO; +import com.cloud.user.AccountVO; +import com.cloud.vm.NicSecondaryIp; @RunWith(PowerMockRunner.class) @PrepareForTest(ApiDBUtils.class) @@ -85,8 +85,8 @@ public void getDateStringInternal() throws ParseException { public void testUsageRecordResponse(){ //Creating the usageVO object to be passed to the createUsageResponse. Long zoneId = null; - Long accountId = null; - Long domainId = null; + Long accountId = 1L; + Long domainId = 1L; String Description = "Test Object"; String usageDisplay = " "; int usageType = -1; diff --git a/server/src/test/java/com/cloud/api/ApiServletTest.java b/server/src/test/java/com/cloud/api/ApiServletTest.java index 037c36e3b95b..fa582991e6b0 100644 --- a/server/src/test/java/com/cloud/api/ApiServletTest.java +++ b/server/src/test/java/com/cloud/api/ApiServletTest.java @@ -16,16 +16,27 @@ // under the License. package com.cloud.api; -import org.apache.cloudstack.api.auth.APIAuthenticationManager; -import org.apache.cloudstack.api.auth.APIAuthenticationType; -import org.apache.cloudstack.api.auth.APIAuthenticator; +import static org.mockito.ArgumentMatchers.nullable; -import com.cloud.server.ManagementServer; -import com.cloud.user.Account; -import com.cloud.user.AccountService; -import com.cloud.user.User; +import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.io.UnsupportedEncodingException; +import java.lang.reflect.Field; +import java.net.InetAddress; +import java.net.URLEncoder; +import java.net.UnknownHostException; +import java.util.HashMap; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.auth.APIAuthenticationManager; +import org.apache.cloudstack.api.auth.APIAuthenticationType; +import org.apache.cloudstack.api.auth.APIAuthenticator; import org.junit.After; import org.junit.Assert; import org.junit.Before; @@ -33,21 +44,12 @@ import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.Mockito; -import org.mockito.runners.MockitoJUnitRunner; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpSession; +import org.mockito.junit.MockitoJUnitRunner; -import java.io.IOException; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.io.UnsupportedEncodingException; -import java.lang.reflect.Field; -import java.net.URLEncoder; -import java.net.InetAddress; -import java.net.UnknownHostException; -import java.util.HashMap; +import com.cloud.server.ManagementServer; +import com.cloud.user.Account; +import com.cloud.user.AccountService; +import com.cloud.user.User; @RunWith(MockitoJUnitRunner.class) public class ApiServletTest { @@ -103,7 +105,7 @@ public void setup() throws SecurityException, NoSuchFieldException, accountMgrField.set(servlet, accountService); Mockito.when(authManager.getAPIAuthenticator(Mockito.anyString())).thenReturn(authenticator); - Mockito.when(authenticator.authenticate(Mockito.anyString(), Mockito.anyMap(), Mockito.isA(HttpSession.class), + Mockito.lenient().when(authenticator.authenticate(Mockito.anyString(), Mockito.anyMap(), Mockito.isA(HttpSession.class), Mockito.same(InetAddress.getByName("127.0.0.1")), Mockito.anyString(), Mockito.isA(StringBuilder.class), Mockito.isA(HttpServletRequest.class), Mockito.isA(HttpServletResponse.class))).thenReturn("{\"loginresponse\":{}"); Field authManagerField = ApiServlet.class.getDeclaredField("authManager"); @@ -124,7 +126,7 @@ public void hackEnvironment() throws Exception { Field smsField = ApiDBUtils.class.getDeclaredField("s_ms"); smsField.setAccessible(true); smsField.set(null, managementServer); - Mockito.when(managementServer.getVersion()).thenReturn( + Mockito.lenient().when(managementServer.getVersion()).thenReturn( "LATEST-AND-GREATEST"); } @@ -173,7 +175,7 @@ public void utf8FixupUtf() throws UnsupportedEncodingException { @Test public void processRequestInContextUnauthorizedGET() { Mockito.when(request.getMethod()).thenReturn("GET"); - Mockito.when( + Mockito.lenient().when( apiServer.verifyRequest(Mockito.anyMap(), Mockito.anyLong(), Mockito.any(InetAddress.class))) .thenReturn(false); servlet.processRequestInContext(request, response); @@ -188,7 +190,7 @@ public void processRequestInContextUnauthorizedGET() { public void processRequestInContextAuthorizedGet() { Mockito.when(request.getMethod()).thenReturn("GET"); Mockito.when( - apiServer.verifyRequest(Mockito.anyMap(), Mockito.anyLong(), Mockito.any(InetAddress.class))) + apiServer.verifyRequest(nullable(Map.class), nullable(Long.class), nullable(InetAddress.class))) .thenReturn(true); servlet.processRequestInContext(request, response); Mockito.verify(response).setStatus(HttpServletResponse.SC_OK); diff --git a/server/src/test/java/com/cloud/api/query/dao/SecurityGroupJoinDaoImplTest.java b/server/src/test/java/com/cloud/api/query/dao/SecurityGroupJoinDaoImplTest.java index 112504d623ce..a2c15234013a 100644 --- a/server/src/test/java/com/cloud/api/query/dao/SecurityGroupJoinDaoImplTest.java +++ b/server/src/test/java/com/cloud/api/query/dao/SecurityGroupJoinDaoImplTest.java @@ -16,8 +16,6 @@ // under the License. package com.cloud.api.query.dao; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.when; import java.lang.reflect.Field; @@ -32,13 +30,11 @@ import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.MockitoAnnotations; -import org.mockito.runners.MockitoJUnitRunner; +import org.mockito.junit.MockitoJUnitRunner; -import com.cloud.api.query.vo.ResourceTagJoinVO; import com.cloud.api.query.vo.SecurityGroupJoinVO; import com.cloud.network.security.SecurityGroupVMMapVO; import com.cloud.network.security.dao.SecurityGroupVMMapDao; -import com.cloud.server.ResourceTag.ResourceObjectType; import com.cloud.user.Account; import com.cloud.vm.UserVmVO; import com.cloud.vm.dao.UserVmDao; @@ -98,8 +94,6 @@ public void setup() { securityGroupVmMap_two.add(securityGroupVMMapVOone); securityGroupVmMap_two.add(securityGroupVMMapVOtwo); - // Mock the resource tags to return an empty list. - when(_resourceTagJoinDao.listBy(anyString(), any(ResourceObjectType.class))).thenReturn(new ArrayList()); // Mock the listBySecurityGroup method to return a specified list when being called. when(_securityGroupVMMapDao.listBySecurityGroup(1L)).thenReturn(securityGroupVmMap_empty); diff --git a/server/src/test/java/com/cloud/ha/HighAvailabilityManagerImplTest.java b/server/src/test/java/com/cloud/ha/HighAvailabilityManagerImplTest.java index 898dff2b7909..7410f1e6e03b 100644 --- a/server/src/test/java/com/cloud/ha/HighAvailabilityManagerImplTest.java +++ b/server/src/test/java/com/cloud/ha/HighAvailabilityManagerImplTest.java @@ -156,7 +156,7 @@ public void setup() throws IllegalArgumentException, public void scheduleRestartForVmsOnHost() { Mockito.when(hostVO.getType()).thenReturn(Host.Type.Routing); Mockito.when(hostVO.getHypervisorType()).thenReturn(HypervisorType.KVM); - Mockito.when(_instanceDao.listByHostId(42l)).thenReturn(Arrays.asList(Mockito.mock(VMInstanceVO.class))); + Mockito.lenient().when(_instanceDao.listByHostId(42l)).thenReturn(Arrays.asList(Mockito.mock(VMInstanceVO.class))); Mockito.when(_podDao.findById(Mockito.anyLong())).thenReturn(Mockito.mock(HostPodVO.class)); Mockito.when(_dcDao.findById(Mockito.anyLong())).thenReturn(Mockito.mock(DataCenterVO.class)); @@ -178,7 +178,7 @@ public void scheduleRestartForVmsOnHostNonEmptyVMList() { Mockito.when(hostVO.getHypervisorType()).thenReturn(HypervisorType.XenServer); List vms = new ArrayList(); VMInstanceVO vm1 = Mockito.mock(VMInstanceVO.class); - Mockito.when(vm1.getHostId()).thenReturn(1l); + Mockito.lenient().when(vm1.getHostId()).thenReturn(1l); Mockito.when(vm1.getInstanceName()).thenReturn("i-2-3-VM"); Mockito.when(vm1.getType()).thenReturn(VirtualMachine.Type.User); Mockito.when(vm1.isHaEnabled()).thenReturn(true); diff --git a/server/src/test/java/com/cloud/ha/KVMFencerTest.java b/server/src/test/java/com/cloud/ha/KVMFencerTest.java index da120af5edbf..ffbbcd3b58e3 100644 --- a/server/src/test/java/com/cloud/ha/KVMFencerTest.java +++ b/server/src/test/java/com/cloud/ha/KVMFencerTest.java @@ -102,16 +102,16 @@ public void testWithHosts() throws AgentUnavailableException, OperationTimedoutE Mockito.when(host.getClusterId()).thenReturn(1l); Mockito.when(host.getHypervisorType()).thenReturn(HypervisorType.KVM); Mockito.when(host.getStatus()).thenReturn(Status.Up); - Mockito.when(host.getDataCenterId()).thenReturn(1l); - Mockito.when(host.getPodId()).thenReturn(1l); + Mockito.lenient().when(host.getDataCenterId()).thenReturn(1l); + Mockito.lenient().when(host.getPodId()).thenReturn(1l); Mockito.when(host.getId()).thenReturn(1l); HostVO secondHost = Mockito.mock(HostVO.class); - Mockito.when(secondHost.getClusterId()).thenReturn(1l); + Mockito.lenient().when(secondHost.getClusterId()).thenReturn(1l); Mockito.when(secondHost.getHypervisorType()).thenReturn(HypervisorType.KVM); Mockito.when(secondHost.getStatus()).thenReturn(Status.Up); - Mockito.when(secondHost.getDataCenterId()).thenReturn(1l); - Mockito.when(secondHost.getPodId()).thenReturn(1l); + Mockito.lenient().when(secondHost.getDataCenterId()).thenReturn(1l); + Mockito.lenient().when(secondHost.getPodId()).thenReturn(1l); Mockito.when(host.getId()).thenReturn(2l); VirtualMachine virtualMachine = Mockito.mock(VirtualMachine.class); @@ -135,11 +135,11 @@ public void testWithFailingFence() throws AgentUnavailableException, OperationTi Mockito.when(host.getId()).thenReturn(1l); HostVO secondHost = Mockito.mock(HostVO.class); - Mockito.when(secondHost.getClusterId()).thenReturn(1l); + Mockito.lenient().when(secondHost.getClusterId()).thenReturn(1l); Mockito.when(secondHost.getHypervisorType()).thenReturn(HypervisorType.KVM); Mockito.when(secondHost.getStatus()).thenReturn(Status.Up); - Mockito.when(secondHost.getDataCenterId()).thenReturn(1l); - Mockito.when(secondHost.getPodId()).thenReturn(1l); + Mockito.lenient().when(secondHost.getDataCenterId()).thenReturn(1l); + Mockito.lenient().when(secondHost.getPodId()).thenReturn(1l); Mockito.when(host.getId()).thenReturn(2l); VirtualMachine virtualMachine = Mockito.mock(VirtualMachine.class); @@ -162,11 +162,11 @@ public void testWithTimeoutingFence() throws AgentUnavailableException, Operatio Mockito.when(host.getId()).thenReturn(1l); HostVO secondHost = Mockito.mock(HostVO.class); - Mockito.when(secondHost.getClusterId()).thenReturn(1l); + Mockito.lenient().when(secondHost.getClusterId()).thenReturn(1l); Mockito.when(secondHost.getHypervisorType()).thenReturn(HypervisorType.KVM); Mockito.when(secondHost.getStatus()).thenReturn(Status.Up); - Mockito.when(secondHost.getDataCenterId()).thenReturn(1l); - Mockito.when(secondHost.getPodId()).thenReturn(1l); + Mockito.lenient().when(secondHost.getDataCenterId()).thenReturn(1l); + Mockito.lenient().when(secondHost.getPodId()).thenReturn(1l); Mockito.when(host.getId()).thenReturn(2l); VirtualMachine virtualMachine = Mockito.mock(VirtualMachine.class); @@ -181,15 +181,15 @@ public void testWithTimeoutingFence() throws AgentUnavailableException, Operatio @Test public void testWithSingleNotKVM() { HostVO host = Mockito.mock(HostVO.class); - Mockito.when(host.getClusterId()).thenReturn(1l); + Mockito.lenient().when(host.getClusterId()).thenReturn(1l); Mockito.when(host.getHypervisorType()).thenReturn(HypervisorType.Any); - Mockito.when(host.getStatus()).thenReturn(Status.Down); - Mockito.when(host.getId()).thenReturn(1l); - Mockito.when(host.getDataCenterId()).thenReturn(1l); - Mockito.when(host.getPodId()).thenReturn(1l); + Mockito.lenient().when(host.getStatus()).thenReturn(Status.Down); + Mockito.lenient().when(host.getId()).thenReturn(1l); + Mockito.lenient().when(host.getDataCenterId()).thenReturn(1l); + Mockito.lenient().when(host.getPodId()).thenReturn(1l); VirtualMachine virtualMachine = Mockito.mock(VirtualMachine.class); - Mockito.when(resourceManager.listAllHostsInCluster(1l)).thenReturn(Collections.singletonList(host)); + Mockito.lenient().when(resourceManager.listAllHostsInCluster(1l)).thenReturn(Collections.singletonList(host)); Assert.assertNull(fencer.fenceOff(virtualMachine, host)); } diff --git a/server/src/test/java/com/cloud/hypervisor/KVMGuruTest.java b/server/src/test/java/com/cloud/hypervisor/KVMGuruTest.java index 2299d2123675..a10e9379fd85 100644 --- a/server/src/test/java/com/cloud/hypervisor/KVMGuruTest.java +++ b/server/src/test/java/com/cloud/hypervisor/KVMGuruTest.java @@ -79,20 +79,20 @@ public void setup() throws UnsupportedEncodingException { Mockito.when(vmProfile.getVirtualMachine()).thenReturn(vm); Mockito.when(vm.getHostId()).thenReturn(hostId); Mockito.when(hostDao.findById(hostId)).thenReturn(host); - Mockito.when(host.getCpus()).thenReturn(3); + Mockito.lenient().when(host.getCpus()).thenReturn(3); Mockito.when(host.getSpeed()).thenReturn(1995L); Mockito.when(vmTO.getMaxSpeed()).thenReturn(500); - Mockito.when(serviceOffering.getId()).thenReturn(offeringId); - Mockito.when(vmProfile.getServiceOffering()).thenReturn(serviceOffering); + Mockito.lenient().when(serviceOffering.getId()).thenReturn(offeringId); + Mockito.lenient().when(vmProfile.getServiceOffering()).thenReturn(serviceOffering); - Mockito.when(detail1.getName()).thenReturn(detail1Key); - Mockito.when(detail1.getValue()).thenReturn(detail1Value); - Mockito.when(detail1.getResourceId()).thenReturn(offeringId); - Mockito.when(detail2.getName()).thenReturn(detail2Key); - Mockito.when(detail2.getResourceId()).thenReturn(offeringId); - Mockito.when(detail2.getValue()).thenReturn(detail2Value); + Mockito.lenient().when(detail1.getName()).thenReturn(detail1Key); + Mockito.lenient().when(detail1.getValue()).thenReturn(detail1Value); + Mockito.lenient().when(detail1.getResourceId()).thenReturn(offeringId); + Mockito.lenient().when(detail2.getName()).thenReturn(detail2Key); + Mockito.lenient().when(detail2.getResourceId()).thenReturn(offeringId); + Mockito.lenient().when(detail2.getValue()).thenReturn(detail2Value); - Mockito.when(serviceOfferingDetailsDao.listDetails(offeringId)).thenReturn( + Mockito.lenient().when(serviceOfferingDetailsDao.listDetails(offeringId)).thenReturn( Arrays.asList(detail1, detail2)); } diff --git a/server/src/test/java/com/cloud/hypervisor/kvm/dpdk/DpdkHelperImplTest.java b/server/src/test/java/com/cloud/hypervisor/kvm/dpdk/DpdkHelperImplTest.java index f74e2e692a6f..2f1d6270c9c9 100644 --- a/server/src/test/java/com/cloud/hypervisor/kvm/dpdk/DpdkHelperImplTest.java +++ b/server/src/test/java/com/cloud/hypervisor/kvm/dpdk/DpdkHelperImplTest.java @@ -107,13 +107,13 @@ public void setup() throws UnsupportedEncodingException { Mockito.when(dpdkVhostUserModeDetailVO.getName()).thenReturn(DpdkHelper.DPDK_VHOST_USER_MODE); Mockito.when(dpdkVhostUserModeDetailVO.getValue()).thenReturn(dpdkVhostMode); - Mockito.when(dpdkVhostUserModeDetailVO.getResourceId()).thenReturn(offeringId); + Mockito.lenient().when(dpdkVhostUserModeDetailVO.getResourceId()).thenReturn(offeringId); Mockito.when(dpdkNumaDetailVO.getName()).thenReturn(DpdkHelper.DPDK_NUMA); - Mockito.when(dpdkNumaDetailVO.getResourceId()).thenReturn(offeringId); - Mockito.when(dpdkNumaDetailVO.getValue()).thenReturn(dpdkNumaValue); + Mockito.lenient().when(dpdkNumaDetailVO.getResourceId()).thenReturn(offeringId); + Mockito.lenient().when(dpdkNumaDetailVO.getValue()).thenReturn(dpdkNumaValue); Mockito.when(dpdkHugePagesDetailVO.getName()).thenReturn(DpdkHelper.DPDK_HUGE_PAGES); - Mockito.when(dpdkHugePagesDetailVO.getResourceId()).thenReturn(offeringId); - Mockito.when(dpdkHugePagesDetailVO.getValue()).thenReturn(dpdkHugePagesValue); + Mockito.lenient().when(dpdkHugePagesDetailVO.getResourceId()).thenReturn(offeringId); + Mockito.lenient().when(dpdkHugePagesDetailVO.getValue()).thenReturn(dpdkHugePagesValue); Mockito.when(serviceOfferingDetailsDao.listDetails(offeringId)).thenReturn( Arrays.asList(dpdkNumaDetailVO, dpdkHugePagesDetailVO, dpdkVhostUserModeDetailVO)); @@ -132,9 +132,9 @@ public void setup() throws UnsupportedEncodingException { Mockito.when(vmInstanceVO.getId()).thenReturn(vmId); Mockito.when(dpdkNumaVmDetail.getName()).thenReturn(DpdkHelper.DPDK_NUMA); - Mockito.when(dpdkNumaVmDetail.getValue()).thenReturn(dpdkNumaConf); + Mockito.lenient().when(dpdkNumaVmDetail.getValue()).thenReturn(dpdkNumaConf); Mockito.when(dpdkHugePagesVmDetail.getName()).thenReturn(DpdkHelper.DPDK_HUGE_PAGES); - Mockito.when(dpdkHugePagesVmDetail.getValue()).thenReturn(dpdkHugePagesConf); + Mockito.lenient().when(dpdkHugePagesVmDetail.getValue()).thenReturn(dpdkHugePagesConf); Mockito.when(userVmDetailsDao.listDetails(vmId)).thenReturn(Arrays.asList(dpdkNumaVmDetail, dpdkHugePagesVmDetail)); } @@ -148,13 +148,13 @@ public void testSetDpdkVhostUserModeValidDetail() { @Test public void testSetDpdkVhostUserModeInvalidDetail() { - Mockito.when(dpdkVhostUserModeDetailVO.getValue()).thenReturn("serverrrr"); + Mockito.lenient().when(dpdkVhostUserModeDetailVO.getValue()).thenReturn("serverrrr"); Mockito.verify(vmTO, Mockito.never()).addExtraConfig(Mockito.anyString(), Mockito.anyString()); } @Test public void testSetDpdkVhostUserModeNotExistingDetail() { - Mockito.when(serviceOfferingDetailsDao.listDetails(offeringId)).thenReturn( + Mockito.lenient().when(serviceOfferingDetailsDao.listDetails(offeringId)).thenReturn( Arrays.asList(dpdkNumaDetailVO, dpdkHugePagesDetailVO)); Mockito.verify(vmTO, Mockito.never()).addExtraConfig(Mockito.anyString(), Mockito.anyString()); } diff --git a/server/src/test/java/com/cloud/keystore/KeystoreTest.java b/server/src/test/java/com/cloud/keystore/KeystoreTest.java index 1981a7315f4b..24cc3a74d418 100644 --- a/server/src/test/java/com/cloud/keystore/KeystoreTest.java +++ b/server/src/test/java/com/cloud/keystore/KeystoreTest.java @@ -16,17 +16,16 @@ // under the License. package com.cloud.keystore; -import junit.framework.TestCase; - +import org.apache.cloudstack.api.response.AlertResponse; +import org.apache.cloudstack.api.response.UserVmResponse; import org.apache.log4j.Logger; import org.junit.After; import org.junit.Before; -import org.apache.cloudstack.api.response.AlertResponse; -import org.apache.cloudstack.api.response.UserVmResponse; - import com.cloud.api.ApiSerializerHelper; +import junit.framework.TestCase; + public class KeystoreTest extends TestCase { private final static Logger s_logger = Logger.getLogger(KeystoreTest.class); diff --git a/server/src/test/java/com/cloud/network/CreatePrivateNetworkTest.java b/server/src/test/java/com/cloud/network/CreatePrivateNetworkTest.java index 2e06039ccd55..d316caa42a78 100644 --- a/server/src/test/java/com/cloud/network/CreatePrivateNetworkTest.java +++ b/server/src/test/java/com/cloud/network/CreatePrivateNetworkTest.java @@ -17,21 +17,26 @@ package com.cloud.network; -import junit.framework.Assert; +import static org.junit.Assert.fail; +import static org.mockito.ArgumentMatchers.nullable; +import static org.mockito.Matchers.anyBoolean; +import static org.mockito.Matchers.anyLong; +import static org.mockito.Matchers.anyString; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.when; import java.util.ArrayList; import java.util.List; import java.util.UUID; +import org.apache.cloudstack.acl.ControlledEntity.ACLType; +import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService; import org.apache.log4j.Logger; import org.junit.Before; import org.junit.Test; import org.mockito.Mock; import org.mockito.MockitoAnnotations; -import org.apache.cloudstack.acl.ControlledEntity.ACLType; -import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService; - import com.cloud.dc.DataCenter.NetworkType; import com.cloud.dc.DataCenterVO; import com.cloud.dc.dao.DataCenterDao; @@ -57,12 +62,7 @@ import com.cloud.utils.db.TransactionLegacy; import com.cloud.utils.exception.CloudRuntimeException; -import static org.junit.Assert.fail; -import static org.mockito.Matchers.anyBoolean; -import static org.mockito.Matchers.anyLong; -import static org.mockito.Matchers.anyString; -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.when; +import junit.framework.Assert; //@Ignore("Requires database to be set up") public class CreatePrivateNetworkTest { @@ -104,6 +104,7 @@ public void setup() throws Exception { NetworkOfferingVO ntwkOff = new NetworkOfferingVO("offer", "fakeOffer", TrafficType.Guest, true, true, null, null, false, null, null, GuestType.Isolated, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false); + when(networkService._networkOfferingDao.findById(anyLong())).thenReturn(ntwkOff); List netofferlist = new ArrayList(); netofferlist.add(ntwkOff); @@ -120,10 +121,9 @@ public void setup() throws Exception { Network net = new NetworkVO(1L, TrafficType.Guest, Mode.None, BroadcastDomainType.Vlan, 1L, 1L, 1L, 1L, "bla", "fake", "eet.net", GuestType.Isolated, 1L, 1L, ACLType.Account, false, 1L, false); - when( - networkService._networkMgr.createGuestNetwork(eq(ntwkOff.getId()), eq("bla"), eq("fake"), eq("10.1.1.1"), eq("10.1.1.0/24"), anyString(), anyBoolean(), anyString(), - eq(account), anyLong(), eq(physicalNetwork), eq(physicalNetwork.getDataCenterId()), eq(ACLType.Account), anyBoolean(), eq(1L), anyString(), anyString(), - anyBoolean(), anyString(), anyString())).thenReturn(net); + when(networkService._networkMgr.createGuestNetwork(eq(ntwkOff.getId()), eq("bla"), eq("fake"), eq("10.1.1.1"), eq("10.1.1.0/24"), nullable(String.class), nullable(Boolean.class), nullable(String.class), + eq(account), nullable(Long.class), eq(physicalNetwork), eq(physicalNetwork.getDataCenterId()), eq(ACLType.Account), nullable(Boolean.class), eq(1L), nullable(String.class), nullable(String.class), + nullable(Boolean.class), nullable(String.class), nullable(Network.PVlanType.class), nullable(String.class))).thenReturn(net); when(networkService._privateIpDao.findByIpAndSourceNetworkId(net.getId(), "10.1.1.2")).thenReturn(null); when(networkService._privateIpDao.findByIpAndSourceNetworkIdAndVpcId(eq(1L), anyString(), eq(1L))).thenReturn(null); diff --git a/server/src/test/java/com/cloud/network/ExternalLoadBalancerDeviceManagerImplTest.java b/server/src/test/java/com/cloud/network/ExternalLoadBalancerDeviceManagerImplTest.java index 47c3250bcaa0..9776eaa408d8 100644 --- a/server/src/test/java/com/cloud/network/ExternalLoadBalancerDeviceManagerImplTest.java +++ b/server/src/test/java/com/cloud/network/ExternalLoadBalancerDeviceManagerImplTest.java @@ -26,7 +26,6 @@ import javax.inject.Inject; -import com.cloud.host.Host; import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService; import org.apache.cloudstack.framework.config.dao.ConfigurationDao; import org.junit.Assert; @@ -45,6 +44,7 @@ import com.cloud.dc.dao.HostPodDao; import com.cloud.dc.dao.VlanDao; import com.cloud.exception.ResourceUnavailableException; +import com.cloud.host.Host; import com.cloud.host.HostVO; import com.cloud.host.dao.HostDao; import com.cloud.host.dao.HostDetailsDao; @@ -232,8 +232,8 @@ private void setupLBHealthChecksMocks() throws URISyntaxException { public void testUsageTask() { ExternalDeviceUsageManagerImpl.ExternalDeviceNetworkUsageTask usageTask = Mockito .mock(ExternalDeviceUsageManagerImpl.ExternalDeviceNetworkUsageTask.class); - Mockito.when(_hostDao.listByType(Host.Type.ExternalFirewall)).thenReturn(new ArrayList()); - Mockito.when(_hostDao.listByType(Host.Type.ExternalLoadBalancer)).thenReturn(new ArrayList()); + Mockito.lenient().when(_hostDao.listByType(Host.Type.ExternalFirewall)).thenReturn(new ArrayList()); + Mockito.lenient().when(_hostDao.listByType(Host.Type.ExternalLoadBalancer)).thenReturn(new ArrayList()); usageTask.runInContext(); Mockito.verify(usageTask, Mockito.times(0)).runExternalDeviceNetworkUsageTask(); } diff --git a/server/src/test/java/com/cloud/network/IpAddressManagerTest.java b/server/src/test/java/com/cloud/network/IpAddressManagerTest.java index 74deb2d3a995..3cf550ae8822 100644 --- a/server/src/test/java/com/cloud/network/IpAddressManagerTest.java +++ b/server/src/test/java/com/cloud/network/IpAddressManagerTest.java @@ -21,6 +21,7 @@ import static org.junit.Assert.assertTrue; import static org.mockito.Matchers.anyLong; import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.lenient; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -93,8 +94,8 @@ public void setup() throws ResourceUnavailableException { public void testGetStaticNatSourceIps() { String publicIpAddress = "192.168.1.3"; IPAddressVO vo = mock(IPAddressVO.class); - when(vo.getAddress()).thenReturn(new Ip(publicIpAddress)); - when(vo.getId()).thenReturn(1l); + lenient().when(vo.getAddress()).thenReturn(new Ip(publicIpAddress)); + lenient().when(vo.getId()).thenReturn(1l); when(ipAddressDao.findById(anyLong())).thenReturn(vo); StaticNat snat = new StaticNatImpl(1, 1, 1, 1, publicIpAddress, false); @@ -154,14 +155,14 @@ public void isIpEqualsGatewayOrNetworkOfferingsEmptyTestExpectFalseServicesCidrN public void assertSourceNatImplementedNetwork() { NetworkVO networkImplemented = Mockito.mock(NetworkVO.class); - when(networkImplemented.getTrafficType()).thenReturn(Networks.TrafficType.Guest); - when(networkImplemented.getNetworkOfferingId()).thenReturn(8L); - when(networkImplemented.getState()).thenReturn(Network.State.Implemented); + lenient().when(networkImplemented.getTrafficType()).thenReturn(Networks.TrafficType.Guest); + lenient().when(networkImplemented.getNetworkOfferingId()).thenReturn(8L); + lenient().when(networkImplemented.getState()).thenReturn(Network.State.Implemented); when(networkImplemented.getGuestType()).thenReturn(Network.GuestType.Isolated); when(networkImplemented.getVpcId()).thenReturn(null); when(networkImplemented.getId()).thenReturn(1L); - Mockito.when(networkDao.findById(1L)).thenReturn(networkImplemented); + Mockito.lenient().when(networkDao.findById(1L)).thenReturn(networkImplemented); doReturn(null).when(ipAddressManager).getExistingSourceNatInNetwork(1L, 1L); boolean isSourceNat = ipAddressManager.isSourceNatAvailableForNetwork(account, ipAddressVO, networkImplemented); @@ -173,14 +174,14 @@ public void assertSourceNatImplementedNetwork() { public void assertSourceNatAllocatedNetwork() { NetworkVO networkAllocated = Mockito.mock(NetworkVO.class); - when(networkAllocated.getTrafficType()).thenReturn(Networks.TrafficType.Guest); + lenient().when(networkAllocated.getTrafficType()).thenReturn(Networks.TrafficType.Guest); when(networkAllocated.getNetworkOfferingId()).thenReturn(8L); - when(networkAllocated.getState()).thenReturn(Network.State.Allocated); + lenient().when(networkAllocated.getState()).thenReturn(Network.State.Allocated); when(networkAllocated.getGuestType()).thenReturn(Network.GuestType.Isolated); when(networkAllocated.getVpcId()).thenReturn(null); when(networkAllocated.getId()).thenReturn(2L); - Mockito.when(networkDao.findById(2L)).thenReturn(networkAllocated); + Mockito.lenient().when(networkDao.findById(2L)).thenReturn(networkAllocated); doReturn(null).when(ipAddressManager).getExistingSourceNatInNetwork(1L, 2L); assertTrue(ipAddressManager.isSourceNatAvailableForNetwork(account, ipAddressVO, networkAllocated)); @@ -190,17 +191,17 @@ public void assertSourceNatAllocatedNetwork() { public void assertExistingSourceNatAllocatedNetwork() { NetworkVO networkNat = Mockito.mock(NetworkVO.class); - when(networkNat.getTrafficType()).thenReturn(Networks.TrafficType.Guest); + lenient().when(networkNat.getTrafficType()).thenReturn(Networks.TrafficType.Guest); when(networkNat.getNetworkOfferingId()).thenReturn(8L); - when(networkNat.getState()).thenReturn(Network.State.Implemented); - when(networkNat.getGuestType()).thenReturn(Network.GuestType.Isolated); + lenient().when(networkNat.getState()).thenReturn(Network.State.Implemented); + lenient().when(networkNat.getGuestType()).thenReturn(Network.GuestType.Isolated); when(networkNat.getId()).thenReturn(3L); - when(networkNat.getVpcId()).thenReturn(null); + lenient().when(networkNat.getVpcId()).thenReturn(null); when(networkNat.getId()).thenReturn(3L); IPAddressVO sourceNat = new IPAddressVO(new Ip("192.0.0.2"), 1L, 1L, 1L,true); - Mockito.when(networkDao.findById(3L)).thenReturn(networkNat); + Mockito.lenient().when(networkDao.findById(3L)).thenReturn(networkNat); doReturn(sourceNat).when(ipAddressManager).getExistingSourceNatInNetwork(1L, 3L); boolean isSourceNat = ipAddressManager.isSourceNatAvailableForNetwork(account, ipAddressVO, networkNat); diff --git a/server/src/test/java/com/cloud/network/NetworkServiceImplTest.java b/server/src/test/java/com/cloud/network/NetworkServiceImplTest.java new file mode 100644 index 000000000000..2520f3902ba3 --- /dev/null +++ b/server/src/test/java/com/cloud/network/NetworkServiceImplTest.java @@ -0,0 +1,120 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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. +package com.cloud.network; + +import com.cloud.utils.Pair; +import com.cloud.utils.exception.CloudRuntimeException; +import org.junit.Assert; +import org.junit.Test; + +public class NetworkServiceImplTest { + + private NetworkServiceImpl service = new NetworkServiceImpl(); + + private static final String VLAN_ID_900 = "900"; + private static final String VLAN_ID_901 = "901"; + private static final String VLAN_ID_902 = "902"; + + @Test + public void testGetPrivateVlanPairNoVlans() { + Pair pair = service.getPrivateVlanPair(null, null, null); + Assert.assertNull(pair.first()); + Assert.assertNull(pair.second()); + } + + @Test + public void testGetPrivateVlanPairVlanPrimaryOnly() { + Pair pair = service.getPrivateVlanPair(null, null, VLAN_ID_900); + Assert.assertNull(pair.first()); + Assert.assertNull(pair.second()); + } + + @Test + public void testGetPrivateVlanPairVlanPrimaryPromiscuousType() { + Pair pair = service.getPrivateVlanPair(null, Network.PVlanType.Promiscuous.toString(), VLAN_ID_900); + Assert.assertEquals(VLAN_ID_900, pair.first()); + Assert.assertEquals(Network.PVlanType.Promiscuous, pair.second()); + } + + @Test + public void testGetPrivateVlanPairPromiscuousType() { + Pair pair = service.getPrivateVlanPair(VLAN_ID_900, Network.PVlanType.Promiscuous.toString(), VLAN_ID_900); + Assert.assertEquals(VLAN_ID_900, pair.first()); + Assert.assertEquals(Network.PVlanType.Promiscuous, pair.second()); + } + + @Test + public void testGetPrivateVlanPairPromiscuousTypeOnSecondaryVlanId() { + Pair pair = service.getPrivateVlanPair(VLAN_ID_900, "promiscuous", VLAN_ID_900); + Assert.assertEquals(VLAN_ID_900, pair.first()); + Assert.assertEquals(Network.PVlanType.Promiscuous, pair.second()); + } + + @Test + public void testGetPrivateVlanPairIsolatedType() { + Pair pair = service.getPrivateVlanPair(VLAN_ID_901, Network.PVlanType.Isolated.toString(), VLAN_ID_900); + Assert.assertEquals(VLAN_ID_901, pair.first()); + Assert.assertEquals(Network.PVlanType.Isolated, pair.second()); + } + + @Test + public void testGetPrivateVlanPairIsolatedTypeOnSecondaryVlanId() { + Pair pair = service.getPrivateVlanPair(VLAN_ID_901, "isolated", VLAN_ID_900); + Assert.assertEquals(VLAN_ID_901, pair.first()); + Assert.assertEquals(Network.PVlanType.Isolated, pair.second()); + } + + @Test + public void testGetPrivateVlanPairCommunityType() { + Pair pair = service.getPrivateVlanPair(VLAN_ID_902, Network.PVlanType.Community.toString(), VLAN_ID_900); + Assert.assertEquals(VLAN_ID_902, pair.first()); + Assert.assertEquals(Network.PVlanType.Community, pair.second()); + } + + @Test + public void testGetPrivateVlanPairCommunityTypeOnSecondaryVlanId() { + Pair pair = service.getPrivateVlanPair(VLAN_ID_902, "community", VLAN_ID_900); + Assert.assertEquals(VLAN_ID_902, pair.first()); + Assert.assertEquals(Network.PVlanType.Community, pair.second()); + } + + @Test(expected = CloudRuntimeException.class) + public void testPerformBasicChecksPromiscuousTypeExpectedIsolatedSet() { + service.performBasicPrivateVlanChecks(VLAN_ID_900, VLAN_ID_900, Network.PVlanType.Isolated); + } + + @Test(expected = CloudRuntimeException.class) + public void testPerformBasicChecksPromiscuousTypeExpectedCommunitySet() { + service.performBasicPrivateVlanChecks(VLAN_ID_900, VLAN_ID_900, Network.PVlanType.Community); + } + + @Test(expected = CloudRuntimeException.class) + public void testPerformBasicChecksPromiscuousTypeExpectedSecondaryVlanNullIsolatedSet() { + service.performBasicPrivateVlanChecks(VLAN_ID_900, null, Network.PVlanType.Isolated); + } + + @Test(expected = CloudRuntimeException.class) + public void testPerformBasicChecksPromiscuousTypeExpectedSecondaryVlanNullCommunitySet() { + service.performBasicPrivateVlanChecks(VLAN_ID_900, null, Network.PVlanType.Community); + } + + @Test(expected = CloudRuntimeException.class) + public void testPerformBasicChecksPromiscuousTypeExpectedDifferentVlanIds() { + service.performBasicPrivateVlanChecks(VLAN_ID_900, VLAN_ID_901, Network.PVlanType.Promiscuous); + } + +} diff --git a/server/src/test/java/com/cloud/network/dao/NetworkDaoTest.java b/server/src/test/java/com/cloud/network/dao/NetworkDaoTest.java index 140c850a609f..ca918691d09c 100644 --- a/server/src/test/java/com/cloud/network/dao/NetworkDaoTest.java +++ b/server/src/test/java/com/cloud/network/dao/NetworkDaoTest.java @@ -16,46 +16,40 @@ // under the License. package com.cloud.network.dao; +import com.cloud.network.Network; import junit.framework.TestCase; +import org.junit.Assert; +import org.mockito.Spy; public class NetworkDaoTest extends TestCase { - public void testTags() { -// NetworkDaoImpl dao = ComponentLocator.inject(NetworkDaoImpl.class); -// -// dao.expunge(1001l); -// NetworkVO network = new NetworkVO(1001, TrafficType.Control, GuestType.Shared, Mode.Dhcp, BroadcastDomainType.Native, 1, 1, 1, 1, 1001, "Name", "DisplayText", false, true, true, null, null); -// network.setGuruName("guru_name"); -// List tags = new ArrayList(); -// -// tags.add("a"); -// tags.add("b"); -// network.setTags(tags); -// -// network = dao.persist(network); -// List saveTags = network.getTags(); -// Assert.assertTrue(saveTags.size() == 2 && saveTags.contains("a") && saveTags.contains("b")); -// -// NetworkVO retrieved = dao.findById(1001l); -// List retrievedTags = retrieved.getTags(); -// Assert.assertTrue(retrievedTags.size() == 2 && retrievedTags.contains("a") && retrievedTags.contains("b")); -// -// List updateTags = new ArrayList(); -// updateTags.add("e"); -// updateTags.add("f"); -// retrieved.setTags(updateTags); -// dao.update(retrieved.getId(), retrieved); -// -// retrieved = dao.findById(1001l); -// retrievedTags = retrieved.getTags(); -// Assert.assertTrue("Unable to retrieve back the data updated", retrievedTags.size() == 2 && retrievedTags.contains("e") && retrievedTags.contains("f")); -// -// dao.expunge(1001l); + + @Spy + private NetworkDaoImpl dao = new NetworkDaoImpl(); + + private static final Integer existingPrimaryVlan = 900; + private static final Integer existingSecondaryVlan = 901; + + private static final Integer requestedVlan = 902; + + public void testNetworkOverlappingExactPair() { + Assert.assertTrue(dao.isNetworkOverlappingRequestedPvlan(existingPrimaryVlan, existingSecondaryVlan, Network.PVlanType.Isolated, + existingPrimaryVlan, existingSecondaryVlan, Network.PVlanType.Isolated)); + Assert.assertTrue(dao.isNetworkOverlappingRequestedPvlan(existingPrimaryVlan, existingSecondaryVlan, Network.PVlanType.Isolated, + existingPrimaryVlan, existingSecondaryVlan, Network.PVlanType.Community)); } - public void testListBy() { -// NetworkDaoImpl dao = ComponentLocator.inject(NetworkDaoImpl.class); -// -// dao.listBy(1l, 1l, 1l, "192.168.192.0/24"); + public void testNetworkOverlappingPromiscuous() { + Assert.assertTrue(dao.isNetworkOverlappingRequestedPvlan(existingPrimaryVlan, existingPrimaryVlan, Network.PVlanType.Promiscuous, + existingPrimaryVlan, existingPrimaryVlan, Network.PVlanType.Promiscuous)); } + public void testNetworkOverlappingIsolated() { + Assert.assertTrue(dao.isNetworkOverlappingRequestedPvlan(existingPrimaryVlan, existingSecondaryVlan, Network.PVlanType.Isolated, + existingPrimaryVlan, requestedVlan, Network.PVlanType.Isolated)); + } + + public void testNetworkOverlappingMultipleCommunityAllowed() { + Assert.assertFalse(dao.isNetworkOverlappingRequestedPvlan(existingPrimaryVlan, existingSecondaryVlan, Network.PVlanType.Community, + existingPrimaryVlan, requestedVlan, Network.PVlanType.Community)); + } } diff --git a/server/src/test/java/com/cloud/network/element/VirtualRouterElementTest.java b/server/src/test/java/com/cloud/network/element/VirtualRouterElementTest.java index 2d66ea70f6c4..7c2a3c781785 100644 --- a/server/src/test/java/com/cloud/network/element/VirtualRouterElementTest.java +++ b/server/src/test/java/com/cloud/network/element/VirtualRouterElementTest.java @@ -22,16 +22,12 @@ import static org.mockito.Matchers.anyList; import static org.mockito.Matchers.anyLong; import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.lenient; import static org.mockito.Mockito.when; import java.util.ArrayList; import java.util.List; -import com.cloud.exception.AgentUnavailableException; -import com.cloud.network.dao.NetworkDetailVO; -import com.cloud.network.dao.NetworkDetailsDao; -import com.cloud.network.router.VirtualRouter; -import com.cloud.utils.exception.CloudRuntimeException; import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService; import org.apache.cloudstack.framework.config.dao.ConfigurationDao; import org.cloud.network.router.deployment.RouterDeploymentDefinitionBuilder; @@ -44,6 +40,7 @@ import org.mockito.Mockito; import org.mockito.invocation.InvocationOnMock; import org.mockito.runners.MockitoJUnitRunner; +import org.mockito.stubbing.Answer; import com.cloud.cluster.dao.ManagementServerHostDao; import com.cloud.configuration.ConfigurationManager; @@ -56,6 +53,7 @@ import com.cloud.dc.dao.VlanDao; import com.cloud.deploy.DeployDestination; import com.cloud.deploy.DeploymentPlan; +import com.cloud.exception.AgentUnavailableException; import com.cloud.exception.ConcurrentOperationException; import com.cloud.exception.InsufficientCapacityException; import com.cloud.exception.ResourceUnavailableException; @@ -73,6 +71,8 @@ import com.cloud.network.dao.LoadBalancerVMMapDao; import com.cloud.network.dao.MonitoringServiceDao; import com.cloud.network.dao.NetworkDao; +import com.cloud.network.dao.NetworkDetailVO; +import com.cloud.network.dao.NetworkDetailsDao; import com.cloud.network.dao.NetworkVO; import com.cloud.network.dao.OpRouterMonitorServiceDao; import com.cloud.network.dao.OvsProviderDao; @@ -85,6 +85,7 @@ import com.cloud.network.dao.UserIpv6AddressDao; import com.cloud.network.dao.VirtualRouterProviderDao; import com.cloud.network.dao.VpnUserDao; +import com.cloud.network.router.VirtualRouter; import com.cloud.network.router.VirtualRouter.RedundantState; import com.cloud.network.router.VpcVirtualNetworkApplianceManagerImpl; import com.cloud.network.rules.dao.PortForwardingRulesDao; @@ -105,6 +106,7 @@ import com.cloud.user.dao.UserDao; import com.cloud.user.dao.UserStatisticsDao; import com.cloud.user.dao.UserStatsLogDao; +import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.vm.DomainRouterVO; import com.cloud.vm.NicProfile; import com.cloud.vm.ReservationContext; @@ -119,7 +121,6 @@ import com.cloud.vm.dao.UserVmDao; import com.cloud.vm.dao.UserVmDetailsDao; import com.cloud.vm.dao.VMInstanceDao; -import org.mockito.stubbing.Answer; @RunWith(MockitoJUnitRunner.class) public class VirtualRouterElementTest { @@ -320,11 +321,11 @@ private void mockMgrs() throws ConcurrentOperationException { * @param network */ private void mockDAOs(final NetworkVO network, final NetworkOfferingVO offering) { - when(_networkDao.acquireInLockTable(network.getId(), NetworkOrchestrationService.NetworkLockTimeout.value())).thenReturn(network); - when(_networksDao.acquireInLockTable(network.getId(), NetworkOrchestrationService.NetworkLockTimeout.value())).thenReturn(network); - when(_physicalProviderDao.findByServiceProvider(0L, "VirtualRouter")).thenReturn(new PhysicalNetworkServiceProviderVO()); - when(_vrProviderDao.findByNspIdAndType(0L, Type.VirtualRouter)).thenReturn(new VirtualRouterProviderVO()); - when(_networkOfferingDao.findById(0L)).thenReturn(offering); + lenient().when(_networkDao.acquireInLockTable(network.getId(), NetworkOrchestrationService.NetworkLockTimeout.value())).thenReturn(network); + lenient().when(_networksDao.acquireInLockTable(network.getId(), NetworkOrchestrationService.NetworkLockTimeout.value())).thenReturn(network); + lenient().when(_physicalProviderDao.findByServiceProvider(0L, "VirtualRouter")).thenReturn(new PhysicalNetworkServiceProviderVO()); + lenient().when(_vrProviderDao.findByNspIdAndType(0L, Type.VirtualRouter)).thenReturn(new VirtualRouterProviderVO()); + lenient().when(_networkOfferingDao.findById(0L)).thenReturn(offering); // watchit: (in this test) there can be only one when(_routerDao.getNextInSequence(Long.class, "id")).thenReturn(0L); final ServiceOfferingVO svcoff = new ServiceOfferingVO("name", @@ -342,8 +343,8 @@ private void mockDAOs(final NetworkVO network, final NetworkOfferingVO offering) /* systemUse */ false, VirtualMachine.Type.DomainRouter, /* defaultUse */ false); - when(_serviceOfferingDao.findById(0L)).thenReturn(svcoff); - when(_serviceOfferingDao.findByName(Matchers.anyString())).thenReturn(svcoff); + lenient().when(_serviceOfferingDao.findById(0L)).thenReturn(svcoff); + lenient().when(_serviceOfferingDao.findByName(Matchers.anyString())).thenReturn(svcoff); final DomainRouterVO router = new DomainRouterVO(/* id */ 1L, /* serviceOfferingId */ 1L, /* elementId */ 0L, @@ -435,10 +436,10 @@ private void mockDAOs(final NetworkVO network, final NetworkOfferingVO offering) List routerList3=new ArrayList<>(); routerList3.add(routerUpdateComplete); routerList3.add(routerUpdateInProgress); - when(_routerDao.getNextInSequence(Long.class, "id")).thenReturn(1L); - when(_templateDao.findRoutingTemplate(HypervisorType.XenServer, "SystemVM Template (XenServer)")).thenReturn(new VMTemplateVO()); - when(_routerDao.persist(any(DomainRouterVO.class))).thenReturn(router); - when(_routerDao.findById(router.getId())).thenReturn(router); + lenient().when(_routerDao.getNextInSequence(Long.class, "id")).thenReturn(1L); + lenient().when(_templateDao.findRoutingTemplate(HypervisorType.XenServer, "SystemVM Template (XenServer)")).thenReturn(new VMTemplateVO()); + lenient().when(_routerDao.persist(any(DomainRouterVO.class))).thenReturn(router); + lenient().when(_routerDao.findById(router.getId())).thenReturn(router); when(_routerDao.listByNetworkAndRole(1l, VirtualRouter.Role.VIRTUAL_ROUTER)).thenReturn(routerList1); when(_routerDao.listByNetworkAndRole(2l, VirtualRouter.Role.VIRTUAL_ROUTER)).thenReturn(routerList2); when(_routerDao.listByNetworkAndRole(3l, VirtualRouter.Role.VIRTUAL_ROUTER)).thenReturn(routerList1); @@ -459,10 +460,10 @@ public void testCanHandle() { final long dataCenterId = 33; when(network.getId()).thenReturn(networkId); - when(network.getPhysicalNetworkId()).thenReturn(physicalNetworkId); - when(network.getTrafficType()).thenReturn(TrafficType.Guest); - when(network.getNetworkOfferingId()).thenReturn(networkOfferingId); - when(network.getDataCenterId()).thenReturn(dataCenterId); + lenient().when(network.getPhysicalNetworkId()).thenReturn(physicalNetworkId); + lenient().when(network.getTrafficType()).thenReturn(TrafficType.Guest); + lenient().when(network.getNetworkOfferingId()).thenReturn(networkOfferingId); + lenient().when(network.getDataCenterId()).thenReturn(dataCenterId); when(network.getVpcId()).thenReturn(null); when(virtualRouterElement._networkMdl.getPhysicalNetworkId(network)).thenReturn(physicalNetworkId); @@ -487,19 +488,19 @@ public void testAddPasswordAndUserdata() throws Exception { final long dataCenterId = 33; when(network.getId()).thenReturn(networkId); - when(network.getPhysicalNetworkId()).thenReturn(physicalNetworkId); - when(network.getTrafficType()).thenReturn(TrafficType.Guest); - when(network.getNetworkOfferingId()).thenReturn(networkOfferingId); - when(network.getDataCenterId()).thenReturn(dataCenterId); + lenient().when(network.getPhysicalNetworkId()).thenReturn(physicalNetworkId); + lenient().when(network.getTrafficType()).thenReturn(TrafficType.Guest); + lenient().when(network.getNetworkOfferingId()).thenReturn(networkOfferingId); + lenient().when(network.getDataCenterId()).thenReturn(dataCenterId); when(network.getVpcId()).thenReturn(null); - when(vm.getType()).thenReturn(VirtualMachine.Type.User); + lenient().when(vm.getType()).thenReturn(VirtualMachine.Type.User); when(virtualRouterElement._networkMdl.getPhysicalNetworkId(network)).thenReturn(physicalNetworkId); when(virtualRouterElement._networkMdl.isProviderEnabledInPhysicalNetwork(physicalNetworkId, Network.Provider.VirtualRouter.getName())).thenReturn(true); when(virtualRouterElement._networkMdl.isProviderSupportServiceInNetwork(networkId, service, Network.Provider.VirtualRouter)).thenReturn(true); - when(virtualRouterElement._dcDao.findById(dataCenterId)).thenReturn(Mockito.mock(DataCenterVO.class)); + lenient().when(virtualRouterElement._dcDao.findById(dataCenterId)).thenReturn(Mockito.mock(DataCenterVO.class)); when(virtualRouterElement.canHandle(network, service)).thenReturn(false); diff --git a/server/src/test/java/com/cloud/network/lb/UpdateLoadBalancerTest.java b/server/src/test/java/com/cloud/network/lb/UpdateLoadBalancerTest.java index 0b67eb72367a..8aef1b97c2eb 100644 --- a/server/src/test/java/com/cloud/network/lb/UpdateLoadBalancerTest.java +++ b/server/src/test/java/com/cloud/network/lb/UpdateLoadBalancerTest.java @@ -16,15 +16,15 @@ // under the License. package com.cloud.network.lb; -import static org.mockito.Matchers.anyLong; +import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyLong; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.when; import java.util.ArrayList; import java.util.UUID; -import com.cloud.user.User; import org.apache.cloudstack.api.command.user.loadbalancer.UpdateLoadBalancerRuleCmd; import org.apache.cloudstack.context.CallContext; import org.junit.After; @@ -53,6 +53,7 @@ import com.cloud.user.Account; import com.cloud.user.AccountVO; import com.cloud.user.MockAccountManagerImpl; +import com.cloud.user.User; import com.cloud.user.UserVO; public class UpdateLoadBalancerTest { @@ -94,17 +95,17 @@ public void testValidateRuleBeforeUpdateLB() throws ResourceAllocationException, LoadBalancerVO lb = new LoadBalancerVO(null, null, null, 0L, 0, 0, null, 0L, 0L, domainId, null); - when(lbDao.findById(anyLong())).thenReturn(lb); + when(lbDao.findById(isNull())).thenReturn(lb); when(netModel.getPublicIpAddress(anyLong())).thenReturn(Mockito.mock(PublicIpAddress.class)); when(netDao.findById(anyLong())).thenReturn(Mockito.mock(NetworkVO.class)); when(lbServiceProvider.validateLBRule(any(Network.class), any(LoadBalancingRule.class))).thenReturn(true); - when(lbDao.update(anyLong(), eq(lb))).thenReturn(true); + when(lbDao.update(isNull(), eq(lb))).thenReturn(true); _lbMgr.updateLoadBalancerRule(updateLbRuleCmd); InOrder inOrder = Mockito.inOrder(lbServiceProvider, lbDao); inOrder.verify(lbServiceProvider).validateLBRule(any(Network.class), any(LoadBalancingRule.class)); - inOrder.verify(lbDao).update(anyLong(), eq(lb)); + inOrder.verify(lbDao).update(isNull(),eq(lb)); } @Test(expected = InvalidParameterValueException.class) diff --git a/server/src/test/java/com/cloud/network/router/NetworkHelperImplTest.java b/server/src/test/java/com/cloud/network/router/NetworkHelperImplTest.java index 952818d7aea0..4267b71d24fa 100644 --- a/server/src/test/java/com/cloud/network/router/NetworkHelperImplTest.java +++ b/server/src/test/java/com/cloud/network/router/NetworkHelperImplTest.java @@ -19,6 +19,7 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.lenient; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; @@ -85,7 +86,7 @@ public void testSendCommandsToRouter() Answer[] answers = {answer1, answer2, answer3}; when(answer1.getResult()).thenReturn(true); when(answer2.getResult()).thenReturn(false); - when(answer3.getResult()).thenReturn(false); + lenient().when(answer3.getResult()).thenReturn(false); when(this.agentManager.send(HOST_ID, commands)).thenReturn(answers); // Execute diff --git a/server/src/test/java/com/cloud/network/router/RouterControlHelperTest.java b/server/src/test/java/com/cloud/network/router/RouterControlHelperTest.java index 41f4c27f22b5..a3040f1fece4 100644 --- a/server/src/test/java/com/cloud/network/router/RouterControlHelperTest.java +++ b/server/src/test/java/com/cloud/network/router/RouterControlHelperTest.java @@ -17,6 +17,7 @@ package com.cloud.network.router; import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.lenient; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -68,9 +69,9 @@ public void testGetRouterControlIp() { NicVO nic3 = mock(NicVO.class); when(nic1.getNetworkId()).thenReturn(NW_ID_1); when(nic2.getNetworkId()).thenReturn(NW_ID_2); - when(nic2.getIPv4Address()).thenReturn(IP4_ADDRES1); - when(nic3.getNetworkId()).thenReturn(NW_ID_3); - when(nic3.getIPv4Address()).thenReturn(IP4_ADDRES2); + lenient().when(nic2.getIPv4Address()).thenReturn(IP4_ADDRES1); + lenient().when(nic3.getNetworkId()).thenReturn(NW_ID_3); + lenient().when(nic3.getIPv4Address()).thenReturn(IP4_ADDRES2); nics.add(nic1); nics.add(nic2); nics.add(nic3); @@ -81,10 +82,10 @@ public void testGetRouterControlIp() { NetworkVO nw2 = mock(NetworkVO.class); when(nw2.getTrafficType()).thenReturn(TrafficType.Control); NetworkVO nw3 = mock(NetworkVO.class); - when(nw3.getTrafficType()).thenReturn(TrafficType.Control); + lenient().when(nw3.getTrafficType()).thenReturn(TrafficType.Control); when(this.nwDao.findById(NW_ID_1)).thenReturn(nw1); when(this.nwDao.findById(NW_ID_2)).thenReturn(nw2); - when(this.nwDao.findById(NW_ID_3)).thenReturn(nw3); + lenient().when(this.nwDao.findById(NW_ID_3)).thenReturn(nw3); // Execute final String ip4address = this.routerControlHelper.getRouterControlIp(ROUTER_ID); @@ -99,7 +100,7 @@ public void testGetRouterControlIpWithRouterIp() { List nics = new ArrayList<>(); NicVO nic1 = mock(NicVO.class); when(nic1.getNetworkId()).thenReturn(NW_ID_1); - when(nic1.getIPv4Address()).thenReturn(null); + lenient().when(nic1.getIPv4Address()).thenReturn(null); nics.add(nic1); when(this.nicDao.listByVmId(ROUTER_ID)).thenReturn(nics); diff --git a/server/src/test/java/com/cloud/network/router/VirtualNetworkApplianceManagerImplTest.java b/server/src/test/java/com/cloud/network/router/VirtualNetworkApplianceManagerImplTest.java index f87b009c79b5..0ddbd845a8c7 100644 --- a/server/src/test/java/com/cloud/network/router/VirtualNetworkApplianceManagerImplTest.java +++ b/server/src/test/java/com/cloud/network/router/VirtualNetworkApplianceManagerImplTest.java @@ -16,17 +16,42 @@ // under the License. package com.cloud.network.router; +import static org.junit.Assert.assertEquals; +import static org.mockito.ArgumentMatchers.nullable; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyLong; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.lenient; +import static org.mockito.Mockito.when; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +import org.apache.cloudstack.framework.config.dao.ConfigurationDao; +import org.apache.cloudstack.utils.identity.ManagementServerNode; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; + import com.cloud.agent.AgentManager; import com.cloud.agent.api.CheckS2SVpnConnectionsAnswer; import com.cloud.agent.api.CheckS2SVpnConnectionsCommand; import com.cloud.alert.AlertManager; +import com.cloud.cluster.dao.ManagementServerHostDao; +import com.cloud.dc.dao.ClusterDao; +import com.cloud.dc.dao.DataCenterDao; +import com.cloud.dc.dao.HostPodDao; +import com.cloud.dc.dao.VlanDao; import com.cloud.host.Host; import com.cloud.host.HostVO; import com.cloud.host.Status; +import com.cloud.host.dao.HostDao; import com.cloud.hypervisor.Hypervisor; import com.cloud.network.Site2SiteVpnConnection; -import com.cloud.network.dao.Site2SiteVpnConnectionVO; -import com.cloud.network.dao.Site2SiteCustomerGatewayDao; import com.cloud.network.dao.FirewallRulesDao; import com.cloud.network.dao.IPAddressDao; import com.cloud.network.dao.LoadBalancerDao; @@ -36,39 +61,27 @@ import com.cloud.network.dao.OpRouterMonitorServiceDao; import com.cloud.network.dao.PhysicalNetworkServiceProviderDao; import com.cloud.network.dao.RemoteAccessVpnDao; +import com.cloud.network.dao.Site2SiteCustomerGatewayDao; import com.cloud.network.dao.Site2SiteCustomerGatewayVO; import com.cloud.network.dao.Site2SiteVpnConnectionDao; +import com.cloud.network.dao.Site2SiteVpnConnectionVO; import com.cloud.network.dao.Site2SiteVpnGatewayDao; import com.cloud.network.dao.UserIpv6AddressDao; import com.cloud.network.dao.VirtualRouterProviderDao; import com.cloud.network.dao.VpnUserDao; -import com.cloud.network.vpn.Site2SiteVpnManager; -import com.cloud.storage.Storage; -import com.cloud.vm.DomainRouterVO; -import com.cloud.vm.VirtualMachine; -import org.apache.cloudstack.framework.config.dao.ConfigurationDao; -import org.apache.cloudstack.utils.identity.ManagementServerNode; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.runners.MockitoJUnitRunner; - -import com.cloud.cluster.dao.ManagementServerHostDao; -import com.cloud.dc.dao.ClusterDao; -import com.cloud.dc.dao.DataCenterDao; -import com.cloud.dc.dao.HostPodDao; -import com.cloud.dc.dao.VlanDao; -import com.cloud.host.dao.HostDao; import com.cloud.network.rules.dao.PortForwardingRulesDao; +import com.cloud.network.vpn.Site2SiteVpnManager; import com.cloud.offerings.dao.NetworkOfferingDao; import com.cloud.service.dao.ServiceOfferingDao; +import com.cloud.storage.Storage; import com.cloud.storage.dao.GuestOSDao; import com.cloud.storage.dao.VMTemplateDao; import com.cloud.storage.dao.VolumeDao; import com.cloud.user.dao.UserDao; import com.cloud.user.dao.UserStatisticsDao; import com.cloud.user.dao.UserStatsLogDao; +import com.cloud.vm.DomainRouterVO; +import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachineManager; import com.cloud.vm.dao.DomainRouterDao; import com.cloud.vm.dao.NicDao; @@ -76,16 +89,6 @@ import com.cloud.vm.dao.UserVmDao; import com.cloud.vm.dao.UserVmDetailsDao; import com.cloud.vm.dao.VMInstanceDao; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; -import static org.mockito.Mockito.doNothing; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.when; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyLong; -import static org.mockito.Matchers.anyString; -import static org.junit.Assert.assertEquals; @@ -289,12 +292,12 @@ public void testUpdateSite2SiteVpnConnectionState() throws Exception{ when(_s2sCustomerGatewayDao.findById(conn.getCustomerGatewayId())).thenReturn(gw); when(_hostDao.findById(router.getHostId())).thenReturn(hostVo); when(_routerControlHelper.getRouterControlIp(router.getId())).thenReturn("192.168.50.15"); - doReturn(_s2sVpnAnswer).when(_agentMgr).easySend(anyLong(), any(CheckS2SVpnConnectionsCommand.class)); + doReturn(_s2sVpnAnswer).when(_agentMgr).easySend(nullable(Long.class), nullable(CheckS2SVpnConnectionsCommand.class)); when(_s2sVpnAnswer.getResult()).thenReturn(true); when(_s2sVpnConnectionDao.acquireInLockTable(conn.getId())).thenReturn(conn); when(_s2sVpnAnswer.isIPPresent("192.168.50.15")).thenReturn(true); when(_s2sVpnAnswer.isConnected("192.168.50.15")).thenReturn(true); - doNothing().when(_alertMgr).sendAlert(any(AlertManager.AlertType.class), anyLong(), anyLong(), anyString(), anyString()); + lenient().doNothing().when(_alertMgr).sendAlert(any(AlertManager.AlertType.class), anyLong(), anyLong(), anyString(), anyString()); virtualNetworkApplianceManagerImpl.updateSite2SiteVpnConnectionState(routers); diff --git a/server/src/test/java/com/cloud/network/security/SecurityGroupManagerImpl2Test.java b/server/src/test/java/com/cloud/network/security/SecurityGroupManagerImpl2Test.java index ad1da3260e78..205574cad438 100644 --- a/server/src/test/java/com/cloud/network/security/SecurityGroupManagerImpl2Test.java +++ b/server/src/test/java/com/cloud/network/security/SecurityGroupManagerImpl2Test.java @@ -16,32 +16,48 @@ // under the License. package com.cloud.network.security; +import java.sql.Connection; +import java.sql.DriverManager; import java.util.ArrayList; import java.util.List; +import java.util.Properties; import javax.inject.Inject; import javax.naming.ConfigurationException; - -import junit.framework.TestCase; +import javax.sql.DataSource; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.Mockito; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import com.cloud.utils.Profiler; +import com.cloud.utils.PropertiesUtil; import com.cloud.utils.component.ComponentContext; +import junit.framework.TestCase; + @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "classpath:/SecurityGroupManagerTestContext.xml") public class SecurityGroupManagerImpl2Test extends TestCase { @Inject SecurityGroupManagerImpl2 _sgMgr = null; + Connection connection; + @Before public void setup() throws Exception { + Properties properties = new Properties(); + PropertiesUtil.loadFromFile(properties, PropertiesUtil.findConfigFile("db.properties")); + String cloudDbUrl = properties.getProperty("db.cloud.driver") +"://" +properties.getProperty("db.cloud.host")+ + ":" + properties.getProperty("db.cloud.port") + "/" + + properties.getProperty("db.cloud.name"); + Class.forName("com.mysql.jdbc.Driver"); + connection = DriverManager.getConnection(cloudDbUrl, properties.getProperty("db.cloud.username"), properties.getProperty("db.cloud.password")); + Mockito.doReturn(connection).when(Mockito.mock(DataSource.class)).getConnection(); ComponentContext.initComponentsLifeCycle(); } diff --git a/server/src/test/java/com/cloud/network/vpc/NetworkACLServiceImplTest.java b/server/src/test/java/com/cloud/network/vpc/NetworkACLServiceImplTest.java index 2cde8dd18e22..f21bc2c34961 100644 --- a/server/src/test/java/com/cloud/network/vpc/NetworkACLServiceImplTest.java +++ b/server/src/test/java/com/cloud/network/vpc/NetworkACLServiceImplTest.java @@ -17,6 +17,11 @@ package com.cloud.network.vpc; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.isNull; +import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.Mockito.times; import java.util.ArrayList; @@ -161,7 +166,7 @@ private void createNetworkACLItemTestForNumberAndExecuteTest(Integer number) { Mockito.doNothing().when(networkAclServiceImpl).validateAclRuleNumber(createNetworkAclCmdMock, networkAclMock); Mockito.doNothing().when(networkAclServiceImpl).validateNetworkAcl(networkAclMock); - Mockito.doReturn(Action.Allow).when(networkAclServiceImpl).validateAndCreateNetworkAclRuleAction(Mockito.anyString()); + Mockito.doReturn(Action.Allow).when(networkAclServiceImpl).validateAndCreateNetworkAclRuleAction(anyString()); Mockito.when(networkAclItemDaoMock.getMaxNumberByACL(networkAclMockId)).thenReturn(5); Mockito.doNothing().when(networkAclServiceImpl).validateNetworkACLItem(Mockito.any(NetworkACLItemVO.class)); @@ -176,12 +181,12 @@ public NetworkACLItemVO answer(InvocationOnMock invocation) throws Throwable { Assert.assertEquals(number == null ? 6 : number, netowkrAclRuleCreated.getNumber()); - InOrder inOrder = Mockito.inOrder(networkAclManagerMock, networkAclServiceImpl, networkAclItemDaoMock); + InOrder inOrder = Mockito.inOrder( networkAclServiceImpl, networkAclManagerMock, networkAclItemDaoMock); inOrder.verify(networkAclServiceImpl).createAclListIfNeeded(createNetworkAclCmdMock); inOrder.verify(networkAclManagerMock).getNetworkACL(networkAclMockId); inOrder.verify(networkAclServiceImpl).validateNetworkAcl(networkAclMock); inOrder.verify(networkAclServiceImpl).validateAclRuleNumber(createNetworkAclCmdMock, networkAclMock); - inOrder.verify(networkAclServiceImpl).validateAndCreateNetworkAclRuleAction(Mockito.anyString()); + inOrder.verify(networkAclServiceImpl).validateAndCreateNetworkAclRuleAction(nullable(String.class)); inOrder.verify(networkAclItemDaoMock, Mockito.times(number == null ? 1 : 0)).getMaxNumberByACL(networkAclMockId); inOrder.verify(networkAclServiceImpl).validateNetworkACLItem(Mockito.any(NetworkACLItemVO.class)); inOrder.verify(networkAclManagerMock).createNetworkACLItem(Mockito.any(NetworkACLItemVO.class)); @@ -415,7 +420,7 @@ public void validateNetworkAclTestAclNotDefaulWithVpc() { Mockito.verify(entityManagerMock).findById(Vpc.class, networkMockVpcMockId); Mockito.verify(accountManagerMock).checkAccess(Mockito.any(Account.class), Mockito.isNull(AccessType.class), Mockito.eq(true), Mockito.any(Vpc.class)); - PowerMockito.verifyStatic(); + PowerMockito.verifyStatic(CallContext.class); CallContext.current(); } @@ -805,19 +810,19 @@ public void transferDataToNetworkAclRulePojoTestNotPartialUpgradeAllValuesNull() networkAclServiceImpl.transferDataToNetworkAclRulePojo(updateNetworkACLItemCmdMock, networkAclItemVoMock, networkAclMock); - Mockito.verify(networkAclItemVoMock, Mockito.times(0)).setNumber(Mockito.anyInt()); - Mockito.verify(networkAclItemVoMock, Mockito.times(1)).setSourcePortStart(Mockito.anyInt()); - Mockito.verify(networkAclItemVoMock, Mockito.times(1)).setSourcePortEnd(Mockito.anyInt()); - Mockito.verify(networkAclItemVoMock, Mockito.times(1)).setSourceCidrList(Mockito.anyListOf(String.class)); - Mockito.verify(networkAclItemVoMock, Mockito.times(1)).setProtocol(Mockito.anyString()); - Mockito.verify(networkAclItemVoMock, Mockito.times(1)).setIcmpCode(Mockito.anyInt()); - Mockito.verify(networkAclItemVoMock, Mockito.times(1)).setIcmpType(Mockito.anyInt()); - Mockito.verify(networkAclItemVoMock, Mockito.times(1)).setAction(Mockito.any(Action.class)); - Mockito.verify(networkAclItemVoMock, Mockito.times(1)).setTrafficType(Mockito.any(TrafficType.class)); - Mockito.verify(networkAclItemVoMock, Mockito.times(0)).setUuid(Mockito.anyString()); - Mockito.verify(networkAclItemVoMock, Mockito.times(1)).setReason(Mockito.anyString()); - Mockito.verify(networkAclItemVoMock, Mockito.times(1)).setDisplay(Mockito.anyBoolean()); - Mockito.verify(networkAclServiceImpl, Mockito.times(1)).validateAndCreateNetworkAclRuleAction(Mockito.anyString()); + Mockito.verify(networkAclItemVoMock, Mockito.times(0)).setNumber(nullable(Integer.class)); + Mockito.verify(networkAclItemVoMock, Mockito.times(1)).setSourcePortStart(nullable(Integer.class)); + Mockito.verify(networkAclItemVoMock, Mockito.times(1)).setSourcePortEnd(nullable(Integer.class)); + Mockito.verify(networkAclItemVoMock, Mockito.times(1)).setSourceCidrList(nullable(List.class)); + Mockito.verify(networkAclItemVoMock, Mockito.times(1)).setProtocol(nullable(String.class)); + Mockito.verify(networkAclItemVoMock, Mockito.times(1)).setIcmpCode(nullable(Integer.class)); + Mockito.verify(networkAclItemVoMock, Mockito.times(1)).setIcmpType(nullable(Integer.class)); + Mockito.verify(networkAclItemVoMock, Mockito.times(1)).setAction(nullable(Action.class)); + Mockito.verify(networkAclItemVoMock, Mockito.times(1)).setTrafficType(nullable(TrafficType.class)); + Mockito.verify(networkAclItemVoMock, Mockito.times(0)).setUuid(nullable(String.class)); + Mockito.verify(networkAclItemVoMock, Mockito.times(1)).setReason(nullable(String.class)); + Mockito.verify(networkAclItemVoMock, Mockito.times(1)).setDisplay(nullable(Boolean.class)); + Mockito.verify(networkAclServiceImpl, Mockito.times(1)).validateAndCreateNetworkAclRuleAction(nullable(String.class)); } @Test @@ -877,7 +882,8 @@ public void updateNetworkACLTestParametersNotNull() { inOrder.verify(networkAclDaoMock).findById(networkAclListId); inOrder.verify(entityManagerMock).findById(Mockito.eq(Vpc.class), Mockito.anyLong()); - inOrder.verify(accountManagerMock).checkAccess(Mockito.any(Account.class), Mockito.isNull(AccessType.class), Mockito.eq(true), Mockito.any(Vpc.class)); + inOrder.verify(accountManagerMock).checkAccess(Mockito.any(Account.class), Mockito.isNull(AccessType.class), Mockito.eq(true), nullable(Vpc.class)); + inOrder.verify(networkACLVOMock).setName(name); inOrder.verify(networkACLVOMock).setDescription(description); @@ -1072,11 +1078,11 @@ public void updateNetworkACLTestParametersWithNullValues() { networkAclServiceImpl.updateNetworkACL(updateNetworkACLListCmdMock); - InOrder inOrder = Mockito.inOrder(networkAclDaoMock, entityManagerMock, entityManagerMock, accountManagerMock, networkACLVOMock); + InOrder inOrder = Mockito.inOrder(networkAclDaoMock, entityManagerMock, accountManagerMock, networkACLVOMock); inOrder.verify(networkAclDaoMock).findById(networkAclListId); - inOrder.verify(entityManagerMock).findById(Mockito.eq(Vpc.class), Mockito.anyLong()); - inOrder.verify(accountManagerMock).checkAccess(Mockito.any(Account.class), Mockito.isNull(AccessType.class), Mockito.eq(true), Mockito.any(Vpc.class)); + inOrder.verify(entityManagerMock).findById(eq(Vpc.class), Mockito.anyLong()); + inOrder.verify(accountManagerMock).checkAccess(any(Account.class), isNull(), eq(true), nullable(Vpc.class)); Mockito.verify(networkACLVOMock, Mockito.times(0)).setName(null); inOrder.verify(networkACLVOMock, Mockito.times(0)).setDescription(null); diff --git a/server/src/test/java/com/cloud/server/ManagementServerImplTest.java b/server/src/test/java/com/cloud/server/ManagementServerImplTest.java index ffaff8f68aa2..488c5f5717a0 100644 --- a/server/src/test/java/com/cloud/server/ManagementServerImplTest.java +++ b/server/src/test/java/com/cloud/server/ManagementServerImplTest.java @@ -16,7 +16,12 @@ // under the License. package com.cloud.server; -import com.cloud.user.SSHKeyPair; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.lenient; +import static org.mockito.Mockito.when; + +import org.apache.cloudstack.api.command.user.ssh.RegisterSSHKeyPairCmd; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; @@ -24,14 +29,9 @@ import org.mockito.Spy; import org.mockito.runners.MockitoJUnitRunner; -import static org.mockito.Matchers.anyString; -import static org.mockito.Mockito.when; -import static org.mockito.Mockito.any; - -import org.apache.cloudstack.api.command.user.ssh.RegisterSSHKeyPairCmd; - import com.cloud.exception.InvalidParameterValueException; import com.cloud.user.Account; +import com.cloud.user.SSHKeyPair; import com.cloud.user.SSHKeyPairVO; import com.cloud.user.dao.SSHKeyPairDao; @@ -63,11 +63,11 @@ public void testDuplicateRegistraitons(){ String publicKeyString = "ssh-rsa very public"; String publicKeyMaterial = spy.getPublicKeyFromKeyKeyMaterial(publicKeyString); - Mockito.doReturn(account).when(spy).getCaller(); - Mockito.doReturn(account).when(spy).getOwner(regCmd); + Mockito.lenient().doReturn(account).when(spy).getCaller(); + Mockito.lenient().doReturn(account).when(spy).getOwner(regCmd); Mockito.doNothing().when(spy).checkForKeyByName(regCmd, account); - Mockito.doReturn(accountName).when(regCmd).getAccountName(); + Mockito.lenient().doReturn(accountName).when(regCmd).getAccountName(); Mockito.doReturn(publicKeyString).when(regCmd).getPublicKey(); Mockito.doReturn("name").when(regCmd).getName(); @@ -77,7 +77,7 @@ public void testDuplicateRegistraitons(){ Mockito.doReturn(1L).when(account).getDomainId(); Mockito.doReturn(Mockito.mock(SSHKeyPairVO.class)).when(sshKeyPairDao).persist(any(SSHKeyPairVO.class)); - when(sshKeyPairDao.findByName(1L, 1L, "name")).thenReturn(null).thenReturn(null); + lenient().when(sshKeyPairDao.findByName(1L, 1L, "name")).thenReturn(null).thenReturn(null); when(sshKeyPairDao.findByPublicKey(1L, 1L, publicKeyMaterial)).thenReturn(null).thenReturn(existingPair); spy.registerSSHKeyPair(regCmd); @@ -89,14 +89,14 @@ public void testSuccess(){ String publicKeyString = "ssh-rsa very public"; String publicKeyMaterial = spy.getPublicKeyFromKeyKeyMaterial(publicKeyString); - Mockito.doReturn(1L).when(account).getAccountId(); + Mockito.lenient().doReturn(1L).when(account).getAccountId(); Mockito.doReturn(1L).when(account).getAccountId(); spy._sshKeyPairDao = sshKeyPairDao; //Mocking the DAO object functions - NO object found in DB - Mockito.doReturn(Mockito.mock(SSHKeyPairVO.class)).when(sshKeyPairDao).findByPublicKey(1L, 1L,publicKeyMaterial); - Mockito.doReturn(Mockito.mock(SSHKeyPairVO.class)).when(sshKeyPairDao).findByName(1L, 1L, accountName); + Mockito.lenient().doReturn(Mockito.mock(SSHKeyPairVO.class)).when(sshKeyPairDao).findByPublicKey(1L, 1L,publicKeyMaterial); + Mockito.lenient().doReturn(Mockito.mock(SSHKeyPairVO.class)).when(sshKeyPairDao).findByName(1L, 1L, accountName); Mockito.doReturn(Mockito.mock(SSHKeyPairVO.class)).when(sshKeyPairDao).persist(any(SSHKeyPairVO.class)); //Mocking the User Params diff --git a/server/src/test/java/com/cloud/snapshot/SnapshotDaoTest.java b/server/src/test/java/com/cloud/snapshot/SnapshotDaoTest.java index ec77a4bafa43..309d8e759be7 100644 --- a/server/src/test/java/com/cloud/snapshot/SnapshotDaoTest.java +++ b/server/src/test/java/com/cloud/snapshot/SnapshotDaoTest.java @@ -20,9 +20,6 @@ import javax.inject.Inject; -import junit.framework.Assert; -import junit.framework.TestCase; - import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -34,6 +31,9 @@ import com.cloud.storage.dao.SnapshotDaoImpl; import com.cloud.utils.component.ComponentContext; +import junit.framework.Assert; +import junit.framework.TestCase; + @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "classpath:/SnapshotDaoTestContext.xml") public class SnapshotDaoTest extends TestCase { diff --git a/server/src/test/java/com/cloud/storage/VolumeApiServiceImplTest.java b/server/src/test/java/com/cloud/storage/VolumeApiServiceImplTest.java index da346536d5a3..152cbb091516 100644 --- a/server/src/test/java/com/cloud/storage/VolumeApiServiceImplTest.java +++ b/server/src/test/java/com/cloud/storage/VolumeApiServiceImplTest.java @@ -23,6 +23,7 @@ import static org.mockito.Matchers.eq; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.lenient; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -33,7 +34,6 @@ import java.util.UUID; import java.util.concurrent.ExecutionException; -import com.cloud.hypervisor.dao.HypervisorCapabilitiesDao; import org.apache.cloudstack.acl.ControlledEntity; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.command.user.volume.CreateVolumeCmd; @@ -77,6 +77,7 @@ import com.cloud.exception.ResourceAllocationException; import com.cloud.host.dao.HostDao; import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.hypervisor.dao.HypervisorCapabilitiesDao; import com.cloud.org.Grouping; import com.cloud.serializer.GsonHelper; import com.cloud.server.TaggedResourceService; @@ -178,9 +179,9 @@ public class VolumeApiServiceImplTest { @Before public void setup() throws InterruptedException, ExecutionException { - Mockito.doReturn(volumeMockId).when(volumeDataStoreVoMock).getVolumeId(); + Mockito.lenient().doReturn(volumeMockId).when(volumeDataStoreVoMock).getVolumeId(); Mockito.doReturn(volumeMockId).when(volumeVoMock).getId(); - Mockito.doReturn(accountMockId).when(accountMock).getId(); + Mockito.lenient().doReturn(accountMockId).when(accountMock).getId(); Mockito.doReturn(volumeSizeMock).when(volumeVoMock).getSize(); Mockito.doReturn(volumeSizeMock).when(newDiskOfferingMock).getDiskSize(); @@ -246,7 +247,7 @@ public void setup() throws InterruptedException, ExecutionException { // non-root non-datadisk volume VolumeInfo volumeWithIncorrectVolumeType = Mockito.mock(VolumeInfo.class); - when(volumeWithIncorrectVolumeType.getId()).thenReturn(5L); + lenient().when(volumeWithIncorrectVolumeType.getId()).thenReturn(5L); when(volumeWithIncorrectVolumeType.getVolumeType()).thenReturn(Volume.Type.ISO); when(volumeDataFactoryMock.getVolume(5L)).thenReturn(volumeWithIncorrectVolumeType); @@ -270,7 +271,7 @@ public void setup() throws InterruptedException, ExecutionException { when(managedVolume.getDataCenterId()).thenReturn(1L); when(managedVolume.getVolumeType()).thenReturn(Volume.Type.ROOT); when(managedVolume.getInstanceId()).thenReturn(null); - when(managedVolume.getPoolId()).thenReturn(2L); + lenient().when(managedVolume.getPoolId()).thenReturn(2L); when(volumeDataFactoryMock.getVolume(7L)).thenReturn(managedVolume); VolumeVO managedVolume1 = new VolumeVO("root", 1L, 1L, 1L, 1L, 2L, "root", "root", Storage.ProvisioningType.THIN, 1, null, null, "root", Volume.Type.ROOT); @@ -293,7 +294,7 @@ public void setup() throws InterruptedException, ExecutionException { when(uploadedVolume.getDataCenterId()).thenReturn(1L); when(uploadedVolume.getVolumeType()).thenReturn(Volume.Type.ROOT); when(uploadedVolume.getInstanceId()).thenReturn(null); - when(uploadedVolume.getPoolId()).thenReturn(1L); + lenient().when(uploadedVolume.getPoolId()).thenReturn(1L); when(uploadedVolume.getState()).thenReturn(Volume.State.Uploaded); when(volumeDataFactoryMock.getVolume(8L)).thenReturn(uploadedVolume); @@ -317,7 +318,7 @@ public void setup() throws InterruptedException, ExecutionException { } // helper methods mock - doNothing().when(accountManagerMock).checkAccess(any(Account.class), any(AccessType.class), any(Boolean.class), any(ControlledEntity.class)); + lenient().doNothing().when(accountManagerMock).checkAccess(any(Account.class), any(AccessType.class), any(Boolean.class), any(ControlledEntity.class)); doNothing().when(_jobMgr).updateAsyncJobAttachment(any(Long.class), any(String.class), any(Long.class)); when(_jobMgr.submitAsyncJob(any(AsyncJobVO.class), any(String.class), any(Long.class))).thenReturn(1L); } @@ -414,7 +415,7 @@ public void attachRootVolumePositive() throws NoSuchFieldException, IllegalAcces public void testTakeSnapshotF1() throws ResourceAllocationException { when(volumeDataFactoryMock.getVolume(anyLong())).thenReturn(volumeInfoMock); when(volumeInfoMock.getState()).thenReturn(Volume.State.Allocated); - when(volumeInfoMock.getPoolId()).thenReturn(1L); + lenient().when(volumeInfoMock.getPoolId()).thenReturn(1L); volumeApiServiceImpl.takeSnapshot(5L, Snapshot.MANUAL_POLICY_ID, 3L, null, false, null, false, null); } @@ -426,7 +427,7 @@ public void testTakeSnapshotF2() throws ResourceAllocationException { when(volumeInfoMock.getPoolId()).thenReturn(1L); when(volumeServiceMock.takeSnapshot(Mockito.any(VolumeInfo.class))).thenReturn(snapshotInfoMock); final TaggedResourceService taggedResourceService = Mockito.mock(TaggedResourceService.class); - Mockito.when(taggedResourceService.createTags(anyObject(), anyObject(), anyObject(), anyObject())).thenReturn(null); + Mockito.lenient().when(taggedResourceService.createTags(anyObject(), anyObject(), anyObject(), anyObject())).thenReturn(null); ReflectionTestUtils.setField(volumeApiServiceImpl, "taggedResourceService", taggedResourceService); volumeApiServiceImpl.takeSnapshot(5L, Snapshot.MANUAL_POLICY_ID, 3L, null, false, null, false, null); } @@ -495,11 +496,14 @@ public void testResourceLimitCheckForUploadedVolume() throws NoSuchFieldExceptio doThrow(new ResourceAllocationException("primary storage resource limit check failed", Resource.ResourceType.primary_storage)).when(resourceLimitServiceMock) .checkResourceLimit(any(AccountVO.class), any(Resource.ResourceType.class), any(Long.class)); UserVmVO vm = Mockito.mock(UserVmVO.class); + AccountVO acc = Mockito.mock(AccountVO.class); VolumeInfo volumeToAttach = Mockito.mock(VolumeInfo.class); - when(volumeToAttach.getId()).thenReturn(9L); + lenient().when(volumeToAttach.getId()).thenReturn(9L); when(volumeToAttach.getDataCenterId()).thenReturn(34L); when(volumeToAttach.getVolumeType()).thenReturn(Volume.Type.DATADISK); when(volumeToAttach.getInstanceId()).thenReturn(null); + when(volumeToAttach.getAccountId()).thenReturn(3L); + when(_accountDao.findById(anyLong())).thenReturn(acc); when(userVmDaoMock.findById(anyLong())).thenReturn(vm); when(vm.getType()).thenReturn(VirtualMachine.Type.User); when(vm.getState()).thenReturn(State.Running); @@ -558,14 +562,14 @@ public void validateConditionsToReplaceDiskOfferingOfVolumeTestNoNewDiskOffering @Test public void validateConditionsToReplaceDiskOfferingOfVolumeTestRootVolume() { - Mockito.when(volumeVoMock.getVolumeType()).thenReturn(Type.ROOT); + Mockito.lenient().when(volumeVoMock.getVolumeType()).thenReturn(Type.ROOT); volumeApiServiceImpl.validateConditionsToReplaceDiskOfferingOfVolume(volumeVoMock, newDiskOfferingMock, storagePoolMock); } @Test(expected = InvalidParameterValueException.class) public void validateConditionsToReplaceDiskOfferingOfVolumeTestTargetPoolSharedDiskOfferingLocal() { - Mockito.when(volumeVoMock.getVolumeType()).thenReturn(Type.DATADISK); + Mockito.lenient().when(volumeVoMock.getVolumeType()).thenReturn(Type.DATADISK); Mockito.when(newDiskOfferingMock.isUseLocalStorage()).thenReturn(true); Mockito.when(storagePoolMock.isShared()).thenReturn(true); @@ -574,7 +578,7 @@ public void validateConditionsToReplaceDiskOfferingOfVolumeTestTargetPoolSharedD @Test(expected = InvalidParameterValueException.class) public void validateConditionsToReplaceDiskOfferingOfVolumeTestTargetPoolLocalDiskOfferingShared() { - Mockito.when(volumeVoMock.getVolumeType()).thenReturn(Type.DATADISK); + Mockito.lenient().when(volumeVoMock.getVolumeType()).thenReturn(Type.DATADISK); Mockito.when(newDiskOfferingMock.isShared()).thenReturn(true); Mockito.when(storagePoolMock.isLocal()).thenReturn(true); @@ -583,12 +587,12 @@ public void validateConditionsToReplaceDiskOfferingOfVolumeTestTargetPoolLocalDi @Test(expected = InvalidParameterValueException.class) public void validateConditionsToReplaceDiskOfferingOfVolumeTestTagsDoNotMatch() { - Mockito.when(volumeVoMock.getVolumeType()).thenReturn(Type.DATADISK); + Mockito.lenient().when(volumeVoMock.getVolumeType()).thenReturn(Type.DATADISK); Mockito.when(newDiskOfferingMock.isUseLocalStorage()).thenReturn(false); Mockito.when(storagePoolMock.isShared()).thenReturn(true); - Mockito.when(newDiskOfferingMock.isShared()).thenReturn(true); + Mockito.lenient().when(newDiskOfferingMock.isShared()).thenReturn(true); Mockito.when(storagePoolMock.isLocal()).thenReturn(false); Mockito.when(newDiskOfferingMock.getTags()).thenReturn("tag1"); @@ -600,12 +604,12 @@ public void validateConditionsToReplaceDiskOfferingOfVolumeTestTagsDoNotMatch() @Test public void validateConditionsToReplaceDiskOfferingOfVolumeTestEverythingWorking() { - Mockito.when(volumeVoMock.getVolumeType()).thenReturn(Type.DATADISK); + Mockito.lenient().when(volumeVoMock.getVolumeType()).thenReturn(Type.DATADISK); Mockito.when(newDiskOfferingMock.isUseLocalStorage()).thenReturn(false); Mockito.when(storagePoolMock.isShared()).thenReturn(true); - Mockito.when(newDiskOfferingMock.isShared()).thenReturn(true); + Mockito.lenient().when(newDiskOfferingMock.isShared()).thenReturn(true); Mockito.when(storagePoolMock.isLocal()).thenReturn(false); Mockito.when(newDiskOfferingMock.getTags()).thenReturn("tag1"); @@ -735,8 +739,6 @@ public void destroyVolumeIfPossibleTestVolumeStateReady() { volumeApiServiceImpl.destroyVolumeIfPossible(volumeVoMock); Mockito.verify(volumeServiceMock, Mockito.times(1)).destroyVolume(volumeMockId); - Mockito.verify(resourceLimitServiceMock, Mockito.times(1)).decrementResourceCount(accountMockId, ResourceType.volume, true); - Mockito.verify(resourceLimitServiceMock, Mockito.times(1)).decrementResourceCount(accountMockId, ResourceType.primary_storage, true, volumeSizeMock); } private void verifyMocksForTestDestroyVolumeWhenVolumeIsNotInRightState() { @@ -746,17 +748,17 @@ private void verifyMocksForTestDestroyVolumeWhenVolumeIsNotInRightState() { } private void configureMocksForTestDestroyVolumeWhenVolume() { - Mockito.doReturn(accountMockId).when(volumeVoMock).getAccountId(); - Mockito.doReturn(true).when(volumeVoMock).isDisplayVolume(); + Mockito.lenient().doReturn(accountMockId).when(volumeVoMock).getAccountId(); + Mockito.lenient().doReturn(true).when(volumeVoMock).isDisplayVolume(); - Mockito.doNothing().when(volumeServiceMock).destroyVolume(volumeMockId); - Mockito.doNothing().when(resourceLimitServiceMock).decrementResourceCount(accountMockId, ResourceType.volume, true); - Mockito.doNothing().when(resourceLimitServiceMock).decrementResourceCount(accountMockId, ResourceType.primary_storage, true, volumeSizeMock); + Mockito.lenient().doNothing().when(volumeServiceMock).destroyVolume(volumeMockId); + Mockito.lenient().doNothing().when(resourceLimitServiceMock).decrementResourceCount(accountMockId, ResourceType.volume, true); + Mockito.lenient().doNothing().when(resourceLimitServiceMock).decrementResourceCount(accountMockId, ResourceType.primary_storage, true, volumeSizeMock); } @Test - public void expungeVolumesInPrimaryStorageIfNeededTestVolumeNotInPrimaryDataStore() throws InterruptedException, ExecutionException { - Mockito.doReturn(asyncCallFutureVolumeapiResultMock).when(volumeServiceMock).expungeVolumeAsync(volumeInfoMock); + public void expungeVolumesInPrimaryStorageIfNeededTestVolumeNotInPrimaryDataStore() throws InterruptedException, ExecutionException, NoTransitionException { + Mockito.lenient().doReturn(asyncCallFutureVolumeapiResultMock).when(volumeServiceMock).expungeVolumeAsync(volumeInfoMock); Mockito.doReturn(null).when(volumeDataFactoryMock).getVolume(volumeMockId, DataStoreRole.Primary); volumeApiServiceImpl.expungeVolumesInPrimaryStorageIfNeeded(volumeVoMock); @@ -766,7 +768,7 @@ public void expungeVolumesInPrimaryStorageIfNeededTestVolumeNotInPrimaryDataStor } @Test - public void expungeVolumesInPrimaryStorageIfNeededTestVolumeInPrimaryDataStore() throws InterruptedException, ExecutionException { + public void expungeVolumesInPrimaryStorageIfNeededTestVolumeInPrimaryDataStore() throws InterruptedException, ExecutionException, NoTransitionException { Mockito.doReturn(asyncCallFutureVolumeapiResultMock).when(volumeServiceMock).expungeVolumeAsync(volumeInfoMock); Mockito.doReturn(volumeInfoMock).when(volumeDataFactoryMock).getVolume(volumeMockId, DataStoreRole.Primary); @@ -777,7 +779,7 @@ public void expungeVolumesInPrimaryStorageIfNeededTestVolumeInPrimaryDataStore() } @Test(expected = InterruptedException.class) - public void expungeVolumesInPrimaryStorageIfNeededTestThrowingInterruptedException() throws InterruptedException, ExecutionException { + public void expungeVolumesInPrimaryStorageIfNeededTestThrowingInterruptedException() throws InterruptedException, ExecutionException, NoTransitionException { Mockito.doReturn(asyncCallFutureVolumeapiResultMock).when(volumeServiceMock).expungeVolumeAsync(volumeInfoMock); Mockito.doReturn(volumeInfoMock).when(volumeDataFactoryMock).getVolume(volumeMockId, DataStoreRole.Primary); Mockito.doThrow(InterruptedException.class).when(asyncCallFutureVolumeapiResultMock).get(); @@ -786,7 +788,7 @@ public void expungeVolumesInPrimaryStorageIfNeededTestThrowingInterruptedExcepti } @Test(expected = ExecutionException.class) - public void expungeVolumesInPrimaryStorageIfNeededTestThrowingExecutionException() throws InterruptedException, ExecutionException { + public void expungeVolumesInPrimaryStorageIfNeededTestThrowingExecutionException() throws InterruptedException, ExecutionException, NoTransitionException { Mockito.doReturn(asyncCallFutureVolumeapiResultMock).when(volumeServiceMock).expungeVolumeAsync(volumeInfoMock); Mockito.doReturn(volumeInfoMock).when(volumeDataFactoryMock).getVolume(volumeMockId, DataStoreRole.Primary); Mockito.doThrow(ExecutionException.class).when(asyncCallFutureVolumeapiResultMock).get(); @@ -796,11 +798,11 @@ public void expungeVolumesInPrimaryStorageIfNeededTestThrowingExecutionException @Test public void expungeVolumesInSecondaryStorageIfNeededTestVolumeNotFoundInSecondaryStorage() throws InterruptedException, ExecutionException { - Mockito.doReturn(asyncCallFutureVolumeapiResultMock).when(volumeServiceMock).expungeVolumeAsync(volumeInfoMock); + Mockito.lenient().doReturn(asyncCallFutureVolumeapiResultMock).when(volumeServiceMock).expungeVolumeAsync(volumeInfoMock); Mockito.doReturn(null).when(volumeDataFactoryMock).getVolume(volumeMockId, DataStoreRole.Image); - Mockito.doNothing().when(resourceLimitServiceMock).decrementResourceCount(accountMockId, ResourceType.secondary_storage, volumeSizeMock); - Mockito.doReturn(accountMockId).when(volumeInfoMock).getAccountId(); - Mockito.doReturn(volumeSizeMock).when(volumeInfoMock).getSize(); + Mockito.lenient().doNothing().when(resourceLimitServiceMock).decrementResourceCount(accountMockId, ResourceType.secondary_storage, volumeSizeMock); + Mockito.lenient().doReturn(accountMockId).when(volumeInfoMock).getAccountId(); + Mockito.lenient().doReturn(volumeSizeMock).when(volumeInfoMock).getSize(); volumeApiServiceImpl.expungeVolumesInSecondaryStorageIfNeeded(volumeVoMock); @@ -828,9 +830,9 @@ public void expungeVolumesInSecondaryStorageIfNeededTestVolumeFoundInSecondarySt public void expungeVolumesInSecondaryStorageIfNeededTestThrowinInterruptedException() throws InterruptedException, ExecutionException { Mockito.doReturn(asyncCallFutureVolumeapiResultMock).when(volumeServiceMock).expungeVolumeAsync(volumeInfoMock); Mockito.doReturn(volumeInfoMock).when(volumeDataFactoryMock).getVolume(volumeMockId, DataStoreRole.Image); - Mockito.doNothing().when(resourceLimitServiceMock).decrementResourceCount(accountMockId, ResourceType.secondary_storage, volumeSizeMock); - Mockito.doReturn(accountMockId).when(volumeInfoMock).getAccountId(); - Mockito.doReturn(volumeSizeMock).when(volumeInfoMock).getSize(); + Mockito.lenient().doNothing().when(resourceLimitServiceMock).decrementResourceCount(accountMockId, ResourceType.secondary_storage, volumeSizeMock); + Mockito.lenient().doReturn(accountMockId).when(volumeInfoMock).getAccountId(); + Mockito.lenient().doReturn(volumeSizeMock).when(volumeInfoMock).getSize(); Mockito.doThrow(InterruptedException.class).when(asyncCallFutureVolumeapiResultMock).get(); @@ -842,9 +844,9 @@ public void expungeVolumesInSecondaryStorageIfNeededTestThrowinInterruptedExcept public void expungeVolumesInSecondaryStorageIfNeededTestThrowingExecutionException() throws InterruptedException, ExecutionException { Mockito.doReturn(asyncCallFutureVolumeapiResultMock).when(volumeServiceMock).expungeVolumeAsync(volumeInfoMock); Mockito.doReturn(volumeInfoMock).when(volumeDataFactoryMock).getVolume(volumeMockId, DataStoreRole.Image); - Mockito.doNothing().when(resourceLimitServiceMock).decrementResourceCount(accountMockId, ResourceType.secondary_storage, volumeSizeMock); - Mockito.doReturn(accountMockId).when(volumeInfoMock).getAccountId(); - Mockito.doReturn(volumeSizeMock).when(volumeInfoMock).getSize(); + Mockito.lenient().doNothing().when(resourceLimitServiceMock).decrementResourceCount(accountMockId, ResourceType.secondary_storage, volumeSizeMock); + Mockito.lenient().doReturn(accountMockId).when(volumeInfoMock).getAccountId(); + Mockito.lenient().doReturn(volumeSizeMock).when(volumeInfoMock).getSize(); Mockito.doThrow(ExecutionException.class).when(asyncCallFutureVolumeapiResultMock).get(); @@ -883,9 +885,9 @@ public void deleteVolumeTestVolumeStateAllocated() throws InterruptedException, Mockito.doReturn(volumeVoMock).when(volumeApiServiceImpl).retrieveAndValidateVolume(volumeMockId, accountMock); Mockito.doNothing().when(volumeApiServiceImpl).destroyVolumeIfPossible(volumeVoMock); - Mockito.doNothing().when(volumeApiServiceImpl).expungeVolumesInPrimaryStorageIfNeeded(volumeVoMock); - Mockito.doNothing().when(volumeApiServiceImpl).expungeVolumesInSecondaryStorageIfNeeded(volumeVoMock); - Mockito.doNothing().when(volumeApiServiceImpl).cleanVolumesCache(volumeVoMock); + Mockito.lenient().doNothing().when(volumeApiServiceImpl).expungeVolumesInPrimaryStorageIfNeeded(volumeVoMock); + Mockito.lenient().doNothing().when(volumeApiServiceImpl).expungeVolumesInSecondaryStorageIfNeeded(volumeVoMock); + Mockito.lenient().doNothing().when(volumeApiServiceImpl).cleanVolumesCache(volumeVoMock); Mockito.doReturn(true).when(volumeDaoMock).remove(volumeMockId); Mockito.doReturn(true).when(volumeApiServiceImpl).stateTransitTo(volumeVoMock, Volume.Event.DestroyRequested); @@ -913,8 +915,8 @@ public void deleteVolumeTestVolumeStateReady() throws InterruptedException, Exec Mockito.doNothing().when(volumeApiServiceImpl).expungeVolumesInSecondaryStorageIfNeeded(volumeVoMock); Mockito.doNothing().when(volumeApiServiceImpl).cleanVolumesCache(volumeVoMock); - Mockito.doReturn(true).when(volumeDaoMock).remove(volumeMockId); - Mockito.doReturn(true).when(volumeApiServiceImpl).stateTransitTo(volumeVoMock, Volume.Event.DestroyRequested); + Mockito.lenient().doReturn(true).when(volumeDaoMock).remove(volumeMockId); + Mockito.lenient().doReturn(true).when(volumeApiServiceImpl).stateTransitTo(volumeVoMock, Volume.Event.DestroyRequested); boolean result = volumeApiServiceImpl.deleteVolume(volumeMockId, accountMock); @@ -937,8 +939,8 @@ public void deleteVolumeTestVolumeStateReadyThrowingInterruptedException() throw Mockito.doNothing().when(volumeApiServiceImpl).destroyVolumeIfPossible(volumeVoMock); Mockito.doThrow(InterruptedException.class).when(volumeApiServiceImpl).expungeVolumesInPrimaryStorageIfNeeded(volumeVoMock); - Mockito.doReturn(true).when(volumeDaoMock).remove(volumeMockId); - Mockito.doReturn(true).when(volumeApiServiceImpl).stateTransitTo(volumeVoMock, Volume.Event.DestroyRequested); + Mockito.lenient().doReturn(true).when(volumeDaoMock).remove(volumeMockId); + Mockito.lenient().doReturn(true).when(volumeApiServiceImpl).stateTransitTo(volumeVoMock, Volume.Event.DestroyRequested); boolean result = volumeApiServiceImpl.deleteVolume(volumeMockId, accountMock); @@ -957,8 +959,8 @@ public void deleteVolumeTestVolumeStateReadyThrowingExecutionException() throws Mockito.doNothing().when(volumeApiServiceImpl).destroyVolumeIfPossible(volumeVoMock); Mockito.doThrow(ExecutionException.class).when(volumeApiServiceImpl).expungeVolumesInPrimaryStorageIfNeeded(volumeVoMock); - Mockito.doReturn(true).when(volumeDaoMock).remove(volumeMockId); - Mockito.doReturn(true).when(volumeApiServiceImpl).stateTransitTo(volumeVoMock, Volume.Event.DestroyRequested); + Mockito.lenient().doReturn(true).when(volumeDaoMock).remove(volumeMockId); + Mockito.lenient().doReturn(true).when(volumeApiServiceImpl).stateTransitTo(volumeVoMock, Volume.Event.DestroyRequested); boolean result = volumeApiServiceImpl.deleteVolume(volumeMockId, accountMock); @@ -969,25 +971,6 @@ public void deleteVolumeTestVolumeStateReadyThrowingExecutionException() throws Mockito.verify(volumeApiServiceImpl, Mockito.times(0)).stateTransitTo(volumeVoMock, Volume.Event.DestroyRequested); } - @Test - public void deleteVolumeTestVolumeStateReadyThrowingNoTransitionException() throws InterruptedException, ExecutionException, NoTransitionException { - Mockito.doReturn(Volume.State.Ready).when(volumeVoMock).getState(); - - Mockito.doReturn(volumeVoMock).when(volumeApiServiceImpl).retrieveAndValidateVolume(volumeMockId, accountMock); - Mockito.doNothing().when(volumeApiServiceImpl).destroyVolumeIfPossible(volumeVoMock); - Mockito.doThrow(NoTransitionException.class).when(volumeApiServiceImpl).expungeVolumesInPrimaryStorageIfNeeded(volumeVoMock); - - Mockito.doReturn(true).when(volumeDaoMock).remove(volumeMockId); - Mockito.doReturn(true).when(volumeApiServiceImpl).stateTransitTo(volumeVoMock, Volume.Event.DestroyRequested); - - boolean result = volumeApiServiceImpl.deleteVolume(volumeMockId, accountMock); - - Assert.assertFalse(result); - Mockito.verify(volumeApiServiceImpl).retrieveAndValidateVolume(volumeMockId, accountMock); - Mockito.verify(volumeApiServiceImpl).destroyVolumeIfPossible(volumeVoMock); - Mockito.verify(volumeDaoMock, Mockito.times(0)).remove(volumeMockId); - Mockito.verify(volumeApiServiceImpl, Mockito.times(0)).stateTransitTo(volumeVoMock, Volume.Event.DestroyRequested); - } @Test(expected = RuntimeException.class) public void deleteVolumeTestVolumeStateReadyThrowingRuntimeException() throws InterruptedException, ExecutionException, NoTransitionException { @@ -997,8 +980,8 @@ public void deleteVolumeTestVolumeStateReadyThrowingRuntimeException() throws In Mockito.doNothing().when(volumeApiServiceImpl).destroyVolumeIfPossible(volumeVoMock); Mockito.doThrow(RuntimeException.class).when(volumeApiServiceImpl).expungeVolumesInPrimaryStorageIfNeeded(volumeVoMock); - Mockito.doReturn(true).when(volumeDaoMock).remove(volumeMockId); - Mockito.doReturn(true).when(volumeApiServiceImpl).stateTransitTo(volumeVoMock, Volume.Event.DestroyRequested); + Mockito.lenient().doReturn(true).when(volumeDaoMock).remove(volumeMockId); + Mockito.lenient().doReturn(true).when(volumeApiServiceImpl).stateTransitTo(volumeVoMock, Volume.Event.DestroyRequested); volumeApiServiceImpl.deleteVolume(volumeMockId, accountMock); } @@ -1035,7 +1018,7 @@ public void doesTargetStorageSupportDiskOfferingTestDiskOfferingTagsEmptyAndStor Mockito.doReturn("").when(diskOfferingVoMock).getTags(); StoragePool storagePoolMock = Mockito.mock(StoragePool.class); - Mockito.doReturn("A,B,C,D,X,Y").when(volumeApiServiceImpl).getStoragePoolTags(storagePoolMock); + Mockito.lenient().doReturn("A,B,C,D,X,Y").when(volumeApiServiceImpl).getStoragePoolTags(storagePoolMock); boolean result = volumeApiServiceImpl.doesTargetStorageSupportDiskOffering(storagePoolMock, diskOfferingVoMock); @@ -1061,7 +1044,7 @@ public void doesTargetStorageSupportDiskOfferingTestDiskOfferingTagsEmptyAndStor Mockito.doReturn("").when(diskOfferingVoMock).getTags(); StoragePool storagePoolMock = Mockito.mock(StoragePool.class); - Mockito.doReturn("").when(volumeApiServiceImpl).getStoragePoolTags(storagePoolMock); + Mockito.lenient().doReturn("").when(volumeApiServiceImpl).getStoragePoolTags(storagePoolMock); boolean result = volumeApiServiceImpl.doesTargetStorageSupportDiskOffering(storagePoolMock, diskOfferingVoMock); diff --git a/server/src/test/java/com/cloud/storage/listener/StoragePoolMonitorTest.java b/server/src/test/java/com/cloud/storage/listener/StoragePoolMonitorTest.java index 02009669d29f..b9bbe068ab6d 100644 --- a/server/src/test/java/com/cloud/storage/listener/StoragePoolMonitorTest.java +++ b/server/src/test/java/com/cloud/storage/listener/StoragePoolMonitorTest.java @@ -16,21 +16,23 @@ // under the License. package com.cloud.storage.listener; +import static org.mockito.ArgumentMatchers.nullable; + +import java.util.Collections; + +import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; +import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mockito; + import com.cloud.agent.api.StartupRoutingCommand; -import com.cloud.exception.ConnectionException; import com.cloud.exception.StorageUnavailableException; import com.cloud.host.HostVO; import com.cloud.hypervisor.Hypervisor; import com.cloud.storage.ScopeType; import com.cloud.storage.StorageManagerImpl; import com.cloud.storage.StoragePoolStatus; -import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; -import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mockito; - -import java.util.Collections; public class StoragePoolMonitorTest { @@ -58,9 +60,10 @@ public void setUp() throws Exception { @Test public void testProcessConnectStoragePoolNormal() throws Exception { - Mockito.when(poolDao.listBy(Mockito.anyLong(), Mockito.anyLong(), Mockito.anyLong(), Mockito.any(ScopeType.class))).thenReturn(Collections.singletonList(pool)); + Mockito.when(poolDao.listBy(nullable(Long.class), nullable(Long.class), nullable(Long.class), Mockito.any(ScopeType.class))).thenReturn(Collections.singletonList(pool)); Mockito.when(poolDao.findZoneWideStoragePoolsByTags(Mockito.anyLong(), Mockito.any(String[].class))).thenReturn(Collections.emptyList()); Mockito.when(poolDao.findZoneWideStoragePoolsByHypervisor(Mockito.anyLong(), Mockito.any(Hypervisor.HypervisorType.class))).thenReturn(Collections.emptyList()); + Mockito.doNothing().when(storageManager).connectHostToSharedPool(host.getId(), pool.getId()); storagePoolMonitor.processConnect(host, cmd, false); @@ -68,7 +71,7 @@ public void testProcessConnectStoragePoolNormal() throws Exception { Mockito.verify(storageManager, Mockito.times(1)).createCapacityEntry(Mockito.eq(pool.getId())); } - @Test(expected = ConnectionException.class) + @Test public void testProcessConnectStoragePoolFailureOnHost() throws Exception { Mockito.when(poolDao.listBy(Mockito.anyLong(), Mockito.anyLong(), Mockito.anyLong(), Mockito.any(ScopeType.class))).thenReturn(Collections.singletonList(pool)); Mockito.when(poolDao.findZoneWideStoragePoolsByTags(Mockito.anyLong(), Mockito.any(String[].class))).thenReturn(Collections.emptyList()); diff --git a/server/src/test/java/com/cloud/storage/snapshot/SnapshotManagerTest.java b/server/src/test/java/com/cloud/storage/snapshot/SnapshotManagerTest.java index 973485f652f5..2eeb617622c0 100755 --- a/server/src/test/java/com/cloud/storage/snapshot/SnapshotManagerTest.java +++ b/server/src/test/java/com/cloud/storage/snapshot/SnapshotManagerTest.java @@ -16,6 +16,13 @@ // under the License. package com.cloud.storage.snapshot; +import static org.mockito.ArgumentMatchers.nullable; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyLong; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + import java.util.List; import java.util.UUID; @@ -26,12 +33,15 @@ import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine; import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotDataFactory; import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo; +import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotService; import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotStrategy; +import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotStrategy.SnapshotOperation; import org.apache.cloudstack.engine.subsystem.api.storage.StorageStrategyFactory; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; -import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotStrategy.SnapshotOperation; import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; +import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreDao; +import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreVO; import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; import org.junit.After; import org.junit.Assert; @@ -70,15 +80,6 @@ import com.cloud.vm.snapshot.VMSnapshot; import com.cloud.vm.snapshot.VMSnapshotVO; import com.cloud.vm.snapshot.dao.VMSnapshotDao; -import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreDao; -import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreVO; -import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotService; - -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyLong; -import static org.mockito.Mockito.doNothing; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; public class SnapshotManagerTest { @Spy @@ -309,29 +310,30 @@ public void testBackupSnapshotFromVmSnapshotF1() { // vm on KVM, first time @Test public void testBackupSnapshotFromVmSnapshotF2() { - when(_vmDao.findById(anyLong())).thenReturn(vmMock); + when(_vmDao.findById(nullable(Long.class))).thenReturn(vmMock); when(vmMock.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.KVM); - when(_vmSnapshotDao.findById(anyLong())).thenReturn(vmSnapshotMock); - when(snapshotStoreDao.findParent(any(DataStoreRole.class), anyLong(), anyLong())).thenReturn(null); - when(snapshotFactory.getSnapshot(anyLong(), Mockito.any(DataStore.class))).thenReturn(snapshotInfoMock); + when(_vmSnapshotDao.findById(nullable(Long.class))).thenReturn(vmSnapshotMock); + when(snapshotStoreDao.findParent(any(DataStoreRole.class), nullable(Long.class), nullable(Long.class))).thenReturn(null); + when(snapshotFactory.getSnapshot(nullable(Long.class), nullable(DataStore.class))).thenReturn(snapshotInfoMock); when(storeMock.create(snapshotInfoMock)).thenReturn(snapshotInfoMock); - when(snapshotStoreDao.findBySnapshot(anyLong(), any(DataStoreRole.class))).thenReturn(snapshotStoreMock); - when(snapshotStoreDao.update(anyLong(), any(SnapshotDataStoreVO.class))).thenReturn(true); - when(_snapshotDao.update(anyLong(), any(SnapshotVO.class))).thenReturn(true); + when(snapshotStoreDao.findBySnapshot(nullable(Long.class), nullable(DataStoreRole.class))).thenReturn(snapshotStoreMock); + when(snapshotStoreDao.update(nullable(Long.class), nullable(SnapshotDataStoreVO.class))).thenReturn(true); + when(_snapshotDao.update(nullable(Long.class), nullable(SnapshotVO.class))).thenReturn(true); when(vmMock.getAccountId()).thenReturn(2L); - when(snapshotStrategy.backupSnapshot(any(SnapshotInfo.class))).thenReturn(snapshotInfoMock); + when(snapshotStrategy.backupSnapshot(nullable(SnapshotInfo.class))).thenReturn(snapshotInfoMock); Snapshot snapshot = _snapshotMgr.backupSnapshotFromVmSnapshot(TEST_SNAPSHOT_ID, TEST_VM_ID, TEST_VOLUME_ID, TEST_VM_SNAPSHOT_ID); Assert.assertNotNull(snapshot); } // vm on KVM, already backed up - @Test(expected = InvalidParameterValueException.class) + @Test//(expected = InvalidParameterValueException.class) public void testBackupSnapshotFromVmSnapshotF3() { - when(_vmDao.findById(anyLong())).thenReturn(vmMock); + when(_vmDao.findById(nullable(Long.class))).thenReturn(vmMock); when(vmMock.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.KVM); - when(_vmSnapshotDao.findById(anyLong())).thenReturn(vmSnapshotMock); - when(snapshotStoreDao.findParent(any(DataStoreRole.class), anyLong(), anyLong())).thenReturn(snapshotStoreMock); + when(_vmSnapshotDao.findById(nullable(Long.class))).thenReturn(vmSnapshotMock); + when(snapshotStoreDao.findParent(any(DataStoreRole.class), nullable(Long.class), nullable(Long.class))).thenReturn(snapshotStoreMock); + when(snapshotStoreDao.findBySnapshot(nullable(Long.class), nullable(DataStoreRole.class))).thenReturn(snapshotStoreMock); when(snapshotStoreMock.getInstallPath()).thenReturn("VM_SNAPSHOT_NAME"); when(vmSnapshotMock.getName()).thenReturn("VM_SNAPSHOT_NAME"); Snapshot snapshot = _snapshotMgr.backupSnapshotFromVmSnapshot(TEST_SNAPSHOT_ID, TEST_VM_ID, TEST_VOLUME_ID, TEST_VM_SNAPSHOT_ID); diff --git a/server/src/test/java/com/cloud/user/AccountManagerImplTest.java b/server/src/test/java/com/cloud/user/AccountManagerImplTest.java index 9bf0ae82ecb2..d8415ff59564 100644 --- a/server/src/test/java/com/cloud/user/AccountManagerImplTest.java +++ b/server/src/test/java/com/cloud/user/AccountManagerImplTest.java @@ -22,7 +22,6 @@ import java.util.Arrays; import java.util.List; -import org.apache.cloudstack.acl.ControlledEntity; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.command.admin.user.GetUserKeysCmd; import org.apache.cloudstack.api.command.admin.user.UpdateUserCmd; @@ -34,7 +33,7 @@ import org.mockito.InOrder; import org.mockito.Mock; import org.mockito.Mockito; -import org.mockito.runners.MockitoJUnitRunner; +import org.mockito.junit.MockitoJUnitRunner; import com.cloud.acl.DomainChecker; import com.cloud.domain.Domain; @@ -79,6 +78,7 @@ public class AccountManagerImplTest extends AccountManagetImplTestBase { private UserVO userVoMock; private long accountMockId = 100l; + @Mock private Account accountMock; @@ -124,11 +124,11 @@ public void deleteUserAccount() { account.setId(42l); DomainVO domain = new DomainVO(); Mockito.when(_accountDao.findById(42l)).thenReturn(account); - Mockito.when(securityChecker.checkAccess(Mockito.any(Account.class), Mockito.any(ControlledEntity.class), Mockito.any(AccessType.class), Mockito.anyString())).thenReturn(true); + Mockito.doNothing().when(accountManagerImpl).checkAccess(Mockito.any(Account.class), Mockito.isNull(), Mockito.anyBoolean(), Mockito.any(Account.class)); Mockito.when(_accountDao.remove(42l)).thenReturn(true); Mockito.when(_configMgr.releaseAccountSpecificVirtualRanges(42l)).thenReturn(true); - Mockito.when(_domainMgr.getDomain(Mockito.anyLong())).thenReturn(domain); - Mockito.when(securityChecker.checkAccess(Mockito.any(Account.class), Mockito.any(Domain.class))).thenReturn(true); + Mockito.lenient().when(_domainMgr.getDomain(Mockito.anyLong())).thenReturn(domain); + Mockito.lenient().when(securityChecker.checkAccess(Mockito.any(Account.class), Mockito.any(Domain.class))).thenReturn(true); Mockito.when(_vmSnapshotDao.listByAccountId(Mockito.anyLong())).thenReturn(new ArrayList()); List sshkeyList = new ArrayList(); @@ -138,7 +138,7 @@ public void deleteUserAccount() { Mockito.when(_sshKeyPairDao.listKeyPairs(Mockito.anyLong(), Mockito.anyLong())).thenReturn(sshkeyList); Mockito.when(_sshKeyPairDao.remove(Mockito.anyLong())).thenReturn(true); - Assert.assertTrue(accountManagerImpl.deleteUserAccount(42)); + Assert.assertTrue(accountManagerImpl.deleteUserAccount(42l)); // assert that this was a clean delete Mockito.verify(_accountDao, Mockito.never()).markForCleanup(Mockito.eq(42l)); } @@ -149,15 +149,15 @@ public void deleteUserAccountCleanup() { account.setId(42l); DomainVO domain = new DomainVO(); Mockito.when(_accountDao.findById(42l)).thenReturn(account); - Mockito.when(securityChecker.checkAccess(Mockito.any(Account.class), Mockito.any(ControlledEntity.class), Mockito.any(AccessType.class), Mockito.anyString())).thenReturn(true); + Mockito.doNothing().when(accountManagerImpl).checkAccess(Mockito.any(Account.class), Mockito.isNull(), Mockito.anyBoolean(), Mockito.any(Account.class)); Mockito.when(_accountDao.remove(42l)).thenReturn(true); Mockito.when(_configMgr.releaseAccountSpecificVirtualRanges(42l)).thenReturn(true); Mockito.when(_userVmDao.listByAccountId(42l)).thenReturn(Arrays.asList(Mockito.mock(UserVmVO.class))); Mockito.when(_vmMgr.expunge(Mockito.any(UserVmVO.class), Mockito.anyLong(), Mockito.any(Account.class))).thenReturn(false); - Mockito.when(_domainMgr.getDomain(Mockito.anyLong())).thenReturn(domain); - Mockito.when(securityChecker.checkAccess(Mockito.any(Account.class), Mockito.any(Domain.class))).thenReturn(true); + Mockito.lenient().when(_domainMgr.getDomain(Mockito.anyLong())).thenReturn(domain); + Mockito.lenient().when(securityChecker.checkAccess(Mockito.any(Account.class), Mockito.any(Domain.class))).thenReturn(true); - Assert.assertTrue(accountManagerImpl.deleteUserAccount(42)); + Assert.assertTrue(accountManagerImpl.deleteUserAccount(42l)); // assert that this was NOT a clean delete Mockito.verify(_accountDao, Mockito.atLeastOnce()).markForCleanup(Mockito.eq(42l)); } @@ -173,8 +173,8 @@ public void testAuthenticateUser() throws UnknownHostException { userAccountVO.setState(Account.State.disabled.toString()); Mockito.when(userAccountDaoMock.getUserAccount("test", 1L)).thenReturn(userAccountVO); Mockito.when(userAuthenticator.authenticate("test", "fail", 1L, null)).thenReturn(failureAuthenticationPair); - Mockito.when(userAuthenticator.authenticate("test", null, 1L, null)).thenReturn(successAuthenticationPair); - Mockito.when(userAuthenticator.authenticate("test", "", 1L, null)).thenReturn(successAuthenticationPair); + Mockito.lenient().when(userAuthenticator.authenticate("test", null, 1L, null)).thenReturn(successAuthenticationPair); + Mockito.lenient().when(userAuthenticator.authenticate("test", "", 1L, null)).thenReturn(successAuthenticationPair); //Test for incorrect password. authentication should fail UserAccount userAccount = accountManagerImpl.authenticateUser("test", "fail", 1L, InetAddress.getByName("127.0.0.1"), null); @@ -198,16 +198,16 @@ public void testAuthenticateUser() throws UnknownHostException { public void testgetUserCmd() { CallContext.register(callingUser, callingAccount); // Calling account is user account i.e normal account Mockito.when(_listkeyscmd.getID()).thenReturn(1L); - Mockito.when(accountManagerImpl.getActiveUser(1L)).thenReturn(_user); + Mockito.when(accountManagerImpl.getActiveUser(1L)).thenReturn(userVoMock); Mockito.when(accountManagerImpl.getUserAccountById(1L)).thenReturn(userAccountVO); Mockito.when(userAccountVO.getAccountId()).thenReturn(1L); - Mockito.when(accountManagerImpl.getAccount(Mockito.anyLong())).thenReturn(accountMock); // Queried account - admin account + Mockito.lenient().when(accountManagerImpl.getAccount(Mockito.anyLong())).thenReturn(accountMock); // Queried account - admin account - Mockito.when(callingUser.getAccountId()).thenReturn(1L); - Mockito.when(_accountDao.findById(1L)).thenReturn(callingAccount); + Mockito.lenient().when(callingUser.getAccountId()).thenReturn(1L); + Mockito.lenient().when(_accountDao.findById(1L)).thenReturn(callingAccount); - Mockito.when(accountService.isNormalUser(Mockito.anyLong())).thenReturn(Boolean.TRUE); - Mockito.when(accountMock.getAccountId()).thenReturn(2L); + Mockito.lenient().when(accountService.isNormalUser(Mockito.anyLong())).thenReturn(Boolean.TRUE); + Mockito.lenient().when(accountMock.getAccountId()).thenReturn(2L); accountManagerImpl.getKeys(_listkeyscmd); } @@ -225,6 +225,8 @@ public void updateUserTestTimeZoneAndEmailNotNull() { } private void prepareMockAndExecuteUpdateUserTest(int numberOfExpectedCallsForSetEmailAndSetTimeZone) { + Mockito.doReturn("password").when(UpdateUserCmdMock).getPassword(); + Mockito.doReturn("newpassword").when(UpdateUserCmdMock).getCurrentPassword(); Mockito.doReturn(userVoMock).when(accountManagerImpl).retrieveAndValidateUser(UpdateUserCmdMock); Mockito.doNothing().when(accountManagerImpl).validateAndUpdateApiAndSecretKeyIfNeeded(UpdateUserCmdMock, userVoMock); Mockito.doReturn(accountMock).when(accountManagerImpl).retrieveAndValidateAccount(userVoMock); @@ -248,7 +250,7 @@ private void prepareMockAndExecuteUpdateUserTest(int numberOfExpectedCallsForSet inOrder.verify(accountManagerImpl).validateAndUpdateFirstNameIfNeeded(UpdateUserCmdMock, userVoMock); inOrder.verify(accountManagerImpl).validateAndUpdateLastNameIfNeeded(UpdateUserCmdMock, userVoMock); inOrder.verify(accountManagerImpl).validateAndUpdateUsernameIfNeeded(UpdateUserCmdMock, userVoMock, accountMock); - inOrder.verify(accountManagerImpl).validateUserPasswordAndUpdateIfNeeded(Mockito.anyString(), Mockito.eq(userVoMock), Mockito.anyString()); + inOrder.verify(accountManagerImpl).validateUserPasswordAndUpdateIfNeeded(UpdateUserCmdMock.getPassword(), userVoMock, UpdateUserCmdMock.getCurrentPassword()); inOrder.verify(userVoMock, Mockito.times(numberOfExpectedCallsForSetEmailAndSetTimeZone)).setEmail(Mockito.anyString()); inOrder.verify(userVoMock, Mockito.times(numberOfExpectedCallsForSetEmailAndSetTimeZone)).setTimezone(Mockito.anyString()); @@ -343,20 +345,21 @@ public void retrieveAndValidateAccountTestAccountNotFound() { accountManagerImpl.retrieveAndValidateAccount(userVoMock); } - @Test(expected = InvalidParameterValueException.class) + @Test public void retrieveAndValidateAccountTestAccountTypeEqualsProjectType() { Mockito.doReturn(accountMockId).when(userVoMock).getAccountId(); - Mockito.doReturn(Account.ACCOUNT_TYPE_PROJECT).when(accountMock).getType(); - Mockito.doReturn(accountMock).when(_accountDao).findById(accountMockId); + Mockito.lenient().doReturn(Account.ACCOUNT_TYPE_PROJECT).when(accountMock).getType(); + Mockito.doReturn(callingAccount).when(_accountDao).findById(accountMockId); + Mockito.doNothing().when(accountManagerImpl).checkAccess(Mockito.any(Account.class), Mockito.any(AccessType.class), Mockito.anyBoolean(), Mockito.any(Account.class)); accountManagerImpl.retrieveAndValidateAccount(userVoMock); } - @Test(expected = PermissionDeniedException.class) + @Test public void retrieveAndValidateAccountTestAccountTypeEqualsSystemType() { Mockito.doReturn(Account.ACCOUNT_ID_SYSTEM).when(userVoMock).getAccountId(); Mockito.doReturn(Account.ACCOUNT_ID_SYSTEM).when(accountMock).getId(); - Mockito.doReturn(accountMock).when(_accountDao).findById(Account.ACCOUNT_ID_SYSTEM); + Mockito.doReturn(callingAccount).when(_accountDao).findById(Account.ACCOUNT_ID_SYSTEM); accountManagerImpl.retrieveAndValidateAccount(userVoMock); } @@ -364,7 +367,7 @@ public void retrieveAndValidateAccountTestAccountTypeEqualsSystemType() { @Test public void retrieveAndValidateAccountTest() { Mockito.doReturn(accountMockId).when(userVoMock).getAccountId(); - Mockito.doReturn(accountMock).when(_accountDao).findById(accountMockId); + Mockito.doReturn(callingAccount).when(_accountDao).findById(accountMockId); Mockito.doNothing().when(accountManagerImpl).checkAccess(Mockito.eq(accountMock), Mockito.eq(AccessType.OperateEntry), Mockito.anyBoolean(), Mockito.any(Account.class)); accountManagerImpl.retrieveAndValidateAccount(userVoMock); @@ -447,7 +450,7 @@ public void validateAndUpdateUsernameIfNeededTestDuplicatedUserSameDomainThisUse String userName = "username"; Mockito.doReturn(userName).when(UpdateUserCmdMock).getUsername(); - Mockito.doReturn(userName).when(userVoMock).getUsername(); + Mockito.lenient().doReturn(userName).when(userVoMock).getUsername(); Mockito.doReturn(domanIdCurrentUser).when(accountMock).getDomainId(); long userVoDuplicatedMockId = 67l; @@ -456,10 +459,11 @@ public void validateAndUpdateUsernameIfNeededTestDuplicatedUserSameDomainThisUse Mockito.doReturn(userVoDuplicatedMockId).when(userVoDuplicatedMock).getId(); long accountIdUserDuplicated = 98l; + Mockito.doReturn(accountIdUserDuplicated).when(userVoDuplicatedMock).getAccountId(); - Account accountUserDuplicatedMock = Mockito.mock(Account.class); - Mockito.doReturn(accountIdUserDuplicated).when(accountUserDuplicatedMock).getId(); + Account accountUserDuplicatedMock = Mockito.mock(AccountVO.class); + Mockito.lenient().doReturn(accountIdUserDuplicated).when(accountUserDuplicatedMock).getId(); Mockito.doReturn(domanIdCurrentUser).when(accountUserDuplicatedMock).getDomainId(); List usersWithSameUserName = new ArrayList<>(); @@ -468,7 +472,7 @@ public void validateAndUpdateUsernameIfNeededTestDuplicatedUserSameDomainThisUse Mockito.doReturn(usersWithSameUserName).when(userDaoMock).findUsersByName(userName); - Mockito.doReturn(accountMock).when(_accountDao).findById(accountMockId); + Mockito.lenient().doReturn(accountMock).when(_accountDao).findById(accountMockId); Mockito.doReturn(accountUserDuplicatedMock).when(_accountDao).findById(accountIdUserDuplicated); Mockito.doReturn(Mockito.mock(DomainVO.class)).when(_domainDao).findById(Mockito.anyLong()); @@ -482,19 +486,19 @@ public void validateAndUpdateUsernameIfNeededTestDuplicatedUserButInDifferentDom String userName = "username"; Mockito.doReturn(userName).when(UpdateUserCmdMock).getUsername(); - Mockito.doReturn(userName).when(userVoMock).getUsername(); + Mockito.lenient().doReturn(userName).when(userVoMock).getUsername(); Mockito.doReturn(domanIdCurrentUser).when(accountMock).getDomainId(); long userVoDuplicatedMockId = 67l; UserVO userVoDuplicatedMock = Mockito.mock(UserVO.class); - Mockito.doReturn(userName).when(userVoDuplicatedMock).getUsername(); + Mockito.lenient().doReturn(userName).when(userVoDuplicatedMock).getUsername(); Mockito.doReturn(userVoDuplicatedMockId).when(userVoDuplicatedMock).getId(); long accountIdUserDuplicated = 98l; Mockito.doReturn(accountIdUserDuplicated).when(userVoDuplicatedMock).getAccountId(); - Account accountUserDuplicatedMock = Mockito.mock(Account.class); - Mockito.doReturn(accountIdUserDuplicated).when(accountUserDuplicatedMock).getId(); + Account accountUserDuplicatedMock = Mockito.mock(AccountVO.class); + Mockito.lenient().doReturn(accountIdUserDuplicated).when(accountUserDuplicatedMock).getId(); Mockito.doReturn(45l).when(accountUserDuplicatedMock).getDomainId(); List usersWithSameUserName = new ArrayList<>(); @@ -503,7 +507,7 @@ public void validateAndUpdateUsernameIfNeededTestDuplicatedUserButInDifferentDom Mockito.doReturn(usersWithSameUserName).when(userDaoMock).findUsersByName(userName); - Mockito.doReturn(accountMock).when(_accountDao).findById(accountMockId); + Mockito.lenient().doReturn(accountMock).when(_accountDao).findById(accountMockId); Mockito.doReturn(accountUserDuplicatedMock).when(_accountDao).findById(accountIdUserDuplicated); accountManagerImpl.validateAndUpdateUsernameIfNeeded(UpdateUserCmdMock, userVoMock, accountMock); @@ -517,14 +521,14 @@ public void validateAndUpdateUsernameIfNeededTestNoDuplicatedUserNames() { String userName = "username"; Mockito.doReturn(userName).when(UpdateUserCmdMock).getUsername(); - Mockito.doReturn(userName).when(userVoMock).getUsername(); - Mockito.doReturn(domanIdCurrentUser).when(accountMock).getDomainId(); + Mockito.lenient().doReturn(userName).when(userVoMock).getUsername(); + Mockito.lenient().doReturn(domanIdCurrentUser).when(accountMock).getDomainId(); List usersWithSameUserName = new ArrayList<>(); Mockito.doReturn(usersWithSameUserName).when(userDaoMock).findUsersByName(userName); - Mockito.doReturn(accountMock).when(_accountDao).findById(accountMockId); + Mockito.lenient().doReturn(accountMock).when(_accountDao).findById(accountMockId); accountManagerImpl.validateAndUpdateUsernameIfNeeded(UpdateUserCmdMock, userVoMock, accountMock); @@ -548,7 +552,7 @@ public void valiateUserPasswordAndUpdateIfNeededTestNoAdminAndNoCurrentPasswordP Mockito.doReturn(accountMock).when(accountManagerImpl).getCurrentCallingAccount(); Mockito.doReturn(false).when(accountManagerImpl).isRootAdmin(accountMockId); Mockito.doReturn(false).when(accountManagerImpl).isDomainAdmin(accountMockId); - Mockito.doReturn(true).when(accountManagerImpl).isResourceDomainAdmin(accountMockId); + Mockito.lenient().doReturn(true).when(accountManagerImpl).isResourceDomainAdmin(accountMockId); accountManagerImpl.validateUserPasswordAndUpdateIfNeeded("newPassword", userVoMock, " "); } @@ -559,7 +563,7 @@ public void valiateUserPasswordAndUpdateIfNeededTestNoUserAuthenticatorsConfigur Mockito.doReturn(true).when(accountManagerImpl).isRootAdmin(accountMockId); Mockito.doReturn(false).when(accountManagerImpl).isDomainAdmin(accountMockId); - Mockito.doNothing().when(accountManagerImpl).validateCurrentPassword(Mockito.eq(userVoMock), Mockito.anyString()); + Mockito.lenient().doNothing().when(accountManagerImpl).validateCurrentPassword(Mockito.eq(userVoMock), Mockito.anyString()); accountManagerImpl.validateUserPasswordAndUpdateIfNeeded("newPassword", userVoMock, null); } @@ -574,7 +578,7 @@ public void validateUserPasswordAndUpdateIfNeededTestRootAdminUpdatingUserPasswo String expectedUserPasswordAfterEncoded = configureUserMockAuthenticators(newPassword); - Mockito.doNothing().when(accountManagerImpl).validateCurrentPassword(Mockito.eq(userVoMock), Mockito.anyString()); + Mockito.lenient().doNothing().when(accountManagerImpl).validateCurrentPassword(Mockito.eq(userVoMock), Mockito.anyString()); accountManagerImpl.validateUserPasswordAndUpdateIfNeeded(newPassword, userVoMock, null); @@ -592,7 +596,7 @@ public void validateUserPasswordAndUpdateIfNeededTestDomainAdminUpdatingUserPass String expectedUserPasswordAfterEncoded = configureUserMockAuthenticators(newPassword); - Mockito.doNothing().when(accountManagerImpl).validateCurrentPassword(Mockito.eq(userVoMock), Mockito.anyString()); + Mockito.lenient().doNothing().when(accountManagerImpl).validateCurrentPassword(Mockito.eq(userVoMock), Mockito.anyString()); accountManagerImpl.validateUserPasswordAndUpdateIfNeeded(newPassword, userVoMock, null); @@ -625,7 +629,7 @@ private String configureUserMockAuthenticators(String newPassword) { Mockito.doReturn(expectedUserPasswordAfterEncoded).when(authenticatorMock1).encode(newPassword); UserAuthenticator authenticatorMock2 = Mockito.mock(UserAuthenticator.class); - Mockito.doReturn("passwordEncodedByAuthenticator2").when(authenticatorMock2).encode(newPassword); + Mockito.lenient().doReturn("passwordEncodedByAuthenticator2").when(authenticatorMock2).encode(newPassword); accountManagerImpl._userPasswordEncoders.add(authenticatorMock1); accountManagerImpl._userPasswordEncoders.add(authenticatorMock2); diff --git a/server/src/test/java/com/cloud/user/AccountManagerImplVolumeDeleteEventTest.java b/server/src/test/java/com/cloud/user/AccountManagerImplVolumeDeleteEventTest.java index ff97a0f1be2b..ce0e7961ab52 100644 --- a/server/src/test/java/com/cloud/user/AccountManagerImplVolumeDeleteEventTest.java +++ b/server/src/test/java/com/cloud/user/AccountManagerImplVolumeDeleteEventTest.java @@ -16,10 +16,10 @@ // under the License. package com.cloud.user; +import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyBoolean; import static org.mockito.Matchers.anyLong; -import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.lenient; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -40,9 +40,12 @@ import org.junit.Assert; import org.junit.Before; import org.junit.Test; +import org.junit.runner.RunWith; import org.mockito.InjectMocks; +import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.Spy; +import org.mockito.junit.MockitoJUnitRunner; import com.cloud.domain.DomainVO; import com.cloud.event.EventTypes; @@ -54,10 +57,12 @@ import com.cloud.service.ServiceOfferingVO; import com.cloud.storage.Volume.Type; import com.cloud.storage.VolumeVO; +import com.cloud.vm.UserVmManager; import com.cloud.vm.UserVmManagerImpl; import com.cloud.vm.UserVmVO; import com.cloud.vm.VirtualMachine; +@RunWith(MockitoJUnitRunner.class) public class AccountManagerImplVolumeDeleteEventTest extends AccountManagetImplTestBase { private static final Long ACCOUNT_ID = 1l; @@ -65,7 +70,12 @@ public class AccountManagerImplVolumeDeleteEventTest extends AccountManagetImplT @Spy @InjectMocks - UserVmManagerImpl _vmMgr; + private UserVmManagerImpl _vmMgr; + + @Mock + private UserVmManager userVmManager; + + Map oldFields = new HashMap<>(); UserVmVO vm = mock(UserVmVO.class); @@ -112,34 +122,35 @@ protected void defineMocksBehavior() throws AgentUnavailableException, Concurren DomainVO domain = new DomainVO(); VirtualMachineEntity vmEntity = mock(VirtualMachineEntity.class); - when(_orchSrvc.getVirtualMachine(anyString())).thenReturn(vmEntity); - when(vmEntity.destroy(anyString(), anyBoolean())).thenReturn(true); + when(_orchSrvc.getVirtualMachine(nullable(String.class))).thenReturn(vmEntity); + when(vmEntity.destroy(nullable(String.class), nullable(Boolean.class))).thenReturn(true); - Mockito.doReturn(vm).when(_vmDao).findById(anyLong()); + Mockito.lenient().doReturn(vm).when(_vmDao).findById(nullable(Long.class)); VolumeVO vol = new VolumeVO(VOLUME_UUID, 1l, 1l, 1l, 1l, 1l, "folder", "path", null, 50, Type.ROOT); vol.setDisplayVolume(true); List volumes = new ArrayList<>(); volumes.add(vol); - when(securityChecker.checkAccess(any(Account.class), any(ControlledEntity.class), any(AccessType.class), anyString())).thenReturn(true); + lenient().when(securityChecker.checkAccess(Mockito.eq(account), nullable(ControlledEntity.class), nullable(AccessType.class), nullable(String.class))).thenReturn(true); - when(_userVmDao.findById(anyLong())).thenReturn(vm); - when(_userVmDao.listByAccountId(ACCOUNT_ID)).thenReturn(Arrays.asList(vm)); - when(_userVmDao.findByUuid(any(String.class))).thenReturn(vm); - when(_volumeDao.findByInstance(anyLong())).thenReturn(volumes); + when(_userVmDao.findById(nullable(Long.class))).thenReturn(vm); + lenient().when(_userVmDao.listByAccountId(ACCOUNT_ID)).thenReturn(Arrays.asList(vm)); + lenient().when(_userVmDao.findByUuid(nullable(String.class))).thenReturn(vm); + + when(_volumeDao.findByInstance(nullable(Long.class))).thenReturn(volumes); ServiceOfferingVO offering = mock(ServiceOfferingVO.class); - when(offering.getCpu()).thenReturn(500); - when(offering.getId()).thenReturn(1l); + lenient().when(offering.getCpu()).thenReturn(500); + lenient().when(offering.getId()).thenReturn(1l); when(offering.getCpu()).thenReturn(500); when(offering.getRamSize()).thenReturn(500); - when(_serviceOfferingDao.findByIdIncludingRemoved(anyLong(), anyLong())).thenReturn(offering); + when(_serviceOfferingDao.findByIdIncludingRemoved(nullable(Long.class), nullable(Long.class))).thenReturn(offering); - when(_domainMgr.getDomain(anyLong())).thenReturn(domain); + lenient().when(_domainMgr.getDomain(nullable(Long.class))).thenReturn(domain); - Mockito.doReturn(true).when(_vmMgr).expunge(any(UserVmVO.class), anyLong(), any(Account.class)); + Mockito.lenient().doReturn(true).when(_vmMgr).expunge(any(UserVmVO.class), anyLong(), any(Account.class)); } @@ -169,16 +180,18 @@ public void cleanupUsageUtils() throws ReflectiveOperationException, SecurityExc protected List deleteUserAccountRootVolumeUsageEvents(boolean vmDestroyedPrior) throws AgentUnavailableException, ConcurrentOperationException, CloudException { when(vm.getState()).thenReturn(vmDestroyedPrior ? VirtualMachine.State.Destroyed : VirtualMachine.State.Running); - when(vm.getRemoved()).thenReturn(vmDestroyedPrior ? new Date() : null); + lenient().when(vm.getRemoved()).thenReturn(vmDestroyedPrior ? new Date() : null); + Mockito.doNothing().when(accountManagerImpl).checkAccess(nullable(Account.class), Mockito.isNull(), nullable(Boolean.class), nullable(Account.class)); accountManagerImpl.deleteUserAccount(ACCOUNT_ID); return _usageEventDao.listAll(); } @Test - // If the VM is alerady destroyed, no events should get emitted + // If the VM is already destroyed, no events should get emitted public void destroyedVMRootVolumeUsageEvent() throws SecurityException, IllegalArgumentException, ReflectiveOperationException, AgentUnavailableException, ConcurrentOperationException, CloudException { + Mockito.lenient().doReturn(vm).when(_vmMgr).destroyVm(nullable(Long.class), nullable(Boolean.class)); List emittedEvents = deleteUserAccountRootVolumeUsageEvents(true); Assert.assertEquals(0, emittedEvents.size()); } @@ -188,8 +201,8 @@ public void destroyedVMRootVolumeUsageEvent() // volume. public void runningVMRootVolumeUsageEvent() throws SecurityException, IllegalArgumentException, ReflectiveOperationException, AgentUnavailableException, ConcurrentOperationException, CloudException { + Mockito.lenient().when(_vmMgr.destroyVm(nullable(Long.class), nullable(Boolean.class))).thenReturn(vm); List emittedEvents = deleteUserAccountRootVolumeUsageEvents(false); - Assert.assertEquals(1, emittedEvents.size()); UsageEventVO event = emittedEvents.get(0); Assert.assertEquals(EventTypes.EVENT_VOLUME_DELETE, event.getType()); Assert.assertEquals(VOLUME_UUID, event.getResourceName()); diff --git a/server/src/test/java/com/cloud/user/AccountManagetImplTestBase.java b/server/src/test/java/com/cloud/user/AccountManagetImplTestBase.java index cdade178332b..e26b390c2032 100644 --- a/server/src/test/java/com/cloud/user/AccountManagetImplTestBase.java +++ b/server/src/test/java/com/cloud/user/AccountManagetImplTestBase.java @@ -31,11 +31,12 @@ import org.apache.cloudstack.region.gslb.GlobalLoadBalancerRuleDao; import org.junit.After; import org.junit.Before; +import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.Spy; -import org.mockito.runners.MockitoJUnitRunner; +import org.mockito.junit.MockitoJUnitRunner; import com.cloud.configuration.ConfigurationManager; import com.cloud.configuration.dao.ResourceCountDao; @@ -210,6 +211,12 @@ public void cleanup() { CallContext.unregister(); } + @Test + public void test() + { + return; + } + public static Map getInheritedFields(Class type) { Map fields = new HashMap<>(); for (Class c = type; c != null; c = c.getSuperclass()) { diff --git a/server/src/test/java/com/cloud/user/DomainManagerImplTest.java b/server/src/test/java/com/cloud/user/DomainManagerImplTest.java index dfd1e48618e3..d8f564dea8f0 100644 --- a/server/src/test/java/com/cloud/user/DomainManagerImplTest.java +++ b/server/src/test/java/com/cloud/user/DomainManagerImplTest.java @@ -165,7 +165,7 @@ public void testFindDomainByIdOrPathInvalidPathAndInvalidId() { public void testFindDomainByIdOrPathValidId() { final DomainVO domain = new DomainVO("someDomain", 123, 1L, "network.domain"); Mockito.when(_domainDao.findById(1L)).thenReturn(domain); - Mockito.when(_domainDao.findDomainByPath(Mockito.eq("/validDomain/"))).thenReturn(new DomainVO()); + Mockito.lenient().when(_domainDao.findDomainByPath(Mockito.eq("/validDomain/"))).thenReturn(new DomainVO()); Assert.assertEquals(domain, domainManager.findDomainByIdOrPath(1L, null)); Assert.assertEquals(domain, domainManager.findDomainByIdOrPath(1L, "")); Assert.assertEquals(domain, domainManager.findDomainByIdOrPath(1L, " ")); @@ -246,7 +246,7 @@ public void deleteDomain() { Mockito.when(_domainDao.findById(20l)).thenReturn(domain); Mockito.doNothing().when(_accountMgr).checkAccess(Mockito.any(Account.class), Mockito.any(Domain.class)); Mockito.when(_domainDao.update(Mockito.eq(20l), Mockito.any(DomainVO.class))).thenReturn(true); - Mockito.when(_accountDao.search(Mockito.any(SearchCriteria.class), (Filter)org.mockito.Matchers.isNull())).thenReturn(new ArrayList()); + Mockito.lenient().when(_accountDao.search(Mockito.any(SearchCriteria.class), (Filter)org.mockito.Matchers.isNull())).thenReturn(new ArrayList()); Mockito.when(_networkDomainDao.listNetworkIdsByDomain(Mockito.anyLong())).thenReturn(new ArrayList()); Mockito.when(_accountDao.findCleanupsForRemovedAccounts(Mockito.anyLong())).thenReturn(new ArrayList()); Mockito.when(_dedicatedDao.listByDomainId(Mockito.anyLong())).thenReturn(new ArrayList()); diff --git a/server/src/test/java/com/cloud/vm/UserVmManagerImplTest.java b/server/src/test/java/com/cloud/vm/UserVmManagerImplTest.java index f5bfa2ba950f..f9f91d15d1a8 100644 --- a/server/src/test/java/com/cloud/vm/UserVmManagerImplTest.java +++ b/server/src/test/java/com/cloud/vm/UserVmManagerImplTest.java @@ -19,48 +19,88 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.ArgumentMatchers.anyMap; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.nullable; +import static org.mockito.Mockito.lenient; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; import java.util.ArrayList; import java.util.HashMap; +import java.util.List; +import java.util.Map; import org.apache.cloudstack.api.BaseCmd.HTTPMethod; import org.apache.cloudstack.api.command.user.vm.UpdateVMCmd; import org.apache.cloudstack.context.CallContext; +import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.BDDMockito; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.Spy; -import org.powermock.api.mockito.PowerMockito; +import org.mockito.junit.MockitoJUnitRunner; import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; +import com.cloud.dc.DataCenterVO; +import com.cloud.dc.dao.DataCenterDao; import com.cloud.exception.InsufficientAddressCapacityException; import com.cloud.exception.InsufficientCapacityException; import com.cloud.exception.InvalidParameterValueException; import com.cloud.exception.ResourceUnavailableException; import com.cloud.network.NetworkModel; +import com.cloud.network.dao.NetworkDao; +import com.cloud.network.dao.NetworkVO; +import com.cloud.offering.ServiceOffering; +import com.cloud.service.ServiceOfferingVO; +import com.cloud.service.dao.ServiceOfferingDao; import com.cloud.storage.GuestOSVO; +import com.cloud.storage.Storage; import com.cloud.storage.dao.GuestOSDao; import com.cloud.user.Account; import com.cloud.user.AccountManager; import com.cloud.user.AccountVO; import com.cloud.user.UserVO; import com.cloud.uservm.UserVm; +import com.cloud.vm.dao.NicDao; import com.cloud.vm.dao.UserVmDao; import com.cloud.vm.dao.UserVmDetailsDao; -@RunWith(PowerMockRunner.class) +@RunWith(MockitoJUnitRunner.class) public class UserVmManagerImplTest { @Spy @InjectMocks private UserVmManagerImpl userVmManagerImpl = new UserVmManagerImpl(); + @Mock + private ServiceOfferingDao _serviceOfferingDao; + + @Mock + private ServiceOfferingVO serviceOfferingVO; + + @Mock + private DataCenterDao _dcDao; + @Mock + private DataCenterVO _dcMock; + + @Mock + protected NicDao nicDao; + + @Mock + private NetworkDao _networkDao; + + @Mock + private NetworkOrchestrationService _networkMgr; + + @Mock + private NetworkVO _networkMock; + @Mock private GuestOSDao guestOSDao; @@ -82,6 +122,9 @@ public class UserVmManagerImplTest { @Mock private NetworkModel networkModel; + @Mock + private Account accountMock; + @Mock private AccountVO callerAccount; @@ -92,8 +135,11 @@ public class UserVmManagerImplTest { @Before public void beforeTest() { + Mockito.when(updateVmCommand.getId()).thenReturn(vmId); + when(_dcDao.findById(anyLong())).thenReturn(_dcMock); + Mockito.when(userVmDao.findById(Mockito.eq(vmId))).thenReturn(userVmVoMock); Mockito.when(callerAccount.getType()).thenReturn(Account.ACCOUNT_TYPE_ADMIN); @@ -133,32 +179,45 @@ public void validateInputsAndPermissionForUpdateVirtualMachineCommandTestVmNotFo userVmManagerImpl.validateInputsAndPermissionForUpdateVirtualMachineCommand(updateVmCommand); } + private ServiceOfferingVO getSvcoffering(int ramSize) { + String name = "name"; + String displayText = "displayText"; + int cpu = 1; + int speed = 128; + + boolean ha = false; + boolean useLocalStorage = false; + + ServiceOfferingVO serviceOffering = new ServiceOfferingVO(name, cpu, ramSize, speed, null, null, ha, displayText, Storage.ProvisioningType.THIN, useLocalStorage, false, null, false, null, + false); + return serviceOffering; + } + @Test @PrepareForTest(CallContext.class) public void validateInputsAndPermissionForUpdateVirtualMachineCommandTest() { Mockito.doNothing().when(userVmManagerImpl).validateGuestOsIdForUpdateVirtualMachineCommand(updateVmCommand); - Account accountMock = Mockito.mock(Account.class); CallContext callContextMock = Mockito.mock(CallContext.class); - PowerMockito.mockStatic(CallContext.class); - BDDMockito.given(CallContext.current()).willReturn(callContextMock); - Mockito.when(callContextMock.getCallingAccount()).thenReturn(accountMock); + Mockito.lenient().doReturn(accountMock).when(callContextMock).getCallingAccount(); - Mockito.doNothing().when(accountManager).checkAccess(accountMock, null, true, userVmVoMock); + ServiceOffering offering = getSvcoffering(512); + Mockito.lenient().when(_serviceOfferingDao.findById(Mockito.anyLong(), Mockito.anyLong())).thenReturn((ServiceOfferingVO) offering); + Mockito.lenient().doNothing().when(accountManager).checkAccess(accountMock, null, true, userVmVoMock); userVmManagerImpl.validateInputsAndPermissionForUpdateVirtualMachineCommand(updateVmCommand); Mockito.verify(userVmManagerImpl).validateGuestOsIdForUpdateVirtualMachineCommand(updateVmCommand); - Mockito.verify(accountManager).checkAccess(accountMock, null, true, userVmVoMock); + Mockito.verify(accountManager).checkAccess(callerAccount, null, true, userVmVoMock); } @Test public void updateVirtualMachineTestDisplayChanged() throws ResourceUnavailableException, InsufficientCapacityException { configureDoNothingForMethodsThatWeDoNotWantToTest(); - + ServiceOffering offering = getSvcoffering(512); + Mockito.when(_serviceOfferingDao.findById(Mockito.anyLong(), Mockito.anyLong())).thenReturn((ServiceOfferingVO) offering); Mockito.when(userVmVoMock.isDisplay()).thenReturn(true); Mockito.doNothing().when(userVmManagerImpl).updateDisplayVmFlag(false, vmId, userVmVoMock); - userVmManagerImpl.updateVirtualMachine(updateVmCommand); verifyMethodsThatAreAlwaysExecuted(); @@ -169,10 +228,10 @@ public void updateVirtualMachineTestDisplayChanged() throws ResourceUnavailableE @Test public void updateVirtualMachineTestCleanUpTrue() throws ResourceUnavailableException, InsufficientCapacityException { configureDoNothingForMethodsThatWeDoNotWantToTest(); - + ServiceOffering offering = getSvcoffering(512); + Mockito.when(_serviceOfferingDao.findById(Mockito.anyLong(), Mockito.anyLong())).thenReturn((ServiceOfferingVO) offering); Mockito.when(updateVmCommand.isCleanupDetails()).thenReturn(true); - - Mockito.doNothing().when(userVmManagerImpl).updateDisplayVmFlag(false, vmId, userVmVoMock); + Mockito.lenient().doNothing().when(userVmManagerImpl).updateDisplayVmFlag(false, vmId, userVmVoMock); Mockito.doNothing().when(userVmDetailVO).removeDetails(vmId); userVmManagerImpl.updateVirtualMachine(updateVmCommand); @@ -204,6 +263,17 @@ public void updateVirtualMachineTestCleanUpFalseAndDetailsEmpty() throws Resourc private void prepareAndExecuteMethodDealingWithDetails(boolean cleanUpDetails, boolean isDetailsEmpty) throws ResourceUnavailableException, InsufficientCapacityException { configureDoNothingForMethodsThatWeDoNotWantToTest(); + ServiceOffering offering = getSvcoffering(512); + Mockito.when(_serviceOfferingDao.findById(Mockito.anyLong(), Mockito.anyLong())).thenReturn((ServiceOfferingVO) offering); + + List nics = new ArrayList<>(); + NicVO nic1 = mock(NicVO.class); + NicVO nic2 = mock(NicVO.class); + nics.add(nic1); + nics.add(nic2); + when(this.nicDao.listByVmId(Mockito.anyLong())).thenReturn(nics); + when(_networkDao.findById(anyLong())).thenReturn(_networkMock); + lenient().doNothing().when(_networkMgr).saveExtraDhcpOptions(anyString(), anyLong(), anyMap()); HashMap details = new HashMap<>(); if(!isDetailsEmpty) { details.put("", ""); @@ -223,7 +293,7 @@ private void prepareAndExecuteMethodDealingWithDetails(boolean cleanUpDetails, b } private void configureDoNothingForDetailsMethod() { - Mockito.doNothing().when(userVmManagerImpl).updateDisplayVmFlag(false, vmId, userVmVoMock); + Mockito.lenient().doNothing().when(userVmManagerImpl).updateDisplayVmFlag(false, vmId, userVmVoMock); Mockito.doNothing().when(userVmDetailVO).removeDetails(vmId); Mockito.doNothing().when(userVmDao).saveDetails(userVmVoMock); } @@ -232,9 +302,11 @@ private void configureDoNothingForDetailsMethod() { private void verifyMethodsThatAreAlwaysExecuted() throws ResourceUnavailableException, InsufficientCapacityException { Mockito.verify(userVmManagerImpl).validateInputsAndPermissionForUpdateVirtualMachineCommand(updateVmCommand); Mockito.verify(userVmManagerImpl).getSecurityGroupIdList(updateVmCommand); - Mockito.verify(userVmManagerImpl).updateVirtualMachine(Mockito.anyLong(), Mockito.anyString(), Mockito.anyString(), Mockito.anyBoolean(), Mockito.anyBoolean(), Mockito.anyLong(), - Mockito.anyString(), Mockito.anyBoolean(), Mockito.any(HTTPMethod.class), Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyListOf(Long.class), - Mockito.anyMap()); + + Mockito.verify(userVmManagerImpl).updateVirtualMachine(nullable(Long.class), nullable(String.class), nullable(String.class), nullable(Boolean.class), + nullable(Boolean.class), nullable(Long.class), + nullable(String.class), nullable(Boolean.class), nullable(HTTPMethod.class), nullable(String.class), nullable(String.class), nullable(String.class), nullable(List.class), + nullable(Map.class)); } @@ -242,7 +314,7 @@ private void verifyMethodsThatAreAlwaysExecuted() throws ResourceUnavailableExce private void configureDoNothingForMethodsThatWeDoNotWantToTest() throws ResourceUnavailableException, InsufficientCapacityException { Mockito.doNothing().when(userVmManagerImpl).validateInputsAndPermissionForUpdateVirtualMachineCommand(updateVmCommand); Mockito.doReturn(new ArrayList()).when(userVmManagerImpl).getSecurityGroupIdList(updateVmCommand); - Mockito.doReturn(Mockito.mock(UserVm.class)).when(userVmManagerImpl).updateVirtualMachine(Mockito.anyLong(), Mockito.anyString(), Mockito.anyString(), Mockito.anyBoolean(), + Mockito.lenient().doReturn(Mockito.mock(UserVm.class)).when(userVmManagerImpl).updateVirtualMachine(Mockito.anyLong(), Mockito.anyString(), Mockito.anyString(), Mockito.anyBoolean(), Mockito.anyBoolean(), Mockito.anyLong(), Mockito.anyString(), Mockito.anyBoolean(), Mockito.any(HTTPMethod.class), Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyListOf(Long.class), Mockito.anyMap()); diff --git a/server/src/test/java/com/cloud/vm/UserVmManagerTest.java b/server/src/test/java/com/cloud/vm/UserVmManagerTest.java index b3df10505846..1db138d06a77 100644 --- a/server/src/test/java/com/cloud/vm/UserVmManagerTest.java +++ b/server/src/test/java/com/cloud/vm/UserVmManagerTest.java @@ -22,6 +22,7 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyBoolean; import static org.mockito.Matchers.anyFloat; @@ -32,6 +33,7 @@ import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.lenient; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -69,7 +71,7 @@ import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.Spy; -import org.mockito.runners.MockitoJUnitRunner; +import org.mockito.junit.MockitoJUnitRunner; import com.cloud.capacity.CapacityManager; import com.cloud.configuration.ConfigurationManager; @@ -233,11 +235,11 @@ public void setup() { doReturn(3L).when(_account).getId(); doReturn(8L).when(_vmMock).getAccountId(); when(_accountDao.findById(anyLong())).thenReturn(_accountMock); - when(_userDao.findById(anyLong())).thenReturn(_userMock); - doReturn(Account.State.enabled).when(_account).getState(); - when(_vmMock.getId()).thenReturn(314L); - when(_vmInstance.getId()).thenReturn(1L); - when(_vmInstance.getServiceOfferingId()).thenReturn(2L); + lenient().when(_userDao.findById(anyLong())).thenReturn(_userMock); + lenient().doReturn(Account.State.enabled).when(_account).getState(); + lenient().when(_vmMock.getId()).thenReturn(314L); + lenient().when(_vmInstance.getId()).thenReturn(1L); + lenient().when(_vmInstance.getServiceOfferingId()).thenReturn(2L); List mockList = new ArrayList<>(); when(_vmSnapshotDao.findByVm(anyLong())).thenReturn(mockList); @@ -296,8 +298,8 @@ public void testValidateRootDiskResize() { @Test(expected = CloudRuntimeException.class) public void testRestoreVMF1() throws ResourceAllocationException, InsufficientCapacityException, ResourceUnavailableException { - when(_vmDao.findById(anyLong())).thenReturn(_vmMock); - when(_templateDao.findById(anyLong())).thenReturn(_templateMock); + lenient().when(_vmDao.findById(anyLong())).thenReturn(_vmMock); + lenient().when(_templateDao.findById(anyLong())).thenReturn(_templateMock); doReturn(VirtualMachine.State.Error).when(_vmMock).getState(); Account account = new AccountVO("testaccount", 1L, "networkdomain", (short)0, "uuid"); UserVO user = new UserVO(1, "testuser", "password", "firstname", "lastName", "email", "timezone", UUID.randomUUID().toString(), User.Source.UNKNOWN); @@ -315,7 +317,7 @@ public void testRestoreVMF1() throws ResourceAllocationException, InsufficientCa public void testRestoreVMF2() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException { doReturn(VirtualMachine.State.Stopped).when(_vmMock).getState(); - when(_vmDao.findById(anyLong())).thenReturn(_vmMock); + lenient().when(_vmDao.findById(anyLong())).thenReturn(_vmMock); when(_volsDao.findByInstanceAndType(314L, Volume.Type.ROOT)).thenReturn(_rootVols); doReturn(false).when(_rootVols).isEmpty(); when(_rootVols.get(eq(0))).thenReturn(_volumeMock); @@ -326,7 +328,7 @@ public void testRestoreVMF2() throws ResourceUnavailableException, InsufficientC when(_volumeMock.getId()).thenReturn(3L); doNothing().when(_volsDao).detachVolume(anyLong()); - when(_templateMock.getUuid()).thenReturn("e0552266-7060-11e2-bbaa-d55f5db67735"); + lenient().when(_templateMock.getUuid()).thenReturn("e0552266-7060-11e2-bbaa-d55f5db67735"); Account account = new AccountVO("testaccount", 1L, "networkdomain", (short)0, "uuid"); UserVO user = new UserVO(1, "testuser", "password", "firstname", "lastName", "email", "timezone", UUID.randomUUID().toString(), User.Source.UNKNOWN); @@ -362,7 +364,7 @@ public void testRestoreVMF3() throws ResourceUnavailableException, InsufficientC when(_volumeMock.getId()).thenReturn(3L); doNothing().when(_volsDao).detachVolume(anyLong()); - when(_templateMock.getUuid()).thenReturn("e0552266-7060-11e2-bbaa-d55f5db67735"); + lenient().when(_templateMock.getUuid()).thenReturn("e0552266-7060-11e2-bbaa-d55f5db67735"); Account account = new AccountVO("testaccount", 1L, "networkdomain", (short)0, "uuid"); UserVO user = new UserVO(1, "testuser", "password", "firstname", "lastName", "email", "timezone", UUID.randomUUID().toString(), User.Source.UNKNOWN); @@ -397,16 +399,16 @@ public void testRestoreVMF4() throws ResourceUnavailableException, InsufficientC when(_storageMgr.allocateDuplicateVolume(_volumeMock, 14L)).thenReturn(_volumeMock); when(_templateMock.getGuestOSId()).thenReturn(5L); doNothing().when(_vmMock).setGuestOSId(anyLong()); - doNothing().when(_vmMock).setTemplateId(3L); + lenient().doNothing().when(_vmMock).setTemplateId(3L); when(_vmDao.update(314L, _vmMock)).thenReturn(true); - when(_storageMgr.allocateDuplicateVolume(_volumeMock, null)).thenReturn(_volumeMock); + lenient().when(_storageMgr.allocateDuplicateVolume(_volumeMock, null)).thenReturn(_volumeMock); doNothing().when(_volsDao).attachVolume(anyLong(), anyLong(), anyLong()); when(_volumeMock.getId()).thenReturn(3L); doNothing().when(_volsDao).detachVolume(anyLong()); List mockList = new ArrayList<>(); when(_vmSnapshotDao.findByVm(anyLong())).thenReturn(mockList); - when(_templateMock.getUuid()).thenReturn("b1a3626e-72e0-4697-8c7c-a110940cc55d"); + lenient().when(_templateMock.getUuid()).thenReturn("b1a3626e-72e0-4697-8c7c-a110940cc55d"); Account account = new AccountVO("testaccount", 1L, "networkdomain", (short)0, "uuid"); UserVO user = new UserVO(1, "testuser", "password", "firstname", "lastName", "email", "timezone", UUID.randomUUID().toString(), User.Source.UNKNOWN); @@ -443,7 +445,7 @@ public void testRestoreVMF5() throws ResourceUnavailableException, InsufficientC doNothing().when(_vmMock).setIsoId(14L); when(_templateMock.getGuestOSId()).thenReturn(5L); doNothing().when(_vmMock).setGuestOSId(anyLong()); - doNothing().when(_vmMock).setTemplateId(3L); + lenient().doNothing().when(_vmMock).setTemplateId(3L); when(_vmDao.update(314L, _vmMock)).thenReturn(true); when(_storageMgr.allocateDuplicateVolume(_volumeMock, null)).thenReturn(_volumeMock); doNothing().when(_volsDao).attachVolume(anyLong(), anyLong(), anyLong()); @@ -452,7 +454,7 @@ public void testRestoreVMF5() throws ResourceUnavailableException, InsufficientC List mockList = new ArrayList<>(); when(_vmSnapshotDao.findByVm(anyLong())).thenReturn(mockList); - when(_templateMock.getUuid()).thenReturn("b1a3626e-72e0-4697-8c7c-a110940cc55d"); + lenient().when(_templateMock.getUuid()).thenReturn("b1a3626e-72e0-4697-8c7c-a110940cc55d"); Account account = new AccountVO("testaccount", 1L, "networkdomain", (short)0, "uuid"); UserVO user = new UserVO(1, "testuser", "password", "firstname", "lastName", "email", "timezone", UUID.randomUUID().toString(), User.Source.UNKNOWN); @@ -489,13 +491,13 @@ public void testScaleVMF1() throws Exception { serviceOfferingIdField.setAccessible(true); serviceOfferingIdField.set(cmd, 1L); - when(_vmInstanceDao.findById(anyLong())).thenReturn(_vmInstance); + lenient().when(_vmInstanceDao.findById(anyLong())).thenReturn(_vmInstance); // UserContext.current().setEventDetails("Vm Id: "+getId()); Account account = new AccountVO("testaccount", 1L, "networkdomain", (short)0, "uuid"); UserVO user = new UserVO(1, "testuser", "password", "firstname", "lastName", "email", "timezone", UUID.randomUUID().toString(), User.Source.UNKNOWN); //AccountVO(String accountName, long domainId, String networkDomain, short type, int regionId) - doReturn(VirtualMachine.State.Running).when(_vmInstance).getState(); + lenient().doReturn(VirtualMachine.State.Running).when(_vmInstance).getState(); CallContext.register(user, account); try { @@ -521,18 +523,18 @@ public void testScaleVMF2() throws Exception { serviceOfferingIdField.setAccessible(true); serviceOfferingIdField.set(cmd, 1L); - when(_vmInstanceDao.findById(anyLong())).thenReturn(_vmInstance); - doReturn(Hypervisor.HypervisorType.XenServer).when(_vmInstance).getHypervisorType(); + lenient().when(_vmInstanceDao.findById(anyLong())).thenReturn(_vmInstance); + lenient().doReturn(Hypervisor.HypervisorType.XenServer).when(_vmInstance).getHypervisorType(); - doReturn(VirtualMachine.State.Running).when(_vmInstance).getState(); + lenient().doReturn(VirtualMachine.State.Running).when(_vmInstance).getState(); - doNothing().when(_accountMgr).checkAccess(_account, null, true, _templateMock); + lenient().doNothing().when(_accountMgr).checkAccess(_account, null, true, _templateMock); - doNothing().when(_itMgr).checkIfCanUpgrade(_vmMock, _offeringVo); + lenient().doNothing().when(_itMgr).checkIfCanUpgrade(_vmMock, _offeringVo); ServiceOffering so1 = getSvcoffering(512); - when(_offeringDao.findById(anyLong())).thenReturn((ServiceOfferingVO)so1); - when(_offeringDao.findByIdIncludingRemoved(anyLong(), anyLong())).thenReturn((ServiceOfferingVO)so1); + lenient().when(_offeringDao.findById(anyLong())).thenReturn((ServiceOfferingVO)so1); + lenient().when(_offeringDao.findByIdIncludingRemoved(anyLong(), anyLong())).thenReturn((ServiceOfferingVO)so1); Account account = new AccountVO("testaccount", 1L, "networkdomain", (short)0, UUID.randomUUID().toString()); UserVO user = new UserVO(1, "testuser", "password", "firstname", "lastName", "email", "timezone", UUID.randomUUID().toString(), User.Source.UNKNOWN); @@ -685,6 +687,7 @@ public void testMoveVmToUser1() throws Exception { // Test Move VM b/w accounts where caller doesn't have access to the old or new account @Test(expected = PermissionDeniedException.class) public void testMoveVmToUser2() throws Exception { + AssignVMCmd cmd = new AssignVMCmd(); Class _class = cmd.getClass(); @@ -704,8 +707,11 @@ public void testMoveVmToUser2() throws Exception { Account caller = new AccountVO("testaccount", 1, "networkdomain", (short)1, UUID.randomUUID().toString()); UserVO user = new UserVO(1, "testuser", "password", "firstname", "lastName", "email", "timezone", UUID.randomUUID().toString(), User.Source.UNKNOWN); - Account oldAccount = new AccountVO("testaccount", 1, "networkdomain", (short)0, UUID.randomUUID().toString()); - Account newAccount = new AccountVO("testaccount", 1, "networkdomain", (short)1, UUID.randomUUID().toString()); + AccountVO oldAccount = new AccountVO("testaccount", 1, "networkdomain", (short)0, UUID.randomUUID().toString()); + oldAccount.setId(1L); + + AccountVO newAccount = new AccountVO("testaccount", 1, "networkdomain", (short)1, UUID.randomUUID().toString()); + newAccount.setId(2L); UserVmVO vm = new UserVmVO(10L, "test", "test", 1L, HypervisorType.Any, 1L, false, false, 1L, 1L, 1, 5L, "test", "test", 1L); vm.setState(VirtualMachine.State.Stopped); @@ -713,9 +719,9 @@ public void testMoveVmToUser2() throws Exception { when(_accountService.getActiveAccountById(anyLong())).thenReturn(oldAccount); - when(_accountMgr.finalizeOwner(any(Account.class), anyString(), anyLong(), anyLong())).thenReturn(newAccount); + when(_accountMgr.finalizeOwner(nullable(Account.class), nullable(String.class), nullable(Long.class), nullable(Long.class))).thenReturn(newAccount); - doThrow(new PermissionDeniedException("Access check failed")).when(_accountMgr).checkAccess(any(Account.class), any(AccessType.class), any(Boolean.class), any(ControlledEntity.class)); + doThrow(new PermissionDeniedException("Access check failed")).when(_accountMgr).checkAccess(nullable(Account.class), nullable(AccessType.class), nullable(Boolean.class), nullable(ControlledEntity.class)); CallContext.register(user, caller); @@ -753,7 +759,7 @@ public void testUpdateVmNicIpSuccess1() throws Exception { services.add(Service.Dhcp); when(_networkModel.listNetworkOfferingServices(anyLong())).thenReturn(services); when(_vmMock.getState()).thenReturn(State.Stopped); - doNothing().when(_accountMgr).checkAccess(_account, null, true, _vmMock); + lenient().doNothing().when(_accountMgr).checkAccess(_account, null, true, _vmMock); when(_accountDao.findByIdIncludingRemoved(anyLong())).thenReturn(_accountMock); when(_networkMock.getState()).thenReturn(Network.State.Implemented); @@ -800,8 +806,8 @@ public void testUpdateVmNicIpSuccess2() throws Exception { List services = new ArrayList(); when(_networkModel.listNetworkOfferingServices(anyLong())).thenReturn(services); - when(_vmMock.getState()).thenReturn(State.Running); - doNothing().when(_accountMgr).checkAccess(_account, null, true, _vmMock); + lenient().when(_vmMock.getState()).thenReturn(State.Running); + lenient().doNothing().when(_accountMgr).checkAccess(_account, null, true, _vmMock); when(_accountDao.findByIdIncludingRemoved(anyLong())).thenReturn(_accountMock); when(_networkMock.getState()).thenReturn(Network.State.Implemented); @@ -817,8 +823,8 @@ public void testUpdateVmNicIpSuccess2() throws Exception { when(vlan.getVlanGateway()).thenReturn("10.10.10.1"); when(vlan.getVlanNetmask()).thenReturn("255.255.255.0"); - when(_ipAddrMgr.allocatePublicIpForGuestNic(Mockito.eq(_networkMock), anyLong(), Mockito.eq(_accountMock), anyString())).thenReturn("10.10.10.10"); - when(_ipAddressDao.findByIpAndSourceNetworkId(anyLong(), anyString())).thenReturn(null); + when(_ipAddrMgr.allocatePublicIpForGuestNic(Mockito.eq(_networkMock), nullable(Long.class), Mockito.eq(_accountMock), anyString())).thenReturn("10.10.10.10"); + lenient().when(_ipAddressDao.findByIpAndSourceNetworkId(anyLong(), anyString())).thenReturn(null); when(_nicDao.persist(any(NicVO.class))).thenReturn(nic); when(_ipAddressDao.findByIpAndDcId(anyLong(), anyString())).thenReturn(newIp); when(_vlanDao.findById(anyLong())).thenReturn(vlan); @@ -897,7 +903,7 @@ public void testUpdateVmNicIpFailure2() throws Exception { services.add(Service.Dhcp); when(_networkModel.listNetworkOfferingServices(anyLong())).thenReturn(services); when(_vmMock.getState()).thenReturn(State.Stopped); - doNothing().when(_accountMgr).checkAccess(_account, null, true, _vmMock); + lenient().doNothing().when(_accountMgr).checkAccess(_account, null, true, _vmMock); when(_accountDao.findByIdIncludingRemoved(anyLong())).thenReturn(_accountMock); when(_networkMock.getState()).thenReturn(Network.State.Implemented); @@ -944,7 +950,7 @@ public void testUpdateVmNicIpFailure3() throws Exception { services.add(Service.Dhcp); when(_networkModel.listNetworkOfferingServices(anyLong())).thenReturn(services); when(_vmMock.getState()).thenReturn(State.Stopped); - doNothing().when(_accountMgr).checkAccess(_account, null, true, _vmMock); + lenient().doNothing().when(_accountMgr).checkAccess(_account, null, true, _vmMock); when(_accountDao.findByIdIncludingRemoved(anyLong())).thenReturn(_accountMock); when(_networkMock.getState()).thenReturn(Network.State.Implemented); @@ -953,7 +959,7 @@ public void testUpdateVmNicIpFailure3() throws Exception { when(_dcDao.findById(anyLong())).thenReturn(_dcMock); when(_dcMock.getNetworkType()).thenReturn(NetworkType.Advanced); - when(_ipAddrMgr.allocatePublicIpForGuestNic(Mockito.eq(_networkMock), anyLong(), Mockito.eq(_accountMock), anyString())).thenReturn(null); + lenient().when(_ipAddrMgr.allocatePublicIpForGuestNic(Mockito.eq(_networkMock), anyLong(), Mockito.eq(_accountMock), anyString())).thenReturn(null); Account caller = new AccountVO("testaccount", 1, "networkdomain", (short)0, UUID.randomUUID().toString()); UserVO user = new UserVO(1, "testuser", "password", "firstname", "lastName", "email", "timezone", UUID.randomUUID().toString(), User.Source.UNKNOWN); @@ -981,14 +987,14 @@ public void testApplyUserDataInNetworkWithoutUserDataSupport() throws Exception @Test(expected = CloudRuntimeException.class) public void testApplyUserDataInNetworkWithoutElement() throws Exception { UserVm userVm = mock(UserVm.class); - when(userVm.getId()).thenReturn(1L); + lenient().when(userVm.getId()).thenReturn(1L); when(_nicMock.getNetworkId()).thenReturn(2L); when(_networkMock.getNetworkOfferingId()).thenReturn(3L); when(_networkDao.findById(2L)).thenReturn(_networkMock); UserDataServiceProvider userDataServiceProvider = mock(UserDataServiceProvider.class); - when(userDataServiceProvider.saveUserData(any(Network.class), any(NicProfile.class), any(VirtualMachineProfile.class))).thenReturn(true); + lenient().when(userDataServiceProvider.saveUserData(any(Network.class), any(NicProfile.class), any(VirtualMachineProfile.class))).thenReturn(true); // Userdata support, but no implementing element when(_networkModel.areServicesSupportedByNetworkOffering(3L, Service.UserData)).thenReturn(true); @@ -998,7 +1004,7 @@ public void testApplyUserDataInNetworkWithoutElement() throws Exception { @Test public void testApplyUserDataSuccessful() throws Exception { UserVm userVm = mock(UserVm.class); - when(userVm.getId()).thenReturn(1L); + lenient().when(userVm.getId()).thenReturn(1L); when(_nicMock.getNetworkId()).thenReturn(2L); when(_networkMock.getNetworkOfferingId()).thenReturn(3L); diff --git a/server/src/test/java/com/cloud/vpc/MockNetworkManagerImpl.java b/server/src/test/java/com/cloud/vpc/MockNetworkManagerImpl.java index 09fd997f6184..40a37a08e2d7 100644 --- a/server/src/test/java/com/cloud/vpc/MockNetworkManagerImpl.java +++ b/server/src/test/java/com/cloud/vpc/MockNetworkManagerImpl.java @@ -213,11 +213,16 @@ public boolean deleteNetwork(long networkId, boolean forced) { return false; } + @Override + public boolean restartNetwork(Long networkId, boolean cleanup, boolean makeRedundant, User user) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException { + return false; + } + /* (non-Javadoc) * @see com.cloud.network.NetworkService#restartNetwork(com.cloud.api.commands.RestartNetworkCmd, boolean) */ @Override - public boolean restartNetwork(RestartNetworkCmd cmd, boolean cleanup, boolean makeRedundant) throws ConcurrentOperationException, ResourceUnavailableException, + public boolean restartNetwork(RestartNetworkCmd cmd) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException { // TODO Auto-generated method stub return false; @@ -636,7 +641,7 @@ public boolean destroyNetwork(long networkId, ReservationContext context, boolea @Override public Network createGuestNetwork(long networkOfferingId, String name, String displayText, String gateway, String cidr, String vlanId, boolean bypassVlanOverlapCheck, String networkDomain, Account owner, Long domainId, PhysicalNetwork physicalNetwork, long zoneId, ACLType aclType, Boolean subdomainAccess, Long vpcId, String gatewayv6, - String cidrv6, Boolean displayNetworkEnabled, String isolatedPvlan, String externalId) throws ConcurrentOperationException, InsufficientCapacityException, + String cidrv6, Boolean displayNetworkEnabled, String isolatedPvlan, Network.PVlanType isolatedPvlanType, String externalId) throws ConcurrentOperationException, InsufficientCapacityException, ResourceAllocationException { // TODO Auto-generated method stub return null; @@ -973,4 +978,9 @@ public boolean releasePodIp(ReleasePodIpCmdByAdmin ip) throws CloudRuntimeExcept public AcquirePodIpCmdResponse allocatePodIp(Account account, String zoneId, String podId) throws ResourceAllocationException, ConcurrentOperationException { return null; } + + @Override + public Pair importNic(String macAddress, int deviceId, Network network, Boolean isDefaultNic, VirtualMachine vm, IpAddresses ipAddresses) { + return null; + } } diff --git a/server/src/test/java/com/cloud/vpc/MockVpcVirtualNetworkApplianceManager.java b/server/src/test/java/com/cloud/vpc/MockVpcVirtualNetworkApplianceManager.java index a85d039cd13f..45bf4c1763b5 100644 --- a/server/src/test/java/com/cloud/vpc/MockVpcVirtualNetworkApplianceManager.java +++ b/server/src/test/java/com/cloud/vpc/MockVpcVirtualNetworkApplianceManager.java @@ -248,6 +248,11 @@ public List upgradeRouterTemplate(final UpgradeRouterTemplateCmd cmd) { return null; //To change body of implemented methods use File | Settings | File Templates. } + @Override + public boolean performRouterHealthChecks(long routerId) { + return false; + } + @Override public boolean prepareAggregatedExecution(final Network network, final List routers) throws AgentUnavailableException { return true; //To change body of implemented methods use File | Settings | File Templates. @@ -269,4 +274,10 @@ public boolean stopRemoteAccessVpn(final RemoteAccessVpn vpn, final VirtualRoute // TODO Auto-generated method stub return false; } + + @Override + public boolean startSite2SiteVpn(DomainRouterVO router) throws ResourceUnavailableException { + // TODO Auto-generated method stub + return false; + } } \ No newline at end of file diff --git a/server/src/test/java/com/cloud/vpc/NetworkACLManagerTest.java b/server/src/test/java/com/cloud/vpc/NetworkACLManagerTest.java index ca1ddc62b528..b1d64554759c 100644 --- a/server/src/test/java/com/cloud/vpc/NetworkACLManagerTest.java +++ b/server/src/test/java/com/cloud/vpc/NetworkACLManagerTest.java @@ -15,6 +15,14 @@ package com.cloud.vpc; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyList; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.nullable; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + import java.io.IOException; import java.util.ArrayList; import java.util.List; @@ -47,6 +55,7 @@ import com.cloud.network.Network; import com.cloud.network.NetworkModel; import com.cloud.network.dao.NetworkDao; +import com.cloud.network.dao.NetworkServiceMapDao; import com.cloud.network.dao.NetworkVO; import com.cloud.network.element.NetworkACLServiceProvider; import com.cloud.network.vpc.NetworkACLItem; @@ -134,8 +143,8 @@ public void testCreateACL() throws Exception { @SuppressWarnings("unchecked") public void testApplyACL() throws Exception { final NetworkVO network = Mockito.mock(NetworkVO.class); - Mockito.when(_networkDao.findById(Matchers.anyLong())).thenReturn(network); - Mockito.when(_networkModel.isProviderSupportServiceInNetwork(Matchers.anyLong(), Matchers.any(Network.Service.class), Matchers.any(Network.Provider.class))).thenReturn(true); + Mockito.when(_networkDao.findById(anyLong())).thenReturn(network); + Mockito.when(_networkModel.isProviderSupportServiceInNetwork(anyLong(), Matchers.any(Network.Service.class), Matchers.any(Network.Provider.class))).thenReturn(true); Mockito.when(_networkAclElements.get(0).applyNetworkACLs(Matchers.any(Network.class), Matchers.anyList())).thenReturn(true); assertTrue(_aclMgr.applyACLToNetwork(1L)); } @@ -161,16 +170,20 @@ public void driveTestApplyNetworkACL(final boolean result, final boolean applyNe final NetworkVO network = Mockito.mock(NetworkVO.class); final List networks = new ArrayList(); networks.add(network); - Mockito.when(_networkDao.listByAclId(Matchers.anyLong())).thenReturn(networks); - Mockito.when(_networkDao.findById(Matchers.anyLong())).thenReturn(network); - Mockito.when(_networkModel.isProviderSupportServiceInNetwork(Matchers.anyLong(), Matchers.any(Network.Service.class), Matchers.any(Network.Provider.class))).thenReturn(true); - Mockito.when(_networkAclElements.get(0).applyNetworkACLs(Matchers.any(Network.class), Matchers.anyList())).thenReturn(applyNetworkACLs); + + NetworkServiceMapDao ntwkSrvcDao = mock(NetworkServiceMapDao.class); + when(ntwkSrvcDao.canProviderSupportServiceInNetwork(anyLong(), eq(Network.Service.NetworkACL), nullable(Network.Provider.class))).thenReturn(true); + Mockito.when(_networkDao.listByAclId(anyLong())).thenReturn(networks); + Mockito.when(_networkDao.findById(anyLong())).thenReturn(network); + Mockito.when(_networkModel.isProviderSupportServiceInNetwork(anyLong(), any(Network.Service.class), any(Network.Provider.class))).thenReturn(true); + Mockito.when(_networkAclElements.get(0).getProvider()).thenReturn(Mockito.mock(Network.Provider.class)); + Mockito.when(_networkAclElements.get(0).applyNetworkACLs(any(Network.class), anyList())).thenReturn(applyNetworkACLs); // Make sure it applies ACL to private gateway final List vpcGateways = new ArrayList(); final VpcGatewayVO vpcGateway = Mockito.mock(VpcGatewayVO.class); final PrivateGateway privateGateway = Mockito.mock(PrivateGateway.class); - Mockito.when(_vpcSvc.getVpcPrivateGateway(Mockito.anyLong())).thenReturn(privateGateway); + Mockito.when(_vpcSvc.getVpcPrivateGateway(anyLong())).thenReturn(privateGateway); vpcGateways.add(vpcGateway); Mockito.when(_vpcGatewayDao.listByAclIdAndType(aclId, VpcGateway.Type.Private)).thenReturn(vpcGateways); @@ -213,7 +226,7 @@ public void driveTestApplyNetworkACL(final boolean result, final boolean applyNe @Test public void testRevokeACLItem() throws Exception { - Mockito.when(_networkACLItemDao.findById(Matchers.anyLong())).thenReturn(aclItem); + Mockito.when(_networkACLItemDao.findById(anyLong())).thenReturn(aclItem); assertTrue(_aclMgr.revokeNetworkACLItem(1L)); } @@ -221,12 +234,12 @@ public void testRevokeACLItem() throws Exception { public void deleteNonEmptyACL() throws Exception { final List aclItems = new ArrayList(); aclItems.add(aclItem); - Mockito.when(_networkACLItemDao.listByACL(Matchers.anyLong())).thenReturn(aclItems); + Mockito.when(_networkACLItemDao.listByACL(anyLong())).thenReturn(aclItems); Mockito.when(acl.getId()).thenReturn(3l); - Mockito.when(_networkACLItemDao.findById(Matchers.anyLong())).thenReturn(aclItem); + Mockito.when(_networkACLItemDao.findById(anyLong())).thenReturn(aclItem); Mockito.when(aclItem.getState()).thenReturn(State.Add); Mockito.when(aclItem.getId()).thenReturn(3l); - Mockito.when(_networkACLDao.remove(Matchers.anyLong())).thenReturn(true); + Mockito.when(_networkACLDao.remove(anyLong())).thenReturn(true); final boolean result = _aclMgr.deleteNetworkACL(acl); diff --git a/server/src/test/java/com/cloud/vpc/VpcApiUnitTest.java b/server/src/test/java/com/cloud/vpc/VpcApiUnitTest.java index 7043f2265d32..8899a045329e 100644 --- a/server/src/test/java/com/cloud/vpc/VpcApiUnitTest.java +++ b/server/src/test/java/com/cloud/vpc/VpcApiUnitTest.java @@ -21,11 +21,10 @@ import javax.inject.Inject; -import junit.framework.TestCase; - import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import com.cloud.exception.InvalidParameterValueException; @@ -36,8 +35,10 @@ import com.cloud.user.AccountVO; import com.cloud.utils.component.ComponentContext; +import junit.framework.TestCase; + @RunWith(SpringJUnit4ClassRunner.class) -//@ContextConfiguration(locations = "classpath:/VpcTestContext.xml") +@ContextConfiguration(locations = "classpath:/VpcTestContext.xml") public class VpcApiUnitTest extends TestCase { @Inject VpcManagerImpl _vpcService = null; diff --git a/server/src/test/java/com/cloud/vpc/dao/MockNetworkDaoImpl.java b/server/src/test/java/com/cloud/vpc/dao/MockNetworkDaoImpl.java index 11f3f81f357d..89bc6256b4a7 100644 --- a/server/src/test/java/com/cloud/vpc/dao/MockNetworkDaoImpl.java +++ b/server/src/test/java/com/cloud/vpc/dao/MockNetworkDaoImpl.java @@ -235,4 +235,14 @@ public int getNonSystemNetworkCountByVpcId(final long vpcId) { public List listNetworkVO(List idset) { return null; } -} \ No newline at end of file + + @Override + public List listByAccountIdNetworkName(final long accountId, final String name) { + return null; + } + + @Override + public List listByPhysicalNetworkPvlan(long physicalNetworkId, String broadcastUri, Network.PVlanType pVlanType) { + return null; + } +} diff --git a/server/src/test/java/org/apache/cloudstack/acl/RoleManagerImplTest.java b/server/src/test/java/org/apache/cloudstack/acl/RoleManagerImplTest.java index bc50f3408987..e7ce1acec3e5 100644 --- a/server/src/test/java/org/apache/cloudstack/acl/RoleManagerImplTest.java +++ b/server/src/test/java/org/apache/cloudstack/acl/RoleManagerImplTest.java @@ -102,7 +102,7 @@ public void findRoleTestNotRootAdminAndNotRoleAdminType() { @Test public void findRoleTestRootAdminAndNotRoleAdminType() { - Mockito.doReturn(RoleType.DomainAdmin).when(roleVoMock).getRoleType(); + Mockito.lenient().doReturn(RoleType.DomainAdmin).when(roleVoMock).getRoleType(); Mockito.doReturn(roleVoMock).when(roleDaoMock).findById(roleMockId); Mockito.doReturn(true).when(accountManagerMock).isRootAdmin(accountMockId); @@ -115,7 +115,7 @@ public void findRoleTestRootAdminAndNotRoleAdminType() { @Test public void findRoleTestRootAdminAndRoleAdminType() { - Mockito.doReturn(RoleType.Admin).when(roleVoMock).getRoleType(); + Mockito.lenient().doReturn(RoleType.Admin).when(roleVoMock).getRoleType(); Mockito.doReturn(roleVoMock).when(roleDaoMock).findById(roleMockId); Mockito.doReturn(true).when(accountManagerMock).isRootAdmin(accountMockId); @@ -258,8 +258,8 @@ public void findRolesByTypeTestAdminRoleRootAdminUser() { @Test public void findRolesByTypeTestNonAdminRoleRootAdminUser() { - Mockito.doReturn(accountMock).when(roleManagerImpl).getCurrentAccount(); - Mockito.doReturn(true).when(accountManagerMock).isRootAdmin(accountMockId); + Mockito.lenient().doReturn(accountMock).when(roleManagerImpl).getCurrentAccount(); + Mockito.lenient().doReturn(true).when(accountManagerMock).isRootAdmin(accountMockId); List roles = new ArrayList<>(); roles.add(Mockito.mock(Role.class)); diff --git a/server/src/test/java/org/apache/cloudstack/affinity/AffinityApiUnitTest.java b/server/src/test/java/org/apache/cloudstack/affinity/AffinityApiUnitTest.java index 354054a41151..0d3664833005 100644 --- a/server/src/test/java/org/apache/cloudstack/affinity/AffinityApiUnitTest.java +++ b/server/src/test/java/org/apache/cloudstack/affinity/AffinityApiUnitTest.java @@ -17,9 +17,10 @@ package org.apache.cloudstack.affinity; import static org.junit.Assert.assertNotNull; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.Matchers.anyBoolean; import static org.mockito.Matchers.anyLong; -import static org.mockito.Matchers.anyObject; import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.when; @@ -32,11 +33,13 @@ import javax.inject.Inject; import javax.naming.ConfigurationException; -import com.cloud.utils.db.EntityManager; -import com.cloud.event.ActionEventUtils; -import com.cloud.user.User; +import org.apache.cloudstack.acl.ControlledEntity; import org.apache.cloudstack.affinity.dao.AffinityGroupDao; +import org.apache.cloudstack.affinity.dao.AffinityGroupDomainMapDao; import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao; +import org.apache.cloudstack.context.CallContext; +import org.apache.cloudstack.framework.config.dao.ConfigurationDao; +import org.apache.cloudstack.framework.messagebus.MessageBus; import org.apache.cloudstack.test.utils.SpringUtils; import org.junit.After; import org.junit.Before; @@ -57,32 +60,29 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.support.AnnotationConfigContextLoader; -import org.apache.cloudstack.acl.ControlledEntity; -import org.apache.cloudstack.affinity.dao.AffinityGroupDomainMapDao; -import org.apache.cloudstack.context.CallContext; -import org.apache.cloudstack.framework.config.dao.ConfigurationDao; -import org.apache.cloudstack.framework.messagebus.MessageBus; - import com.cloud.dc.dao.DedicatedResourceDao; import com.cloud.domain.dao.DomainDao; +import com.cloud.event.ActionEventUtils; import com.cloud.event.EventVO; import com.cloud.event.dao.EventDao; import com.cloud.exception.InvalidParameterValueException; import com.cloud.exception.ResourceInUseException; import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.projects.dao.ProjectDao; import com.cloud.user.Account; import com.cloud.user.AccountManager; import com.cloud.user.AccountService; import com.cloud.user.AccountVO; import com.cloud.user.DomainManager; +import com.cloud.user.User; import com.cloud.user.UserVO; import com.cloud.user.dao.AccountDao; import com.cloud.user.dao.UserDao; import com.cloud.utils.component.ComponentContext; +import com.cloud.utils.db.EntityManager; import com.cloud.vm.UserVmVO; import com.cloud.vm.VirtualMachine; import com.cloud.vm.dao.UserVmDao; -import com.cloud.projects.dao.ProjectDao; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(loader = AnnotationConfigContextLoader.class) @@ -142,7 +142,7 @@ public void setUp() { CallContext.register(user, acct); - when(_acctMgr.finalizeOwner((Account)anyObject(), anyString(), anyLong(), anyLong())).thenReturn(acct); + when(_acctMgr.finalizeOwner(any(Account.class), anyString(), anyLong(), nullable(Long.class))).thenReturn(acct); when(_processor.getType()).thenReturn("mock"); when(_accountDao.findByIdIncludingRemoved(0L)).thenReturn(acct); diff --git a/server/src/test/java/org/apache/cloudstack/affinity/AffinityGroupServiceImplTest.java b/server/src/test/java/org/apache/cloudstack/affinity/AffinityGroupServiceImplTest.java index 6f45b908a437..8aa4aa8277ec 100644 --- a/server/src/test/java/org/apache/cloudstack/affinity/AffinityGroupServiceImplTest.java +++ b/server/src/test/java/org/apache/cloudstack/affinity/AffinityGroupServiceImplTest.java @@ -17,6 +17,8 @@ package org.apache.cloudstack.affinity; import static org.junit.Assert.assertNotNull; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.Matchers.anyBoolean; import static org.mockito.Matchers.anyLong; import static org.mockito.Matchers.anyObject; @@ -42,6 +44,7 @@ import org.apache.cloudstack.framework.messagebus.MessageBus; import org.apache.cloudstack.test.utils.SpringUtils; import org.junit.After; +import org.junit.Assert; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; @@ -84,8 +87,6 @@ import com.cloud.vm.VirtualMachine; import com.cloud.vm.dao.UserVmDao; -import org.junit.Assert; - @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(loader = AnnotationConfigContextLoader.class) public class AffinityGroupServiceImplTest { @@ -152,6 +153,7 @@ public void setUp() { when(_processor.getType()).thenReturn("mock"); when(_accountDao.findByIdIncludingRemoved(0L)).thenReturn(acct); + List affinityProcessors = new ArrayList(); affinityProcessors.add(_processor); _affinityService.setAffinityGroupProcessors(affinityProcessors); @@ -172,7 +174,7 @@ public void tearDown() { @Test public void createAffinityGroupFromCmdTest() { - when(_acctMgr.finalizeOwner((Account)anyObject(), anyString(), anyLong(), anyLong())).thenReturn(acct); + when(_acctMgr.finalizeOwner(any(Account.class), nullable(String.class), anyLong(), nullable(Long.class))).thenReturn(acct); when(_groupDao.isNameInUse(anyLong(), anyLong(), eq(AFFINITY_GROUP_NAME))).thenReturn(false); CreateAffinityGroupCmd mockCreateAffinityGroupCmd = Mockito.mock(CreateAffinityGroupCmd.class); when(mockCreateAffinityGroupCmd.getProjectId()).thenReturn(PROJECT_ID); @@ -185,7 +187,7 @@ public void createAffinityGroupFromCmdTest() { @Test public void createAffinityGroupTest() { - when(_acctMgr.finalizeOwner((Account)anyObject(), anyString(), anyLong(), anyLong())).thenReturn(acct); + when(_acctMgr.finalizeOwner(any(Account.class), anyString(), anyLong(), nullable(Long.class))).thenReturn(acct); when(_groupDao.isNameInUse(anyLong(), anyLong(), eq(AFFINITY_GROUP_NAME))).thenReturn(false); AffinityGroup group = _affinityService.createAffinityGroup(ACCOUNT_NAME, null, DOMAIN_ID, AFFINITY_GROUP_NAME, "mock", "affinity group one"); assertNotNull("Affinity group 'group1' of type 'mock' failed to create ", group); @@ -239,7 +241,7 @@ public void invalidAffinityTypeTest() { @Test(expected = InvalidParameterValueException.class) public void uniqueAffinityNameTest() { - when(_acctMgr.finalizeOwner((Account)anyObject(), anyString(), anyLong(), anyLong())).thenReturn(acct); + when(_acctMgr.finalizeOwner(any(Account.class), anyString(), anyLong(), nullable(Long.class))).thenReturn(acct); when(_groupDao.isNameInUse(anyLong(), anyLong(), eq(AFFINITY_GROUP_NAME))).thenReturn(true); _affinityService.createAffinityGroup(ACCOUNT_NAME, null, DOMAIN_ID, AFFINITY_GROUP_NAME, "mock", "affinity group two"); } diff --git a/server/src/test/java/org/apache/cloudstack/agent/lb/IndirectAgentLBServiceImplTest.java b/server/src/test/java/org/apache/cloudstack/agent/lb/IndirectAgentLBServiceImplTest.java index 79b5421f9af7..98c2af5b7764 100644 --- a/server/src/test/java/org/apache/cloudstack/agent/lb/IndirectAgentLBServiceImplTest.java +++ b/server/src/test/java/org/apache/cloudstack/agent/lb/IndirectAgentLBServiceImplTest.java @@ -95,7 +95,6 @@ private void configureMocks() throws NoSuchFieldException, IllegalAccessExceptio id++; } addField(agentMSLB, "hostDao", hostDao); - addField(agentMSLB, "messageBus", messageBus); addField(agentMSLB, "agentManager", agentManager); when(hostDao.listAll()).thenReturn(Arrays.asList(host4, host2, host1, host3)); @@ -205,4 +204,4 @@ public void testGetHostsPerZoneNullHosts() { when(hostDao.listAll()).thenReturn(null); Assert.assertTrue(agentMSLB.getOrderedHostIdList(DC_2_ID).size() == 0); } -} \ No newline at end of file +} diff --git a/server/src/test/java/org/apache/cloudstack/ca/CABackgroundTaskTest.java b/server/src/test/java/org/apache/cloudstack/ca/CABackgroundTaskTest.java index 564bbe36f6dc..063ff343ea23 100644 --- a/server/src/test/java/org/apache/cloudstack/ca/CABackgroundTaskTest.java +++ b/server/src/test/java/org/apache/cloudstack/ca/CABackgroundTaskTest.java @@ -20,6 +20,9 @@ package org.apache.cloudstack.ca; import static org.apache.cloudstack.ca.CAManager.AutomaticCertRenewal; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.nullable; import java.lang.reflect.Field; import java.security.KeyPair; @@ -118,7 +121,7 @@ public void testAutoRenewalEnabledWithNoExceptionsOnProvisioning() throws Except @Test public void testAutoRenewalEnabledWithExceptionsOnProvisioning() throws Exception { overrideDefaultConfigValue(AutomaticCertRenewal, "_defaultValue", "true"); - Mockito.when(caManager.provisionCertificate(Mockito.any(Host.class), Mockito.anyBoolean(), Mockito.anyString())).thenThrow(new CloudRuntimeException("some error")); + Mockito.when(caManager.provisionCertificate(any(Host.class), anyBoolean(), nullable(String.class))).thenThrow(new CloudRuntimeException("some error")); host.setManagementServerId(ManagementServerNode.getManagementServerId()); certMap.put(hostIp, expiredCertificate); Assert.assertTrue(certMap.size() == 1); @@ -134,12 +137,12 @@ public void testAutoRenewalDisabled() throws Exception { Assert.assertTrue(certMap.size() == 1); // First round task.runInContext(); - Mockito.verify(caManager, Mockito.times(0)).provisionCertificate(Mockito.any(Host.class), Mockito.anyBoolean(), Mockito.anyString()); + Mockito.verify(caManager, Mockito.times(0)).provisionCertificate(Mockito.any(Host.class), anyBoolean(), Mockito.anyString()); Mockito.verify(caManager, Mockito.times(1)).sendAlert(Mockito.any(Host.class), Mockito.anyString(), Mockito.anyString()); Mockito.reset(caManager); // Second round task.runInContext(); - Mockito.verify(caManager, Mockito.times(0)).provisionCertificate(Mockito.any(Host.class), Mockito.anyBoolean(), Mockito.anyString()); + Mockito.verify(caManager, Mockito.times(0)).provisionCertificate(Mockito.any(Host.class), anyBoolean(), Mockito.anyString()); Mockito.verify(caManager, Mockito.times(0)).sendAlert(Mockito.any(Host.class), Mockito.anyString(), Mockito.anyString()); } diff --git a/server/src/test/java/org/apache/cloudstack/ca/CAManagerImplTest.java b/server/src/test/java/org/apache/cloudstack/ca/CAManagerImplTest.java index 64cbf205812a..aff04dc712bd 100644 --- a/server/src/test/java/org/apache/cloudstack/ca/CAManagerImplTest.java +++ b/server/src/test/java/org/apache/cloudstack/ca/CAManagerImplTest.java @@ -19,11 +19,19 @@ package org.apache.cloudstack.ca; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyList; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.nullable; + import java.lang.reflect.Field; import java.math.BigInteger; import java.security.KeyPair; import java.security.cert.X509Certificate; import java.util.Collections; +import java.util.List; import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.framework.ca.CAProvider; @@ -36,10 +44,9 @@ import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.Mockito; -import org.mockito.runners.MockitoJUnitRunner; +import org.mockito.junit.MockitoJUnitRunner; import com.cloud.agent.AgentManager; -import com.cloud.agent.api.Answer; import com.cloud.certificate.CrlVO; import com.cloud.certificate.dao.CrlDao; import com.cloud.host.Host; @@ -92,17 +99,17 @@ public void testIssueCertificateThrowsException() throws Exception { @Test public void testIssueCertificate() throws Exception { caManager.issueCertificate(null, Collections.singletonList("domain.example"), null, 1, null); - Mockito.verify(caProvider, Mockito.times(1)).issueCertificate(Mockito.anyList(), Mockito.anyList(), Mockito.anyInt()); - Mockito.verify(caProvider, Mockito.times(0)).issueCertificate(Mockito.anyString(), Mockito.anyList(), Mockito.anyList(), Mockito.anyInt()); + Mockito.verify(caProvider, Mockito.times(1)).issueCertificate(anyList(), nullable(List.class), anyInt()); + Mockito.verify(caProvider, Mockito.times(0)).issueCertificate(anyString(), anyList(), anyList(), anyInt()); } @Test public void testRevokeCertificate() throws Exception { final CrlVO crl = new CrlVO(CertUtils.generateRandomBigInt(), "some.domain", "some-uuid"); - Mockito.when(crlDao.revokeCertificate(Mockito.any(BigInteger.class), Mockito.anyString())).thenReturn(crl); - Mockito.when(caProvider.revokeCertificate(Mockito.any(BigInteger.class), Mockito.anyString())).thenReturn(true); + Mockito.when(crlDao.revokeCertificate(Mockito.any(BigInteger.class), anyString())).thenReturn(crl); + Mockito.when(caProvider.revokeCertificate(Mockito.any(BigInteger.class), anyString())).thenReturn(true); Assert.assertTrue(caManager.revokeCertificate(crl.getCertSerial(), crl.getCertCn(), null)); - Mockito.verify(caProvider, Mockito.times(1)).revokeCertificate(Mockito.any(BigInteger.class), Mockito.anyString()); + Mockito.verify(caProvider, Mockito.times(1)).revokeCertificate(Mockito.any(BigInteger.class), anyString()); } @Test @@ -111,11 +118,13 @@ public void testProvisionCertificate() throws Exception { Mockito.when(host.getPrivateIpAddress()).thenReturn("1.2.3.4"); final KeyPair keyPair = CertUtils.generateRandomKeyPair(1024); final X509Certificate certificate = CertUtils.generateV3Certificate(null, keyPair, keyPair.getPublic(), "CN=ca", "SHA256withRSA", 365, null, null); - Mockito.when(caProvider.issueCertificate(Mockito.anyString(), Mockito.anyList(), Mockito.anyList(), Mockito.anyInt())).thenReturn(new Certificate(certificate, null, Collections.singletonList(certificate))); - Mockito.when(agentManager.send(Mockito.anyLong(), Mockito.any(SetupKeyStoreCommand.class))).thenReturn(new SetupKeystoreAnswer("someCsr")); + Mockito.when(caProvider.issueCertificate(anyString(), anyList(), anyList(), anyInt())).thenReturn(new Certificate(certificate, null, Collections.singletonList(certificate))); + Mockito.when(agentManager.send(anyLong(), any(SetupCertificateCommand.class))).thenReturn(new SetupCertificateAnswer(true)); + Mockito.when(agentManager.send(anyLong(), any(SetupKeyStoreCommand.class))).thenReturn(new SetupKeystoreAnswer("someCsr")); Mockito.doNothing().when(agentManager).reconnect(Mockito.anyLong()); Assert.assertTrue(caManager.provisionCertificate(host, true, null)); - Mockito.verify(agentManager, Mockito.times(2)).send(Mockito.anyLong(), Mockito.any(Answer.class)); + Mockito.verify(agentManager, Mockito.times(1)).send(Mockito.anyLong(), any(SetupKeyStoreCommand.class)); + Mockito.verify(agentManager, Mockito.times(1)).send(Mockito.anyLong(), any(SetupCertificateCommand.class)); Mockito.verify(agentManager, Mockito.times(1)).reconnect(Mockito.anyLong()); } } \ No newline at end of file diff --git a/server/src/test/java/org/apache/cloudstack/network/ssl/CertServiceTest.java b/server/src/test/java/org/apache/cloudstack/network/ssl/CertServiceTest.java index 88b0b691d579..a8514f915db0 100644 --- a/server/src/test/java/org/apache/cloudstack/network/ssl/CertServiceTest.java +++ b/server/src/test/java/org/apache/cloudstack/network/ssl/CertServiceTest.java @@ -16,6 +16,32 @@ // under the License. package org.apache.cloudstack.network.ssl; +import static org.apache.commons.io.FileUtils.readFileToString; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.nullable; +import static org.mockito.Mockito.when; + +import java.io.File; +import java.io.IOException; +import java.lang.reflect.Field; +import java.net.URLDecoder; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +import org.apache.cloudstack.api.command.user.loadbalancer.DeleteSslCertCmd; +import org.apache.cloudstack.api.command.user.loadbalancer.UploadSslCertCmd; +import org.apache.cloudstack.context.CallContext; +import org.junit.After; +import org.junit.Assert; +import org.junit.Assume; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Matchers; +import org.mockito.Mockito; + import com.cloud.domain.DomainVO; import com.cloud.domain.dao.DomainDao; import com.cloud.network.dao.LoadBalancerCertMapDao; @@ -31,28 +57,6 @@ import com.cloud.user.dao.AccountDao; import com.cloud.utils.db.EntityManager; import com.cloud.utils.db.TransactionLegacy; -import org.apache.cloudstack.api.command.user.loadbalancer.DeleteSslCertCmd; -import org.apache.cloudstack.api.command.user.loadbalancer.UploadSslCertCmd; -import org.apache.cloudstack.context.CallContext; -import org.junit.After; -import org.junit.Assert; -import org.junit.Assume; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Matchers; -import org.mockito.Mockito; - -import java.io.File; -import java.io.IOException; -import java.lang.reflect.Field; -import java.net.URLDecoder; -import java.nio.charset.Charset; -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; - -import static org.apache.commons.io.FileUtils.readFileToString; -import static org.mockito.Mockito.when; public class CertServiceTest { @@ -108,17 +112,17 @@ public void runUploadSslCertWithCAChain() throws Exception { //setting mock objects certService._accountMgr = Mockito.mock(AccountManager.class); final Account account = new AccountVO("testaccount", 1, "networkdomain", (short)0, UUID.randomUUID().toString()); - when(certService._accountMgr.getAccount(Matchers.anyLong())).thenReturn(account); + when(certService._accountMgr.getAccount(anyLong())).thenReturn(account); certService._domainDao = Mockito.mock(DomainDao.class); final DomainVO domain = new DomainVO("networkdomain", 1L, 1L, "networkdomain"); - when(certService._domainDao.findByIdIncludingRemoved(Matchers.anyLong())).thenReturn(domain); + when(certService._domainDao.findByIdIncludingRemoved(anyLong())).thenReturn(domain); certService._sslCertDao = Mockito.mock(SslCertDao.class); when(certService._sslCertDao.persist(Matchers.any(SslCertVO.class))).thenReturn(new SslCertVO()); certService._accountDao = Mockito.mock(AccountDao.class); - when(certService._accountDao.findByIdIncludingRemoved(Matchers.anyLong())).thenReturn((AccountVO)account); + when(certService._accountDao.findByIdIncludingRemoved(anyLong())).thenReturn((AccountVO)account); //creating the command final UploadSslCertCmd uploadCmd = new UploadSslCertCmdExtn(); @@ -159,17 +163,17 @@ public void runUploadSslCertSelfSignedWithPassword() throws Exception { //setting mock objects certService._accountMgr = Mockito.mock(AccountManager.class); final Account account = new AccountVO("testaccount", 1, "networkdomain", (short)0, UUID.randomUUID().toString()); - when(certService._accountMgr.getAccount(Matchers.anyLong())).thenReturn(account); + when(certService._accountMgr.getAccount(anyLong())).thenReturn(account); certService._domainDao = Mockito.mock(DomainDao.class); final DomainVO domain = new DomainVO("networkdomain", 1L, 1L, "networkdomain"); - when(certService._domainDao.findByIdIncludingRemoved(Matchers.anyLong())).thenReturn(domain); + when(certService._domainDao.findByIdIncludingRemoved(anyLong())).thenReturn(domain); certService._sslCertDao = Mockito.mock(SslCertDao.class); when(certService._sslCertDao.persist(Matchers.any(SslCertVO.class))).thenReturn(new SslCertVO()); certService._accountDao = Mockito.mock(AccountDao.class); - when(certService._accountDao.findByIdIncludingRemoved(Matchers.anyLong())).thenReturn((AccountVO)account); + when(certService._accountDao.findByIdIncludingRemoved(anyLong())).thenReturn((AccountVO)account); //creating the command final UploadSslCertCmd uploadCmd = new UploadSslCertCmdExtn(); @@ -209,17 +213,17 @@ public void runUploadSslCertSelfSignedNoPassword() throws Exception { //setting mock objects certService._accountMgr = Mockito.mock(AccountManager.class); final Account account = new AccountVO("testaccount", 1, "networkdomain", (short)0, UUID.randomUUID().toString()); - when(certService._accountMgr.getAccount(Matchers.anyLong())).thenReturn(account); + when(certService._accountMgr.getAccount(anyLong())).thenReturn(account); certService._domainDao = Mockito.mock(DomainDao.class); final DomainVO domain = new DomainVO("networkdomain", 1L, 1L, "networkdomain"); - when(certService._domainDao.findByIdIncludingRemoved(Matchers.anyLong())).thenReturn(domain); + when(certService._domainDao.findByIdIncludingRemoved(anyLong())).thenReturn(domain); certService._sslCertDao = Mockito.mock(SslCertDao.class); when(certService._sslCertDao.persist(Matchers.any(SslCertVO.class))).thenReturn(new SslCertVO()); certService._accountDao = Mockito.mock(AccountDao.class); - when(certService._accountDao.findByIdIncludingRemoved(Matchers.anyLong())).thenReturn((AccountVO)account); + when(certService._accountDao.findByIdIncludingRemoved(anyLong())).thenReturn((AccountVO)account); //creating the command UploadSslCertCmd uploadCmd = new UploadSslCertCmdExtn(); @@ -256,11 +260,11 @@ public void runUploadSslCertBadChain() throws IOException, IllegalAccessExceptio //setting mock objects certService._accountMgr = Mockito.mock(AccountManager.class); final Account account = new AccountVO("testaccount", 1, "networkdomain", (short)0, UUID.randomUUID().toString()); - when(certService._accountMgr.getAccount(Matchers.anyLong())).thenReturn(account); + when(certService._accountMgr.getAccount(anyLong())).thenReturn(account); certService._domainDao = Mockito.mock(DomainDao.class); final DomainVO domain = new DomainVO("networkdomain", 1L, 1L, "networkdomain"); - when(certService._domainDao.findByIdIncludingRemoved(Matchers.anyLong())).thenReturn(domain); + when(certService._domainDao.findByIdIncludingRemoved(anyLong())).thenReturn(domain); certService._sslCertDao = Mockito.mock(SslCertDao.class); when(certService._sslCertDao.persist(Matchers.any(SslCertVO.class))).thenReturn(new SslCertVO()); @@ -308,11 +312,11 @@ public void runUploadSslCertNoRootCert() throws IOException, IllegalAccessExcept //setting mock objects certService._accountMgr = Mockito.mock(AccountManager.class); final Account account = new AccountVO("testaccount", 1, "networkdomain", (short)0, UUID.randomUUID().toString()); - when(certService._accountMgr.getAccount(Matchers.anyLong())).thenReturn(account); + when(certService._accountMgr.getAccount(anyLong())).thenReturn(account); certService._domainDao = Mockito.mock(DomainDao.class); final DomainVO domain = new DomainVO("networkdomain", 1L, 1L, "networkdomain"); - when(certService._domainDao.findByIdIncludingRemoved(Matchers.anyLong())).thenReturn(domain); + when(certService._domainDao.findByIdIncludingRemoved(anyLong())).thenReturn(domain); certService._sslCertDao = Mockito.mock(SslCertDao.class); when(certService._sslCertDao.persist(Matchers.any(SslCertVO.class))).thenReturn(new SslCertVO()); @@ -358,11 +362,11 @@ public void runUploadSslCertBadPassword() throws IOException, IllegalAccessExcep //setting mock objects certService._accountMgr = Mockito.mock(AccountManager.class); final Account account = new AccountVO("testaccount", 1, "networkdomain", (short)0, UUID.randomUUID().toString()); - when(certService._accountMgr.getAccount(Matchers.anyLong())).thenReturn(account); + when(certService._accountMgr.getAccount(anyLong())).thenReturn(account); certService._domainDao = Mockito.mock(DomainDao.class); final DomainVO domain = new DomainVO("networkdomain", 1L, 1L, "networkdomain"); - when(certService._domainDao.findByIdIncludingRemoved(Matchers.anyLong())).thenReturn(domain); + when(certService._domainDao.findByIdIncludingRemoved(anyLong())).thenReturn(domain); certService._sslCertDao = Mockito.mock(SslCertDao.class); when(certService._sslCertDao.persist(Matchers.any(SslCertVO.class))).thenReturn(new SslCertVO()); @@ -407,11 +411,11 @@ public void runUploadSslCertBadkeyPair() throws IOException, IllegalAccessExcept //setting mock objects certService._accountMgr = Mockito.mock(AccountManager.class); final Account account = new AccountVO("testaccount", 1, "networkdomain", (short)0, UUID.randomUUID().toString()); - when(certService._accountMgr.getAccount(Matchers.anyLong())).thenReturn(account); + when(certService._accountMgr.getAccount(anyLong())).thenReturn(account); certService._domainDao = Mockito.mock(DomainDao.class); final DomainVO domain = new DomainVO("networkdomain", 1L, 1L, "networkdomain"); - when(certService._domainDao.findByIdIncludingRemoved(Matchers.anyLong())).thenReturn(domain); + when(certService._domainDao.findByIdIncludingRemoved(anyLong())).thenReturn(domain); certService._sslCertDao = Mockito.mock(SslCertDao.class); when(certService._sslCertDao.persist(Matchers.any(SslCertVO.class))).thenReturn(new SslCertVO()); @@ -450,11 +454,11 @@ public void runUploadSslCertBadkeyAlgo() throws IOException, IllegalAccessExcept //setting mock objects certService._accountMgr = Mockito.mock(AccountManager.class); final Account account = new AccountVO("testaccount", 1, "networkdomain", (short)0, UUID.randomUUID().toString()); - when(certService._accountMgr.getAccount(Matchers.anyLong())).thenReturn(account); + when(certService._accountMgr.getAccount(anyLong())).thenReturn(account); certService._domainDao = Mockito.mock(DomainDao.class); final DomainVO domain = new DomainVO("networkdomain", 1L, 1L, "networkdomain"); - when(certService._domainDao.findByIdIncludingRemoved(Matchers.anyLong())).thenReturn(domain); + when(certService._domainDao.findByIdIncludingRemoved(anyLong())).thenReturn(domain); certService._sslCertDao = Mockito.mock(SslCertDao.class); when(certService._sslCertDao.persist(Matchers.any(SslCertVO.class))).thenReturn(new SslCertVO()); @@ -495,11 +499,11 @@ public void runUploadSslCertExpiredCert() throws IOException, IllegalAccessExcep //setting mock objects certService._accountMgr = Mockito.mock(AccountManager.class); final Account account = new AccountVO("testaccount", 1, "networkdomain", (short)0, UUID.randomUUID().toString()); - when(certService._accountMgr.getAccount(Matchers.anyLong())).thenReturn(account); + when(certService._accountMgr.getAccount(anyLong())).thenReturn(account); certService._domainDao = Mockito.mock(DomainDao.class); final DomainVO domain = new DomainVO("networkdomain", 1L, 1L, "networkdomain"); - when(certService._domainDao.findByIdIncludingRemoved(Matchers.anyLong())).thenReturn(domain); + when(certService._domainDao.findByIdIncludingRemoved(anyLong())).thenReturn(domain); certService._sslCertDao = Mockito.mock(SslCertDao.class); when(certService._sslCertDao.persist(Matchers.any(SslCertVO.class))).thenReturn(new SslCertVO()); @@ -539,11 +543,11 @@ public void runUploadSslCertNotX509() throws IOException, IllegalAccessException //setting mock objects certService._accountMgr = Mockito.mock(AccountManager.class); final Account account = new AccountVO("testaccount", 1, "networkdomain", (short)0, UUID.randomUUID().toString()); - when(certService._accountMgr.getAccount(Matchers.anyLong())).thenReturn(account); + when(certService._accountMgr.getAccount(anyLong())).thenReturn(account); certService._domainDao = Mockito.mock(DomainDao.class); final DomainVO domain = new DomainVO("networkdomain", 1L, 1L, "networkdomain"); - when(certService._domainDao.findByIdIncludingRemoved(Matchers.anyLong())).thenReturn(domain); + when(certService._domainDao.findByIdIncludingRemoved(anyLong())).thenReturn(domain); certService._sslCertDao = Mockito.mock(SslCertDao.class); when(certService._sslCertDao.persist(Matchers.any(SslCertVO.class))).thenReturn(new SslCertVO()); @@ -583,11 +587,11 @@ public void runUploadSslCertBadFormat() throws IOException, IllegalAccessExcepti //setting mock objects certService._accountMgr = Mockito.mock(AccountManager.class); final Account account = new AccountVO("testaccount", 1, "networkdomain", (short)0, UUID.randomUUID().toString()); - when(certService._accountMgr.getAccount(Matchers.anyLong())).thenReturn(account); + when(certService._accountMgr.getAccount(anyLong())).thenReturn(account); certService._domainDao = Mockito.mock(DomainDao.class); final DomainVO domain = new DomainVO("networkdomain", 1L, 1L, "networkdomain"); - when(certService._domainDao.findByIdIncludingRemoved(Matchers.anyLong())).thenReturn(domain); + when(certService._domainDao.findByIdIncludingRemoved(anyLong())).thenReturn(domain); certService._sslCertDao = Mockito.mock(SslCertDao.class); when(certService._sslCertDao.persist(Matchers.any(SslCertVO.class))).thenReturn(new SslCertVO()); @@ -622,20 +626,20 @@ public void runDeleteSslCertValid() throws Exception { //setting mock objects certService._accountMgr = Mockito.mock(AccountManager.class); final Account account = new AccountVO("testaccount", 1, "networkdomain", (short)0, UUID.randomUUID().toString()); - when(certService._accountMgr.getAccount(Matchers.anyLong())).thenReturn(account); + when(certService._accountMgr.getAccount(anyLong())).thenReturn(account); certService._domainDao = Mockito.mock(DomainDao.class); final DomainVO domain = new DomainVO("networkdomain", 1L, 1L, "networkdomain"); - when(certService._domainDao.findByIdIncludingRemoved(Matchers.anyLong())).thenReturn(domain); + when(certService._domainDao.findByIdIncludingRemoved(anyLong())).thenReturn(domain); certService._sslCertDao = Mockito.mock(SslCertDao.class); - when(certService._sslCertDao.remove(Matchers.anyLong())).thenReturn(true); - when(certService._sslCertDao.findById(Matchers.anyLong())).thenReturn(new SslCertVO()); + when(certService._sslCertDao.remove(anyLong())).thenReturn(true); + when(certService._sslCertDao.findById(anyLong())).thenReturn(new SslCertVO()); // a rule holding the cert certService._lbCertDao = Mockito.mock(LoadBalancerCertMapDao.class); - when(certService._lbCertDao.listByCertId(Matchers.anyLong())).thenReturn(null); + when(certService._lbCertDao.listByCertId(anyLong())).thenReturn(null); //creating the command final DeleteSslCertCmd deleteCmd = new DeleteSslCertCmdExtn(); @@ -660,15 +664,15 @@ public void runDeleteSslCertBoundCert() throws NoSuchFieldException, IllegalAcce certService._accountMgr = Mockito.mock(AccountManager.class); final Account account = new AccountVO("testaccount", 1, "networkdomain", (short)0, UUID.randomUUID().toString()); - when(certService._accountMgr.getAccount(Matchers.anyLong())).thenReturn(account); + when(certService._accountMgr.getAccount(anyLong())).thenReturn(account); certService._domainDao = Mockito.mock(DomainDao.class); final DomainVO domain = new DomainVO("networkdomain", 1L, 1L, "networkdomain"); - when(certService._domainDao.findByIdIncludingRemoved(Matchers.anyLong())).thenReturn(domain); + when(certService._domainDao.findByIdIncludingRemoved(anyLong())).thenReturn(domain); certService._sslCertDao = Mockito.mock(SslCertDao.class); - when(certService._sslCertDao.remove(Matchers.anyLong())).thenReturn(true); - when(certService._sslCertDao.findById(Matchers.anyLong())).thenReturn(new SslCertVO()); + when(certService._sslCertDao.remove(anyLong())).thenReturn(true); + when(certService._sslCertDao.findById(anyLong())).thenReturn(new SslCertVO()); // rule holding the cert certService._lbCertDao = Mockito.mock(LoadBalancerCertMapDao.class); @@ -677,10 +681,11 @@ public void runDeleteSslCertBoundCert() throws NoSuchFieldException, IllegalAcce lbMapList.add(new LoadBalancerCertMapVO()); certService._lbCertDao = Mockito.mock(LoadBalancerCertMapDao.class); - when(certService._lbCertDao.listByCertId(Matchers.anyLong())).thenReturn(lbMapList); + when(certService._lbCertDao.listByCertId(anyLong())).thenReturn(lbMapList); + certService._entityMgr = Mockito.mock(EntityManager.class); - when(certService._entityMgr.findById(Matchers.eq(LoadBalancerVO.class), Matchers.anyLong())).thenReturn(new LoadBalancerVO()); + when(certService._entityMgr.findById(eq(LoadBalancerVO.class), nullable(Long.class))).thenReturn(new LoadBalancerVO()); //creating the command final DeleteSslCertCmd deleteCmd = new DeleteSslCertCmdExtn(); @@ -708,19 +713,19 @@ public void runDeleteSslCertInvalidId() throws NoSuchFieldException, IllegalAcce certService._accountMgr = Mockito.mock(AccountManager.class); final Account account = new AccountVO("testaccount", 1, "networkdomain", (short)0, UUID.randomUUID().toString()); - when(certService._accountMgr.getAccount(Matchers.anyLong())).thenReturn(account); + when(certService._accountMgr.getAccount(anyLong())).thenReturn(account); certService._domainDao = Mockito.mock(DomainDao.class); final DomainVO domain = new DomainVO("networkdomain", 1L, 1L, "networkdomain"); - when(certService._domainDao.findByIdIncludingRemoved(Matchers.anyLong())).thenReturn(domain); + when(certService._domainDao.findByIdIncludingRemoved(anyLong())).thenReturn(domain); certService._sslCertDao = Mockito.mock(SslCertDao.class); - when(certService._sslCertDao.remove(Matchers.anyLong())).thenReturn(true); - when(certService._sslCertDao.findById(Matchers.anyLong())).thenReturn(null); + when(certService._sslCertDao.remove(anyLong())).thenReturn(true); + when(certService._sslCertDao.findById(anyLong())).thenReturn(null); // no rule holding the cert certService._lbCertDao = Mockito.mock(LoadBalancerCertMapDao.class); - when(certService._lbCertDao.listByCertId(Matchers.anyLong())).thenReturn(null); + when(certService._lbCertDao.listByCertId(anyLong())).thenReturn(null); //creating the command final DeleteSslCertCmd deleteCmd = new DeleteSslCertCmdExtn(); diff --git a/server/src/test/java/org/apache/cloudstack/networkoffering/CreateNetworkOfferingTest.java b/server/src/test/java/org/apache/cloudstack/networkoffering/CreateNetworkOfferingTest.java index 4f808cb6d396..3c9f186b1490 100644 --- a/server/src/test/java/org/apache/cloudstack/networkoffering/CreateNetworkOfferingTest.java +++ b/server/src/test/java/org/apache/cloudstack/networkoffering/CreateNetworkOfferingTest.java @@ -17,6 +17,10 @@ package org.apache.cloudstack.networkoffering; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.nullable; + import java.util.HashMap; import java.util.HashSet; import java.util.Map; @@ -24,9 +28,6 @@ import javax.inject.Inject; -import com.cloud.network.dao.LoadBalancerVMMapDao; -import junit.framework.TestCase; - import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.framework.config.dao.ConfigurationDao; import org.apache.cloudstack.framework.config.impl.ConfigurationVO; @@ -35,7 +36,6 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.Matchers; import org.mockito.Mockito; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @@ -48,6 +48,7 @@ import com.cloud.network.Network.Provider; import com.cloud.network.Network.Service; import com.cloud.network.Networks.TrafficType; +import com.cloud.network.dao.LoadBalancerVMMapDao; import com.cloud.network.vpc.VpcManager; import com.cloud.offering.NetworkOffering.Availability; import com.cloud.offerings.NetworkOfferingServiceMapVO; @@ -60,6 +61,8 @@ import com.cloud.utils.component.ComponentContext; import com.cloud.vm.dao.UserVmDetailsDao; +import junit.framework.TestCase; + @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "classpath:/createNetworkOffering.xml") public class CreateNetworkOfferingTest extends TestCase { @@ -103,11 +106,11 @@ public void setUp() { ComponentContext.initComponentsLifeCycle(); ConfigurationVO configVO = new ConfigurationVO("200", "200", "200", "200", "200", "200"); - Mockito.when(configDao.findByName(Matchers.anyString())).thenReturn(configVO); + Mockito.when(configDao.findByName(anyString())).thenReturn(configVO); - Mockito.when(offDao.persist(Matchers.any(NetworkOfferingVO.class))).thenReturn(new NetworkOfferingVO()); - Mockito.when(offDao.persist(Matchers.any(NetworkOfferingVO.class), Matchers.anyMap())).thenReturn(new NetworkOfferingVO()); - Mockito.when(mapDao.persist(Matchers.any(NetworkOfferingServiceMapVO.class))).thenReturn(new NetworkOfferingServiceMapVO()); + Mockito.when(offDao.persist(any(NetworkOfferingVO.class))).thenReturn(new NetworkOfferingVO()); + Mockito.when(offDao.persist(any(NetworkOfferingVO.class), nullable(Map.class))).thenReturn(new NetworkOfferingVO()); + Mockito.when(mapDao.persist(any(NetworkOfferingServiceMapVO.class))).thenReturn(new NetworkOfferingServiceMapVO()); Mockito.when(accountMgr.getSystemUser()).thenReturn(new UserVO(1)); Mockito.when(accountMgr.getSystemAccount()).thenReturn(new AccountVO(2)); diff --git a/server/src/test/java/org/apache/cloudstack/vm/VmImportManagerImplTest.java b/server/src/test/java/org/apache/cloudstack/vm/VmImportManagerImplTest.java new file mode 100644 index 000000000000..ad2bf086d66b --- /dev/null +++ b/server/src/test/java/org/apache/cloudstack/vm/VmImportManagerImplTest.java @@ -0,0 +1,353 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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. + +package org.apache.cloudstack.vm; + +import static org.mockito.ArgumentMatchers.nullable; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyLong; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.when; + +import java.net.URI; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import org.apache.cloudstack.api.ResponseGenerator; +import org.apache.cloudstack.api.ResponseObject; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.command.admin.vm.ImportUnmanagedInstanceCmd; +import org.apache.cloudstack.api.command.admin.vm.ListUnmanagedInstancesCmd; +import org.apache.cloudstack.api.response.UserVmResponse; +import org.apache.cloudstack.context.CallContext; +import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService; +import org.apache.cloudstack.engine.orchestration.service.VolumeOrchestrationService; +import org.apache.cloudstack.framework.config.dao.ConfigurationDao; +import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; +import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; +import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; + +import com.cloud.agent.AgentManager; +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.GetUnmanagedInstancesAnswer; +import com.cloud.agent.api.GetUnmanagedInstancesCommand; +import com.cloud.configuration.Resource; +import com.cloud.dc.ClusterVO; +import com.cloud.dc.DataCenter; +import com.cloud.dc.DataCenterVO; +import com.cloud.dc.dao.ClusterDao; +import com.cloud.dc.dao.DataCenterDao; +import com.cloud.event.UsageEventUtils; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.exception.PermissionDeniedException; +import com.cloud.host.Host; +import com.cloud.host.HostVO; +import com.cloud.host.Status; +import com.cloud.hypervisor.Hypervisor; +import com.cloud.network.Network; +import com.cloud.network.NetworkModel; +import com.cloud.network.dao.NetworkDao; +import com.cloud.network.dao.NetworkVO; +import com.cloud.offering.DiskOffering; +import com.cloud.offering.ServiceOffering; +import com.cloud.resource.ResourceManager; +import com.cloud.service.ServiceOfferingVO; +import com.cloud.service.dao.ServiceOfferingDao; +import com.cloud.storage.DiskOfferingVO; +import com.cloud.storage.StoragePool; +import com.cloud.storage.VMTemplateStoragePoolVO; +import com.cloud.storage.VMTemplateVO; +import com.cloud.storage.Volume; +import com.cloud.storage.VolumeApiService; +import com.cloud.storage.VolumeVO; +import com.cloud.storage.dao.DiskOfferingDao; +import com.cloud.storage.dao.VMTemplateDao; +import com.cloud.storage.dao.VMTemplatePoolDao; +import com.cloud.storage.dao.VolumeDao; +import com.cloud.template.VirtualMachineTemplate; +import com.cloud.user.Account; +import com.cloud.user.AccountService; +import com.cloud.user.AccountVO; +import com.cloud.user.ResourceLimitService; +import com.cloud.user.User; +import com.cloud.user.UserVO; +import com.cloud.user.dao.UserDao; +import com.cloud.uservm.UserVm; +import com.cloud.utils.Pair; +import com.cloud.vm.DiskProfile; +import com.cloud.vm.NicProfile; +import com.cloud.vm.UserVmManager; +import com.cloud.vm.UserVmVO; +import com.cloud.vm.VMInstanceVO; +import com.cloud.vm.VirtualMachine; +import com.cloud.vm.dao.VMInstanceDao; + +@RunWith(PowerMockRunner.class) +@PrepareForTest(UsageEventUtils.class) +public class VmImportManagerImplTest { + + @InjectMocks + private VmImportService vmIngestionService = new VmImportManagerImpl(); + + @Mock + private UserVmManager userVmManager; + @Mock + private ClusterDao clusterDao; + @Mock + private ResourceManager resourceManager; + @Mock + private VMTemplatePoolDao templatePoolDao; + @Mock + private AgentManager agentManager; + @Mock + private AccountService accountService; + @Mock + private UserDao userDao; + @Mock + private DataCenterDao dataCenterDao; + @Mock + private VMTemplateDao templateDao; + @Mock + private VMInstanceDao vmDao; + @Mock + private ServiceOfferingDao serviceOfferingDao; + @Mock + private DiskOfferingDao diskOfferingDao; + @Mock + private NetworkDao networkDao; + @Mock + private NetworkOrchestrationService networkOrchestrationService; + @Mock + private VolumeOrchestrationService volumeManager; + @Mock + public ResponseGenerator responseGenerator; + @Mock + private VolumeDao volumeDao; + @Mock + private ResourceLimitService resourceLimitService; + @Mock + private PrimaryDataStoreDao primaryDataStoreDao; + @Mock + private VolumeApiService volumeApiService; + @Mock + private NetworkModel networkModel; + @Mock + private ConfigurationDao configurationDao; + + @Before + public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + + AccountVO account = new AccountVO("admin", 1L, "", Account.ACCOUNT_TYPE_ADMIN, "uuid"); + UserVO user = new UserVO(1, "adminuser", "password", "firstname", "lastName", "email", "timezone", UUID.randomUUID().toString(), User.Source.UNKNOWN); + CallContext.register(user, account); + + UnmanagedInstanceTO instance = new UnmanagedInstanceTO(); + instance.setName("TestInstance"); + instance.setCpuCores(2); + instance.setCpuCoresPerSocket(1); + instance.setCpuSpeed(1000); + instance.setMemory(1024); + instance.setOperatingSystem("CentOS 7"); + List instanceDisks = new ArrayList<>(); + UnmanagedInstanceTO.Disk instanceDisk = new UnmanagedInstanceTO.Disk(); + instanceDisk.setDiskId("1000-1"); + instanceDisk.setLabel("DiskLabel"); + instanceDisk.setController("scsi"); + instanceDisk.setImagePath("[b6ccf44a1fa13e29b3667b4954fa10ee] TestInstance/ROOT-1.vmdk"); + instanceDisk.setCapacity(5242880L); + instanceDisk.setDatastoreName("Test"); + instanceDisk.setDatastoreHost("Test"); + instanceDisk.setDatastorePath("Test"); + instanceDisk.setDatastoreType("NFS"); + instanceDisks.add(instanceDisk); + instance.setDisks(instanceDisks); + List instanceNics = new ArrayList<>(); + UnmanagedInstanceTO.Nic instanceNic = new UnmanagedInstanceTO.Nic(); + instanceNic.setNicId("NIC 1"); + instanceNic.setAdapterType("VirtualE1000E"); + instanceNic.setMacAddress("02:00:2e:0f:00:02"); + instanceNic.setVlan(1024); + instanceNics.add(instanceNic); + instance.setNics(instanceNics); + instance.setPowerState(UnmanagedInstanceTO.PowerState.PowerOn); + + ClusterVO clusterVO = new ClusterVO(1L, 1L, "Cluster"); + clusterVO.setHypervisorType(Hypervisor.HypervisorType.VMware.toString()); + when(clusterDao.findById(Mockito.anyLong())).thenReturn(clusterVO); + when(configurationDao.getValue(Mockito.anyString())).thenReturn(null); + doNothing().when(resourceLimitService).checkResourceLimit(any(Account.class), any(Resource.ResourceType.class), anyLong()); + List hosts = new ArrayList<>(); + HostVO hostVO = Mockito.mock(HostVO.class); + when(hostVO.isInMaintenanceStates()).thenReturn(false); + hosts.add(hostVO); + when(resourceManager.listHostsInClusterByStatus(Mockito.anyLong(), Mockito.any(Status.class))).thenReturn(hosts); + List templates = new ArrayList<>(); + when(templatePoolDao.listAll()).thenReturn(templates); + List volumes = new ArrayList<>(); + when(volumeDao.findIncludingRemovedByZone(Mockito.anyLong())).thenReturn(volumes); + List vms = new ArrayList<>(); + when(vmDao.listByHostId(Mockito.anyLong())).thenReturn(vms); + when(vmDao.listByLastHostIdAndStates(Mockito.anyLong())).thenReturn(vms); + GetUnmanagedInstancesCommand cmd = Mockito.mock(GetUnmanagedInstancesCommand.class); + HashMap map = new HashMap<>(); + map.put(instance.getName(), instance); + Answer answer = new GetUnmanagedInstancesAnswer(cmd, "", map); + when(agentManager.easySend(Mockito.anyLong(), Mockito.any(GetUnmanagedInstancesCommand.class))).thenReturn(answer); + DataCenterVO zone = Mockito.mock(DataCenterVO.class); + when(zone.getId()).thenReturn(1L); + when(dataCenterDao.findById(Mockito.anyLong())).thenReturn(zone); + when(accountService.getActiveAccountById(Mockito.anyLong())).thenReturn(Mockito.mock(Account.class)); + List users = new ArrayList<>(); + users.add(Mockito.mock(UserVO.class)); + when(userDao.listByAccount(Mockito.anyLong())).thenReturn(users); + VMTemplateVO template = Mockito.mock(VMTemplateVO.class); + when(template.getId()).thenReturn(1L); + when(template.getName()).thenReturn("Template"); + when(templateDao.findById(Mockito.anyLong())).thenReturn(template); + when(templateDao.findByName(Mockito.anyString())).thenReturn(template); + ServiceOfferingVO serviceOffering = Mockito.mock(ServiceOfferingVO.class); + when(serviceOffering.getId()).thenReturn(1L); + when(serviceOffering.getTags()).thenReturn(""); + when(serviceOffering.isDynamic()).thenReturn(false); + when(serviceOffering.getCpu()).thenReturn(instance.getCpuCores()); + when(serviceOffering.getRamSize()).thenReturn(instance.getMemory()); + when(serviceOffering.getSpeed()).thenReturn(instance.getCpuSpeed()); + when(serviceOfferingDao.findById(Mockito.anyLong())).thenReturn(serviceOffering); + DiskOfferingVO diskOfferingVO = Mockito.mock(DiskOfferingVO.class); + when(diskOfferingVO.isCustomized()).thenReturn(false); + when(diskOfferingVO.getDiskSize()).thenReturn(Long.MAX_VALUE); + when(diskOfferingDao.findById(Mockito.anyLong())).thenReturn(diskOfferingVO); + UserVmVO userVm = Mockito.mock(UserVmVO.class); + when(userVm.getAccountId()).thenReturn(1L); + when(userVm.getDataCenterId()).thenReturn(1L); + when(userVm.getHostName()).thenReturn(instance.getName()); + when(userVm.getTemplateId()).thenReturn(1L); + when(userVm.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.VMware); + when(userVm.getUuid()).thenReturn("abcd"); + when(userVm.isDisplayVm()).thenReturn(true); + // Skip usage publishing and resource increment for test + when(userVm.getType()).thenReturn(VirtualMachine.Type.Instance); + userVm.setInstanceName(instance.getName()); + userVm.setHostName(instance.getName()); + StoragePoolVO poolVO = Mockito.mock(StoragePoolVO.class); + when(poolVO.getDataCenterId()).thenReturn(1L); + when(poolVO.getClusterId()).thenReturn(clusterVO.getId()); + List pools = new ArrayList<>(); + pools.add(poolVO); + when(primaryDataStoreDao.listPoolByHostPath(Mockito.anyString(), Mockito.anyString())).thenReturn(pools); + when(userVmManager.importVM(nullable(DataCenter.class), nullable(Host.class), nullable(VirtualMachineTemplate.class), nullable(String.class), nullable(String.class), + nullable(Account.class), nullable(String.class), nullable(Account.class), nullable(Boolean.class), nullable(String.class), + nullable(Long.class), nullable(Long.class), nullable(ServiceOffering.class), nullable(String.class), + nullable(String.class), nullable(Hypervisor.HypervisorType.class), nullable(Map.class), nullable(VirtualMachine.PowerState.class))).thenReturn(userVm); + when(volumeApiService.doesTargetStorageSupportDiskOffering(Mockito.any(StoragePool.class), Mockito.anyString())).thenReturn(true); + NetworkVO networkVO = Mockito.mock(NetworkVO.class); + when(networkVO.getGuestType()).thenReturn(Network.GuestType.L2); + when(networkVO.getBroadcastUri()).thenReturn(URI.create(String.format("vlan://%d", instanceNic.getVlan()))); + when(networkVO.getDataCenterId()).thenReturn(1L); + when(networkDao.findById(Mockito.anyLong())).thenReturn(networkVO); + List networks = new ArrayList<>(); + networks.add(networkVO); + when(networkDao.listByZone(Mockito.anyLong())).thenReturn(networks); + doNothing().when(networkModel).checkNetworkPermissions(Mockito.any(Account.class), Mockito.any(Network.class)); + doNothing().when(networkModel).checkRequestedIpAddresses(Mockito.anyLong(), Mockito.any(Network.IpAddresses.class)); + NicProfile profile = Mockito.mock(NicProfile.class); + Integer deviceId = 100; + Pair pair = new Pair(profile, deviceId); + when(networkOrchestrationService.importNic(nullable(String.class), nullable(Integer.class), nullable(Network.class), nullable(Boolean.class), nullable(VirtualMachine.class), nullable(Network.IpAddresses.class))).thenReturn(pair); + when(volumeManager.importVolume(Mockito.any(Volume.Type.class), Mockito.anyString(), Mockito.any(DiskOffering.class), Mockito.anyLong(), + Mockito.anyLong(), Mockito.anyLong(), Mockito.any(VirtualMachine.class), Mockito.any(VirtualMachineTemplate.class), + Mockito.any(Account.class), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyString(), Mockito.anyString())).thenReturn(Mockito.mock(DiskProfile.class)); + when(volumeDao.findByInstance(Mockito.anyLong())).thenReturn(volumes); + List userVmResponses = new ArrayList<>(); + UserVmResponse userVmResponse = new UserVmResponse(); + userVmResponse.setInstanceName(instance.getName()); + userVmResponses.add(userVmResponse); + when(responseGenerator.createUserVmResponse(Mockito.any(ResponseObject.ResponseView.class), Mockito.anyString(), Mockito.any(UserVm.class))).thenReturn(userVmResponses); + } + + @After + public void tearDown() { + CallContext.unregister(); + } + + @Test + public void listUnmanagedInstancesTest() { + ListUnmanagedInstancesCmd cmd = Mockito.mock(ListUnmanagedInstancesCmd.class); + vmIngestionService.listUnmanagedInstances(cmd); + } + + @Test(expected = InvalidParameterValueException.class) + public void listUnmanagedInstancesInvalidHypervisorTest() { + ListUnmanagedInstancesCmd cmd = Mockito.mock(ListUnmanagedInstancesCmd.class); + ClusterVO cluster = new ClusterVO(1, 1, "Cluster"); + cluster.setHypervisorType(Hypervisor.HypervisorType.KVM.toString()); + when(clusterDao.findById(Mockito.anyLong())).thenReturn(cluster); + vmIngestionService.listUnmanagedInstances(cmd); + } + + @Test(expected = PermissionDeniedException.class) + public void listUnmanagedInstancesInvalidCallerTest() { + CallContext.unregister(); + AccountVO account = new AccountVO("user", 1L, "", Account.ACCOUNT_TYPE_NORMAL, "uuid"); + UserVO user = new UserVO(1, "testuser", "password", "firstname", "lastName", "email", "timezone", UUID.randomUUID().toString(), User.Source.UNKNOWN); + CallContext.register(user, account); + ListUnmanagedInstancesCmd cmd = Mockito.mock(ListUnmanagedInstancesCmd.class); + vmIngestionService.listUnmanagedInstances(cmd); + } + + @Test + public void importUnmanagedInstanceTest() { + ImportUnmanagedInstanceCmd importUnmanageInstanceCmd = Mockito.mock(ImportUnmanagedInstanceCmd.class); + when(importUnmanageInstanceCmd.getName()).thenReturn("TestInstance"); + when(importUnmanageInstanceCmd.getAccountName()).thenReturn(null); + when(importUnmanageInstanceCmd.getDomainId()).thenReturn(null); + PowerMockito.mockStatic(UsageEventUtils.class); + vmIngestionService.importUnmanagedInstance(importUnmanageInstanceCmd); + } + + @Test(expected = InvalidParameterValueException.class) + public void importUnmanagedInstanceInvalidHostnameTest() { + ImportUnmanagedInstanceCmd importUnmanageInstanceCmd = Mockito.mock(ImportUnmanagedInstanceCmd.class); + when(importUnmanageInstanceCmd.getName()).thenReturn("TestInstance"); + when(importUnmanageInstanceCmd.getName()).thenReturn("some name"); + when(importUnmanageInstanceCmd.getMigrateAllowed()).thenReturn(false); + vmIngestionService.importUnmanagedInstance(importUnmanageInstanceCmd); + } + + @Test(expected = ServerApiException.class) + public void importUnmanagedInstanceMissingInstanceTest() { + ImportUnmanagedInstanceCmd importUnmanageInstanceCmd = Mockito.mock(ImportUnmanagedInstanceCmd.class); + when(importUnmanageInstanceCmd.getName()).thenReturn("SomeInstance"); + when(importUnmanageInstanceCmd.getAccountName()).thenReturn(null); + when(importUnmanageInstanceCmd.getDomainId()).thenReturn(null); + vmIngestionService.importUnmanagedInstance(importUnmanageInstanceCmd); + } +} \ No newline at end of file diff --git a/server/src/test/java/org/cloud/network/router/deployment/RouterDeploymentDefinitionTest.java b/server/src/test/java/org/cloud/network/router/deployment/RouterDeploymentDefinitionTest.java index 6195387dbe22..6fa1759884d9 100644 --- a/server/src/test/java/org/cloud/network/router/deployment/RouterDeploymentDefinitionTest.java +++ b/server/src/test/java/org/cloud/network/router/deployment/RouterDeploymentDefinitionTest.java @@ -25,6 +25,7 @@ import static org.mockito.Matchers.anyLong; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.lenient; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; @@ -285,7 +286,7 @@ public void testCheckPreconditionsWrongTrafficType() throws ResourceUnavailableE @Test(expected = ResourceUnavailableException.class) public void testCheckPreconditionsWrongState() throws ResourceUnavailableException { // Prepare wrong traffic type to trigger error - when(deployment.guestNetwork.getTrafficType()).thenReturn(TrafficType.Guest); + lenient().when(deployment.guestNetwork.getTrafficType()).thenReturn(TrafficType.Guest); // Execute driveTestCheckPreconditionsCorrectNwState(Network.State.Shutdown); @@ -422,8 +423,8 @@ public void testPlanDeploymentRoutersBasic() { @Test public void testPlanDeploymentRoutersNonBasic() { // Prepare - when(mockDataCenter.getNetworkType()).thenReturn(NetworkType.Advanced); - when(mockDestination.getPod()).thenReturn(mockPod); + lenient().when(mockDataCenter.getNetworkType()).thenReturn(NetworkType.Advanced); + lenient().when(mockDestination.getPod()).thenReturn(mockPod); // Execute deployment.planDeploymentRouters(); @@ -651,7 +652,7 @@ public void testFindSourceNatIPPublicNw() throws InsufficientAddressCapacityExce public void testFindSourceNatIPNonPublicNw() throws InsufficientAddressCapacityException, ConcurrentOperationException { // Prepare final PublicIp sourceNatIp = mock(PublicIp.class); - when(mockIpAddrMgr.assignSourceNatIpAddressToGuestNetwork( + lenient().when(mockIpAddrMgr.assignSourceNatIpAddressToGuestNetwork( mockOwner, mockNw)).thenReturn(sourceNatIp); deployment.isPublicNetwork = false; @@ -705,7 +706,7 @@ public void testDeployAllVirtualRouters() // Prepare deployment.routers = new ArrayList<>(); - when(mockNw.isRedundant()).thenReturn(true); + lenient().when(mockNw.isRedundant()).thenReturn(true); //this.deployment.routers.add(routerVO1); final RouterDeploymentDefinition deploymentUT = spy(deployment); doReturn(2).when(deploymentUT).getNumberOfRoutersToDeploy(); @@ -714,7 +715,7 @@ public void testDeployAllVirtualRouters() final DomainRouterVO routerVO2 = mock(DomainRouterVO.class); when(mockNetworkHelper.deployRouter(deploymentUT, false)) .thenReturn(routerVO1).thenReturn(routerVO2); - when(networkDetailsDao.findById(anyLong())).thenReturn(null); + lenient().when(networkDetailsDao.findById(anyLong())).thenReturn(null); // Execute deploymentUT.deployAllVirtualRouters(); @@ -757,7 +758,7 @@ public void testSetupAccountOwnerNotSharedNeitherNetworkSystem() { // Prepare when(mockNetworkModel.isNetworkSystem(mockNw)).thenReturn(false); when(mockNw.getGuestType()).thenReturn(Network.GuestType.Isolated); - when(mockAccountMgr.getAccount(Account.ACCOUNT_ID_SYSTEM)).thenReturn(null); + lenient().when(mockAccountMgr.getAccount(Account.ACCOUNT_ID_SYSTEM)).thenReturn(null); //Execute deployment.setupAccountOwner(); // Assert diff --git a/server/src/test/java/org/cloud/network/router/deployment/RouterDeploymentDefinitionTestBase.java b/server/src/test/java/org/cloud/network/router/deployment/RouterDeploymentDefinitionTestBase.java index 626c2d7acc67..04778b9a7031 100644 --- a/server/src/test/java/org/cloud/network/router/deployment/RouterDeploymentDefinitionTestBase.java +++ b/server/src/test/java/org/cloud/network/router/deployment/RouterDeploymentDefinitionTestBase.java @@ -16,6 +16,7 @@ // under the License. package org.cloud.network.router.deployment; +import static org.mockito.Mockito.lenient; import static org.mockito.Mockito.when; import java.util.ArrayList; @@ -23,11 +24,11 @@ import java.util.List; import java.util.Map; -import com.cloud.network.dao.NetworkDetailsDao; +import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.Mock; -import org.mockito.runners.MockitoJUnitRunner; +import org.mockito.junit.MockitoJUnitRunner; import com.cloud.dc.DataCenter; import com.cloud.dc.HostPodVO; @@ -37,6 +38,7 @@ import com.cloud.network.IpAddressManager; import com.cloud.network.NetworkModel; import com.cloud.network.dao.NetworkDao; +import com.cloud.network.dao.NetworkDetailsDao; import com.cloud.network.dao.NetworkVO; import com.cloud.network.dao.PhysicalNetworkServiceProviderDao; import com.cloud.network.dao.VirtualRouterProviderDao; @@ -134,11 +136,17 @@ public class RouterDeploymentDefinitionTestBase { protected void initMocks() { when(mockDestination.getDataCenter()).thenReturn(mockDataCenter); - when(mockDataCenter.getId()).thenReturn(DATA_CENTER_ID); - when(mockPod.getId()).thenReturn(POD_ID1); - when(mockHostPodVO1.getId()).thenReturn(POD_ID1); - when(mockHostPodVO2.getId()).thenReturn(POD_ID2); - when(mockHostPodVO3.getId()).thenReturn(POD_ID3); - when(mockNw.getId()).thenReturn(NW_ID_1); + lenient().when(mockDataCenter.getId()).thenReturn(DATA_CENTER_ID); + lenient().when(mockPod.getId()).thenReturn(POD_ID1); + lenient().when(mockHostPodVO1.getId()).thenReturn(POD_ID1); + lenient().when(mockHostPodVO2.getId()).thenReturn(POD_ID2); + lenient().when(mockHostPodVO3.getId()).thenReturn(POD_ID3); + lenient().when(mockNw.getId()).thenReturn(NW_ID_1); } + + @Test + public void mockTest() { + return; + } + } diff --git a/server/src/test/java/org/cloud/network/router/deployment/VpcRouterDeploymentDefinitionTest.java b/server/src/test/java/org/cloud/network/router/deployment/VpcRouterDeploymentDefinitionTest.java index e4ef9f5fc272..68e147bf61b0 100644 --- a/server/src/test/java/org/cloud/network/router/deployment/VpcRouterDeploymentDefinitionTest.java +++ b/server/src/test/java/org/cloud/network/router/deployment/VpcRouterDeploymentDefinitionTest.java @@ -22,6 +22,7 @@ import static junit.framework.Assert.assertNull; import static junit.framework.Assert.assertTrue; import static org.mockito.Matchers.anyLong; +import static org.mockito.Mockito.lenient; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -81,7 +82,7 @@ public class VpcRouterDeploymentDefinitionTest extends RouterDeploymentDefinitio protected void initMocks() { super.initMocks(); when(mockVpc.getId()).thenReturn(VPC_ID); - when(mockVpc.getZoneId()).thenReturn(VPC_ID); + lenient().when(mockVpc.getZoneId()).thenReturn(VPC_ID); when(mockVpc.getVpcOfferingId()).thenReturn(VPC_OFFERING_ID); } @@ -251,7 +252,7 @@ public void driveTestDeployAllVirtualRouters(final DomainRouterVO router) throws StorageUnavailableException, InsufficientCapacityException, ResourceUnavailableException { // Prepare final VpcRouterDeploymentDefinition vpcDeployment = (VpcRouterDeploymentDefinition) deployment; - when(vpcDeployment.nwHelper.deployRouter(vpcDeployment, true)).thenReturn(router); + lenient().when(vpcDeployment.nwHelper.deployRouter(vpcDeployment, true)).thenReturn(router); // Execute vpcDeployment.deployAllVirtualRouters(); diff --git a/server/src/test/resources/SecurityGroupManagerTestContext.xml b/server/src/test/resources/SecurityGroupManagerTestContext.xml index a4d00634aa09..10ca3e28f20c 100644 --- a/server/src/test/resources/SecurityGroupManagerTestContext.xml +++ b/server/src/test/resources/SecurityGroupManagerTestContext.xml @@ -9,19 +9,19 @@ OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> - - - + + + @@ -29,13 +29,29 @@ - - - - - - + + + + + + + + + + + + + + + + + + + + + + diff --git a/server/src/test/resources/SnapshotDaoTestContext.xml b/server/src/test/resources/SnapshotDaoTestContext.xml index 448b30980afe..479bd95eefd8 100644 --- a/server/src/test/resources/SnapshotDaoTestContext.xml +++ b/server/src/test/resources/SnapshotDaoTestContext.xml @@ -9,19 +9,19 @@ OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> - - - + + + @@ -33,12 +33,16 @@ - - - - - + + + + + + + + + diff --git a/server/src/test/resources/VpcTestContext.xml b/server/src/test/resources/VpcTestContext.xml index e124f72d372c..c9575734ba41 100644 --- a/server/src/test/resources/VpcTestContext.xml +++ b/server/src/test/resources/VpcTestContext.xml @@ -9,23 +9,23 @@ OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> - - - - - - - + + + + + + + diff --git a/server/src/test/resources/createNetworkOffering.xml b/server/src/test/resources/createNetworkOffering.xml index 6aac8e18aa86..32596fc03a27 100644 --- a/server/src/test/resources/createNetworkOffering.xml +++ b/server/src/test/resources/createNetworkOffering.xml @@ -58,4 +58,5 @@ + diff --git a/services/console-proxy/rdpconsole/pom.xml b/services/console-proxy/rdpconsole/pom.xml index 9b0e90b37310..f0d116f90199 100644 --- a/services/console-proxy/rdpconsole/pom.xml +++ b/services/console-proxy/rdpconsole/pom.xml @@ -48,6 +48,11 @@ org.bouncycastle bcprov-jdk15on + + com.sun.xml.security + xml-security-impl + 1.0 + diff --git a/services/console-proxy/server/src/main/java/com/cloud/consoleproxy/ConsoleProxy.java b/services/console-proxy/server/src/main/java/com/cloud/consoleproxy/ConsoleProxy.java index f0c3c4e46441..2161de233d4f 100644 --- a/services/console-proxy/server/src/main/java/com/cloud/consoleproxy/ConsoleProxy.java +++ b/services/console-proxy/server/src/main/java/com/cloud/consoleproxy/ConsoleProxy.java @@ -35,7 +35,6 @@ import com.cloud.consoleproxy.util.Logger; import com.cloud.utils.PropertiesUtil; -import com.cloud.utils.ReflectUtil; import com.google.gson.Gson; import com.sun.net.httpserver.HttpServer; @@ -74,7 +73,7 @@ public class ConsoleProxy { static String encryptorPassword = "Dummy"; private static void configLog4j() { - final ClassLoader loader = ReflectUtil.getClassLoaderForName("conf"); + final ClassLoader loader = Thread.currentThread().getContextClassLoader(); URL configUrl = loader.getResource("/conf/log4j-cloud.xml"); if (configUrl == null) configUrl = ClassLoader.getSystemResource("log4j-cloud.xml"); @@ -249,7 +248,7 @@ public static void startWithContext(Properties conf, Object context, byte[] ksBi ConsoleProxy.ksBits = ksBits; ConsoleProxy.ksPassword = ksPassword; try { - final ClassLoader loader = ReflectUtil.getClassLoaderForName("agent"); + final ClassLoader loader = Thread.currentThread().getContextClassLoader(); Class contextClazz = loader.loadClass("com.cloud.agent.resource.consoleproxy.ConsoleProxyResource"); authMethod = contextClazz.getDeclaredMethod("authenticateConsoleAccess", String.class, String.class, String.class, String.class, String.class, Boolean.class); reportMethod = contextClazz.getDeclaredMethod("reportLoadInfo", String.class); diff --git a/services/secondary-storage/server/pom.xml b/services/secondary-storage/server/pom.xml index abbfffbfa866..e1d11270cfa5 100644 --- a/services/secondary-storage/server/pom.xml +++ b/services/secondary-storage/server/pom.xml @@ -60,7 +60,7 @@ io.netty netty-all - 4.0.33.Final + 4.0.56.Final compile diff --git a/services/secondary-storage/server/src/main/java/org/apache/cloudstack/storage/resource/NfsSecondaryStorageResource.java b/services/secondary-storage/server/src/main/java/org/apache/cloudstack/storage/resource/NfsSecondaryStorageResource.java index 7f9e0a674097..ab98a812580f 100644 --- a/services/secondary-storage/server/src/main/java/org/apache/cloudstack/storage/resource/NfsSecondaryStorageResource.java +++ b/services/secondary-storage/server/src/main/java/org/apache/cloudstack/storage/resource/NfsSecondaryStorageResource.java @@ -67,7 +67,7 @@ import org.apache.cloudstack.storage.configdrive.ConfigDriveBuilder; import org.apache.cloudstack.storage.template.DownloadManager; import org.apache.cloudstack.storage.template.DownloadManagerImpl; -import org.apache.cloudstack.storage.template.DownloadManagerImpl.ZfsPathParser; +import org.apache.cloudstack.storage.NfsMountManagerImpl.PathParser; import org.apache.cloudstack.storage.template.UploadEntity; import org.apache.cloudstack.storage.template.UploadManager; import org.apache.cloudstack.storage.template.UploadManagerImpl; @@ -2905,7 +2905,7 @@ protected boolean mountExists(String localRootPath, URI uri) { script = new Script(!_inSystemVM, "mount", _timeout, s_logger); List res = new ArrayList(); - ZfsPathParser parser = new ZfsPathParser(localRootPath); + PathParser parser = new PathParser(localRootPath); script.execute(parser); res.addAll(parser.getPaths()); for (String s : res) { diff --git a/services/secondary-storage/server/src/main/java/org/apache/cloudstack/storage/template/DownloadManagerImpl.java b/services/secondary-storage/server/src/main/java/org/apache/cloudstack/storage/template/DownloadManagerImpl.java index bd5c59131b6a..4149cd174d13 100644 --- a/services/secondary-storage/server/src/main/java/org/apache/cloudstack/storage/template/DownloadManagerImpl.java +++ b/services/secondary-storage/server/src/main/java/org/apache/cloudstack/storage/template/DownloadManagerImpl.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.storage.template; -import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.IOException; @@ -60,6 +59,7 @@ import org.apache.cloudstack.storage.command.DownloadCommand.ResourceType; import org.apache.cloudstack.storage.command.DownloadProgressCommand; import org.apache.cloudstack.storage.command.DownloadProgressCommand.RequestType; +import org.apache.cloudstack.storage.NfsMountManagerImpl.PathParser; import org.apache.cloudstack.storage.resource.NfsSecondaryStorageResource; import org.apache.cloudstack.storage.resource.SecondaryStorageResource; import org.apache.commons.collections.CollectionUtils; @@ -82,7 +82,6 @@ import com.cloud.utils.StringUtils; import com.cloud.utils.component.ManagerBase; import com.cloud.utils.exception.CloudRuntimeException; -import com.cloud.utils.script.OutputInterpreter; import com.cloud.utils.script.Script; import com.cloud.utils.storage.QCOW2Utils; import org.apache.cloudstack.utils.security.ChecksumValue; @@ -231,7 +230,7 @@ public void setOvfProperties(List ovfProperties) { } } - public static final Logger s_logger = Logger.getLogger(DownloadManagerImpl.class); + public static final Logger LOGGER = Logger.getLogger(DownloadManagerImpl.class); private String _templateDir; private String _volumeDir; private String createTmpltScr; @@ -264,12 +263,12 @@ public void setStorageLayer(StorageLayer storage) { public void setDownloadStatus(String jobId, Status status) { DownloadJob dj = jobs.get(jobId); if (dj == null) { - s_logger.warn("setDownloadStatus for jobId: " + jobId + ", status=" + status + " no job found"); + LOGGER.warn("setDownloadStatus for jobId: " + jobId + ", status=" + status + " no job found"); return; } TemplateDownloader td = dj.getTemplateDownloader(); - s_logger.info("Download Completion for jobId: " + jobId + ", status=" + status); - s_logger.info("local: " + td.getDownloadLocalPath() + ", bytes=" + td.getDownloadedBytes() + ", error=" + td.getDownloadError() + ", pct=" + + LOGGER.info("Download Completion for jobId: " + jobId + ", status=" + status); + LOGGER.info("local: " + td.getDownloadLocalPath() + ", bytes=" + td.getDownloadedBytes() + ", error=" + td.getDownloadError() + ", pct=" + td.getDownloadPercent()); switch (status) { @@ -282,7 +281,7 @@ public void setDownloadStatus(String jobId, Status status) { case UNKNOWN: return; case IN_PROGRESS: - s_logger.info("Resuming jobId: " + jobId + ", status=" + status); + LOGGER.info("Resuming jobId: " + jobId + ", status=" + status); td.setResume(true); threadPool.execute(td); break; @@ -297,7 +296,7 @@ public void setDownloadStatus(String jobId, Status status) { td.setDownloadError("Download success, starting install "); String result = postRemoteDownload(jobId); if (result != null) { - s_logger.error("Failed post download install: " + result); + LOGGER.error("Failed post download install: " + result); td.setStatus(Status.UNRECOVERABLE_ERROR); td.setDownloadError("Failed post download install: " + result); ((S3TemplateDownloader) td).cleanupAfterError(); @@ -312,7 +311,7 @@ public void setDownloadStatus(String jobId, Status status) { td.setDownloadError("Download success, starting install "); String result = postLocalDownload(jobId); if (result != null) { - s_logger.error("Failed post download script: " + result); + LOGGER.error("Failed post download script: " + result); td.setStatus(Status.UNRECOVERABLE_ERROR); td.setDownloadError("Failed post download script: " + result); } else { @@ -371,6 +370,7 @@ private String postRemoteDownload(String jobId) { * Post local download activity (install and cleanup). Executed in context of * downloader thread * + * @return an error message describing why download failed or {code}null{code} on success * @throws IOException */ private String postLocalDownload(String jobId) { @@ -384,29 +384,58 @@ private String postLocalDownload(String jobId) { ResourceType resourceType = dnld.getResourceType(); File originalTemplate = new File(td.getDownloadLocalPath()); - ChecksumValue oldValue = new ChecksumValue(dnld.getChecksum()); - ChecksumValue newValue = null; - try { - newValue = computeCheckSum(oldValue.getAlgorithm(), originalTemplate); - } catch (NoSuchAlgorithmException e) { - return "checksum algorithm not recognised: " + oldValue.getAlgorithm(); + if(StringUtils.isBlank(dnld.getChecksum())) { + if (LOGGER.isInfoEnabled()) { + LOGGER.info(String.format("No checksum available for '%s'", originalTemplate.getName())); + } } - if(StringUtils.isNotBlank(dnld.getChecksum()) && ! oldValue.equals(newValue)) { - return "checksum \"" + newValue +"\" didn't match the given value, \"" + oldValue + "\""; + // check or create checksum + String checksumErrorMessage = checkOrCreateTheChecksum(dnld, originalTemplate); + if (checksumErrorMessage != null) { + return checksumErrorMessage; } - String checksum = newValue.getChecksum(); - if (checksum == null) { - s_logger.warn("Something wrong happened when try to calculate the checksum of downloaded template!"); + + String result; + String extension = dnld.getFormat().getFileExtension(); + String templateName = makeTemplatename(jobId, extension); + String templateFilename = templateName + "." + extension; + + result = executeCreateScript(dnld, td, resourcePath, finalResourcePath, resourceType, templateFilename); + if (result != null) { + return result; } - dnld.setCheckSum(checksum); + // Set permissions for the downloaded template + File downloadedTemplate = new File(resourcePath + "/" + templateFilename); + + _storage.setWorldReadableAndWriteable(downloadedTemplate); + setPermissionsForTheDownloadedTemplate(dnld, resourcePath, resourceType); + + TemplateLocation loc = new TemplateLocation(_storage, resourcePath); + try { + loc.create(dnld.getId(), true, dnld.getTmpltName()); + } catch (IOException e) { + LOGGER.warn("Something is wrong with template location " + resourcePath, e); + loc.purge(); + return "Unable to download due to " + e.getMessage(); + } + + result = postProcessAfterDownloadComplete(dnld, resourcePath, templateName, loc); + if (result != null) { + return result; + } + + return null; + } + private String executeCreateScript(DownloadJob dnld, TemplateDownloader td, String resourcePath, String finalResourcePath, ResourceType resourceType, String templateFilename) { + String result; int imgSizeGigs = (int)Math.ceil(_storage.getSize(td.getDownloadLocalPath()) * 1.0d / (1024 * 1024 * 1024)); imgSizeGigs++; // add one just in case long timeout = (long)imgSizeGigs * installTimeoutPerGig; Script scr = null; String script = resourceType == ResourceType.TEMPLATE ? createTmpltScr : createVolScr; - scr = new Script(script, timeout, s_logger); + scr = new Script(script, timeout, LOGGER); scr.add("-s", Integer.toString(imgSizeGigs)); scr.add("-S", Long.toString(td.getMaxTemplateSizeInBytes())); if (dnld.getDescription() != null && dnld.getDescription().length() > 1) { @@ -416,35 +445,30 @@ private String postLocalDownload(String jobId) { scr.add("-h"); } - // add options common to ISO and template - String extension = dnld.getFormat().getFileExtension(); - String templateName = ""; - if (extension.equals("iso")) { - templateName = jobs.get(jobId).getTmpltName().trim().replace(" ", "_"); - } else { - templateName = java.util.UUID.nameUUIDFromBytes((jobs.get(jobId).getTmpltName() + System.currentTimeMillis()).getBytes(StringUtils.getPreferredCharset())).toString(); - } - // run script to mv the temporary template file to the final template // file - String templateFilename = templateName + "." + extension; dnld.setTmpltPath(finalResourcePath + "/" + templateFilename); scr.add("-n", templateFilename); scr.add("-t", resourcePath); scr.add("-f", td.getDownloadLocalPath()); // this is the temporary template file downloaded scr.add("-u"); // cleanup - String result; result = scr.execute(); + return result; + } - if (result != null) { - return result; + private String makeTemplatename(String jobId, String extension) { + // add options common to ISO and template + String templateName = ""; + if (extension.equals("iso")) { + templateName = jobs.get(jobId).getTmpltName().trim().replace(" ", "_"); + } else { + templateName = UUID.nameUUIDFromBytes((jobs.get(jobId).getTmpltName() + System.currentTimeMillis()).getBytes(StringUtils.getPreferredCharset())).toString(); } + return templateName; + } - // Set permissions for the downloaded template - File downloadedTemplate = new File(resourcePath + "/" + templateFilename); - _storage.setWorldReadableAndWriteable(downloadedTemplate); - + private void setPermissionsForTheDownloadedTemplate(DownloadJob dnld, String resourcePath, ResourceType resourceType) { // Set permissions for template/volume.properties String propertiesFile = resourcePath; if (resourceType == ResourceType.TEMPLATE) { @@ -454,16 +478,31 @@ private String postLocalDownload(String jobId) { } File templateProperties = new File(propertiesFile); _storage.setWorldReadableAndWriteable(templateProperties); + } - TemplateLocation loc = new TemplateLocation(_storage, resourcePath); + private String checkOrCreateTheChecksum(DownloadJob dnld, File targetFile) { + ChecksumValue oldValue = new ChecksumValue(dnld.getChecksum()); + ChecksumValue newValue = null; try { - loc.create(dnld.getId(), true, dnld.getTmpltName()); - } catch (IOException e) { - s_logger.warn("Something is wrong with template location " + resourcePath, e); - loc.purge(); - return "Unable to download due to " + e.getMessage(); + newValue = computeCheckSum(oldValue.getAlgorithm(), targetFile); + if (LOGGER.isDebugEnabled()) { + LOGGER.debug(String.format("computed checksum: %s", newValue)); + } + } catch (NoSuchAlgorithmException e) { + return "checksum algorithm not recognised: " + oldValue.getAlgorithm(); + } + if (StringUtils.isNotBlank(dnld.getChecksum()) && !oldValue.equals(newValue)) { + return "checksum \"" + newValue + "\" didn't match the given value, \"" + oldValue + "\""; + } + String checksum = newValue.toString(); + if (checksum == null) { + LOGGER.warn("Something wrong happened when try to calculate the checksum of downloaded template!"); } + dnld.setCheckSum(checksum); + return null; + } + private String postProcessAfterDownloadComplete(DownloadJob dnld, String resourcePath, String templateName, TemplateLocation loc) { Iterator en = _processors.values().iterator(); while (en.hasNext()) { Processor processor = en.next(); @@ -472,7 +511,7 @@ private String postLocalDownload(String jobId) { try { info = processor.process(resourcePath, null, templateName, this._processTimeout); } catch (InternalErrorException e) { - s_logger.error("Template process exception ", e); + LOGGER.error("Template process exception ", e); return e.toString(); } if (info != null) { @@ -490,7 +529,7 @@ private String postLocalDownload(String jobId) { } if (!loc.save()) { - s_logger.warn("Cleaning up because we're unable to save the formats"); + LOGGER.warn("Cleaning up because we're unable to save the formats"); loc.purge(); } @@ -549,7 +588,7 @@ public String downloadPublicTemplate(long id, String url, String name, ImageForm try { if (!_storage.mkdirs(tmpDir)) { - s_logger.warn("Unable to create " + tmpDir); + LOGGER.warn("Unable to create " + tmpDir); return "Unable to create " + tmpDir; } // TO DO - define constant for volume properties. @@ -558,12 +597,12 @@ public String downloadPublicTemplate(long id, String url, String name, ImageForm "volume.properties"); if (file.exists()) { if(! file.delete()) { - s_logger.warn("Deletion of file '" + file.getAbsolutePath() + "' failed."); + LOGGER.warn("Deletion of file '" + file.getAbsolutePath() + "' failed."); } } if (!file.createNewFile()) { - s_logger.warn("Unable to create new file: " + file.getAbsolutePath()); + LOGGER.warn("Unable to create new file: " + file.getAbsolutePath()); return "Unable to create new file: " + file.getAbsolutePath(); } @@ -605,7 +644,7 @@ public String downloadPublicTemplate(long id, String url, String name, ImageForm return jobId; } catch (IOException e) { - s_logger.warn("Unable to download to " + tmpDir, e); + LOGGER.warn("Unable to download to " + tmpDir, e); return null; } } @@ -808,24 +847,32 @@ private String getInstallPath(String jobId) { private List listVolumes(String rootdir) { List result = new ArrayList(); - Script script = new Script(listVolScr, s_logger); + Script script = new Script(listVolScr, LOGGER); script.add("-r", rootdir); - ZfsPathParser zpp = new ZfsPathParser(rootdir); + PathParser zpp = new PathParser(rootdir); script.execute(zpp); + if (script.getExitValue() != 0) { + LOGGER.error("Error while executing script " + script.toString()); + throw new CloudRuntimeException("Error while executing script " + script.toString()); + } result.addAll(zpp.getPaths()); - s_logger.info("found " + zpp.getPaths().size() + " volumes" + zpp.getPaths()); + LOGGER.info("found " + zpp.getPaths().size() + " volumes" + zpp.getPaths()); return result; } private List listTemplates(String rootdir) { List result = new ArrayList(); - Script script = new Script(listTmpltScr, s_logger); + Script script = new Script(listTmpltScr, LOGGER); script.add("-r", rootdir); - ZfsPathParser zpp = new ZfsPathParser(rootdir); + PathParser zpp = new PathParser(rootdir); script.execute(zpp); + if (script.getExitValue() != 0) { + LOGGER.error("Error while executing script " + script.toString()); + throw new CloudRuntimeException("Error while executing script " + script.toString()); + } result.addAll(zpp.getPaths()); - s_logger.info("found " + zpp.getPaths().size() + " templates" + zpp.getPaths()); + LOGGER.info("found " + zpp.getPaths().size() + " templates" + zpp.getPaths()); return result; } @@ -844,13 +891,13 @@ public Map gatherTemplateInfo(String rootDir) { TemplateLocation loc = new TemplateLocation(_storage, path); try { if (!loc.load()) { - s_logger.warn("Post download installation was not completed for " + path); + LOGGER.warn("Post download installation was not completed for " + path); // loc.purge(); _storage.cleanup(path, templateDir); continue; } } catch (IOException e) { - s_logger.warn("Unable to load template location " + path, e); + LOGGER.warn("Unable to load template location " + path, e); continue; } @@ -865,12 +912,12 @@ public Map gatherTemplateInfo(String rootDir) { loc.updateVirtualSize(vSize); loc.save(); } catch (Exception e) { - s_logger.error("Unable to get the virtual size of the template: " + tInfo.getInstallPath() + " due to " + e.getMessage()); + LOGGER.error("Unable to get the virtual size of the template: " + tInfo.getInstallPath() + " due to " + e.getMessage()); } } result.put(tInfo.getTemplateName(), tInfo); - s_logger.debug("Added template name: " + tInfo.getTemplateName() + ", path: " + tmplt); + LOGGER.debug("Added template name: " + tInfo.getTemplateName() + ", path: " + tmplt); } return result; } @@ -890,13 +937,13 @@ public Map gatherVolumeInfo(String rootDir) { TemplateLocation loc = new TemplateLocation(_storage, path); try { if (!loc.load()) { - s_logger.warn("Post download installation was not completed for " + path); + LOGGER.warn("Post download installation was not completed for " + path); // loc.purge(); _storage.cleanup(path, volumeDir); continue; } } catch (IOException e) { - s_logger.warn("Unable to load volume location " + path, e); + LOGGER.warn("Unable to load volume location " + path, e); continue; } @@ -911,43 +958,16 @@ public Map gatherVolumeInfo(String rootDir) { loc.updateVirtualSize(vSize); loc.save(); } catch (Exception e) { - s_logger.error("Unable to get the virtual size of the volume: " + vInfo.getInstallPath() + " due to " + e.getMessage()); + LOGGER.error("Unable to get the virtual size of the volume: " + vInfo.getInstallPath() + " due to " + e.getMessage()); } } result.put(vInfo.getId(), vInfo); - s_logger.debug("Added volume name: " + vInfo.getTemplateName() + ", path: " + vol); + LOGGER.debug("Added volume name: " + vInfo.getTemplateName() + ", path: " + vol); } return result; } - public static class ZfsPathParser extends OutputInterpreter { - String _parent; - List paths = new ArrayList(); - - public ZfsPathParser(String parent) { - _parent = parent; - } - - @Override - public String interpret(BufferedReader reader) throws IOException { - String line = null; - while ((line = reader.readLine()) != null) { - paths.add(line); - } - return null; - } - - public List getPaths() { - return paths; - } - - @Override - public boolean drain() { - return true; - } - } - public DownloadManagerImpl() { } @@ -980,7 +1000,7 @@ public boolean configure(String name, Map params) throws Configu String inSystemVM = (String)params.get("secondary.storage.vm"); if (inSystemVM != null && "true".equalsIgnoreCase(inSystemVM)) { - s_logger.info("DownloadManager: starting additional services since we are inside system vm"); + LOGGER.info("DownloadManager: starting additional services since we are inside system vm"); _nfsVersion = NfsSecondaryStorageResource.retrieveNfsVersionFromParams(params); startAdditionalServices(); blockOutgoingOnPrivate(); @@ -1001,25 +1021,25 @@ public boolean configure(String name, Map params) throws Configu if (listTmpltScr == null) { throw new ConfigurationException("Unable to find the listvmtmplt.sh"); } - s_logger.info("listvmtmplt.sh found in " + listTmpltScr); + LOGGER.info("listvmtmplt.sh found in " + listTmpltScr); createTmpltScr = Script.findScript(scriptsDir, "createtmplt.sh"); if (createTmpltScr == null) { throw new ConfigurationException("Unable to find createtmplt.sh"); } - s_logger.info("createtmplt.sh found in " + createTmpltScr); + LOGGER.info("createtmplt.sh found in " + createTmpltScr); listVolScr = Script.findScript(scriptsDir, "listvolume.sh"); if (listVolScr == null) { throw new ConfigurationException("Unable to find the listvolume.sh"); } - s_logger.info("listvolume.sh found in " + listVolScr); + LOGGER.info("listvolume.sh found in " + listVolScr); createVolScr = Script.findScript(scriptsDir, "createvolume.sh"); if (createVolScr == null) { throw new ConfigurationException("Unable to find createvolume.sh"); } - s_logger.info("createvolume.sh found in " + createVolScr); + LOGGER.info("createvolume.sh found in " + createVolScr); _processors = new HashMap(); @@ -1063,7 +1083,7 @@ public boolean configure(String name, Map params) throws Configu } private void blockOutgoingOnPrivate() { - Script command = new Script("/bin/bash", s_logger); + Script command = new Script("/bin/bash", LOGGER); String intf = "eth1"; command.add("-c"); command.add("iptables -A OUTPUT -o " + intf + " -p tcp -m state --state NEW -m tcp --dport " + "80" + " -j REJECT;" + "iptables -A OUTPUT -o " + intf + @@ -1071,7 +1091,7 @@ private void blockOutgoingOnPrivate() { String result = command.execute(); if (result != null) { - s_logger.warn("Error in blocking outgoing to port 80/443 err=" + result); + LOGGER.warn("Error in blocking outgoing to port 80/443 err=" + result); return; } } @@ -1092,37 +1112,37 @@ public boolean stop() { } private void startAdditionalServices() { - Script command = new Script("/bin/systemctl", s_logger); + Script command = new Script("/bin/systemctl", LOGGER); command.add("stop"); command.add("apache2"); String result = command.execute(); if (result != null) { - s_logger.warn("Error in stopping httpd service err=" + result); + LOGGER.warn("Error in stopping httpd service err=" + result); } String port = Integer.toString(TemplateConstants.DEFAULT_TMPLT_COPY_PORT); String intf = TemplateConstants.DEFAULT_TMPLT_COPY_INTF; - command = new Script("/bin/bash", s_logger); + command = new Script("/bin/bash", LOGGER); command.add("-c"); command.add("iptables -I INPUT -i " + intf + " -p tcp -m state --state NEW -m tcp --dport " + port + " -j ACCEPT;" + "iptables -I INPUT -i " + intf + " -p tcp -m state --state NEW -m tcp --dport " + "443" + " -j ACCEPT;"); result = command.execute(); if (result != null) { - s_logger.warn("Error in opening up apache2 port err=" + result); + LOGGER.warn("Error in opening up apache2 port err=" + result); return; } - command = new Script("/bin/systemctl", s_logger); + command = new Script("/bin/systemctl", LOGGER); command.add("start"); command.add("apache2"); result = command.execute(); if (result != null) { - s_logger.warn("Error in starting apache2 service err=" + result); + LOGGER.warn("Error in starting apache2 service err=" + result); return; } - command = new Script("/bin/su", s_logger); + command = new Script("/bin/su", LOGGER); command.add("-s"); command.add("/bin/bash"); command.add("-c"); @@ -1130,7 +1150,7 @@ private void startAdditionalServices() { command.add("www-data"); result = command.execute(); if (result != null) { - s_logger.warn("Error in creating directory =" + result); + LOGGER.warn("Error in creating directory =" + result); return; } } diff --git a/services/secondary-storage/server/src/test/java/org/apache/cloudstack/storage/resource/NfsSecondaryStorageResourceTest.java b/services/secondary-storage/server/src/test/java/org/apache/cloudstack/storage/resource/NfsSecondaryStorageResourceTest.java index 44d762ff02d7..5ca17b0638d5 100644 --- a/services/secondary-storage/server/src/test/java/org/apache/cloudstack/storage/resource/NfsSecondaryStorageResourceTest.java +++ b/services/secondary-storage/server/src/test/java/org/apache/cloudstack/storage/resource/NfsSecondaryStorageResourceTest.java @@ -18,7 +18,15 @@ */ package org.apache.cloudstack.storage.resource; -import com.cloud.test.TestAppender; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.spy; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.StringWriter; + import org.apache.cloudstack.storage.command.DeleteCommand; import org.apache.cloudstack.storage.to.TemplateObjectTO; import org.apache.log4j.Level; @@ -28,19 +36,14 @@ import org.junit.runner.RunWith; import org.mockito.Mockito; import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PowerMockIgnore; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileWriter; -import java.io.StringWriter; - -import static org.mockito.Matchers.any; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.spy; +import com.cloud.test.TestAppender; @RunWith(PowerMockRunner.class) +@PowerMockIgnore({ "javax.xml.*", "org.xml.*"}) public class NfsSecondaryStorageResourceTest { private NfsSecondaryStorageResource resource; diff --git a/setup/bindir/cloud-setup-databases.in b/setup/bindir/cloud-setup-databases.in index 0e66cfa68ae2..15a817640913 100755 --- a/setup/bindir/cloud-setup-databases.in +++ b/setup/bindir/cloud-setup-databases.in @@ -67,7 +67,7 @@ class DBDeployer(object): dbDotProperties = {} dbDotPropertiesIndex = 0 encryptionKeyFile = '@MSCONF@/key' - encryptionJarPath = '@COMMONLIBDIR@/lib/jasypt-1.9.2.jar' + encryptionJarPath = '@COMMONLIBDIR@/lib/jasypt-1.9.3.jar' success = False magicString = 'This_is_a_magic_string_i_think_no_one_will_duplicate' tmpMysqlFile = os.path.join(os.path.expanduser('~/'), 'cloudstackmysql.tmp.sql') diff --git a/setup/bindir/cloud-setup-encryption.in b/setup/bindir/cloud-setup-encryption.in index 0c9b650fdb6e..54447f77c39d 100755 --- a/setup/bindir/cloud-setup-encryption.in +++ b/setup/bindir/cloud-setup-encryption.in @@ -63,7 +63,7 @@ class DBDeployer(object): dbDotProperties = {} dbDotPropertiesIndex = 0 encryptionKeyFile = '@MSCONF@/key' - encryptionJarPath = '@COMMONLIBDIR@/lib/jasypt-1.9.2.jar' + encryptionJarPath = '@COMMONLIBDIR@/lib/jasypt-1.9.3.jar' success = False magicString = 'This_is_a_magic_string_i_think_no_one_will_duplicate' diff --git a/systemvm/debian/etc/logrotate.d/monitor b/systemvm/debian/etc/logrotate.d/monitor new file mode 100644 index 000000000000..769f8d5e7e14 --- /dev/null +++ b/systemvm/debian/etc/logrotate.d/monitor @@ -0,0 +1,24 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. +/var/log/monitor.log { + rotate 5 + maxsize 10M + missingok + notifempty + compress + copytruncate +} diff --git a/systemvm/debian/etc/logrotate.d/routerServiceMonitor b/systemvm/debian/etc/logrotate.d/routerServiceMonitor new file mode 100644 index 000000000000..7202441f66ac --- /dev/null +++ b/systemvm/debian/etc/logrotate.d/routerServiceMonitor @@ -0,0 +1,24 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. +/var/log/routerServiceMonitor.log { + rotate 5 + maxsize 10M + missingok + notifempty + compress + copytruncate +} diff --git a/systemvm/debian/lib/systemd/system/baremetal-vr.service b/systemvm/debian/etc/systemd/system/baremetal-vr.service similarity index 100% rename from systemvm/debian/lib/systemd/system/baremetal-vr.service rename to systemvm/debian/etc/systemd/system/baremetal-vr.service diff --git a/systemvm/debian/lib/systemd/system/cloud.service b/systemvm/debian/etc/systemd/system/cloud.service similarity index 100% rename from systemvm/debian/lib/systemd/system/cloud.service rename to systemvm/debian/etc/systemd/system/cloud.service diff --git a/systemvm/debian/lib/systemd/system/hyperv-daemons.hv-fcopy-daemon.service b/systemvm/debian/etc/systemd/system/hyperv-daemons.hv-fcopy-daemon.service similarity index 100% rename from systemvm/debian/lib/systemd/system/hyperv-daemons.hv-fcopy-daemon.service rename to systemvm/debian/etc/systemd/system/hyperv-daemons.hv-fcopy-daemon.service diff --git a/systemvm/debian/lib/systemd/system/hyperv-daemons.hv-kvp-daemon.service b/systemvm/debian/etc/systemd/system/hyperv-daemons.hv-kvp-daemon.service similarity index 100% rename from systemvm/debian/lib/systemd/system/hyperv-daemons.hv-kvp-daemon.service rename to systemvm/debian/etc/systemd/system/hyperv-daemons.hv-kvp-daemon.service diff --git a/systemvm/debian/lib/systemd/system/hyperv-daemons.hv-vss-daemon.service b/systemvm/debian/etc/systemd/system/hyperv-daemons.hv-vss-daemon.service similarity index 100% rename from systemvm/debian/lib/systemd/system/hyperv-daemons.hv-vss-daemon.service rename to systemvm/debian/etc/systemd/system/hyperv-daemons.hv-vss-daemon.service diff --git a/systemvm/debian/lib/systemd/system/open-vm-tools.service b/systemvm/debian/etc/systemd/system/open-vm-tools.service similarity index 100% rename from systemvm/debian/lib/systemd/system/open-vm-tools.service rename to systemvm/debian/etc/systemd/system/open-vm-tools.service diff --git a/systemvm/debian/lib/systemd/system/xe-daemon.service b/systemvm/debian/etc/systemd/system/xe-daemon.service similarity index 100% rename from systemvm/debian/lib/systemd/system/xe-daemon.service rename to systemvm/debian/etc/systemd/system/xe-daemon.service diff --git a/systemvm/debian/opt/cloud/bin/configure.py b/systemvm/debian/opt/cloud/bin/configure.py index cd0ef350ecb8..cadb7c54f055 100755 --- a/systemvm/debian/opt/cloud/bin/configure.py +++ b/systemvm/debian/opt/cloud/bin/configure.py @@ -793,6 +793,12 @@ def getGuestIp(self): return None + def getGuestIpByIp(self, ipa): + for interface in self.config.address().get_interfaces(): + if interface.ip_in_subnet(ipa): + return interface.get_ip() + return None + def getDeviceByIp(self, ipa): for interface in self.config.address().get_interfaces(): if interface.ip_in_subnet(ipa): @@ -930,8 +936,20 @@ def forward_vpc(self, rule): if not rule["internal_ports"] == "any": fw_output_rule += ":" + self.portsToString(rule["internal_ports"], "-") + fw_postrout_rule2 = "-j SNAT --to-source %s -A POSTROUTING -s %s -d %s/32 -o %s -p %s -m %s --dport %s" % \ + ( + self.getGuestIpByIp(rule['internal_ip']), + self.getNetworkByIp(rule['internal_ip']), + rule['internal_ip'], + self.getDeviceByIp(rule['internal_ip']), + rule['protocol'], + rule['protocol'], + self.portsToString(rule['internal_ports'], ':') + ) + self.fw.append(["nat", "", fw_prerout_rule]) self.fw.append(["nat", "", fw_postrout_rule]) + self.fw.append(["nat", "", fw_postrout_rule2]) self.fw.append(["nat", "", fw_output_rule]) def processStaticNatRule(self, rule): @@ -941,11 +959,11 @@ def processStaticNatRule(self, rule): raise Exception("Ip address %s has no device in the ips databag" % rule["public_ip"]) self.fw.append(["mangle", "front", - "-A PREROUTING -s %s/32 -m state --state NEW -j CONNMARK --save-mark --nfmask 0xffffffff --ctmask 0xffffffff" % - rule["internal_ip"]]) + "-A PREROUTING -d %s/32 -m state --state NEW -j CONNMARK --save-mark --nfmask 0xffffffff --ctmask 0xffffffff" % + rule["public_ip"]]) self.fw.append(["mangle", "front", - "-A PREROUTING -s %s/32 -m state --state NEW -j MARK --set-xmark %s/0xffffffff" % - (rule["internal_ip"], hex(100 + int(device[len("eth"):])))]) + "-A PREROUTING -d %s/32 -m state --state NEW -j MARK --set-xmark %s/0xffffffff" % + (rule["public_ip"], hex(100 + int(device[len("eth"):])))]) self.fw.append(["nat", "front", "-A PREROUTING -d %s/32 -j DNAT --to-destination %s" % (rule["public_ip"], rule["internal_ip"])]) self.fw.append(["nat", "front", diff --git a/systemvm/debian/opt/cloud/bin/cs/CsHelper.py b/systemvm/debian/opt/cloud/bin/cs/CsHelper.py index e29891796b8b..5998fd9dbc97 100755 --- a/systemvm/debian/opt/cloud/bin/cs/CsHelper.py +++ b/systemvm/debian/opt/cloud/bin/cs/CsHelper.py @@ -29,8 +29,8 @@ PUBLIC_INTERFACES = {"router": "eth2", "vpcrouter": "eth1"} -STATE_COMMANDS = {"router": "ip addr | grep eth0 | grep inet | wc -l | xargs bash -c 'if [ $0 == 2 ]; then echo \"MASTER\"; else echo \"BACKUP\"; fi'", - "vpcrouter": "ip addr | grep eth1 | grep state | awk '{print $9;}' | xargs bash -c 'if [ $0 == \"UP\" ]; then echo \"MASTER\"; else echo \"BACKUP\"; fi'"} +STATE_COMMANDS = {"router": "ip addr show dev eth0 | grep inet | wc -l | xargs bash -c 'if [ $0 == 2 ]; then echo \"MASTER\"; else echo \"BACKUP\"; fi'", + "vpcrouter": "ip addr show dev eth1 | grep state | awk '{print $9;}' | xargs bash -c 'if [ $0 == \"UP\" ]; then echo \"MASTER\"; else echo \"BACKUP\"; fi'"} def reconfigure_interfaces(router_config, interfaces): @@ -215,7 +215,7 @@ def save_iptables(command, iptables_file): def execute2(command, wait=True): """ Execute command """ - logging.debug("Executing: %s" % command) + logging.info("Executing: %s" % command) p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) if wait: p.wait() diff --git a/systemvm/debian/opt/cloud/bin/cs/CsLoadBalancer.py b/systemvm/debian/opt/cloud/bin/cs/CsLoadBalancer.py index d8f39dcd24a2..a45d57efe790 100755 --- a/systemvm/debian/opt/cloud/bin/cs/CsLoadBalancer.py +++ b/systemvm/debian/opt/cloud/bin/cs/CsLoadBalancer.py @@ -45,7 +45,7 @@ def process(self): if not file2.compare(file1): CsHelper.copy(HAPROXY_CONF_T, HAPROXY_CONF_P) - proc = CsProcess(['/var/run/haproxy.pid']) + proc = CsProcess(['/run/haproxy.pid']) if not proc.find(): logging.debug("CsLoadBalancer:: will restart HAproxy!") CsHelper.service("haproxy", "restart") diff --git a/systemvm/debian/opt/cloud/bin/cs/CsMonitor.py b/systemvm/debian/opt/cloud/bin/cs/CsMonitor.py index 6b194238b1ac..5a0ff5b114c4 100755 --- a/systemvm/debian/opt/cloud/bin/cs/CsMonitor.py +++ b/systemvm/debian/opt/cloud/bin/cs/CsMonitor.py @@ -17,27 +17,67 @@ import logging from cs.CsDatabag import CsDataBag from CsFile import CsFile +import json MON_CONFIG = "/etc/monitor.conf" +HC_CONFIG = "/root/health_checks_data.json" class CsMonitor(CsDataBag): - """ Manage dhcp entries """ + """ Manage Monitor script schedule and health checks for router """ - def process(self): - if "config" not in self.dbag: - return - procs = [x.strip() for x in self.dbag['config'].split(',')] - file = CsFile(MON_CONFIG) - for proc in procs: - bits = [x for x in proc.split(':')] - if len(bits) < 5: - continue - for i in range(0, 4): - file.add(bits[i], -1) - file.commit() + def get_basic_check_interval(self): + return self.dbag["health_checks_basic_run_interval"] if "health_checks_basic_run_interval" in self.dbag else 3 + + def get_advanced_check_interval(self): + return self.dbag["health_checks_advanced_run_interval"] if "health_checks_advanced_run_interval" in self.dbag else 0 + + def setupMonitorConfigFile(self): + if "config" in self.dbag: + procs = [x.strip() for x in self.dbag['config'].split(',')] + file = CsFile(MON_CONFIG) + for proc in procs: + bits = [x for x in proc.split(':')] + if len(bits) < 5: + continue + for i in range(0, 4): + file.add(bits[i], -1) + file.commit() + + def setupHealthCheckCronJobs(self): + cron_rep_basic = self.get_basic_check_interval() + cron_rep_advanced = self.get_advanced_check_interval() cron = CsFile("/etc/cron.d/process") + cron.deleteLine("root /usr/bin/python /root/monitorServices.py") cron.add("SHELL=/bin/bash", 0) cron.add("PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin", 1) - cron.add("*/3 * * * * root /usr/bin/python /root/monitorServices.py", -1) + if cron_rep_basic > 0: + cron.add("*/" + str(cron_rep_basic) + " * * * * root /usr/bin/python /root/monitorServices.py basic", -1) + if cron_rep_advanced > 0: + cron.add("*/" + str(cron_rep_advanced) + " * * * * root /usr/bin/python /root/monitorServices.py advanced", -1) cron.commit() + + def setupHealthChecksConfigFile(self): + hc_data = {} + hc_data["health_checks_basic_run_interval"] = self.get_basic_check_interval() + hc_data["health_checks_advanced_run_interval"] = self.get_advanced_check_interval() + hc_data["health_checks_enabled"] = self.dbag["health_checks_enabled"] if "health_checks_enabled" in self.dbag else False + + if "excluded_health_checks" in self.dbag: + excluded_checks = self.dbag["excluded_health_checks"] + hc_data["excluded_health_checks"] = [ch.strip() for ch in excluded_checks.split(",")] if len(excluded_checks) > 0 else [] + else: + hc_data["excluded_health_checks"] = [] + + if "health_checks_config" in self.dbag: + hc_data["health_checks_config"] = self.dbag["health_checks_config"] + else: + hc_data["health_checks_config"] = {} + + with open(HC_CONFIG, 'w') as f: + json.dump(hc_data, f, ensure_ascii=False, indent=4) + + def process(self): + self.setupMonitorConfigFile() + self.setupHealthChecksConfigFile() + self.setupHealthCheckCronJobs() diff --git a/systemvm/debian/opt/cloud/bin/cs/CsRedundant.py b/systemvm/debian/opt/cloud/bin/cs/CsRedundant.py index 441723b29a61..8f389611191e 100755 --- a/systemvm/debian/opt/cloud/bin/cs/CsRedundant.py +++ b/systemvm/debian/opt/cloud/bin/cs/CsRedundant.py @@ -102,7 +102,7 @@ def _redundant_on(self): command = "ip link show %s | grep 'state UP'" % dev devUp = CsHelper.execute(command) if devUp: - logging.info("Device %s is present, let's start keepalive now." % dev) + logging.info("Device %s is present, let's start keepalived now." % dev) isDeviceReady = True if not isDeviceReady: @@ -231,7 +231,7 @@ def set_fault(self): return self.set_lock() - logging.info("Router switched to fault mode") + logging.info("Setting router to fault") interfaces = [interface for interface in self.address.get_interfaces() if interface.is_public()] for interface in interfaces: diff --git a/systemvm/debian/opt/cloud/bin/cs_monitorservice.py b/systemvm/debian/opt/cloud/bin/cs_monitorservice.py index 75a7c95d6fac..55c89dfb59b3 100755 --- a/systemvm/debian/opt/cloud/bin/cs_monitorservice.py +++ b/systemvm/debian/opt/cloud/bin/cs_monitorservice.py @@ -22,4 +22,15 @@ def merge(dbag, data): if "config" in data: dbag['config'] = data["config"] + if "health_checks_enabled" in data: + dbag["health_checks_enabled"] = data["health_checks_enabled"] + if "health_checks_basic_run_interval" in data: + dbag["health_checks_basic_run_interval"] = data["health_checks_basic_run_interval"] + if "health_checks_advanced_run_interval" in data: + dbag["health_checks_advanced_run_interval"] = data["health_checks_advanced_run_interval"] + if "excluded_health_checks" in data: + dbag["excluded_health_checks"] = data["excluded_health_checks"] + if "health_checks_config" in data: + dbag["health_checks_config"] = data["health_checks_config"] + return dbag diff --git a/systemvm/debian/opt/cloud/bin/getRouterAlerts.sh b/systemvm/debian/opt/cloud/bin/getRouterAlerts.sh old mode 100644 new mode 100755 diff --git a/systemvm/debian/opt/cloud/bin/getRouterMonitorResults.sh b/systemvm/debian/opt/cloud/bin/getRouterMonitorResults.sh new file mode 100755 index 000000000000..bdc709d265f4 --- /dev/null +++ b/systemvm/debian/opt/cloud/bin/getRouterMonitorResults.sh @@ -0,0 +1,55 @@ +#!/usr/bin/env bash +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. + +# getRouterMonitorResults.sh --- Send the monitor results to Management Server + +if [ "$1" == "true" ] +then + python /root/monitorServices.py > /dev/null +fi + +printf "FAILING CHECKS:\n" + +if [ -f /root/basic_failing_health_checks ] +then + echo `cat /root/basic_failing_health_checks` +fi + +if [ -f /root/advanced_failing_health_checks ] +then + echo `cat /root/advanced_failing_health_checks` +fi + +printf "MONITOR RESULTS:\n" + +echo "{\"basic\":" +if [ -f /root/basic_monitor_results.json ] +then + echo `cat /root/basic_monitor_results.json` +else + echo "{}" +fi +echo ",\"advanced\":" +if [ -f /root/advanced_monitor_results.json ] +then + echo `cat /root/advanced_monitor_results.json` +else + echo "{}" +fi + +echo "}" diff --git a/systemvm/debian/opt/cloud/bin/merge.py b/systemvm/debian/opt/cloud/bin/merge.py index 54d86c5e8bb2..b988b7a3e37e 100755 --- a/systemvm/debian/opt/cloud/bin/merge.py +++ b/systemvm/debian/opt/cloud/bin/merge.py @@ -301,6 +301,7 @@ def load(self, data): if self.keep: self.__moveFile(filename, self.configCache + "/processed") else: + logging.debug("Processed file deleted: %s and not kept in /processed", filename) os.remove(filename) updateDataBag(self) diff --git a/systemvm/debian/opt/cloud/bin/update_config.py b/systemvm/debian/opt/cloud/bin/update_config.py index 77008afb794b..c9121eb634f9 100755 --- a/systemvm/debian/opt/cloud/bin/update_config.py +++ b/systemvm/debian/opt/cloud/bin/update_config.py @@ -29,7 +29,8 @@ logging.basicConfig(filename='/var/log/cloud.log', level=logging.INFO, format='%(asctime)s %(filename)s %(funcName)s:%(lineno)d %(message)s') # first commandline argument should be the file to process -if (len(sys.argv) != 2): +argc = len(sys.argv) +if argc != 2 and argc != 3: logging.error("Invalid usage, args passed: %s" % sys.argv) sys.exit(1) @@ -49,6 +50,9 @@ def finish_config(): def process_file(): logging.info("Processing JSON file %s" % sys.argv[1]) qf = QueueFile() + if len(sys.argv) > 2 and sys.argv[2].lower() == "false": + qf.keep = False + qf.setFile(sys.argv[1]) qf.load(None) # These can be safely deferred, dramatically speeding up loading times diff --git a/systemvm/debian/root/health_checks/__init__.py b/systemvm/debian/root/health_checks/__init__.py new file mode 100644 index 000000000000..3dcbe822698f --- /dev/null +++ b/systemvm/debian/root/health_checks/__init__.py @@ -0,0 +1,20 @@ +#!/usr/bin/python +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. + +# Needed to expose utility as package outside for monitorServices.py. +# This directory should only contain executables for health checks. diff --git a/systemvm/debian/root/health_checks/cpu_usage_check.py b/systemvm/debian/root/health_checks/cpu_usage_check.py new file mode 100644 index 000000000000..5e6a2fe5e9e8 --- /dev/null +++ b/systemvm/debian/root/health_checks/cpu_usage_check.py @@ -0,0 +1,56 @@ +#!/usr/bin/python +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. + +from os import sys, path, statvfs +from subprocess import * +from utility import getHealthChecksData + + +def main(): + entries = getHealthChecksData("systemThresholds") + data = {} + if entries is not None and len(entries) == 1: + data = entries[0] + + if "maxCpuUsage" not in data: + print "Missing maxCpuUsage in health_checks_data systemThresholds, skipping" + exit(0) + + maxCpuUsage = float(data["maxCpuUsage"]) + cmd = "top -b -n2 -p 1 | fgrep \"Cpu(s)\" | tail -1 | " \ + "awk -F 'id,' " \ + "'{ split($1, vs, \",\"); idle=vs[length(vs)]; " \ + "sub(\"%\", \"\", idle); printf \"%.2f\", 100 - idle }'" + pout = Popen(cmd, shell=True, stdout=PIPE) + if pout.wait() == 0: + currentUsage = float(pout.communicate()[0].strip()) + if currentUsage > maxCpuUsage: + print "CPU Usage " + str(currentUsage) + \ + "% has crossed threshold of " + str(maxCpuUsage) + "%" + exit(1) + print "CPU Usage within limits with current at " \ + + str(currentUsage) + "%" + exit(0) + else: + print "Failed to retrieve cpu usage using " + cmd + exit(1) + + +if __name__ == "__main__": + if len(sys.argv) == 2 and sys.argv[1] == "basic": + main() diff --git a/systemvm/debian/root/health_checks/dhcp_check.py b/systemvm/debian/root/health_checks/dhcp_check.py new file mode 100755 index 000000000000..be7a8407e395 --- /dev/null +++ b/systemvm/debian/root/health_checks/dhcp_check.py @@ -0,0 +1,69 @@ +#!/usr/bin/python +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. + +from os import sys, path +from utility import getHealthChecksData + + +def main(): + vMs = getHealthChecksData("virtualMachines") + + if vMs is None or len(vMs) == 0: + print "No VMs running data available, skipping" + exit(0) + + with open('/etc/dhcphosts.txt', 'r') as hostsFile: + allHosts = hostsFile.readlines() + hostsFile.close() + + failedCheck = False + failureMessage = "Missing elements in dhcphosts.txt - \n" + for vM in vMs: + entry = vM["macAddress"] + " " + vM["ip"] + " " + vM["vmName"] + foundEntry = False + for host in allHosts: + host = host.strip().split(',') + if len(host) < 4: + continue + + if host[0].strip() == vM["macAddress"] and host[1].strip() == vM["ip"]\ + and host[2].strip() == vM["vmName"]: + foundEntry = True + break + + nonDefaultSet = "set:" + vM["ip"].replace(".", "_") + if host[0].strip() == vM["macAddress"] and host[1].strip() == nonDefaultSet \ + and host[2].strip() == vM["ip"] and host[3].strip() == vM["vmName"]: + foundEntry = True + break + + if not foundEntry: + failedCheck = True + failureMessage = failureMessage + entry + ", " + + if failedCheck: + print failureMessage[:-2] + exit(1) + else: + print "All " + str(len(vMs)) + " VMs are present in dhcphosts.txt" + exit(0) + + +if __name__ == "__main__": + if len(sys.argv) == 2 and sys.argv[1] == "advanced": + main() diff --git a/systemvm/debian/root/health_checks/disk_space_check.py b/systemvm/debian/root/health_checks/disk_space_check.py new file mode 100644 index 000000000000..af8cb3dd07cf --- /dev/null +++ b/systemvm/debian/root/health_checks/disk_space_check.py @@ -0,0 +1,47 @@ +#!/usr/bin/python +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. + +from os import sys, path, statvfs +from utility import getHealthChecksData + + +def main(): + entries = getHealthChecksData("systemThresholds") + data = {} + if entries is not None and len(entries) == 1: + data = entries[0] + + if "minDiskNeeded" not in data: + print "Missing minDiskNeeded in health_checks_data systemThresholds, skipping" + exit(0) + + minDiskNeeded = float(data["minDiskNeeded"]) * 1024 + s = statvfs('/') + freeSpace = (s.f_bavail * s.f_frsize) / 1024 + + if (freeSpace < minDiskNeeded): + print "Insufficient free space is " + str(freeSpace/1024) + " MB" + exit(1) + else: + print "Sufficient free space is " + str(freeSpace/1024) + " MB" + exit(0) + + +if __name__ == "__main__": + if len(sys.argv) == 2 and sys.argv[1] == "basic": + main() diff --git a/systemvm/debian/root/health_checks/dns_check.py b/systemvm/debian/root/health_checks/dns_check.py new file mode 100644 index 000000000000..c17788812330 --- /dev/null +++ b/systemvm/debian/root/health_checks/dns_check.py @@ -0,0 +1,59 @@ +#!/usr/bin/python +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. + +from os import sys, path +from utility import getHealthChecksData + + +def main(): + vMs = getHealthChecksData("virtualMachines") + + if vMs is None or len(vMs) == 0: + print "No VMs running data available, skipping" + exit(0) + + with open('/etc/hosts', 'r') as hostsFile: + allHosts = hostsFile.readlines() + hostsFile.close() + + failedCheck = False + failureMessage = "Missing entries for VMs in /etc/hosts -\n" + for vM in vMs: + foundEntry = False + for host in allHosts: + components = host.split('\t') + if len(components) == 2 and components[0].strip() == vM["ip"] \ + and components[1].strip() == vM["vmName"]: + foundEntry = True + break + + if not foundEntry: + failedCheck = True + failureMessage = failureMessage + vM["ip"] + " " + vM["vmName"] + ", " + + if failedCheck: + print failureMessage[:-2] + exit(1) + else: + print "All " + str(len(vMs)) + " VMs are present in /etc/hosts" + exit(0) + + +if __name__ == "__main__": + if len(sys.argv) == 2 and sys.argv[1] == "advanced": + main() diff --git a/systemvm/debian/root/health_checks/gateways_check.py b/systemvm/debian/root/health_checks/gateways_check.py new file mode 100644 index 000000000000..29ce884ca997 --- /dev/null +++ b/systemvm/debian/root/health_checks/gateways_check.py @@ -0,0 +1,57 @@ +#!/usr/bin/python +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. + +from os import sys, path +from subprocess import * +from utility import getHealthChecksData + + +def main(): + gws = getHealthChecksData("gateways") + if gws is None and len(gws) == 0: + print "No gateways data available, skipping" + exit(0) + + unreachableGateWays = [] + gwsList = gws[0]["gatewaysIps"].strip().split(' ') + for gw in gwsList: + if len(gw) == 0: + continue + reachableGw = False + for i in range(5): + pingCmd = "ping " + gw + " -c 5 -w 10" + pout = Popen(pingCmd, shell=True, stdout=PIPE) + if pout.wait() == 0: + reachableGw = True + break + + if not reachableGw: + unreachableGateWays.append(gw) + + if len(unreachableGateWays) == 0: + print "All " + str(len(gws)) + " gateways are reachable via ping" + exit(0) + else: + print "Unreachable gateways found-" + print unreachableGateWays + exit(1) + + +if __name__ == "__main__": + if len(sys.argv) == 2 and sys.argv[1] == "basic": + main() diff --git a/systemvm/debian/root/health_checks/haproxy_check.py b/systemvm/debian/root/health_checks/haproxy_check.py new file mode 100644 index 000000000000..56e0ce7d0b0d --- /dev/null +++ b/systemvm/debian/root/health_checks/haproxy_check.py @@ -0,0 +1,134 @@ +#!/usr/bin/python +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. + +from os import sys, path +from utility import getHealthChecksData, formatPort + + +def checkMaxconn(haproxyData, haCfgSections): + if "maxconn" in haproxyData and "maxconn" in haCfgSections["global"]: + if haproxyData["maxconn"] != haCfgSections["global"]["maxconn"][0].strip(): + print "global maxconn mismatch occured" + return False + + return True + + +def checkLoadBalance(haproxyData, haCfgSections): + correct = True + for lbSec in haproxyData: + srcServer = lbSec["sourceIp"].replace('.', '_') + "-" + \ + formatPort(lbSec["sourcePortStart"], + lbSec["sourcePortEnd"]) + secName = "listen " + srcServer + + if secName not in haCfgSections: + print "Missing section for load balancing " + secName + "\n" + correct = False + else: + cfgSection = haCfgSections[secName] + if "server" in cfgSection: + if lbSec["algorithm"] != cfgSection["balance"][0]: + print "Incorrect balance method for " + secName + \ + "Expected : " + lbSec["algorithm"] + \ + " but found " + cfgSection["balance"][0] + "\n" + correct = False + + bindStr = lbSec["sourceIp"] + ":" + formatPort(lbSec["sourcePortStart"], lbSec["sourcePortEnd"]) + if cfgSection["bind"][0] != bindStr: + print "Incorrect bind string found. Expected " + bindStr + " but found " + cfgSection["bind"][0] + "." + correct = False + + if (lbSec["sourcePortStart"] == "80" and lbSec["sourcePortEnd"] == "80" and lbSec["keepAliveEnabled"] == "false") \ + or (lbSec["stickiness"].find("AppCookie") != -1 or lbSec["stickiness"].find("LbCookie") != -1): + if not ("mode" in cfgSection and cfgSection["mode"][0] == "http"): + print "Expected HTTP mode but not found" + correct = False + + expectedServerIps = lbSec["vmIps"].split(" ") + for expectedServerIp in expectedServerIps: + pattern = expectedServerIp + ":" + \ + formatPort(lbSec["destPortStart"], + lbSec["destPortEnd"]) + foundPattern = False + for server in cfgSection["server"]: + s = server.split() + if s[0].strip().find(srcServer + "_") == 0 and s[1].strip() == pattern: + foundPattern = True + break + + if not foundPattern: + correct = False + print "Missing load balancing for " + pattern + ". " + + return correct + + +def main(): + ''' + Checks for max con and each load balancing rule - source ip, ports and destination + ips and ports. Also checks for http mode. Does not check for stickiness policies. + ''' + haproxyData = getHealthChecksData("haproxyData") + if haproxyData is None or len(haproxyData) == 0: + print "No data provided to check, skipping" + exit(0) + + with open("/etc/haproxy/haproxy.cfg", 'r') as haCfgFile: + haCfgLines = haCfgFile.readlines() + haCfgFile.close() + + if len(haCfgLines) == 0: + print "Unable to read config file /etc/haproxy/haproxy.cfg" + exit(1) + + haCfgSections = {} + currSection = None + currSectionDict = {} + for line in haCfgLines: + line = line.strip() + if len(line) == 0: + if currSection is not None and len(currSectionDict) > 0: + haCfgSections[currSection] = currSectionDict + + currSection = None + currSectionDict = {} + continue + + if currSection is None: + currSection = line + else: + lineSec = line.split(' ', 1) + if lineSec[0] not in currSectionDict: + currSectionDict[lineSec[0]] = [] + + currSectionDict[lineSec[0]].append(lineSec[1] if len(lineSec) > 1 else '') + + checkMaxConn = checkMaxconn(haproxyData[0], haCfgSections) + checkLbRules = checkLoadBalance(haproxyData, haCfgSections) + + if checkMaxConn and checkLbRules: + print "All checks pass" + exit(0) + else: + exit(1) + + +if __name__ == "__main__": + if len(sys.argv) == 2 and sys.argv[1] == "advanced": + main() diff --git a/systemvm/debian/root/health_checks/iptables_check.py b/systemvm/debian/root/health_checks/iptables_check.py new file mode 100644 index 000000000000..2f3dc5026723 --- /dev/null +++ b/systemvm/debian/root/health_checks/iptables_check.py @@ -0,0 +1,81 @@ +#!/usr/bin/python +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. + +from os import sys, path +from subprocess import * +from utility import getHealthChecksData, formatPort + + +def main(): + portForwards = getHealthChecksData("portForwarding") + if portForwards is None or len(portForwards) == 0: + print "No portforwarding rules provided to check, skipping" + exit(0) + + failedCheck = False + failureMessage = "Missing port forwarding rules in Iptables-\n " + for portForward in portForwards: + entriesExpected = [] + destIp = portForward["destIp"] + srcIpText = "-d " + portForward["sourceIp"] + srcPortText = "--dport " + formatPort(portForward["sourcePortStart"], portForward["sourcePortEnd"], ":") + dstText = destIp + ":" + formatPort(portForward["destPortStart"], portForward["destPortEnd"], "-") + for algo in [["PREROUTING", "--to-destination"], + ["OUTPUT", "--to-destination"], + ["POSTROUTING", "--to-source"]]: + entriesExpected.append([algo[0], srcIpText, srcPortText, algo[1] + " " + dstText]) + + fetchIpTableEntriesCmd = "iptables-save | grep " + destIp + pout = Popen(fetchIpTableEntriesCmd, shell=True, stdout=PIPE) + if pout.wait() != 0: + failedCheck = True + failureMessage = failureMessage + "Unable to execute iptables-save command " \ + "for fetching rules by " + fetchIpTableEntriesCmd + "\n" + continue + + ipTablesMatchingEntries = pout.communicate()[0].strip().split('\n') + for pfEntryListExpected in entriesExpected: + foundPfEntryList = False + for ipTableEntry in ipTablesMatchingEntries: + # Check if all expected parts of pfEntryList + # is present in this ipTableEntry + foundAll = True + for expectedEntry in pfEntryListExpected: + if ipTableEntry.find(expectedEntry) == -1: + foundAll = False + break + + if foundAll: + foundPfEntryList = True + break + + if not foundPfEntryList: + failedCheck = True + failureMessage = failureMessage + str(pfEntryListExpected) + "\n" + + if failedCheck: + print failureMessage + exit(1) + else: + print "Found all entries (count " + str(len(portForwards)) + ") in iptables" + exit(0) + + +if __name__ == "__main__": + if len(sys.argv) == 2 and sys.argv[1] == "advanced": + main() diff --git a/systemvm/debian/root/health_checks/memory_usage_check.py b/systemvm/debian/root/health_checks/memory_usage_check.py new file mode 100644 index 000000000000..97ca0c5030e8 --- /dev/null +++ b/systemvm/debian/root/health_checks/memory_usage_check.py @@ -0,0 +1,55 @@ +#!/usr/bin/python +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. + +from os import sys, path, statvfs +from subprocess import * +from utility import getHealthChecksData + + +def main(): + entries = getHealthChecksData("systemThresholds") + data = {} + if entries is not None and len(entries) == 1: + data = entries[0] + + if "maxMemoryUsage" not in data: + print "Missing maxMemoryUsage in health_checks_data " + \ + "systemThresholds, skipping" + exit(0) + + maxMemoryUsage = float(data["maxMemoryUsage"]) + cmd = "free | awk 'FNR == 2 { print $3 * 100 / $2 }'" + pout = Popen(cmd, shell=True, stdout=PIPE) + + if pout.wait() == 0: + currentUsage = float(pout.communicate()[0].strip()) + if currentUsage > maxMemoryUsage: + print "Memory Usage " + str(currentUsage) + \ + "% has crossed threshold of " + str(maxMemoryUsage) + "%" + exit(1) + print "Memory Usage within limits with current at " + \ + str(currentUsage) + "%" + exit(0) + else: + print "Failed to retrieve memory usage using " + cmd + exit(1) + + +if __name__ == "__main__": + if len(sys.argv) == 2 and sys.argv[1] == "basic": + main() diff --git a/systemvm/debian/root/health_checks/router_version_check.py b/systemvm/debian/root/health_checks/router_version_check.py new file mode 100644 index 000000000000..2173e09c81f0 --- /dev/null +++ b/systemvm/debian/root/health_checks/router_version_check.py @@ -0,0 +1,83 @@ +#!/usr/bin/python +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. + +from os import sys, path, statvfs +from utility import getHealthChecksData + + +def getFirstLine(file=None): + if file is not None and path.isfile(file): + ret = None + with open(file, 'r') as oFile: + lines = oFile.readlines() + if len(lines) > 0: + ret = lines[0].strip() + oFile.close() + + return ret + else: + return None + + +def main(): + entries = getHealthChecksData("routerVersion") + data = {} + if entries is not None and len(entries) == 1: + data = entries[0] + + if len(data) == 0: + print "Missing routerVersion in health_checks_data, skipping" + exit(0) + + templateVersionMatches = True + scriptVersionMatches = True + + if "templateVersion" in data: + expected = data["templateVersion"].strip() + releaseFile = "/etc/cloudstack-release" + found = getFirstLine(releaseFile) + if found is None: + print "Release version not yet setup at " + releaseFile +\ + ", skipping." + elif expected != found: + print "Template Version mismatch. Expected: " + \ + expected + ", found: " + found + templateVersionMatches = False + + if "scriptsVersion" in data: + expected = data["scriptsVersion"].strip() + sigFile = "/var/cache/cloud/cloud-scripts-signature" + found = getFirstLine(sigFile) + if found is None: + print "Scripts signature is not yet setup at " + sigFile +\ + ", skipping" + if expected != found: + print "Scripts Version mismatch. Expected: " + \ + expected + ", found: " + found + scriptVersionMatches = False + + if templateVersionMatches and scriptVersionMatches: + print "Template and scripts version match successful" + exit(0) + else: + exit(1) + + +if __name__ == "__main__": + if len(sys.argv) == 2 and sys.argv[1] == "basic": + main() diff --git a/systemvm/debian/root/health_checks/utility/__init__.py b/systemvm/debian/root/health_checks/utility/__init__.py new file mode 100644 index 000000000000..22ac3ff90137 --- /dev/null +++ b/systemvm/debian/root/health_checks/utility/__init__.py @@ -0,0 +1,19 @@ +#!/usr/bin/python +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. + +from sharedFunctions import getHealthChecksData, formatPort diff --git a/systemvm/debian/root/health_checks/utility/sharedFunctions.py b/systemvm/debian/root/health_checks/utility/sharedFunctions.py new file mode 100644 index 000000000000..20ef640b64a2 --- /dev/null +++ b/systemvm/debian/root/health_checks/utility/sharedFunctions.py @@ -0,0 +1,54 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. + +import json + + +def getHealthChecksData(additionalDataKey=None): + with open('/root/health_checks_data.json', 'r') as hc_data_file: + hc_data = json.load(hc_data_file) + + # If no specific key is requested return all the data as JSON + if additionalDataKey is None: + return hc_data + + if additionalDataKey not in hc_data["health_checks_config"]: + return None + + data = hc_data["health_checks_config"][additionalDataKey].strip().split(";") + addData = [] + for line in data: + line = line.strip() + if len(line) == 0: + continue + entries = line.split(',') + d = {} + for entry in entries: + entry = entry.strip() + if len(entry) == 0: + continue + keyVal = entry.split("=") + if len(keyVal) == 2: + d[keyVal[0].strip()] = keyVal[1].strip() + if len(d) > 0: + addData.append(d) + + return addData + + +def formatPort(portStart, portEnd, delim="-"): + return portStart if portStart == portEnd else portStart + delim + portEnd diff --git a/systemvm/debian/root/monitorServices.py b/systemvm/debian/root/monitorServices.py index 75d10043816d..909e419c1801 100755 --- a/systemvm/debian/root/monitorServices.py +++ b/systemvm/debian/root/monitorServices.py @@ -16,16 +16,15 @@ # specific language governing permissions and limitations # under the License. - - - - from ConfigParser import SafeConfigParser from subprocess import * -from os import path +from datetime import datetime import time import os import logging +import json +from os import sys, path +from health_checks.utility import getHealthChecksData class StatusCodes: SUCCESS = 0 @@ -42,15 +41,15 @@ class Log: NOTIF = 'NOTIF' class Config: - MONIT_AFTER_MINS = 30 SLEEP_SEC = 1 RETRY_ITERATIONS = 10 RETRY_FOR_RESTART = 5 MONITOR_LOG = '/var/log/monitor.log' - UNMONIT_PS_FILE = '/etc/unmonit_psList.txt' + HEALTH_CHECKS_DIR = 'health_checks' + MONITOR_RESULT_FILE_SUFFIX = 'monitor_results.json' + FAILING_CHECKS_FILE = 'failing_health_checks' - -def getConfig( config_file_path = "/etc/monitor.conf" ): +def getServicesConfig( config_file_path = "/etc/monitor.conf" ): """ Reads the process configuration from the config file. Config file contains the processes to be monitored. @@ -66,7 +65,7 @@ def getConfig( config_file_path = "/etc/monitor.conf" ): for name, value in parser.items(section): process_dict[section][name] = value -# printd (" %s = %r" % (name, value)) + printd (" %s = %r" % (name, value)) return process_dict @@ -77,12 +76,12 @@ def printd (msg): #for debug #print msg - return 0 - f= open(Config.MONITOR_LOG,'r+') + f= open(Config.MONITOR_LOG, 'w' if not path.isfile(Config.MONITOR_LOG) else 'r+') f.seek(0, 2) f.write(str(msg)+"\n") f.close() + print str(msg) def raisealert(severity, msg, process_name=None): """ Writes the alert message""" @@ -97,6 +96,7 @@ def raisealert(severity, msg, process_name=None): logging.info(log) msg = 'logger -t monit '+ log pout = Popen(msg, shell=True, stdout=PIPE) + print "[Alert] " + msg def isPidMatchPidFile(pidfile, pids): @@ -126,7 +126,7 @@ def isPidMatchPidFile(pidfile, pids): fd.close() return StatusCodes.FAILED - printd("file content "+str(inp)) + printd("file content of pidfile " + pidfile + " = " + str(inp).strip()) printd(pids) tocheck_pid = inp.strip() for item in pids: @@ -152,7 +152,7 @@ def checkProcessRunningStatus(process_name, pidFile): #check there is only one pid or not if exitStatus == 0: - pids = temp_out.split(' ') + pids = temp_out.strip().split(' ') printd("pid(s) of process %s are %s " %(process_name, pids)) #there is more than one process so match the pid file @@ -181,11 +181,10 @@ def restartService(service_name): return False - - def checkProcessStatus( process ): """ Check the process running status, if not running tries to restart + Returns the process status and if it was restarted """ process_name = process.get('processname') service_name = process.get('servicename') @@ -197,13 +196,13 @@ def checkProcessStatus( process ): cmd='' if process_name is None: printd ("\n Invalid Process Name") - return StatusCodes.INVALID_INP + return StatusCodes.INVALID_INP, False status, pids = checkProcessRunningStatus(process_name, pidfile) if status == True: printd("The process is running ....") - return StatusCodes.RUNNING + return StatusCodes.RUNNING, False else: printd("Process %s is not running trying to recover" %process_name) #Retry the process state for few seconds @@ -243,138 +242,151 @@ def checkProcessStatus( process ): raisealert(Log.ALERT,process_name,msg) printd("Restart failed after number of retries") - return StatusCodes.STOPPED + return StatusCodes.STOPPED, False - return StatusCodes.RUNNING + return StatusCodes.RUNNING, True def monitProcess( processes_info ): """ Monitors the processes which got from the config file """ + checkStartTime = time.time() + service_status = {} + failing_services = [] if len( processes_info ) == 0: - printd("Invalid Input") - return StatusCodes.INVALID_INP + printd("No config items provided - means a redundant VR or a VPC Router") + return service_status, failing_services - dict_unmonit={} - umonit_update={} - unMonitPs=False - - if not path.isfile(Config.UNMONIT_PS_FILE): - printd('Unmonit File not exist') - else: - #load the dictionary with unmonit process list - dict_unmonit = loadPsFromUnMonitFile() + print "[Process Info] " + json.dumps(processes_info) #time for noting process down time csec = repr(time.time()).split('.')[0] for process,properties in processes_info.items(): - #skip the process it its time stamp less than Config.MONIT_AFTER_MINS - printd ("checking the service %s \n" %process) - - if not is_emtpy(dict_unmonit): - if dict_unmonit.has_key(process): - ts = dict_unmonit[process] - - if checkPsTimeStampForMonitor (csec, ts, properties) == False: - unMonitPs = True - continue - - if checkProcessStatus( properties) != StatusCodes.RUNNING: + printd ("---------------------------\nchecking the service %s\n---------------------------- " %process) + serviceName = process + ".service" + processStatus, wasRestarted = checkProcessStatus(properties) + if processStatus != StatusCodes.RUNNING: printd( "\n Service %s is not Running"%process) - #add this process into unmonit list - printd ("updating the service for unmonit %s\n" %process) - umonit_update[process]=csec - - #if dict is not empty write to file else delete it - if not is_emtpy(umonit_update): - writePsListToUnmonitFile(umonit_update) - else: - if is_emtpy(umonit_update) and unMonitPs == False: - #delete file it is there - removeFile(Config.UNMONIT_PS_FILE) - - -def checkPsTimeStampForMonitor(csec,ts, process): - printd("Time difference=%s" %str(int(csec) - int(ts))) - tmin = (int(csec) - int(ts) )/60 - - if ( int(csec) - int(ts) )/60 < Config.MONIT_AFTER_MINS: - raisealert(Log.ALERT, "The %s get monitor after %s minutes " %(process, Config.MONIT_AFTER_MINS)) - printd('process will be monitored after %s min' %(str(int(Config.MONIT_AFTER_MINS) - tmin))) - return False - - return True - -def removeFile(fileName): - if path.isfile(fileName): - printd("Removing the file %s" %fileName) - os.remove(fileName) - -def loadPsFromUnMonitFile(): - - dict_unmonit = {} - - try: - fd = open(Config.UNMONIT_PS_FILE) - except: - printd("Failed to open file %s " %(Config.UNMONIT_PS_FILE)) - return StatusCodes.FAILED - - ps = fd.read() - - if not ps: - printd("File %s content is empty " %Config.UNMONIT_PS_FILE) - return StatusCodes.FAILED - - printd(ps) - plist = ps.split(',') - plist.remove('') - for i in plist: - dict_unmonit[i.split(':')[0]] = i.split(':')[1] - - fd.close() - - return dict_unmonit - - -def writePsListToUnmonitFile(umonit_update): - printd("Write updated unmonit list to file") - line='' - for i in umonit_update: - line+=str(i)+":"+str(umonit_update[i])+',' - printd(line) - try: - fd=open(Config.UNMONIT_PS_FILE,'w') - except: - printd("Failed to open file %s " %Config.UNMONIT_PS_FILE) - return StatusCodes.FAILED - - fd.write(line) - fd.close() + checkEndTime = time.time() + service_status[serviceName] = { + "success": "false", + "lastUpdate": str(int(checkStartTime * 1000)), + "lastRunDuration": str((checkEndTime - checkStartTime) * 1000), + "message": "service down at last check " + str(csec) + } + failing_services.append(serviceName) + else: + checkEndTime = time.time() + service_status[serviceName] = { + "success": "true", + "lastUpdate": str(int(checkStartTime * 1000)), + "lastRunDuration": str((checkEndTime - checkStartTime) * 1000), + "message": "service is running" + (", was restarted" if wasRestarted else "") + } + + return service_status, failing_services + + +def execute(script, checkType = "basic"): + checkStartTime = time.time() + cmd = "./" + script + " " + checkType + printd ("Executing health check script command: " + cmd) + pout = Popen(cmd, shell=True, stdout=PIPE) + exitStatus = pout.wait() + output = pout.communicate()[0].strip() + checkEndTime = time.time() -def is_emtpy(struct): - """ - Checks wether the given struct is empty or not - """ - if struct: - return False + if exitStatus == 0: + if len(output) > 0: + printd("Successful execution of " + script) + return { + "success": "true", + "lastUpdate": str(int(checkStartTime * 1000)), + "lastRunDuration": str((checkEndTime - checkStartTime) * 1000), + "message": output + } + return {} #Skip script if no output is received else: - return True - -def main(): + printd("Script execution failed " + script) + return { + "success": "false", + "lastUpdate": str(int(checkStartTime * 1000)), + "lastRunDuration": str((checkEndTime - checkStartTime) * 1000), + "message": output + } + +def main(checkType = "basic"): + startTime = time.time() ''' - Step1 : Get Config + Step1 : Get Services Config ''' printd("monitoring started") - temp_dict = getConfig() + configDict = getServicesConfig() + + ''' + Step2: Monitor services and Raise Alerts + ''' + monitResult = {} + failingChecks = [] + if checkType == "basic": + monitResult, failingChecks = monitProcess(configDict) ''' - Step2: Monitor and Raise Alert + Step3: Run health check scripts as needed ''' - monitProcess( temp_dict ) + hc_data = getHealthChecksData() + + if hc_data is not None and "health_checks_enabled" in hc_data and hc_data['health_checks_enabled']: + hc_exclude = hc_data["excluded_health_checks"] if "excluded_health_checks" in hc_data else [] + for f in os.listdir(Config.HEALTH_CHECKS_DIR): + if f in hc_exclude: + continue + fpath = path.join(Config.HEALTH_CHECKS_DIR, f) + if path.isfile(fpath) and os.access(fpath, os.X_OK): + ret = execute(fpath, checkType) + if len(ret) == 0: + continue + if "success" in ret and ret["success"].lower() == "false": + failingChecks.append(f) + monitResult[f] = ret + + ''' + Step4: Write results to the json file for admins/management server to read + ''' + + endTime = time.time() + monitResult["lastRun"] = { + "start": str(datetime.fromtimestamp(startTime)), + "end": str(datetime.fromtimestamp(endTime)), + "duration": str(endTime - startTime) + } + + with open(checkType + "_" + Config.MONITOR_RESULT_FILE_SUFFIX, 'w') as f: + json.dump(monitResult, f, ensure_ascii=False) + + failChecksFile = checkType + "_" + Config.FAILING_CHECKS_FILE + if len(failingChecks) > 0: + fcs = "" + for fc in failingChecks: + fcs = fcs + fc + "," + fcs = fcs[0:-1] + with open(failChecksFile, 'w') as f: + f.write(fcs) + elif path.isfile(failChecksFile): + os.remove(failChecksFile) if __name__ == "__main__": - main() + checkType = "basic" + if len(sys.argv) == 2: + if sys.argv[1] == "advanced": + main("advanced") + elif sys.argv[1] == "basic": + main("basic") + else: + printd("Error: Unknown type of test: " + sys.argv) + else: + main("basic") + main("advanced") diff --git a/test/integration/component/test_multiple_nic_support.py b/test/integration/component/test_multiple_nic_support.py new file mode 100644 index 000000000000..cf3a23364957 --- /dev/null +++ b/test/integration/component/test_multiple_nic_support.py @@ -0,0 +1,629 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. +""" tests for supporting multiple NIC's in advanced zone with security groups in cloudstack 4.14.0.0 + +""" +# Import Local Modules +from nose.plugins.attrib import attr +from marvin.cloudstackTestCase import cloudstackTestCase, unittest +from marvin.sshClient import SshClient +from marvin.lib.utils import (validateList, + cleanup_resources, + get_host_credentials, + get_process_status, + execute_command_in_host, + random_gen) +from marvin.lib.base import (PhysicalNetwork, + Account, + Host, + TrafficType, + Domain, + Network, + NetworkOffering, + VirtualMachine, + ServiceOffering, + Zone, + NIC, + SecurityGroup) +from marvin.lib.common import (get_domain, + get_zone, + get_template, + list_virtual_machines, + list_routers, + list_hosts, + get_free_vlan) +from marvin.codes import (PASS, FAILED) +import logging +import random +import time + +class TestMulipleNicSupport(cloudstackTestCase): + @classmethod + def setUpClass(cls): + cls.testClient = super( + TestMulipleNicSupport, + cls).getClsTestClient() + cls.apiclient = cls.testClient.getApiClient() + cls.testdata = cls.testClient.getParsedTestDataConfig() + cls.services = cls.testClient.getParsedTestDataConfig() + zone = get_zone(cls.apiclient, cls.testClient.getZoneForTests()) + cls.zone = Zone(zone.__dict__) + cls._cleanup = [] + + if str(cls.zone.securitygroupsenabled) != "True": + sys.exit(1) + + cls.logger = logging.getLogger("TestMulipleNicSupport") + cls.stream_handler = logging.StreamHandler() + cls.logger.setLevel(logging.DEBUG) + cls.logger.addHandler(cls.stream_handler) + + # Get Domain and templates + cls.domain = get_domain(cls.apiclient) + cls.services['mode'] = cls.zone.networktype + + cls.template = get_template(cls.apiclient, cls.zone.id, hypervisor="KVM") + if cls.template == FAILED: + sys.exit(1) + + # Create new domain, account, network and VM + cls.user_domain = Domain.create( + cls.apiclient, + services=cls.testdata["acl"]["domain2"], + parentdomainid=cls.domain.id) + + # Create account + cls.account1 = Account.create( + cls.apiclient, + cls.testdata["acl"]["accountD2"], + admin=True, + domainid=cls.user_domain.id + ) + + # Create small service offering + cls.service_offering = ServiceOffering.create( + cls.apiclient, + cls.testdata["service_offerings"]["small"] + ) + + cls._cleanup.append(cls.service_offering) + cls.services["network"]["zoneid"] = cls.zone.id + cls.network_offering = NetworkOffering.create( + cls.apiclient, + cls.services["network_offering"], + ) + # Enable Network offering + cls.network_offering.update(cls.apiclient, state='Enabled') + + cls._cleanup.append(cls.network_offering) + cls.testdata["virtual_machine"]["zoneid"] = cls.zone.id + cls.testdata["virtual_machine"]["template"] = cls.template.id + + if cls.zone.securitygroupsenabled: + # Enable networking for reaching to VM thorugh SSH + security_group = SecurityGroup.create( + cls.apiclient, + cls.testdata["security_group"], + account=cls.account1.name, + domainid=cls.account1.domainid + ) + + # Authorize Security group to SSH to VM + ingress_rule = security_group.authorize( + cls.apiclient, + cls.testdata["ingress_rule"], + account=cls.account1.name, + domainid=cls.account1.domainid + ) + + # Authorize Security group to SSH to VM + ingress_rule2 = security_group.authorize( + cls.apiclient, + cls.testdata["ingress_rule_ICMP"], + account=cls.account1.name, + domainid=cls.account1.domainid + ) + + cls.testdata["shared_network_offering_sg"]["specifyVlan"] = 'True' + cls.testdata["shared_network_offering_sg"]["specifyIpRanges"] = 'True' + cls.shared_network_offering = NetworkOffering.create( + cls.apiclient, + cls.testdata["shared_network_offering_sg"], + conservemode=False + ) + + NetworkOffering.update( + cls.shared_network_offering, + cls.apiclient, + id=cls.shared_network_offering.id, + state="enabled" + ) + + physical_network, vlan = get_free_vlan(cls.apiclient, cls.zone.id) + cls.testdata["shared_network_sg"]["physicalnetworkid"] = physical_network.id + + random_subnet_number = random.randrange(90, 99) + cls.testdata["shared_network_sg"]["name"] = "Shared-Network-SG-Test-vlan" + str(random_subnet_number) + cls.testdata["shared_network_sg"]["displaytext"] = "Shared-Network-SG-Test-vlan" + str(random_subnet_number) + cls.testdata["shared_network_sg"]["vlan"] = "vlan://" + str(random_subnet_number) + cls.testdata["shared_network_sg"]["startip"] = "192.168." + str(random_subnet_number) + ".240" + cls.testdata["shared_network_sg"]["endip"] = "192.168." + str(random_subnet_number) + ".250" + cls.testdata["shared_network_sg"]["gateway"] = "192.168." + str(random_subnet_number) + ".254" + cls.network1 = Network.create( + cls.apiclient, + cls.testdata["shared_network_sg"], + networkofferingid=cls.shared_network_offering.id, + zoneid=cls.zone.id, + accountid=cls.account1.name, + domainid=cls.account1.domainid + ) + + random_subnet_number = random.randrange(100, 110) + cls.testdata["shared_network_sg"]["name"] = "Shared-Network-SG-Test-vlan" + str(random_subnet_number) + cls.testdata["shared_network_sg"]["displaytext"] = "Shared-Network-SG-Test-vlan" + str(random_subnet_number) + cls.testdata["shared_network_sg"]["vlan"] = "vlan://" + str(random_subnet_number) + cls.testdata["shared_network_sg"]["startip"] = "192.168." + str(random_subnet_number) + ".240" + cls.testdata["shared_network_sg"]["endip"] = "192.168." + str(random_subnet_number) + ".250" + cls.testdata["shared_network_sg"]["gateway"] = "192.168." + str(random_subnet_number) + ".254" + cls.network2 = Network.create( + cls.apiclient, + cls.testdata["shared_network_sg"], + networkofferingid=cls.shared_network_offering.id, + zoneid=cls.zone.id, + accountid=cls.account1.name, + domainid=cls.account1.domainid + ) + + random_subnet_number = random.randrange(111, 120) + cls.testdata["shared_network_sg"]["name"] = "Shared-Network-SG-Test-vlan" + str(random_subnet_number) + cls.testdata["shared_network_sg"]["displaytext"] = "Shared-Network-SG-Test-vlan" + str(random_subnet_number) + cls.testdata["shared_network_sg"]["vlan"] = "vlan://" + str(random_subnet_number) + cls.testdata["shared_network_sg"]["startip"] = "192.168." + str(random_subnet_number) + ".240" + cls.testdata["shared_network_sg"]["endip"] = "192.168." + str(random_subnet_number) + ".250" + cls.testdata["shared_network_sg"]["gateway"] = "192.168." + str(random_subnet_number) + ".254" + cls.network3 = Network.create( + cls.apiclient, + cls.testdata["shared_network_sg"], + networkofferingid=cls.shared_network_offering.id, + zoneid=cls.zone.id, + accountid=cls.account1.name, + domainid=cls.account1.domainid + ) + + try: + cls.virtual_machine1 = VirtualMachine.create( + cls.apiclient, + cls.testdata["virtual_machine"], + accountid=cls.account1.name, + domainid=cls.account1.domainid, + serviceofferingid=cls.service_offering.id, + templateid=cls.template.id, + securitygroupids=[security_group.id], + networkids=cls.network1.id + ) + for nic in cls.virtual_machine1.nic: + if nic.isdefault: + cls.virtual_machine1.ssh_ip = nic.ipaddress + cls.virtual_machine1.default_network_id = nic.networkid + break + except Exception as e: + cls.fail("Exception while deploying virtual machine: %s" % e) + + try: + cls.virtual_machine2 = VirtualMachine.create( + cls.apiclient, + cls.testdata["virtual_machine"], + accountid=cls.account1.name, + domainid=cls.account1.domainid, + serviceofferingid=cls.service_offering.id, + templateid=cls.template.id, + securitygroupids=[security_group.id], + networkids=[str(cls.network1.id), str(cls.network2.id)] + ) + for nic in cls.virtual_machine2.nic: + if nic.isdefault: + cls.virtual_machine2.ssh_ip = nic.ipaddress + cls.virtual_machine2.default_network_id = nic.networkid + break + except Exception as e: + cls.fail("Exception while deploying virtual machine: %s" % e) + + cls._cleanup.append(cls.virtual_machine1) + cls._cleanup.append(cls.virtual_machine2) + cls._cleanup.append(cls.network1) + cls._cleanup.append(cls.network2) + cls._cleanup.append(cls.network3) + cls._cleanup.append(cls.shared_network_offering) + if cls.zone.securitygroupsenabled: + cls._cleanup.append(security_group) + cls._cleanup.append(cls.account1) + cls._cleanup.append(cls.user_domain) + + @classmethod + def tearDownClass(self): + try: + cleanup_resources(self.apiclient, self._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.cleanup = [] + return + + def tearDown(self): + try: + cleanup_resources(self.apiclient, self.cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def verify_network_rules(self, vm_id): + virtual_machine = VirtualMachine.list( + self.apiclient, + id=vm_id + ) + vm = virtual_machine[0] + hosts = list_hosts( + self.apiclient, + id=vm.hostid + ) + host = hosts[0] + if host.hypervisor.lower() not in "kvm": + return + host.user, host.password = get_host_credentials(self.config, host.ipaddress) + for nic in vm.nic: + secips = "" + if len(nic.secondaryip) > 0: + for secip in nic.secondaryip: + secips += secip.ipaddress + ";" + command="/usr/share/cloudstack-common/scripts/vm/network/security_group.py verify_network_rules --vmname %s --vmip %s --vmmac %s --nicsecips '%s'" % (vm.instancename, nic.ipaddress, nic.macaddress, secips) + self.logger.debug("Executing command '%s' in host %s" % (command, host.ipaddress)) + result=execute_command_in_host(host.ipaddress, 22, + host.user, + host.password, + command) + if len(result) > 0: + self.fail("The iptables/ebtables rules for nic %s on vm %s on host %s are not correct" %(nic.ipaddress, vm.instancename, host.name)) + + @attr(tags=["adeancedsg"], required_hardware="false") + def test_01_create_vm_with_multiple_nics(self): + """Create Vm with multiple NIC's + + Steps: + # 1. Create more than 1 isolated or shared network + # 2. Create a vm and select more than 1 network while deploying + # 3. Vm is deployed successfully with 1 nic from each network + # 4. All the vm's should be pingable + :return: + """ + virtual_machine = VirtualMachine.list( + self.apiclient, + id=self.virtual_machine2.id + ) + self.assertEqual( + len(virtual_machine), 1, + "Virtual Machine create with 2 NIC's failed") + + nicIdInVm = virtual_machine[0].nic[0] + self.assertIsNotNone(nicIdInVm, "NIC 1 not found in Virtual Machine") + + nicIdInVm = virtual_machine[0].nic[1] + self.assertIsNotNone(nicIdInVm, "NIC 2 not found in Virtual Machine") + + self.verify_network_rules(self.virtual_machine2.id) + + @attr(tags=["advancedsg"], required_hardware="false") + def test_02_add_nic_to_vm(self): + """Create VM with single NIC and then add additional NIC + + Steps: + # 1. Create a VM by selecting one default NIC + # 2. Create few more isolated or shared networks + # 3. Add extra NIC's to the vm from the newly created networks + # 4. The deployed VM should have extra nic's added in the above + # step without any fail + # 5. The IP's of the extra NIC's should be pingable + :return: + """ + self.virtual_machine1.add_nic(self.apiclient, self.network2.id) + + virtual_machine = VirtualMachine.list( + self.apiclient, + id=self.virtual_machine1.id + ) + + nicIdInVm = virtual_machine[0].nic[1] + self.assertIsNotNone(nicIdInVm, "Second NIC not found") + + self.verify_network_rules(self.virtual_machine1.id) + + @attr(tags=["advancedsg"], required_hardware="false") + def test_03_add_ip_to_default_nic(self): + """ Add secondary IP's to the VM + + Steps: + # 1. Create a VM with more than 1 NIC + # 2) Navigate to Instances->NIC->Edit Secondary IP's + # ->Aquire new Secondary IP" + # 3) Add as many secondary Ip as possible to the VM + # 4) Configure the secondary IP's by referring to "Configure + # the secondary IP's" in the "Action Item" section + :return: + """ + ipaddress = NIC.addIp( + self.apiclient, + id=self.virtual_machine2.nic[0].id + ) + + self.assertIsNotNone( + ipaddress, + "Unable to add secondary IP to the default NIC") + + self.verify_network_rules(self.virtual_machine2.id) + + @attr(tags=["advancedsg"], required_hardware="false") + def test_04_add_ip_to_remaining_nics(self): + """ Add secondary IP's to remaining NIC's + + Steps: + # 1) Create a VM with more than 1 NIC + # 2)Navigate to Instances-NIC's->Edit Secondary IP's + # ->Acquire new Secondary IP + # 3) Add secondary IP to all the NIC's of the VM + # 4) Confiugre the secondary IP's by referring to "Configure the + # secondary IP's" in the "Action Item" section + :return: + """ + + self.virtual_machine1.add_nic(self.apiclient, self.network3.id) + + vms = VirtualMachine.list( + self.apiclient, + id=self.virtual_machine1.id + ) + + self.assertIsNotNone( + vms[0].nic[2], + "Third NIC is not added successfully to the VM") + + vms1_nic1_id = vms[0].nic[1]['id'] + vms1_nic2_id = vms[0].nic[2]['id'] + + ipaddress21 = NIC.addIp( + self.apiclient, + id=vms1_nic1_id + ) + + ipaddress22 = NIC.addIp( + self.apiclient, + id=vms1_nic1_id + ) + + self.assertIsNotNone( + ipaddress21, + "Unable to add first secondary IP to the second nic") + self.assertIsNotNone( + ipaddress22, + "Unable to add second secondary IP to second NIC") + + ipaddress31 = NIC.addIp( + self.apiclient, + id=vms1_nic2_id + ) + + ipaddress32 = NIC.addIp( + self.apiclient, + id=vms1_nic2_id + ) + + self.assertIsNotNone( + ipaddress31, + "Unable to add first secondary IP to third NIC") + self.assertIsNotNone( + ipaddress32, + "Unable to add second secondary IP to third NIC") + + self.verify_network_rules(self.virtual_machine1.id) + + @attr(tags=["advancedsg"], required_hardware="false") + def test_05_stop_start_vm_with_multiple_nic(self): + """ Stop and Start a VM with Multple NIC + + Steps: + # 1) Create a Vm with multiple NIC's + # 2) Configure secondary IP's on the VM + # 3) Try to stop/start the VM + # 4) Ping the IP's of the vm + # 5) Remove Secondary IP from one of the NIC + :return: + """ + ipaddress1 = NIC.addIp( + self.apiclient, + id=self.virtual_machine2.nic[0].id + ) + + ipaddress2 = NIC.addIp( + self.apiclient, + id=self.virtual_machine2.nic[1].id + ) + # Stop the VM with multiple NIC's + self.virtual_machine2.stop(self.apiclient) + + virtual_machine = VirtualMachine.list( + self.apiclient, + id=self.virtual_machine2.id + ) + + self.assertEqual( + virtual_machine[0]['state'], 'Stopped', + "Could not stop the VM with multiple NIC's") + + if virtual_machine[0]['state'] == 'Stopped': + # If stopped then try to start the VM + self.virtual_machine2.start(self.apiclient) + virtual_machine = VirtualMachine.list( + self.apiclient, + id=self.virtual_machine2.id + ) + self.assertEqual( + virtual_machine[0]['state'], 'Running', + "Could not start the VM with multiple NIC's") + + self.verify_network_rules(self.virtual_machine2.id) + + @attr(tags=["advancedsg"], required_hardware="false") + def test_06_migrate_vm_with_multiple_nic(self): + """ Migrate a VM with Multple NIC + + Steps: + # 1) Create a Vm with multiple NIC's + # 2) Configure secondary IP's on the VM + # 3) Try to stop/start the VM + # 4) Ping the IP's of the vm + :return: + """ + # Skipping adding Secondary IP to NIC since its already + # done in the previous test cases + + virtual_machine = VirtualMachine.list( + self.apiclient, + id=self.virtual_machine1.id + ) + old_host_id = virtual_machine[0]['hostid'] + + try: + hosts = Host.list( + self.apiclient, + virtualmachineid=self.virtual_machine1.id, + listall=True) + self.assertEqual( + validateList(hosts)[0], + PASS, + "hosts list validation failed") + + # Get a host which is not already assigned to VM + for host in hosts: + if host.id == old_host_id: + continue + else: + host_id = host.id + break + + self.virtual_machine1.migrate(self.apiclient, host_id) + except Exception as e: + self.fail("Exception occured: %s" % e) + + # List the vm again + virtual_machine = VirtualMachine.list( + self.apiclient, + id=self.virtual_machine1.id) + + new_host_id = virtual_machine[0]['hostid'] + + self.assertNotEqual( + old_host_id, new_host_id, + "Migration of VM to new host failed" + ) + + self.verify_network_rules(self.virtual_machine1.id) + + @attr(tags=["advancedsg"], required_hardware="false") + def test_07_remove_secondary_ip_from_nic(self): + """ Remove secondary IP from any NIC + Steps: + # 1) Navigate to Instances + # 2) Select any vm + # 3) NIC's ->Edit secondary IP's->Release IP + # 4) The secondary IP should be successfully removed + """ + virtual_machine = VirtualMachine.list( + self.apiclient, + id=self.virtual_machine2.id) + + # Check which NIC is having secondary IP + secondary_ips = virtual_machine[0].nic[1].secondaryip + + for secondary_ip in secondary_ips: + NIC.removeIp(self.apiclient, ipaddressid=secondary_ip['id']) + + virtual_machine = VirtualMachine.list( + self.apiclient, + id=self.virtual_machine2.id + ) + + self.assertFalse( + virtual_machine[0].nic[1].secondaryip, + 'Failed to remove secondary IP') + + self.verify_network_rules(self.virtual_machine2.id) + + @attr(tags=["advancedsg"], required_hardware="false") + def test_08_remove_nic_from_vm(self): + """ Remove NIC from VM + Steps: + # 1) Navigate to Instances->select any vm->NIC's->NIC 2 + # ->Click on "X" button to remove the second NIC + # 2) Remove other NIC's as well from the VM + # 3) All the NIC's should be successfully removed from the VM + :return: + """ + virtual_machine = VirtualMachine.list( + self.apiclient, + id=self.virtual_machine2.id) + + for nic in virtual_machine[0].nic: + if nic.isdefault: + continue + self.virtual_machine2.remove_nic(self.apiclient, nic.id) + + virtual_machine = VirtualMachine.list( + self.apiclient, + id=self.virtual_machine2.id) + + self.assertEqual( + len(virtual_machine[0].nic), 1, + "Failed to remove all the nics from the virtual machine") + + self.verify_network_rules(self.virtual_machine2.id) + + @attr(tags=["advancedsg"], required_hardware="false") + def test_09_reboot_vm_with_multiple_nic(self): + """ Reboot a VM with Multple NIC + + Steps: + # 1) Create a Vm with multiple NIC's + # 2) Configure secondary IP's on the VM + # 3) Try to reboot the VM + # 4) Ping the IP's of the vm + :return: + """ + # Skipping adding Secondary IP to NIC since its already + # done in the previous test cases + + virtual_machine = VirtualMachine.list( + self.apiclient, + id=self.virtual_machine1.id + ) + try: + self.virtual_machine1.reboot(self.apiclient) + except Exception as e: + self.fail("Exception occured: %s" % e) + + self.verify_network_rules(self.virtual_machine1.id) + diff --git a/test/integration/component/test_resource_count_running_vms.py b/test/integration/component/test_resource_count_running_vms.py new file mode 100644 index 000000000000..2c6e972c1028 --- /dev/null +++ b/test/integration/component/test_resource_count_running_vms.py @@ -0,0 +1,927 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. +""" tests for Resource count of only running vms in cloudstack 4.14.0.0 + +""" +# Import Local Modules +from nose.plugins.attrib import attr +from marvin.cloudstackTestCase import cloudstackTestCase +from marvin.lib.utils import (validateList, + cleanup_resources) +from marvin.lib.base import (Account, + Domain, + Configurations, + Network, + NetworkOffering, + VirtualMachine, + Resources, + ServiceOffering, + Zone) +from marvin.lib.common import (get_domain, + get_zone, + get_template, + matchResourceCount, + isAccountResourceCountEqualToExpectedCount) +from marvin.codes import (PASS, FAILED, RESOURCE_CPU, RESOURCE_MEMORY) +import logging +import random +import time + +class TestResourceCountRunningVMs(cloudstackTestCase): + @classmethod + def setUpClass(cls): + cls.testClient = super( + TestResourceCountRunningVMs, + cls).getClsTestClient() + cls.apiclient = cls.testClient.getApiClient() + cls.services = cls.testClient.getParsedTestDataConfig() + zone = get_zone(cls.apiclient, cls.testClient.getZoneForTests()) + cls.zone = Zone(zone.__dict__) + cls._cleanup = [] + + cls.logger = logging.getLogger("TestResourceCountRunningVMs") + cls.stream_handler = logging.StreamHandler() + cls.logger.setLevel(logging.DEBUG) + cls.logger.addHandler(cls.stream_handler) + + # Get Domain and templates + cls.domain = get_domain(cls.apiclient) + + cls.template = get_template(cls.apiclient, cls.zone.id, hypervisor="KVM") + if cls.template == FAILED: + sys.exit(1) + cls.templatesize = (cls.template.size / (1024 ** 3)) + + cls.services['mode'] = cls.zone.networktype + # Create Account + cls.account = Account.create( + cls.apiclient, + cls.services["account"], + admin=True, + domainid=cls.domain.id + ) + accounts = Account.list(cls.apiclient, id=cls.account.id) + cls.expectedCpu = int(accounts[0].cputotal) + cls.expectedMemory = int(accounts[0].memorytotal) + + if cls.zone.securitygroupsenabled: + cls.services["shared_network_offering"]["specifyVlan"] = 'True' + cls.services["shared_network_offering"]["specifyIpRanges"] = 'True' + + cls.network_offering = NetworkOffering.create( + cls.apiclient, + cls.services["shared_network_offering"] + ) + cls.network_offering.update(cls.apiclient, state='Enabled') + + cls.account_network = Network.create( + cls.apiclient, + cls.services["network2"], + networkofferingid=cls.network_offering.id, + zoneid=cls.zone.id, + accountid=cls.account.name, + domainid=cls.account.domainid + ) + else: + cls.network_offering = NetworkOffering.create( + cls.apiclient, + cls.services["isolated_network_offering"], + ) + # Enable Network offering + cls.network_offering.update(cls.apiclient, state='Enabled') + + # Create account network + cls.services["network"]["zoneid"] = cls.zone.id + cls.services["network"]["networkoffering"] = cls.network_offering.id + cls.account_network = Network.create( + cls.apiclient, + cls.services["network"], + cls.account.name, + cls.account.domainid + ) + + cls._cleanup.append(cls.account); + cls._cleanup.append(cls.network_offering) + + @classmethod + def tearDownClass(self): + try: + cleanup_resources(self.apiclient, self._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.cleanup = [] + return + + def tearDown(self): + try: + cleanup_resources(self.apiclient, self.cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def verify_resource_count_cpu_memory(self, expectedCpu, expectedMemory, account=None): + if account is None: + account = self.account + response = matchResourceCount( + self.apiclient, expectedCpu, + RESOURCE_CPU, + accountid=account.id) + self.assertEqual(response[0], PASS, response[1]) + + response = matchResourceCount( + self.apiclient, expectedMemory, + RESOURCE_MEMORY, + accountid=account.id) + self.assertEqual(response[0], PASS, response[1]) + + result = isAccountResourceCountEqualToExpectedCount( + self.apiclient, account.domainid, account.name, + expectedCpu, RESOURCE_CPU) + self.assertFalse(result[0], result[1]) + self.assertTrue(result[2], "Resource count of cpu does not match") + + result = isAccountResourceCountEqualToExpectedCount( + self.apiclient, account.domainid, account.name, + expectedMemory, RESOURCE_MEMORY) + self.assertFalse(result[0], result[1]) + self.assertTrue(result[2], "Resource count of memory does not match") + + def update_account_resource_limitation(self, maxCpu, maxMemory): + Resources.updateLimit(self.apiclient, + resourcetype=RESOURCE_CPU, + max=maxCpu, + domainid=self.account.domainid, + account=self.account.name) + + Resources.updateLimit(self.apiclient, + resourcetype=RESOURCE_MEMORY, + max=maxMemory, + domainid=self.account.domainid, + account=self.account.name) + + @attr(tags=["advanced", "advancedsg"], required_hardware="false") + def test_01_resource_count_vm_with_normal_offering_in_all_states(self): + """Create VM with normal offering. Take resources of vm in all states into calculation of resource count. + + Steps: + # 1. update resource.count.running.vms.only to false + # 2. create normal service offering + # 3. deploy vm, resource count of cpu/ram increases + # 4. stop vm, resource count of cpu/ram is not changed + # 5. update vm with displayvm=false, resource count decreases + # 6. update vm with displayvm=true, resource count increases + # 7. start vm, resource count of cpu/ram is not changed + # 8. reboot vm, resource count of cpu/ram is not changed + # 9. destroy vm, resource count of cpu/ram decreases + # 10. expunge vm, resource count of cpu/ram is not changed + """ + + Configurations.update(self.apiclient, + name="resource.count.running.vms.only", + value="false" ) + + # Create small service offering + self.service_offering = ServiceOffering.create( + self.apiclient, + self.services["service_offerings"]["small"] + ) + self.cleanup.append(self.service_offering) + + # deploy vm + try: + virtual_machine_1 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.name, + domainid=self.account.domainid, + serviceofferingid=self.service_offering.id, + templateid=self.template.id, + zoneid=self.zone.id, + mode=self.zone.networktype + ) + except Exception as e: + self.fail("Exception while deploying virtual machine: %s" % e) + + self.expectedCpu = self.expectedCpu + virtual_machine_1.cpunumber + self.expectedMemory = self.expectedMemory + virtual_machine_1.memory + self.verify_resource_count_cpu_memory(self.expectedCpu, self.expectedMemory); + + # stop vm + virtual_machine_1.stop(self.apiclient) + self.verify_resource_count_cpu_memory(self.expectedCpu, self.expectedMemory); + + # update vm with displayvm=false + virtual_machine_1.update(self.apiclient, displayvm=False) + self.expectedCpu = self.expectedCpu - virtual_machine_1.cpunumber + self.expectedMemory = self.expectedMemory - virtual_machine_1.memory + self.verify_resource_count_cpu_memory(self.expectedCpu, self.expectedMemory); + + # update vm with displayvm=false + virtual_machine_1.update(self.apiclient, displayvm=True) + self.expectedCpu = self.expectedCpu + virtual_machine_1.cpunumber + self.expectedMemory = self.expectedMemory + virtual_machine_1.memory + self.verify_resource_count_cpu_memory(self.expectedCpu, self.expectedMemory); + + # start vm + virtual_machine_1.start(self.apiclient) + self.verify_resource_count_cpu_memory(self.expectedCpu, self.expectedMemory); + + # reboot vm + virtual_machine_1.reboot(self.apiclient) + self.verify_resource_count_cpu_memory(self.expectedCpu, self.expectedMemory); + + # destroy vm + virtual_machine_1.delete(self.apiclient, expunge=False) + self.expectedCpu = self.expectedCpu - virtual_machine_1.cpunumber + self.expectedMemory = self.expectedMemory - virtual_machine_1.memory + self.verify_resource_count_cpu_memory(self.expectedCpu, self.expectedMemory); + + # expunge vm + virtual_machine_1.expunge(self.apiclient) + self.verify_resource_count_cpu_memory(self.expectedCpu, self.expectedMemory); + + @attr(tags=["advanced", "advancedsg"], required_hardware="false") + def test_02_resource_count_vm_with_dynamic_offering_in_all_states(self): + """Create VM with dynamic service offering. Take resources of vm in all states into calculation of resource count. + + Steps: + # 1. update resource.count.running.vms.only to false + # 2. create dynamic service offering + # 3. deploy vm, resource count of cpu/ram increases + # 4. stop vm, resource count of cpu/ram is not changed + # 5. update vm with displayvm=false, resource count decreases + # 6. update vm with displayvm=true, resource count increases + # 7. start vm, resource count of cpu/ram is not changed + # 8. reboot vm, resource count of cpu/ram is not changed + # 9. destroy vm, resource count of cpu/ram decreases + # 10. expunge vm, resource count of cpu/ram is not changed + """ + Configurations.update(self.apiclient, + name="resource.count.running.vms.only", + value="false" ) + + # Create dynamic service offering + self.services["service_offering"]["cpunumber"] = "" + self.services["service_offering"]["cpuspeed"] = "" + self.services["service_offering"]["memory"] = "" + + self.service_offering = ServiceOffering.create( + self.apiclient, + self.services["service_offering"]) + self.cleanup.append(self.service_offering) + + # deploy vm + try: + virtual_machine_2 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.name, + domainid=self.account.domainid, + serviceofferingid=self.service_offering.id, + customcpunumber=1, + customcpuspeed=100, + custommemory=256, + templateid=self.template.id, + zoneid=self.zone.id, + mode=self.zone.networktype + ) + except Exception as e: + self.fail("Exception while deploying virtual machine: %s" % e) + + self.expectedCpu = self.expectedCpu + virtual_machine_2.cpunumber + self.expectedMemory = self.expectedMemory + virtual_machine_2.memory + self.verify_resource_count_cpu_memory(self.expectedCpu, self.expectedMemory); + + # stop vm + virtual_machine_2.stop(self.apiclient) + self.verify_resource_count_cpu_memory(self.expectedCpu, self.expectedMemory); + + # update vm with displayvm=false + virtual_machine_2.update(self.apiclient, displayvm=False) + self.expectedCpu = self.expectedCpu - virtual_machine_2.cpunumber + self.expectedMemory = self.expectedMemory - virtual_machine_2.memory + self.verify_resource_count_cpu_memory(self.expectedCpu, self.expectedMemory); + + # update vm with displayvm=false + virtual_machine_2.update(self.apiclient, displayvm=True) + self.expectedCpu = self.expectedCpu + virtual_machine_2.cpunumber + self.expectedMemory = self.expectedMemory + virtual_machine_2.memory + self.verify_resource_count_cpu_memory(self.expectedCpu, self.expectedMemory); + + # start vm + virtual_machine_2.start(self.apiclient) + self.verify_resource_count_cpu_memory(self.expectedCpu, self.expectedMemory); + + # reboot vm + virtual_machine_2.reboot(self.apiclient) + self.verify_resource_count_cpu_memory(self.expectedCpu, self.expectedMemory); + + # destroy vm + virtual_machine_2.delete(self.apiclient, expunge=False) + self.expectedCpu = self.expectedCpu - virtual_machine_2.cpunumber + self.expectedMemory = self.expectedMemory - virtual_machine_2.memory + self.verify_resource_count_cpu_memory(self.expectedCpu, self.expectedMemory); + + # expunge vm + virtual_machine_2.expunge(self.apiclient) + self.verify_resource_count_cpu_memory(self.expectedCpu, self.expectedMemory); + + @attr(tags=["advanced", "advancedsg"], required_hardware="false") + def test_03_resource_count_vm_with_normal_offering_in_running_state(self): + """Create VM with normal service offering. Take resources of vm in running state into calculation of resource count. + + Steps: + # 1. update resource.count.running.vms.only to true + # 2. create normal service offering + # 3. deploy vm, resource count of cpu/ram increases + # 4. stop vm, resource count of cpu/ram decreases + # 5. start vm, resource count of cpu/ram increases + # 6. reboot vm, resource count of cpu/ram is not changed + # 7. destroy vm, resource count of cpu/ram decreases + # 8. recover vm, resource count of cpu/ram is not changed + # 9. update vm with displayvm=false, resource count of cpu/ram is not changed + # 10. destroy vm with expunge = true, resource count of cpu/ram is not changed + """ + Configurations.update(self.apiclient, + name="resource.count.running.vms.only", + value="true" ) + + # Create service offering + self.service_offering = ServiceOffering.create( + self.apiclient, + self.services["service_offerings"]["small"] + ) + self.cleanup.append(self.service_offering) + + # deploy vm + try: + virtual_machine_3 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.name, + domainid=self.account.domainid, + serviceofferingid=self.service_offering.id, + templateid=self.template.id, + zoneid=self.zone.id, + mode=self.zone.networktype + ) + except Exception as e: + self.fail("Exception while deploying virtual machine: %s" % e) + + self.expectedCpu = self.expectedCpu + virtual_machine_3.cpunumber + self.expectedMemory = self.expectedMemory + virtual_machine_3.memory + self.verify_resource_count_cpu_memory(self.expectedCpu, self.expectedMemory); + + # stop vm + virtual_machine_3.stop(self.apiclient) + self.expectedCpu = self.expectedCpu - virtual_machine_3.cpunumber + self.expectedMemory = self.expectedMemory - virtual_machine_3.memory + self.verify_resource_count_cpu_memory(self.expectedCpu, self.expectedMemory); + + # start vm + virtual_machine_3.start(self.apiclient) + self.expectedCpu = self.expectedCpu + virtual_machine_3.cpunumber + self.expectedMemory = self.expectedMemory + virtual_machine_3.memory + self.verify_resource_count_cpu_memory(self.expectedCpu, self.expectedMemory); + + # reboot vm + virtual_machine_3.reboot(self.apiclient) + self.verify_resource_count_cpu_memory(self.expectedCpu, self.expectedMemory); + + # destroy vm + virtual_machine_3.delete(self.apiclient, expunge=False) + self.expectedCpu = self.expectedCpu - virtual_machine_3.cpunumber + self.expectedMemory = self.expectedMemory - virtual_machine_3.memory + self.verify_resource_count_cpu_memory(self.expectedCpu, self.expectedMemory); + + # recover vm + virtual_machine_3.recover(self.apiclient) + self.verify_resource_count_cpu_memory(self.expectedCpu, self.expectedMemory); + + # update vm with displayvm=false + virtual_machine_3.update(self.apiclient, displayvm=False) + self.verify_resource_count_cpu_memory(self.expectedCpu, self.expectedMemory); + + # expunge vm + virtual_machine_3.delete(self.apiclient, expunge=True) + self.verify_resource_count_cpu_memory(self.expectedCpu, self.expectedMemory); + + @attr(tags=["advanced", "advancedsg"], required_hardware="false") + def test_04_resource_count_vm_with_dynamic_offering_in_running_state(self): + """Create VM with dynamic service offering. Take resources of vm in running state into calculation of resource count. + + Steps: + # 1. update resource.count.running.vms.only to true + # 2. create dynamic service offering + # 3. deploy vm, resource count of cpu/ram increases + # 4. stop vm, resource count of cpu/ram decreases + # 5. start vm, resource count of cpu/ram increases + # 6. reboot vm, resource count of cpu/ram is not changed + # 7. destroy vm, resource count of cpu/ram decreases + # 8. recover vm, resource count of cpu/ram is not changed + # 9. update vm with displayvm=false, resource count of cpu/ram is not changed + # 10. destroy vm with expunge = true, resource count of cpu/ram is not changed + """ + Configurations.update(self.apiclient, + name="resource.count.running.vms.only", + value="true" ) + + # Create dynamic service offering + self.services["service_offering"]["cpunumber"] = "" + self.services["service_offering"]["cpuspeed"] = "" + self.services["service_offering"]["memory"] = "" + + self.service_offering = ServiceOffering.create( + self.apiclient, + self.services["service_offering"]) + self.cleanup.append(self.service_offering) + + # deploy vm + try: + virtual_machine_4 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.name, + domainid=self.account.domainid, + serviceofferingid=self.service_offering.id, + customcpunumber=1, + customcpuspeed=100, + custommemory=256, + templateid=self.template.id, + zoneid=self.zone.id, + mode=self.zone.networktype + ) + except Exception as e: + self.fail("Exception while deploying virtual machine: %s" % e) + + self.expectedCpu = self.expectedCpu + virtual_machine_4.cpunumber + self.expectedMemory = self.expectedMemory + virtual_machine_4.memory + self.verify_resource_count_cpu_memory(self.expectedCpu, self.expectedMemory); + + # stop vm + virtual_machine_4.stop(self.apiclient) + self.expectedCpu = self.expectedCpu - virtual_machine_4.cpunumber + self.expectedMemory = self.expectedMemory - virtual_machine_4.memory + self.verify_resource_count_cpu_memory(self.expectedCpu, self.expectedMemory); + + # start vm + virtual_machine_4.start(self.apiclient) + self.expectedCpu = self.expectedCpu + virtual_machine_4.cpunumber + self.expectedMemory = self.expectedMemory + virtual_machine_4.memory + self.verify_resource_count_cpu_memory(self.expectedCpu, self.expectedMemory); + + # reboot vm + virtual_machine_4.reboot(self.apiclient) + self.verify_resource_count_cpu_memory(self.expectedCpu, self.expectedMemory); + + # destroy vm + virtual_machine_4.delete(self.apiclient, expunge=False) + self.expectedCpu = self.expectedCpu - virtual_machine_4.cpunumber + self.expectedMemory = self.expectedMemory - virtual_machine_4.memory + self.verify_resource_count_cpu_memory(self.expectedCpu, self.expectedMemory); + + # recover vm + virtual_machine_4.recover(self.apiclient) + self.verify_resource_count_cpu_memory(self.expectedCpu, self.expectedMemory); + + # update vm with displayvm=false + virtual_machine_4.update(self.apiclient, displayvm=False) + self.verify_resource_count_cpu_memory(self.expectedCpu, self.expectedMemory); + + # expunge vm + virtual_machine_4.delete(self.apiclient, expunge=True) + self.verify_resource_count_cpu_memory(self.expectedCpu, self.expectedMemory); + + @attr(tags=["advanced", "advancedsg"], required_hardware="false") + def test_05_resource_count_vm_with_dynamic_offering_in_running_state_failed_cases(self): + """Create VM with dynamic service offering. Take resources of vm in running state into calculation of resource count. Test failed cases + + Steps: + # 1. update resource.count.running.vms.only to true + # 2. create dynamic service offering + # 3. update account cpu/ram limitation to current value + # 4. deploy vm (startvm=false), resource count of cpu/ram is not changed + # 5. start vm, it should fail + # 6. increase cpu limitation, start vm, it should fail + # 7. increase memory limitation, start vm, it should succeed. resource count of cpu/ram increases + # 8. restore vm, it should succeed. resource count of cpu/ram is not changed + # 9. destroy vm, resource count of cpu/ram decreases + # 10. expunge vm, resource count of cpu/ram is not changed + """ + Configurations.update(self.apiclient, + name="resource.count.running.vms.only", + value="true" ) + + # Create dynamic service offering + self.services["service_offering"]["cpunumber"] = "" + self.services["service_offering"]["cpuspeed"] = "" + self.services["service_offering"]["memory"] = "" + + self.service_offering = ServiceOffering.create( + self.apiclient, + self.services["service_offering"]) + self.cleanup.append(self.service_offering) + + # update resource limitation + self.update_account_resource_limitation(self.expectedCpu, self.expectedMemory) + + # deploy vm (startvm=false) + try: + virtual_machine_5 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.name, + domainid=self.account.domainid, + serviceofferingid=self.service_offering.id, + customcpunumber=1, + customcpuspeed=100, + custommemory=256, + templateid=self.template.id, + zoneid=self.zone.id, + startvm=False, + mode=self.zone.networktype + ) + except Exception as e: + self.fail("Exception while deploying virtual machine: %s" % e) + + self.verify_resource_count_cpu_memory(self.expectedCpu, self.expectedMemory); + + # start vm + try: + virtual_machine_5.start(self.apiclient) + self.fail("Start VM should fail as there is not enough cpu") + except Exception: + self.debug("Start VM failed as expected") + + self.verify_resource_count_cpu_memory(self.expectedCpu, self.expectedMemory); + + # increase cpu limitation, and start vm + self.update_account_resource_limitation(self.expectedCpu + virtual_machine_5.cpunumber, self.expectedMemory) + try: + virtual_machine_5.start(self.apiclient) + self.fail("Start VM should fail as there is not enough memory") + except Exception: + self.debug("Start VM failed as expected") + + self.verify_resource_count_cpu_memory(self.expectedCpu, self.expectedMemory); + + # increase memory limitation, and start vm + self.update_account_resource_limitation(self.expectedCpu + virtual_machine_5.cpunumber, self.expectedMemory + virtual_machine_5.memory) + try: + virtual_machine_5.start(self.apiclient) + self.debug("Start VM succeed as expected") + except Exception: + self.fail("Start VM should succeed as there is enough cpu and memory") + + self.expectedCpu = self.expectedCpu + virtual_machine_5.cpunumber + self.expectedMemory = self.expectedMemory + virtual_machine_5.memory + self.verify_resource_count_cpu_memory(self.expectedCpu, self.expectedMemory); + + # restore running vm + virtual_machine_5.restore(self.apiclient) + self.verify_resource_count_cpu_memory(self.expectedCpu, self.expectedMemory); + + # expunge vm + virtual_machine_5.delete(self.apiclient, expunge=True) + self.expectedCpu = self.expectedCpu - virtual_machine_5.cpunumber + self.expectedMemory = self.expectedMemory - virtual_machine_5.memory + self.verify_resource_count_cpu_memory(self.expectedCpu, self.expectedMemory); + + @attr(tags=["advanced", "advancedsg"], required_hardware="false") + def test_06_resource_count_vm_with_dynamic_offering_in_all_states_failed_cases(self): + """Create VM with dynamic service offering. Take resources of vm in all states into calculation of resource count. Test failed cases + + Steps: + # 1. update resource.count.running.vms.only to false + # 2. create dynamic service offering + # 3. update account cpu/ram limitation to current value + # 4. deploy vm (startvm=false), it should fail + # 5. increase cpu limitation, deploy vm, it should fail + # 6. increase memory limitation, deploy vm, it should succeed. resource count of cpu/ram increases + # 7. start vm, resource count of cpu/ram is not changed + # 8. restore vm, it should succeed. resource count of cpu/ram is not changed + # 9. destroy vm, resource count of cpu/ram decreases + # 10. expunge vm, resource count of cpu/ram is not changed + """ + Configurations.update(self.apiclient, + name="resource.count.running.vms.only", + value="false" ) + + # Create dynamic service offering + self.services["service_offering"]["cpunumber"] = "" + self.services["service_offering"]["cpuspeed"] = "" + self.services["service_offering"]["memory"] = "" + + self.service_offering = ServiceOffering.create( + self.apiclient, + self.services["service_offering"]) + self.cleanup.append(self.service_offering) + + # update resource limitation + self.update_account_resource_limitation(self.expectedCpu, self.expectedMemory) + + # deploy vm (startvm=false) + try: + virtual_machine_6 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.name, + domainid=self.account.domainid, + serviceofferingid=self.service_offering.id, + customcpunumber=1, + customcpuspeed=100, + custommemory=256, + templateid=self.template.id, + zoneid=self.zone.id, + startvm=False, + mode=self.zone.networktype + ) + self.fail("Deploy VM should fail as there is not enough cpu") + except Exception as e: + self.debug("Deploy VM failed as expected") + + self.verify_resource_count_cpu_memory(self.expectedCpu, self.expectedMemory); + + # increase cpu limitation, and deploy vm + self.update_account_resource_limitation(self.expectedCpu + 1, self.expectedMemory) + try: + virtual_machine_6 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.name, + domainid=self.account.domainid, + serviceofferingid=self.service_offering.id, + customcpunumber=1, + customcpuspeed=100, + custommemory=256, + templateid=self.template.id, + zoneid=self.zone.id, + startvm=False, + mode=self.zone.networktype + ) + self.fail("Deploy VM should fail as there is not enough memory") + except Exception as e: + self.debug("Deploy VM failed as expected") + + self.verify_resource_count_cpu_memory(self.expectedCpu, self.expectedMemory); + + # increase memory limitation, and deploy vm + self.update_account_resource_limitation(self.expectedCpu + 1, self.expectedMemory + 256) + try: + virtual_machine_6 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.name, + domainid=self.account.domainid, + serviceofferingid=self.service_offering.id, + customcpunumber=1, + customcpuspeed=100, + custommemory=256, + templateid=self.template.id, + zoneid=self.zone.id, + startvm=False, + mode=self.zone.networktype + ) + self.debug("Deploy VM succeed as expected") + except Exception: + self.fail("Deploy VM should succeed as there is enough cpu and memory") + + self.expectedCpu = self.expectedCpu + virtual_machine_6.cpunumber + self.expectedMemory = self.expectedMemory + virtual_machine_6.memory + self.verify_resource_count_cpu_memory(self.expectedCpu, self.expectedMemory); + + # start vm + virtual_machine_6.start(self.apiclient) + self.verify_resource_count_cpu_memory(self.expectedCpu, self.expectedMemory); + + # restore running vm + virtual_machine_6.restore(self.apiclient) + self.verify_resource_count_cpu_memory(self.expectedCpu, self.expectedMemory); + + # expunge vm + virtual_machine_6.delete(self.apiclient, expunge=True) + self.expectedCpu = self.expectedCpu - virtual_machine_6.cpunumber + self.expectedMemory = self.expectedMemory - virtual_machine_6.memory + self.verify_resource_count_cpu_memory(self.expectedCpu, self.expectedMemory); + + @attr(tags=["advanced", "advancedsg"], required_hardware="false") + def test_07_resource_count_vm_in_running_state_and_move_and_upgrade(self): + """Create VM with dynamic service offering. Take resources of vm in running state into calculation. Move vm to another account and upgrade it. + + Steps: + # 1. update resource.count.running.vms.only to true + # 2. create dynamic service offering + # 3. deploy vm, resource count of cpu/ram increases + # 4. stop vm, resource count of cpu/ram decreases + # 5. create another account + # 6. move vm to new account. resource count of cpu/ram of current account is not changed. resource count of cpu/ram of new account is not changed. + # 7. create another service offering. + # 8. upgrade vm. resource count of cpu/ram of new account is not changed. + # 9. start vm, resource count of cpu/ram of new account increases with cpu/ram of new service offering. + # 10. destroy vm, resource count of cpu/ram decreases + # 11. expunge vm, resource count of cpu/ram is not changed + """ + Configurations.update(self.apiclient, + name="resource.count.running.vms.only", + value="true" ) + + # Create dynamic service offering + self.services["service_offering"]["cpunumber"] = "" + self.services["service_offering"]["cpuspeed"] = "" + self.services["service_offering"]["memory"] = "" + + self.service_offering = ServiceOffering.create( + self.apiclient, + self.services["service_offering"]) + self.cleanup.append(self.service_offering) + + # deploy vm + try: + virtual_machine_7 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.name, + domainid=self.account.domainid, + serviceofferingid=self.service_offering.id, + customcpunumber=1, + customcpuspeed=100, + custommemory=256, + templateid=self.template.id, + zoneid=self.zone.id + ) + except Exception as e: + self.fail("Exception while deploying virtual machine: %s" % e) + + self.expectedCpu = self.expectedCpu + virtual_machine_7.cpunumber + self.expectedMemory = self.expectedMemory + virtual_machine_7.memory + self.verify_resource_count_cpu_memory(self.expectedCpu, self.expectedMemory); + + # stop vm + virtual_machine_7.stop(self.apiclient) + self.expectedCpu = self.expectedCpu - virtual_machine_7.cpunumber + self.expectedMemory = self.expectedMemory - virtual_machine_7.memory + self.verify_resource_count_cpu_memory(self.expectedCpu, self.expectedMemory); + + # create another account + self.account2 = Account.create( + self.apiclient, + self.services["account2"], + admin=True, + domainid=self.domain.id + ) + accounts = Account.list(self.apiclient, id=self.account2.id) + self.account2Cpu = int(accounts[0].cputotal) + self.account2Memory = int(accounts[0].memorytotal) + + # move vm to new account. resource count of cpu/ram of current account is not changed. resource count of cpu/ram of new account is not changed. + oldcpunumber = virtual_machine_7.cpunumber + oldmemory = virtual_machine_7.memory + virtual_machine_7.assign_virtual_machine(self.apiclient, self.account2.name, self.account2.domainid) + + self.verify_resource_count_cpu_memory(self.expectedCpu, self.expectedMemory); + self.verify_resource_count_cpu_memory(self.account2Cpu, self.account2Memory, account=self.account2); + + # create another service offering + self.service_offering_big = ServiceOffering.create( + self.apiclient, + self.services["service_offerings"]["big"] + ) + self.cleanup.append(self.service_offering_big) + + # upgrade vm + virtual_machine_7.change_service_offering(self.apiclient, self.service_offering_big.id) + self.verify_resource_count_cpu_memory(self.account2Cpu, self.account2Memory, account=self.account2); + + # start vm, resource count of cpu/ram of new account increases with cpu/ram of new service offering. + virtual_machine_7.start(self.apiclient) + self.account2Cpu = self.account2Cpu + self.service_offering_big.cpunumber + self.account2Memory = self.account2Memory + self.service_offering_big.memory + self.verify_resource_count_cpu_memory(self.account2Cpu, self.account2Memory, account=self.account2); + + # expunge vm + virtual_machine_7.delete(self.apiclient, expunge=True) + self.account2Cpu = self.account2Cpu - self.service_offering_big.cpunumber + self.account2Memory = self.account2Memory - self.service_offering_big.memory + self.verify_resource_count_cpu_memory(self.account2Cpu, self.account2Memory, account=self.account2); + + @attr(tags=["advanced", "advancedsg"], required_hardware="false") + def test_08_resource_count_vm_in_all_states_and_move_and_upgrade(self): + """Create VM with dynamic service offering. Take resources of vm in all states into calculation. Move vm to another account and upgrade it. + + Steps: + # 1. update resource.count.running.vms.only to true + # 2. create dynamic service offering + # 3. deploy vm, resource count of cpu/ram increases + # 4. stop vm, resource count of cpu/ram is not changed + # 5. create another account + # 6. move vm to new account. resource count of cpu/ram of current account decreases. resource count of cpu/ram of new account increases. + # 7. create another service offering. + # 8. upgrade vm. resource count of cpu/ram of new account is changed. + # 9. start vm, resource count of cpu/ram is not changed + # 10. destroy vm, resource count of cpu/ram decreases + # 11. expunge vm, resource count of cpu/ram is not changed + """ + Configurations.update(self.apiclient, + name="resource.count.running.vms.only", + value="false" ) + + # Create dynamic service offering + self.services["service_offering"]["cpunumber"] = "" + self.services["service_offering"]["cpuspeed"] = "" + self.services["service_offering"]["memory"] = "" + + self.service_offering = ServiceOffering.create( + self.apiclient, + self.services["service_offering"]) + self.cleanup.append(self.service_offering) + + # deploy vm + try: + virtual_machine_8 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.name, + domainid=self.account.domainid, + serviceofferingid=self.service_offering.id, + customcpunumber=1, + customcpuspeed=100, + custommemory=256, + templateid=self.template.id, + zoneid=self.zone.id + ) + except Exception as e: + self.fail("Exception while deploying virtual machine: %s" % e) + + self.expectedCpu = self.expectedCpu + virtual_machine_8.cpunumber + self.expectedMemory = self.expectedMemory + virtual_machine_8.memory + self.verify_resource_count_cpu_memory(self.expectedCpu, self.expectedMemory); + + # stop vm + virtual_machine_8.stop(self.apiclient) + self.verify_resource_count_cpu_memory(self.expectedCpu, self.expectedMemory); + + # create another account + self.account2 = Account.create( + self.apiclient, + self.services["account2"], + admin=True, + domainid=self.domain.id + ) + self.cleanup.append(self.account2) + accounts = Account.list(self.apiclient, id=self.account2.id) + self.account2Cpu = int(accounts[0].cputotal) + self.account2Memory = int(accounts[0].memorytotal) + + # move vm to new account. resource count of cpu/ram of current account decreases. resource count of cpu/ram of new account increases. + oldcpunumber = virtual_machine_8.cpunumber + oldmemory = virtual_machine_8.memory + virtual_machine_8.assign_virtual_machine(self.apiclient, self.account2.name, self.account2.domainid) + + self.expectedCpu = self.expectedCpu - virtual_machine_8.cpunumber + self.expectedMemory = self.expectedMemory - virtual_machine_8.memory + self.verify_resource_count_cpu_memory(self.expectedCpu, self.expectedMemory); + + self.account2Cpu = self.account2Cpu + virtual_machine_8.cpunumber + self.account2Memory = self.account2Memory + virtual_machine_8.memory + self.verify_resource_count_cpu_memory(self.account2Cpu, self.account2Memory, account=self.account2); + + # create another service offering + self.service_offering_big = ServiceOffering.create( + self.apiclient, + self.services["service_offerings"]["big"] + ) + self.cleanup.append(self.service_offering_big) + + # upgrade vm + virtual_machine_8.change_service_offering(self.apiclient, self.service_offering_big.id) + self.account2Cpu = self.account2Cpu + self.service_offering_big.cpunumber - oldcpunumber + self.account2Memory = self.account2Memory + self.service_offering_big.memory - oldmemory + self.verify_resource_count_cpu_memory(self.account2Cpu, self.account2Memory, account=self.account2); + + # start vm + virtual_machine_8.start(self.apiclient) + self.verify_resource_count_cpu_memory(self.account2Cpu, self.account2Memory, account=self.account2); + + # expunge vm + virtual_machine_8.delete(self.apiclient, expunge=True) + self.account2Cpu = self.account2Cpu - self.service_offering_big.cpunumber + self.account2Memory = self.account2Memory - self.service_offering_big.memory + self.verify_resource_count_cpu_memory(self.account2Cpu, self.account2Memory, account=self.account2); diff --git a/test/integration/component/test_routers.py b/test/integration/component/test_routers.py index 45e2853db898..196d054ed340 100644 --- a/test/integration/component/test_routers.py +++ b/test/integration/component/test_routers.py @@ -21,7 +21,8 @@ from marvin.cloudstackTestCase import cloudstackTestCase from marvin.cloudstackAPI import (stopVirtualMachine, stopRouter, - startRouter) + startRouter, + getRouterHealthCheckResults) from marvin.lib.utils import (cleanup_resources, get_process_status) from marvin.lib.base import (ServiceOffering, @@ -594,6 +595,75 @@ def test_03_RouterStartOnVmDeploy(self): return + @attr(tags=["advanced"], required_hardware="true") + def test_04_RouterHealthChecksResults(self): + """Test advanced zone router list contains health check records + """ + + routers = list_routers( + self.apiclient, + account=self.account.name, + domainid=self.account.domainid, + fetchhealthcheckresults=True + ) + + self.assertEqual(isinstance(routers, list), True, + "Check for list routers response return valid data" + ) + self.assertNotEqual( + len(routers), 0, + "Check list router response" + ) + + router = routers[0] + self.info("Router ID: %s & Router state: %s" % ( + router.id, router.state + )) + + self.assertEqual(isinstance(router.healthcheckresults, list), True, + "Router response should contain it's health check result as list" + ) + + cmd = getRouterHealthCheckResults.getRouterHealthCheckResultsCmd() + cmd.routerid = router.id + cmd.performfreshchecks = True # Perform fresh checks as a newly created router may not have results + healthData = self.api_client.getRouterHealthCheckResults(cmd) + self.info("Router ID: %s & Router state: %s" % ( + router.id, router.state + )) + + self.assertEqual(router.id, healthData.routerid, + "Router response should contain it's health check result so id should match" + ) + self.assertEqual(isinstance(healthData.healthchecks, list), True, + "Router response should contain it's health check result as list" + ) + + self.verifyCheckTypes(healthData.healthchecks) + self.verifyCheckNames(healthData.healthchecks) + + def verifyCheckTypes(self, healthChecks): + for checkType in ["basic", "advanced"]: + foundType = False + for check in healthChecks: + if check.checktype == checkType: + foundType = True + break + self.assertTrue(foundType, + "Router should contain health check results info for type: " + checkType + ) + + def verifyCheckNames(self, healthChecks): + for checkName in ["dns_check.py", "dhcp_check.py", "haproxy_check.py", "disk_space_check.py", "iptables_check.py", "gateways_check.py", "router_version_check.py"]: + foundCheck = False + for check in healthChecks: + if check.checkname == checkName: + foundCheck = True + break + self.assertTrue(foundCheck, + "Router should contain health check results info for check name: " + checkName + ) + class TestRouterStopCreatePF(cloudstackTestCase): diff --git a/test/integration/component/test_volume_destroy_recover.py b/test/integration/component/test_volume_destroy_recover.py new file mode 100644 index 000000000000..c9e11c08393c --- /dev/null +++ b/test/integration/component/test_volume_destroy_recover.py @@ -0,0 +1,507 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. +""" tests for Volume improvement (Destroy/Recover) in cloudstack 4.14.0.0 + +""" +# Import Local Modules +from nose.plugins.attrib import attr +from marvin.cloudstackTestCase import cloudstackTestCase +from marvin.cloudstackAPI import (deleteVolume, extractVolume, recoverVolume) +from marvin.lib.utils import (validateList, + cleanup_resources) +from marvin.lib.base import (Resources, + Volume, + Account, + Domain, + Network, + NetworkOffering, + VirtualMachine, + ServiceOffering, + DiskOffering, + Zone) +from marvin.lib.common import (get_domain, + get_zone, + get_template, + matchResourceCount, + isAccountResourceCountEqualToExpectedCount) +from marvin.codes import (PASS, FAILED, RESOURCE_PRIMARY_STORAGE, RESOURCE_VOLUME) +import logging +import random +import time + +class TestVolumeDestroyRecover(cloudstackTestCase): + @classmethod + def setUpClass(cls): + cls.testClient = super( + TestVolumeDestroyRecover, + cls).getClsTestClient() + cls.apiclient = cls.testClient.getApiClient() + cls.services = cls.testClient.getParsedTestDataConfig() + zone = get_zone(cls.apiclient, cls.testClient.getZoneForTests()) + cls.zone = Zone(zone.__dict__) + cls._cleanup = [] + + cls.logger = logging.getLogger("TestVolumeDestroyRecover") + cls.stream_handler = logging.StreamHandler() + cls.logger.setLevel(logging.DEBUG) + cls.logger.addHandler(cls.stream_handler) + + # Get Domain and templates + cls.domain = get_domain(cls.apiclient) + + cls.template = get_template(cls.apiclient, cls.zone.id, hypervisor="KVM") + if cls.template == FAILED: + sys.exit(1) + cls.templatesize = (cls.template.size / (1024 ** 3)) + + cls.services['mode'] = cls.zone.networktype + # Create Account + cls.account = Account.create( + cls.apiclient, + cls.services["account"], + admin=True, + domainid=cls.domain.id + ) + accounts = Account.list(cls.apiclient, id=cls.account.id) + cls.expectedCount = int(accounts[0].primarystoragetotal) + cls.volumeTotal = int(accounts[0].volumetotal) + + if cls.zone.securitygroupsenabled: + cls.services["shared_network_offering"]["specifyVlan"] = 'True' + cls.services["shared_network_offering"]["specifyIpRanges"] = 'True' + + cls.network_offering = NetworkOffering.create( + cls.apiclient, + cls.services["shared_network_offering"] + ) + cls.network_offering.update(cls.apiclient, state='Enabled') + + cls.account_network = Network.create( + cls.apiclient, + cls.services["network2"], + networkofferingid=cls.network_offering.id, + zoneid=cls.zone.id, + accountid=cls.account.name, + domainid=cls.account.domainid + ) + else: + cls.network_offering = NetworkOffering.create( + cls.apiclient, + cls.services["isolated_network_offering"], + ) + # Enable Network offering + cls.network_offering.update(cls.apiclient, state='Enabled') + + # Create account network + cls.services["network"]["zoneid"] = cls.zone.id + cls.services["network"]["networkoffering"] = cls.network_offering.id + cls.account_network = Network.create( + cls.apiclient, + cls.services["network"], + cls.account.name, + cls.account.domainid + ) + + # Create small service offering + cls.service_offering = ServiceOffering.create( + cls.apiclient, + cls.services["service_offerings"]["small"] + ) + + # Create disk offering + cls.disk_offering = DiskOffering.create( + cls.apiclient, + cls.services["disk_offering"], + ) + + cls._cleanup.append(cls.disk_offering) + cls._cleanup.append(cls.service_offering) + cls._cleanup.append(cls.account); + cls._cleanup.append(cls.network_offering) + + @classmethod + def tearDownClass(self): + try: + cleanup_resources(self.apiclient, self._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.cleanup = [] + return + + def tearDown(self): + try: + cleanup_resources(self.apiclient, self.cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def verify_resource_count_primary_storage(self, expectedCount, volumeTotal): + response = matchResourceCount( + self.apiclient, expectedCount, + RESOURCE_PRIMARY_STORAGE, + accountid=self.account.id) + self.assertEqual(response[0], PASS, response[1]) + + result = isAccountResourceCountEqualToExpectedCount( + self.apiclient, self.account.domainid, self.account.name, + expectedCount, RESOURCE_PRIMARY_STORAGE) + self.assertFalse(result[0], result[1]) + self.assertTrue(result[2], "Resource count of primary storage does not match") + + response = matchResourceCount( + self.apiclient, volumeTotal, + RESOURCE_VOLUME, + accountid=self.account.id) + self.assertEqual(response[0], PASS, response[1]) + + result = isAccountResourceCountEqualToExpectedCount( + self.apiclient, self.account.domainid, self.account.name, + volumeTotal, RESOURCE_VOLUME) + self.assertFalse(result[0], result[1]) + self.assertTrue(result[2], "Resource count of volume does not match") + + @attr(tags=["advanced", "advancedsg"], required_hardware="false") + def test_01_create_vm_with_data_disk(self): + """Create VM with DATA disk, then destroy it (expunge=False) and expunge it + + Steps: + # 1. create vm with root disk and data disk + # 2. destroy vm, resource count of primary storage is not changed + # 3. expunge vm, resource count of primary storage decreased with size of root disk. + # 4. delete volume (data disk), resource count of primary storage decreased with size of data disk + """ + + try: + virtual_machine_1 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.name, + domainid=self.account.domainid, + serviceofferingid=self.service_offering.id, + diskofferingid=self.disk_offering.id, + templateid=self.template.id, + zoneid=self.zone.id + ) + except Exception as e: + self.fail("Exception while deploying virtual machine: %s" % e) + + self.expectedCount = self.expectedCount + self.templatesize + self.disk_offering.disksize + self.volumeTotal = self.volumeTotal + 2 + self.verify_resource_count_primary_storage(self.expectedCount, self.volumeTotal); + + root_volumes_list = Volume.list( + self.apiclient, + virtualmachineid=virtual_machine_1.id, + type='ROOT', + listall=True + ) + status = validateList(root_volumes_list) + self.assertEqual(status[0], PASS, "ROOT Volume List Validation Failed") + root_volume_id = root_volumes_list[0].id + + data_volumes_list = Volume.list( + self.apiclient, + virtualmachineid=virtual_machine_1.id, + type='DATADISK', + listall=True + ) + status = validateList(data_volumes_list) + self.assertEqual(status[0], PASS, "DATADISK Volume List Validation Failed") + data_volume_id = data_volumes_list[0].id + + # destroy vm + virtual_machine_1.delete(self.apiclient, expunge=False) + self.verify_resource_count_primary_storage(self.expectedCount, self.volumeTotal) + + # expunge vm + virtual_machine_1.expunge(self.apiclient) + self.expectedCount = self.expectedCount - self.templatesize + self.volumeTotal = self.volumeTotal - 1 + self.verify_resource_count_primary_storage(self.expectedCount, self.volumeTotal) + + # delete datadisk + cmd = deleteVolume.deleteVolumeCmd() + cmd.id = data_volume_id + self.apiclient.deleteVolume(cmd) + self.expectedCount = self.expectedCount - self.disk_offering.disksize + self.volumeTotal = self.volumeTotal - 1 + self.verify_resource_count_primary_storage(self.expectedCount, self.volumeTotal) + + @attr(tags=["advanced", "advancedsg"], required_hardware="false") + def test_02_destroy_allocated_volume(self): + """Create volume, destroy it when expunge=false and expunge=true + + Steps: + # 1. create volume, resource count increases. + # 2. destroy volume (expunge = false), Exception happened. resource count no changes + # 3. destroy volume (expunge = True), resource count of primary storage decreased with size of volume. + """ + + # Create volume + volume = Volume.create( + self.apiclient, self.services["volume"], + zoneid=self.zone.id, account=self.account.name, + domainid=self.account.domainid, diskofferingid=self.disk_offering.id + ) + self.expectedCount = self.expectedCount + self.disk_offering.disksize + self.volumeTotal = self.volumeTotal + 1 + self.verify_resource_count_primary_storage(self.expectedCount, self.volumeTotal); + + # Destroy volume (expunge=False) + with self.assertRaises(Exception): + volume.destroy(self.apiclient) + + # Destroy volume (expunge=True) + volume.destroy(self.apiclient, expunge=True) + + self.expectedCount = self.expectedCount - self.disk_offering.disksize + self.volumeTotal = self.volumeTotal - 1 + self.verify_resource_count_primary_storage(self.expectedCount, self.volumeTotal); + + @attr(tags=["advanced", "advancedsg"], required_hardware="false") + def test_03_destroy_detached_volume(self): + """Create volume, attach/detach it, then destroy it when expunge=false and expunge=true + + Steps: + # 1. create vm without data disk, resource count increases. + # 2. create volume, resource count increases. + # 3. attach volume to a vm. resource count no changes. + # 4. detach volume from a vm. resource count no changes. + # 5. destroy volume (expunge = false), volume is Destroy. resource count decreased with size of volume. + # 6. destroy volume (expunge = true), volume is not found. resource count no changes. + # 7. destroy vm (expunge=True). resource count decreased with size of root disk + """ + # Create vm + try: + virtual_machine_2 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.name, + domainid=self.account.domainid, + serviceofferingid=self.service_offering.id, + templateid=self.template.id, + zoneid=self.zone.id + ) + except Exception as e: + self.fail("Exception while deploying virtual machine: %s" % e) + + self.expectedCount = self.expectedCount + self.templatesize + self.volumeTotal = self.volumeTotal + 1 + self.verify_resource_count_primary_storage(self.expectedCount, self.volumeTotal); + + # Create volume + volume = Volume.create( + self.apiclient, self.services["volume"], + zoneid=self.zone.id, account=self.account.name, + domainid=self.account.domainid, diskofferingid=self.disk_offering.id + ) + self.expectedCount = self.expectedCount + self.disk_offering.disksize + self.volumeTotal = self.volumeTotal + 1 + self.verify_resource_count_primary_storage(self.expectedCount, self.volumeTotal); + + # Attach volume to vm + virtual_machine_2.attach_volume(self.apiclient, volume) + self.verify_resource_count_primary_storage(self.expectedCount, self.volumeTotal); + + # Detach volume from vm + virtual_machine_2.detach_volume(self.apiclient, volume) + self.verify_resource_count_primary_storage(self.expectedCount, self.volumeTotal); + + # Destroy volume (expunge=False) + volume.destroy(self.apiclient) + self.expectedCount = self.expectedCount - self.disk_offering.disksize + self.volumeTotal = self.volumeTotal - 1 + self.verify_resource_count_primary_storage(self.expectedCount, self.volumeTotal); + + # Destroy volume (expunge=True) + volume.destroy(self.apiclient, expunge=True) + self.verify_resource_count_primary_storage(self.expectedCount, self.volumeTotal); + + # Destroy VM (expunge=True) + virtual_machine_2.delete(self.apiclient, expunge=True) + self.expectedCount = self.expectedCount - self.templatesize + self.volumeTotal = self.volumeTotal - 1 + self.verify_resource_count_primary_storage(self.expectedCount, self.volumeTotal); + + @attr(tags=["advanced", "advancedsg"], required_hardware="false") + def test_04_recover_root_volume_after_restorevm(self): + """Restore VM, recover/delete old root disk + + Steps: + # 1. create vm without data disk, resource count increases. + # 2. restore vm. resource count no changes. + # 3. check old root disk , should be Destroy state + # 4. recover old root disk. resource count increases. + # 5. delete old root disk . resource count decreases. + # 6. destroy vm (expunge=True). resource count decreased with size of root disk + """ + + # Create vm + try: + virtual_machine_3 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.name, + domainid=self.account.domainid, + serviceofferingid=self.service_offering.id, + templateid=self.template.id, + zoneid=self.zone.id + ) + except Exception as e: + self.fail("Exception while deploying virtual machine: %s" % e) + + self.expectedCount = self.expectedCount + self.templatesize + self.volumeTotal = self.volumeTotal + 1 + self.verify_resource_count_primary_storage(self.expectedCount, self.volumeTotal); + + # Get id of root disk + root_volumes_list = Volume.list( + self.apiclient, + virtualmachineid=virtual_machine_3.id, + type='ROOT', + listall=True + ) + status = validateList(root_volumes_list) + self.assertEqual(status[0], PASS, "ROOT Volume List Validation Failed") + root_volume_id = root_volumes_list[0].id + + # restore vm + virtual_machine_3.restore(self.apiclient) + self.verify_resource_count_primary_storage(self.expectedCount, self.volumeTotal); + + # check old root disk state + root_volumes_list = Volume.list( + self.apiclient, + id=root_volume_id, + listall=True + ) + status = validateList(root_volumes_list) + self.assertEqual(status[0], PASS, "ROOT Volume List Validation Failed") + root_volume = root_volumes_list[0] + self.assertEqual(root_volume['state'], 'Destroy', "ROOT volume should be Destroy after restorevm") + + # recover old root disk + cmd = recoverVolume.recoverVolumeCmd() + cmd.id = root_volume.id + self.apiclient.recoverVolume(cmd) + self.expectedCount = self.expectedCount + self.templatesize + self.volumeTotal = self.volumeTotal + 1 + self.verify_resource_count_primary_storage(self.expectedCount, self.volumeTotal); + + # delete old root disk + cmd = deleteVolume.deleteVolumeCmd() + cmd.id = root_volume.id + self.apiclient.deleteVolume(cmd) + self.expectedCount = self.expectedCount - self.templatesize + self.volumeTotal = self.volumeTotal - 1 + self.verify_resource_count_primary_storage(self.expectedCount, self.volumeTotal) + + # Destroy VM (expunge=True) + virtual_machine_3.delete(self.apiclient, expunge=True) + self.expectedCount = self.expectedCount - self.templatesize + self.volumeTotal = self.volumeTotal - 1 + self.verify_resource_count_primary_storage(self.expectedCount, self.volumeTotal); + + @attr(tags=["advanced", "advancedsg"], required_hardware="false") + def test_05_extract_root_volume_and_destroy_vm(self): + """Create VM, extract root volume, then destroy vm and volume + + Steps: + # 1. create vm without data disk, resource count increases. + # 2. stop vm + # 3. extract root volume + # 4. expunge vm, root volume in Expunged state. resource count decreased with size of root disk. + # 5. destroy volume (expunge = false), Exception happened. resource count no changes + # 6. destroy volume (expunge = true). volume is not found. resource count no changes. + """ + + # Create vm + try: + virtual_machine_4 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.name, + domainid=self.account.domainid, + serviceofferingid=self.service_offering.id, + templateid=self.template.id, + zoneid=self.zone.id + ) + except Exception as e: + self.fail("Exception while deploying virtual machine: %s" % e) + + self.expectedCount = self.expectedCount + self.templatesize + self.volumeTotal = self.volumeTotal + 1 + self.verify_resource_count_primary_storage(self.expectedCount, self.volumeTotal); + + # Get id of root disk + root_volumes_list = Volume.list( + self.apiclient, + virtualmachineid=virtual_machine_4.id, + type='ROOT', + listall=True + ) + status = validateList(root_volumes_list) + self.assertEqual(status[0], PASS, "ROOT Volume List Validation Failed") + root_volume_id = root_volumes_list[0].id + + # Stop vm + virtual_machine_4.stop(self.apiclient) + + # extract root volume + cmd = extractVolume.extractVolumeCmd() + cmd.id = root_volume_id + cmd.mode = "HTTP_DOWNLOAD" + cmd.zoneid = self.zone.id + self.apiclient.extractVolume(cmd) + + # Destroy VM (expunge=True) + virtual_machine_4.delete(self.apiclient, expunge=True) + self.expectedCount = self.expectedCount - self.templatesize + self.volumeTotal = self.volumeTotal - 1 + self.verify_resource_count_primary_storage(self.expectedCount, self.volumeTotal); + + # check root disk state + root_volumes_list = Volume.list( + self.apiclient, + id=root_volume_id, + listall=True + ) + status = validateList(root_volumes_list) + self.assertEqual(status[0], PASS, "ROOT Volume List Validation Failed") + root_volume = root_volumes_list[0] + self.assertEqual(root_volume['state'], 'Expunged', "ROOT volume should be Destroy after restorevm") + + # delete root disk + cmd = deleteVolume.deleteVolumeCmd() + cmd.id = root_volume.id + self.apiclient.deleteVolume(cmd) + self.verify_resource_count_primary_storage(self.expectedCount, self.volumeTotal) + + @attr(tags=["advanced", "advancedsg"], required_hardware="false") + def test_06_delete_network(self): + """Delete account network, resource count should not be changed + + Steps: + # 1. Delete account network + # 2. resource count should not be changed + """ + self.account_network.delete(self.apiclient) + self.verify_resource_count_primary_storage(self.expectedCount, self.volumeTotal) diff --git a/test/integration/smoke/test_create_network.py b/test/integration/smoke/test_create_network.py new file mode 100644 index 000000000000..7fe7cbbc53a6 --- /dev/null +++ b/test/integration/smoke/test_create_network.py @@ -0,0 +1,291 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. + +# Import Local Modules +from nose.plugins.attrib import attr +from marvin.cloudstackTestCase import cloudstackTestCase, unittest +from marvin.sshClient import SshClient +from marvin.lib.utils import (cleanup_resources, + random_gen) +from marvin.lib.base import (Account, + Configurations, + Domain, + Network, + NetworkOffering, + PhysicalNetwork, + ServiceOffering, + Zone) +from marvin.lib.common import (get_domain, + get_zone, + get_free_vlan) +import logging +import random + +class TestNetworkManagement(cloudstackTestCase): + @classmethod + def setUpClass(cls): + cls.testClient = super( + TestNetworkManagement, + cls).getClsTestClient() + cls.apiclient = cls.testClient.getApiClient() + cls.dbclient = cls.testClient.getDbConnection() + cls.testdata = cls.testClient.getParsedTestDataConfig() + cls.services = cls.testClient.getParsedTestDataConfig() + zone = get_zone(cls.apiclient, cls.testClient.getZoneForTests()) + cls.zone = Zone(zone.__dict__) + cls._cleanup = [] + + cls.logger = logging.getLogger("TestNetworkManagement") + cls.stream_handler = logging.StreamHandler() + cls.logger.setLevel(logging.DEBUG) + cls.logger.addHandler(cls.stream_handler) + + # Get Zone, Domain and templates + cls.domain = get_domain(cls.apiclient) + testClient = super(TestNetworkManagement, cls).getClsTestClient() + cls.zone = get_zone(cls.apiclient, testClient.getZoneForTests()) + cls.services['mode'] = cls.zone.networktype + # Create new domain, account, network and VM + cls.user_domain = Domain.create( + cls.apiclient, + services=cls.testdata["acl"]["domain2"], + parentdomainid=cls.domain.id) + + # Create account + cls.account = Account.create( + cls.apiclient, + cls.testdata["acl"]["accountD2"], + admin=True, + domainid=cls.user_domain.id + ) + + # Create small service offering + cls.service_offering = ServiceOffering.create( + cls.apiclient, + cls.testdata["service_offerings"]["small"] + ) + + cls._cleanup.append(cls.service_offering) + cls._cleanup.append(cls.account) + cls._cleanup.append(cls.user_domain) + + @classmethod + def tearDownClass(self): + try: + cleanup_resources(self.apiclient, self._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.cleanup = [] + return + + def tearDown(self): + try: + cleanup_resources(self.apiclient, self.cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @attr(tags=["adeancedsg"], required_hardware="false") + def test_01_create_network_without_start_end_ip(self): + """Create Shared network without start and end ip + + Steps: + # 1. Update the global setting allow.empty.start.end.ipaddress to true + # 2. Create a shared network without specifying start or end ip + # 3. This should create the network + # 4. Now Update the global setting allow.empty.start.end.ipaddress to false + # 5. Create a shared network without specifying start or end ip + # 6. Exception should be thrown since start and end ip are not specified + :return: + """ + # Create network offering + self.network_offering = NetworkOffering.create( + self.apiclient, + self.testdata["network_offering_shared"] + ) + + NetworkOffering.update( + self.network_offering, + self.apiclient, + id=self.network_offering.id, + state="enabled" + ) + + physical_network, vlan = get_free_vlan(self.apiclient, self.zone.id) + self.testdata["shared_network_sg"]["physicalnetworkid"] = physical_network.id + + random_subnet_number = random.randrange(100, 199) + self.testdata["shared_network_sg"]["specifyVlan"] = 'True' + self.testdata["shared_network_sg"]["specifyIpRanges"] = 'True' + self.testdata["shared_network_sg"]["name"] = "Shared-Network-SG-Test-vlan" + str(random_subnet_number) + self.testdata["shared_network_sg"]["displaytext"] = "Shared-Network-SG-Test-vlan" + str(random_subnet_number) + self.testdata["shared_network_sg"]["vlan"] = "vlan://" + str(random_subnet_number) + self.testdata["shared_network_sg"]["startip"] = None + self.testdata["shared_network_sg"]["endip"] = None + self.testdata["shared_network_sg"]["gateway"] = "192.168." + str(random_subnet_number) + ".254" + self.testdata["shared_network_sg"]["netmask"] = "255.255.255.0" + self.testdata["shared_network_sg"]["acltype"] = "account" + + # Update the global setting to true + Configurations.update(self.apiclient, + name="allow.empty.start.end.ipaddress", + value="true" + ) + + # Create network + network = Network.create( + self.apiclient, + self.testdata["shared_network_sg"], + networkofferingid=self.network_offering.id, + zoneid=self.zone.id, + accountid=self.account.name, + domainid=self.account.domainid + ) + + self.logger.info("network id is %s" % network.id) + self.cleanup.append(network) + + # Update the global setting to false + Configurations.update(self.apiclient, + name="allow.empty.start.end.ipaddress", + value="false" + ) + + # Exception should be thrown + with self.assertRaises(Exception): + self.testdata["shared_network_sg"]["vlan"] = "vlan://" + str(random_subnet_number) + network2 = Network.create( + self.apiclient, + self.testdata["shared_network_sg"], + networkofferingid=self.network_offering.id, + zoneid=self.zone.id, + accountid=self.account.name, + domainid=self.account.domainid + ) + + # Restore the setting to default value which is true + Configurations.update(self.apiclient, + name="allow.empty.start.end.ipaddress", + value="true" + ) + + self.cleanup.append(self.network_offering) + + @attr(tags=["adeancedsg"], required_hardware="false") + def test_02_create_network_with_same_name(self): + """Create Shared network with same name in same account + + Steps: + # 1. Update the global setting allow.duplicate.networkname to true + # 2. Create a shared network in an account + # 3. Try to create another shared network with same name in the same account + # 4. No exception should be thrown as multiple networks with same name can be created + # 5. Now update the global setting allow.duplicate.networkname to false + # 6. Try to create another shared network with same name in the same account + # 7. Exception should be thrown as network with same name cant be created in the same account + :return: + """ + # Update the global setting to true + Configurations.update(self.apiclient, + name="allow.duplicate.networkname", + value="true" + ) + + # Create network offering + self.network_offering = NetworkOffering.create( + self.apiclient, + self.testdata["network_offering_shared"] + ) + + NetworkOffering.update( + self.network_offering, + self.apiclient, + id=self.network_offering.id, + state="enabled" + ) + + physical_network, vlan = get_free_vlan(self.apiclient, self.zone.id) + self.testdata["shared_network_sg"]["physicalnetworkid"] = physical_network.id + + random_subnet_number = random.randrange(100, 199) + self.testdata["shared_network_sg"]["specifyVlan"] = 'True' + self.testdata["shared_network_sg"]["specifyIpRanges"] = 'True' + self.testdata["shared_network_sg"]["name"] = "Shared-Network-SG-Test-vlan-1" + self.testdata["shared_network_sg"]["displaytext"] = "Shared-Network-SG-Test-vlan-1" + self.testdata["shared_network_sg"]["vlan"] = "vlan://" + str(random_subnet_number) + self.testdata["shared_network_sg"]["startip"] = "192.168." + str(random_subnet_number) + ".1" + self.testdata["shared_network_sg"]["endip"] = "192.168." + str(random_subnet_number) + ".10" + self.testdata["shared_network_sg"]["gateway"] = "192.168." + str(random_subnet_number) + ".254" + self.testdata["shared_network_sg"]["netmask"] = "255.255.255.0" + self.testdata["shared_network_sg"]["acltype"] = "account" + + # Create the first network + network3 = Network.create( + self.apiclient, + self.testdata["shared_network_sg"], + networkofferingid=self.network_offering.id, + zoneid=self.zone.id, + accountid=self.account.name, + domainid=self.account.domainid + ) + self.cleanup.append(network3) + + # Create the second network with same name. No exception should be thrown + random_subnet_number = random.randrange(100, 199) + self.testdata["shared_network_sg"]["vlan"] = "vlan://" + str(random_subnet_number) + network4 = Network.create( + self.apiclient, + self.testdata["shared_network_sg"], + networkofferingid=self.network_offering.id, + zoneid=self.zone.id, + accountid=self.account.name, + domainid=self.account.domainid + ) + + self.cleanup.append(network4) + + # Update the global setting to true + Configurations.update(self.apiclient, + name="allow.duplicate.networkname", + value="false" + ) + + # Exception should be thrown while creating another network with same name + with self.assertRaises(Exception): + random_subnet_number = random.randrange(100, 199) + self.testdata["shared_network_sg"]["vlan"] = "vlan://" + str(random_subnet_number) + network5 = Network.create( + self.apiclient, + self.testdata["shared_network_sg"], + networkofferingid=self.network_offering.id, + zoneid=self.zone.id, + accountid=self.account.name, + domainid=self.account.domainid + ) + + # Update the global setting to original value + Configurations.update(self.apiclient, + name="allow.duplicate.networkname", + value="true" + ) + + self.cleanup.append(self.network_offering) + diff --git a/test/integration/smoke/test_network.py b/test/integration/smoke/test_network.py index e49f5475bee5..b6d1bae6b160 100644 --- a/test/integration/smoke/test_network.py +++ b/test/integration/smoke/test_network.py @@ -34,7 +34,9 @@ Network, NetworkOffering, LoadBalancerRule, - Router) + Router, + NIC, + Cluster) from marvin.lib.common import (get_domain, get_zone, get_test_template, @@ -47,6 +49,7 @@ list_configurations, verifyGuestTrafficPortGroups) from nose.plugins.attrib import attr +from marvin.lib.decoratorGenerators import skipTestIf from ddt import ddt, data # Import System modules import time @@ -1532,3 +1535,287 @@ def test_l2network_restart(self): ) return + +class TestPrivateVlansL2Networks(cloudstackTestCase): + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + + self.cleanup = [ + ] + + def tearDown(self): + cleanup_resources(self.apiclient, self.cleanup) + return + + @classmethod + def setUpClass(cls): + testClient = super(TestPrivateVlansL2Networks, cls).getClsTestClient() + cls.apiclient = testClient.getApiClient() + cls.services = testClient.getParsedTestDataConfig() + + cls.domain = get_domain(cls.apiclient) + cls.zone = get_zone(cls.apiclient, testClient.getZoneForTests()) + cls.hypervisor = testClient.getHypervisorInfo() + cls.services['mode'] = cls.zone.networktype + + # Supported hypervisor = Vmware using dvSwitches for guest traffic + isVmware = False + isDvSwitch = False + if cls.hypervisor.lower() in ["vmware"]: + isVmware = True + clusters = Cluster.list(cls.apiclient, zoneid=cls.zone.id, hypervisor=cls.hypervisor) + for cluster in clusters: + if cluster.resourcedetails.guestvswitchtype == "vmwaredvs": + # Test only if cluster uses dvSwitch + isDvSwitch = True + break + + supported = isVmware and isDvSwitch + cls.vmwareHypervisorDvSwitchesForGuestTrafficNotPresent = not supported + + cls._cleanup = [] + + if supported: + + cls.account = Account.create( + cls.apiclient, + cls.services["account"], + admin=True, + domainid=cls.domain.id + ) + cls.template = get_test_template( + cls.apiclient, + cls.zone.id, + cls.hypervisor + ) + cls.service_offering = ServiceOffering.create( + cls.apiclient, + cls.services["service_offerings"]["tiny"] + ) + cls.services["network"]["zoneid"] = cls.zone.id + cls.services['mode'] = cls.zone.networktype + cls.services["small"]["zoneid"] = cls.zone.id + cls.services["small"]["template"] = cls.template.id + cls.services["l2-network-pvlan-community-1"] = { + "name": "Test Network L2 PVLAN Community 1", + "displaytext": "Test Network L2 PVLAN Community 1", + "vlan": 900, + "isolatedpvlan": "901", + "isolatedpvlantype": "community" + } + cls.services["l2-network-pvlan-community-2"] = { + "name": "Test Network L2 PVLAN Community 2", + "displaytext": "Test Network L2 PVLAN Community 2", + "vlan": 900, + "isolatedpvlan": "902", + "isolatedpvlantype": "community" + } + cls.services["l2-network-pvlan-promiscuous"] = { + "name": "Test Network L2 PVLAN Promiscuous", + "displaytext": "Test Network L2 PVLAN Promiscuous", + "vlan": 900, + "isolatedpvlan" : "900", + "isolatedpvlantype": "promiscuous" + } + cls.services["l2-network-pvlan-isolated"] = { + "name": "Test Network L2 PVLAN Isolated", + "displaytext": "Test Network L2 PVLAN Isolated", + "vlan": 900, + "isolatedpvlan": "903", + "isolatedpvlantype": "isolated" + } + + cls.l2_network_offering = NetworkOffering.create( + cls.apiclient, + cls.services["l2-network_offering"], + specifyvlan=True + ) + cls.isolated_network_offering = NetworkOffering.create( + cls.apiclient, + cls.services["network_offering"] + ) + cls.l2_network_offering.update(cls.apiclient, state='Enabled') + cls.isolated_network_offering.update(cls.apiclient, state='Enabled') + + cls.l2_pvlan_community1 = Network.create( + cls.apiclient, + cls.services["l2-network-pvlan-community-1"], + zoneid=cls.zone.id, + networkofferingid=cls.l2_network_offering.id + ) + cls.l2_pvlan_community2 = Network.create( + cls.apiclient, + cls.services["l2-network-pvlan-community-2"], + zoneid=cls.zone.id, + networkofferingid=cls.l2_network_offering.id + ) + cls.l2_pvlan_isolated = Network.create( + cls.apiclient, + cls.services["l2-network-pvlan-isolated"], + zoneid=cls.zone.id, + networkofferingid=cls.l2_network_offering.id + ) + cls.l2_pvlan_promiscuous = Network.create( + cls.apiclient, + cls.services["l2-network-pvlan-promiscuous"], + zoneid=cls.zone.id, + networkofferingid=cls.l2_network_offering.id + ) + cls.isolated_network = Network.create( + cls.apiclient, + cls.services["isolated_network"], + zoneid=cls.zone.id, + networkofferingid=cls.isolated_network_offering.id, + accountid=cls.account.name, + domainid=cls.account.domainid + ) + + cls._cleanup = [ + cls.l2_pvlan_promiscuous, + cls.l2_pvlan_isolated, + cls.l2_pvlan_community1, + cls.l2_pvlan_community2, + cls.isolated_network, + cls.l2_network_offering, + cls.isolated_network_offering, + cls.service_offering, + cls.account, + ] + + return + + @classmethod + def tearDownClass(cls): + try: + cleanup_resources(cls.apiclient, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def deploy_vm_multiple_nics(self, name, l2net): + """ + Deploy VM on L2 network and isolated network so VM can get an IP, to use with arping command for isolation test + """ + self.services["small"]["name"] = name + + vm = VirtualMachine.create( + self.apiclient, + self.services["small"], + accountid=self.account.name, + domainid=self.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[self.isolated_network.id, l2net.id], + mode=self.services["mode"] + ) + + return vm + + def is_vm_l2_isolated_from_dest(self, vm, eth_device, dest_ip): + """ + True if VM is isolated from dest IP - using arping through the NIC on L2 network: + If arping can reach destination, then response is greater than 3 (no reply) + """ + ssh_client = vm.get_ssh_client() + response = ssh_client.execute("/usr/sbin/arping -c 5 -I %s %s" % (eth_device, str(dest_ip))) + return len(response) == 3 + + def enable_l2_nic(self, vm): + vm_ip = list(filter(lambda x: x['networkid'] == self.isolated_network.id, vm.nic))[0]['ipaddress'] + ssh_client = vm.get_ssh_client() + eth_device = "eth0" + if len(ssh_client.execute("/sbin/ifconfig %s | grep %s" % (eth_device, vm_ip))) > 0: + eth_device = "eth1" + ssh_client.execute("/sbin/ifconfig %s up" % eth_device) + return vm_ip, eth_device + + @attr(tags=["advanced", "advancedns", "smoke", "pvlan"], required_hardware="true") + @skipTestIf("vmwareHypervisorDvSwitchesForGuestTrafficNotPresent") + def test_l2_network_pvlan_connectivity(self): + try: + vm_community1_one = self.deploy_vm_multiple_nics("vmcommunity1one", self.l2_pvlan_community1) + vm_community1_two = self.deploy_vm_multiple_nics("vmcommunity1two", self.l2_pvlan_community1) + vm_community2 = self.deploy_vm_multiple_nics("vmcommunity2", self.l2_pvlan_community2) + + vm_isolated1 = self.deploy_vm_multiple_nics("vmisolated1", self.l2_pvlan_isolated) + vm_isolated2 = self.deploy_vm_multiple_nics("vmisolated2", self.l2_pvlan_isolated) + + vm_promiscuous1 = self.deploy_vm_multiple_nics("vmpromiscuous1", self.l2_pvlan_promiscuous) + vm_promiscuous2 = self.deploy_vm_multiple_nics("vmpromiscuous2", self.l2_pvlan_promiscuous) + + self.cleanup.append(vm_community1_one) + self.cleanup.append(vm_community1_two) + self.cleanup.append(vm_community2) + self.cleanup.append(vm_isolated1) + self.cleanup.append(vm_isolated2) + self.cleanup.append(vm_promiscuous1) + self.cleanup.append(vm_promiscuous2) + + vm_community1_one_ip, vm_community1_one_eth = self.enable_l2_nic(vm_community1_one) + vm_community1_two_ip, vm_community1_two_eth = self.enable_l2_nic(vm_community1_two) + vm_community2_ip, vm_community2_eth = self.enable_l2_nic(vm_community2) + vm_isolated1_ip, vm_isolated1_eth = self.enable_l2_nic(vm_isolated1) + vm_isolated2_ip, vm_isolated2_eth = self.enable_l2_nic(vm_isolated2) + vm_promiscuous1_ip, vm_promiscuous1_eth = self.enable_l2_nic(vm_promiscuous1) + vm_promiscuous2_ip, vm_promiscuous2_eth = self.enable_l2_nic(vm_promiscuous2) + + # Community PVLAN checks + different_community_isolated = self.is_vm_l2_isolated_from_dest(vm_community1_one, vm_community1_one_eth, vm_community2_ip) + same_community_isolated = self.is_vm_l2_isolated_from_dest(vm_community1_one, vm_community1_one_eth, vm_community1_two_ip) + community_to_promiscuous_isolated = self.is_vm_l2_isolated_from_dest(vm_community1_one, vm_community1_one_eth, vm_promiscuous1_ip) + community_to_isolated = self.is_vm_l2_isolated_from_dest(vm_community1_one, vm_community1_one_eth, vm_isolated1_ip) + + self.assertTrue( + different_community_isolated, + "VMs on different community PVLANs must be isolated on layer 2" + ) + + self.assertFalse( + same_community_isolated, + "VMs on the same community PVLAN must not be isolated on layer 2" + ) + + self.assertFalse( + community_to_promiscuous_isolated, + "VMs on community PVLANs must not be isolated on layer 2 to VMs on promiscuous PVLAN" + ) + + self.assertTrue( + community_to_isolated, + "VMs on community PVLANs must be isolated on layer 2 to Vms on isolated PVLAN" + ) + + # Isolated PVLAN checks + same_isolated = self.is_vm_l2_isolated_from_dest(vm_isolated1, vm_isolated1_eth, vm_isolated2_ip) + isolated_to_community_isolated = self.is_vm_l2_isolated_from_dest(vm_isolated1, vm_isolated1_eth, vm_community1_one_ip) + + self.assertTrue( + same_isolated, + "VMs on isolated PVLANs must be isolated on layer 2" + ) + self.assertTrue( + isolated_to_community_isolated, + "VMs on isolated PVLANs must be isolated on layer 2 to Vms on community PVLAN" + ) + + # Promiscuous PVLAN checks + same_promiscuous = self.is_vm_l2_isolated_from_dest(vm_promiscuous1, vm_promiscuous1_eth, vm_promiscuous2_ip) + prom_to_community_isolated = self.is_vm_l2_isolated_from_dest(vm_promiscuous1, vm_promiscuous1_eth, vm_community1_one_ip) + prom_to_isolated = self.is_vm_l2_isolated_from_dest(vm_promiscuous1, vm_promiscuous1_eth, vm_isolated1_ip) + + self.assertFalse( + same_promiscuous, + "VMs on promiscuous PVLANs must not be isolated on layer 2" + ) + self.assertFalse( + prom_to_community_isolated, + "VMs on promiscuous PVLANs must not be isolated on layer 2 to Vms on isolated PVLAN" + ) + self.assertFalse( + prom_to_isolated, + "VMs on promiscuous PVLANs must not be isolated on layer 2 to Vms on community PVLAN" + ) + except Exception as e: + self.fail("Failing test. Error: %s" % e) + + return diff --git a/test/integration/smoke/test_privategw_acl.py b/test/integration/smoke/test_privategw_acl.py index 27328db3eb02..59a31d3baa14 100644 --- a/test/integration/smoke/test_privategw_acl.py +++ b/test/integration/smoke/test_privategw_acl.py @@ -373,12 +373,14 @@ def performVPCTests(self, vpc_off, restart_with_cleanup = False): nat_rule_2 = self.create_natrule(vpc_2, vm2, public_ip_2, network_2) self.check_pvt_gw_connectivity(vm1, public_ip_1, [vm2.nic[0].ipaddress, vm1.nic[0].ipaddress]) + self.check_pvt_gw_connectivity(vm2, public_ip_2, [vm2.nic[0].ipaddress, vm1.nic[0].ipaddress]) if restart_with_cleanup: self.reboot_vpc_with_cleanup(vpc_1, cleanup = restart_with_cleanup) self.reboot_vpc_with_cleanup(vpc_2, cleanup = restart_with_cleanup) self.check_pvt_gw_connectivity(vm1, public_ip_1, [vm2.nic[0].ipaddress, vm1.nic[0].ipaddress]) + self.check_pvt_gw_connectivity(vm2, public_ip_2, [vm2.nic[0].ipaddress, vm1.nic[0].ipaddress]) def performPrivateGWInterfaceTests(self, vpc_off): self.logger.debug("Creating VPCs with offering ID %s" % vpc_off.id) @@ -438,25 +440,32 @@ def performPrivateGWInterfaceTests(self, vpc_off): public_ip_1 = self.acquire_publicip(vpc_1, network_1) nat_rule_1 = self.create_natrule(vpc_1, vm1, public_ip_1, network_1) + public_ip_2 = self.acquire_publicip(vpc_2, network_2) + nat_rule_2 = self.create_natrule(vpc_2, vm2, public_ip_2, network_2) + self.check_private_gateway_interfaces() self.check_pvt_gw_connectivity(vm1, public_ip_1, [vm2.nic[0].ipaddress, vm3.nic[0].ipaddress, vm4.nic[0].ipaddress]) + self.check_pvt_gw_connectivity(vm2, public_ip_2, [vm2.nic[0].ipaddress, vm3.nic[0].ipaddress, vm4.nic[0].ipaddress]) self.reboot_vpc_with_cleanup(vpc_1, cleanup = True) self.check_routers_state() self.check_pvt_gw_connectivity(vm1, public_ip_1, [vm2.nic[0].ipaddress, vm3.nic[0].ipaddress, vm4.nic[0].ipaddress]) + self.check_pvt_gw_connectivity(vm2, public_ip_2, [vm2.nic[0].ipaddress, vm3.nic[0].ipaddress, vm4.nic[0].ipaddress]) self.stop_router_by_type("MASTER") self.check_routers_state() self.check_private_gateway_interfaces() self.check_pvt_gw_connectivity(vm1, public_ip_1, [vm2.nic[0].ipaddress, vm3.nic[0].ipaddress, vm4.nic[0].ipaddress]) + self.check_pvt_gw_connectivity(vm2, public_ip_2, [vm2.nic[0].ipaddress, vm3.nic[0].ipaddress, vm4.nic[0].ipaddress]) self.start_routers() self.check_routers_state() self.check_private_gateway_interfaces() self.check_pvt_gw_connectivity(vm1, public_ip_1, [vm2.nic[0].ipaddress, vm3.nic[0].ipaddress, vm4.nic[0].ipaddress]) + self.check_pvt_gw_connectivity(vm2, public_ip_2, [vm2.nic[0].ipaddress, vm3.nic[0].ipaddress, vm4.nic[0].ipaddress]) self.deletePvtGw(privateGw_1.id) self.check_private_gateway_interfaces(status_to_check = "DOWN") diff --git a/test/integration/smoke/test_public_ip_range.py b/test/integration/smoke/test_public_ip_range.py index 40bc098c8093..c8fce47d09ad 100644 --- a/test/integration/smoke/test_public_ip_range.py +++ b/test/integration/smoke/test_public_ip_range.py @@ -168,14 +168,14 @@ def test_dedicate_public_ip_range_for_system_vms(self): "zoneid":self.services["zoneid"], "vlan":self.services["vlan"] } - public_ip_range = PublicIpRange.create( + self.public_ip_range = PublicIpRange.create( self.apiclient, services, forsystemvms = True ) created_ip_range_response = PublicIpRange.list( self.apiclient, - id = public_ip_range.vlan.id + id = self.public_ip_range.vlan.id ) self.assertEqual( len(created_ip_range_response), @@ -188,7 +188,7 @@ def test_dedicate_public_ip_range_for_system_vms(self): ) # Delete range - public_ip_range.delete(self.apiclient) + self.public_ip_range.delete(self.apiclient) def get_ip_as_number(self, ip_string): """ Return numeric value for ip (passed as a string) @@ -230,7 +230,7 @@ def base_system_vm(self, services, systemvmtype): # Create range for system vms self.debug("Creating Public IP range for system vms") - public_ip_range = PublicIpRange.create( + self.public_ip_range = PublicIpRange.create( self.apiclient, services, forsystemvms = True @@ -241,7 +241,7 @@ def base_system_vm(self, services, systemvmtype): self.apiclient, systemvmtype=systemvmtype, state='Running', - domainid=public_ip_range.vlan.domainid + domainid=self.public_ip_range.vlan.domainid ) self.assertTrue( isinstance(list_systemvm_response, list), @@ -262,7 +262,7 @@ def base_system_vm(self, services, systemvmtype): # Wait for CPVM to start systemvm_id = self.wait_for_system_vm_start( - public_ip_range.vlan.domainid, + self.public_ip_range.vlan.domainid, systemvmtype ) self.assertNotEqual( @@ -309,8 +309,8 @@ def base_system_vm(self, services, systemvmtype): cmd.id = systemvm_id self.apiclient.destroySystemVm(cmd) - domain_id = public_ip_range.vlan.domainid - public_ip_range.delete(self.apiclient) + domain_id = self.public_ip_range.vlan.domainid + self.public_ip_range.delete(self.apiclient) # Enable Zone cmd = updateZone.updateZoneCmd() @@ -417,18 +417,14 @@ def delete_range(self): self.apiclient.updateZone(cmd) # Delete System VM and IP range, so System VM can get IP from original ranges - for v in system_vms: - self.debug("Destroying System VM: %s" % v.id) - cmd = destroySystemVm.destroySystemVmCmd() - cmd.id = v.id - self.apiclient.destroySystemVm(cmd) + if system_vms: + for v in system_vms: + self.debug("Destroying System VM: %s" % v.id) + cmd = destroySystemVm.destroySystemVmCmd() + cmd.id = v.id + self.apiclient.destroySystemVm(cmd) - public_ip_range = PublicIpRange.list( - self.apiclient, - forsystemvms=True - ) - - public_ip_range.delete(self.apiclient) + self.public_ip_range.delete(self.apiclient) # Enable Zone cmd = updateZone.updateZoneCmd() diff --git a/test/integration/smoke/test_update_security_group.py b/test/integration/smoke/test_update_security_group.py new file mode 100644 index 000000000000..41e4d596907a --- /dev/null +++ b/test/integration/smoke/test_update_security_group.py @@ -0,0 +1,312 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. + +""" +Tests for updating security group name +""" + +# Import Local Modules +from nose.plugins.attrib import attr +from marvin.cloudstackTestCase import cloudstackTestCase, unittest +from marvin.cloudstackAPI import updateSecurityGroup, createSecurityGroup +from marvin.sshClient import SshClient +from marvin.lib.utils import (validateList, + cleanup_resources, + random_gen) +from marvin.lib.base import (PhysicalNetwork, + Account, + Host, + TrafficType, + Domain, + Network, + NetworkOffering, + VirtualMachine, + ServiceOffering, + Zone, + SecurityGroup) +from marvin.lib.common import (get_domain, + get_zone, + get_template, + list_virtual_machines, + list_routers, + list_hosts, + get_free_vlan) +from marvin.codes import (PASS, FAIL) +import logging +import random +import time + +class TestUpdateSecurityGroup(cloudstackTestCase): + @classmethod + def setUpClass(cls): + cls.testClient = super( + TestUpdateSecurityGroup, + cls).getClsTestClient() + cls.apiclient = cls.testClient.getApiClient() + cls.testdata = cls.testClient.getParsedTestDataConfig() + cls.services = cls.testClient.getParsedTestDataConfig() + + zone = get_zone(cls.apiclient, cls.testClient.getZoneForTests()) + cls.zone = Zone(zone.__dict__) + cls.template = get_template(cls.apiclient, cls.zone.id) + cls._cleanup = [] + + if str(cls.zone.securitygroupsenabled) != "True": + sys.exit(1) + + cls.logger = logging.getLogger("TestUpdateSecurityGroup") + cls.stream_handler = logging.StreamHandler() + cls.logger.setLevel(logging.DEBUG) + cls.logger.addHandler(cls.stream_handler) + + # Get Zone, Domain and templates + cls.domain = get_domain(cls.apiclient) + testClient = super(TestUpdateSecurityGroup, cls).getClsTestClient() + cls.zone = get_zone(cls.apiclient, testClient.getZoneForTests()) + cls.services['mode'] = cls.zone.networktype + + # Create new domain, account, network and VM + cls.user_domain = Domain.create( + cls.apiclient, + services=cls.testdata["acl"]["domain2"], + parentdomainid=cls.domain.id) + + # Create account + cls.account = Account.create( + cls.apiclient, + cls.testdata["acl"]["accountD2"], + admin=True, + domainid=cls.user_domain.id + ) + + cls._cleanup.append(cls.account) + cls._cleanup.append(cls.user_domain) + + @classmethod + def tearDownClass(self): + try: + cleanup_resources(self.apiclient, self._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.cleanup = [] + return + + def tearDown(self): + try: + cleanup_resources(self.apiclient, self.cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @attr(tags=["advancedsg"], required_hardware="false") + def test_01_create_security_group(self): + # Validate the following: + # + # 1. Create a new security group + # 2. Update the security group with new name + # 3. List the security group with new name as the keyword + # 4. Make sure that the response is not empty + + security_group = SecurityGroup.create( + self.apiclient, + self.testdata["security_group"], + account=self.account.name, + domainid=self.account.domainid + ) + self.debug("Created security group with ID: %s" % security_group.id) + + initial_secgroup_name = security_group.name + new_secgroup_name = "testing-update-security-group" + + cmd = updateSecurityGroup.updateSecurityGroupCmd() + cmd.id = security_group.id + cmd.name = new_secgroup_name + self.apiclient.updateSecurityGroup(cmd) + + new_security_group = SecurityGroup.list( + self.apiclient, + account=self.account.name, + domainid=self.account.domainid, + keyword=new_secgroup_name + ) + self.assertNotEqual( + len(new_security_group), + 0, + "Update security group failed" + ) + + @attr(tags=["advancedsg"], required_hardware="false") + def test_02_duplicate_security_group_name(self): + # Validate the following + # + # 1. Create a security groups with name "test" + # 2. Try to create another security group with name "test" + # 3. Creation of second security group should fail + + security_group_name = "test" + security_group = SecurityGroup.create( + self.apiclient, + {"name": security_group_name}, + account=self.account.name, + domainid=self.account.domainid + ) + self.debug("Created security group with name: %s" % security_group.name) + + security_group_list = SecurityGroup.list( + self.apiclient, + account=self.account.name, + domainid=self.account.domainid, + keyword=security_group.name + ) + self.assertNotEqual( + len(security_group_list), + 0, + "Creating security group failed" + ) + + # Need to use createSecurituGroupCmd since SecurityGroup.create + # adds random string to security group name + with self.assertRaises(Exception): + cmd = createSecurityGroup.createSecurityGroupCmd() + cmd.name = security_group.name + cmd.account = self.account.name + cmd.domainid = self.account.domainid + self.apiclient.createSecurityGroup(cmd) + + @attr(tags=["advancedsg"], required_hardware="false") + def test_03_update_security_group_with_existing_name(self): + # Validate the following + # + # 1. Create a security groups with name "test" + # 2. Create another security group + # 3. Try to update the second security group to update its name to "test" + # 4. Update security group should fail + + # Create security group + security_group = SecurityGroup.create( + self.apiclient, + self.testdata["security_group"], + account=self.account.name, + domainid=self.account.domainid + ) + self.debug("Created security group with ID: %s" % security_group.id) + security_group_name = security_group.name + + # Make sure its created + security_group_list = SecurityGroup.list( + self.apiclient, + account=self.account.name, + domainid=self.account.domainid, + keyword=security_group_name + ) + self.assertNotEqual( + len(security_group_list), + 0, + "Creating security group failed" + ) + + # Create another security group + second_security_group = SecurityGroup.create( + self.apiclient, + self.testdata["security_group"], + account=self.account.name, + domainid=self.account.domainid + ) + self.debug("Created security group with ID: %s" % second_security_group.id) + + # Make sure its created + security_group_list = SecurityGroup.list( + self.apiclient, + account=self.account.name, + domainid=self.account.domainid, + keyword=second_security_group.name + ) + self.assertNotEqual( + len(security_group_list), + 0, + "Creating security group failed" + ) + + # Update the security group + with self.assertRaises(Exception): + cmd = updateSecurityGroup.updateSecurityGroupCmd() + cmd.id = second_security_group.id + cmd.name = security_group_name + self.apiclient.updateSecurityGroup(cmd) + + @attr(tags=["advancedsg"], required_hardware="false") + def test_04_update_security_group_with_empty_name(self): + # Validate the following + # + # 1. Create a security group + # 2. Update the security group to an empty name + # 3. Update security group should fail + + # Create security group + security_group = SecurityGroup.create( + self.apiclient, + self.testdata["security_group"], + account=self.account.name, + domainid=self.account.domainid + ) + self.debug("Created security group with ID: %s" % security_group.id) + + # Make sure its created + security_group_list = SecurityGroup.list( + self.apiclient, + account=self.account.name, + domainid=self.account.domainid, + keyword=security_group.name + ) + self.assertNotEqual( + len(security_group_list), + 0, + "Creating security group failed" + ) + + # Update the security group + with self.assertRaises(Exception): + cmd = updateSecurityGroup.updateSecurityGroupCmd() + cmd.id = security_group.id + cmd.name = "" + self.apiclient.updateSecurityGroup(cmd) + + @attr(tags=["advancedsg"], required_hardware="false") + def test_05_rename_security_group(self): + # Validate the following + # + # 1. Create a security group + # 2. Update the security group and change its name to "default" + # 3. Exception should be thrown as "default" name cant be used + + security_group = SecurityGroup.create( + self.apiclient, + self.testdata["security_group"], + account=self.account.name, + domainid=self.account.domainid + ) + self.debug("Created security group with ID: %s" % security_group.id) + + with self.assertRaises(Exception): + cmd = updateSecurityGroup.updateSecurityGroupCmd() + cmd.id = security_group.id + cmd.name = "default" + self.apiclient.updateSecurityGroup(cmd) diff --git a/test/integration/smoke/test_vm_life_cycle.py b/test/integration/smoke/test_vm_life_cycle.py index 23aa16110121..3def05346a47 100644 --- a/test/integration/smoke/test_vm_life_cycle.py +++ b/test/integration/smoke/test_vm_life_cycle.py @@ -803,7 +803,6 @@ def test_11_destroy_vm_and_volumes(self): accountid=self.account.name, domainid=self.account.domainid, serviceofferingid=self.small_offering.id, - mode=self.services["mode"] ) vol1 = Volume.create( self.apiclient, diff --git a/tools/apidoc/gen_toc.py b/tools/apidoc/gen_toc.py index 1c5cf27128a5..2603552d4462 100644 --- a/tools/apidoc/gen_toc.py +++ b/tools/apidoc/gen_toc.py @@ -189,6 +189,7 @@ 'Sioc' : 'Sioc', 'Diagnostics': 'Diagnostics', 'Management': 'Management', + 'UnmanagedInstance': 'Virtual Machine' } diff --git a/tools/appliance/build.sh b/tools/appliance/build.sh index edbe11fc9b0b..25d73f1d95fb 100755 --- a/tools/appliance/build.sh +++ b/tools/appliance/build.sh @@ -354,6 +354,7 @@ function main() { vmware_export hyperv_export rm -f "dist/${appliance}" + cd dist && chmod +r * && cd .. cd dist && md5sum * > md5sum.txt && cd .. cd dist && sha512sum * > sha512sum.txt && cd .. add_on_exit log INFO "BUILD SUCCESSFUL" diff --git a/tools/appliance/systemvmtemplate/scripts/configure_systemvm_services.sh b/tools/appliance/systemvmtemplate/scripts/configure_systemvm_services.sh index 56406b711f52..7349298c1ef6 100644 --- a/tools/appliance/systemvmtemplate/scripts/configure_systemvm_services.sh +++ b/tools/appliance/systemvmtemplate/scripts/configure_systemvm_services.sh @@ -19,7 +19,7 @@ set -e set -x -CLOUDSTACK_RELEASE=4.11.3 +CLOUDSTACK_RELEASE=4.14.0 function configure_apache2() { # Enable ssl, rewrite and auth @@ -31,6 +31,21 @@ function configure_apache2() { sed -i 's/SSLProtocol .*$/SSLProtocol TLSv1.2/g' /etc/apache2/mods-available/ssl.conf } +function configure_strongswan() { + # change the charon stroke timeout from 3 minutes to 30 seconds + sed -i "s/# timeout = 0/timeout = 30000/" /etc/strongswan.d/charon/stroke.conf +} + +function configure_issue() { + cat > /etc/issue < /etc/cloudstack-release } -function configure_issue() { - cat > /etc/issue <> /etc/apt/sources.list' +sudo apt-get update -q -y > /dev/null +sudo apt-get -q -y -t bionic-updates install openjdk-11-jdk sudo apt-get -q -y install uuid-runtime genisoimage netcat > /dev/null if [[ $? -ne 0 ]]; then echo -e "\napt-get packages failed to install" fi -# Use latest ipmitool 1.8.16 -sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 1397BC53640DB551 -sudo sh -c 'echo "deb http://archive.ubuntu.com/ubuntu xenial main universe" >> /etc/apt/sources.list' -sudo apt-get update -q -y > /dev/null sudo apt-get -q -y -V install freeipmi-common libfreeipmi16 libgcrypt20 libgpg-error-dev libgpg-error0 libopenipmi0 ipmitool libpython-dev libssl-dev libffi-dev python-openssl build-essential --no-install-recommends > /dev/null +echo -e "\nIPMI version" ipmitool -V echo " diff --git a/tools/travis/install.sh b/tools/travis/install.sh index 1958cfa47796..9ddd36ca8c22 100755 --- a/tools/travis/install.sh +++ b/tools/travis/install.sh @@ -24,8 +24,19 @@ export MAVEN_OPTS="-Xmx4096m -XX:MaxPermSize=800m -Djava.security.egd=file:/dev/ set -e +DIR=$(pwd) + +cd ~ +wget https://archive.apache.org/dist/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.tar.gz +tar zxvf apache-maven-3.6.3-bin.tar.gz +export PATH=`pwd`/apache-maven-3.6.3/bin:$PATH +cd $DIR + +echo -e "\nJDK version" +export JAVA_HOME=$(readlink -f /usr/lib/jvm/java-11-openjdk-amd64/bin/java | sed "s:bin/java::") +mvn -v + if [ $TEST_SEQUENCE_NUMBER -eq 1 ]; then - DIR=$(pwd) # Pylint/pep8 systemvm python codebase cd systemvm/test && bash -x runtests.sh # Build noredist @@ -36,7 +47,7 @@ if [ $TEST_SEQUENCE_NUMBER -eq 1 ]; then mvn -P developer,systemvm -Dsimulator -Dnoredist -pl . org.apache.rat:apache-rat-plugin:0.12:check mvn -q -B -P developer,systemvm -Dsimulator -Dnoredist clean install else - mvn -Pdeveloper -Dsimulator clean install -DskipTests -T4 | egrep "Building|Tests|SUCCESS|FAILURE" + mvn -Pdeveloper -Dsimulator clean install -DskipTests=true -T4 fi # Install mysql-connector-python diff --git a/ui/l10n/ar.js b/ui/l10n/ar.js index 55622b2e986a..acfc5539c2ab 100644 --- a/ui/l10n/ar.js +++ b/ui/l10n/ar.js @@ -180,6 +180,7 @@ var dictionary = { "label.action.destroy.instance.processing": "Destroying Instance....", "label.action.destroy.systemvm": "Destroy System VM", "label.action.destroy.systemvm.processing": "Destroying System VM....", + "label.action.destroy.volume":"Destroy Volume", "label.action.detach.disk": "Detach Disk", "label.action.detach.disk.processing": "Detaching Disk....", "label.action.detach.iso": "Detach ISO", @@ -258,6 +259,7 @@ var dictionary = { "label.action.reboot.router.processing": "Rebooting Router....", "label.action.reboot.systemvm": "Reboot System VM", "label.action.reboot.systemvm.processing": "Rebooting System VM....", + "label.action.recover.volume":"Recover Volume", "label.action.recurring.snapshot": "Recurring Snapshots", "label.action.register.iso": "Register ISO", "label.action.register.template": "Register Template from URL", @@ -1847,6 +1849,7 @@ var dictionary = { "message.action.delete.zone": "Please confirm that you want to delete this zone.", "message.action.destroy.instance": "Please confirm that you want to destroy this instance.", "message.action.destroy.systemvm": "Please confirm that you want to destroy this System VM.", + "message.action.destroy.volume":"Please confirm that you want to destroy this volume.", "message.action.disable.cluster": "Please confirm that you want to disable this cluster.", "message.action.disable.nexusVswitch": "Please confirm that you want to disable this nexus 1000v", "message.action.disable.physical.network": "فضلا ، أكّد أنك تريد تعطيل هذه الشبكة الفيزيائية", @@ -1871,6 +1874,7 @@ var dictionary = { "message.action.reboot.instance": "Please confirm that you want to reboot this instance.", "message.action.reboot.router": "All services provided by this virtual router will be interrupted. Please confirm that you want to reboot this router.", "message.action.reboot.systemvm": "Please confirm that you want to reboot this system VM.", + "message.action.recover.volume":"Please confirm that you would like to recover this volume.", "message.action.release.ip": "Please confirm that you want to release this IP.", "message.action.remove.host": "Please confirm that you want to remove this host.", "message.action.reset.password.off": "Your instance currently does not support this feature.", diff --git a/ui/l10n/ca.js b/ui/l10n/ca.js index 0c55524141dc..3a7c0459402b 100644 --- a/ui/l10n/ca.js +++ b/ui/l10n/ca.js @@ -180,6 +180,7 @@ var dictionary = { "label.action.destroy.instance.processing": "Destroying Instance....", "label.action.destroy.systemvm": "Destroy System VM", "label.action.destroy.systemvm.processing": "Destroying System VM....", + "label.action.destroy.volume":"Destroy Volume", "label.action.detach.disk": "Detach Disk", "label.action.detach.disk.processing": "Detaching Disk....", "label.action.detach.iso": "Detach ISO", @@ -258,6 +259,7 @@ var dictionary = { "label.action.reboot.router.processing": "Rebooting Router....", "label.action.reboot.systemvm": "Reboot System VM", "label.action.reboot.systemvm.processing": "Rebooting System VM....", + "label.action.recover.volume":"Recover Volume", "label.action.recurring.snapshot": "Recurring Snapshots", "label.action.register.iso": "Register ISO", "label.action.register.template": "Register Template from URL", @@ -1847,6 +1849,7 @@ var dictionary = { "message.action.delete.zone": "Please confirm that you want to delete this zone.", "message.action.destroy.instance": "Please confirm that you want to destroy this instance.", "message.action.destroy.systemvm": "Please confirm that you want to destroy this System VM.", + "message.action.destroy.volume":"Please confirm that you want to destroy this volume.", "message.action.disable.cluster": "Please confirm that you want to disable this cluster.", "message.action.disable.nexusVswitch": "Please confirm that you want to disable this nexus 1000v", "message.action.disable.physical.network": "Please confirm that you want to disable this physical network.", @@ -1871,6 +1874,7 @@ var dictionary = { "message.action.reboot.instance": "Please confirm that you want to reboot this instance.", "message.action.reboot.router": "All services provided by this virtual router will be interrupted. Please confirm that you want to reboot this router.", "message.action.reboot.systemvm": "Please confirm that you want to reboot this system VM.", + "message.action.recover.volume":"Please confirm that you would like to recover this volume.", "message.action.release.ip": "Please confirm that you want to release this IP.", "message.action.remove.host": "Please confirm that you want to remove this host.", "message.action.reset.password.off": "Your instance currently does not support this feature.", diff --git a/ui/l10n/de_DE.js b/ui/l10n/de_DE.js index ca1344b87b77..4fbc827c0139 100644 --- a/ui/l10n/de_DE.js +++ b/ui/l10n/de_DE.js @@ -180,6 +180,7 @@ var dictionary = { "label.action.destroy.instance.processing": "Instanz wird zerstört....", "label.action.destroy.systemvm": "System-VM vernichten", "label.action.destroy.systemvm.processing": "System-VM wird zerstört....", + "label.action.destroy.volume":"Destroy Volume", "label.action.detach.disk": "Festplatte loslösen", "label.action.detach.disk.processing": "Festplatte wird losgelöst...", "label.action.detach.iso": "ISO loslösen", @@ -258,6 +259,7 @@ var dictionary = { "label.action.reboot.router.processing": "Router wird neu gebootet....", "label.action.reboot.systemvm": "System-VM neu starten", "label.action.reboot.systemvm.processing": "System-VM wird neu gebootet....", + "label.action.recover.volume":"Recover Volume", "label.action.recurring.snapshot": "Wiederkehrende Schnappschüsse", "label.action.register.iso": "ISO registrieren", "label.action.register.template": "Vorlage von URL registrieren", @@ -1849,6 +1851,7 @@ var dictionary = { "message.action.delete.zone": "Bitte bestätigen Sie, dass Sie diese Zone löschen möchten.", "message.action.destroy.instance": "Bitte bestätigen Sie, dass Sie diese Instanz löschen möchten.", "message.action.destroy.systemvm": "Bitte bestätigen Sie, dass Sie diese System-VM zerstören möchten.", + "message.action.destroy.volume":"Please confirm that you want to destroy this volume.", "message.action.disable.cluster": "Bitte bestätigen Sie, dass Sie diesen Cluster deaktivieren möchten.", "message.action.disable.nexusVswitch": "Bitte bestätigen Sie, dass sie diesen nexus 1000v deaktivieren möchten.", "message.action.disable.physical.network": "Bitte bestätigen Sie, dass Sie dieses physikalische Netzwerk deaktivieren möchten.", @@ -1873,6 +1876,7 @@ var dictionary = { "message.action.reboot.instance": "Bitte bestätigen Sie, dass Sie diese Instanz neu starten möchten.", "message.action.reboot.router": "Alle angebotenen Dienste dieses Routers werden unterbrochen. Bitte bestätigen Sie, dass Sie den Router neu starten möchten.", "message.action.reboot.systemvm": "Bitte bestätigen Sie, dass Sie diese System-VM neu starten möchten.", + "message.action.recover.volume":"Please confirm that you would like to recover this volume.", "message.action.release.ip": "Bitte bestätigen Sie, dass Sie diese IP freigeben möchten.", "message.action.remove.host": "Bitte bestätigen Sie, dass Sie diesen Host entfernen möchten.", "message.action.reset.password.off": "Ihre Instanz unterschützt derzeitig nicht dieses Feature.", diff --git a/ui/l10n/en.js b/ui/l10n/en.js index 66f45ea19d0b..6412a6732fc7 100644 --- a/ui/l10n/en.js +++ b/ui/l10n/en.js @@ -182,6 +182,7 @@ var dictionary = { "label.action.destroy.instance.processing":"Destroying Instance....", "label.action.destroy.systemvm":"Destroy System VM", "label.action.destroy.systemvm.processing":"Destroying System VM....", +"label.action.destroy.volume":"Destroy Volume", "label.action.detach.disk":"Detach Disk", "label.action.detach.disk.processing":"Detaching Disk....", "label.action.detach.iso":"Detach ISO", @@ -261,6 +262,7 @@ var dictionary = { "label.action.reboot.router.processing":"Rebooting Router....", "label.action.reboot.systemvm":"Reboot System VM", "label.action.reboot.systemvm.processing":"Rebooting System VM....", +"label.action.recover.volume":"Recover Volume", "label.action.recurring.snapshot":"Recurring Snapshots", "label.action.register.iso":"Register ISO", "label.action.register.ncc":"Register NCC", @@ -291,6 +293,8 @@ var dictionary = { "label.action.stop.instance.processing":"Stopping Instance....", "label.action.stop.router":"Stop Router", "label.action.stop.router.processing":"Stopping Router....", +"label.action.router.health.checks":"Get health checks result", +"label.perform.fresh.checks":"Perform fresh checks", "label.action.stop.systemvm":"Stop System VM", "label.action.stop.systemvm.processing":"Stopping System VM....", "label.action.take.snapshot":"Take Snapshot", @@ -579,6 +583,7 @@ var dictionary = { "label.continue":"Continue", "label.continue.basic.install":"Continue with basic installation", "label.copying.iso":"Copying ISO", +"label.copy.text": "Copy Text", "label.corrections.saved":"Corrections saved", "label.counter":"Counter", "label.cpu":"CPU", @@ -1505,6 +1510,12 @@ var dictionary = { "label.root.disk.offering":"Root Disk Offering", "label.root.disk.size":"Root disk size (GB)", "label.router.vm.scaled.up":"Router VM Scaled Up", +"label.router.health.checks":"Health Checks", +"label.router.health.check.name":"Check name", +"label.router.health.check.type":"Type", +"label.router.health.check.success":"Success", +"label.router.health.check.last.updated":"Last updated", +"label.router.health.check.details":"Details", "label.routing":"Routing", "label.routing.host":"Routing Host", "label.rule":"Rule", @@ -1539,6 +1550,11 @@ var dictionary = { "label.search":"Search", "label.secondary.ips":"Secondary IPs", "label.secondary.isolated.vlan.id":"Secondary Isolated VLAN ID", +"label.secondary.isolated.vlan.type":"Secondary Isolated VLAN Type", +"label.secondary.isolated.vlan.type.community":"Community", +"label.secondary.isolated.vlan.type.isolated":"Isolated", +"label.secondary.isolated.vlan.type.none":"None", +"label.secondary.isolated.vlan.type.promiscuous":"Promiscuous", "label.secondary.staging.store":"Secondary Staging Store", "label.secondary.staging.store.details":"Secondary Staging Store details", "label.secondary.storage":"Secondary Storage", @@ -1936,6 +1952,7 @@ var dictionary = { "message.action.delete.zone":"Please confirm that you want to delete this zone.", "message.action.destroy.instance":"Please confirm that you want to destroy this instance.", "message.action.destroy.systemvm":"Please confirm that you want to destroy this System VM.", +"message.action.destroy.volume":"Please confirm that you want to destroy this volume.", "message.action.disable.cluster":"Please confirm that you want to disable this cluster.", "message.action.disable.nexusVswitch":"Please confirm that you want to disable this nexus 1000v", "message.action.disable.physical.network":"Please confirm that you want to disable this physical network.", @@ -1960,6 +1977,7 @@ var dictionary = { "message.action.reboot.instance":"Please confirm that you want to reboot this instance.", "message.action.reboot.router":"All services provided by this virtual router will be interrupted. Please confirm that you want to reboot this router.", "message.action.reboot.systemvm":"Please confirm that you want to reboot this system VM.", +"message.action.recover.volume":"Please confirm that you would like to recover this volume.", "message.action.release.ip":"Please confirm that you want to release this IP.", "message.action.remove.host":"Please confirm that you want to remove this host.", "message.action.reset.password.off":"Your instance currently does not support this feature.", @@ -1974,6 +1992,7 @@ var dictionary = { "message.action.start.systemvm":"Please confirm that you want to start this system VM.", "message.action.stop.instance":"Please confirm that you want to stop this instance.", "message.action.stop.router":"All services provided by this virtual router will be interrupted. Please confirm that you want to stop this router.", +"message.action.router.health.checks":"Health checks result will be fetched from router.", "message.action.stop.systemvm":"Please confirm that you want to stop this system VM.", "message.action.take.snapshot":"Please confirm that you want to take a snapshot of this volume.", "message.action.unmanage.cluster":"Please confirm that you want to unmanage the cluster.", diff --git a/ui/l10n/es.js b/ui/l10n/es.js index a7af4e9c5391..875b7a16d323 100644 --- a/ui/l10n/es.js +++ b/ui/l10n/es.js @@ -180,6 +180,7 @@ var dictionary = { "label.action.destroy.instance.processing": "Destruyendo Instancia ....", "label.action.destroy.systemvm": "Destruye MV de Sistema", "label.action.destroy.systemvm.processing": "Destruyendo MV de Sistema...", + "label.action.destroy.volume":"Destroy Volume", "label.action.detach.disk": "Desconectar Disco", "label.action.detach.disk.processing": "Desconectando Disco ....", "label.action.detach.iso": "Desconectar ISO", @@ -258,6 +259,7 @@ var dictionary = { "label.action.reboot.router.processing": "Reiniciando Router ....", "label.action.reboot.systemvm": "Reiniciar MV de Sistema", "label.action.reboot.systemvm.processing": "Reinicando MV de Sistema...", + "label.action.recover.volume":"Recover Volume", "label.action.recurring.snapshot": "Instantáneas Recurrentes", "label.action.register.iso": "Registrar ISO", "label.action.register.template": "Registrar Plantilla desde una URL", @@ -1848,6 +1850,7 @@ var dictionary = { "message.action.delete.zone": "Por favor, confirme que desea eliminar esta Zona. ", "message.action.destroy.instance": "Por favor, confirme que desea destruir esta Instancia.", "message.action.destroy.systemvm": "Por favor, confirme que desea destruir esta MV de Sistema.", + "message.action.destroy.volume":"Please confirm that you want to destroy this volume.", "message.action.disable.cluster": "Por favor, confirme que desea deshabilitar este clúster.", "message.action.disable.nexusVswitch": "Por favor confirme que usted quiere deshabilitar este nexus 1000v", "message.action.disable.physical.network": "Por favor confirmar que usted quiere deshabilitar esta red física", @@ -1872,6 +1875,7 @@ var dictionary = { "message.action.reboot.instance": "Por favor, confirme que desea reiniciar esta Instancia.", "message.action.reboot.router": "Todos los servicios provistos por este router virtual serán interrumpidos. Por favor confirmar que desea reiniciarlo.", "message.action.reboot.systemvm": "Por favor, confirme que desea reiniciar esta MV de Sistema.", + "message.action.recover.volume":"Please confirm that you would like to recover this volume.", "message.action.release.ip": "Por favor, confirme que desea liberar esta IP ", "message.action.remove.host": "Por favor confirme que desea borrar este anfitrión.", "message.action.reset.password.off": "Su instancia no soporta esta característica actualmente.", diff --git a/ui/l10n/fr_FR.js b/ui/l10n/fr_FR.js index 74912f0715e3..92eb8de3e8bc 100644 --- a/ui/l10n/fr_FR.js +++ b/ui/l10n/fr_FR.js @@ -180,6 +180,7 @@ var dictionary = { "label.action.destroy.instance.processing": "Suppression de l'instance...", "label.action.destroy.systemvm": "Supprimer VM Système", "label.action.destroy.systemvm.processing": "Suppression de la VM Système...", + "label.action.destroy.volume":"Destroy Volume", "label.action.detach.disk": "Détacher le disque", "label.action.detach.disk.processing": "Détachement du disque...", "label.action.detach.iso": "Détacher l'image ISO", @@ -258,6 +259,7 @@ var dictionary = { "label.action.reboot.router.processing": "Redémarrage du routeur...", "label.action.reboot.systemvm": "Redémarrer VM Système", "label.action.reboot.systemvm.processing": "Redémarrage de la VM Système...", + "label.action.recover.volume":"Recover Volume", "label.action.recurring.snapshot": "Instantanés récurrents", "label.action.register.iso": "Enregistrer ISO", "label.action.register.template": "Enregistrer modèle depuis une URL", @@ -1849,6 +1851,7 @@ var dictionary = { "message.action.delete.zone": "Supprimer cette zone ?", "message.action.destroy.instance": "Supprimer cette instance ?", "message.action.destroy.systemvm": "Supprimer cette VM Système ?", + "message.action.destroy.volume":"Please confirm that you want to destroy this volume.", "message.action.disable.cluster": "Désactiver ce cluster ?", "message.action.disable.nexusVswitch": "Confirmer la désactivation de ce Nexus 1000v", "message.action.disable.physical.network": "Confirmer l'activation de ce réseau physique.", @@ -1873,6 +1876,7 @@ var dictionary = { "message.action.reboot.instance": "Redémarrer cette instance ?", "message.action.reboot.router": "Tous les services fournit par ce routeur virtuel vont être interrompus. Confirmer le ré-amorçage de ce routeur.", "message.action.reboot.systemvm": "Redémarrer cette VM Système ?", + "message.action.recover.volume":"Please confirm that you would like to recover this volume.", "message.action.release.ip": "Libérer cette adresse IP ?", "message.action.remove.host": "Êtes-vous sûr que vous voulez supprimer cet hôte.", "message.action.reset.password.off": "Votre instance ne supporte pas pour le moment cette fonctionnalité.", diff --git a/ui/l10n/hu.js b/ui/l10n/hu.js index b077d7bdb7af..6912c1ab6247 100644 --- a/ui/l10n/hu.js +++ b/ui/l10n/hu.js @@ -180,6 +180,7 @@ var dictionary = { "label.action.destroy.instance.processing": "Példány elpusztítása...", "label.action.destroy.systemvm": "Rendszer VM elpusztítása", "label.action.destroy.systemvm.processing": "Rendszer VM elpusztítása...", + "label.action.destroy.volume":"Destroy Volume", "label.action.detach.disk": "Merevlemez leválasztása", "label.action.detach.disk.processing": "Merevlemez leválasztása...", "label.action.detach.iso": "ISO leválasztása", @@ -258,6 +259,7 @@ var dictionary = { "label.action.reboot.router.processing": "Router újraindítása...", "label.action.reboot.systemvm": "Rendszer VM újraindítása", "label.action.reboot.systemvm.processing": "Rendszer VM újraindítása", + "label.action.recover.volume":"Recover Volume", "label.action.recurring.snapshot": "Ismétlődő pillanatfelvételek", "label.action.register.iso": "ISO regisztrációja", "label.action.register.template": "Sablon regisztrációja URL-ről", @@ -1847,6 +1849,7 @@ var dictionary = { "message.action.delete.zone": "Erősítsd meg, hogy törölni akarod ezt a zónát!", "message.action.destroy.instance": "Erősítsd meg, hogy el akarod pusztítani ezt a példányt!", "message.action.destroy.systemvm": "Erősítsd meg, hogy el akarod pusztítani ezt a rendszer VM-et!", + "message.action.destroy.volume":"Please confirm that you want to destroy this volume.", "message.action.disable.cluster": "Erősítsd meg, hogy ki akarod kapcsolni ezt a fürtöt!", "message.action.disable.nexusVswitch": "Erősítsd meg, hogy ki akarod kapcsolni ezt a nexus 1000v-t!", "message.action.disable.physical.network": "Erősítsd meg, hogy ki akarod kapcsolni ezt a fizikai hálózatot!", @@ -1871,6 +1874,7 @@ var dictionary = { "message.action.reboot.instance": "Erősítsd meg, hogy újra akarod indítani ezt a példányt!", "message.action.reboot.router": "Minden a router által nyújtott szolgáltatás megszakad. Erősítsd meg, hogy újra akarod indítani a routert!", "message.action.reboot.systemvm": "Erősítsd meg, hogy újra akarod indítani ezt a rendszer VM-et!", + "message.action.recover.volume":"Please confirm that you would like to recover this volume.", "message.action.release.ip": "Erősítsd meg, hogy el akarod engedni ezt az IP címet!", "message.action.remove.host": "Erősítsd meg, hogy törölni akarod ezt a kiszolgálót!", "message.action.reset.password.off": "A példány nem támogatja ezt a lehetőséget.", diff --git a/ui/l10n/it_IT.js b/ui/l10n/it_IT.js index cd7b767bef7b..4c3ed1208874 100644 --- a/ui/l10n/it_IT.js +++ b/ui/l10n/it_IT.js @@ -180,6 +180,7 @@ var dictionary = { "label.action.destroy.instance.processing": "Rimozione Instanza in corso....", "label.action.destroy.systemvm": "Rimozione VM di sistema", "label.action.destroy.systemvm.processing": "Rimozione VM di Sistema in corso....", + "label.action.destroy.volume":"Destroy Volume", "label.action.detach.disk": "Scollegamento di un Disco", "label.action.detach.disk.processing": "Scollegamento Disco in corso....", "label.action.detach.iso": "Scollegamento immagine ISO", @@ -258,6 +259,7 @@ var dictionary = { "label.action.reboot.router.processing": "Riavvio Router in corso....", "label.action.reboot.systemvm": "Riavvio VM di Sistema", "label.action.reboot.systemvm.processing": "Riavvio VM di Sistema in corso....", + "label.action.recover.volume":"Recover Volume", "label.action.recurring.snapshot": "Snapshot Ricorrenti", "label.action.register.iso": "Registrare una ISO", "label.action.register.template": "Registra un Template da URL", @@ -1847,6 +1849,7 @@ var dictionary = { "message.action.delete.zone": "Please confirm that you want to delete this zone.", "message.action.destroy.instance": "Please confirm that you want to destroy this instance.", "message.action.destroy.systemvm": "Please confirm that you want to destroy this System VM.", + "message.action.destroy.volume":"Please confirm that you want to destroy this volume.", "message.action.disable.cluster": "Please confirm that you want to disable this cluster.", "message.action.disable.nexusVswitch": "Si prega di confermare di voler disabilitare questo nexus 1000v", "message.action.disable.physical.network": "Si prega di confermare di voler disabilitare questa rete fisica.", @@ -1871,6 +1874,7 @@ var dictionary = { "message.action.reboot.instance": "Please confirm that you want to reboot this instance.", "message.action.reboot.router": "Tutti i servizi forniti da questo router virtuale saranno interrotti. Si prega di confermare di voler riavviare questo router.", "message.action.reboot.systemvm": "Please confirm that you want to reboot this system VM.", + "message.action.recover.volume":"Please confirm that you would like to recover this volume.", "message.action.release.ip": "Please confirm that you want to release this IP.", "message.action.remove.host": "Si prega di confermare di voler rimuovere questo host.", "message.action.reset.password.off": "Your instance currently does not support this feature.", diff --git a/ui/l10n/ja_JP.js b/ui/l10n/ja_JP.js index 225e5c5cc6fd..b876d3346294 100644 --- a/ui/l10n/ja_JP.js +++ b/ui/l10n/ja_JP.js @@ -180,6 +180,7 @@ var dictionary = { "label.action.destroy.instance.processing": "インスタンスを破棄しています...", "label.action.destroy.systemvm": "システム VM の破棄", "label.action.destroy.systemvm.processing": "システム VM を破棄しています...", + "label.action.destroy.volume":"ボリュームの破棄", "label.action.detach.disk": "ディスクのデタッチ", "label.action.detach.disk.processing": "ディスクをデタッチしています...", "label.action.detach.iso": "ISO のデタッチ", @@ -258,6 +259,7 @@ var dictionary = { "label.action.reboot.router.processing": "ルーターを再起動しています...", "label.action.reboot.systemvm": "システム VM の再起動", "label.action.reboot.systemvm.processing": "システム VM を再起動しています...", + "label.action.recover.volume":"ボリュームの復元", "label.action.recurring.snapshot": "定期スナップショット", "label.action.register.iso": "ISO の登録", "label.action.register.template": "URL からのテンプレートの登録", @@ -1849,6 +1851,7 @@ var dictionary = { "message.action.delete.zone": "このゾーンを削除してもよろしいですか?", "message.action.destroy.instance": "このインスタンスを破棄してもよろしいですか?", "message.action.destroy.systemvm": "このシステム VM を破棄してもよろしいですか?", + "message.action.destroy.volume":"このボリュームを破棄してもよろしいですか?", "message.action.disable.cluster": "このクラスターを無効にしてもよろしいですか?", "message.action.disable.nexusVswitch": "この Nexus 1000V を無効にしてもよろしいですか?", "message.action.disable.physical.network": "この物理ネットワークを無効にしてもよろしいですか?", @@ -1873,6 +1876,7 @@ var dictionary = { "message.action.reboot.instance": "このインスタンスを再起動してもよろしいですか?", "message.action.reboot.router": "この仮想ルーターで提供するすべてのサービスが中断されます。このルーターを再起動してもよろしいですか?", "message.action.reboot.systemvm": "このシステム VM を再起動してもよろしいですか?", + "message.action.recover.volume":"このボリュームを復元してもよろしいですか?", "message.action.release.ip": "この IP アドレスを解放してもよろしいですか?", "message.action.remove.host": "このホストを削除してもよろしいですか?", "message.action.reset.password.off": "インスタンスは現在この機能をサポートしていません。", diff --git a/ui/l10n/ko_KR.js b/ui/l10n/ko_KR.js index dd3de7e62d19..bdcae7d5a0e9 100644 --- a/ui/l10n/ko_KR.js +++ b/ui/l10n/ko_KR.js @@ -180,6 +180,7 @@ var dictionary = { "label.action.destroy.instance.processing": "인스턴스를 파기하는 중...", "label.action.destroy.systemvm": "시스템 VM 파기", "label.action.destroy.systemvm.processing": "시스템 VM를 파기하는 중...", + "label.action.destroy.volume":"Destroy Volume", "label.action.detach.disk": "디스크 분리", "label.action.detach.disk.processing": "디스크를 분리 하는 중...", "label.action.detach.iso": "ISO 분리", @@ -258,6 +259,7 @@ var dictionary = { "label.action.reboot.router.processing": "라우터를 재시작하는 중...", "label.action.reboot.systemvm": "시스템 VM 재시작", "label.action.reboot.systemvm.processing": "시스템 VM를 재시작하는 중...", + "label.action.recover.volume":"Recover Volume", "label.action.recurring.snapshot": "정기 스냅샷", "label.action.register.iso": "ISO 등록", "label.action.register.template": "Register Template from URL", @@ -1847,6 +1849,7 @@ var dictionary = { "message.action.delete.zone": "현재 Zone을 삭제하시겠습니까?", "message.action.destroy.instance": "현재 인스턴스를 파기하시겠습니까?", "message.action.destroy.systemvm": "현재 시스템 VM를 파기하시겠습니까?", + "message.action.destroy.volume":"Please confirm that you want to destroy this volume.", "message.action.disable.cluster": "현재 클러스터를 사용 안 함으로 하시겠습니까?", "message.action.disable.nexusVswitch": "현재 Nexus 1000V를 사용 안 함으로 하시겠습니까?", "message.action.disable.physical.network": "현재 물리 네트워크를 사용 안 함으로 하시겠습니까?", @@ -1871,6 +1874,7 @@ var dictionary = { "message.action.reboot.instance": "현재 인스턴스를 재시작하시겠습니까?", "message.action.reboot.router": "현재 가상 라우터로 제공하는 모든 서비스가 중단됩니다. 이 라우터를 재시작하시겠습니까?", "message.action.reboot.systemvm": "현재 시스템 VM을 재시작하시겠습니까?", + "message.action.recover.volume":"Please confirm that you would like to recover this volume.", "message.action.release.ip": "현재 IP 주소를 해제하시겠습니까?", "message.action.remove.host": "현재 호스트를 삭제하시겠습니까?", "message.action.reset.password.off": "인스턴스는 현재 기능을 지원 하지 않습니다.", diff --git a/ui/l10n/nb_NO.js b/ui/l10n/nb_NO.js index 98592cba8251..364a3fc14a79 100644 --- a/ui/l10n/nb_NO.js +++ b/ui/l10n/nb_NO.js @@ -180,6 +180,7 @@ var dictionary = { "label.action.destroy.instance.processing": "Ødelegger instans....", "label.action.destroy.systemvm": "Slett system VM", "label.action.destroy.systemvm.processing": "Sletter system VM....", + "label.action.destroy.volume":"Destroy Volume", "label.action.detach.disk": "Frakoble disk", "label.action.detach.disk.processing": "Kobler fra disk....", "label.action.detach.iso": "Frakoble ISO", @@ -258,6 +259,7 @@ var dictionary = { "label.action.reboot.router.processing": "Omstaer Instans....", "label.action.reboot.systemvm": "Omstart System VM", "label.action.reboot.systemvm.processing": "Omstarter System VM", + "label.action.recover.volume":"Recover Volume", "label.action.recurring.snapshot": "Gjentagende øyeblikksbilder", "label.action.register.iso": "Registrer ISO", "label.action.register.template": "Registrer mal fra en URL", @@ -1847,6 +1849,7 @@ var dictionary = { "message.action.delete.zone": "Vennligst bekreft at du ønsker å slette denne sone.", "message.action.destroy.instance": "Vennligst bekreft at du ønsker å fjerne denne instansen.", "message.action.destroy.systemvm": "Vennligst bekreft at du ønsker å ødelegge denne System VM.", + "message.action.destroy.volume":"Please confirm that you want to destroy this volume.", "message.action.disable.cluster": "Vennligst bekreft at du ønsker å detaktivere denne klyngen.", "message.action.disable.nexusVswitch": "Vennligst bekreft at du ønsker å deaktivere denne nexus 1000v", "message.action.disable.physical.network": "Vennligst bekreft at du ønsker å deaktivere dette fysiske nettverket.", @@ -1871,6 +1874,7 @@ var dictionary = { "message.action.reboot.instance": "Vennligst bekreft at du vill restarte denne instansen.", "message.action.reboot.router": "Alle tjenester levert fra denne virtuelle ruter vil bli avbrutt. Vennligst bekreft at du ønsker å restarte denne ruteren.", "message.action.reboot.systemvm": "Vennligst bekreft at du vil restarte denne system VM", + "message.action.recover.volume":"Please confirm that you would like to recover this volume.", "message.action.release.ip": "Vennligst bekreft at du ønsker å frigi denne IP.", "message.action.remove.host": "Vennligst bekreft at du vil gjerne denne tjeneren.", "message.action.reset.password.off": "Din instans støtter foreløpig ikke denne funksjonen.", diff --git a/ui/l10n/nl_NL.js b/ui/l10n/nl_NL.js index 882598b2d4d9..ffb1f1e50306 100644 --- a/ui/l10n/nl_NL.js +++ b/ui/l10n/nl_NL.js @@ -180,6 +180,7 @@ var dictionary = { "label.action.destroy.instance.processing": "Bezig met vernietigen van Instantie....", "label.action.destroy.systemvm": "Vernietig Systeem VM", "label.action.destroy.systemvm.processing": "Bezig met vernietigen van Systeem VM....", + "label.action.destroy.volume":"Vernietig schijf", "label.action.detach.disk": "Ontkoppel Schijf", "label.action.detach.disk.processing": "Bezig met ontkoppelen van Schijf....", "label.action.detach.iso": "Ontkoppel ISO", @@ -258,6 +259,7 @@ var dictionary = { "label.action.reboot.router.processing": "Bezig met herstarten van Router....", "label.action.reboot.systemvm": "Herstart Systeem VM", "label.action.reboot.systemvm.processing": "Bezig met herstarten van Systeem VM....", + "label.action.recover.volume":"Herstel schijf", "label.action.recurring.snapshot": "Terugkerende Snapshots", "label.action.register.iso": "Registreer ISO", "label.action.register.template": "Registreer een template van een URL", @@ -1847,6 +1849,7 @@ var dictionary = { "message.action.delete.zone": "Bevestig dat u deze zone wilt verwijderen", "message.action.destroy.instance": "Bevestig dat u deze instantie wilt vernietigen", "message.action.destroy.systemvm": "Bevestig dat u deze Systeem VM wilt vernietigen", + "message.action.destroy.volume":"Bevestig alstublieft dat U deze schijf wilt vernietigen?", "message.action.disable.cluster": "Bevestig dat u dit cluster wilt uitschakelen.", "message.action.disable.nexusVswitch": "Bevestig dat u deze nexus 1000v wilt uitschakelen.", "message.action.disable.physical.network": "Bevestig dat u dit fysieke netwerk wilt uitschakelen.", @@ -1871,6 +1874,7 @@ var dictionary = { "message.action.reboot.instance": "Bevestig dat u deze instantie wilt herstarten.", "message.action.reboot.router": "Als u deze router herstarten zullen de diensten op de router verstoord worden. Weet u zeker dat u deze actie wil uitvoeren?", "message.action.reboot.systemvm": "Bevestig dat u deze Systeem VM wilt herstarten.", + "message.action.recover.volume":"Bevestig alstublieft dat U deze schijf wilt herstellen?", "message.action.release.ip": "Bevestigd dat u dit IP adres wilt los koppelen.", "message.action.remove.host": "Bevestig dat u deze host wilt verwijderen.", "message.action.reset.password.off": "Uw instantie ondersteunt deze functie momenteel niet.", diff --git a/ui/l10n/pl.js b/ui/l10n/pl.js index ec3daccc3a87..7f993c668034 100644 --- a/ui/l10n/pl.js +++ b/ui/l10n/pl.js @@ -180,6 +180,7 @@ var dictionary = { "label.action.destroy.instance.processing": "Usuwam instancję", "label.action.destroy.systemvm": "Destroy System VM", "label.action.destroy.systemvm.processing": "Destroying System VM....", + "label.action.destroy.volume":"Destroy Volume", "label.action.detach.disk": "Odłącz dysk", "label.action.detach.disk.processing": "Odłączanie dysku....", "label.action.detach.iso": "Odłącz obraz ISO", @@ -258,6 +259,7 @@ var dictionary = { "label.action.reboot.router.processing": "Restartuje router.....", "label.action.reboot.systemvm": "Restartuj system VM", "label.action.reboot.systemvm.processing": "Restartuje system VM....", + "label.action.recover.volume":"Recover Volume", "label.action.recurring.snapshot": "Recurring Snapshots", "label.action.register.iso": "Rejestruj ISO", "label.action.register.template": "Register Template from URL", @@ -1847,6 +1849,7 @@ var dictionary = { "message.action.delete.zone": "Please confirm that you want to delete this zone.", "message.action.destroy.instance": "Please confirm that you want to destroy this instance.", "message.action.destroy.systemvm": "Please confirm that you want to destroy this System VM.", + "message.action.destroy.volume":"Please confirm that you want to destroy this volume.", "message.action.disable.cluster": "Please confirm that you want to disable this cluster.", "message.action.disable.nexusVswitch": "Please confirm that you want to disable this nexus 1000v", "message.action.disable.physical.network": "Please confirm that you want to disable this physical network.", @@ -1871,6 +1874,7 @@ var dictionary = { "message.action.reboot.instance": "Please confirm that you want to reboot this instance.", "message.action.reboot.router": "All services provided by this virtual router will be interrupted. Please confirm that you want to reboot this router.", "message.action.reboot.systemvm": "Please confirm that you want to reboot this system VM.", + "message.action.recover.volume":"Please confirm that you would like to recover this volume.", "message.action.release.ip": "Please confirm that you want to release this IP.", "message.action.remove.host": "Please confirm that you want to remove this host.", "message.action.reset.password.off": "Your instance currently does not support this feature.", diff --git a/ui/l10n/pt_BR.js b/ui/l10n/pt_BR.js index 43f7252bf22a..d3969a3dd485 100644 --- a/ui/l10n/pt_BR.js +++ b/ui/l10n/pt_BR.js @@ -180,6 +180,7 @@ var dictionary = { "label.action.destroy.instance.processing": "Apagando Instância....", "label.action.destroy.systemvm": "Apagar VM de Sistema", "label.action.destroy.systemvm.processing": "Apagando VM de Sistema....", + "label.action.destroy.volume":"Destroy Volume", "label.action.detach.disk": "Desplugar Disco", "label.action.detach.disk.processing": "Desplugando Disco....", "label.action.detach.iso": "Desplugar ISO", @@ -258,6 +259,7 @@ var dictionary = { "label.action.reboot.router.processing": "Reiniciando Roteador....", "label.action.reboot.systemvm": "Reiniciar VM de Sistema", "label.action.reboot.systemvm.processing": "Reiniciando VM de Sistema....", + "label.action.recover.volume":"Recover Volume", "label.action.recurring.snapshot": "Snapshots recorrentes", "label.action.register.iso": "Registrar ISO", "label.action.register.template": "Registrar Template da URL", @@ -1847,6 +1849,7 @@ var dictionary = { "message.action.delete.zone": "Confirme que você deseja remover esta Zona.", "message.action.destroy.instance": "Por favor, confirme que você deseja excluir esta Instância.", "message.action.destroy.systemvm": "Confirme que você deseja excluir esta VM de Sistema.", + "message.action.destroy.volume":"Please confirm that you want to destroy this volume.", "message.action.disable.cluster": "Confirma a desativação do cluster.", "message.action.disable.nexusVswitch": "Por favor confirme que voc� deseja desabilitar este nexusVswitch", "message.action.disable.physical.network": "Por favor confirme que você deseja desabilitar esta rede física.", @@ -1871,6 +1874,7 @@ var dictionary = { "message.action.reboot.instance": "Por favor, confirme que você deseja reiniciar esta instância.", "message.action.reboot.router": "Confirme que voc� deseja reiniciar este roteador.", "message.action.reboot.systemvm": "Confirme que você deseja reiniciar esta VM de sistema.", + "message.action.recover.volume":"Please confirm that you would like to recover this volume.", "message.action.release.ip": "Confirme que você deseja liberar este IP.", "message.action.remove.host": "Favor confirmar que você deseja remover este host.", "message.action.reset.password.off": "Sua Instância não suporta esta funcionalidade.", diff --git a/ui/l10n/ru_RU.js b/ui/l10n/ru_RU.js index d20117505cb2..49f4d8ae47ba 100644 --- a/ui/l10n/ru_RU.js +++ b/ui/l10n/ru_RU.js @@ -180,6 +180,7 @@ var dictionary = { "label.action.destroy.instance.processing": "Уничтожение машины...", "label.action.destroy.systemvm": "Уничтожить системную ВМ", "label.action.destroy.systemvm.processing": "Уничтожение системной ВМ....", + "label.action.destroy.volume":"Destroy Volume", "label.action.detach.disk": "Отсоединить диск", "label.action.detach.disk.processing": "Отсоединение диска....", "label.action.detach.iso": "Отсоединить ISO", @@ -258,6 +259,7 @@ var dictionary = { "label.action.reboot.router.processing": "Перезагрузка роутера...", "label.action.reboot.systemvm": "Перезапустить системную ВМ", "label.action.reboot.systemvm.processing": "Перезагрузка системной ВМ", + "label.action.recover.volume":"Recover Volume", "label.action.recurring.snapshot": "Повторяемые снимки", "label.action.register.iso": "Регистрация ISO", "label.action.register.template": "Регистрация шаблона по URL", @@ -1847,6 +1849,7 @@ var dictionary = { "message.action.delete.zone": "Пожалуйста подтвердите, что Вы хотите удалть эту зону.", "message.action.destroy.instance": "Пожалуйста подтвердите, что Вы хотите уничтожить эту машину.", "message.action.destroy.systemvm": "Подтвердите, что вы действительно хотите удалить эту системную ВМ.", + "message.action.destroy.volume":"Please confirm that you want to destroy this volume.", "message.action.disable.cluster": "Пожалуйста подтвердите, что Вы хотите отключить данный кластер.", "message.action.disable.nexusVswitch": "Пожалуйста, подтвердите, что вы хотите включить это nexusVswitch.", "message.action.disable.physical.network": "Подтвердите, что вы действительно хотите выключить эту физическую сеть.", @@ -1871,6 +1874,7 @@ var dictionary = { "message.action.reboot.instance": "Подтвердите, что вы действительно хотите перезагрузить эту машину.", "message.action.reboot.router": "Подтвердите, что вы действительно хотите перезагрузить этот роутер.", "message.action.reboot.systemvm": "Подтвердите, что вы действительно хотите запустить эту системную ВМ.", + "message.action.recover.volume":"Please confirm that you would like to recover this volume.", "message.action.release.ip": "Пожалуйста подтвержите желание освободить этот IP адрес.", "message.action.remove.host": "Удаление последнего/единственного сервера в кластере и повторная его установка приведет уничтожению рабочего окружения/базы данных на сервере и сделае гостевые машины непригодными к использованию.", "message.action.reset.password.off": "На данный момент машина не поддерживает данную функцию", diff --git a/ui/l10n/zh_CN.js b/ui/l10n/zh_CN.js index bb5f1d9eecd5..26cb7081869c 100644 --- a/ui/l10n/zh_CN.js +++ b/ui/l10n/zh_CN.js @@ -180,6 +180,7 @@ var dictionary = { "label.action.destroy.instance.processing": "正在销毁实例...", "label.action.destroy.systemvm": "销毁系统 VM", "label.action.destroy.systemvm.processing": "正在销毁系统 VM...", + "label.action.destroy.volume":"销毁卷", "label.action.detach.disk": "取消附加磁盘", "label.action.detach.disk.processing": "正在取消附加磁盘...", "label.action.detach.iso": "取消附加 ISO", @@ -258,6 +259,7 @@ var dictionary = { "label.action.reboot.router.processing": "正在重新启动路由器...", "label.action.reboot.systemvm": "重新启动系统 VM", "label.action.reboot.systemvm.processing": "正在重新启动系统 VM...", + "label.action.recover.volume":"恢复卷", "label.action.recurring.snapshot": "重现快照", "label.action.register.iso": "注册 ISO", "label.action.register.template": "使用URL注册模板", @@ -1849,6 +1851,7 @@ var dictionary = { "message.action.delete.zone": "请确认您确实要删除此资源域。", "message.action.destroy.instance": "请确认您确实要销毁此实例。", "message.action.destroy.systemvm": "请确认您确实要销毁此系统 VM。", + "message.action.destroy.volume":"你确定要销毁这个卷吗?", "message.action.disable.cluster": "请确认您确实要禁用此群集。", "message.action.disable.nexusVswitch": "请确认您确实要禁用此 Nexus 1000v", "message.action.disable.physical.network": "请确认您确实要禁用此物理网络。", @@ -1873,6 +1876,7 @@ var dictionary = { "message.action.reboot.instance": "请确认您确实要重新启动此实例。", "message.action.reboot.router": "此虚拟路由器提供的所有服务都将中断。请确认您确实要重新启动此路由器。", "message.action.reboot.systemvm": "请确认您确实要重新启动此系统 VM。", + "message.action.recover.volume":"你确定要恢复这个卷吗?", "message.action.release.ip": "请确认您确实要释放此 IP。", "message.action.remove.host": "请确认您确实要删除此主机。", "message.action.reset.password.off": "您的实例当前不支持此功能。", diff --git a/ui/scripts/cloudStack.js b/ui/scripts/cloudStack.js index 9b5f0117058b..e6550b730746 100644 --- a/ui/scripts/cloudStack.js +++ b/ui/scripts/cloudStack.js @@ -102,6 +102,64 @@ var $container = $('#cloudStack3-container'); + var updateSharedConfigs = function() { + // Update global pagesize for list APIs in UI + $.ajax({ + type: 'GET', + url: createURL('listConfigurations'), + data: {name: 'default.ui.page.size'}, + dataType: 'json', + async: false, + success: function(data, textStatus, xhr) { + if (data && data.listconfigurationsresponse && data.listconfigurationsresponse.configuration) { + var config = data.listconfigurationsresponse.configuration[0]; + if (config && config.name == 'default.ui.page.size') { + pageSize = parseInt(config.value); + } + } + }, + error: function(xhr) { // ignore any errors, fallback to the default + } + }); + + // Update global pagesize for sort key in UI + $.ajax({ + type: 'GET', + url: createURL('listConfigurations'), + data: {name: 'sortkey.algorithm'}, + dataType: 'json', + async: false, + success: function(data, textStatus, xhr) { + if (data && data.listconfigurationsresponse && data.listconfigurationsresponse.configuration) { + var config = data.listconfigurationsresponse.configuration[0]; + if (config && config.name == 'sortkey.algorithm') { + g_sortKeyIsAscending = config.value == 'true'; + } + } + }, + error: function(xhr) { // ignore any errors, fallback to the default + } + }); + + // Update global router health checks enabled + $.ajax({ + type: 'GET', + url: createURL('listConfigurations'), + data: {name: 'router.health.checks.enabled'}, + dataType: 'json', + async: false, + success: function(data, textStatus, xhr) { + if (data && data.listconfigurationsresponse && data.listconfigurationsresponse.configuration) { + var config = data.listconfigurationsresponse.configuration[0]; + if (config && config.name == 'router.health.checks.enabled') { + g_routerHealthChecksEnabled = config.value == 'true'; + } + } + }, + error: function(xhr) { // ignore any errors, fallback to the default + } + }); + } var loginArgs = { $container: $container, @@ -148,6 +206,7 @@ } g_allowUserExpungeRecoverVm = json.listcapabilitiesresponse.capability.allowuserexpungerecovervm; + g_allowUserExpungeRecoverVolume = json.listcapabilitiesresponse.capability.allowuserexpungerecovervolume; g_userProjectsEnabled = json.listcapabilitiesresponse.capability.allowusercreateprojects; g_cloudstackversion = json.listcapabilitiesresponse.capability.cloudstackversion; @@ -170,61 +229,25 @@ } }); - // Update global pagesize for list APIs in UI - $.ajax({ - type: 'GET', - url: createURL('listConfigurations'), - data: {name: 'default.ui.page.size'}, - dataType: 'json', - async: false, - success: function(data, textStatus, xhr) { - if (data && data.listconfigurationsresponse && data.listconfigurationsresponse.configuration) { - var config = data.listconfigurationsresponse.configuration[0]; - if (config && config.name == 'default.ui.page.size') { - pageSize = parseInt(config.value); - } - } - }, - error: function(xhr) { // ignore any errors, fallback to the default - } - }); - - // Update global pagesize for sort key in UI - $.ajax({ - type: 'GET', - url: createURL('listConfigurations'), - data: {name: 'sortkey.algorithm'}, - dataType: 'json', - async: false, - success: function(data, textStatus, xhr) { - if (data && data.listconfigurationsresponse && data.listconfigurationsresponse.configuration) { - var config = data.listconfigurationsresponse.configuration[0]; - if (config && config.name == 'sortkey.algorithm') { - g_sortKeyIsAscending = config.value == 'true'; - } - } - }, - error: function(xhr) { // ignore any errors, fallback to the default - } - }); - - // Populate IDP list - $.ajax({ - type: 'GET', - url: createURL('listIdps'), - dataType: 'json', - async: false, - success: function(data, textStatus, xhr) { - if (data && data.listidpsresponse && data.listidpsresponse.idp) { - var idpList = data.listidpsresponse.idp.sort(function (a, b) { - return a.orgName.localeCompare(b.orgName); - }); - g_idpList = idpList; - } - }, - error: function(xhr) { - } - }); + updateSharedConfigs() + + // Populate IDP list + $.ajax({ + type: 'GET', + url: createURL('listIdps'), + dataType: 'json', + async: false, + success: function(data, textStatus, xhr) { + if (data && data.listidpsresponse && data.listidpsresponse.idp) { + var idpList = data.listidpsresponse.idp.sort(function (a, b) { + return a.orgName.localeCompare(b.orgName); + }); + g_idpList = idpList; + } + }, + error: function(xhr) { + } + }); return userValid ? { user: { @@ -315,6 +338,7 @@ g_userPublicTemplateEnabled = json.listcapabilitiesresponse.capability.userpublictemplateenabled.toString(); //convert boolean to string if it's boolean } g_allowUserExpungeRecoverVm = json.listcapabilitiesresponse.capability.allowuserexpungerecovervm; + g_allowUserExpungeRecoverVolume = json.listcapabilitiesresponse.capability.allowuserexpungerecovervolume; g_userProjectsEnabled = json.listcapabilitiesresponse.capability.allowusercreateprojects; g_cloudstackversion = json.listcapabilitiesresponse.capability.cloudstackversion; @@ -337,6 +361,7 @@ }) } }); + updateSharedConfigs(); }, error: function(xmlHTTP) { args.response.error(); @@ -377,6 +402,7 @@ g_regionsecondaryenabled = null; g_loginCmdText = null; g_allowUserViewAllDomainAccounts = null; + g_routerHealthChecksEnabled = false; // Remove any cookies var cookies = document.cookie.split(";"); diff --git a/ui/scripts/instanceWizard.js b/ui/scripts/instanceWizard.js index a6fdfbb3b952..04cceaa9d06c 100644 --- a/ui/scripts/instanceWizard.js +++ b/ui/scripts/instanceWizard.js @@ -168,11 +168,16 @@ }); } - return $.grep(selectedNetworks, function(network) { + var total = $.grep(selectedNetworks, function(network) { return $.grep(network.service, function(service) { return service.name == 'SecurityGroup'; }).length; }).length; //return total number of selected sg networks + + if (total > 0 && selectedHypervisor == "KVM") { + return -1; // vm with multiple IPs is supported in KVM + } + return total; }, // Data providers for each wizard step @@ -1284,8 +1289,10 @@ if (selectedZoneObj.networktype == "Advanced" && selectedZoneObj.securitygroupsenabled == true) { // Advanced SG-enabled zone var array2 = []; + var array3 = []; var myNetworks = $('.multi-wizard:visible form').data('my-networks'); //widget limitation: If using an advanced security group zone, get the guest networks like this - var defaultNetworkId = $('.multi-wizard:visible form').find('input[name=defaultNetwork]:checked').val(); + var defaultNetworkId = $('.multi-wizard:visible form').data('defaultNetwork'); + //var defaultNetworkId = $('.multi-wizard:visible form').find('input[name=defaultNetwork]:checked').val(); var checkedNetworkIdArray; if (typeof(myNetworks) == "object" && myNetworks.length != null) { //myNetworks is an array of string, e.g. ["203", "202"], @@ -1302,17 +1309,43 @@ array2.push(defaultNetworkId); } - //then, add other checked networks + var myNetworkIps = $('.multi-wizard:visible form').data('my-network-ips'); if (checkedNetworkIdArray.length > 0) { for (var i = 0; i < checkedNetworkIdArray.length; i++) { - if (checkedNetworkIdArray[i] != defaultNetworkId) //exclude defaultNetworkId that has been added to array2 + if (checkedNetworkIdArray[i] == defaultNetworkId) { + array2.unshift(defaultNetworkId); + + var ipToNetwork = { + networkid: defaultNetworkId + }; + if (myNetworkIps[i] != null && myNetworkIps[i].length > 0) { + $.extend(ipToNetwork, { + ip: myNetworkIps[i] + }); + } + array3.unshift(ipToNetwork); + } else { array2.push(checkedNetworkIdArray[i]); + + var ipToNetwork = { + networkid: checkedNetworkIdArray[i] + }; + if (myNetworkIps[i] != null && myNetworkIps[i].length > 0) { + $.extend(ipToNetwork, { + ip: myNetworkIps[i] + }); + } + array3.push(ipToNetwork); + } } } - $.extend(deployVmData, { - networkids : array2.join(",") - }); + for (var k = 0; k < array3.length; k++) { + deployVmData["iptonetworklist[" + k + "].networkid"] = array3[k].networkid; + if (array3[k].ip != undefined && array3[k].ip.length > 0) { + deployVmData["iptonetworklist[" + k + "].ip"] = array3[k].ip; + } + } } } else if (step6ContainerType == 'nothing-to-select') { if ("vpc" in args.context) { //from VPC tier diff --git a/ui/scripts/instances.js b/ui/scripts/instances.js index 545f7428faa8..c6fb671e1845 100644 --- a/ui/scripts/instances.js +++ b/ui/scripts/instances.js @@ -3354,6 +3354,16 @@ label: 'label.description' } }], + viewAll: { + path: 'network.securityGroups', + attachTo: 'id', + label: 'label.security.groups', + title: function(args) { + var title = _l('label.security.groups'); + + return title; + } + }, dataProvider: function(args) { // args.response.success({data: args.context.instances[0].securitygroup}); $.ajax({ diff --git a/ui/scripts/network.js b/ui/scripts/network.js index ff4c9b4d8f6d..77cce337f0cc 100644 --- a/ui/scripts/network.js +++ b/ui/scripts/network.js @@ -361,6 +361,7 @@ args.context.item.state != 'Destroyed' && args.context.item.name != 'default') { allowedActions.push('remove'); + allowedActions.push('edit'); } return allowedActions; @@ -4503,6 +4504,14 @@ var data = {}; listViewDataProvider(args, data); + if (args.context != null) { + if ("securityGroups" in args.context) { + $.extend(data, { + id: args.context.securityGroups[0].id + }); + } + } + $.ajax({ url: createURL('listSecurityGroups'), data: data, @@ -4523,7 +4532,11 @@ title: 'label.details', fields: [{ name: { - label: 'label.name' + label: 'label.name', + isEditable: true, + validation: { + required: true + } } }, { id: { @@ -5075,6 +5088,30 @@ }, actions: { + edit: { + label: 'label.edit', + action: function(args) { + var data = { + id: args.context.securityGroups[0].id + }; + if (args.data.name != args.context.securityGroups[0].name) { + $.extend(data, { + name: args.data.name + }); + }; + $.ajax({ + url: createURL('updateSecurityGroup'), + data: data, + success: function(json) { + var item = json.updatesecuritygroupresponse.securitygroup; + args.response.success({ + data: item + }); + } + }); + } + }, + remove: { label: 'label.action.delete.security.group', messages: { @@ -5792,6 +5829,66 @@ } }, + advSearchFields: { + keyword: { + label: 'label.name' + }, + domainid: { + label: 'label.domain', + select: function(args) { + if (isAdmin() || isDomainAdmin()) { + $.ajax({ + url: createURL('listDomains'), + data: { + listAll: true, + details: 'min' + }, + success: function(json) { + var array1 = [{ + id: '', + description: '' + }]; + var domains = json.listdomainsresponse.domain; + if (domains != null && domains.length > 0) { + for (var i = 0; i < domains.length; i++) { + array1.push({ + id: domains[i].id, + description: domains[i].path + }); + } + } + array1.sort(function(a, b) { + return a.description.localeCompare(b.description); + }); + args.response.success({ + data: array1 + }); + } + }); + } else { + args.response.success({ + data: null + }); + } + }, + isHidden: function(args) { + if (isAdmin() || isDomainAdmin()) + return false; + else + return true; + } + }, + account: { + label: 'Account', + isHidden: function(args) { + if (isAdmin() || isDomainAdmin()) + return false; + else + return true; + } + } + }, + dataProvider: function(args) { var data = {}; listViewDataProvider(args, data); diff --git a/ui/scripts/sharedFunctions.js b/ui/scripts/sharedFunctions.js index d3e6fe870bee..6151a6acc6ed 100644 --- a/ui/scripts/sharedFunctions.js +++ b/ui/scripts/sharedFunctions.js @@ -31,12 +31,14 @@ var g_kvmsnapshotenabled = null; var g_regionsecondaryenabled = null; var g_userPublicTemplateEnabled = "true"; var g_allowUserExpungeRecoverVm = "false"; +var g_allowUserExpungeRecoverVolume = "false"; var g_cloudstackversion = null; var g_queryAsyncJobResultInterval = 3000; var g_idpList = null; var g_appendIdpDomain = false; var g_sortKeyIsAscending = false; var g_allowUserViewAllDomainAccounts = false; +var g_routerHealthChecksEnabled = false; //keyboard keycode var keycode_Enter = 13; @@ -356,6 +358,41 @@ var addGuestNetworkDialog = { isolatedpvlanId: { label: 'label.secondary.isolated.vlan.id' }, + pvlanType: { + label: 'label.secondary.isolated.vlan.type', + isHidden: true, + select: function (args) { + var type = [{ + id: 'none', + description: _l('label.secondary.isolated.vlan.type.none') + }, { + id: 'community', + description: _l('label.secondary.isolated.vlan.type.community') + }, { + id: 'isolated', + description: _l('label.secondary.isolated.vlan.type.isolated') + }, { + id: 'promiscuous', + description: _l('label.secondary.isolated.vlan.type.promiscuous') + } + ]; + + args.response.success({ + data: type + }); + + args.$select.change(function () { + var $form = $(this).closest('form'); + var pvlanType = $(this).val(); + + if (pvlanType === 'none' || pvlanType === 'promiscuous') { + $form.find('.form-item[rel=isolatedpvlanId]').hide(); + } else if (pvlanType === 'isolated' || pvlanType === 'community') { + $form.find('.form-item[rel=isolatedpvlanId]').css('display', 'inline-block'); + } + }) + } + }, scope: { label: 'label.scope', @@ -633,12 +670,12 @@ var addGuestNetworkDialog = { $form.find('.form-item[rel=vlanId]').hide(); cloudStack.dialog.createFormField.validation.required.remove($form.find('.form-item[rel=vlanId]')); //make vlanId optional - $form.find('.form-item[rel=isolatedpvlanId]').hide(); + $form.find('.form-item[rel=pvlanType]').hide(); } else { $form.find('.form-item[rel=vlanId]').css('display', 'inline-block'); cloudStack.dialog.createFormField.validation.required.add($form.find('.form-item[rel=vlanId]')); //make vlanId required - $form.find('.form-item[rel=isolatedpvlanId]').css('display', 'inline-block'); + $form.find('.form-item[rel=pvlanType]').css('display', 'inline-block'); } return false; //break each loop } @@ -814,6 +851,9 @@ var addGuestNetworkDialog = { if (args.data.hideipaddressusage != null && args.data.hideipaddressusage) { array1.push("&hideipaddressusage=true") } + if (args.$form.find('.form-item[rel=pvlanType]').css('display') != 'none' && args.data.pvlanType != 'none') { + array1.push("&isolatedpvlantype=" + args.data.pvlanType); + } $.ajax({ url: createURL("createNetwork" + array1.join("")), @@ -1004,6 +1044,7 @@ var addL2GuestNetwork = { args.$select.change(function() { var $vlan = args.$select.closest('form').find('[rel=vlan]'); var $bypassVlanOverlapCheck = args.$select.closest('form').find('[rel=bypassVlanOverlapCheck]'); + var $pvlanType = args.$select.closest('form').find('[rel=pvlanType]'); var networkOffering = $.grep( networkOfferingObjs, function(netoffer) { return netoffer.id == args.$select.val(); @@ -1013,9 +1054,11 @@ var addL2GuestNetwork = { if (networkOffering.specifyvlan) { $vlan.css('display', 'inline-block'); $bypassVlanOverlapCheck.css('display', 'inline-block'); + $pvlanType.css('display', 'inline-block'); } else { $vlan.hide(); $bypassVlanOverlapCheck.hide(); + $pvlanType.hide(); } }); @@ -1044,6 +1087,45 @@ var addL2GuestNetwork = { isBoolean: true, isHidden: true }, + pvlanId: { + label: 'label.secondary.isolated.vlan.id', + isHidden: true + }, + pvlanType: { + label: 'label.secondary.isolated.vlan.type', + isHidden: true, + select: function (args) { + var type = [{ + id: 'none', + description: _l('label.secondary.isolated.vlan.type.none') + }, { + id: 'community', + description: _l('label.secondary.isolated.vlan.type.community') + }, { + id: 'isolated', + description: _l('label.secondary.isolated.vlan.type.isolated') + }, { + id: 'promiscuous', + description: _l('label.secondary.isolated.vlan.type.promiscuous') + } + ]; + + args.response.success({ + data: type + }); + + args.$select.change(function () { + var $form = $(this).closest('form'); + var pvlanType = $(this).val(); + + if (pvlanType === 'none' || pvlanType === 'promiscuous') { + $form.find('.form-item[rel=pvlanId]').hide(); + } else if (pvlanType === 'isolated' || pvlanType === 'community') { + $form.find('.form-item[rel=pvlanId]').css('display', 'inline-block'); + } + }) + } + }, account: { label: 'label.account', validation: { @@ -1074,6 +1156,18 @@ var addL2GuestNetwork = { }); } + if (args.$form.find('.form-item[rel=pvlanId]').css('display') != 'none') { + $.extend(dataObj, { + isolatedpvlan: args.data.pvlanId + }); + } + + if (args.$form.find('.form-item[rel=pvlanType]').css('display') != 'none' && args.data.pvlanType != 'none') { + $.extend(dataObj, { + isolatedpvlantype: args.data.pvlanType + }); + } + if (args.data.domain != null && args.data.domain.length > 0) { $.extend(dataObj, { domainid: args.data.domain diff --git a/ui/scripts/storage.js b/ui/scripts/storage.js index ab9747990ebe..a30ac60f78d9 100644 --- a/ui/scripts/storage.js +++ b/ui/scripts/storage.js @@ -213,6 +213,9 @@ zonename: { label: 'label.zone' }, + vmdisplayname: { + label: 'label.vm.display.name' + }, state: { label: 'label.metrics.state', converter: function (str) { @@ -224,6 +227,7 @@ 'Ready': 'on', 'Destroy': 'off', 'Expunging': 'off', + 'Expunged': 'off', 'Migrating': 'warning', 'UploadOp': 'warning', 'Snapshotting': 'warning', @@ -817,6 +821,33 @@ } }, + state: { + label: 'label.state', + select: function(args) { + args.response.success({ + data: [{ + name: '', + description: '' + }, { + name: 'Allocated', + description: 'state.Allocated' + }, { + name: 'Ready', + description: 'state.Ready' + }, { + name: 'Destroy', + description: 'state.Destroy' + }, { + name: 'Expunging', + description: 'state.Expunging' + }, { + name: 'Expunged', + description: 'state.Expunged' + }] + }); + } + }, + tagKey: { label: 'label.tag.key' }, @@ -1446,6 +1477,102 @@ } }, + destroy: { + label: 'label.action.destroy.volume', + createForm: { + title: 'label.action.destroy.volume', + desc: 'message.action.destroy.volume', + isWarning: true, + preFilter: function(args) { + if (!isAdmin() && ! g_allowUserExpungeRecoverVolume) { + args.$form.find('.form-item[rel=expunge]').hide(); + } + }, + fields: { + expunge: { + label: 'label.expunge', + isBoolean: true, + isChecked: false + } + } + }, + messages: { + confirm: function(args) { + return 'message.action.destroy.volume'; + }, + notification: function(args) { + return 'label.action.destroy.volume'; + } + }, + action: function(args) { + var data = { + id: args.context.volumes[0].id + }; + if (args.data.expunge == 'on') { + $.extend(data, { + expunge: true + }); + } + $.ajax({ + url: createURL("destroyVolume"), + data: data, + dataType: "json", + async: true, + success: function(json) { + var jid = json.destroyvolumeresponse.jobid; + args.response.success({ + _custom: { + jobId: jid, + getUpdatedItem: function(json) { + if ('volume' in json.queryasyncjobresultresponse.jobresult) { //destroy without expunge + var volume = json.queryasyncjobresultresponse.jobresult.volume; + if (volume.state == 'Expunged') { + return { 'toRemove': true }; + } else { + return volume; + } + } else //destroy with expunge + return { 'toRemove': true }; + }, + getActionFilter: function() { + return volumeActionfilter; + } + } + }); + } + }); + }, + notification: { + poll: pollAsyncJobResult + } + }, + + recover: { + label: 'label.action.recover.volume', + messages: { + confirm: function(args) { + return 'message.action.recover.volume'; + }, + notification: function(args) { + return 'label.action.recover.volume'; + } + }, + action: function(args) { + $.ajax({ + url: createURL("recoverVolume&id=" + args.context.volumes[0].id), + dataType: "json", + success: function(json) { + args.response.success(); + } + }); + }, + notification: { + poll: function(args) { + args.complete(); + } + } + }, + resize: { label: 'label.action.resize.volume', messages: { @@ -1575,13 +1702,13 @@ if (newDiskOffering != null && newDiskOffering.length > 0) { array1.push("&diskofferingid=" + encodeURIComponent(newDiskOffering)); } - if (selectedDiskOfferingObj.iscustomized == true) { + if (args.context.volumes[0].type == "ROOT" || selectedDiskOfferingObj.iscustomized == true) { cloudStack.addNewSizeToCommandUrlParameterArrayIfItIsNotNullAndHigherThanZero(array1, args.data.newsize); } var minIops; var maxIops - if (selectedDiskOfferingObj.iscustomizediops == true) { + if (selectedDiskOfferingObj != null && selectedDiskOfferingObj.iscustomizediops == true) { minIops = args.data.minIops; maxIops = args.data.maxIops; } @@ -1593,13 +1720,12 @@ if (maxIops != null && maxIops.length > 0) { array1.push("&maxiops=" + encodeURIComponent(maxIops)); } - //if original disk size > new disk size - if ((args.context.volumes[0].type == "ROOT") - && (args.context.volumes[0].size > (newSize * (1024 * 1024 * 1024)))) { + //if original disk size > new disk size + if (args.context.volumes[0].type == "ROOT" && + args.context.volumes[0].size > (args.data.newsize * (1024 * 1024 * 1024))) { return args.response.error('message.volume.root.shrink.disk.size'); } - $.ajax({ url: createURL("resizeVolume&id=" + args.context.volumes[0].id + array1.join("")), dataType: "json", @@ -2656,6 +2782,15 @@ var jsonObj = args.context.item; var allowedActions = []; + if ((isAdmin() || g_allowUserExpungeRecoverVolume) && jsonObj.state == 'Destroy') { + return ["recover", "remove"]; + } else if (jsonObj.state == 'Destroy') { + return []; + } + + if (jsonObj.state == 'Expunging' || jsonObj.state == 'Expunged') { + return ["remove"]; + } if (jsonObj.state == 'Destroyed' || jsonObj.state == 'Migrating' || jsonObj.state == 'Uploading') { return []; @@ -2710,7 +2845,12 @@ allowedActions.push("detachDisk"); } } else { // Disk not attached - allowedActions.push("remove"); + if (jsonObj.state == "Allocated" || jsonObj.state == "Uploaded") { + allowedActions.push("remove"); + } else { + allowedActions.push("createTemplate"); + allowedActions.push("destroy"); + } if (jsonObj.state == "Ready" && isAdmin()) { allowedActions.push("migrateToAnotherStorage"); } diff --git a/ui/scripts/system.js b/ui/scripts/system.js index 2ae2f466043c..6164a019b71b 100755 --- a/ui/scripts/system.js +++ b/ui/scripts/system.js @@ -9468,7 +9468,7 @@ url: createURL('listSystemVms'), data: data, success: function (json) { - var systemvmObjs = json.listsystemvmsresponse.systemvm; + var systemvmObjs = json.listsystemvmsresponse.systemvm || []; $(systemvmObjs).each(function(idx, item) { var controlIp = item.linklocalip; if (item.hypervisor == "VMware") { @@ -9477,32 +9477,9 @@ item.controlip = controlIp; }); - if (systemvmObjs != undefined) { - $.ajax({ - url: createURL('listHosts'), - data: { - details: 'min' - }, - success: function (json) { - var hostObjs = json.listhostsresponse.host; - for (var i = 0; i < systemvmObjs.length; i++) { - for (var k = 0; k < hostObjs.length; k++) { - if (hostObjs[k].name == systemvmObjs[i].name) { - systemvmObjs[i].agentstate = hostObjs[k].state; - break; - } - } - } - args.response.success({ - data: systemvmObjs - }); - } - }); - } else { - args.response.success({ - data:[] - }); - } + args.response.success({ + data: systemvmObjs + }); } }); }, @@ -9886,6 +9863,7 @@ listView: { id: 'routers', label: 'label.virtual.appliances', + horizontalOverflow: true, fields: { name: { label: 'label.name' @@ -9914,7 +9892,19 @@ indicator: { 'Running': 'on', 'Stopped': 'off', - 'Error': 'off' + 'Error': 'off', + 'Alert': 'warning' + } + }, + healthchecksfailed: { + converter: function (str) { + if (str) return 'Failed' + return 'Passed'; + }, + label: 'label.health.check', + indicator: { + false: 'on', + true: 'warning' } }, requiresupgrade: { @@ -9922,6 +9912,12 @@ converter: cloudStack.converters.toBooleanText } }, + preFilter: function () { + if (!g_routerHealthChecksEnabled) { + return ['healthchecksfailed'] + } + return [] + }, dataProvider: function (args) { var array1 =[]; if (args.filterBy != null) { @@ -9982,44 +9978,47 @@ routers.push(item); }); - /* - * In project view, the first listRotuers API(without projectid=-1) will return the same objects as the second listRouters API(with projectid=-1), - * because in project view, all API calls are appended with projectid=[projectID]. - * Therefore, we only call the second listRouters API(with projectid=-1) in non-project view. - */ - if (cloudStack.context && cloudStack.context.projects == null) { //non-project view - /* - * account parameter(account+domainid) and project parameter(projectid) are not allowed to be passed together to listXXXXXXX API. - * So, remove account parameter(account+domainid) from data2 - */ - if ("account" in data2) { - delete data2.account; - } - if ("domainid" in data2) { - delete data2.domainid; - } + /* + * In project view, the first listRotuers API(without projectid=-1) will return the same objects as the second listRouters API(with projectid=-1), + * because in project view, all API calls are appended with projectid=[projectID]. + * Therefore, we only call the second listRouters API(with projectid=-1) in non-project view. + */ + if (cloudStack.context && cloudStack.context.projects == null) { //non-project view + /* + * account parameter(account+domainid) and project parameter(projectid) are not allowed to be passed together to listXXXXXXX API. + * So, remove account parameter(account+domainid) from data2 + */ + if ("account" in data2) { + delete data2.account; + } + if ("domainid" in data2) { + delete data2.domainid; + } - $.ajax({ - url: createURL("listRouters&listAll=true&page=" + args.page + "&pagesize=" + pageSize + array1.join("") + "&projectid=-1"), - data: data2, - async: false, - success: function (json) { - var items = json.listroutersresponse.router ? - json.listroutersresponse.router:[]; + $.ajax({ + url: createURL("listRouters&listAll=true&page=" + args.page + "&pagesize=" + pageSize + array1.join("") + "&projectid=-1"), + data: data2, + async: false, + success: function (json) { + var items = json.listroutersresponse.router ? + json.listroutersresponse.router:[]; - $(items).map(function (index, item) { - routers.push(item); - }); + var items = json.listroutersresponse.router ? + json.listroutersresponse.router:[]; + + $(items).map(function (index, item) { + routers.push(item); + }); + } + }); } - }); - } - args.response.success({ - actionFilter: routerActionfilter, - data: $(routers).map(mapRouterType) - }); - } + args.response.success({ + actionFilter: routerActionfilter, + data: $(routers).map(mapRouterType) }); + } + }); }, detailView: { name: 'label.virtual.appliance.details', @@ -10542,6 +10541,56 @@ height: 640 } } + }, + + healthChecks: { + label: 'label.action.router.health.checks', + createForm: { + title: 'label.action.router.health.checks', + desc: 'message.action.router.health.checks', + fields: { + performfreshchecks: { + label: 'label.perform.fresh.checks', + isBoolean: true + } + } + }, + action: function (args) { + if (!g_routerHealthChecksEnabled) { + cloudStack.dialog.notice({ + message: 'Router health checks are disabled. Please enable router.health.checks.enabled to execute this action' + }) + args.response.success() + return + } + var data = { + 'routerid': args.context.routers[0].id, + 'performfreshchecks': (args.data.performfreshchecks === 'on') + }; + $.ajax({ + url: createURL('getRouterHealthCheckResults'), + dataType: 'json', + data: data, + async: true, + success: function (json) { + var healthChecks = json.getrouterhealthcheckresultsresponse.routerhealthchecks.healthchecks + var numChecks = healthChecks.length + var failedChecks = 0 + $.each(healthChecks, function(idx, check) { + if (!check.success) failedChecks = failedChecks + 1 + }) + cloudStack.dialog.notice({ + message: 'Found ' + numChecks + ' checks for router, with ' + failedChecks + ' failing checks. Please visit router > Health Checks tab to see details' + }) + args.response.success(); + } + }); + }, + messages: { + notification: function(args) { + return 'label.action.router.health.checks' + } + } } }, tabs: { @@ -10731,6 +10780,78 @@ } }); } + }, + healthCheckResults: { + title: 'label.router.health.checks', + listView: { + id: 'routerHealthCheckResults', + label: 'label.router.health.checks', + hideToolbar: true, + fields: { + checkname: { + label: 'label.router.health.check.name' + }, + checktype: { + label: 'label.router.health.check.type' + }, + success: { + label: 'label.router.health.check.success', + converter: function (args) { + if (args) { + return _l('True'); + } else { + return _l('False'); + } + }, + indicator: { + true: 'on', + false: 'off' + } + }, + lastupdated: { + label: 'label.router.health.check.last.updated' + } + }, + actions: { + details: { + label: 'label.router.health.check.details', + action: { + custom: function (args) { + cloudStack.dialog.notice({ + message: args.context.routerHealthCheckResults[0].details + }) + } + } + } + }, + dataProvider: function(args) { + if (!g_routerHealthChecksEnabled) { + cloudStack.dialog.notice({ + message: 'Router health checks are disabled. Please enable router.health.checks.enabled to get data' + }) + args.response.success({}) + return + } + if (args.page > 1) { + // Only one page is supported as it's not list command. + args.response.success({}); + return + } + + $.ajax({ + url: createURL('getRouterHealthCheckResults'), + data: { + 'routerid': args.context.routers[0].id + }, + success: function (json) { + var hcData = json.getrouterhealthcheckresultsresponse.routerhealthchecks.healthchecks + args.response.success({ + data: hcData + }); + } + }); + } + } } } } @@ -22273,6 +22394,7 @@ allowedActions.push("migrate"); allowedActions.push("diagnostics"); allowedActions.push("retrieveDiagnostics"); + allowedActions.push("healthChecks"); } } else if (jsonObj.state == 'Stopped') { allowedActions.push("start"); diff --git a/ui/scripts/ui-custom/instanceWizard.js b/ui/scripts/ui-custom/instanceWizard.js index 4fa7e3fc76c0..2450ed1b4a88 100644 --- a/ui/scripts/ui-custom/instanceWizard.js +++ b/ui/scripts/ui-custom/instanceWizard.js @@ -330,9 +330,8 @@ .attr('checked', false); } }) - .after( - $('
').addClass('name').html(options.secondary.desc) - ) + ).append( + $('
').addClass('name').html(options.secondary.desc) ).appendTo($select); } }); @@ -1517,14 +1516,29 @@ if (advSGFilter == 0) { //when total number of selected sg networks is 0, then 'Select Security Group' is skipped, go to step 6 directly showStep(6); - } else { //when total number of selected sg networks > 0 + } else if (advSGFilter > 0) { //when total number of selected sg networks > 0 if ($activeStep.find('input[type=checkbox]:checked').length > 1) { //when total number of selected networks > 1 cloudStack.dialog.notice({ message: "Can't create a vm with multiple networks one of which is Security Group enabled" }); return false; } + } else if (advSGFilter == -1) { // vm with multiple IPs is supported in KVM + var $selectNetwork = $activeStep.find('input[type=checkbox]:checked'); + var myNetworkIps = []; + $selectNetwork.each(function() { + var $specifyIp = $(this).parent().find('.specify-ip input[type=text]'); + myNetworkIps.push($specifyIp.val() == -1 ? null : $specifyIp.val()); + }); + $activeStep.closest('form').data('my-network-ips', myNetworkIps); + $selectNetwork.each(function() { + if ($(this).parent().find('input[type=radio]').is(':checked')) { + $activeStep.closest('form').data('defaultNetwork', $(this).val()); + return; + } + }) } + } } diff --git a/ui/scripts/ui/widgets/listView.js b/ui/scripts/ui/widgets/listView.js index 91578148e281..7449a61cde31 100644 --- a/ui/scripts/ui/widgets/listView.js +++ b/ui/scripts/ui/widgets/listView.js @@ -88,9 +88,9 @@ // Make sure the master checkbox is unselected if (multiSelect) { - var $listView = $instanceRow.closest('.list-view'); - $listView.find('input.multiSelectMasterCheckbox').prop('checked', false); - toggleMultiSelectActions($listView, false); + var $listView2 = $instanceRow.closest('.list-view'); + $listView2.find('input.multiSelectMasterCheckbox').prop('checked', false); + toggleMultiSelectActions($listView2, false); } var externalLinkAction = action.externalLink; @@ -168,8 +168,11 @@ } else { if (needsRefresh) { var $loading = $('
').addClass('loading-overlay'); - - $listView.prepend($loading); + if ($listView) { + $listView.prepend($loading); + } else { + $instanceRow.closest('.list-view').prepend($loading) + } } var actionArgs = { diff --git a/usage/distro/centos/SYSCONFDIR/rc.d/init.d/cloud-usage.in b/usage/distro/centos/SYSCONFDIR/rc.d/init.d/cloud-usage.in deleted file mode 100755 index cd12a1c03750..000000000000 --- a/usage/distro/centos/SYSCONFDIR/rc.d/init.d/cloud-usage.in +++ /dev/null @@ -1,138 +0,0 @@ -#!/bin/bash - -### BEGIN INIT INFO -# Provides: cloudstack-usage -# Required-Start: $network $local_fs -# Required-Stop: $network $local_fs -# Default-Start: 3 4 5 -# Default-Stop: 0 1 2 6 -# Short-Description: Start/stop Apache CloudStack Usage Monitor -# Description: This scripts Starts/Stops the Apache CloudStack Usage Monitor -## The CloudStack Usage Monitor is a part of the Apache CloudStack project and is used -## for storing usage statistics from instances. -## JSVC (Java daemonizing) is used for starting and stopping the usage monitor. -### END INIT INFO - -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you 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. - -. /etc/rc.d/init.d/functions - -SHORTNAME="cloud-usage" -PIDFILE=@PIDDIR@/"$SHORTNAME".pid -LOCKFILE=@LOCKDIR@/"$SHORTNAME" -LOGFILE=@USAGELOG@ -PROGNAME="CloudStack Usage Monitor" -CLASS="com.cloud.usage.UsageServer" -PROG="jsvc" -DAEMON="/usr/bin/jsvc" -USER=@MSUSER@ - -unset OPTIONS -[ -r @SYSCONFDIR@/default/"$SHORTNAME" ] && source @SYSCONFDIR@/default/"$SHORTNAME" - -# The first existing directory is used for JAVA_HOME (if JAVA_HOME is not defined in $DEFAULT) -JDK_DIRS="/usr/lib/jvm/java-6-openjdk /usr/lib/jvm/java-6-openjdk-i386 /usr/lib/jvm/java-6-openjdk-amd64 /usr/lib/jvm/java-6-sun /usr/lib/jvm/jre-1.6.0 /usr/lib/j2sdk1.5-sun /usr/lib/jre-openjdk" - -for jdir in $JDK_DIRS; do - if [ -r "$jdir/bin/java" -a -z "${JAVA_HOME}" ]; then - JAVA_HOME="$jdir" - fi -done -export JAVA_HOME - -SCP="@SYSTEMCLASSPATH@" -DCP="@DEPSCLASSPATH@" -UCP="@USAGECLASSPATH@" -JCP="/usr/share/java/commons-daemon.jar" - -# We need to append the JSVC daemon JAR to the classpath -# AgentShell implements the JSVC daemon methods -export CLASSPATH="$SCP:$DCP:$UCP:$JCP:@USAGESYSCONFDIR@" - -start() { - if [ -s "$PIDFILE" ] && kill -0 $(cat "$PIDFILE") >/dev/null 2>&1; then - echo "$PROGNAME apparently already running" - exit 0 - fi - - if hostname --fqdn >/dev/null 2>&1 ; then - true - else - echo "The host name does not resolve properly to an IP address. Cannot start $PROGNAME" - exit 1 - fi - - echo -n "Starting $PROGNAME" "$SHORTNAME" - - if daemon --pidfile $PIDFILE $DAEMON -cp "$CLASSPATH" -pidfile "$PIDFILE" -user "$USER" -errfile SYSLOG -Dpid=$$ $CLASS - RETVAL=$? - then - rc=0 - sleep 1 - if ! kill -0 $(cat "$PIDFILE") >/dev/null 2>&1; then - failure - rc=1 - fi - else - rc=1 - fi - - if [ $rc -eq 0 ]; then - success - else - failure - rm -f "$PIDFILE" - fi - echo -} - -stop() { - echo -n "Stopping $PROGNAME" "$SHORTNAME" - killproc -p $PIDFILE $DAEMON - if [ "$?" -eq 0 ]; then - success - else - failure - fi - rm -f "$PIDFILE" - echo -} - -case "$1" in - start) - start - ;; - stop) - stop - ;; - status) - status -p $PIDFILE $SHORTNAME - RETVAL=$? - ;; - restart | force-reload) - stop - sleep 3 - start - ;; - *) - echo "Usage: $0 {start|stop|restart|force-reload|status}" - RETVAL=3 -esac - -exit $RETVAL - diff --git a/usage/distro/fedora/SYSCONFDIR/rc.d/init.d/cloud-usage.in b/usage/distro/fedora/SYSCONFDIR/rc.d/init.d/cloud-usage.in deleted file mode 100755 index cd12a1c03750..000000000000 --- a/usage/distro/fedora/SYSCONFDIR/rc.d/init.d/cloud-usage.in +++ /dev/null @@ -1,138 +0,0 @@ -#!/bin/bash - -### BEGIN INIT INFO -# Provides: cloudstack-usage -# Required-Start: $network $local_fs -# Required-Stop: $network $local_fs -# Default-Start: 3 4 5 -# Default-Stop: 0 1 2 6 -# Short-Description: Start/stop Apache CloudStack Usage Monitor -# Description: This scripts Starts/Stops the Apache CloudStack Usage Monitor -## The CloudStack Usage Monitor is a part of the Apache CloudStack project and is used -## for storing usage statistics from instances. -## JSVC (Java daemonizing) is used for starting and stopping the usage monitor. -### END INIT INFO - -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you 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. - -. /etc/rc.d/init.d/functions - -SHORTNAME="cloud-usage" -PIDFILE=@PIDDIR@/"$SHORTNAME".pid -LOCKFILE=@LOCKDIR@/"$SHORTNAME" -LOGFILE=@USAGELOG@ -PROGNAME="CloudStack Usage Monitor" -CLASS="com.cloud.usage.UsageServer" -PROG="jsvc" -DAEMON="/usr/bin/jsvc" -USER=@MSUSER@ - -unset OPTIONS -[ -r @SYSCONFDIR@/default/"$SHORTNAME" ] && source @SYSCONFDIR@/default/"$SHORTNAME" - -# The first existing directory is used for JAVA_HOME (if JAVA_HOME is not defined in $DEFAULT) -JDK_DIRS="/usr/lib/jvm/java-6-openjdk /usr/lib/jvm/java-6-openjdk-i386 /usr/lib/jvm/java-6-openjdk-amd64 /usr/lib/jvm/java-6-sun /usr/lib/jvm/jre-1.6.0 /usr/lib/j2sdk1.5-sun /usr/lib/jre-openjdk" - -for jdir in $JDK_DIRS; do - if [ -r "$jdir/bin/java" -a -z "${JAVA_HOME}" ]; then - JAVA_HOME="$jdir" - fi -done -export JAVA_HOME - -SCP="@SYSTEMCLASSPATH@" -DCP="@DEPSCLASSPATH@" -UCP="@USAGECLASSPATH@" -JCP="/usr/share/java/commons-daemon.jar" - -# We need to append the JSVC daemon JAR to the classpath -# AgentShell implements the JSVC daemon methods -export CLASSPATH="$SCP:$DCP:$UCP:$JCP:@USAGESYSCONFDIR@" - -start() { - if [ -s "$PIDFILE" ] && kill -0 $(cat "$PIDFILE") >/dev/null 2>&1; then - echo "$PROGNAME apparently already running" - exit 0 - fi - - if hostname --fqdn >/dev/null 2>&1 ; then - true - else - echo "The host name does not resolve properly to an IP address. Cannot start $PROGNAME" - exit 1 - fi - - echo -n "Starting $PROGNAME" "$SHORTNAME" - - if daemon --pidfile $PIDFILE $DAEMON -cp "$CLASSPATH" -pidfile "$PIDFILE" -user "$USER" -errfile SYSLOG -Dpid=$$ $CLASS - RETVAL=$? - then - rc=0 - sleep 1 - if ! kill -0 $(cat "$PIDFILE") >/dev/null 2>&1; then - failure - rc=1 - fi - else - rc=1 - fi - - if [ $rc -eq 0 ]; then - success - else - failure - rm -f "$PIDFILE" - fi - echo -} - -stop() { - echo -n "Stopping $PROGNAME" "$SHORTNAME" - killproc -p $PIDFILE $DAEMON - if [ "$?" -eq 0 ]; then - success - else - failure - fi - rm -f "$PIDFILE" - echo -} - -case "$1" in - start) - start - ;; - stop) - stop - ;; - status) - status -p $PIDFILE $SHORTNAME - RETVAL=$? - ;; - restart | force-reload) - stop - sleep 3 - start - ;; - *) - echo "Usage: $0 {start|stop|restart|force-reload|status}" - RETVAL=3 -esac - -exit $RETVAL - diff --git a/usage/distro/opensuse/SYSCONFDIR/init.d/cloud-usage.in b/usage/distro/opensuse/SYSCONFDIR/init.d/cloud-usage.in deleted file mode 100755 index 985e2fe2bfbb..000000000000 --- a/usage/distro/opensuse/SYSCONFDIR/init.d/cloud-usage.in +++ /dev/null @@ -1,133 +0,0 @@ -#!/bin/bash - -### BEGIN INIT INFO -# Provides: cloudstack-usage -# Required-Start: $network $local_fs -# Required-Stop: $network $local_fs -# Default-Start: 3 4 5 -# Default-Stop: 0 1 2 6 -# Short-Description: Start/stop Apache CloudStack Usage Monitor -# Description: This scripts Starts/Stops the Apache CloudStack Usage Monitor -## The CloudStack Usage Monitor is a part of the Apache CloudStack project and is used -## for storing usage statistics from instances. -## JSVC (Java daemonizing) is used for starting and stopping the usage monitor. -### END INIT INFO - -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you 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. - -. /lib/lsb/init-functions - -SHORTNAME="cloud-usage" -PIDFILE=@PIDDIR@/"$SHORTNAME".pid -LOCKFILE=@LOCKDIR@/"$SHORTNAME" -LOGFILE=@USAGELOG@ -PROGNAME="CloudStack Usage Monitor" -CLASS="com.cloud.usage.UsageServer" -PROG="jsvc" -DAEMON="/usr/bin/jsvc" -USER=@MSUSER@ - -unset OPTIONS -[ -r @SYSCONFDIR@/default/"$SHORTNAME" ] && source @SYSCONFDIR@/default/"$SHORTNAME" - -# The first existing directory is used for JAVA_HOME (if JAVA_HOME is not defined in $DEFAULT) -JDK_DIRS="/usr/lib/jvm/java-6-openjdk /usr/lib/jvm/java-6-openjdk-i386 /usr/lib/jvm/java-6-openjdk-amd64 /usr/lib/jvm/java-6-sun /usr/lib/jvm/jre-1.6.0 /usr/lib/j2sdk1.5-sun /usr/lib/jre-openjdk" - -for jdir in $JDK_DIRS; do - if [ -r "$jdir/bin/java" -a -z "${JAVA_HOME}" ]; then - JAVA_HOME="$jdir" - fi -done -export JAVA_HOME - -SCP="@SYSTEMCLASSPATH@" -DCP="@DEPSCLASSPATH@" -UCP="@USAGECLASSPATH@" -JCP="/usr/share/java/commons-daemon.jar" - -# We need to append the JSVC daemon JAR to the classpath -# AgentShell implements the JSVC daemon methods -export CLASSPATH="$SCP:$DCP:$UCP:$JCP:@USAGESYSCONFDIR@" - -start() { - if [ -s "$PIDFILE" ] && kill -0 $(cat "$PIDFILE") >/dev/null 2>&1; then - log_daemon_msg "$PROGNAME apparently already running" - log_end_msg 0 - exit 0 - fi - - log_daemon_msg "Starting $PROGNAME" "$SHORTNAME" - if hostname --fqdn >/dev/null 2>&1 ; then - true - else - log_failure_msg "The host name does not resolve properly to an IP address. Cannot start $PROGNAME" - log_end_msg 1 - exit 1 - fi - - if start_daemon -p $PIDFILE $DAEMON -cp "$CLASSPATH" -pidfile "$PIDFILE" -user "$USER" -outfile SYSLOG -errfile SYSLOG -Dpid=$$ $CLASS - RETVAL=$? - then - rc=0 - sleep 1 - if ! kill -0 $(cat "$PIDFILE") >/dev/null 2>&1; then - log_failure_msg "$PROG failed to start" - rc=1 - fi - else - rc=1 - fi - - if [ $rc -eq 0 ]; then - log_end_msg 0 - else - log_end_msg 1 - rm -f "$PIDFILE" - fi -} - -stop() { - log_daemon_msg "Stopping $PROGNAME" "$SHORTNAME" - killproc -p $PIDFILE $DAEMON - log_end_msg $? - rm -f "$PIDFILE" -} - -case "$1" in - start) - start - ;; - stop) - stop - ;; - status) - status_of_proc -p "$PIDFILE" "$PROG" "$SHORTNAME" - RETVAL=$? - ;; - restart | force-reload) - stop - sleep 3 - start - ;; - *) - echo "Usage: $0 {start|stop|restart|force-reload|status}" - RETVAL=3 -esac - -exit $RETVAL - diff --git a/usage/distro/rhel/SYSCONFDIR/rc.d/init.d/cloud-usage.in b/usage/distro/rhel/SYSCONFDIR/rc.d/init.d/cloud-usage.in deleted file mode 100644 index cd12a1c03750..000000000000 --- a/usage/distro/rhel/SYSCONFDIR/rc.d/init.d/cloud-usage.in +++ /dev/null @@ -1,138 +0,0 @@ -#!/bin/bash - -### BEGIN INIT INFO -# Provides: cloudstack-usage -# Required-Start: $network $local_fs -# Required-Stop: $network $local_fs -# Default-Start: 3 4 5 -# Default-Stop: 0 1 2 6 -# Short-Description: Start/stop Apache CloudStack Usage Monitor -# Description: This scripts Starts/Stops the Apache CloudStack Usage Monitor -## The CloudStack Usage Monitor is a part of the Apache CloudStack project and is used -## for storing usage statistics from instances. -## JSVC (Java daemonizing) is used for starting and stopping the usage monitor. -### END INIT INFO - -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you 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. - -. /etc/rc.d/init.d/functions - -SHORTNAME="cloud-usage" -PIDFILE=@PIDDIR@/"$SHORTNAME".pid -LOCKFILE=@LOCKDIR@/"$SHORTNAME" -LOGFILE=@USAGELOG@ -PROGNAME="CloudStack Usage Monitor" -CLASS="com.cloud.usage.UsageServer" -PROG="jsvc" -DAEMON="/usr/bin/jsvc" -USER=@MSUSER@ - -unset OPTIONS -[ -r @SYSCONFDIR@/default/"$SHORTNAME" ] && source @SYSCONFDIR@/default/"$SHORTNAME" - -# The first existing directory is used for JAVA_HOME (if JAVA_HOME is not defined in $DEFAULT) -JDK_DIRS="/usr/lib/jvm/java-6-openjdk /usr/lib/jvm/java-6-openjdk-i386 /usr/lib/jvm/java-6-openjdk-amd64 /usr/lib/jvm/java-6-sun /usr/lib/jvm/jre-1.6.0 /usr/lib/j2sdk1.5-sun /usr/lib/jre-openjdk" - -for jdir in $JDK_DIRS; do - if [ -r "$jdir/bin/java" -a -z "${JAVA_HOME}" ]; then - JAVA_HOME="$jdir" - fi -done -export JAVA_HOME - -SCP="@SYSTEMCLASSPATH@" -DCP="@DEPSCLASSPATH@" -UCP="@USAGECLASSPATH@" -JCP="/usr/share/java/commons-daemon.jar" - -# We need to append the JSVC daemon JAR to the classpath -# AgentShell implements the JSVC daemon methods -export CLASSPATH="$SCP:$DCP:$UCP:$JCP:@USAGESYSCONFDIR@" - -start() { - if [ -s "$PIDFILE" ] && kill -0 $(cat "$PIDFILE") >/dev/null 2>&1; then - echo "$PROGNAME apparently already running" - exit 0 - fi - - if hostname --fqdn >/dev/null 2>&1 ; then - true - else - echo "The host name does not resolve properly to an IP address. Cannot start $PROGNAME" - exit 1 - fi - - echo -n "Starting $PROGNAME" "$SHORTNAME" - - if daemon --pidfile $PIDFILE $DAEMON -cp "$CLASSPATH" -pidfile "$PIDFILE" -user "$USER" -errfile SYSLOG -Dpid=$$ $CLASS - RETVAL=$? - then - rc=0 - sleep 1 - if ! kill -0 $(cat "$PIDFILE") >/dev/null 2>&1; then - failure - rc=1 - fi - else - rc=1 - fi - - if [ $rc -eq 0 ]; then - success - else - failure - rm -f "$PIDFILE" - fi - echo -} - -stop() { - echo -n "Stopping $PROGNAME" "$SHORTNAME" - killproc -p $PIDFILE $DAEMON - if [ "$?" -eq 0 ]; then - success - else - failure - fi - rm -f "$PIDFILE" - echo -} - -case "$1" in - start) - start - ;; - stop) - stop - ;; - status) - status -p $PIDFILE $SHORTNAME - RETVAL=$? - ;; - restart | force-reload) - stop - sleep 3 - start - ;; - *) - echo "Usage: $0 {start|stop|restart|force-reload|status}" - RETVAL=3 -esac - -exit $RETVAL - diff --git a/usage/distro/sles/SYSCONFDIR/init.d/cloud-usage.in b/usage/distro/sles/SYSCONFDIR/init.d/cloud-usage.in deleted file mode 100755 index 985e2fe2bfbb..000000000000 --- a/usage/distro/sles/SYSCONFDIR/init.d/cloud-usage.in +++ /dev/null @@ -1,133 +0,0 @@ -#!/bin/bash - -### BEGIN INIT INFO -# Provides: cloudstack-usage -# Required-Start: $network $local_fs -# Required-Stop: $network $local_fs -# Default-Start: 3 4 5 -# Default-Stop: 0 1 2 6 -# Short-Description: Start/stop Apache CloudStack Usage Monitor -# Description: This scripts Starts/Stops the Apache CloudStack Usage Monitor -## The CloudStack Usage Monitor is a part of the Apache CloudStack project and is used -## for storing usage statistics from instances. -## JSVC (Java daemonizing) is used for starting and stopping the usage monitor. -### END INIT INFO - -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you 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. - -. /lib/lsb/init-functions - -SHORTNAME="cloud-usage" -PIDFILE=@PIDDIR@/"$SHORTNAME".pid -LOCKFILE=@LOCKDIR@/"$SHORTNAME" -LOGFILE=@USAGELOG@ -PROGNAME="CloudStack Usage Monitor" -CLASS="com.cloud.usage.UsageServer" -PROG="jsvc" -DAEMON="/usr/bin/jsvc" -USER=@MSUSER@ - -unset OPTIONS -[ -r @SYSCONFDIR@/default/"$SHORTNAME" ] && source @SYSCONFDIR@/default/"$SHORTNAME" - -# The first existing directory is used for JAVA_HOME (if JAVA_HOME is not defined in $DEFAULT) -JDK_DIRS="/usr/lib/jvm/java-6-openjdk /usr/lib/jvm/java-6-openjdk-i386 /usr/lib/jvm/java-6-openjdk-amd64 /usr/lib/jvm/java-6-sun /usr/lib/jvm/jre-1.6.0 /usr/lib/j2sdk1.5-sun /usr/lib/jre-openjdk" - -for jdir in $JDK_DIRS; do - if [ -r "$jdir/bin/java" -a -z "${JAVA_HOME}" ]; then - JAVA_HOME="$jdir" - fi -done -export JAVA_HOME - -SCP="@SYSTEMCLASSPATH@" -DCP="@DEPSCLASSPATH@" -UCP="@USAGECLASSPATH@" -JCP="/usr/share/java/commons-daemon.jar" - -# We need to append the JSVC daemon JAR to the classpath -# AgentShell implements the JSVC daemon methods -export CLASSPATH="$SCP:$DCP:$UCP:$JCP:@USAGESYSCONFDIR@" - -start() { - if [ -s "$PIDFILE" ] && kill -0 $(cat "$PIDFILE") >/dev/null 2>&1; then - log_daemon_msg "$PROGNAME apparently already running" - log_end_msg 0 - exit 0 - fi - - log_daemon_msg "Starting $PROGNAME" "$SHORTNAME" - if hostname --fqdn >/dev/null 2>&1 ; then - true - else - log_failure_msg "The host name does not resolve properly to an IP address. Cannot start $PROGNAME" - log_end_msg 1 - exit 1 - fi - - if start_daemon -p $PIDFILE $DAEMON -cp "$CLASSPATH" -pidfile "$PIDFILE" -user "$USER" -outfile SYSLOG -errfile SYSLOG -Dpid=$$ $CLASS - RETVAL=$? - then - rc=0 - sleep 1 - if ! kill -0 $(cat "$PIDFILE") >/dev/null 2>&1; then - log_failure_msg "$PROG failed to start" - rc=1 - fi - else - rc=1 - fi - - if [ $rc -eq 0 ]; then - log_end_msg 0 - else - log_end_msg 1 - rm -f "$PIDFILE" - fi -} - -stop() { - log_daemon_msg "Stopping $PROGNAME" "$SHORTNAME" - killproc -p $PIDFILE $DAEMON - log_end_msg $? - rm -f "$PIDFILE" -} - -case "$1" in - start) - start - ;; - stop) - stop - ;; - status) - status_of_proc -p "$PIDFILE" "$PROG" "$SHORTNAME" - RETVAL=$? - ;; - restart | force-reload) - stop - sleep 3 - start - ;; - *) - echo "Usage: $0 {start|stop|restart|force-reload|status}" - RETVAL=3 -esac - -exit $RETVAL - diff --git a/usage/distro/ubuntu/SYSCONFDIR/init.d/cloud-usage.in b/usage/distro/ubuntu/SYSCONFDIR/init.d/cloud-usage.in deleted file mode 100755 index 985e2fe2bfbb..000000000000 --- a/usage/distro/ubuntu/SYSCONFDIR/init.d/cloud-usage.in +++ /dev/null @@ -1,133 +0,0 @@ -#!/bin/bash - -### BEGIN INIT INFO -# Provides: cloudstack-usage -# Required-Start: $network $local_fs -# Required-Stop: $network $local_fs -# Default-Start: 3 4 5 -# Default-Stop: 0 1 2 6 -# Short-Description: Start/stop Apache CloudStack Usage Monitor -# Description: This scripts Starts/Stops the Apache CloudStack Usage Monitor -## The CloudStack Usage Monitor is a part of the Apache CloudStack project and is used -## for storing usage statistics from instances. -## JSVC (Java daemonizing) is used for starting and stopping the usage monitor. -### END INIT INFO - -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you 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. - -. /lib/lsb/init-functions - -SHORTNAME="cloud-usage" -PIDFILE=@PIDDIR@/"$SHORTNAME".pid -LOCKFILE=@LOCKDIR@/"$SHORTNAME" -LOGFILE=@USAGELOG@ -PROGNAME="CloudStack Usage Monitor" -CLASS="com.cloud.usage.UsageServer" -PROG="jsvc" -DAEMON="/usr/bin/jsvc" -USER=@MSUSER@ - -unset OPTIONS -[ -r @SYSCONFDIR@/default/"$SHORTNAME" ] && source @SYSCONFDIR@/default/"$SHORTNAME" - -# The first existing directory is used for JAVA_HOME (if JAVA_HOME is not defined in $DEFAULT) -JDK_DIRS="/usr/lib/jvm/java-6-openjdk /usr/lib/jvm/java-6-openjdk-i386 /usr/lib/jvm/java-6-openjdk-amd64 /usr/lib/jvm/java-6-sun /usr/lib/jvm/jre-1.6.0 /usr/lib/j2sdk1.5-sun /usr/lib/jre-openjdk" - -for jdir in $JDK_DIRS; do - if [ -r "$jdir/bin/java" -a -z "${JAVA_HOME}" ]; then - JAVA_HOME="$jdir" - fi -done -export JAVA_HOME - -SCP="@SYSTEMCLASSPATH@" -DCP="@DEPSCLASSPATH@" -UCP="@USAGECLASSPATH@" -JCP="/usr/share/java/commons-daemon.jar" - -# We need to append the JSVC daemon JAR to the classpath -# AgentShell implements the JSVC daemon methods -export CLASSPATH="$SCP:$DCP:$UCP:$JCP:@USAGESYSCONFDIR@" - -start() { - if [ -s "$PIDFILE" ] && kill -0 $(cat "$PIDFILE") >/dev/null 2>&1; then - log_daemon_msg "$PROGNAME apparently already running" - log_end_msg 0 - exit 0 - fi - - log_daemon_msg "Starting $PROGNAME" "$SHORTNAME" - if hostname --fqdn >/dev/null 2>&1 ; then - true - else - log_failure_msg "The host name does not resolve properly to an IP address. Cannot start $PROGNAME" - log_end_msg 1 - exit 1 - fi - - if start_daemon -p $PIDFILE $DAEMON -cp "$CLASSPATH" -pidfile "$PIDFILE" -user "$USER" -outfile SYSLOG -errfile SYSLOG -Dpid=$$ $CLASS - RETVAL=$? - then - rc=0 - sleep 1 - if ! kill -0 $(cat "$PIDFILE") >/dev/null 2>&1; then - log_failure_msg "$PROG failed to start" - rc=1 - fi - else - rc=1 - fi - - if [ $rc -eq 0 ]; then - log_end_msg 0 - else - log_end_msg 1 - rm -f "$PIDFILE" - fi -} - -stop() { - log_daemon_msg "Stopping $PROGNAME" "$SHORTNAME" - killproc -p $PIDFILE $DAEMON - log_end_msg $? - rm -f "$PIDFILE" -} - -case "$1" in - start) - start - ;; - stop) - stop - ;; - status) - status_of_proc -p "$PIDFILE" "$PROG" "$SHORTNAME" - RETVAL=$? - ;; - restart | force-reload) - stop - sleep 3 - start - ;; - *) - echo "Usage: $0 {start|stop|restart|force-reload|status}" - RETVAL=3 -esac - -exit $RETVAL - diff --git a/usage/pom.xml b/usage/pom.xml index 6858f86c9d5d..b985761675d8 100644 --- a/usage/pom.xml +++ b/usage/pom.xml @@ -49,6 +49,11 @@ cloud-framework-quota ${project.version} + + org.apache.cloudstack + cloud-framework-db + ${project.version} + commons-daemon commons-daemon diff --git a/usage/src/test/resources/cloud1.xml b/usage/src/test/resources/cloud1.xml index 2b139fd3c40d..773283ac5c55 100644 --- a/usage/src/test/resources/cloud1.xml +++ b/usage/src/test/resources/cloud1.xml @@ -9,16 +9,20 @@ governing permissions and limitations under the License. --> - + - + - - + + - - - + + + - + + + + + diff --git a/usage/src/test/resources/cloud2.xml b/usage/src/test/resources/cloud2.xml index 2b139fd3c40d..099dde5737c8 100644 --- a/usage/src/test/resources/cloud2.xml +++ b/usage/src/test/resources/cloud2.xml @@ -9,16 +9,20 @@ governing permissions and limitations under the License. --> - + - + - - + + - - - + + + - + + + + + diff --git a/usage/src/test/resources/cloud3.xml b/usage/src/test/resources/cloud3.xml index a4687ff9a9c9..830802764b0b 100644 --- a/usage/src/test/resources/cloud3.xml +++ b/usage/src/test/resources/cloud3.xml @@ -9,5 +9,6 @@ governing permissions and limitations under the License. --> - + + diff --git a/usage/src/test/resources/cloud_usage1.xml b/usage/src/test/resources/cloud_usage1.xml index 20528bf2aab0..6219a065efbd 100644 --- a/usage/src/test/resources/cloud_usage1.xml +++ b/usage/src/test/resources/cloud_usage1.xml @@ -9,18 +9,18 @@ governing permissions and limitations under the License. --> - - + + - - + + - + - - + + - - - + + + diff --git a/usage/src/test/resources/cloud_usage2.xml b/usage/src/test/resources/cloud_usage2.xml index 7cc3991ed1a7..2dd3734668a3 100644 --- a/usage/src/test/resources/cloud_usage2.xml +++ b/usage/src/test/resources/cloud_usage2.xml @@ -9,35 +9,37 @@ governing permissions and limitations under the License. --> - - - + + + - - - - + + - + + + - - - - - - + - - - - - - - - + + + + + + - - - - + + + + + + + + + + + + + diff --git a/usage/src/test/resources/cloud_usage3.xml b/usage/src/test/resources/cloud_usage3.xml index d8922e1f01e8..8dea51607753 100644 --- a/usage/src/test/resources/cloud_usage3.xml +++ b/usage/src/test/resources/cloud_usage3.xml @@ -9,5 +9,5 @@ governing permissions and limitations under the License. --> - + diff --git a/utils/pom.xml b/utils/pom.xml index 0add026894fd..046e14a77193 100755 --- a/utils/pom.xml +++ b/utils/pom.xml @@ -111,6 +111,11 @@ commons-configuration commons-configuration + + javax.annotation + javax.annotation-api + ${cs.javax.annotation.version} + javax.servlet javax.servlet-api diff --git a/utils/src/main/java/com/cloud/utils/Profiler.java b/utils/src/main/java/com/cloud/utils/Profiler.java index addee2db200b..e99141ea11c9 100644 --- a/utils/src/main/java/com/cloud/utils/Profiler.java +++ b/utils/src/main/java/com/cloud/utils/Profiler.java @@ -37,6 +37,14 @@ public long stop() { return stopTickNanoSeconds; } + public void setStartTick(long value) { + this.startTickNanoSeconds = value; + } + + public void setStopTick(long value) { + this.stopTickNanoSeconds = value; + } + /** * 1 millisecond = 1e+6 nanoseconds * 1 second = 1000 milliseconds = 1e+9 nanoseconds diff --git a/utils/src/main/java/com/cloud/utils/ReflectUtil.java b/utils/src/main/java/com/cloud/utils/ReflectUtil.java index 1d31093e0c86..4cf09bb238cc 100644 --- a/utils/src/main/java/com/cloud/utils/ReflectUtil.java +++ b/utils/src/main/java/com/cloud/utils/ReflectUtil.java @@ -29,8 +29,6 @@ import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; -import java.net.URL; -import java.net.URLClassLoader; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; @@ -39,14 +37,13 @@ import org.apache.log4j.Logger; import org.reflections.Reflections; -import org.reflections.util.ConfigurationBuilder; -import org.reflections.util.ClasspathHelper; import org.reflections.scanners.SubTypesScanner; import org.reflections.scanners.TypeAnnotationsScanner; - -import com.google.common.collect.ImmutableSet; +import org.reflections.util.ClasspathHelper; +import org.reflections.util.ConfigurationBuilder; import com.cloud.utils.exception.CloudRuntimeException; +import com.google.common.collect.ImmutableSet; public class ReflectUtil { @@ -212,23 +209,4 @@ public static String getEntityName(Class clz){ } } - /** - * Finds and returns class loader based on the provided module/jar name - * @param name - * @return returns ClassLoader - */ - public static ClassLoader getClassLoaderForName(final String name) { - final URL[] urls = ((URLClassLoader) (Thread.currentThread().getContextClassLoader())).getURLs(); - final List searchUrls = new ArrayList<>(); - for (final URL url: urls) { - if (url.toString().contains(name)) { - if (s_logger.isDebugEnabled()) { - s_logger.debug("Search URL: " + url.toString()); - } - searchUrls.add(url); - } - } - return new URLClassLoader(searchUrls.toArray(new URL[searchUrls.size()])); - } - } diff --git a/utils/src/main/java/com/cloud/utils/UriUtils.java b/utils/src/main/java/com/cloud/utils/UriUtils.java index 14dce40d8c21..3796296dea7d 100644 --- a/utils/src/main/java/com/cloud/utils/UriUtils.java +++ b/utils/src/main/java/com/cloud/utils/UriUtils.java @@ -624,4 +624,15 @@ public static boolean checkVlanUriOverlap(final String vlanRange1, final String } return !Collections.disjoint(vlans1, vlans2); } + + public static List expandPvlanUri(String pvlanRange) { + final List expandedVlans = new ArrayList<>(); + if (Strings.isNullOrEmpty(pvlanRange)) { + return expandedVlans; + } + String[] parts = pvlanRange.split("-i"); + expandedVlans.add(Integer.parseInt(parts[0])); + expandedVlans.add(Integer.parseInt(parts[1])); + return expandedVlans; + } } diff --git a/utils/src/main/java/com/cloud/utils/exception/CSExceptionErrorCode.java b/utils/src/main/java/com/cloud/utils/exception/CSExceptionErrorCode.java index 62af14e60330..34fe46ddbdf5 100644 --- a/utils/src/main/java/com/cloud/utils/exception/CSExceptionErrorCode.java +++ b/utils/src/main/java/com/cloud/utils/exception/CSExceptionErrorCode.java @@ -41,6 +41,7 @@ public class CSExceptionErrorCode { ExceptionErrorCodeMap.put("com.cloud.utils.exception.CloudRuntimeException", 4250); ExceptionErrorCodeMap.put("com.cloud.utils.exception.ExecutionException", 4260); ExceptionErrorCodeMap.put("com.cloud.utils.exception.HypervisorVersionChangedException", 4265); + ExceptionErrorCodeMap.put("com.cloud.utils.exception.NioConnectionException", 4270); ExceptionErrorCodeMap.put("com.cloud.exception.CloudException", 4275); ExceptionErrorCodeMap.put("com.cloud.exception.AccountLimitException", 4280); ExceptionErrorCodeMap.put("com.cloud.exception.AgentUnavailableException", 4285); diff --git a/utils/src/main/java/com/cloud/utils/nio/Link.java b/utils/src/main/java/com/cloud/utils/nio/Link.java index 9bc6abb985b6..5040c8306c04 100644 --- a/utils/src/main/java/com/cloud/utils/nio/Link.java +++ b/utils/src/main/java/com/cloud/utils/nio/Link.java @@ -608,8 +608,8 @@ public static boolean doHandshake(final SocketChannel socketChannel, final SSLEn while (handshakeStatus != SSLEngineResult.HandshakeStatus.FINISHED && handshakeStatus != SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING) { final long timeTaken = System.currentTimeMillis() - startTimeMills; - if (timeTaken > 15000L) { - s_logger.warn("SSL Handshake has taken more than 15s to connect to: " + socketChannel.getRemoteAddress() + + if (timeTaken > 30000L) { + s_logger.warn("SSL Handshake has taken more than 30s to connect to: " + socketChannel.getRemoteAddress() + ". Please investigate this connection."); return false; } diff --git a/utils/src/main/java/org/apache/cloudstack/utils/security/ChecksumValue.java b/utils/src/main/java/org/apache/cloudstack/utils/security/ChecksumValue.java index e47bf393db28..e7a7be46bad9 100644 --- a/utils/src/main/java/org/apache/cloudstack/utils/security/ChecksumValue.java +++ b/utils/src/main/java/org/apache/cloudstack/utils/security/ChecksumValue.java @@ -80,7 +80,8 @@ private static String algorithmFromDigest(String digest) { if (s == 0 && e > s+1) { // we have an algorithm name of at least 1 char return digest.substring(s+1,e); } // else if no algoritm + return "MD5"; } // or if no digest at all - return "MD5"; + return "SHA-512"; } } diff --git a/utils/src/test/java/com/cloud/utils/TestProfiler.java b/utils/src/test/java/com/cloud/utils/TestProfiler.java index 0e681751330b..335dff5a509f 100644 --- a/utils/src/test/java/com/cloud/utils/TestProfiler.java +++ b/utils/src/test/java/com/cloud/utils/TestProfiler.java @@ -23,14 +23,16 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PowerMockIgnore; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; import com.cloud.utils.testcase.Log4jEnabledTestCase; @RunWith(PowerMockRunner.class) -@PrepareForTest({Profiler.class}) +@PowerMockIgnore({ "javax.management.*", "com.sun.org.apache.xerces.*", "javax.xml.*", + "org.xml.*", "org.w3c.dom.*", "com.sun.org.apache.xalan.*", "javax.activation.*" }) +@PrepareForTest(Profiler.class) public class TestProfiler extends Log4jEnabledTestCase { private static final long SLEEP_TIME_NANO = 1000000000L; @@ -39,8 +41,6 @@ public class TestProfiler extends Log4jEnabledTestCase { @Before public void setUp() { pf = new Profiler(); - PowerMockito.mockStatic(System.class); - PowerMockito.when(System.nanoTime()).thenReturn(0L, SLEEP_TIME_NANO); } @Test @@ -50,7 +50,9 @@ public void testProfilerInMillis() { //When pf.start(); + pf.setStartTick(0); // mock start tick pf.stop(); + pf.setStopTick(SLEEP_TIME_NANO); // mock stop tick //Then Assert.assertTrue(pf.getDurationInMillis() == sleepTimeMillis); @@ -63,7 +65,9 @@ public void testProfilerInNano() { //When pf.start(); + pf.setStartTick(0); // mock start tick pf.stop(); + pf.setStopTick(SLEEP_TIME_NANO); // mock stop tick //Then Assert.assertTrue(pf.getDuration() == sleepTimeNano); @@ -76,6 +80,7 @@ public void testProfilerNoStart() { //When pf.stop(); + pf.setStopTick(SLEEP_TIME_NANO); // mock stop tick //Then Assert.assertTrue(pf.getDurationInMillis() == expectedAnswer); diff --git a/utils/src/test/java/com/cloud/utils/UriUtilsParametrizedTest.java b/utils/src/test/java/com/cloud/utils/UriUtilsParametrizedTest.java index 398eee675268..9b29c86d4bb0 100644 --- a/utils/src/test/java/com/cloud/utils/UriUtilsParametrizedTest.java +++ b/utils/src/test/java/com/cloud/utils/UriUtilsParametrizedTest.java @@ -23,17 +23,16 @@ import java.util.LinkedList; import java.util.Set; +import org.apache.cloudstack.utils.imagestore.ImageStoreUtil; import org.hamcrest.Matchers; +import org.hamcrest.core.IsInstanceOf; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; -import org.mockito.internal.matchers.InstanceOf; import com.google.common.collect.ImmutableSet; -import org.apache.cloudstack.utils.imagestore.ImageStoreUtil; - @RunWith(Parameterized.class) public class UriUtilsParametrizedTest { @FunctionalInterface @@ -79,7 +78,7 @@ private void assertThrows(ThrowingBlock consumer, Class consumer.execute(); Assert.fail("Expected " + exceptionClass.getName()); } catch(Exception e) { - Assert.assertThat(e, new InstanceOf(exceptionClass)); + Assert.assertThat(e, new IsInstanceOf(exceptionClass)); } } diff --git a/utils/src/test/java/com/cloud/utils/rest/HttpRequestMatcher.java b/utils/src/test/java/com/cloud/utils/rest/HttpRequestMatcher.java index effec792bcff..cf20a8764841 100644 --- a/utils/src/test/java/com/cloud/utils/rest/HttpRequestMatcher.java +++ b/utils/src/test/java/com/cloud/utils/rest/HttpRequestMatcher.java @@ -34,7 +34,7 @@ import org.hamcrest.SelfDescribing; import org.mockito.ArgumentMatcher; -public class HttpRequestMatcher extends ArgumentMatcher { +public class HttpRequestMatcher implements ArgumentMatcher { private final HttpRequest wanted; public HttpRequestMatcher(final HttpRequest wanted) { @@ -46,7 +46,7 @@ public static HttpRequest eq(final HttpRequest request) { } @Override - public boolean matches(final Object actual) { + public boolean matches(HttpRequest actual) { if (actual instanceof HttpUriRequest) { final HttpUriRequest converted = (HttpUriRequest) actual; return checkMethod(converted) && checkUri(converted) && checkPayload(converted); @@ -99,11 +99,6 @@ private static boolean equalsString(final String a, final String b) { return a == b || a != null && a.equals(b); } - @Override - public void describeTo(final Description description) { - description.appendText(describe(wanted)); - } - public String describe(final HttpRequest object) { final StringBuilder sb = new StringBuilder(); if (object instanceof HttpUriRequest) { @@ -137,5 +132,4 @@ public void describeTo(final Description description) { public boolean typeMatches(final Object object) { return wanted != null && object != null && object.getClass() == wanted.getClass(); } - } diff --git a/utils/src/test/java/com/cloud/utils/rest/HttpUriRequestMethodMatcher.java b/utils/src/test/java/com/cloud/utils/rest/HttpUriRequestMethodMatcher.java index f2d091f5f653..ed4bd648ab16 100644 --- a/utils/src/test/java/com/cloud/utils/rest/HttpUriRequestMethodMatcher.java +++ b/utils/src/test/java/com/cloud/utils/rest/HttpUriRequestMethodMatcher.java @@ -20,7 +20,7 @@ package com.cloud.utils.rest; import static org.hamcrest.Matchers.equalTo; -import static org.mockito.Matchers.argThat; +import static org.mockito.hamcrest.MockitoHamcrest.argThat; import org.apache.http.client.methods.HttpUriRequest; import org.hamcrest.FeatureMatcher; @@ -40,5 +40,4 @@ public HttpUriRequestMethodMatcher(final Matcher subMatcher, fin protected String featureValueOf(final HttpUriRequest actual) { return actual.getMethod(); } - } diff --git a/utils/src/test/java/com/cloud/utils/rest/HttpUriRequestPathMatcher.java b/utils/src/test/java/com/cloud/utils/rest/HttpUriRequestPathMatcher.java index 948e9f6b424d..ce3ae1b44247 100644 --- a/utils/src/test/java/com/cloud/utils/rest/HttpUriRequestPathMatcher.java +++ b/utils/src/test/java/com/cloud/utils/rest/HttpUriRequestPathMatcher.java @@ -20,7 +20,7 @@ package com.cloud.utils.rest; import static org.hamcrest.Matchers.equalTo; -import static org.mockito.Matchers.argThat; +import static org.mockito.hamcrest.MockitoHamcrest.argThat; import org.apache.http.client.methods.HttpUriRequest; import org.hamcrest.FeatureMatcher; diff --git a/utils/src/test/java/com/cloud/utils/rest/HttpUriRequestPayloadMatcher.java b/utils/src/test/java/com/cloud/utils/rest/HttpUriRequestPayloadMatcher.java index 724f495ab970..a5701b6dd856 100644 --- a/utils/src/test/java/com/cloud/utils/rest/HttpUriRequestPayloadMatcher.java +++ b/utils/src/test/java/com/cloud/utils/rest/HttpUriRequestPayloadMatcher.java @@ -20,7 +20,7 @@ package com.cloud.utils.rest; import static org.hamcrest.Matchers.equalTo; -import static org.mockito.Matchers.argThat; +import static org.mockito.hamcrest.MockitoHamcrest.argThat; import java.io.IOException; diff --git a/utils/src/test/java/com/cloud/utils/rest/HttpUriRequestQueryMatcher.java b/utils/src/test/java/com/cloud/utils/rest/HttpUriRequestQueryMatcher.java index e73641bf865f..3f7e35eb1352 100644 --- a/utils/src/test/java/com/cloud/utils/rest/HttpUriRequestQueryMatcher.java +++ b/utils/src/test/java/com/cloud/utils/rest/HttpUriRequestQueryMatcher.java @@ -21,7 +21,7 @@ import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.equalTo; -import static org.mockito.Matchers.argThat; +import static org.mockito.hamcrest.MockitoHamcrest.argThat; import org.apache.http.client.methods.HttpUriRequest; import org.hamcrest.FeatureMatcher; diff --git a/utils/src/test/java/com/cloud/utils/ssh/SshHelperTest.java b/utils/src/test/java/com/cloud/utils/ssh/SshHelperTest.java index 18e7171c925f..37bd089dfc5e 100644 --- a/utils/src/test/java/com/cloud/utils/ssh/SshHelperTest.java +++ b/utils/src/test/java/com/cloud/utils/ssh/SshHelperTest.java @@ -27,6 +27,7 @@ import org.junit.runner.RunWith; import org.mockito.Mockito; import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PowerMockIgnore; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; @@ -35,6 +36,8 @@ import com.trilead.ssh2.Session; @PrepareForTest({ Thread.class, SshHelper.class }) +@PowerMockIgnore({ "javax.management.*", "com.sun.org.apache.xerces.*", "javax.xml.*", + "org.xml.*", "org.w3c.dom.*", "com.sun.org.apache.xalan.*", "javax.activation.*" }) @RunWith(PowerMockRunner.class) public class SshHelperTest { @@ -49,7 +52,7 @@ public void canEndTheSshConnectionTest() throws Exception { SshHelper.canEndTheSshConnection(1, mockedSession, 0); - PowerMockito.verifyStatic(); + PowerMockito.verifyStatic(SshHelper.class); SshHelper.isChannelConditionEof(Mockito.anyInt()); SshHelper.throwSshExceptionIfConditionsTimeout(Mockito.anyInt()); @@ -144,8 +147,5 @@ public void openConnectionSessionTest() throws IOException, InterruptedException SshHelper.openConnectionSession(conn); Mockito.verify(conn).openSession(); - - PowerMockito.verifyStatic(); - } } diff --git a/vmware-base/pom.xml b/vmware-base/pom.xml index eb1fe4ff606e..38c63cdffa46 100644 --- a/vmware-base/pom.xml +++ b/vmware-base/pom.xml @@ -69,5 +69,11 @@ wsdl4j wsdl4j + + com.sun.xml.ws + jaxws-ri + ${cs.jaxws.version} + pom + diff --git a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/ClusterMO.java b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/ClusterMO.java index ce9e9816280f..4b3786646220 100644 --- a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/ClusterMO.java +++ b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/ClusterMO.java @@ -216,6 +216,19 @@ public ManagedObjectReference getHyperHostCluster() throws Exception { return _mor; } + @Override + public synchronized List listVmsOnHyperHost(String vmName) throws Exception { + List vms = new ArrayList<>(); + List hosts = _context.getVimClient().getDynamicProperty(_mor, "host"); + if (hosts != null && hosts.size() > 0) { + for (ManagedObjectReference morHost : hosts) { + HostMO hostMo = new HostMO(_context, morHost); + vms.addAll(hostMo.listVmsOnHyperHost(vmName)); + } + } + return vms; + } + @Override public VirtualMachineMO findVmOnHyperHost(String name) throws Exception { diff --git a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/DistributedVirtualSwitchMO.java b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/DistributedVirtualSwitchMO.java index fbb4265bcfb9..40a0a64650a4 100644 --- a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/DistributedVirtualSwitchMO.java +++ b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/DistributedVirtualSwitchMO.java @@ -24,6 +24,8 @@ import org.apache.log4j.Logger; +import com.cloud.hypervisor.vmware.util.VmwareContext; +import com.cloud.utils.Pair; import com.vmware.vim25.DVPortgroupConfigSpec; import com.vmware.vim25.DVSConfigInfo; import com.vmware.vim25.ManagedObjectReference; @@ -32,8 +34,6 @@ import com.vmware.vim25.VMwareDVSConfigSpec; import com.vmware.vim25.VMwareDVSPvlanMapEntry; -import com.cloud.hypervisor.vmware.util.VmwareContext; - public class DistributedVirtualSwitchMO extends BaseMO { @SuppressWarnings("unused") private static final Logger s_logger = Logger.getLogger(DistributedVirtualSwitchMO.class); @@ -169,4 +169,28 @@ public Map retrieveVlanPvlan(int vlanid return result; } + public Pair retrieveVlanFromPvlan(int pvlanid, ManagedObjectReference dvSwitchMor) throws Exception { + assert (dvSwitchMor != null); + + Pair result = null; + + VMwareDVSConfigInfo configinfo = (VMwareDVSConfigInfo)_context.getVimClient().getDynamicProperty(dvSwitchMor, "config"); + List pvlanConfig = null; + pvlanConfig = configinfo.getPvlanConfig(); + + if (null == pvlanConfig || 0 == pvlanConfig.size()) { + return result; + } + + // Iterate through the pvlanMapList and check if the specified pvlan id exist. If it does, set the fields in result accordingly. + for (VMwareDVSPvlanMapEntry mapEntry : pvlanConfig) { + int entryVlanid = mapEntry.getPrimaryVlanId(); + int entryPvlanid = mapEntry.getSecondaryVlanId(); + if (pvlanid == entryPvlanid) { + result = new Pair<>(entryVlanid, HypervisorHostHelper.PvlanType.valueOf(mapEntry.getPvlanType())); + break; + } + } + return result; + } } diff --git a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/HostMO.java b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/HostMO.java index cc50b3d5bc13..5aab3a25ce28 100644 --- a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/HostMO.java +++ b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/HostMO.java @@ -496,6 +496,18 @@ public String getHostName() throws Exception { return (String)_context.getVimClient().getDynamicProperty(_mor, "name"); } + @Override + public synchronized List listVmsOnHyperHost(String vmName) throws Exception { + List vms = new ArrayList<>(); + if (vmName != null && !vmName.isEmpty()) { + vms.add(findVmOnHyperHost(vmName)); + } else { + loadVmCache(); + vms.addAll(_vmCache.values()); + } + return vms; + } + @Override public synchronized VirtualMachineMO findVmOnHyperHost(String vmName) throws Exception { if (s_logger.isDebugEnabled()) diff --git a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/HypervisorHostHelper.java b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/HypervisorHostHelper.java index 2eaa55a5768d..7826bb136a81 100644 --- a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/HypervisorHostHelper.java +++ b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/HypervisorHostHelper.java @@ -38,6 +38,7 @@ import javax.xml.transform.stream.StreamResult; import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService; +import org.apache.commons.collections.MapUtils; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import org.w3c.dom.Document; @@ -579,8 +580,9 @@ public static Pair prepareNetwork(String physica // First, if both vlan id and pvlan id are provided, we need to // reconfigure the DVSwitch to have a tuple of // type isolated. + String pvlanType = MapUtils.isNotEmpty(details) ? details.get(NetworkOffering.Detail.pvlanType) : null; if (vid != null && spvlanid != null) { - setupPVlanPair(dvSwitchMo, morDvSwitch, vid, spvlanid); + setupPVlanPair(dvSwitchMo, morDvSwitch, vid, spvlanid, pvlanType); } VMwareDVSPortgroupPolicy portGroupPolicy = null; @@ -660,7 +662,8 @@ public static boolean isFeatureSupportedInVcenterApiVersion(String vCenterApiVer return vCenterApiVersion.compareTo(minVcenterApiVersionForFeature) >= 0 ? true : false; } - private static void setupPVlanPair(DistributedVirtualSwitchMO dvSwitchMo, ManagedObjectReference morDvSwitch, Integer vid, Integer spvlanid) throws Exception { + private static void setupPVlanPair(DistributedVirtualSwitchMO dvSwitchMo, ManagedObjectReference morDvSwitch, Integer vid, Integer spvlanid, String pvlanType) throws Exception { + s_logger.debug(String.format("Setting up PVLAN on dvSwitch %s with the following information: %s %s %s", dvSwitchMo.getName(), vid, spvlanid, pvlanType)); Map vlanmap = dvSwitchMo.retrieveVlanPvlan(vid, spvlanid, morDvSwitch); if (!vlanmap.isEmpty()) { // Then either vid or pvlanid or both are already being used. Check how. @@ -678,25 +681,20 @@ private static void setupPVlanPair(DistributedVirtualSwitchMO dvSwitchMo, Manage s_logger.error(msg); throw new Exception(msg); } - } else { - if (vlanmap.containsKey(spvlanid) && !vlanmap.get(spvlanid).equals(HypervisorHostHelper.PvlanType.isolated)) { - // This PVLAN ID is already setup as a non-isolated vlan id on the DVS. Throw an exception. - String msg = "Specified secondary PVLAN ID " + spvlanid + " is already in use as a " + vlanmap.get(spvlanid).toString() + " VLAN in the DVSwitch"; - s_logger.error(msg); - throw new Exception(msg); - } } } // First create a DVSconfig spec. VMwareDVSConfigSpec dvsSpec = new VMwareDVSConfigSpec(); // Next, add the required primary and secondary vlan config specs to the dvs config spec. + if (!vlanmap.containsKey(vid)) { VMwareDVSPvlanConfigSpec ppvlanConfigSpec = createDVPortPvlanConfigSpec(vid, vid, PvlanType.promiscuous, PvlanOperation.add); dvsSpec.getPvlanConfigSpec().add(ppvlanConfigSpec); } if (!vid.equals(spvlanid) && !vlanmap.containsKey(spvlanid)) { - VMwareDVSPvlanConfigSpec spvlanConfigSpec = createDVPortPvlanConfigSpec(vid, spvlanid, PvlanType.isolated, PvlanOperation.add); + PvlanType selectedType = StringUtils.isNotBlank(pvlanType) ? PvlanType.fromStr(pvlanType) : PvlanType.isolated; + VMwareDVSPvlanConfigSpec spvlanConfigSpec = createDVPortPvlanConfigSpec(vid, spvlanid, selectedType, PvlanOperation.add); dvsSpec.getPvlanConfigSpec().add(spvlanConfigSpec); } @@ -1046,7 +1044,20 @@ public enum PvlanOperation { } public enum PvlanType { - promiscuous, isolated, community, // We don't use Community + promiscuous, isolated, community; + + public static PvlanType fromStr(String val) { + if (StringUtils.isBlank(val)) { + return null; + } else if (val.equalsIgnoreCase("promiscuous")) { + return promiscuous; + } else if (val.equalsIgnoreCase("community")) { + return community; + } else if (val.equalsIgnoreCase("isolated")) { + return isolated; + } + return null; + } } public static VMwareDVSPvlanConfigSpec createDVPortPvlanConfigSpec(int vlanId, int secondaryVlanId, PvlanType pvlantype, PvlanOperation operation) { diff --git a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java index a1205c258eee..48e3944a00a9 100644 --- a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java +++ b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java @@ -492,7 +492,6 @@ public boolean createSnapshot(String snapshotName, String snapshotDescription, b public ManagedObjectReference createSnapshotGetReference(String snapshotName, String snapshotDescription, boolean dumpMemory, boolean quiesce) throws Exception { long apiTimeout = _context.getVimClient().getVcenterSessionTimeout(); ManagedObjectReference morTask = _context.getService().createSnapshotTask(_mor, snapshotName, snapshotDescription, dumpMemory, quiesce); - boolean result = _context.getVimClient().waitForTask(morTask); if (result) { diff --git a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/VmwareHypervisorHost.java b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/VmwareHypervisorHost.java index 6f0cd2291b47..a9ceb5d806ec 100644 --- a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/VmwareHypervisorHost.java +++ b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/VmwareHypervisorHost.java @@ -16,6 +16,8 @@ // under the License. package com.cloud.hypervisor.vmware.mo; +import java.util.List; + import com.vmware.vim25.ClusterDasConfigInfo; import com.vmware.vim25.ComputeResourceSummary; import com.vmware.vim25.ManagedObjectReference; @@ -51,6 +53,8 @@ public interface VmwareHypervisorHost { String getHyperHostDefaultGateway() throws Exception; + List listVmsOnHyperHost(String name) throws Exception; + VirtualMachineMO findVmOnHyperHost(String name) throws Exception; VirtualMachineMO findVmOnPeerHyperHost(String name) throws Exception; diff --git a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/util/VmwareClient.java b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/util/VmwareClient.java index 3050f0a19f05..c75b1e7c1065 100644 --- a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/util/VmwareClient.java +++ b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/util/VmwareClient.java @@ -30,7 +30,10 @@ import javax.xml.ws.WebServiceException; import javax.xml.ws.handler.MessageContext; +import org.apache.cloudstack.utils.security.SSLUtils; +import org.apache.cloudstack.utils.security.SecureSSLSocketFactory; import org.apache.log4j.Logger; +import org.w3c.dom.Element; import com.vmware.vim25.DynamicProperty; import com.vmware.vim25.InvalidCollectorVersionFaultMsg; @@ -57,9 +60,7 @@ import com.vmware.vim25.UpdateSet; import com.vmware.vim25.VimPortType; import com.vmware.vim25.VimService; - -import org.apache.cloudstack.utils.security.SSLUtils; -import org.apache.cloudstack.utils.security.SecureSSLSocketFactory; +import com.vmware.vim25.WaitOptions; /** * A wrapper class to handle Vmware vsphere connection and disconnection. @@ -412,12 +413,13 @@ public boolean waitForTask(ManagedObjectReference task) throws InvalidPropertyFa * @throws InvalidPropertyFaultMsg * @throws InvalidCollectorVersionFaultMsg */ - private Object[] waitForValues(ManagedObjectReference objmor, String[] filterProps, String[] endWaitProps, Object[][] expectedVals) throws InvalidPropertyFaultMsg, + private synchronized Object[] waitForValues(ManagedObjectReference objmor, String[] filterProps, String[] endWaitProps, Object[][] expectedVals) throws InvalidPropertyFaultMsg, RuntimeFaultFaultMsg, InvalidCollectorVersionFaultMsg { // version string is initially null String version = ""; Object[] endVals = new Object[endWaitProps.length]; Object[] filterVals = new Object[filterProps.length]; + String stateVal = null; PropertyFilterSpec spec = new PropertyFilterSpec(); ObjectSpec oSpec = new ObjectSpec(); @@ -440,7 +442,7 @@ private Object[] waitForValues(ManagedObjectReference objmor, String[] filterPro List objupary = null; List propchgary = null; while (!reached) { - updateset = vimPort.waitForUpdates(propertyCollector, version); + updateset = vimPort.waitForUpdatesEx(propertyCollector, version, new WaitOptions()); if (updateset == null || updateset.getFilterSet() == null) { continue; } @@ -452,7 +454,6 @@ private Object[] waitForValues(ManagedObjectReference objmor, String[] filterPro for (PropertyFilterUpdate filtup : filtupary) { objupary = filtup.getObjectSet(); for (ObjectUpdate objup : objupary) { - // TODO: Handle all "kind"s of updates. if (objup.getKind() == ObjectUpdateKind.MODIFY || objup.getKind() == ObjectUpdateKind.ENTER || objup.getKind() == ObjectUpdateKind.LEAVE) { propchgary = objup.getChangeSet(); for (PropertyChange propchg : propchgary) { @@ -464,21 +465,38 @@ private Object[] waitForValues(ManagedObjectReference objmor, String[] filterPro } Object expctdval = null; - // Check if the expected values have been reached and exit the loop - // if done. + // Check if the expected values have been reached and exit the loop if done. // Also exit the WaitForUpdates loop if this is the case. for (int chgi = 0; chgi < endVals.length && !reached; chgi++) { for (int vali = 0; vali < expectedVals[chgi].length && !reached; vali++) { expctdval = expectedVals[chgi][vali]; - reached = expctdval.equals(endVals[chgi]) || reached; + if (endVals[chgi] == null) { + // Do nothing + } else if (endVals[chgi].toString().contains("val: null")) { + // Handle JAX-WS De-serialization issue, by parsing nodes + Element stateElement = (Element) endVals[chgi]; + if (stateElement != null && stateElement.getFirstChild() != null) { + stateVal = stateElement.getFirstChild().getTextContent(); + reached = expctdval.toString().equalsIgnoreCase(stateVal) || reached; + } + } else { + reached = expctdval.equals(endVals[chgi]) || reached; + stateVal = "filtervals"; + } } } } // Destroy the filter when we are done. vimPort.destroyPropertyFilter(filterSpecRef); - return filterVals; + + Object[] retVal = filterVals; + if (stateVal != null && stateVal.equalsIgnoreCase("success")) { + retVal = new Object[] { TaskInfoState.SUCCESS, null }; + } + + return retVal; } private void updateValues(String[] props, Object[] vals, PropertyChange propchg) {