From a8ab47bb2782f54f290532992644156d07743dfc Mon Sep 17 00:00:00 2001 From: Wei Zhou Date: Tue, 17 Sep 2024 12:23:33 +0200 Subject: [PATCH 1/8] CPVM: move focus on input area after clearing clipboard (#9669) --- systemvm/agent/noVNC/app/ui.js | 1 + 1 file changed, 1 insertion(+) diff --git a/systemvm/agent/noVNC/app/ui.js b/systemvm/agent/noVNC/app/ui.js index 3a85648bb84..e99d763d60c 100644 --- a/systemvm/agent/noVNC/app/ui.js +++ b/systemvm/agent/noVNC/app/ui.js @@ -1000,6 +1000,7 @@ const UI = { clipboardClear() { document.getElementById('noVNC_clipboard_text').value = ""; + document.getElementById('noVNC_clipboard_text').focus(); }, clipboardSend() { From 2e9986c6a63af0d07e3c416153ddfdebb9a9a74d Mon Sep 17 00:00:00 2001 From: dahn Date: Wed, 18 Sep 2024 12:44:25 +0200 Subject: [PATCH 2/8] list by displayname instead of name (#8503) --- ui/src/config/section/compute.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/src/config/section/compute.js b/ui/src/config/section/compute.js index 9bf8c949144..4dc1f164514 100644 --- a/ui/src/config/section/compute.js +++ b/ui/src/config/section/compute.js @@ -46,7 +46,7 @@ export default { return filters }, columns: () => { - const fields = ['name', 'state', 'ipaddress'] + const fields = ['displayname', 'state', 'ipaddress'] const metricsFields = ['cpunumber', 'cputotal', 'cpuused', 'memorytotal', { memoryused: (record) => { @@ -74,7 +74,7 @@ export default { fields.push('zonename') return fields }, - searchFilters: ['name', 'zoneid', 'domainid', 'account', 'groupid', 'tags'], + searchFilters: ['displayname', 'zoneid', 'domainid', 'account', 'groupid', 'tags'], details: () => { var fields = ['name', 'displayname', 'id', 'state', 'ipaddress', 'ip6address', 'templatename', 'ostypename', 'serviceofferingname', 'isdynamicallyscalable', 'haenable', 'hypervisor', 'boottype', 'bootmode', 'account', From a385ff1a214f432944cba78f721da35473ba6004 Mon Sep 17 00:00:00 2001 From: Nicolas Vazquez Date: Wed, 18 Sep 2024 08:04:12 -0300 Subject: [PATCH 3/8] UI: Fix VPC network offerings listing on VPC tier creation (#9557) --- ui/src/views/network/VpcTiersTab.vue | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/ui/src/views/network/VpcTiersTab.vue b/ui/src/views/network/VpcTiersTab.vue index 214ea1afd6d..402f9f06115 100644 --- a/ui/src/views/network/VpcTiersTab.vue +++ b/ui/src/views/network/VpcTiersTab.vue @@ -522,7 +522,7 @@ export default { }).then(async json => { var lbNetworks = json.listnetworksresponse.network || [] if (lbNetworks.length > 0) { - this.publicLBExists = true + this.publicLBExists = false for (var idx = 0; idx < lbNetworks.length; idx++) { const lbNetworkOffering = await this.getNetworkOffering(lbNetworks[idx].networkofferingid) const index = lbNetworkOffering.service.map(svc => { return svc.name }).indexOf('Lb') @@ -546,16 +546,23 @@ export default { }).then(json => { this.networkOfferings = json.listnetworkofferingsresponse.networkoffering || [] var filteredOfferings = [] - if (this.publicLBExists) { - for (var index in this.networkOfferings) { - const offering = this.networkOfferings[index] - const idx = offering.service.map(svc => { return svc.name }).indexOf('Lb') - if (idx === -1 || this.lbProviderMap.publicLb.vpc.indexOf(offering.service.map(svc => { return svc.provider[0].name })[idx]) === -1) { + const vpcLbServiceIndex = this.resource.service.map(svc => { return svc.name }).indexOf('Lb') + for (var index in this.networkOfferings) { + const offering = this.networkOfferings[index] + const idx = offering.service.map(svc => { return svc.name }).indexOf('Lb') + if (this.publicLBExists && (idx === -1 || this.lbProviderMap.publicLb.vpc.indexOf(offering.service.map(svc => { return svc.provider[0].name })[idx]) === -1)) { + filteredOfferings.push(offering) + } else if (!this.publicLBExists && vpcLbServiceIndex > -1) { + const vpcLbServiceProvider = vpcLbServiceIndex === -1 ? undefined : this.resource.service[vpcLbServiceIndex].provider[0].name + const offeringLbServiceProvider = idx === -1 ? undefined : offering.service[idx].provider[0].name + if (vpcLbServiceProvider && (!offeringLbServiceProvider || (offeringLbServiceProvider && vpcLbServiceProvider === offeringLbServiceProvider))) { filteredOfferings.push(offering) } + } else { + filteredOfferings.push(offering) } - this.networkOfferings = filteredOfferings } + this.networkOfferings = filteredOfferings this.form.networkOffering = this.networkOfferings[0].id }).catch(error => { this.$notifyError(error) From cfbdeba17c7038c3c72baeba7192301e30a4ad50 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Wed, 18 Sep 2024 17:14:43 +0530 Subject: [PATCH 4/8] refactor: cloud-sysvmadm script (#9200) Signed-off-by: Abhishek Kumar --- setup/bindir/cloud-sysvmadm.in | 276 +++++++++++++++++---------------- 1 file changed, 140 insertions(+), 136 deletions(-) diff --git a/setup/bindir/cloud-sysvmadm.in b/setup/bindir/cloud-sysvmadm.in index a5bb9b37ac1..a262f6b710e 100755 --- a/setup/bindir/cloud-sysvmadm.in +++ b/setup/bindir/cloud-sysvmadm.in @@ -18,13 +18,11 @@ # under the License. -. /etc/rc.d/init.d/functions - #set -x usage() { usage_content=" - The tool for stopping/starting running system vms and domain routers + The tool for stopping/starting running system vms and domain routers. It requires integration API port to be enabled. Usage: %s: [-d] [-u] [-p] [-m] [-s] [-r] [-a] [-n] [-t] [-l] [-z] [-v] [-i] [-j] @@ -63,6 +61,7 @@ vmids="" vmidsclause="" withids="" vmtable="vm_instance" +integrationport=0 @@ -104,6 +103,12 @@ do done +integrationport=(`mysql -h $db --user=$user --password=$password --skip-column-names -U cloud -e "SELECT value FROM configuration WHERE name='integration.api.port'"`) +if [ $integrationport -le 0 ]; then + echo "Integration port is not enabled!" + exit +fi + prepare_ids_clause() { if [[ ! -z "$vmidsclause" ]]; then return @@ -117,168 +122,167 @@ prepare_ids_clause() { stop_start_system() { prepare_ids_clause -secondary=(`mysql -h $db --user=$user --password=$password --skip-column-names -U cloud -e "select id from $vmtable where state=\"Running\" and type=\"SecondaryStorageVm\"$zone$vmidsclause"`) -console=(`mysql -h $db --user=$user --password=$password --skip-column-names -U cloud -e "select id from $vmtable where state=\"Running\" and type=\"ConsoleProxy\"$zone$vmidsclause"`) -length_secondary=(${#secondary[@]}) -length_console=(${#console[@]}) + secondary=(`mysql -h $db --user=$user --password=$password --skip-column-names -U cloud -e "select uuid from $vmtable where state=\"Running\" and type=\"SecondaryStorageVm\"$zone$vmidsclause"`) + console=(`mysql -h $db --user=$user --password=$password --skip-column-names -U cloud -e "select uuid from $vmtable where state=\"Running\" and type=\"ConsoleProxy\"$zone$vmidsclause"`) + length_secondary=(${#secondary[@]}) + length_console=(${#console[@]}) -echo -e "\nStopping and starting $length_secondary secondary storage vm(s)$inzone$withids..." -echo -e "[$(date "+%Y.%m.%d-%H.%M.%S")] Stopping and starting $length_secondary secondary storage vm(s)$inzone$withids..." >>$LOGFILE + echo -e "\nStopping and starting $length_secondary secondary storage vm(s)$inzone$withids..." + echo -e "[$(date "+%Y.%m.%d-%H.%M.%S")] Stopping and starting $length_secondary secondary storage vm(s)$inzone$withids..." >>$LOGFILE -for d in "${secondary[@]}"; do - echo "[$(date "+%Y.%m.%d-%H.%M.%S")] INFO: Stopping secondary storage vm with id $d" >>$LOGFILE - jobresult=$(send_request stopSystemVm $d) - if [ "$jobresult" != "1" ]; then - echo -e "ERROR: Failed to stop secondary storage vm with id $d \n" - echo "[$(date "+%Y.%m.%d-%H.%M.%S")] ERROR: Failed to stop secondary storage vm with id $d" >>$LOGFILE - else - echo "[$(date "+%Y.%m.%d-%H.%M.%S")] INFO: Starting secondary storage vm with id $d" >>$LOGFILE - jobresult=$(send_request startSystemVm $d SSVM) - if [ "$jobresult" != "1" ]; then - echo "[$(date "+%Y.%m.%d-%H.%M.%S")] ERROR: Failed to start secondary storage vm with id $d" >>$LOGFILE - echo "[$(date "+%Y.%m.%d-%H.%M.%S")] ERROR: Failed to start secondary storage vm with id $d" >>$LOGFILE - fi - fi -done + for d in "${secondary[@]}"; do + echo "[$(date "+%Y.%m.%d-%H.%M.%S")] INFO: Stopping secondary storage vm with id $d" >>$LOGFILE + jobresult=$(send_request stopSystemVm $d) + if [ "$jobresult" != "1" ]; then + echo -e "ERROR: Failed to stop secondary storage vm with id $d \n" + echo "[$(date "+%Y.%m.%d-%H.%M.%S")] ERROR: Failed to stop secondary storage vm with id $d" >>$LOGFILE + else + echo "[$(date "+%Y.%m.%d-%H.%M.%S")] INFO: Starting secondary storage vm with id $d" >>$LOGFILE + jobresult=$(send_request startSystemVm $d SSVM) + if [ "$jobresult" != "1" ]; then + echo "[$(date "+%Y.%m.%d-%H.%M.%S")] ERROR: Failed to start secondary storage vm with id $d" >>$LOGFILE + echo "[$(date "+%Y.%m.%d-%H.%M.%S")] ERROR: Failed to start secondary storage vm with id $d" >>$LOGFILE + fi + fi + done -if [ "$length_secondary" == "0" ];then - echo -e "No running secondary storage vms found \n" -else - echo -e "Done stopping and starting secondary storage vm(s)$inzone$withids" - echo -e "[$(date "+%Y.%m.%d-%H.%M.%S")] Done stopping and starting secondary storage vm(s)$inzone$withids." >>$LOGFILE -fi - -echo -e "\nStopping and starting $length_console console proxy vm(s)$inzone$withids..." -echo -e "[$(date "+%Y.%m.%d-%H.%M.%S")] Stopping and starting $length_console console proxy vm(s)$inzone$withids..." >>$LOGFILE - -for d in "${console[@]}"; do - echo "[$(date "+%Y.%m.%d-%H.%M.%S")] INFO: Stopping console proxy with id $d" >>$LOGFILE - jobresult=$(send_request stopSystemVm $d) - if [ "$jobresult" != "1" ]; then - echo -e "ERROR: Failed to stop console proxy vm with id $d \n" - echo "[$(date "+%Y.%m.%d-%H.%M.%S")] ERROR: Failed to stop console proxy vm with id $d" >>$LOGFILE + if [ "$length_secondary" == "0" ];then + echo -e "No running secondary storage vms found \n" else - echo "[$(date "+%Y.%m.%d-%H.%M.%S")] INFO: Starting console proxy vm with id $d" >>$LOGFILE - jobresult=$(send_request startSystemVm $d consoleProxy) - if [ "$jobresult" != "1" ]; then - echo -e "ERROR: Failed to start console proxy vm with id $d \n" - echo "[$(date "+%Y.%m.%d-%H.%M.%S")] ERROR: Failed to start console proxy vm with id $d" >>$LOGFILE - fi + echo -e "Done stopping and starting secondary storage vm(s)$inzone$withids" + echo -e "[$(date "+%Y.%m.%d-%H.%M.%S")] Done stopping and starting secondary storage vm(s)$inzone$withids." >>$LOGFILE fi -done -if [ "$length_console" == "0" ];then - echo -e "No running console proxy vms found \n" -else - echo "Done stopping and starting console proxy vm(s) $inzone$withids." - echo "[$(date "+%Y.%m.%d-%H.%M.%S")] Done stopping and starting console proxy vm(s) $inzone$withids." >>$LOGFILE -fi + echo -e "\nStopping and starting $length_console console proxy vm(s)$inzone$withids..." + echo -e "[$(date "+%Y.%m.%d-%H.%M.%S")] Stopping and starting $length_console console proxy vm(s)$inzone$withids..." >>$LOGFILE + + for d in "${console[@]}"; do + echo "[$(date "+%Y.%m.%d-%H.%M.%S")] INFO: Stopping console proxy with id $d" >>$LOGFILE + jobresult=$(send_request stopSystemVm $d) + if [ "$jobresult" != "1" ]; then + echo -e "ERROR: Failed to stop console proxy vm with id $d \n" + echo "[$(date "+%Y.%m.%d-%H.%M.%S")] ERROR: Failed to stop console proxy vm with id $d" >>$LOGFILE + else + echo "[$(date "+%Y.%m.%d-%H.%M.%S")] INFO: Starting console proxy vm with id $d" >>$LOGFILE + jobresult=$(send_request startSystemVm $d consoleProxy) + if [ "$jobresult" != "1" ]; then + echo -e "ERROR: Failed to start console proxy vm with id $d \n" + echo "[$(date "+%Y.%m.%d-%H.%M.%S")] ERROR: Failed to start console proxy vm with id $d" >>$LOGFILE + fi + fi + done + + if [ "$length_console" == "0" ];then + echo -e "No running console proxy vms found \n" + else + echo "Done stopping and starting console proxy vm(s) $inzone$withids." + echo "[$(date "+%Y.%m.%d-%H.%M.%S")] Done stopping and starting console proxy vm(s) $inzone$withids." >>$LOGFILE + fi } stop_start_router() { prepare_ids_clause - router=(`mysql -h $db --user=$user --password=$password --skip-column-names -U cloud -e "select id from vm_instance where state=\"Running\" and type=\"DomainRouter\"$zone$vmidsclause"`) - length_router=(${#router[@]}) + router=(`mysql -h $db --user=$user --password=$password --skip-column-names -U cloud -e "select uuid from vm_instance where state=\"Running\" and type=\"DomainRouter\"$zone$vmidsclause"`) + length_router=(${#router[@]}) - echo -e "\nStopping and starting $length_router running routing vm(s)$inzone$withids... " - echo -e "[$(date "+%Y.%m.%d-%H.%M.%S")] Stopping and starting $length_router running routing vm(s)$inzone$withids... " >>$LOGFILE + echo -e "\nStopping and starting $length_router running routing vm(s)$inzone$withids... " + echo -e "[$(date "+%Y.%m.%d-%H.%M.%S")] Stopping and starting $length_router running routing vm(s)$inzone$withids... " >>$LOGFILE - #Spawn reboot router in parallel - run commands in chunks - number of threads is configurable + #Spawn reboot router in parallel - run commands in chunks - number of threads is configurable - pids=() - for d in "${router[@]}"; do + pids=() + for d in "${router[@]}"; do - reboot_router $d & + reboot_router $d & - pids=( "${pids[@]}" $! ) + pids=( "${pids[@]}" $! ) - length_pids=(${#pids[@]}) - unfinishedPids=(${#pids[@]}) + length_pids=(${#pids[@]}) + unfinishedPids=(${#pids[@]}) - if [ $maxthreads -gt $length_router ]; then - maxthreads=$length_router - fi + if [ $maxthreads -gt $length_router ]; then + maxthreads=$length_router + fi - if [ $length_pids -ge $maxthreads ]; then - while [ $unfinishedPids -gt 0 ]; do - sleep 10 - count=0 - for (( i = 0 ; i < $length_pids; i++ )); do - if ! ps ax | grep -v grep | grep ${pids[$i]} > /dev/null; then - count=`expr $count + 1` - fi - done + if [ $length_pids -ge $maxthreads ]; then + while [ $unfinishedPids -gt 0 ]; do + sleep 10 + count=0 + for (( i = 0 ; i < $length_pids; i++ )); do + if ! ps ax | grep -v grep | grep ${pids[$i]} > /dev/null; then + count=`expr $count + 1` + fi + done - if [ $count -eq $unfinishedPids ]; then - unfinishedPids=0 - fi + if [ $count -eq $unfinishedPids ]; then + unfinishedPids=0 + fi - done + done - #remove all elements from pids - if [ $unfinishedPids -eq 0 ]; then - pids=() - length_pids=(${#pids[@]}) - fi + #remove all elements from pids + if [ $unfinishedPids -eq 0 ]; then + pids=() + length_pids=(${#pids[@]}) + fi - fi + fi - done + done - if [ "$length_router" == "0" ];then - echo -e "[$(date "+%Y.%m.%d-%H.%M.%S")] No running router vms found \n" >>$LOGFILE - else - while [ $unfinishedPids -gt 0 ]; do - sleep 10 - done + if [ "$length_router" == "0" ];then + echo -e "[$(date "+%Y.%m.%d-%H.%M.%S")] No running router vms found \n" >>$LOGFILE + else + while [ $unfinishedPids -gt 0 ]; do + sleep 10 + done - echo -e "Done restarting router(s)$inzone$withids. \n" - echo -e "[$(date "+%Y.%m.%d-%H.%M.%S")] Done restarting router(s)$inzone$withids. \n" >>$LOGFILE + echo -e "Done restarting router(s)$inzone$withids. \n" + echo -e "[$(date "+%Y.%m.%d-%H.%M.%S")] Done restarting router(s)$inzone$withids. \n" >>$LOGFILE - fi + fi } stop_start_all() { -stop_start_system -stop_start_router + stop_start_system + stop_start_router } send_request(){ - jobid=`curl -sS "http://$ms:8096/?command=$1&id=$2&response=json" | sed 's/\"//g' | sed 's/ //g' | sed 's/{//g' | sed 's/}//g' | awk -F: {'print $3'}` - if [ "$jobid" == "" ]; then - echo 2 - return - fi - jobresult=$(query_async_job_result $jobid) + jobid=`curl -sS "http://$ms:$integrationport/?command=$1&id=$2&response=json" | sed 's/\"//g' | sed 's/ //g' | sed 's/{//g' | sed 's/}//g' | awk -F: {'print $3'}` + if [ "$jobid" == "" ]; then + echo 2 + return + fi + jobresult=$(query_async_job_result $jobid) if [ "$jobresult" != "1" ]; then echo -e "ERROR: Failed to $1 id=$2; jobId is $jobid \n" echo "[$(date "+%Y.%m.%d-%H.%M.%S")] ERROR: Failed to $1 id=$2; jobId is $jobid" >>$LOGFILE fi - echo $jobresult + echo $jobresult } reboot_router(){ - echo "[$(date "+%Y.%m.%d-%H.%M.%S")] INFO: Restarting router with id $1" >>$LOGFILE - jobid=`curl -sS "http://$ms:8096/?command=rebootRouter&id=$1&response=json" | sed 's/\"//g' | sed 's/ //g' | sed 's/{//g' | sed 's/}//g' | awk -F: {'print $3'}` - if [ "$jobid" == "" ]; then - echo "[$(date "+%Y.%m.%d-%H.%M.%S")] ERROR: Failed to restart domainRouter with id $1; unable to submit the job" >>$LOGFILE - echo 2 - return - fi + echo "[$(date "+%Y.%m.%d-%H.%M.%S")] INFO: Restarting router with id $1" >>$LOGFILE + jobid=`curl -sS "http://$ms:$integrationport/?command=rebootRouter&id=$1&response=json" | sed 's/\"//g' | sed 's/ //g' | sed 's/{//g' | sed 's/}//g' | awk -F: {'print $3'}` + if [ "$jobid" == "" ]; then + echo "[$(date "+%Y.%m.%d-%H.%M.%S")] ERROR: Failed to restart domainRouter with id $1; unable to submit the job" >>$LOGFILE + echo 2 + return + fi - jobresult=$(query_async_job_result $jobid) - - if [ "$jobresult" != "1" ]; then - echo -e "ERROR: Failed to restart domainRouter with id $1 \n" - echo "[$(date "+%Y.%m.%d-%H.%M.%S")] ERROR: Failed to restart domainRouter with id $1; jobId $jobid" >>$LOGFILE - exit 0 - else - echo "[$(date "+%Y.%m.%d-%H.%M.%S")] INFO: Successfully restarted domainRouter with id $1; jobId $jobid" >>$LOGFILE - exit 0 - fi + jobresult=$(query_async_job_result $jobid) + if [ "$jobresult" != "1" ]; then + echo -e "ERROR: Failed to restart domainRouter with id $1 \n" + echo "[$(date "+%Y.%m.%d-%H.%M.%S")] ERROR: Failed to restart domainRouter with id $1; jobId $jobid" >>$LOGFILE + exit 0 + else + echo "[$(date "+%Y.%m.%d-%H.%M.%S")] INFO: Successfully restarted domainRouter with id $1; jobId $jobid" >>$LOGFILE + exit 0 + fi } restart_networks(){ @@ -346,7 +350,7 @@ restart_networks(){ } restart_network(){ - jobid=`curl -sS "http://$ms:8096/?command=restartNetwork&id=$1&response=json" | sed 's/\"//g' | sed 's/ //g' | sed 's/{//g' | sed 's/}//g' | awk -F: {'print $3'}` + jobid=`curl -sS "http://$ms:$integrationport/?command=restartNetwork&id=$1&response=json" | sed 's/\"//g' | sed 's/ //g' | sed 's/{//g' | sed 's/}//g' | awk -F: {'print $3'}` if [ "$jobid" == "" ]; then echo "[$(date "+%Y.%m.%d-%H.%M.%S")] ERROR: Failed to restart network with id $1; unable to submit the job" >>$LOGFILE echo 2 @@ -367,7 +371,7 @@ restart_network(){ restart_vpc(){ echo -e "INFO: Restarting vpc with id $1" echo "[$(date "+%Y.%m.%d-%H.%M.%S")] INFO: Restarting vpc with id $1" >>$LOGFILE - jobid=`curl -sS "http://$ms:8096/?command=restartVPC&id=$1&response=json" | sed 's/\"//g' | sed 's/ //g' | sed 's/{//g' | sed 's/}//g' | awk -F: {'print $3'}` + jobid=`curl -sS "http://$ms:$integrationport/?command=restartVPC&id=$1&response=json" | sed 's/\"//g' | sed 's/ //g' | sed 's/{//g' | sed 's/}//g' | awk -F: {'print $3'}` if [ "$jobid" == "" ]; then echo "[$(date "+%Y.%m.%d-%H.%M.%S")] ERROR: Failed to restart vpc with id $1; unable to submit the job" >>$LOGFILE echo 2 @@ -387,7 +391,7 @@ restart_vpc(){ restart_vpcs(){ - vpcs=(`mysql -h $db --user=$user --password=$password --skip-column-names -U cloud -e "select id from vpc WHERE removed is null$zone"`) + vpcs=(`mysql -h $db --user=$user --password=$password --skip-column-names -U cloud -e "select uuid from vpc WHERE removed is null$zone"`) length_vpcs=(${#vpcs[@]}) echo -e "\nRestarting $length_vpcs vpcs... " @@ -450,21 +454,21 @@ restart_vpcs(){ } query_async_job_result() { -while [ 1 ] -do - jobstatus=`curl -sS "http://$ms:8096/?command=queryAsyncJobResult&jobId=$1&response=json" | sed 's/\"//g' | sed 's/ //g' | sed 's/{//g' | sed 's/}//g' | awk -F, {'print $4'} | awk -F: {'print $2'}` - if [ "$jobstatus" != "0" ]; then - echo $jobstatus - break - fi -sleep 5 -done + while [ 1 ] + do + jobstatus=`curl -sS "http://$ms:$integrationport/?command=queryAsyncJobResult&jobId=$1&response=json" | sed 's/\"//g' | sed 's/ //g' | sed 's/{//g' | sed 's/}//g' | awk -F, {'print $7'} | awk -F: {'print $2'}` + if [ "$jobstatus" != "0" ]; then + echo $jobstatus + break + fi + sleep 5 + done } if [ "$system$router$all$help$redundant$vpc" == "" ] then - usage - exit + usage + exit fi if [ "$help" == "1" ] From e16a971511137e47bdaa990ba80a647dcf23e56d Mon Sep 17 00:00:00 2001 From: Vishesh Date: Thu, 19 Sep 2024 14:36:00 +0530 Subject: [PATCH 5/8] Fix resource count discrepancy while associating IP address to a network or vpc (#9563) --- .../cloud/network/IpAddressManagerImpl.java | 22 +++++++++++++------ .../com/cloud/network/vpc/VpcManagerImpl.java | 19 +++++++++++----- 2 files changed, 29 insertions(+), 12 deletions(-) diff --git a/server/src/main/java/com/cloud/network/IpAddressManagerImpl.java b/server/src/main/java/com/cloud/network/IpAddressManagerImpl.java index c8ac0c1016b..261dc529434 100644 --- a/server/src/main/java/com/cloud/network/IpAddressManagerImpl.java +++ b/server/src/main/java/com/cloud/network/IpAddressManagerImpl.java @@ -35,6 +35,7 @@ import javax.inject.Inject; import com.cloud.network.dao.PublicIpQuarantineDao; import com.cloud.network.vo.PublicIpQuarantineVO; +import com.cloud.resourcelimit.CheckedReservation; import org.apache.cloudstack.acl.ControlledEntity.ACLType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.annotation.AnnotationService; @@ -53,6 +54,7 @@ import org.apache.cloudstack.region.PortableIp; import org.apache.cloudstack.region.PortableIpDao; import org.apache.cloudstack.region.PortableIpVO; import org.apache.cloudstack.region.Region; +import org.apache.cloudstack.reservation.dao.ReservationDao; import org.apache.commons.collections.CollectionUtils; import org.apache.log4j.Logger; @@ -261,6 +263,8 @@ public class IpAddressManagerImpl extends ManagerBase implements IpAddressManage @Inject ResourceLimitService _resourceLimitMgr; + @Inject + ReservationDao reservationDao; @Inject NetworkOfferingServiceMapDao _ntwkOfferingSrvcDao; @Inject @@ -1556,14 +1560,15 @@ public class IpAddressManagerImpl extends ManagerBase implements IpAddressManage s_logger.debug("Associating ip " + ipToAssoc + " to network " + network); - IPAddressVO ip = _ipAddressDao.findById(ipId); - //update ip address with networkId - ip.setAssociatedWithNetworkId(networkId); - ip.setSourceNat(isSourceNat); - _ipAddressDao.update(ipId, ip); - boolean success = false; - try { + IPAddressVO ip = null; + try (CheckedReservation publicIpReservation = new CheckedReservation(owner, ResourceType.public_ip, 1l, reservationDao, _resourceLimitMgr)) { + ip = _ipAddressDao.findById(ipId); + //update ip address with networkId + ip.setAssociatedWithNetworkId(networkId); + ip.setSourceNat(isSourceNat); + _ipAddressDao.update(ipId, ip); + success = applyIpAssociations(network, false); if (success) { s_logger.debug("Successfully associated ip address " + ip.getAddress().addr() + " to network " + network); @@ -1571,6 +1576,9 @@ public class IpAddressManagerImpl extends ManagerBase implements IpAddressManage s_logger.warn("Failed to associate ip address " + ip.getAddress().addr() + " to network " + network); } return _ipAddressDao.findById(ipId); + } catch (Exception e) { + s_logger.error(String.format("Failed to associate ip address %s to network %s", ipToAssoc, network), e); + throw new CloudRuntimeException(String.format("Failed to associate ip address %s to network %s", ipToAssoc, network), e); } finally { if (!success && releaseOnFailure) { if (ip != null) { 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 c9391a32167..ce3f083135e 100644 --- a/server/src/main/java/com/cloud/network/vpc/VpcManagerImpl.java +++ b/server/src/main/java/com/cloud/network/vpc/VpcManagerImpl.java @@ -42,6 +42,7 @@ import javax.annotation.PostConstruct; import javax.inject.Inject; import javax.naming.ConfigurationException; +import com.cloud.resourcelimit.CheckedReservation; import org.apache.cloudstack.acl.ControlledEntity.ACLType; import org.apache.cloudstack.alert.AlertService; import org.apache.cloudstack.annotation.AnnotationService; @@ -63,6 +64,7 @@ import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationSe import org.apache.cloudstack.framework.config.dao.ConfigurationDao; import org.apache.cloudstack.managed.context.ManagedContextRunnable; import org.apache.cloudstack.query.QueryService; +import org.apache.cloudstack.reservation.dao.ReservationDao; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.ObjectUtils; import org.apache.log4j.Logger; @@ -237,6 +239,8 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis @Inject ResourceLimitService _resourceLimitMgr; @Inject + ReservationDao reservationDao; + @Inject VpcServiceMapDao _vpcSrvcDao; @Inject DataCenterDao _dcDao; @@ -2927,9 +2931,10 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis s_logger.debug("Associating ip " + ipToAssoc + " to vpc " + vpc); final boolean isSourceNatFinal = isSrcNatIpRequired(vpc.getVpcOfferingId()) && getExistingSourceNatInVpc(vpc.getAccountId(), vpcId) == null; - Transaction.execute(new TransactionCallbackNoReturn() { - @Override - public void doInTransactionWithoutResult(final TransactionStatus status) { + try (CheckedReservation publicIpReservation = new CheckedReservation(owner, ResourceType.public_ip, 1l, reservationDao, _resourceLimitMgr)) { + Transaction.execute(new TransactionCallbackNoReturn() { + @Override + public void doInTransactionWithoutResult(final TransactionStatus status) { final IPAddressVO ip = _ipAddressDao.findById(ipId); // update ip address with networkId ip.setVpcId(vpcId); @@ -2939,8 +2944,12 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis // mark ip as allocated _ipAddrMgr.markPublicIpAsAllocated(ip); - } - }); + } + }); + } catch (Exception e) { + s_logger.error("Failed to associate ip " + ipToAssoc + " to vpc " + vpc, e); + throw new CloudRuntimeException("Failed to associate ip " + ipToAssoc + " to vpc " + vpc, e); + } s_logger.debug("Successfully assigned ip " + ipToAssoc + " to vpc " + vpc); CallContext.current().putContextParameter(IpAddress.class, ipToAssoc.getUuid()); From 50d7ebf5cf5a2d4fc38bbf25b4e55dcc0191e861 Mon Sep 17 00:00:00 2001 From: Wei Zhou Date: Thu, 19 Sep 2024 13:53:53 +0200 Subject: [PATCH 6/8] UI: enable project menu on mobile (#9700) --- ui/src/components/page/GlobalHeader.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/src/components/page/GlobalHeader.vue b/ui/src/components/page/GlobalHeader.vue index dd51278b483..47a79613776 100644 --- a/ui/src/components/page/GlobalHeader.vue +++ b/ui/src/components/page/GlobalHeader.vue @@ -26,7 +26,7 @@ - + @@ -45,7 +45,7 @@ - + From 7f2ab635e972499600e386ca42f59ce2c6d74d8e Mon Sep 17 00:00:00 2001 From: Wei Zhou Date: Thu, 19 Sep 2024 13:54:53 +0200 Subject: [PATCH 7/8] lb: fix haproxy cannot start if algorithm is not lowercase (#9698) --- core/src/main/java/com/cloud/network/HAProxyConfigurator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/com/cloud/network/HAProxyConfigurator.java b/core/src/main/java/com/cloud/network/HAProxyConfigurator.java index 8352895e621..9d8301f291f 100644 --- a/core/src/main/java/com/cloud/network/HAProxyConfigurator.java +++ b/core/src/main/java/com/cloud/network/HAProxyConfigurator.java @@ -484,7 +484,7 @@ public class HAProxyConfigurator implements LoadBalancerConfigurator { sb.append("\tbind ").append(publicIP).append(":").append(publicPort); result.add(sb.toString()); sb = new StringBuilder(); - sb.append("\t").append("balance ").append(algorithm); + sb.append("\t").append("balance ").append(algorithm.toLowerCase()); result.add(sb.toString()); int i = 0; From 075f9811c4b1f785f268df00271cdb7b46d73d1d Mon Sep 17 00:00:00 2001 From: Fabricio Duarte Date: Thu, 19 Sep 2024 14:54:30 -0300 Subject: [PATCH 8/8] [VMware] Make disk controller selection on volume attachment consistent with VM creation and start (#9636) * Make volume attachment disk controller selection consistent with VM creation and start * Update vmware-base/src/main/java/com/cloud/hypervisor/vmware/util/VmwareHelper.java Co-authored-by: dahn * Choose disk controllers after converting osdefault * Rename function --------- Co-authored-by: dahn --- .../vmware/resource/VmwareResource.java | 53 +++---------- .../resource/VmwareStorageProcessor.java | 15 ++-- .../vmware/mo/HypervisorHostHelper.java | 23 +----- .../hypervisor/vmware/util/VmwareHelper.java | 75 +++++++++++++++++++ 4 files changed, 97 insertions(+), 69 deletions(-) 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 732d40da307..92821c7e26d 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 @@ -1975,16 +1975,8 @@ public class VmwareResource extends ServerResourceBase implements StoragePoolRes return; } - String msg; - String rootDiskController = controllerInfo.first(); - String dataDiskController = controllerInfo.second(); - String scsiDiskController; - String recommendedDiskController = null; - - if (VmwareHelper.isControllerOsRecommended(dataDiskController) || VmwareHelper.isControllerOsRecommended(rootDiskController)) { - recommendedDiskController = vmMo.getRecommendedDiskController(null); - } - scsiDiskController = HypervisorHostHelper.getScsiController(new Pair(rootDiskController, dataDiskController), recommendedDiskController); + Pair chosenDiskControllers = VmwareHelper.chooseRequiredDiskControllers(controllerInfo, vmMo, null, null); + String scsiDiskController = HypervisorHostHelper.getScsiController(chosenDiskControllers); if (scsiDiskController == null) { return; } @@ -2337,6 +2329,7 @@ public class VmwareResource extends ServerResourceBase implements StoragePoolRes } int controllerKey; + Pair chosenDiskControllers = VmwareHelper.chooseRequiredDiskControllers(controllerInfo,vmMo, null, null); // // Setup ROOT/DATA disk devices @@ -2361,10 +2354,7 @@ public class VmwareResource extends ServerResourceBase implements StoragePoolRes } VirtualMachineDiskInfo matchingExistingDisk = getMatchingExistingDisk(diskInfoBuilder, vol, hyperHost, context); - String diskController = getDiskController(vmMo, matchingExistingDisk, vol, controllerInfo, deployAsIs); - if (DiskControllerType.getType(diskController) == DiskControllerType.osdefault) { - diskController = vmMo.getRecommendedDiskController(null); - } + String diskController = getDiskController(vmMo, matchingExistingDisk, vol, chosenDiskControllers, deployAsIs); if (DiskControllerType.getType(diskController) == DiskControllerType.ide) { controllerKey = vmMo.getIDEControllerKey(ideUnitNumber); if (vol.getType() == Volume.Type.DATADISK) { @@ -2847,27 +2837,10 @@ public class VmwareResource extends ServerResourceBase implements StoragePoolRes } private Pair getControllerInfoFromVmSpec(VirtualMachineTO vmSpec) throws CloudRuntimeException { - String dataDiskController = vmSpec.getDetails().get(VmDetailConstants.DATA_DISK_CONTROLLER); - String rootDiskController = vmSpec.getDetails().get(VmDetailConstants.ROOT_DISK_CONTROLLER); - - // If root disk controller is scsi, then data disk controller would also be scsi instead of using 'osdefault' - // This helps avoid mix of different scsi subtype controllers in instance. - if (DiskControllerType.osdefault == DiskControllerType.getType(dataDiskController) && DiskControllerType.lsilogic == DiskControllerType.getType(rootDiskController)) { - dataDiskController = DiskControllerType.scsi.toString(); - } - - // Validate the controller types - dataDiskController = DiskControllerType.getType(dataDiskController).toString(); - rootDiskController = DiskControllerType.getType(rootDiskController).toString(); - - if (DiskControllerType.getType(rootDiskController) == DiskControllerType.none) { - throw new CloudRuntimeException("Invalid root disk controller detected : " + rootDiskController); - } - if (DiskControllerType.getType(dataDiskController) == DiskControllerType.none) { - throw new CloudRuntimeException("Invalid data disk controller detected : " + dataDiskController); - } - - return new Pair<>(rootDiskController, dataDiskController); + String rootDiskControllerDetail = vmSpec.getDetails().get(VmDetailConstants.ROOT_DISK_CONTROLLER); + String dataDiskControllerDetail = vmSpec.getDetails().get(VmDetailConstants.DATA_DISK_CONTROLLER); + VmwareHelper.validateDiskControllerDetails(rootDiskControllerDetail, dataDiskControllerDetail); + return new Pair<>(rootDiskControllerDetail, dataDiskControllerDetail); } private String getBootModeFromVmSpec(VirtualMachineTO vmSpec, boolean deployAsIs) { @@ -3615,15 +3588,7 @@ public class VmwareResource extends ServerResourceBase implements StoragePoolRes return controllerType.toString(); } - if (vol.getType() == Volume.Type.ROOT) { - s_logger.info("Chose disk controller for vol " + vol.getType() + " -> " + controllerInfo.first() - + ", based on root disk controller settings at global configuration setting."); - return controllerInfo.first(); - } else { - s_logger.info("Chose disk controller for vol " + vol.getType() + " -> " + controllerInfo.second() - + ", based on default data disk controller setting i.e. Operating system recommended."); // Need to bring in global configuration setting & template level setting. - return controllerInfo.second(); - } + return VmwareHelper.getControllerBasedOnDiskType(controllerInfo, vol); } private void postDiskConfigBeforeStart(VirtualMachineMO vmMo, VirtualMachineTO vmSpec, DiskTO[] sortedDisks, int ideControllerKey, 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 57522a678f8..40ebc4cb02a 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 @@ -2100,15 +2100,18 @@ public class VmwareStorageProcessor implements StorageProcessor { AttachAnswer answer = new AttachAnswer(disk); if (isAttach) { - String diskController = getLegacyVmDataDiskController(); - + String rootDiskControllerDetail = DiskControllerType.ide.toString(); + if (controllerInfo != null && StringUtils.isNotEmpty(controllerInfo.get(VmDetailConstants.ROOT_DISK_CONTROLLER))) { + rootDiskControllerDetail = controllerInfo.get(VmDetailConstants.ROOT_DISK_CONTROLLER); + } + String dataDiskControllerDetail = getLegacyVmDataDiskController(); if (controllerInfo != null && StringUtils.isNotEmpty(controllerInfo.get(VmDetailConstants.DATA_DISK_CONTROLLER))) { - diskController = controllerInfo.get(VmDetailConstants.DATA_DISK_CONTROLLER); + dataDiskControllerDetail = controllerInfo.get(VmDetailConstants.DATA_DISK_CONTROLLER); } - if (DiskControllerType.getType(diskController) == DiskControllerType.osdefault) { - diskController = vmMo.getRecommendedDiskController(null); - } + VmwareHelper.validateDiskControllerDetails(rootDiskControllerDetail, dataDiskControllerDetail); + Pair chosenDiskControllers = VmwareHelper.chooseRequiredDiskControllers(new Pair<>(rootDiskControllerDetail, dataDiskControllerDetail), vmMo, null, null); + String diskController = VmwareHelper.getControllerBasedOnDiskType(chosenDiskControllers, disk); vmMo.attachDisk(new String[] { datastoreVolumePath }, morDs, diskController, storagePolicyId, volumeTO.getIopsReadRate() + volumeTO.getIopsWriteRate()); VirtualMachineDiskInfoBuilder diskInfoBuilder = vmMo.getDiskInfoBuilder(); 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 12ef462ec8a..44965e9321b 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 @@ -1567,15 +1567,8 @@ public class HypervisorHostHelper { VmwareHelper.setBasicVmConfig(vmConfig, cpuCount, cpuSpeedMHz, cpuReservedMHz, memoryMB, memoryReserveMB, guestOsIdentifier, limitCpuUse, false); - String newRootDiskController = controllerInfo.first(); - String newDataDiskController = controllerInfo.second(); - String recommendedController = null; - if (VmwareHelper.isControllerOsRecommended(newRootDiskController) || VmwareHelper.isControllerOsRecommended(newDataDiskController)) { - recommendedController = host.getRecommendedDiskController(guestOsIdentifier); - } - - Pair updatedControllerInfo = new Pair(newRootDiskController, newDataDiskController); - String scsiDiskController = HypervisorHostHelper.getScsiController(updatedControllerInfo, recommendedController); + Pair chosenDiskControllers = VmwareHelper.chooseRequiredDiskControllers(controllerInfo, null, host, guestOsIdentifier); + String scsiDiskController = HypervisorHostHelper.getScsiController(chosenDiskControllers); // If there is requirement for a SCSI controller, ensure to create those. if (scsiDiskController != null) { int busNum = 0; @@ -2249,19 +2242,11 @@ public class HypervisorHostHelper { return morHyperHost; } - public static String getScsiController(Pair controllerInfo, String recommendedController) { + public static String getScsiController(Pair controllerInfo) { String rootDiskController = controllerInfo.first(); String dataDiskController = controllerInfo.second(); - // If "osdefault" is specified as controller type, then translate to actual recommended controller. - if (VmwareHelper.isControllerOsRecommended(rootDiskController)) { - rootDiskController = recommendedController; - } - if (VmwareHelper.isControllerOsRecommended(dataDiskController)) { - dataDiskController = recommendedController; - } - - String scsiDiskController = null; //If any of the controller provided is SCSI then return it's sub-type. + String scsiDiskController; //If any of the controller provided is SCSI then return it's sub-type. if (isIdeController(rootDiskController) && isIdeController(dataDiskController)) { //Default controllers would exist return null; diff --git a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/util/VmwareHelper.java b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/util/VmwareHelper.java index 8a637721506..96b176df5f6 100644 --- a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/util/VmwareHelper.java +++ b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/util/VmwareHelper.java @@ -40,11 +40,14 @@ import javax.xml.datatype.DatatypeConfigurationException; import javax.xml.datatype.DatatypeFactory; import javax.xml.datatype.XMLGregorianCalendar; +import com.cloud.agent.api.to.DiskTO; import com.cloud.hypervisor.vmware.mo.ClusterMO; import com.cloud.hypervisor.vmware.mo.DatastoreFile; import com.cloud.hypervisor.vmware.mo.DistributedVirtualSwitchMO; import com.cloud.hypervisor.vmware.mo.HypervisorHostHelper; import com.cloud.serializer.GsonHelper; +import com.cloud.storage.Volume; +import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.net.NetUtils; import com.vmware.vim25.DatastoreInfo; import com.vmware.vim25.DistributedVirtualPort; @@ -1063,4 +1066,76 @@ public class VmwareHelper { } return vmdkAbsFile; } + + /** + * Validates an instance's rootDiskController and dataDiskController details. Throws a + * CloudRuntimeException if they are invalid. + */ + public static void validateDiskControllerDetails(String rootDiskControllerDetail, String dataDiskControllerDetail) { + rootDiskControllerDetail = DiskControllerType.getType(rootDiskControllerDetail).toString(); + if (DiskControllerType.getType(rootDiskControllerDetail) == DiskControllerType.none) { + throw new CloudRuntimeException(String.format("[%s] is not a valid root disk controller", rootDiskControllerDetail)); + } + dataDiskControllerDetail = DiskControllerType.getType(dataDiskControllerDetail).toString(); + if (DiskControllerType.getType(dataDiskControllerDetail) == DiskControllerType.none) { + throw new CloudRuntimeException(String.format("[%s] is not a valid data disk controller", dataDiskControllerDetail)); + } + } + + /** + * Based on an instance's rootDiskController and dataDiskController details, returns a pair + * containing the disk controllers that should be used for root disk and the data disks, respectively. + * + * @param controllerInfo pair containing the root disk and data disk controllers, respectively. + * @param vmMo virtual machine to derive the recommended disk controllers from. If not null, host and guestOsIdentifier will be ignored. + * @param host host to derive the recommended disk controllers from. Must be provided with guestOsIdentifier. + * @param guestOsIdentifier used to derive the recommended disk controllers from the host. + */ + public static Pair chooseRequiredDiskControllers(Pair controllerInfo, VirtualMachineMO vmMo, + VmwareHypervisorHost host, String guestOsIdentifier) throws Exception { + String recommendedDiskControllerClassName = vmMo != null ? vmMo.getRecommendedDiskController(null) : host.getRecommendedDiskController(guestOsIdentifier); + String recommendedDiskController = DiskControllerType.getType(recommendedDiskControllerClassName).toString(); + + String convertedRootDiskController = controllerInfo.first(); + if (isControllerOsRecommended(convertedRootDiskController)) { + convertedRootDiskController = recommendedDiskController; + } + + String convertedDataDiskController = controllerInfo.second(); + if (isControllerOsRecommended(convertedDataDiskController)) { + convertedDataDiskController = recommendedDiskController; + } + + if (diskControllersShareTheSameBusType(convertedRootDiskController, convertedDataDiskController)) { + s_logger.debug("Root and data disk controllers share the same bus type; therefore, we will only use the controllers specified for the root disk."); + return new Pair<>(convertedRootDiskController, convertedRootDiskController); + } + + return new Pair<>(convertedRootDiskController, convertedDataDiskController); + } + + protected static boolean diskControllersShareTheSameBusType(String rootDiskController, String dataDiskController) { + DiskControllerType rootDiskControllerType = DiskControllerType.getType(rootDiskController); + DiskControllerType dataDiskControllerType = DiskControllerType.getType(dataDiskController); + if (rootDiskControllerType.equals(dataDiskControllerType)) { + return true; + } + List scsiDiskControllers = List.of(DiskControllerType.scsi, DiskControllerType.lsilogic, DiskControllerType.lsisas1068, + DiskControllerType.buslogic ,DiskControllerType.pvscsi); + return scsiDiskControllers.contains(rootDiskControllerType) && scsiDiskControllers.contains(dataDiskControllerType); + } + + /** + * Identifies whether the disk is a root or data disk, and returns the controller from the provided pair that should + * be used for the disk. + * @param controllerInfo pair containing the root disk and data disk controllers, respectively. + */ + public static String getControllerBasedOnDiskType(Pair controllerInfo, DiskTO disk) { + if (disk.getType() == Volume.Type.ROOT || disk.getDiskSeq() == 0) { + s_logger.debug(String.format("Choosing disk controller [%s] for the root disk.", controllerInfo.first())); + return controllerInfo.first(); + } + s_logger.debug(String.format("Choosing disk controller [%s] for the data disks.", controllerInfo.second())); + return controllerInfo.second(); + } }