This is an automated email from the ASF dual-hosted git repository.

dahn pushed a commit to branch 4.20
in repository https://gitbox.apache.org/repos/asf/cloudstack.git

commit b7f0aac5194b3df3d67ce6ece0beecdfa04cce44
Merge: ac19379c967 ed1b145a3a0
Author: Daan Hoogland <d...@onecht.net>
AuthorDate: Fri Dec 20 14:34:39 2024 +0100

    Merge branch '4.19' into 4.20

 .../main/java/com/cloud/vm/VmDetailConstants.java  |   1 +
 .../java/com/cloud/agent/manager/AgentAttache.java |  10 +-
 packaging/el8/cloud.spec                           |   3 +
 packaging/el8/filelimit.conf                       |  20 ++++
 .../kvm/resource/LibvirtComputingResource.java     |  89 +++++++++-------
 .../LibvirtGetVmIpAddressCommandWrapper.java       |   3 +
 .../LibvirtPrepareForMigrationCommandWrapper.java  |   2 +-
 ...tupDirectDownloadCertificateCommandWrapper.java |   4 +
 .../wrapper/LibvirtStartCommandWrapper.java        |   2 +-
 .../kvm/storage/IscsiAdmStorageAdaptor.java        |   2 +-
 .../kvm/storage/IscsiAdmStoragePool.java           |   2 +-
 .../kvm/storage/KVMStoragePoolManager.java         |   9 +-
 .../kvm/storage/LibvirtStorageAdaptor.java         |   2 +-
 .../kvm/storage/ManagedNfsStorageAdaptor.java      |   2 +-
 .../kvm/storage/MultipathSCSIAdapterBase.java      |   2 +-
 .../hypervisor/kvm/storage/MultipathSCSIPool.java  |   2 +-
 .../kvm/storage/ScaleIOStorageAdaptor.java         |   4 +-
 .../hypervisor/kvm/storage/ScaleIOStoragePool.java |   2 +-
 .../hypervisor/kvm/storage/StorageAdaptor.java     |  11 +-
 .../kvm/resource/LibvirtComputingResourceTest.java |  10 +-
 .../kvm/storage/ScaleIOStoragePoolTest.java        |   2 +-
 .../CitrixGetVmIpAddressCommandWrapper.java        |  15 ++-
 plugins/storage/volume/linstor/CHANGELOG.md        |  12 +++
 .../kvm/storage/LinstorStorageAdaptor.java         |  33 ++++--
 .../hypervisor/kvm/storage/LinstorStoragePool.java |  42 ++++++--
 .../kvm/storage/StorPoolStorageAdaptor.java        |   2 +-
 .../kvm/storage/StorPoolStoragePool.java           |   2 +-
 .../network/element/ConfigDriveNetworkElement.java |  43 ++++++--
 .../network/element/VirtualRouterElement.java      |   2 +-
 .../java/com/cloud/user/AccountManagerImpl.java    |  41 ++++---
 .../main/java/com/cloud/vm/UserVmManagerImpl.java  |  12 +--
 .../direct/download/DirectDownloadManagerImpl.java |  11 +-
 .../com/cloud/user/AccountManagerImplTest.java     | 118 ++++++++++++++++++++-
 systemvm/debian/opt/cloud/bin/configure.py         |   2 +-
 .../main/java/com/cloud/utils/net/NetUtils.java    |  10 +-
 35 files changed, 400 insertions(+), 129 deletions(-)

diff --cc packaging/el8/cloud.spec
index f9d6fd1ce87,00000000000..eb03cfe0df4
mode 100644,000000..100644
--- a/packaging/el8/cloud.spec
+++ b/packaging/el8/cloud.spec
@@@ -1,705 -1,0 +1,708 @@@
 +# 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.
 +
 +%define __os_install_post %{nil}
 +%global debug_package %{nil}
 +
 +# DISABLE the post-percentinstall java repacking and line number stripping
 +# we need to find a way to just disable the java repacking and line number 
stripping, but not the autodeps
 +
 +Name:      cloudstack
 +Summary:   CloudStack IaaS Platform
 +#http://fedoraproject.org/wiki/PackageNamingGuidelines#Pre-Release_packages
 +%define _maventag %{_fullver}
 +Release:   %{_rel}
 +
 +Version:   %{_ver}
 +License:   ASL 2.0
 +Vendor:    Apache CloudStack <d...@cloudstack.apache.org>
 +Packager:  Apache CloudStack <d...@cloudstack.apache.org>
 +Group:     System Environment/Libraries
 +# FIXME do groups for every single one of the subpackages
 +Source0:   %{name}-%{_maventag}.tgz
 +BuildRoot: %{_tmppath}/%{name}-%{_maventag}-%{release}-build
 +
 +BuildRequires: (java-11-openjdk-devel or java-17-openjdk-devel)
 +#BuildRequires: ws-commons-util
 +BuildRequires: jpackage-utils
 +BuildRequires: gcc
 +BuildRequires: glibc-devel
 +BuildRequires: /usr/bin/mkisofs
 +BuildRequires: python3-setuptools
 +BuildRequires: wget
 +BuildRequires: nodejs
 +
 +%description
 +CloudStack is a highly-scalable elastic, open source,
 +intelligent IaaS cloud implementation.
 +
 +%package management
 +Summary:   CloudStack management server UI
 +Requires: java-17-openjdk
 +Requires: (tzdata-java or timezone-java)
 +Requires: python3
 +Requires: bash
 +Requires: gawk
 +Requires: which
 +Requires: file
 +Requires: tar
 +Requires: bzip2
 +Requires: gzip
 +Requires: unzip
 +Requires: /sbin/mount.nfs
 +Requires: (openssh-clients or openssh)
 +Requires: (nfs-utils or nfs-client)
 +Requires: iproute
 +Requires: wget
 +Requires: mysql
 +Requires: sudo
 +Requires: /sbin/service
 +Requires: /sbin/chkconfig
 +Requires: /usr/bin/ssh-keygen
 +Requires: (genisoimage or mkisofs)
 +Requires: ipmitool
 +Requires: %{name}-common = %{_ver}
 +Requires: (iptables-services or iptables)
 +Requires: rng-tools
 +Requires: (qemu-img or qemu-tools)
 +Requires: python3-pip
 +Requires: python3-setuptools
 +Requires: (libgcrypt > 1.8.3 or libgcrypt20)
 +Group:     System Environment/Libraries
 +%description management
 +The CloudStack management server is the central point of coordination,
 +management, and intelligence in CloudStack.
 +
 +%package common
 +Summary: Apache CloudStack common files and scripts
 +Requires: python3
 +Group:   System Environment/Libraries
 +%description common
 +The Apache CloudStack files shared between agent and management server
 +%global __requires_exclude ^(libuuid\\.so\\.1|/usr/bin/python)$
 +
 +%package agent
 +Summary: CloudStack Agent for KVM hypervisors
 +Requires: (openssh-clients or openssh)
 +Requires: java-17-openjdk
 +Requires: tzdata-java
 +Requires: %{name}-common = %{_ver}
 +Requires: libvirt
 +Requires: libvirt-daemon-driver-storage-rbd
 +Requires: ebtables
 +Requires: iptables
 +Requires: ethtool
 +Requires: (net-tools or net-tools-deprecated)
 +Requires: iproute
 +Requires: ipset
 +Requires: perl
 +Requires: rsync
 +Requires: (python3-libvirt or python3-libvirt-python)
 +Requires: (qemu-img or qemu-tools)
 +Requires: qemu-kvm
 +Requires: cryptsetup
 +Requires: rng-tools
 +Requires: (libgcrypt > 1.8.3 or libgcrypt20)
 +Requires: (selinux-tools if qemu-tools)
 +Provides: cloud-agent
 +Group: System Environment/Libraries
 +%description agent
 +The CloudStack agent for KVM hypervisors
 +
 +%package baremetal-agent
 +Summary: CloudStack baremetal agent
 +Requires: tftp-server
 +Requires: xinetd
 +Requires: syslinux
 +Requires: chkconfig
 +Requires: dhcp
 +Requires: httpd
 +Group:     System Environment/Libraries
 +%description baremetal-agent
 +The CloudStack baremetal agent
 +
 +%package usage
 +Summary: CloudStack Usage calculation server
 +Requires: java-17-openjdk
 +Requires: tzdata-java
 +Group: System Environment/Libraries
 +%description usage
 +The CloudStack usage calculation service
 +
 +%package ui
 +Summary: CloudStack UI
 +Group: System Environment/Libraries
 +%description ui
 +The CloudStack UI
 +
 +%package marvin
 +Summary: Apache CloudStack Marvin library
 +Requires: python3-pip
 +Requires: gcc
 +Requires: python3-devel
 +Requires: libffi-devel
 +Requires: openssl-devel
 +Group: System Environment/Libraries
 +%description marvin
 +Apache CloudStack Marvin library
 +
 +%package integration-tests
 +Summary: Apache CloudStack Marvin integration tests
 +Requires: %{name}-marvin = %{_ver}
 +Group: System Environment/Libraries
 +%description integration-tests
 +Apache CloudStack Marvin integration tests
 +
 +%if "%{_ossnoss}" == "noredist"
 +%package mysql-ha
 +Summary: Apache CloudStack Balancing Strategy for MySQL
 +Group: System Environmnet/Libraries
 +%description mysql-ha
 +Apache CloudStack Balancing Strategy for MySQL
 +
 +%endif
 +
 +%prep
 +echo Doing CloudStack build
 +
 +%setup -q -n %{name}-%{_maventag}
 +
 +%build
 +
 +cp packaging/el8/replace.properties build/replace.properties
 +echo VERSION=%{_maventag} >> build/replace.properties
 +echo PACKAGE=%{name} >> build/replace.properties
 +touch build/gitrev.txt
 +echo $(git rev-parse HEAD) > build/gitrev.txt
 +
 +if [ "%{_ossnoss}" == "NOREDIST" -o "%{_ossnoss}" == "noredist" ] ; then
 +   echo "Adding noredist flag to the maven build"
 +   FLAGS="$FLAGS -Dnoredist"
 +fi
 +
 +if [ "%{_sim}" == "SIMULATOR" -o "%{_sim}" == "simulator" ] ; then
 +   echo "Adding simulator flag to the maven build"
 +   FLAGS="$FLAGS -Dsimulator"
 +fi
 +
 +if [ \"%{_temp}\" != "" ]; then
 +    echo "Adding flags to package requested templates"
 +    FLAGS="$FLAGS `rpm --eval %{?_temp}`"
 +fi
 +
 +mvn -Psystemvm,developer $FLAGS clean package
 +cd ui && npm install && npm run build && cd ..
 +
 +%install
 +[ ${RPM_BUILD_ROOT} != "/" ] && rm -rf ${RPM_BUILD_ROOT}
 +# Common directories
 +mkdir -p ${RPM_BUILD_ROOT}%{_bindir}
 +mkdir -p ${RPM_BUILD_ROOT}%{_localstatedir}/log/%{name}/agent
 +mkdir -p ${RPM_BUILD_ROOT}%{_localstatedir}/log/%{name}/ipallocator
 +mkdir -p ${RPM_BUILD_ROOT}%{_localstatedir}/cache/%{name}/management/work
 +mkdir -p ${RPM_BUILD_ROOT}%{_localstatedir}/cache/%{name}/management/temp
 +mkdir -p ${RPM_BUILD_ROOT}%{_localstatedir}/%{name}/mnt
 +mkdir -p ${RPM_BUILD_ROOT}%{_localstatedir}/%{name}/management
 +mkdir -p ${RPM_BUILD_ROOT}%{_initrddir}
 +mkdir -p ${RPM_BUILD_ROOT}%{_sysconfdir}/default
 +mkdir -p ${RPM_BUILD_ROOT}%{_sysconfdir}/profile.d
 +mkdir -p ${RPM_BUILD_ROOT}%{_sysconfdir}/sudoers.d
 +
 +# Common
 +mkdir -p ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/scripts
 +mkdir -p ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/vms
 +mkdir -p ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/python-site
 +mkdir -p ${RPM_BUILD_ROOT}/usr/bin
 +cp -r scripts/* ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/scripts
 +install -D systemvm/dist/* ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/vms/
 +install python/lib/cloud_utils.py 
${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/python-site/cloud_utils.py
 +cp -r python/lib/cloudutils 
${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/python-site/
 +python3 -m py_compile 
${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/python-site/cloud_utils.py
 +python3 -m compileall 
${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/python-site/cloudutils
 +cp build/gitrev.txt ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/scripts
 +cp packaging/el8/cloudstack-sccs ${RPM_BUILD_ROOT}/usr/bin
 +
 +mkdir -p ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/scripts/network/cisco
 +cp -r plugins/network-elements/cisco-vnmc/src/main/scripts/network/cisco/* 
${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/scripts/network/cisco
 +
 +# Management
 +mkdir -p ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/
 +mkdir -p ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/lib
 +mkdir -p ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/setup
 +mkdir -p ${RPM_BUILD_ROOT}%{_localstatedir}/log/%{name}/management
 +mkdir -p ${RPM_BUILD_ROOT}%{_sysconfdir}/%{name}/management
++mkdir -p 
${RPM_BUILD_ROOT}%{_sysconfdir}/systemd/system/%{name}-management.service.d
 +mkdir -p ${RPM_BUILD_ROOT}%{_localstatedir}/run
 +mkdir -p ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/setup/wheel
 +
 +# Setup Jetty
 +ln -sf /etc/%{name}/management 
${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/conf
 +ln -sf /var/log/%{name}/management 
${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/logs
 +
 +install -D client/target/utilities/bin/cloud-migrate-databases 
${RPM_BUILD_ROOT}%{_bindir}/%{name}-migrate-databases
 +install -D client/target/utilities/bin/cloud-set-guest-password 
${RPM_BUILD_ROOT}%{_bindir}/%{name}-set-guest-password
 +install -D client/target/utilities/bin/cloud-set-guest-sshkey 
${RPM_BUILD_ROOT}%{_bindir}/%{name}-set-guest-sshkey
 +install -D client/target/utilities/bin/cloud-setup-databases 
${RPM_BUILD_ROOT}%{_bindir}/%{name}-setup-databases
 +install -D client/target/utilities/bin/cloud-setup-encryption 
${RPM_BUILD_ROOT}%{_bindir}/%{name}-setup-encryption
 +install -D client/target/utilities/bin/cloud-setup-management 
${RPM_BUILD_ROOT}%{_bindir}/%{name}-setup-management
 +install -D client/target/utilities/bin/cloud-setup-baremetal 
${RPM_BUILD_ROOT}%{_bindir}/%{name}-setup-baremetal
 +install -D client/target/utilities/bin/cloud-sysvmadm 
${RPM_BUILD_ROOT}%{_bindir}/%{name}-sysvmadm
 +install -D client/target/utilities/bin/cloud-update-xenserver-licenses 
${RPM_BUILD_ROOT}%{_bindir}/%{name}-update-xenserver-licenses
 +# Bundle cmk in cloudstack-management
 +CMK_REL=$(wget -O - 
"https://api.github.com/repos/apache/cloudstack-cloudmonkey/releases"; 
2>/dev/null | jq -r '.[0].tag_name')
 +wget 
https://github.com/apache/cloudstack-cloudmonkey/releases/download/$CMK_REL/cmk.linux.x86-64
 -O ${RPM_BUILD_ROOT}%{_bindir}/cmk
 +chmod +x ${RPM_BUILD_ROOT}%{_bindir}/cmk
 +
 +cp -r client/target/utilities/scripts/db/* 
${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/setup
 +
 +cp -r client/target/cloud-client-ui-%{_maventag}.jar 
${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/
 +cp -r client/target/classes/META-INF/webapp 
${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/webapp
 +cp ui/dist/config.json ${RPM_BUILD_ROOT}%{_sysconfdir}/%{name}/management/
 +cp -r ui/dist/* ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/webapp/
 +rm -f ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/webapp/config.json
 +ln -sf /etc/%{name}/management/config.json 
${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/webapp/config.json
 +mv 
${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/cloud-client-ui-%{_maventag}.jar
 ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/lib/cloudstack-%{_maventag}.jar
 +cp client/target/lib/*jar ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/lib/
 +
 +# Don't package the scripts in the management webapp
 +rm -rf 
${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/webapps/client/WEB-INF/classes/scripts
 +rm -rf 
${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/webapps/client/WEB-INF/classes/vms
 +
 +for name in db.properties server.properties log4j-cloud.xml 
environment.properties java.security.ciphers
 +do
 +  cp client/target/conf/$name 
${RPM_BUILD_ROOT}%{_sysconfdir}/%{name}/management/$name
 +done
 +
 +ln -sf log4j-cloud.xml  
${RPM_BUILD_ROOT}%{_sysconfdir}/%{name}/management/log4j2.xml
 +
 +install python/bindir/cloud-external-ipallocator.py 
${RPM_BUILD_ROOT}%{_bindir}/%{name}-external-ipallocator.py
 +install -D client/target/pythonlibs/jasypt-1.9.3.jar 
${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/lib/jasypt-1.9.3.jar
 +install -D utils/target/cloud-utils-%{_maventag}-bundled.jar 
${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/lib/%{name}-utils.jar
 +
 +install -D packaging/el8/cloud-ipallocator.rc 
${RPM_BUILD_ROOT}%{_initrddir}/%{name}-ipallocator
 +install -D packaging/el8/cloud.limits 
${RPM_BUILD_ROOT}%{_sysconfdir}/security/limits.d/cloud
++install -D packaging/el8/filelimit.conf 
${RPM_BUILD_ROOT}%{_sysconfdir}/systemd/system/%{name}-management.service.d
 +install -D packaging/systemd/cloudstack-management.service 
${RPM_BUILD_ROOT}%{_unitdir}/%{name}-management.service
 +install -D packaging/systemd/cloudstack-management.default 
${RPM_BUILD_ROOT}%{_sysconfdir}/default/%{name}-management
 +install -D server/target/conf/cloudstack-sudoers 
${RPM_BUILD_ROOT}%{_sysconfdir}/sudoers.d/%{name}-management
 +touch ${RPM_BUILD_ROOT}%{_localstatedir}/run/%{name}-management.pid
 +#install -D server/target/conf/cloudstack-catalina.logrotate 
${RPM_BUILD_ROOT}%{_sysconfdir}/logrotate.d/%{name}-catalina
 +install -D server/target/conf/cloudstack-management.logrotate 
${RPM_BUILD_ROOT}%{_sysconfdir}/logrotate.d/%{name}-management
 +
 +# SystemVM template
 +mkdir -p ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/templates/systemvm
 +cp -r engine/schema/dist/systemvm-templates/* 
${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/templates/systemvm
 +rm -rf 
${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/templates/systemvm/md5sum.txt
 +
 +# UI
 +mkdir -p ${RPM_BUILD_ROOT}%{_sysconfdir}/%{name}/ui
 +mkdir -p ${RPM_BUILD_ROOT}%{_datadir}/%{name}-ui/
 +cp -r client/target/classes/META-INF/webapp/WEB-INF 
${RPM_BUILD_ROOT}%{_datadir}/%{name}-ui
 +cp ui/dist/config.json ${RPM_BUILD_ROOT}%{_sysconfdir}/%{name}/ui/
 +cp -r ui/dist/* ${RPM_BUILD_ROOT}%{_datadir}/%{name}-ui/
 +rm -f ${RPM_BUILD_ROOT}%{_datadir}/%{name}-ui/config.json
 +ln -sf /etc/%{name}/ui/config.json 
${RPM_BUILD_ROOT}%{_datadir}/%{name}-ui/config.json
 +
 +# Package mysql-connector-python
 +wget -P ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/setup/wheel 
https://files.pythonhosted.org/packages/ee/ff/48bde5c0f013094d729fe4b0316ba2a24774b3ff1c52d924a8a4cb04078a/six-1.15.0-py2.py3-none-any.whl
 +wget -P ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/setup/wheel 
https://files.pythonhosted.org/packages/e9/93/4860cebd5ad3ff2664ad3c966490ccb46e3b88458b2095145bca11727ca4/setuptools-47.3.1-py3-none-any.whl
 +wget -P ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/setup/wheel 
https://files.pythonhosted.org/packages/32/27/1141a8232723dcb10a595cc0ce4321dcbbd5215300bf4acfc142343205bf/protobuf-3.19.6-py2.py3-none-any.whl
 +wget -P ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/setup/wheel 
https://files.pythonhosted.org/packages/08/1f/42d74bae9dd6dcfec67c9ed0f3fa482b1ae5ac5f117ca82ab589ecb3ca19/mysql_connector_python-8.0.31-py2.py3-none-any.whl
 +
 +chmod 440 ${RPM_BUILD_ROOT}%{_sysconfdir}/sudoers.d/%{name}-management
 +chmod 770 ${RPM_BUILD_ROOT}%{_localstatedir}/%{name}/mnt
 +chmod 770 ${RPM_BUILD_ROOT}%{_localstatedir}/%{name}/management
 +chmod 770 ${RPM_BUILD_ROOT}%{_localstatedir}/cache/%{name}/management/work
 +chmod 770 ${RPM_BUILD_ROOT}%{_localstatedir}/cache/%{name}/management/temp
 +chmod 770 ${RPM_BUILD_ROOT}%{_localstatedir}/log/%{name}/management
 +chmod 770 ${RPM_BUILD_ROOT}%{_localstatedir}/log/%{name}/agent
 +
 +# KVM Agent
 +mkdir -p ${RPM_BUILD_ROOT}%{_sysconfdir}/%{name}/agent
 +mkdir -p ${RPM_BUILD_ROOT}%{_localstatedir}/log/%{name}/agent
 +mkdir -p ${RPM_BUILD_ROOT}%{_datadir}/%{name}-agent/lib
 +mkdir -p ${RPM_BUILD_ROOT}%{_datadir}/%{name}-agent/plugins
 +install -D packaging/systemd/cloudstack-agent.service 
${RPM_BUILD_ROOT}%{_unitdir}/%{name}-agent.service
 +install -D packaging/systemd/cloudstack-rolling-maintenance@.service 
${RPM_BUILD_ROOT}%{_unitdir}/%{name}-rolling-maintenance@.service
 +install -D packaging/systemd/cloudstack-agent.default 
${RPM_BUILD_ROOT}%{_sysconfdir}/default/%{name}-agent
 +install -D agent/target/transformed/agent.properties 
${RPM_BUILD_ROOT}%{_sysconfdir}/%{name}/agent/agent.properties
 +install -D agent/target/transformed/environment.properties 
${RPM_BUILD_ROOT}%{_sysconfdir}/%{name}/agent/environment.properties
 +install -D agent/target/transformed/log4j-cloud.xml 
${RPM_BUILD_ROOT}%{_sysconfdir}/%{name}/agent/log4j-cloud.xml
 +install -D agent/target/transformed/cloud-setup-agent 
${RPM_BUILD_ROOT}%{_bindir}/%{name}-setup-agent
 +install -D agent/target/transformed/cloudstack-agent-upgrade 
${RPM_BUILD_ROOT}%{_bindir}/%{name}-agent-upgrade
 +install -D agent/target/transformed/cloud-guest-tool 
${RPM_BUILD_ROOT}%{_bindir}/%{name}-guest-tool
 +install -D agent/target/transformed/libvirtqemuhook 
${RPM_BUILD_ROOT}%{_datadir}/%{name}-agent/lib/libvirtqemuhook
 +install -D agent/target/transformed/rolling-maintenance 
${RPM_BUILD_ROOT}%{_datadir}/%{name}-agent/lib/rolling-maintenance
 +install -D agent/target/transformed/cloud-ssh 
${RPM_BUILD_ROOT}%{_bindir}/%{name}-ssh
 +install -D agent/target/transformed/cloudstack-agent-profile.sh 
${RPM_BUILD_ROOT}%{_sysconfdir}/profile.d/%{name}-agent-profile.sh
 +install -D agent/target/transformed/cloudstack-agent.logrotate 
${RPM_BUILD_ROOT}%{_sysconfdir}/logrotate.d/%{name}-agent
 +install -D 
plugins/hypervisors/kvm/target/cloud-plugin-hypervisor-kvm-%{_maventag}.jar 
${RPM_BUILD_ROOT}%{_datadir}/%name-agent/lib/cloud-plugin-hypervisor-kvm-%{_maventag}.jar
 +cp plugins/hypervisors/kvm/target/dependencies/*  
${RPM_BUILD_ROOT}%{_datadir}/%{name}-agent/lib
 +cp plugins/storage/volume/storpool/target/*.jar  
${RPM_BUILD_ROOT}%{_datadir}/%{name}-agent/lib
 +cp plugins/storage/volume/linstor/target/*.jar  
${RPM_BUILD_ROOT}%{_datadir}/%{name}-agent/lib
 +
 +# Usage server
 +mkdir -p ${RPM_BUILD_ROOT}%{_sysconfdir}/%{name}/usage
 +mkdir -p ${RPM_BUILD_ROOT}%{_datadir}/%{name}-usage/lib
 +install -D usage/target/cloud-usage-%{_maventag}.jar 
${RPM_BUILD_ROOT}%{_datadir}/%{name}-usage/cloud-usage-%{_maventag}.jar
 +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/
 +install -D usage/target/transformed/cloudstack-usage.logrotate 
${RPM_BUILD_ROOT}%{_sysconfdir}/logrotate.d/%{name}-usage
 +
 +# Marvin
 +mkdir -p ${RPM_BUILD_ROOT}%{_datadir}/%{name}-marvin
 +cp tools/marvin/dist/Marvin-*.tar.gz 
${RPM_BUILD_ROOT}%{_datadir}/%{name}-marvin/
 +
 +# integration-tests
 +mkdir -p ${RPM_BUILD_ROOT}%{_datadir}/%{name}-integration-tests
 +cp -r test/integration/* 
${RPM_BUILD_ROOT}%{_datadir}/%{name}-integration-tests/
 +
 +# MYSQL HA
 +if [ "x%{_ossnoss}" == "xnoredist" ] ; then
 +  mkdir -p ${RPM_BUILD_ROOT}%{_datadir}/%{name}-mysql-ha/lib
 +  cp -r 
plugins/database/mysql-ha/target/cloud-plugin-database-mysqlha-%{_maventag}.jar 
${RPM_BUILD_ROOT}%{_datadir}/%{name}-mysql-ha/lib
 +fi
 +
 +#License files from whisker
 +install -D tools/whisker/NOTICE 
${RPM_BUILD_ROOT}%{_defaultdocdir}/%{name}-management-%{version}/NOTICE
 +install -D tools/whisker/LICENSE 
${RPM_BUILD_ROOT}%{_defaultdocdir}/%{name}-management-%{version}/LICENSE
 +install -D tools/whisker/NOTICE 
${RPM_BUILD_ROOT}%{_defaultdocdir}/%{name}-common-%{version}/NOTICE
 +install -D tools/whisker/LICENSE 
${RPM_BUILD_ROOT}%{_defaultdocdir}/%{name}-common-%{version}/LICENSE
 +install -D tools/whisker/NOTICE 
${RPM_BUILD_ROOT}%{_defaultdocdir}/%{name}-agent-%{version}/NOTICE
 +install -D tools/whisker/LICENSE 
${RPM_BUILD_ROOT}%{_defaultdocdir}/%{name}-agent-%{version}/LICENSE
 +install -D tools/whisker/NOTICE 
${RPM_BUILD_ROOT}%{_defaultdocdir}/%{name}-usage-%{version}/NOTICE
 +install -D tools/whisker/LICENSE 
${RPM_BUILD_ROOT}%{_defaultdocdir}/%{name}-usage-%{version}/LICENSE
 +install -D tools/whisker/NOTICE 
${RPM_BUILD_ROOT}%{_defaultdocdir}/%{name}-ui-%{version}/NOTICE
 +install -D tools/whisker/LICENSE 
${RPM_BUILD_ROOT}%{_defaultdocdir}/%{name}-ui-%{version}/LICENSE
 +install -D tools/whisker/NOTICE 
${RPM_BUILD_ROOT}%{_defaultdocdir}/%{name}-marvin-%{version}/NOTICE
 +install -D tools/whisker/LICENSE 
${RPM_BUILD_ROOT}%{_defaultdocdir}/%{name}-marvin-%{version}/LICENSE
 +install -D tools/whisker/NOTICE 
${RPM_BUILD_ROOT}%{_defaultdocdir}/%{name}-integration-tests-%{version}/NOTICE
 +install -D tools/whisker/LICENSE 
${RPM_BUILD_ROOT}%{_defaultdocdir}/%{name}-integration-tests-%{version}/LICENSE
 +
 +%clean
 +[ ${RPM_BUILD_ROOT} != "/" ] && rm -rf ${RPM_BUILD_ROOT}
 +
 +%posttrans common
 +
 +unalias cp
 +python_dir=$(python3 -c "from distutils.sysconfig import get_python_lib; 
print(get_python_lib(1))")
 +if [ ! -z $python_dir ];then
 +  cp -f -r /usr/share/cloudstack-common/python-site/* $python_dir/
 +fi
 +
 +%preun management
 +/usr/bin/systemctl stop cloudstack-management || true
 +/usr/bin/systemctl disable cloudstack-management || true
 +
 +%pre management
 +id cloud > /dev/null 2>&1 || /usr/sbin/useradd -M -U -c "CloudStack 
unprivileged user" \
 +     -r -s /bin/sh -d %{_localstatedir}/cloudstack/management cloud || true
 +
 +rm -rf %{_localstatedir}/cache/cloudstack
 +
 +# in case of upgrade to 4.9+ copy commands.properties if not exists in 
/etc/cloudstack/management/
 +if [ "$1" == "2" ] ; then
 +    if [ -f 
"%{_datadir}/%{name}-management/webapps/client/WEB-INF/classes/commands.properties"
 ] && [ ! -f "%{_sysconfdir}/%{name}/management/commands.properties" ] ; then
 +        cp -p 
%{_datadir}/%{name}-management/webapps/client/WEB-INF/classes/commands.properties
 %{_sysconfdir}/%{name}/management/commands.properties
 +    fi
 +fi
 +
 +# Remove old tomcat symlinks and env config file
 +if [ -L "%{_datadir}/%{name}-management/lib" ]
 +then
 +    rm -f %{_datadir}/%{name}-management/bin
 +    rm -f %{_datadir}/%{name}-management/lib
 +    rm -f %{_datadir}/%{name}-management/temp
 +    rm -f %{_datadir}/%{name}-management/work
 +    rm -f %{_sysconfdir}/default/%{name}-management
 +fi
 +
 +%post management
 +# Install mysql-connector-python
 +pip3 install 
%{_datadir}/%{name}-management/setup/wheel/six-1.15.0-py2.py3-none-any.whl 
%{_datadir}/%{name}-management/setup/wheel/setuptools-47.3.1-py3-none-any.whl 
%{_datadir}/%{name}-management/setup/wheel/protobuf-3.19.6-py2.py3-none-any.whl 
%{_datadir}/%{name}-management/setup/wheel/mysql_connector_python-8.0.31-py2.py3-none-any.whl
 +
 +/usr/bin/systemctl enable cloudstack-management > /dev/null 2>&1 || true
 +/usr/bin/systemctl enable --now rngd > /dev/null 2>&1 || true
 +
 +grep -s -q "db.cloud.driver=jdbc:mysql" 
"%{_sysconfdir}/%{name}/management/db.properties" || sed -i -e 
"\$adb.cloud.driver=jdbc:mysql" 
"%{_sysconfdir}/%{name}/management/db.properties"
 +grep -s -q "db.usage.driver=jdbc:mysql" 
"%{_sysconfdir}/%{name}/management/db.properties" || sed -i -e 
"\$adb.usage.driver=jdbc:mysql"  
"%{_sysconfdir}/%{name}/management/db.properties"
 +grep -s -q "db.simulator.driver=jdbc:mysql" 
"%{_sysconfdir}/%{name}/management/db.properties" || sed -i -e 
"\$adb.simulator.driver=jdbc:mysql" 
"%{_sysconfdir}/%{name}/management/db.properties"
 +
 +# Update DB properties having master and slave(s), with source and replica(s) 
respectively (for inclusiveness)
 +grep -s -q "^db.cloud.slaves=" 
"%{_sysconfdir}/%{name}/management/db.properties" && sed -i 
"s/^db.cloud.slaves=/db.cloud.replicas=/g" 
"%{_sysconfdir}/%{name}/management/db.properties"
 +grep -s -q "^db.cloud.secondsBeforeRetryMaster=" 
"%{_sysconfdir}/%{name}/management/db.properties" && sed -i 
"s/^db.cloud.secondsBeforeRetryMaster=/db.cloud.secondsBeforeRetrySource=/g" 
"%{_sysconfdir}/%{name}/management/db.properties"
 +grep -s -q "^db.cloud.queriesBeforeRetryMaster=" 
"%{_sysconfdir}/%{name}/management/db.properties" && sed -i 
"s/^db.cloud.queriesBeforeRetryMaster=/db.cloud.queriesBeforeRetrySource=/g" 
"%{_sysconfdir}/%{name}/management/db.properties"
 +grep -s -q "^db.usage.slaves=" 
"%{_sysconfdir}/%{name}/management/db.properties" && sed -i 
"s/^db.usage.slaves=/db.usage.replicas=/g" 
"%{_sysconfdir}/%{name}/management/db.properties"
 +grep -s -q "^db.usage.secondsBeforeRetryMaster=" 
"%{_sysconfdir}/%{name}/management/db.properties" && sed -i 
"s/^db.usage.secondsBeforeRetryMaster=/db.usage.secondsBeforeRetrySource=/g" 
"%{_sysconfdir}/%{name}/management/db.properties"
 +grep -s -q "^db.usage.queriesBeforeRetryMaster=" 
"%{_sysconfdir}/%{name}/management/db.properties" && sed -i 
"s/^db.usage.queriesBeforeRetryMaster=/db.usage.queriesBeforeRetrySource=/g" 
"%{_sysconfdir}/%{name}/management/db.properties"
 +
 +if [ ! -f 
%{_datadir}/cloudstack-common/scripts/vm/hypervisor/xenserver/vhd-util ] ; then
 +    echo Please download vhd-util from 
http://download.cloudstack.org/tools/vhd-util and put it in
 +    echo %{_datadir}/cloudstack-common/scripts/vm/hypervisor/xenserver/
 +fi
 +
 +if [ -f %{_sysconfdir}/sysconfig/%{name}-management ] ; then
 +    rm -f %{_sysconfdir}/sysconfig/%{name}-management
 +fi
 +
 +chown -R cloud:cloud /var/log/cloudstack/management
 +
 +systemctl daemon-reload
 +
 +%posttrans management
 +# Print help message
 +if [ -f "/usr/share/cloudstack-common/scripts/installer/cloudstack-help-text" 
];then
 +    sed -i "s,^ACS_VERSION=.*,ACS_VERSION=%{_maventag},g" 
/usr/share/cloudstack-common/scripts/installer/cloudstack-help-text
 +    /usr/share/cloudstack-common/scripts/installer/cloudstack-help-text 
management
 +fi
 +
 +%preun agent
 +/sbin/service cloudstack-agent stop || true
 +if [ "$1" == "0" ] ; then
 +    /sbin/chkconfig --del cloudstack-agent > /dev/null 2>&1 || true
 +fi
 +
 +%pre agent
 +
 +# save old configs if they exist (for upgrade). Otherwise we may lose them
 +# when the old packages are erased. There are a lot of properties files here.
 +if [ -d "%{_sysconfdir}/cloud" ] ; then
 +    mv %{_sysconfdir}/cloud %{_sysconfdir}/cloud.rpmsave
 +fi
 +
 +%posttrans agent
 +
 +if [ "$1" == "2" ] ; then
 +    echo "Running %{_bindir}/%{name}-agent-upgrade to update bridge name for 
upgrade from CloudStack 4.0.x (and before) to CloudStack 4.1 (and later)"
 +    %{_bindir}/%{name}-agent-upgrade
 +fi
 +if [ ! -d %{_sysconfdir}/libvirt/hooks ] ; then
 +    mkdir %{_sysconfdir}/libvirt/hooks
 +fi
 +cp -a ${RPM_BUILD_ROOT}%{_datadir}/%{name}-agent/lib/libvirtqemuhook 
%{_sysconfdir}/libvirt/hooks/qemu
 +mkdir -m 0755 -p /usr/share/cloudstack-agent/tmp
 +/usr/bin/systemctl restart libvirtd
 +/usr/bin/systemctl enable cloudstack-agent > /dev/null 2>&1 || true
 +/usr/bin/systemctl enable cloudstack-rolling-maintenance@p > /dev/null 2>&1 
|| true
 +/usr/bin/systemctl enable --now rngd > /dev/null 2>&1 || true
 +
 +# if saved configs from upgrade exist, copy them over
 +if [ -f "%{_sysconfdir}/cloud.rpmsave/agent/agent.properties" ]; then
 +    mv %{_sysconfdir}/%{name}/agent/agent.properties  
%{_sysconfdir}/%{name}/agent/agent.properties.rpmnew
 +    cp -p %{_sysconfdir}/cloud.rpmsave/agent/agent.properties 
%{_sysconfdir}/%{name}/agent
 +    # make sure we only do this on the first install of this RPM, don't want 
to overwrite on a reinstall
 +    mv %{_sysconfdir}/cloud.rpmsave/agent/agent.properties 
%{_sysconfdir}/cloud.rpmsave/agent/agent.properties.rpmsave
 +fi
 +
 +systemctl daemon-reload
 +
 +# Print help message
 +if [ -f "/usr/share/cloudstack-common/scripts/installer/cloudstack-help-text" 
];then
 +    sed -i "s,^ACS_VERSION=.*,ACS_VERSION=%{_maventag},g" 
/usr/share/cloudstack-common/scripts/installer/cloudstack-help-text
 +    /usr/share/cloudstack-common/scripts/installer/cloudstack-help-text agent
 +fi
 +
 +%pre usage
 +id cloud > /dev/null 2>&1 || /usr/sbin/useradd -M -U -c "CloudStack 
unprivileged user" \
 +     -r -s /bin/sh -d %{_localstatedir}/cloudstack/management cloud|| true
 +
 +%preun usage
 +/sbin/service cloudstack-usage stop || true
 +if [ "$1" == "0" ] ; then
 +    /sbin/chkconfig --del cloudstack-usage > /dev/null 2>&1 || true
 +fi
 +
 +%post usage
 +if [ -f "%{_sysconfdir}/%{name}/management/db.properties" ]; then
 +    echo "Replacing usage server's db.properties with a link to the 
management server's db.properties"
 +    rm -f %{_sysconfdir}/%{name}/usage/db.properties
 +    ln -s %{_sysconfdir}/%{name}/management/db.properties 
%{_sysconfdir}/%{name}/usage/db.properties
 +    /usr/bin/systemctl enable cloudstack-usage > /dev/null 2>&1 || true
 +fi
 +
 +if [ -f "%{_sysconfdir}/%{name}/management/key" ]; then
 +    echo "Replacing usage server's key with a link to the management server's 
key"
 +    rm -f %{_sysconfdir}/%{name}/usage/key
 +    ln -s %{_sysconfdir}/%{name}/management/key 
%{_sysconfdir}/%{name}/usage/key
 +fi
 +
 +if [ ! -f "%{_sysconfdir}/%{name}/usage/key" ]; then
 +    ln -s %{_sysconfdir}/%{name}/management/key 
%{_sysconfdir}/%{name}/usage/key
 +fi
 +
 +mkdir -p /usr/local/libexec
 +if [ ! -f "/usr/local/libexec/sanity-check-last-id" ]; then
 +    echo 1 > /usr/local/libexec/sanity-check-last-id
 +fi
 +chown cloud:cloud /usr/local/libexec/sanity-check-last-id
 +
 +%posttrans usage
 +# Print help message
 +if [ -f "/usr/share/cloudstack-common/scripts/installer/cloudstack-help-text" 
];then
 +    sed -i "s,^ACS_VERSION=.*,ACS_VERSION=%{_maventag},g" 
/usr/share/cloudstack-common/scripts/installer/cloudstack-help-text
 +    /usr/share/cloudstack-common/scripts/installer/cloudstack-help-text usage
 +fi
 +
 +%post marvin
 +pip3 install --upgrade 
https://files.pythonhosted.org/packages/08/1f/42d74bae9dd6dcfec67c9ed0f3fa482b1ae5ac5f117ca82ab589ecb3ca19/mysql_connector_python-8.0.31-py2.py3-none-any.whl
 +pip3 install --upgrade /usr/share/cloudstack-marvin/Marvin-*.tar.gz
 +
 +#No default permission as the permission setup is complex
 +%files management
 +%defattr(-,root,root,-)
 +%dir %{_datadir}/%{name}-management
 +%dir %attr(0770,root,cloud) %{_localstatedir}/%{name}/mnt
 +%dir %attr(0770,cloud,cloud) %{_localstatedir}/%{name}/management
 +%dir %attr(0770,root,cloud) %{_localstatedir}/cache/%{name}/management
 +%dir %attr(0770,root,cloud) %{_localstatedir}/log/%{name}/management
 +%config(noreplace) %{_sysconfdir}/default/%{name}-management
 +%config(noreplace) %{_sysconfdir}/sudoers.d/%{name}-management
 +%config(noreplace) %{_sysconfdir}/security/limits.d/cloud
++%config(noreplace) %{_sysconfdir}/systemd/system/%{name}-management.service.d
 +%config(noreplace) %attr(0640,root,cloud) 
%{_sysconfdir}/%{name}/management/db.properties
 +%config(noreplace) %attr(0640,root,cloud) 
%{_sysconfdir}/%{name}/management/server.properties
 +%config(noreplace) %attr(0640,root,cloud) 
%{_sysconfdir}/%{name}/management/config.json
 +%config(noreplace) %{_sysconfdir}/%{name}/management/log4j-cloud.xml
 +%config(noreplace) %{_sysconfdir}/%{name}/management/log4j2.xml
 +%config(noreplace) %{_sysconfdir}/%{name}/management/environment.properties
 +%config(noreplace) %{_sysconfdir}/%{name}/management/java.security.ciphers
 +%config(noreplace) %attr(0644,root,root) 
%{_sysconfdir}/logrotate.d/%{name}-management
 +%attr(0644,root,root) %{_unitdir}/%{name}-management.service
 +%attr(0755,cloud,cloud) %{_localstatedir}/run/%{name}-management.pid
 +%attr(0755,root,root) %{_bindir}/%{name}-setup-management
 +%attr(0755,root,root) %{_bindir}/%{name}-update-xenserver-licenses
 +%{_datadir}/%{name}-management/conf
 +%{_datadir}/%{name}-management/lib/*.jar
 +%{_datadir}/%{name}-management/logs
 +%{_datadir}/%{name}-management/templates
 +%attr(0755,root,root) %{_bindir}/%{name}-setup-databases
 +%attr(0755,root,root) %{_bindir}/%{name}-migrate-databases
 +%attr(0755,root,root) %{_bindir}/%{name}-set-guest-password
 +%attr(0755,root,root) %{_bindir}/%{name}-set-guest-sshkey
 +%attr(0755,root,root) %{_bindir}/%{name}-sysvmadm
 +%attr(0755,root,root) %{_bindir}/%{name}-setup-encryption
 +%attr(0755,root,root) %{_bindir}/cmk
 +%{_datadir}/%{name}-management/setup/*.sql
 +%{_datadir}/%{name}-management/setup/*.sh
 +%{_datadir}/%{name}-management/setup/server-setup.xml
 +%{_datadir}/%{name}-management/webapp/*
 +%attr(0755,root,root) %{_bindir}/%{name}-external-ipallocator.py
 +%attr(0755,root,root) %{_initrddir}/%{name}-ipallocator
 +%dir %attr(0770,root,root) %{_localstatedir}/log/%{name}/ipallocator
 +%{_defaultdocdir}/%{name}-management-%{version}/LICENSE
 +%{_defaultdocdir}/%{name}-management-%{version}/NOTICE
 +%{_datadir}/%{name}-management/setup/wheel/*.whl
 +
 +%files agent
 +%attr(0755,root,root) %{_bindir}/%{name}-setup-agent
 +%attr(0755,root,root) %{_bindir}/%{name}-agent-upgrade
 +%attr(0755,root,root) %{_bindir}/%{name}-guest-tool
 +%attr(0755,root,root) %{_bindir}/%{name}-ssh
 +%attr(0644,root,root) %{_unitdir}/%{name}-agent.service
 +%attr(0644,root,root) %{_unitdir}/%{name}-rolling-maintenance@.service
 +%config(noreplace) %{_sysconfdir}/default/%{name}-agent
 +%attr(0644,root,root) %{_sysconfdir}/profile.d/%{name}-agent-profile.sh
 +%config(noreplace) %attr(0644,root,root) 
%{_sysconfdir}/logrotate.d/%{name}-agent
 +%attr(0755,root,root) %{_datadir}/%{name}-common/scripts/network/cisco
 +%config(noreplace) %{_sysconfdir}/%{name}/agent
 +%dir %{_localstatedir}/log/%{name}/agent
 +%attr(0644,root,root) %{_datadir}/%{name}-agent/lib/*.jar
 +%attr(0755,root,root) %{_datadir}/%{name}-agent/lib/libvirtqemuhook
 +%attr(0755,root,root) %{_datadir}/%{name}-agent/lib/rolling-maintenance
 +%dir %{_datadir}/%{name}-agent/plugins
 +%{_defaultdocdir}/%{name}-agent-%{version}/LICENSE
 +%{_defaultdocdir}/%{name}-agent-%{version}/NOTICE
 +
 +%files common
 +%dir %attr(0755,root,root) %{_datadir}/%{name}-common/python-site/cloudutils
 +%dir %attr(0755,root,root) %{_datadir}/%{name}-common/vms
 +%attr(0755,root,root) %{_datadir}/%{name}-common/scripts
 +%attr(0755,root,root) /usr/bin/cloudstack-sccs
 +%attr(0644, root, root) %{_datadir}/%{name}-common/vms/agent.zip
 +%attr(0644, root, root) %{_datadir}/%{name}-common/vms/cloud-scripts.tgz
 +%attr(0644, root, root) %{_datadir}/%{name}-common/vms/patch-sysvms.sh
 +%attr(0644,root,root) %{_datadir}/%{name}-common/python-site/cloud_utils.py
 +%attr(0644,root,root) %{_datadir}/%{name}-common/python-site/__pycache__/*
 +%attr(0644,root,root) %{_datadir}/%{name}-common/python-site/cloudutils/*
 +%attr(0644, root, root) %{_datadir}/%{name}-common/lib/jasypt-1.9.3.jar
 +%attr(0644, root, root) %{_datadir}/%{name}-common/lib/%{name}-utils.jar
 +%{_defaultdocdir}/%{name}-common-%{version}/LICENSE
 +%{_defaultdocdir}/%{name}-common-%{version}/NOTICE
 +
 +%files ui
 +%config(noreplace) %attr(0640,root,cloud) 
%{_sysconfdir}/%{name}/ui/config.json
 +%{_datadir}/%{name}-ui/*
 +%{_defaultdocdir}/%{name}-ui-%{version}/LICENSE
 +%{_defaultdocdir}/%{name}-ui-%{version}/NOTICE
 +
 +%files usage
 +%attr(0644,root,root) %{_unitdir}/%{name}-usage.service
 +%config(noreplace) %{_sysconfdir}/default/%{name}-usage
 +%config(noreplace) %attr(0644,root,root) 
%{_sysconfdir}/logrotate.d/%{name}-usage
 +%attr(0644,root,root) %{_datadir}/%{name}-usage/*.jar
 +%attr(0644,root,root) %{_datadir}/%{name}-usage/lib/*.jar
 +%dir %attr(0770,root,cloud) %{_localstatedir}/log/%{name}/usage
 +%attr(0644,root,root) %{_sysconfdir}/%{name}/usage/db.properties
 +%attr(0644,root,root) %{_sysconfdir}/%{name}/usage/log4j-cloud.xml
 +%{_defaultdocdir}/%{name}-usage-%{version}/LICENSE
 +%{_defaultdocdir}/%{name}-usage-%{version}/NOTICE
 +
 +%files marvin
 +%attr(0644,root,root) %{_datadir}/%{name}-marvin/Marvin*.tar.gz
 +%{_defaultdocdir}/%{name}-marvin-%{version}/LICENSE
 +%{_defaultdocdir}/%{name}-marvin-%{version}/NOTICE
 +
 +%files integration-tests
 +%attr(0755,root,root) %{_datadir}/%{name}-integration-tests/*
 +%{_defaultdocdir}/%{name}-integration-tests-%{version}/LICENSE
 +%{_defaultdocdir}/%{name}-integration-tests-%{version}/NOTICE
 +
 +%if "%{_ossnoss}" == "noredist"
 +%files mysql-ha
 +%defattr(0644,cloud,cloud,0755)
 +%attr(0644,root,root) %{_datadir}/%{name}-mysql-ha/lib/*
 +%endif
 +
 +%files baremetal-agent
 +%attr(0755,root,root) %{_bindir}/cloudstack-setup-baremetal
 +
 +%changelog
 +* Thu Dec 22 2022 Rohit Yadav <ro...@apache.org> 4.18.0
 +- Add support for EL9
 +
 +* Fri Oct 14 2022 Daan Hoogland <daan.hoogl...@gmail.com> 4.18.0
 +- initialising sanity check pointer file
 +
 +* Tue Jun 29 2021 David Jumani <dj.davidjumani1...@gmail.com> 4.16.0
 +- Adding SUSE 15 support
 +
 +* Thu Apr 30 2015 Rohit Yadav <bhais...@apache.org> 4.6.0
 +- Remove awsapi package
 +
 +* Wed Nov 19 2014 Hugo Trippaers <h...@apache.org> 4.6.0
 +- Create a specific spec for CentOS 7
 +
 +* Fri Jul 4 2014 Hugo Trippaers <h...@apache.org> 4.5.0
 +- Add a package for the mysql ha module
 +
 +* Fri Oct 5 2012 Hugo Trippaers <h...@apache.org> 4.1.0
 +- new style spec file
diff --cc packaging/el8/filelimit.conf
index 00000000000,7a8a835e3fe..7a8a835e3fe
mode 000000,100644..100644
--- a/packaging/el8/filelimit.conf
+++ b/packaging/el8/filelimit.conf
diff --cc 
plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java
index 7374d46edd6,f9d56f8301d..ca3395be5dc
--- 
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
@@@ -1031,7 -1016,7 +1031,7 @@@ public class LibvirtComputingResource e
  
          hostHealthCheckScriptPath = 
AgentPropertiesFileHandler.getPropertyValue(AgentProperties.HEALTH_CHECK_SCRIPT_PATH);
          if (StringUtils.isNotBlank(hostHealthCheckScriptPath) && !new 
File(hostHealthCheckScriptPath).exists()) {
-             logger.info(String.format("Unable to find the host health check 
script at: %s, " +
 -            s_logger.info(String.format("Unable to find the host health check 
script at: %s, " +
++            LOGGER.info(String.format("Unable to find the host health check 
script at: %s, " +
                      "discarding it", hostHealthCheckScriptPath));
          }
  
@@@ -2796,11 -2781,11 +2796,11 @@@
  
          if (hostCpuMaxCapacity > 0) {
              int updatedCpuShares = (int) Math.ceil((requestedCpuShares * 
CGROUP_V2_UPPER_LIMIT) / (double) hostCpuMaxCapacity);
-             logger.debug(String.format("This host utilizes cgroupv2 (as the 
max shares value is [%s]), thus, the VM requested shares of [%s] will be 
converted to " +
 -            s_logger.debug(String.format("This host utilizes cgroupv2 (as the 
max shares value is [%s]), thus, the VM requested shares of [%s] will be 
converted to " +
++            LOGGER.debug(String.format("This host utilizes cgroupv2 (as the 
max shares value is [%s]), thus, the VM requested shares of [%s] will be 
converted to " +
                      "consider the host limits; the new CPU shares value is 
[%s].", hostCpuMaxCapacity, requestedCpuShares, updatedCpuShares));
              return updatedCpuShares;
          }
-         logger.debug(String.format("This host does not have a maximum CPU 
shares set; therefore, this host utilizes cgroupv1 and the VM requested CPU 
shares [%s] will not be " +
 -        s_logger.debug(String.format("This host does not have a maximum CPU 
shares set; therefore, this host utilizes cgroupv1 and the VM requested CPU 
shares [%s] will not be " +
++        LOGGER.debug(String.format("This host does not have a maximum CPU 
shares set; therefore, this host utilizes cgroupv1 and the VM requested CPU 
shares [%s] will not be " +
                  "converted.", requestedCpuShares));
          return requestedCpuShares;
      }
@@@ -2926,12 -2909,12 +2926,12 @@@
      protected long getCurrentMemAccordingToMemBallooning(VirtualMachineTO 
vmTO, long maxRam) {
          long retVal = maxRam;
          if (noMemBalloon) {
 -            s_logger.warn(String.format("Setting VM's [%s] current memory as 
max memory [%s] due to memory ballooning is disabled. If you are using a custom 
service offering, verify if memory ballooning really should be disabled.", 
vmTO.toString(), maxRam));
 +            LOGGER.warn(String.format("Setting VM's [%s] current memory as 
max memory [%s] due to memory ballooning is disabled. If you are using a custom 
service offering, verify if memory ballooning really should be disabled.", 
vmTO.toString(), maxRam));
          } else if (vmTO != null && vmTO.getType() != 
VirtualMachine.Type.User) {
 -            s_logger.warn(String.format("Setting System VM's [%s] current 
memory as max memory [%s].", vmTO.toString(), maxRam));
 +            LOGGER.warn(String.format("Setting System VM's [%s] current 
memory as max memory [%s].", vmTO.toString(), maxRam));
          } else {
              long minRam = ByteScaleUtils.bytesToKibibytes(vmTO.getMinRam());
-             logger.debug(String.format("Setting VM's [%s] current memory as 
min memory [%s] due to memory ballooning is enabled.", vmTO.toString(), 
minRam));
 -            s_logger.debug(String.format("Setting VM's [%s] current memory as 
min memory [%s] due to memory ballooning is enabled.", vmTO.toString(), 
minRam));
++            LOGGER.debug(String.format("Setting VM's [%s] current memory as 
min memory [%s] due to memory ballooning is enabled.", vmTO.toString(), 
minRam));
              retVal = minRam;
          }
          return retVal;
@@@ -3283,7 -3260,7 +3284,7 @@@
       * (ii) Libvirt >= 6.3.0
       */
      public void setDiskIoDriver(DiskDef disk, IoDriverPolicy ioDriver) {
-         logger.debug(String.format("Disk IO driver policy [%s]. The host 
supports the io_uring policy [%s]", ioDriver, enableIoUring));
 -        s_logger.debug(String.format("Disk IO driver policy [%s]. The host 
supports the io_uring policy [%s]", ioDriver, enableIoUring));
++        LOGGER.debug(String.format("Disk IO driver policy [%s]. The host 
supports the io_uring policy [%s]", ioDriver, enableIoUring));
          if (ioDriver != null) {
              if (IoDriverPolicy.IO_URING != ioDriver) {
                  disk.setIoDriver(ioDriver);
@@@ -3426,13 -3403,15 +3427,15 @@@
          }
          if (configdrive != null) {
              try {
 -                s_logger.debug(String.format("Detaching ConfigDrive ISO of 
the VM %s, at path %s", vmName, configdrive.getDiskPath()));
++                LOGGER.debug(String.format("Detaching ConfigDrive ISO of the 
VM %s, at path %s", vmName, configdrive.getDiskPath()));
                  String result = attachOrDetachISO(conn, vmName, 
configdrive.getDiskPath(), false, CONFIG_DRIVE_ISO_DEVICE_ID);
                  if (result != null) {
-                     LOGGER.warn("Detach ConfigDrive ISO with result: " + 
result);
 -                    s_logger.warn(String.format("Detach ConfigDrive ISO of 
the VM %s, at path %s with %s: ", vmName, configdrive.getDiskPath(), result));
++                    LOGGER.warn("Detach ConfigDrive ISO of the VM {}, at path 
{} with result: {}", vmName, configdrive.getDiskPath(), result);
                  }
 -                s_logger.debug(String.format("Attaching ConfigDrive ISO of 
the VM %s, at path %s", vmName, configdrive.getDiskPath()));
++                LOGGER.debug(String.format("Attaching ConfigDrive ISO of the 
VM %s, at path %s", vmName, configdrive.getDiskPath()));
                  result = attachOrDetachISO(conn, vmName, 
configdrive.getDiskPath(), true, CONFIG_DRIVE_ISO_DEVICE_ID);
                  if (result != null) {
-                     LOGGER.warn("Attach ConfigDrive ISO with result: " + 
result);
 -                    s_logger.warn(String.format("Attach ConfigDrive ISO of 
the VM %s, at path %s with %s: ", vmName, configdrive.getDiskPath(), result));
++                    LOGGER.warn("Attach ConfigDrive ISO of the VM {}, at path 
{} with result: {}", vmName, configdrive.getDiskPath(), result);
                  }
              } catch (final LibvirtException | InternalErrorException | 
URISyntaxException e) {
                  final String msg = "Detach and attach ConfigDrive ISO failed 
due to " + e.toString();
@@@ -3640,19 -3619,19 +3647,19 @@@
       */
      private HealthCheckResult getHostHealthCheckResult() {
          if (StringUtils.isBlank(hostHealthCheckScriptPath)) {
-             logger.debug("Host health check script path is not specified");
 -            s_logger.debug("Host health check script path is not specified");
++            LOGGER.debug("Host health check script path is not specified");
              return HealthCheckResult.IGNORE;
          }
          File script = new File(hostHealthCheckScriptPath);
          if (!script.exists() || !script.isFile() || !script.canExecute()) {
-             logger.warn(String.format("The host health check script file set 
at: %s cannot be executed, " +
 -            s_logger.warn(String.format("The host health check script file 
set at: %s cannot be executed, " +
++            LOGGER.warn(String.format("The host health check script file set 
at: %s cannot be executed, " +
                              "reason: %s", hostHealthCheckScriptPath,
                      !script.exists() ? "file does not exist" : "please check 
file permissions to execute this file"));
              return HealthCheckResult.IGNORE;
          }
          int exitCode = 
executeBashScriptAndRetrieveExitValue(hostHealthCheckScriptPath);
-         if (logger.isDebugEnabled()) {
-             logger.debug(String.format("Host health check script exit code: 
%s", exitCode));
 -        if (s_logger.isDebugEnabled()) {
 -            s_logger.debug(String.format("Host health check script exit code: 
%s", exitCode));
++        if (LOGGER.isDebugEnabled()) {
++            LOGGER.debug(String.format("Host health check script exit code: 
%s", exitCode));
          }
          return retrieveHealthCheckResultFromExitCode(exitCode);
      }
@@@ -3761,17 -3724,17 +3768,17 @@@
       */
      protected void calculateHostCpuMaxCapacity(int cpuCores, Long cpuSpeed) {
          String output = 
Script.runSimpleBashScript(COMMAND_GET_CGROUP_HOST_VERSION);
-         logger.info(String.format("Host uses control group [%s].", output));
 -        s_logger.info(String.format("Host uses control group [%s].", output));
++        LOGGER.info(String.format("Host uses control group [%s].", output));
  
          if (!CGROUP_V2.equals(output)) {
-             logger.info(String.format("Setting host CPU max capacity to 0, as 
it uses cgroup v1.", getHostCpuMaxCapacity()));
 -            s_logger.info(String.format("Setting host CPU max capacity to 0, 
as it uses cgroup v1.", getHostCpuMaxCapacity()));
++            LOGGER.info(String.format("Setting host CPU max capacity to 0, as 
it uses cgroup v1.", getHostCpuMaxCapacity()));
              setHostCpuMaxCapacity(0);
              return;
          }
  
-         logger.info(String.format("Calculating the max shares of the host."));
 -        s_logger.info(String.format("Calculating the max shares of the 
host."));
++        LOGGER.info(String.format("Calculating the max shares of the host."));
          setHostCpuMaxCapacity(cpuCores * cpuSpeed.intValue());
-         logger.info(String.format("The max shares of the host is [%d].", 
getHostCpuMaxCapacity()));
 -        s_logger.info(String.format("The max shares of the host is [%d].", 
getHostCpuMaxCapacity()));
++        LOGGER.info(String.format("The max shares of the host is [%d].", 
getHostCpuMaxCapacity()));
      }
  
      private StartupStorageCommand createLocalStoragePool(String 
localStoragePath, String localStorageUUID, StartupRoutingCommand cmd) {
@@@ -3834,7 -3797,7 +3841,7 @@@
          String sourcePath = null;
          try {
              String mountResult = Script.runSimpleBashScript("mount | grep \"" 
+ diskPath + "\"");
-             logger.debug("Got mount result for " + diskPath + "\n\n" + 
mountResult);
 -            s_logger.debug("Got mount result for " + diskPath + "\n\n" + 
mountResult);
++            LOGGER.debug("Got mount result for " + diskPath + "\n\n" + 
mountResult);
              if (StringUtils.isNotEmpty(mountResult)) {
                  String[] res = mountResult.strip().split(" ");
                  if (res[0].contains(":")) {
@@@ -3851,7 -3814,7 +3858,7 @@@
                  return new Pair<>(sourceHostIp, sourcePath);
              }
          } catch (Exception ex) {
-             logger.warn("Failed to list source host and IP for " + diskPath + 
ex.toString());
 -            s_logger.warn("Failed to list source host and IP for " + diskPath 
+ ex.toString());
++            LOGGER.warn("Failed to list source host and IP for " + diskPath + 
ex.toString());
          }
          return null;
      }
@@@ -3864,14 -3827,14 +3871,14 @@@
                  domainNames.add(names[i]);
              }
          } catch (final LibvirtException e) {
-             logger.warn("Failed to list defined domains", e);
 -            s_logger.warn("Failed to list defined domains", e);
++            LOGGER.warn("Failed to list defined domains", e);
          }
  
          int[] ids = null;
          try {
              ids = conn.listDomains();
          } catch (final LibvirtException e) {
-             logger.warn("Failed to list domains", e);
 -            s_logger.warn("Failed to list domains", e);
++            LOGGER.warn("Failed to list domains", e);
              return domainNames;
          }
  
@@@ -4959,7 -4862,7 +4966,7 @@@
  
      public boolean setupTungstenVRouter(final String oper, final String inf, 
final String subnet, final String route,
          final String vrf) {
-         final Script cmd = new Script(setupTungstenVrouterPath, timeout, 
logger);
 -        final Script cmd = new Script(setupTungstenVrouterPath, timeout, 
s_logger);
++        final Script cmd = new Script(setupTungstenVrouterPath, timeout, 
LOGGER);
          cmd.add(oper);
          cmd.add(inf);
          cmd.add(subnet);
@@@ -4972,7 -4875,7 +4979,7 @@@
  
      public boolean updateTungstenLoadbalancerStats(final String lbUuid, final 
String lbStatsPort,
          final String lbStatsUri, final String lbStatsAuth) {
-         final Script cmd = new Script(updateTungstenLoadbalancerStatsPath, 
timeout, logger);
 -        final Script cmd = new Script(updateTungstenLoadbalancerStatsPath, 
timeout, s_logger);
++        final Script cmd = new Script(updateTungstenLoadbalancerStatsPath, 
timeout, LOGGER);
          cmd.add(lbUuid);
          cmd.add(lbStatsPort);
          cmd.add(lbStatsUri);
@@@ -4984,7 -4887,7 +4991,7 @@@
  
      public boolean updateTungstenLoadbalancerSsl(final String lbUuid, final 
String sslCertName,
          final String certificateKey, final String privateKey, final String 
privateIp, final String port) {
-         final Script cmd = new Script(updateTungstenLoadbalancerSslPath, 
timeout, logger);
 -        final Script cmd = new Script(updateTungstenLoadbalancerSslPath, 
timeout, s_logger);
++        final Script cmd = new Script(updateTungstenLoadbalancerSslPath, 
timeout, LOGGER);
          cmd.add(lbUuid);
          cmd.add(sslCertName);
          cmd.add(certificateKey);
@@@ -4997,7 -4900,7 +5004,7 @@@
      }
  
      public boolean setupTfRoute(final String privateIpAddress, final String 
fromNetwork, final String toNetwork) {
-         final Script setupTfRouteScript = new Script(routerProxyPath, 
timeout, logger);
 -        final Script setupTfRouteScript = new Script(routerProxyPath, 
timeout, s_logger);
++        final Script setupTfRouteScript = new Script(routerProxyPath, 
timeout, LOGGER);
          setupTfRouteScript.add("setup_tf_route.py");
          setupTfRouteScript.add(privateIpAddress);
          setupTfRouteScript.add(fromNetwork);
@@@ -5006,7 -4909,7 +5013,7 @@@
          final OutputInterpreter.OneLineParser setupTfRouteParser = new 
OutputInterpreter.OneLineParser();
          final String result = setupTfRouteScript.execute(setupTfRouteParser);
          if (result != null) {
-             logger.debug("Failed to execute setup TF Route:" + result);
 -            s_logger.debug("Failed to execute setup TF Route:" + result);
++            LOGGER.debug("Failed to execute setup TF Route:" + result);
              return false;
          }
          return true;
@@@ -5525,7 -5411,7 +5532,7 @@@
                      
interfaceDef.setMultiQueueNumber(nicMultiqueueNumberInteger);
                  }
              } catch (NumberFormatException ex) {
-                 logger.warn(String.format("VM details %s is not a valid 
integer value %s", VmDetailConstants.NIC_MULTIQUEUE_NUMBER, 
nicMultiqueueNumber));
 -                s_logger.warn(String.format("VM details %s is not a valid 
integer value %s", VmDetailConstants.NIC_MULTIQUEUE_NUMBER, 
nicMultiqueueNumber));
++                LOGGER.warn(String.format("VM details %s is not a valid 
integer value %s", VmDetailConstants.NIC_MULTIQUEUE_NUMBER, 
nicMultiqueueNumber));
              }
          }
          String nicPackedEnabled = 
details.get(VmDetailConstants.NIC_PACKED_VIRTQUEUES_ENABLED);
@@@ -5533,7 -5419,7 +5540,7 @@@
              try {
                  
interfaceDef.setPackedVirtQueues(Boolean.valueOf(nicPackedEnabled));
              } catch (NumberFormatException ex) {
-                 logger.warn(String.format("VM details %s is not a valid 
Boolean value %s", VmDetailConstants.NIC_PACKED_VIRTQUEUES_ENABLED, 
nicPackedEnabled));
 -                s_logger.warn(String.format("VM details %s is not a valid 
Boolean value %s", VmDetailConstants.NIC_PACKED_VIRTQUEUES_ENABLED, 
nicPackedEnabled));
++                LOGGER.warn(String.format("VM details %s is not a valid 
Boolean value %s", VmDetailConstants.NIC_PACKED_VIRTQUEUES_ENABLED, 
nicPackedEnabled));
              }
          }
      }
@@@ -5548,11 -5434,11 +5555,11 @@@
              command.append(remoteFile);
              command.append(" " + tmpPath);
              command.append(outputFile);
-             logger.debug(String.format("Converting remote disk file: %s, 
output file: %s%s (timeout: %d secs)", remoteFile, tmpPath, outputFile, 
timeoutInSecs));
 -            s_logger.debug(String.format("Converting remote disk file: %s, 
output file: %s%s (timeout: %d secs)", remoteFile, tmpPath, outputFile, 
timeoutInSecs));
++            LOGGER.debug(String.format("Converting remote disk file: %s, 
output file: %s%s (timeout: %d secs)", remoteFile, tmpPath, outputFile, 
timeoutInSecs));
              SshHelper.sshExecute(srcIp, 22, username, null, password, 
command.toString(), timeoutInSecs * 1000);
-             logger.debug("Copying converted remote disk file " + outputFile + 
" to: " + localDir);
 -            s_logger.debug("Copying converted remote disk file " + outputFile 
+ " to: " + localDir);
++            LOGGER.debug("Copying converted remote disk file " + outputFile + 
" to: " + localDir);
              SshHelper.scpFrom(srcIp, 22, username, null, password, localDir, 
tmpPath + outputFile);
-             logger.debug("Successfully copied converted remote disk file to: 
" + localDir + "/" + outputFile);
 -            s_logger.debug("Successfully copied converted remote disk file 
to: " + localDir + "/" + outputFile);
++            LOGGER.debug("Successfully copied converted remote disk file to: 
" + localDir + "/" + outputFile);
              return outputFile;
          } catch (Exception e) {
              try {
diff --cc 
plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/IscsiAdmStorageAdaptor.java
index 09cdad64ace,9288ca2750c..6185c69032f
--- 
a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/IscsiAdmStorageAdaptor.java
+++ 
b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/IscsiAdmStorageAdaptor.java
@@@ -84,9 -79,9 +84,9 @@@ public class IscsiAdmStorageAdaptor imp
      }
  
      @Override
-     public boolean connectPhysicalDisk(String volumeUuid, KVMStoragePool 
pool, Map<String, String> details) {
+     public boolean connectPhysicalDisk(String volumeUuid, KVMStoragePool 
pool, Map<String, String> details, boolean isVMMigrate) {
          // ex. sudo iscsiadm -m node -T iqn.2012-03.com.test:volume1 -p 
192.168.233.10:3260 -o new
 -        Script iScsiAdmCmd = new Script(true, "iscsiadm", 0, s_logger);
 +        Script iScsiAdmCmd = new Script(true, "iscsiadm", 0, logger);
  
          iScsiAdmCmd.add("-m", "node");
          iScsiAdmCmd.add("-T", getIqn(volumeUuid));
diff --cc 
plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStoragePoolManager.java
index 4e76030d06f,2bd068b6c8f..e27547acbb2
--- 
a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStoragePoolManager.java
+++ 
b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStoragePoolManager.java
@@@ -187,10 -159,10 +187,10 @@@ public class KVMStoragePoolManager 
              KVMStoragePool pool = getStoragePool(store.getPoolType(), 
store.getUuid());
              StorageAdaptor adaptor = getStorageAdaptor(pool.getType());
  
-             result = adaptor.connectPhysicalDisk(vol.getPath(), pool, 
disk.getDetails());
+             result = adaptor.connectPhysicalDisk(vol.getPath(), pool, 
disk.getDetails(), isVMMigrate);
  
              if (!result) {
 -                s_logger.error("Failed to connect disks via vm spec for vm: " 
+ vmName + " volume:" + vol.toString());
 +                logger.error("Failed to connect disks via vm spec for vm: " + 
vmName + " volume:" + vol.toString());
                  return result;
              }
          }
@@@ -315,6 -287,7 +315,7 @@@
          URI storageUri = null;
  
          try {
 -            s_logger.debug("Get storage pool by uri: " + uri);
++            logger.debug("Get storage pool by uri: " + uri);
              storageUri = new URI(uri);
          } catch (URISyntaxException e) {
              throw new CloudRuntimeException(e.toString());
diff --cc 
plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/ScaleIOStorageAdaptor.java
index 7477d768e9a,ab9533c075e..335ea0d03d2
--- 
a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/ScaleIOStorageAdaptor.java
+++ 
b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/ScaleIOStorageAdaptor.java
@@@ -224,9 -221,9 +224,9 @@@ public class ScaleIOStorageAdaptor impl
      }
  
      @Override
-     public boolean connectPhysicalDisk(String volumePath, KVMStoragePool 
pool, Map<String, String> details) {
+     public boolean connectPhysicalDisk(String volumePath, KVMStoragePool 
pool, Map<String, String> details, boolean isMigration) {
          if (StringUtils.isEmpty(volumePath) || pool == null) {
 -            LOGGER.error("Unable to connect physical disk due to insufficient 
data");
 +            logger.error("Unable to connect physical disk due to insufficient 
data");
              throw new CloudRuntimeException("Unable to connect physical disk 
due to insufficient data");
          }
  
diff --cc 
plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixGetVmIpAddressCommandWrapper.java
index a324ec1bdad,e03708faf86..dceeec17fb3
--- 
a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixGetVmIpAddressCommandWrapper.java
+++ 
b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixGetVmIpAddressCommandWrapper.java
@@@ -61,17 -63,16 +61,17 @@@ public final class CitrixGetVmIpAddress
              }
  
              if (vmIp != null) {
-                 logger.debug("VM " +vmName + " ip address got retrieved 
"+vmIp);
 -                s_logger.debug("VM " + vmName + " IP address got retrieved " 
+ vmIp);
++                logger.debug("VM {} ip address got retrieved {}", vmName, 
vmIp);
                  result = true;
                  return new Answer(command, result, vmIp);
              }
 +
-         }catch (Types.XenAPIException e) {
-             logger.debug("Got exception in GetVmIpAddressCommand "+ 
e.getMessage());
-             errorMsg = "Failed to retrived vm ip addr, exception: 
"+e.getMessage();
-         }catch (XmlRpcException e) {
-             logger.debug("Got exception in GetVmIpAddressCommand "+ 
e.getMessage());
-             errorMsg = "Failed to retrived vm ip addr, exception: 
"+e.getMessage();
+         } catch (Types.XenAPIException e) {
 -            s_logger.debug("Got exception in GetVmIpAddressCommand " + 
e.getMessage());
 -            errorMsg = "Failed to retrieve vm ip addr, exception: " + 
e.getMessage();
++            logger.debug("Got exception in GetVmIpAddressCommand " + 
e.getMessage());
++            errorMsg = "Failed to retrived vm ip addr, exception: " + 
e.getMessage();
+         } catch (XmlRpcException e) {
 -            s_logger.debug("Got exception in GetVmIpAddressCommand " + 
e.getMessage());
 -            errorMsg = "Failed to retrieve vm ip addr, exception: " + 
e.getMessage();
++            logger.debug("Got exception in GetVmIpAddressCommand " + 
e.getMessage());
++            errorMsg = "Failed to retrived vm ip addr, exception: " + 
e.getMessage();
          }
  
          return new Answer(command, result, errorMsg);
diff --cc 
plugins/storage/volume/linstor/src/main/java/com/cloud/hypervisor/kvm/storage/LinstorStorageAdaptor.java
index 8d99af0dd20,9b7a376e8f2..292e939de49
--- 
a/plugins/storage/volume/linstor/src/main/java/com/cloud/hypervisor/kvm/storage/LinstorStorageAdaptor.java
+++ 
b/plugins/storage/volume/linstor/src/main/java/com/cloud/hypervisor/kvm/storage/LinstorStorageAdaptor.java
@@@ -277,6 -274,7 +278,7 @@@ public class LinstorStorageAdaptor impl
       * @throws ApiException if any problem connecting to the Linstor 
controller
       */
      private void allow2PrimariesIfInUse(DevelopersApi api, String rscName) 
throws ApiException {
 -        s_logger.debug("enabling allow-two-primaries");
++        logger.debug("enabling allow-two-primaries");
          String inUseNode = LinstorUtil.isResourceInUse(api, rscName);
          if (inUseNode != null && !inUseNode.equalsIgnoreCase(localNodeName)) {
              // allow 2 primaries for live migration, should be removed by 
disconnect on the other end
@@@ -292,11 -290,12 +294,12 @@@
      }
  
      @Override
-     public boolean connectPhysicalDisk(String volumePath, KVMStoragePool 
pool, Map<String, String> details)
+     public boolean connectPhysicalDisk(
+             String volumePath, KVMStoragePool pool, Map<String, String> 
details, boolean isVMMigration)
      {
 -        s_logger.debug(String.format("Linstor: connectPhysicalDisk %s:%s -> 
%s", pool.getUuid(), volumePath, details));
 +        logger.debug("Linstor: connectPhysicalDisk {}:{} -> {}", 
pool.getUuid(), volumePath, details);
          if (volumePath == null) {
 -            s_logger.warn("volumePath is null, ignoring");
 +            logger.warn("volumePath is null, ignoring");
              return false;
          }
  
@@@ -315,12 -314,13 +318,13 @@@
              throw new CloudRuntimeException(apiEx.getBestMessage(), apiEx);
          }
  
-         try
-         {
-             allow2PrimariesIfInUse(api, rscName);
-         } catch (ApiException apiEx) {
-             logger.error(apiEx);
-             // do not fail here as adding allow-two-primaries property is 
only a problem while live migrating
+         if (isVMMigration) {
+             try {
+                 allow2PrimariesIfInUse(api, rscName);
+             } catch (ApiException apiEx) {
 -                s_logger.error(apiEx);
++                logger.error(apiEx);
+                 // do not fail here as adding allow-two-primaries property is 
only a problem while live migrating
+             }
          }
          return true;
      }
@@@ -716,4 -716,19 +720,19 @@@
              throw new CloudRuntimeException(apiEx.getBestMessage(), apiEx);
          }
      }
+ 
+     public boolean isNodeOnline(LinstorStoragePool pool, String nodeName) {
+         DevelopersApi linstorApi = getLinstorAPI(pool);
+         try {
+             List<Node> node = 
linstorApi.nodeList(Collections.singletonList(nodeName), 
Collections.emptyList(), null, null);
+             if (node == null || node.isEmpty()) {
+                 return false;
+             }
+ 
+             return 
Node.ConnectionStatusEnum.ONLINE.equals(node.get(0).getConnectionStatus());
+         } catch (ApiException apiEx) {
 -            s_logger.error(apiEx.getMessage());
++            logger.error(apiEx.getMessage());
+             throw new CloudRuntimeException(apiEx.getBestMessage(), apiEx);
+         }
+     }
  }
diff --cc 
plugins/storage/volume/linstor/src/main/java/com/cloud/hypervisor/kvm/storage/LinstorStoragePool.java
index 2d6801049a3,3907bae7f79..bb354bec9b4
--- 
a/plugins/storage/volume/linstor/src/main/java/com/cloud/hypervisor/kvm/storage/LinstorStoragePool.java
+++ 
b/plugins/storage/volume/linstor/src/main/java/com/cloud/hypervisor/kvm/storage/LinstorStoragePool.java
@@@ -294,8 -311,20 +312,20 @@@ public class LinstorStoragePool impleme
                  }
              }
          }
-         LOGGER.warn(String.format("checkDrbdSetupStatusOutput: no resource 
connected to %s.", otherNodeName));
-         return false;
+         boolean otherNodeOnline = false;
+         if (connectionFound) {
 -            s_logger.warn(String.format(
++            LOGGER.warn(String.format(
+                     "checkingHeartBeat: connection found, but not in state 
'Connected' to %s", otherNodeName));
+         } else {
 -            s_logger.warn(String.format(
++            LOGGER.warn(String.format(
+                     "checkingHeartBeat: no resource connected to %s, checking 
LINSTOR", otherNodeName));
+             otherNodeOnline = checkLinstorNodeOnline(otherNodeName);
+         }
 -        s_logger.info(String.format(
++        LOGGER.info(String.format(
+                 "checkingHeartBeat: other node %s is %s.",
+                 otherNodeName,
+                 otherNodeOnline ? "online on controller" : "down"));
+         return otherNodeOnline;
      }
  
      private String executeDrbdEventsNow(OutputInterpreter.AllLinesParser 
parser) {
diff --cc 
plugins/storage/volume/storpool/src/main/java/com/cloud/hypervisor/kvm/storage/StorPoolStorageAdaptor.java
index de3886f6294,4091be10470..d68e9cbd110
--- 
a/plugins/storage/volume/storpool/src/main/java/com/cloud/hypervisor/kvm/storage/StorPoolStorageAdaptor.java
+++ 
b/plugins/storage/volume/storpool/src/main/java/com/cloud/hypervisor/kvm/storage/StorPoolStorageAdaptor.java
@@@ -249,10 -244,10 +249,10 @@@ public class StorPoolStorageAdaptor imp
      }
  
      @Override
-     public boolean connectPhysicalDisk(String volumeUuid, KVMStoragePool 
pool, Map<String, String> details) {
+     public boolean connectPhysicalDisk(String volumeUuid, KVMStoragePool 
pool, Map<String, String> details, boolean isVMMigrate) {
          SP_LOG("StorPoolStorageAdaptor.connectPhysicalDisk: uuid=%s, 
pool=%s", volumeUuid, pool);
  
 -        log.debug(String.format("connectPhysicalDisk: uuid=%s, pool=%s", 
volumeUuid, pool));
 +        LOGGER.debug(String.format("connectPhysicalDisk: uuid=%s, pool=%s", 
volumeUuid, pool));
  
          return attachOrDetachVolume("attach", "volume", volumeUuid);
      }
diff --cc 
server/src/main/java/com/cloud/network/element/ConfigDriveNetworkElement.java
index 3449f1f5d00,38d71b9c507..5d468d95e4c
--- 
a/server/src/main/java/com/cloud/network/element/ConfigDriveNetworkElement.java
+++ 
b/server/src/main/java/com/cloud/network/element/ConfigDriveNetworkElement.java
@@@ -345,19 -341,16 +345,19 @@@ public class ConfigDriveNetworkElement 
              try {
                  if (isConfigDriveIsoOnHostCache(vm.getId())) {
                      vm.setConfigDriveLocation(Location.HOST);
-                     configureConfigDriveData(vm, nic, dest);
- 
-                     // Create the config drive on dest host cache
-                     createConfigDriveIsoOnHostCache(nic, vm, 
dest.getHost().getId());
+                     if (configureConfigDriveData(vm, nic, dest)) {
+                         // Create the config drive on dest host cache
+                         createConfigDriveIsoOnHostCache(vm, 
dest.getHost().getId());
+                     }
                  } else {
                      
vm.setConfigDriveLocation(getConfigDriveLocation(vm.getId()));
 -                    addPasswordAndUserdata(network, nic, vm, dest, context);
 +                    boolean result = addPasswordAndUserdata(network, nic, vm, 
dest, context);
 +                    if (result) {
 +                        createConfigDriveIso(nic, vm, dest, null);
 +                    }
                  }
              } catch (InsufficientCapacityException | 
ResourceUnavailableException e) {
 -                LOG.error("Failed to add config disk drive due to: ", e);
 +                logger.error("Failed to add config disk drive due to: ", e);
                  return false;
              }
          }
@@@ -549,9 -553,7 +560,9 @@@
  
          final String isoFileName = 
ConfigDrive.configIsoFileName(profile.getInstanceName());
          final String isoPath = 
ConfigDrive.createConfigDrivePath(profile.getInstanceName());
-         List<NicProfile> nicProfiles = 
_networkOrchestrationService.getNicProfiles(nic.getVirtualMachineId(), 
profile.getHypervisorType());
 -        final String isoData = 
ConfigDriveBuilder.buildConfigDrive(profile.getVmData(), isoFileName, 
profile.getConfigDriveLabel(), customUserdataParamMap);
++        List<NicProfile> nicProfiles = 
_networkOrchestrationService.getNicProfiles(profile.getVirtualMachine().getId(),
 profile.getHypervisorType());
 +        final Map<Long, List<Service>> supportedServices = 
getSupportedServicesByElementForNetwork(nicProfiles);
 +        final String isoData = 
ConfigDriveBuilder.buildConfigDrive(nicProfiles, profile.getVmData(), 
isoFileName, profile.getConfigDriveLabel(), customUserdataParamMap, 
supportedServices);
          final HandleConfigDriveIsoCommand configDriveIsoCommand = new 
HandleConfigDriveIsoCommand(isoPath, isoData, null, false, true, true);
  
          final HandleConfigDriveIsoAnswer answer = 
(HandleConfigDriveIsoAnswer) agentManager.easySend(hostId, 
configDriveIsoCommand);
diff --cc server/src/main/java/com/cloud/vm/UserVmManagerImpl.java
index 04b64dd80a3,94034da4c8f..ce2e5585a09
--- a/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java
+++ b/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java
@@@ -766,7 -773,7 +764,7 @@@ public class UserVmManagerImpl extends 
              boolean decrementCount = true;
  
              try {
-                 logger.debug("Trying for vm "+ vmId +" nic Id "+nicId +" ip 
retrieval ...");
 -                s_logger.debug(String.format("Trying IP retrieval for VM %s 
(%d), nic Id %d", vmName, vmId, nicId));
++                logger.debug("Trying IP retrieval for VM {} ({}), nic Id {}", 
vmName, vmId, nicId);
                  Answer answer = _agentMgr.send(hostId, cmd);
                  NicVO nic = _nicDao.findById(nicId);
                  if (answer.getResult()) {
@@@ -777,7 -784,7 +775,7 @@@
                          if (nic != null) {
                              nic.setIPv4Address(vmIp);
                              _nicDao.update(nicId, nic);
-                             logger.debug("Vm "+ vmId +" IP "+vmIp +" got 
retrieved successfully");
 -                            s_logger.debug(String.format("VM %s (%d) - IP %s 
retrieved successfully", vmName, vmId, vmIp));
++                            logger.debug("VM {} ({}) - IP {} retrieved 
successfully", vmName, vmId, vmIp);
                              vmIdCountMap.remove(nicId);
                              decrementCount = false;
                              ActionEventUtils.onActionEvent(User.UID_SYSTEM, 
Account.ACCOUNT_ID_SYSTEM,
@@@ -793,7 -800,7 +791,7 @@@
                          _nicDao.update(nicId, nic);
                      }
                      if (answer.getDetails() != null) {
-                         logger.debug("Failed to get vm ip for Vm "+ vmId + 
answer.getDetails());
 -                        s_logger.debug(String.format("Failed to get IP for VM 
%s (%d), details: %s", vmName, vmId, answer.getDetails()));
++                        logger.debug("Failed to get vm ip for Vm {} ({}), 
details: {}", vmName, vmId, answer.getDetails());
                      }
                  }
              } catch (OperationTimedoutException e) {
@@@ -804,7 -811,7 +802,7 @@@
                  if (decrementCount) {
                      VmAndCountDetails vmAndCount = vmIdCountMap.get(nicId);
                      vmAndCount.decrementCount();
-                     logger.debug("Ip is not retrieved for VM " + vmId +" nic 
"+nicId + " ... decremented count to "+vmAndCount.getRetrievalCount());
 -                    s_logger.debug(String.format("IP is not retrieved for VM 
%s (%d), nic %d ... decremented count to %d", vmName, vmId, nicId, 
vmAndCount.getRetrievalCount()));
++                    logger.debug("Ip is not retrieved for VM {} ({}) nic {} 
... decremented count to {}", vmName, vmId, nicId, 
vmAndCount.getRetrievalCount());
                      vmIdCountMap.put(nicId, vmAndCount);
                  }
              }
diff --cc server/src/test/java/com/cloud/user/AccountManagerImplTest.java
index 645c9e5aa67,ed0a123d4a3..3f66c6017a4
--- a/server/src/test/java/com/cloud/user/AccountManagerImplTest.java
+++ b/server/src/test/java/com/cloud/user/AccountManagerImplTest.java
@@@ -26,12 -26,11 +26,15 @@@ import java.util.HashMap
  import java.util.List;
  import java.util.Map;
  
 +import com.cloud.event.ActionEventUtils;
++
+ import org.apache.cloudstack.acl.ControlledEntity;
+ import org.apache.cloudstack.acl.Role;
+ import org.apache.cloudstack.acl.RoleService;
+ import org.apache.cloudstack.acl.RoleType;
  import org.apache.cloudstack.acl.SecurityChecker.AccessType;
 +import org.apache.cloudstack.api.command.admin.account.UpdateAccountCmd;
 +import org.apache.cloudstack.api.command.admin.user.DeleteUserCmd;
- 
- import org.apache.cloudstack.acl.ControlledEntity;
  import org.apache.cloudstack.api.command.admin.user.GetUserKeysCmd;
  import org.apache.cloudstack.api.command.admin.user.UpdateUserCmd;
  import 
org.apache.cloudstack.api.response.UserTwoFactorAuthenticationSetupResponse;
@@@ -47,11 -45,9 +50,12 @@@ import org.junit.Test
  import org.junit.runner.RunWith;
  import org.mockito.InOrder;
  import org.mockito.Mock;
 +import org.mockito.MockedStatic;
  import org.mockito.Mockito;
  import org.mockito.junit.MockitoJUnitRunner;
+ 
 +import org.springframework.beans.factory.NoSuchBeanDefinitionException;
 +
  import com.cloud.acl.DomainChecker;
  import com.cloud.api.auth.SetupUserTwoFactorAuthenticationCmd;
  import com.cloud.domain.Domain;
@@@ -1207,22 -1084,120 +1213,130 @@@ public class AccountManagerImplTest ext
      }
  
      @Test
 -    public void deleteAndCleanupUserTestRemovesUserFromProjects() {
 -        long userId = userVoMock.getId();
 -        
Mockito.doNothing().when(_projectAccountDao).removeUserFromProjects(userId);
 -
 -        accountManagerImpl.deleteAndCleanupUser(userVoMock);
 +    public void testDeleteWebhooksForAccount() {
 +        try (MockedStatic<ComponentContext> mockedComponentContext = 
Mockito.mockStatic(ComponentContext.class)) {
 +            WebhookHelper webhookHelper = Mockito.mock(WebhookHelper.class);
 +            
Mockito.doNothing().when(webhookHelper).deleteWebhooksForAccount(Mockito.anyLong());
 +            mockedComponentContext.when(() -> 
ComponentContext.getDelegateComponentOfType(WebhookHelper.class))
 +                    .thenReturn(webhookHelper);
 +            accountManagerImpl.deleteWebhooksForAccount(1L);
 +        }
 +    }
  
 -        Mockito.verify(_projectAccountDao).removeUserFromProjects(userId);
 +    @Test
 +    public void testDeleteWebhooksForAccountNoBean() {
 +        try (MockedStatic<ComponentContext> mockedComponentContext = 
Mockito.mockStatic(ComponentContext.class)) {
 +            mockedComponentContext.when(() -> 
ComponentContext.getDelegateComponentOfType(WebhookHelper.class))
 +                    .thenThrow(NoSuchBeanDefinitionException.class);
 +            accountManagerImpl.deleteWebhooksForAccount(1L);
 +        }
      }
+ 
+     @Test(expected = PermissionDeniedException.class)
+     public void testValidateRoleChangeUnknownCaller() {
+         Account account = Mockito.mock(Account.class);
+         Mockito.when(account.getRoleId()).thenReturn(1L);
+         Role role = Mockito.mock(Role.class);
+         Mockito.when(role.getRoleType()).thenReturn(RoleType.Unknown);
+         Account caller = Mockito.mock(Account.class);
+         Mockito.when(caller.getRoleId()).thenReturn(2L);
+         Mockito.when(roleService.findRole(2L)).thenReturn(role);
+         accountManagerImpl.validateRoleChange(account, 
Mockito.mock(Role.class), caller);
+     }
+ 
+     @Test(expected = PermissionDeniedException.class)
+     public void testValidateRoleChangeUnknownNewRole() {
+         Account account = Mockito.mock(Account.class);
+         Mockito.when(account.getRoleId()).thenReturn(1L);
+         Role newRole = Mockito.mock(Role.class);
+         Mockito.when(newRole.getRoleType()).thenReturn(RoleType.Unknown);
+         Role callerRole = Mockito.mock(Role.class);
+         
Mockito.when(callerRole.getRoleType()).thenReturn(RoleType.DomainAdmin);
+         Account caller = Mockito.mock(Account.class);
+         Mockito.when(caller.getRoleId()).thenReturn(2L);
+         Mockito.when(roleService.findRole(2L)).thenReturn(callerRole);
+         accountManagerImpl.validateRoleChange(account, newRole, caller);
+     }
+ 
+     @Test
+     public void testValidateRoleNewRoleSameCaller() {
+         Account account = Mockito.mock(Account.class);
+         Mockito.when(account.getRoleId()).thenReturn(1L);
+         Role currentRole = Mockito.mock(Role.class);
+         Mockito.when(currentRole.getRoleType()).thenReturn(RoleType.User);
+         Mockito.when(roleService.findRole(1L)).thenReturn(currentRole);
+         Role newRole = Mockito.mock(Role.class);
+         Mockito.when(newRole.getRoleType()).thenReturn(RoleType.DomainAdmin);
+         Role callerRole = Mockito.mock(Role.class);
+         
Mockito.when(callerRole.getRoleType()).thenReturn(RoleType.DomainAdmin);
+         Account caller = Mockito.mock(Account.class);
+         Mockito.when(caller.getRoleId()).thenReturn(2L);
+         Mockito.when(roleService.findRole(2L)).thenReturn(callerRole);
+         accountManagerImpl.validateRoleChange(account, newRole, caller);
+     }
+ 
+     @Test
+     public void testValidateRoleCurrentRoleSameCaller() {
+         Account account = Mockito.mock(Account.class);
+         Mockito.when(account.getRoleId()).thenReturn(1L);
+         Role accountRole = Mockito.mock(Role.class);
+         
Mockito.when(accountRole.getRoleType()).thenReturn(RoleType.DomainAdmin);
+         Role newRole = Mockito.mock(Role.class);
+         Mockito.when(newRole.getRoleType()).thenReturn(RoleType.User);
+         Role callerRole = Mockito.mock(Role.class);
+         
Mockito.when(callerRole.getRoleType()).thenReturn(RoleType.DomainAdmin);
+         Account caller = Mockito.mock(Account.class);
+         Mockito.when(caller.getRoleId()).thenReturn(2L);
+         Mockito.when(roleService.findRole(1L)).thenReturn(accountRole);
+         Mockito.when(roleService.findRole(2L)).thenReturn(callerRole);
+         accountManagerImpl.validateRoleChange(account, newRole, caller);
+     }
+ 
+     @Test(expected = PermissionDeniedException.class)
+     public void testValidateRoleNewRoleHigherCaller() {
+         Account account = Mockito.mock(Account.class);
+         Mockito.when(account.getRoleId()).thenReturn(1L);
+         Role newRole = Mockito.mock(Role.class);
+         Mockito.when(newRole.getRoleType()).thenReturn(RoleType.Admin);
+         Role callerRole = Mockito.mock(Role.class);
+         
Mockito.when(callerRole.getRoleType()).thenReturn(RoleType.DomainAdmin);
+         Account caller = Mockito.mock(Account.class);
+         Mockito.when(caller.getRoleId()).thenReturn(2L);
+         Mockito.when(roleService.findRole(2L)).thenReturn(callerRole);
+         accountManagerImpl.validateRoleChange(account, newRole, caller);
+     }
+ 
+     @Test
+     public void testValidateRoleNewRoleLowerCaller() {
+         Account account = Mockito.mock(Account.class);
+         Mockito.when(account.getRoleId()).thenReturn(1L);
+         Role newRole = Mockito.mock(Role.class);
+         Mockito.when(newRole.getRoleType()).thenReturn(RoleType.User);
+         Role accountRole = Mockito.mock(Role.class);
+         Mockito.when(accountRole.getRoleType()).thenReturn(RoleType.User);
+         Role callerRole = Mockito.mock(Role.class);
+         
Mockito.when(callerRole.getRoleType()).thenReturn(RoleType.DomainAdmin);
+         Account caller = Mockito.mock(Account.class);
+         Mockito.when(caller.getRoleId()).thenReturn(2L);
+         Mockito.when(roleService.findRole(1L)).thenReturn(accountRole);
+         Mockito.when(roleService.findRole(2L)).thenReturn(callerRole);
+         accountManagerImpl.validateRoleChange(account, newRole, caller);
+     }
+ 
+     @Test(expected = PermissionDeniedException.class)
+     public void testValidateRoleAdminCannotEscalateAdminFromNonRootDomain() {
+         Account account = Mockito.mock(Account.class);
+         Mockito.when(account.getRoleId()).thenReturn(1L);
+         Mockito.when(account.getDomainId()).thenReturn(2L);
+         Role newRole = Mockito.mock(Role.class);
+         Mockito.when(newRole.getRoleType()).thenReturn(RoleType.Admin);
+         Role accountRole = Mockito.mock(Role.class);
+         Role callerRole = Mockito.mock(Role.class);
+         Mockito.when(callerRole.getRoleType()).thenReturn(RoleType.Admin);
+         Account caller = Mockito.mock(Account.class);
+         Mockito.when(caller.getRoleId()).thenReturn(2L);
+         Mockito.when(roleService.findRole(1L)).thenReturn(accountRole);
+         Mockito.when(roleService.findRole(2L)).thenReturn(callerRole);
+         accountManagerImpl.validateRoleChange(account, newRole, caller);
+     }
  }
diff --cc utils/src/main/java/com/cloud/utils/net/NetUtils.java
index 7abe64b0433,2703deaad64..500e2401fca
--- a/utils/src/main/java/com/cloud/utils/net/NetUtils.java
+++ b/utils/src/main/java/com/cloud/utils/net/NetUtils.java
@@@ -1062,16 -1063,16 +1066,16 @@@ public class NetUtils 
          // If it's a host name, don't allow to start with digit
  
          if (hostName.length() > 63 || hostName.length() < 1) {
 -            s_logger.warn("Domain name label must be between 1 and 63 
characters long");
 +            LOGGER.warn("Domain name label must be between 1 and 63 
characters long");
              return false;
-         } else if (!hostName.toLowerCase().matches("[a-z0-9-]*")) {
+         } else if (!HOSTNAME_PATTERN.matcher(hostName).matches()) {
 -            s_logger.warn("Domain name label may contain only the ASCII 
letters 'a' through 'z' (in a case-insensitive manner)");
 +            LOGGER.warn("Domain name label may contain only the ASCII letters 
'a' through 'z' (in a case-insensitive manner)");
              return false;
          } else if (hostName.startsWith("-") || hostName.endsWith("-")) {
-             LOGGER.warn("Domain name label can not start  with a hyphen and 
digit, and must not end with a hyphen");
 -            s_logger.warn("Domain name label can not start or end with a 
hyphen");
++            LOGGER.warn("Domain name label can not start or end with a 
hyphen");
              return false;
-         } else if (isHostName && hostName.matches("^[0-9-].*")) {
+         } else if (isHostName && 
START_HOSTNAME_PATTERN.matcher(hostName).matches()) {
 -            s_logger.warn("Host name can't start with digit");
 +            LOGGER.warn("Host name can't start with digit");
              return false;
          }
  

Reply via email to