From 2d4464d2badc9aff842fd180bafc4c384a83a91d Mon Sep 17 00:00:00 2001 From: Alex Huang Date: Fri, 19 Jul 2013 08:29:07 -0700 Subject: [PATCH 01/74] Applied review request 12685 --- api/src/com/cloud/network/Networks.java | 81 ++++++++++++++++---- api/test/com/cloud/network/NetworksTest.java | 76 ++++++++++++++++++ 2 files changed, 144 insertions(+), 13 deletions(-) create mode 100644 api/test/com/cloud/network/NetworksTest.java diff --git a/api/src/com/cloud/network/Networks.java b/api/src/com/cloud/network/Networks.java index 5aede053d50..c76c3d4a473 100755 --- a/api/src/com/cloud/network/Networks.java +++ b/api/src/com/cloud/network/Networks.java @@ -23,7 +23,7 @@ import com.cloud.utils.exception.CloudRuntimeException; /** * Network includes all of the enums used within networking. - * + * */ public class Networks { @@ -66,8 +66,8 @@ public class Networks { Pvlan("pvlan", String.class), UnDecided(null, null); - private String scheme; - private Class type; + private final String scheme; + private final Class type; private BroadcastDomainType(String scheme, Class type) { this.scheme = scheme; @@ -75,14 +75,16 @@ public class Networks { } /** - * @return scheme to be used in broadcast uri. Null indicates that this type does not have broadcast tags. + * @return scheme to be used in broadcast uri. Null indicates that this + * type does not have broadcast tags. */ public String scheme() { return scheme; } /** - * @return type of the value in the broadcast uri. Null indicates that this type does not have broadcast tags. + * @return type of the value in the broadcast uri. Null indicates that + * this type does not have broadcast tags. */ public Class type() { return type; @@ -90,9 +92,56 @@ public class Networks { public URI toUri(T value) { try { - return new URI(scheme + "://" + value); + // do we need to check that value does not contain a scheme + // part? + if (value.toString().contains(":")) + return new URI(value.toString()); + else + return new URI(scheme, value.toString(), null); } catch (URISyntaxException e) { - throw new CloudRuntimeException("Unable to convert to broadcast URI: " + value); + throw new CloudRuntimeException( + "Unable to convert to broadcast URI: " + value); + } + } + + public static BroadcastDomainType getTypeOf(URI uri) { + return getType(uri.getScheme()); + } + + public static BroadcastDomainType getTypeOf(String str) + throws URISyntaxException { + return getTypeOf(new URI(str)); + } + + public static BroadcastDomainType getType(String scheme) { + if (scheme == null) { + return UnDecided; + } + for (BroadcastDomainType type : values()) { + if (scheme.equalsIgnoreCase(type.scheme())) { + return type; + } + } + return UnDecided; + } + + public static String getValue(String uriString) + throws URISyntaxException { + return getValue(new URI(uriString)); + } + + public static String getValue(URI uri) { + BroadcastDomainType type = getTypeOf(uri); + if (type == Vlan) { + // do complicated stuff for backward compatibility + try { + Long.parseLong(uri.getSchemeSpecificPart()); + return uri.getSchemeSpecificPart(); + } catch (NumberFormatException e) { + return uri.getHost(); + } + } else { + return uri.getSchemeSpecificPart(); } } }; @@ -110,8 +159,7 @@ public class Networks { Vpn; public static boolean isSystemNetwork(TrafficType trafficType) { - if (Storage.equals(trafficType) - || Management.equals(trafficType) + if (Storage.equals(trafficType) || Management.equals(trafficType) || Control.equals(trafficType)) { return true; } @@ -163,11 +211,18 @@ public class Networks { public URI toUri(T value) { try { - // assert(this!=Vlan || value.getClass().isAssignableFrom(Integer.class)) : + // assert(this!=Vlan || + // value.getClass().isAssignableFrom(Integer.class)) : + // do we need to check that value does not contain a scheme + // part? // "Why are you putting non integer into vlan url"; - return new URI(scheme + "://" + value.toString()); + if (value.toString().contains(":")) + return new URI(value.toString()); + else + return new URI(scheme, value.toString(), null); } catch (URISyntaxException e) { - throw new CloudRuntimeException("Unable to convert to isolation type URI: " + value); + throw new CloudRuntimeException( + "Unable to convert to isolation type URI: " + value); } } } @@ -176,7 +231,7 @@ public class Networks { Vlan("vlan"), VSwitch("vswitch"); - private String scheme; + private final String scheme; private BroadcastScheme(String scheme) { this.scheme = scheme; diff --git a/api/test/com/cloud/network/NetworksTest.java b/api/test/com/cloud/network/NetworksTest.java new file mode 100644 index 00000000000..31114e86283 --- /dev/null +++ b/api/test/com/cloud/network/NetworksTest.java @@ -0,0 +1,76 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package com.cloud.network; + +import java.net.URISyntaxException; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.cloud.network.Networks.BroadcastDomainType; + +/** + * @author dhoogland + * + */ +public class NetworksTest { + + @Before + public void setUp() { + } + + @Test + public void emptyBroadcastDomainTypeTest() throws URISyntaxException { + BroadcastDomainType type = BroadcastDomainType.getTypeOf(""); + Assert.assertEquals( + "an empty uri should mean a broadcasttype of undecided", + BroadcastDomainType.UnDecided, type); + } + + @Test + public void vlanBroadcastDomainTypeTest() throws URISyntaxException { + String uri1 = "vlan://1"; + String uri2 = "vlan:2"; + BroadcastDomainType type1 = BroadcastDomainType.getTypeOf(uri1); + BroadcastDomainType type2 = BroadcastDomainType.getTypeOf(uri2); + String id1 = BroadcastDomainType.getValue(uri1); + String id2 = BroadcastDomainType.getValue(uri2); + Assert.assertEquals("uri1 should be of broadcasttype vlan", + BroadcastDomainType.Vlan, type1); + Assert.assertEquals("uri2 should be of broadcasttype vlan", + BroadcastDomainType.Vlan, type2); + Assert.assertEquals("id1 should be \"1\"", "1", id1); + Assert.assertEquals("id1 should be \"2\"", "2", id2); + } + + @Test + public void otherTypesTest() throws URISyntaxException { + String bogeyUri = "lswitch://1"; + String uri2 = "mido:2"; + BroadcastDomainType type1 = BroadcastDomainType.getTypeOf(bogeyUri); + BroadcastDomainType type2 = BroadcastDomainType.getTypeOf(uri2); + String id1 = BroadcastDomainType.getValue(bogeyUri); + String id2 = BroadcastDomainType.getValue(uri2); + Assert.assertEquals("uri1 should be of broadcasttype vlan", + BroadcastDomainType.Lswitch, type1); + Assert.assertEquals("uri2 should be of broadcasttype vlan", + BroadcastDomainType.Mido, type2); + Assert.assertEquals("id1 should be \"//1\"", "//1", id1); + Assert.assertEquals("id1 should be \"2\"", "2", id2); + } +} From 1c21a6296aad0ac262436bb8dc9cbcd61ee50c8a Mon Sep 17 00:00:00 2001 From: Marcus Sorensen Date: Fri, 19 Jul 2013 14:07:59 -0600 Subject: [PATCH 02/74] Summary: devcloud-kvm marvin zone config fix for 4.2, add provider to img store Signed-off-by: Marcus Sorensen 1374264479 -0600 --- tools/devcloud-kvm/devcloud-kvm-advanced.cfg | 3 ++- tools/devcloud-kvm/devcloud-kvm.cfg | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/tools/devcloud-kvm/devcloud-kvm-advanced.cfg b/tools/devcloud-kvm/devcloud-kvm-advanced.cfg index 10cbce00779..45bdfceb0ef 100644 --- a/tools/devcloud-kvm/devcloud-kvm-advanced.cfg +++ b/tools/devcloud-kvm/devcloud-kvm-advanced.cfg @@ -103,7 +103,8 @@ "internaldns1": "8.8.4.4", "secondaryStorages": [ { - "url": "nfs://172.17.10.10:/nfs/secondary" + "url": "nfs://172.17.10.10:/nfs/secondary", + "provider": "NFS" } ] } diff --git a/tools/devcloud-kvm/devcloud-kvm.cfg b/tools/devcloud-kvm/devcloud-kvm.cfg index 9f310e32755..3122e5a9790 100644 --- a/tools/devcloud-kvm/devcloud-kvm.cfg +++ b/tools/devcloud-kvm/devcloud-kvm.cfg @@ -85,7 +85,8 @@ "internaldns1": "192.168.100.10", "secondaryStorages": [ { - "url": "nfs://192.168.100.10:/nfs/secondary" + "url": "nfs://192.168.100.10:/nfs/secondary", + "provider": "NFS" } ] } From 823c72552e82a7210a2156cd0e1d1be6c55bfb4b Mon Sep 17 00:00:00 2001 From: Alena Prokharchyk Date: Fri, 19 Jul 2013 12:59:42 -0700 Subject: [PATCH 03/74] InternalLb: fixed creation for default network offering with internal lb support - public lb support should be disbaled on it --- engine/schema/src/com/cloud/offerings/NetworkOfferingVO.java | 4 ++++ server/src/com/cloud/network/NetworkManagerImpl.java | 1 + 2 files changed, 5 insertions(+) diff --git a/engine/schema/src/com/cloud/offerings/NetworkOfferingVO.java b/engine/schema/src/com/cloud/offerings/NetworkOfferingVO.java index f8f25ea2582..b0cb85d40bf 100755 --- a/engine/schema/src/com/cloud/offerings/NetworkOfferingVO.java +++ b/engine/schema/src/com/cloud/offerings/NetworkOfferingVO.java @@ -436,4 +436,8 @@ public class NetworkOfferingVO implements NetworkOffering { public void setConcurrentConnections(Integer concurrent_connections) { this.concurrent_connections = concurrent_connections; } + + public void setPublicLb(boolean publicLb) { + this.publicLb = publicLb; + } } diff --git a/server/src/com/cloud/network/NetworkManagerImpl.java b/server/src/com/cloud/network/NetworkManagerImpl.java index 196f7de0ba0..279ea848a8d 100755 --- a/server/src/com/cloud/network/NetworkManagerImpl.java +++ b/server/src/com/cloud/network/NetworkManagerImpl.java @@ -1429,6 +1429,7 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L true, Network.GuestType.Isolated, false, null, false, null, false, false, null, false, null); offering.setState(NetworkOffering.State.Enabled); offering.setInternalLb(true); + offering.setPublicLb(false); _networkOfferingDao.update(offering.getId(), offering); } From cd6853cc1a16a033717707e8567c55a406935961 Mon Sep 17 00:00:00 2001 From: Edison Su Date: Fri, 19 Jul 2013 13:26:19 -0700 Subject: [PATCH 04/74] CLOUDSTACK-732 Add disk snapshot for KVM 6.3, add the flag in CS. Signed-off-by: Edison Su Conflicts: engine/schema/src/com/cloud/upgrade/dao/Upgrade410to420.java --- .../cloud/upgrade/dao/Upgrade410to420.java | 44 +++++++++++++++++-- .../src/com/cloud/configuration/Config.java | 1 + .../storage/snapshot/SnapshotManagerImpl.java | 6 +++ 3 files changed, 48 insertions(+), 3 deletions(-) diff --git a/engine/schema/src/com/cloud/upgrade/dao/Upgrade410to420.java b/engine/schema/src/com/cloud/upgrade/dao/Upgrade410to420.java index 0cf6b5b1109..d4b7b6d353b 100644 --- a/engine/schema/src/com/cloud/upgrade/dao/Upgrade410to420.java +++ b/engine/schema/src/com/cloud/upgrade/dao/Upgrade410to420.java @@ -90,6 +90,7 @@ public class Upgrade410to420 implements DbUpgrade { correctExternalNetworkDevicesSetup(conn); removeFirewallServiceFromSharedNetworkOfferingWithSGService(conn); fix22xKVMSnapshots(conn); + setKVMSnapshotFlag(conn); addIndexForAlert(conn); fixBaremetalForeignKeys(conn); // storage refactor related migration @@ -297,9 +298,46 @@ public class Upgrade410to420 implements DbUpgrade { */ } - private void updatePrimaryStore(Connection conn) { - PreparedStatement sql = null; - PreparedStatement sql2 = null; + //KVM snapshot flag: only turn on if Customers is using snapshot; + private void setKVMSnapshotFlag(Connection conn) { + s_logger.debug("Verify and set the KVM snapshot flag if snapshot was used. "); + PreparedStatement pstmt = null; + ResultSet rs = null; + try { + int numRows = 0; + pstmt = conn.prepareStatement("select count(*) from `cloud`.`snapshots` where hypervisor_type = 'KVM'"); + rs = pstmt.executeQuery(); + if(rs.next()){ + numRows = rs.getInt(1); + } + rs.close(); + pstmt.close(); + if (numRows > 0){ + //Add the configuration flag + pstmt = conn.prepareStatement("UPDATE `cloud`.`configuration` SET value = ? WHERE name = 'KVM.snapshot.enabled'"); + pstmt.setString(1, "true"); + pstmt.executeUpdate(); + } + } catch (SQLException e) { + throw new CloudRuntimeException("Failed to read the snapshot table for KVM upgrade. ", e); + } finally { + try { + if (rs != null) { + rs.close(); + } + + if (pstmt != null) { + pstmt.close(); + } + } catch (SQLException e) { + } + } + s_logger.debug("Done set KVM snapshot flag. "); + } + + private void updatePrimaryStore(Connection conn) { + PreparedStatement sql = null; + PreparedStatement sql2 = null; try { sql = conn.prepareStatement("update storage_pool set storage_provider_name = ? , scope = ? where pool_type = 'Filesystem' or pool_type = 'LVM'"); sql.setString(1, DataStoreProvider.DEFAULT_PRIMARY); diff --git a/server/src/com/cloud/configuration/Config.java b/server/src/com/cloud/configuration/Config.java index bb0237c172f..8153dd6daa6 100755 --- a/server/src/com/cloud/configuration/Config.java +++ b/server/src/com/cloud/configuration/Config.java @@ -145,6 +145,7 @@ public enum Config { SnapshotPollInterval("Snapshots", SnapshotManager.class, Integer.class, "snapshot.poll.interval", "300", "The time interval in seconds when the management server polls for snapshots to be scheduled.", null), SnapshotDeltaMax("Snapshots", SnapshotManager.class, Integer.class, "snapshot.delta.max", "16", "max delta snapshots between two full snapshots.", null), BackupSnapshotAferTakingSnapshot("Snapshots", SnapshotManager.class, Boolean.class, "snapshot.backup.rightafter", "true", "backup snapshot right after snapshot is taken", null), + KVMSnapshotEnabled("Snapshots", SnapshotManager.class, Boolean.class, "KVM.snapshot.enabled", "false", "whether snapshot is enabled for KVM hosts", null), // Advanced JobExpireMinutes("Advanced", ManagementServer.class, String.class, "job.expire.minutes", "1440", "Time (in minutes) for async-jobs to be kept in system", null), diff --git a/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java b/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java index d766f7a09d1..123c5957baa 100755 --- a/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java +++ b/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java @@ -910,6 +910,12 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager, if (host.getHypervisorType() != HypervisorType.KVM) { return true; } + + //Turn off snapshot by default for KVM, unless it is set in the global flag + boolean snapshotEnabled = Boolean.parseBoolean(_configDao.getValue("KVM.snapshot.enabled")); + if (!snapshotEnabled) { + return false; + } // Determine host capabilities String caps = host.getCapabilities(); From 0cdda2988ffdd8cb2c63a056bb7cb148e39fe7bf Mon Sep 17 00:00:00 2001 From: Jessica Wang Date: Fri, 19 Jul 2013 15:17:14 -0700 Subject: [PATCH 05/74] CLOUDSTACK-3651: Infrastructure menu - zone detail - listVmwareDcs API only exists in non-oss build, suppress error "The given command does not exist or it is not avaiable for user" from UI for this specific case. --- ui/scripts/system.js | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/ui/scripts/system.js b/ui/scripts/system.js index c2fca60b000..4da35115630 100644 --- a/ui/scripts/system.js +++ b/ui/scripts/system.js @@ -6473,7 +6473,7 @@ }); $.ajax({ - url: createURL('listVmwareDcs'), + url: createURL('listVmwareDcs'), //listVmwareDcs API exists in only non-oss bild data: { zoneid: args.context.physicalResources[0].id }, @@ -6485,15 +6485,21 @@ selectedZoneObj.vmwaredcVcenter = vmwaredcs[0].vcenter; selectedZoneObj.vmwaredcId = vmwaredcs[0].id; } + }, + error: function(XMLHttpResponse) { //override default error handling: cloudStack.dialog.notice({ message: parseXMLHttpResponse(XMLHttpResponse)}); + if(parseXMLHttpResponse(XMLHttpResponse) == 'The given command does not exist or it is not available for user') + return; //do nothing + else + cloudStack.dialog.notice({ message: parseXMLHttpResponse(XMLHttpResponse)}); //pop up error dialog box if the error is not 'The given command does not exist or it is not available for user' } }); // for testing only (begin) /* - selectedZoneObj.vmwaredcName = "datacenter"; - selectedZoneObj.vmwaredcVcenter = "10.10.20.20"; - selectedZoneObj.vmwaredcId = "c3c2562d-65e9-4fc7-92e2-773c2efe8f37"; - */ + selectedZoneObj.vmwaredcName = "datacenter"; + selectedZoneObj.vmwaredcVcenter = "10.10.20.20"; + selectedZoneObj.vmwaredcId = "c3c2562d-65e9-4fc7-92e2-773c2efe8f37"; + */ // for testing only (end) args.response.success({ From 0633608f8035f8f409c271fc6e7548699a63d366 Mon Sep 17 00:00:00 2001 From: frank Date: Fri, 19 Jul 2013 16:15:17 -0700 Subject: [PATCH 06/74] CLOUDSTACK-3453 UCS:API: List Blades after decommissioning a blade, listUcsBlades API returns wrong number of total blades fixed resolved --- .../com/cloud/ucs/manager/UcsManagerImpl.java | 86 ++++++++++++++++++- .../src/com/cloud/configuration/Config.java | 4 +- 2 files changed, 87 insertions(+), 3 deletions(-) diff --git a/plugins/hypervisors/ucs/src/com/cloud/ucs/manager/UcsManagerImpl.java b/plugins/hypervisors/ucs/src/com/cloud/ucs/manager/UcsManagerImpl.java index ee75f1b1a39..f9e2c5a039b 100755 --- a/plugins/hypervisors/ucs/src/com/cloud/ucs/manager/UcsManagerImpl.java +++ b/plugins/hypervisors/ucs/src/com/cloud/ucs/manager/UcsManagerImpl.java @@ -22,14 +22,14 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.UUID; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import javax.ejb.Local; import javax.inject.Inject; import javax.naming.ConfigurationException; -import org.apache.log4j.Logger; - import org.apache.cloudstack.api.AddUcsManagerCmd; import org.apache.cloudstack.api.AssociateUcsProfileToBladeCmd; import org.apache.cloudstack.api.ListUcsBladeCmd; @@ -39,7 +39,10 @@ import org.apache.cloudstack.api.response.ListResponse; import org.apache.cloudstack.api.response.UcsBladeResponse; import org.apache.cloudstack.api.response.UcsManagerResponse; import org.apache.cloudstack.api.response.UcsProfileResponse; +import org.apache.log4j.Logger; +import com.cloud.configuration.Config; +import com.cloud.configuration.dao.ConfigurationDao; import com.cloud.dc.ClusterDetailsDao; import com.cloud.dc.DataCenterVO; import com.cloud.dc.dao.ClusterDao; @@ -54,6 +57,7 @@ import com.cloud.ucs.database.UcsManagerVO; import com.cloud.ucs.structure.ComputeBlade; import com.cloud.ucs.structure.UcsCookie; import com.cloud.ucs.structure.UcsProfile; +import com.cloud.utils.concurrency.NamedThreadFactory; import com.cloud.utils.db.DB; import com.cloud.utils.db.SearchCriteria.Op; import com.cloud.utils.db.SearchCriteria2; @@ -83,11 +87,86 @@ public class UcsManagerImpl implements UcsManager { private HostDao hostDao; @Inject private DataCenterDao dcDao; + @Inject + private ConfigurationDao configDao; private final Map cookies = new HashMap(); private String name; private int runLevel; private Map params; + private ScheduledExecutorService syncBladesExecutor; + private int syncBladeInterval; + + private class SyncBladesThread implements Runnable { + + private void discoverNewBlades(Map previous, + Map now, UcsManagerVO mgr) { + for (Map.Entry e : now.entrySet()) { + String dn = e.getKey(); + if (previous.keySet().contains(dn)) { + continue; + } + + ComputeBlade nc = e.getValue(); + UcsBladeVO vo = new UcsBladeVO(); + vo.setDn(nc.getDn()); + vo.setUcsManagerId(mgr.getId()); + vo.setUuid(UUID.randomUUID().toString()); + bladeDao.persist(vo); + s_logger.debug(String.format("discovered a new UCS blade[dn:%s] during sync", nc.getDn())); + } + } + + private void decommissionFadedBlade(Map previous, Map now) { + for (Map.Entry e : previous.entrySet()) { + String dn = e.getKey(); + if (now.keySet().contains(dn)) { + continue; + } + + UcsBladeVO vo = e.getValue(); + bladeDao.remove(vo.getId()); + s_logger.debug(String.format("decommission faded blade[dn:%s] during sync", vo.getDn())); + } + } + + private void syncBlades(UcsManagerVO mgr) { + SearchCriteriaService q = SearchCriteria2.create(UcsBladeVO.class); + q.addAnd(q.getEntity().getUcsManagerId(), Op.EQ, mgr.getId()); + List pblades = q.list(); + if (pblades.isEmpty()) { + return; + } + + + Map previousBlades = new HashMap(pblades.size()); + for (UcsBladeVO b : pblades) { + previousBlades.put(b.getDn(), b); + } + + List cblades = listBlades(mgr.getId()); + Map currentBlades = new HashMap(cblades.size()); + for (ComputeBlade c : cblades) { + currentBlades.put(c.getDn(), c); + } + + discoverNewBlades(previousBlades, currentBlades, mgr); + decommissionFadedBlade(previousBlades, currentBlades); + } + + @Override + public void run() { + try { + List mgrs = ucsDao.listAll(); + for (UcsManagerVO mgr : mgrs) { + syncBlades(mgr); + } + } catch (Throwable t) { + s_logger.warn(t.getMessage(), t); + } + } + + } @Override public boolean configure(String name, Map params) throws ConfigurationException { @@ -96,6 +175,9 @@ public class UcsManagerImpl implements UcsManager { @Override public boolean start() { + syncBladeInterval = Integer.valueOf(configDao.getValue(Config.UCSSyncBladeInterval.key())); + syncBladesExecutor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("UCS-SyncBlades")); + syncBladesExecutor.scheduleAtFixedRate(new SyncBladesThread(), syncBladeInterval, syncBladeInterval, TimeUnit.SECONDS); return true; } diff --git a/server/src/com/cloud/configuration/Config.java b/server/src/com/cloud/configuration/Config.java index 8153dd6daa6..c815c771290 100755 --- a/server/src/com/cloud/configuration/Config.java +++ b/server/src/com/cloud/configuration/Config.java @@ -437,7 +437,9 @@ public enum Config { ExecuteInSequence("Advanced", ManagementServer.class, Boolean.class, "execute.in.sequence.hypervisor.commands", "false", "If set to true, StartCommand, StopCommand, CopyCommand will be synchronized on the agent side." + " If set to false, these commands become asynchronous. Default value is false.", null), ExecuteInSequenceNetworkElementCommands("Advanced", NetworkManager.class, Boolean.class, "execute.in.sequence.network.element.commands", "false", "If set to true, DhcpEntryCommand, SavePasswordCommand, UserDataCommand, VmDataCommand will be synchronized on the agent side." + - " If set to false, these commands become asynchronous. Default value is false.", null); + " If set to false, these commands become asynchronous. Default value is false.", null), + + UCSSyncBladeInterval("Advanced", ManagementServer.class, Integer.class, "ucs.sync.blade.interval", "3600", "the interval cloudstack sync with UCS manager for available blades in case user remove blades from chassis without notifying CloudStack", null); private final String _category; private final Class _componentClass; From 24fc147ee87306c35ca90d1c5dde391ddf2fc0a8 Mon Sep 17 00:00:00 2001 From: Min Chen Date: Fri, 19 Jul 2013 16:43:44 -0700 Subject: [PATCH 07/74] System Template shows twice in listTemplates with S3 as secondary storage. --- setup/db/db/schema-410to420.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup/db/db/schema-410to420.sql b/setup/db/db/schema-410to420.sql index 596723c9fa4..dd8c75a1237 100644 --- a/setup/db/db/schema-410to420.sql +++ b/setup/db/db/schema-410to420.sql @@ -1964,7 +1964,7 @@ CREATE VIEW `cloud`.`template_view` AS left join `cloud`.`vm_template` source_template ON source_template.id = vm_template.source_template_id left join - `cloud`.`template_store_ref` ON template_store_ref.template_id = vm_template.id + `cloud`.`template_store_ref` ON template_store_ref.template_id = vm_template.id and template_store_ref.store_role = 'Image' left join `cloud`.`image_store` ON image_store.removed is NULL AND template_store_ref.store_id is not NULL AND image_store.id = template_store_ref.store_id left join From 56fad8692097f264455c684d36a8c88795acc52f Mon Sep 17 00:00:00 2001 From: frank Date: Fri, 19 Jul 2013 17:46:27 -0700 Subject: [PATCH 08/74] CLOUDSTACK-3428 UCS:API: We need listUCSManager API to lists all UCS managers registered with CloudStack fix entityType in api command --- .../ucs/src/org/apache/cloudstack/api/ListUcsManagerCmd.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/hypervisors/ucs/src/org/apache/cloudstack/api/ListUcsManagerCmd.java b/plugins/hypervisors/ucs/src/org/apache/cloudstack/api/ListUcsManagerCmd.java index 4d4473d2b8b..228fbcb7330 100755 --- a/plugins/hypervisors/ucs/src/org/apache/cloudstack/api/ListUcsManagerCmd.java +++ b/plugins/hypervisors/ucs/src/org/apache/cloudstack/api/ListUcsManagerCmd.java @@ -36,6 +36,7 @@ import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.response.ListResponse; import org.apache.cloudstack.api.response.UcsManagerResponse; +import org.apache.cloudstack.api.response.ZoneResponse; import org.apache.log4j.Logger; import com.cloud.exception.ConcurrentOperationException; @@ -50,7 +51,7 @@ import com.cloud.user.Account; public class ListUcsManagerCmd extends BaseListCmd { public static final Logger s_logger = Logger.getLogger(ListUcsManagerCmd.class); - @Parameter(name=ApiConstants.ZONE_ID, type=CommandType.LONG, description="the zone id", required=true) + @Parameter(name=ApiConstants.ZONE_ID, type=CommandType.UUID, description="the zone id", entityType=ZoneResponse.class, required=true) private Long zoneId; @Inject From 88c84d91092f7f77bf7766a5164de90ac703bdc9 Mon Sep 17 00:00:00 2001 From: Sheng Yang Date: Fri, 19 Jul 2013 19:25:30 -0700 Subject: [PATCH 09/74] CLOUDSTACK-3643: Fix wrong protocol type and test case sequence --- test/integration/component/test_vpc.py | 373 +++++++++++++------------ 1 file changed, 187 insertions(+), 186 deletions(-) diff --git a/test/integration/component/test_vpc.py b/test/integration/component/test_vpc.py index 63c10aacdb2..c503be8045c 100644 --- a/test/integration/component/test_vpc.py +++ b/test/integration/component/test_vpc.py @@ -147,7 +147,7 @@ class Services: "startport": 80, "endport": 80, "cidrlist": '0.0.0.0/0', - "protocol": "ICMP" + "protocol": "TCP" }, "virtual_machine": { "displayname": "Test VM", @@ -275,9 +275,189 @@ class TestVPC(cloudstackTestCase): ) self.debug("VPC network validated - %s" % network.name) return - + + #list_vpc_apis should be the first case otherwise the vpc counts would be wrong @attr(tags=["advanced", "intervlan"]) - def test_01_restart_vpc_no_networks(self): + def test_01_list_vpc_apis(self): + """ Test list VPC APIs + """ + + # Validate the following + # 1. Create multiple VPCs + # 2. listVPCs() by name. VPC with the provided name should be listed. + # 3. listVPCs() by displayText. VPC with the provided displayText + # should be listed. + # 4. listVPCs() by cidr. All the VPCs with the provided cidr should + # be listed. + # 5. listVPCs() by vpcofferingId.All the VPCs with the vpcofferingId + # should be listed. + # 6. listVPCs() by supported Services(). All the VPCs that provide the + # list of services should be listed. + # 7. listVPCs() by restartRequired (set to true). All the VPCs that + # require restart should be listed. + + self.services["vpc"]["cidr"] = "10.1.1.1/16" + self.debug("creating a VPC network in the account: %s" % + self.account.name) + vpc_1 = VPC.create( + self.apiclient, + self.services["vpc"], + vpcofferingid=self.vpc_off.id, + zoneid=self.zone.id, + account=self.account.name, + domainid=self.account.domainid + ) + self.validate_vpc_network(vpc_1) + + self.services["vpc"]["cidr"] = "10.1.46.1/16" + vpc_2 = VPC.create( + self.apiclient, + self.services["vpc"], + vpcofferingid=self.vpc_off.id, + zoneid=self.zone.id, + account=self.account.name, + domainid=self.account.domainid + ) + self.validate_vpc_network(vpc_2) + + self.debug("Check list VPC API by Name?") + vpcs = VPC.list( + self.apiclient, + name=vpc_1.name, + listall=True + ) + self.assertEqual( + isinstance(vpcs, list), + True, + "List VPC shall return a valid resposne" + ) + vpc = vpcs[0] + self.assertEqual( + vpc.name, + vpc_1.name, + "VPC name should match with the existing one" + ) + + self.debug("Check list VPC API by displayText?") + vpcs = VPC.list( + self.apiclient, + displaytext=vpc_1.displaytext, + listall=True + ) + self.assertEqual( + isinstance(vpcs, list), + True, + "List VPC shall return a valid resposne" + ) + vpc = vpcs[0] + self.assertEqual( + vpc.displaytext, + vpc_1.displaytext, + "VPC displaytext should match with the existing one" + ) + + self.debug("Check list VPC API by cidr?") + vpcs = VPC.list( + self.apiclient, + cidr=vpc_2.cidr, + listall=True + ) + self.assertEqual( + isinstance(vpcs, list), + True, + "List VPC shall return a valid resposne" + ) + vpc = vpcs[0] + self.assertEqual( + vpc.cidr, + vpc_2.cidr, + "VPC cidr should match with the existing one" + ) + self.debug("Validating list VPC by Id") + self.validate_vpc_network(vpc_1) + + self.debug("Validating list VPC by vpcofferingId") + vpcs = VPC.list( + self.apiclient, + vpcofferingid=self.vpc_off.id, + listall=True + ) + self.assertEqual( + isinstance(vpcs, list), + True, + "List VPC by vpcofferingId should return a valid response" + ) + self.debug("Length of list VPC response: %s" % len(vpcs)) + self.assertEqual( + len(vpcs), + 2, + "List VPC should return 2 enabled VPCs" + ) + for vpc in vpcs: + self.assertEqual( + vpc.vpcofferingid, + self.vpc_off.id, + "VPC offering ID should match with that of resposne" + ) + + self.debug("Validating list VPC by supportedservices") + vpcs = VPC.list( + self.apiclient, + supportedservices='Vpn,Dhcp,Dns,SourceNat,PortForwarding,Lb,UserData,StaticNat,NetworkACL', + listall=True, + account=self.account.name, + domainid=self.account.domainid + ) + self.assertEqual( + isinstance(vpcs, list), + True, + "List VPC by vpcofferingId should return a valid response" + ) + for vpc in vpcs: + self.assertIn( + vpc.id, + [vpc_1.id, vpc_2.id], + "VPC offering ID should match with that of resposne" + ) + self.debug("Validating list VPC by restart required") + vpcs = VPC.list( + self.apiclient, + restartrequired=True, + listall=True, + account=self.account.name, + domainid=self.account.domainid + ) + if vpcs is not None: + for vpc in vpcs: + self.assertEqual( + vpc.restartrequired, + True, + "RestartRequired should be set as True" + ) + self.debug("Validating list VPC by restart required") + vpcs = VPC.list( + self.apiclient, + restartrequired=False, + listall=True, + account=self.account.name, + domainid=self.account.domainid + ) + self.assertEqual( + isinstance(vpcs, list), + True, + "List VPC by vpcofferingId should return a valid response" + ) + if vpcs is not None: + for vpc in vpcs: + self.assertEqual( + vpc.restartrequired, + False, + "RestartRequired should be set as False" + ) + return + + @attr(tags=["advanced", "intervlan"]) + def test_02_restart_vpc_no_networks(self): """ Test restart VPC having no networks """ @@ -308,7 +488,7 @@ class TestVPC(cloudstackTestCase): return @attr(tags=["advanced", "intervlan"]) - def test_02_restart_vpc_with_networks(self): + def test_03_restart_vpc_with_networks(self): """ Test restart VPC having networks """ @@ -393,7 +573,7 @@ class TestVPC(cloudstackTestCase): return @attr(tags=["advanced", "intervlan"]) - def test_03_delete_vpc_no_networks(self): + def test_04_delete_vpc_no_networks(self): """ Test delete VPC having no networks """ @@ -433,7 +613,7 @@ class TestVPC(cloudstackTestCase): return @attr(tags=["advanced", "intervlan"]) - def test_04_delete_vpc_with_networks(self): + def test_05_delete_vpc_with_networks(self): """ Test delete VPC having networks """ @@ -563,185 +743,6 @@ class TestVPC(cloudstackTestCase): ) return - @attr(tags=["advanced", "intervlan"]) - def test_05_list_vpc_apis(self): - """ Test list VPC APIs - """ - - # Validate the following - # 1. Create multiple VPCs - # 2. listVPCs() by name. VPC with the provided name should be listed. - # 3. listVPCs() by displayText. VPC with the provided displayText - # should be listed. - # 4. listVPCs() by cidr. All the VPCs with the provided cidr should - # be listed. - # 5. listVPCs() by vpcofferingId.All the VPCs with the vpcofferingId - # should be listed. - # 6. listVPCs() by supported Services(). All the VPCs that provide the - # list of services should be listed. - # 7. listVPCs() by restartRequired (set to true). All the VPCs that - # require restart should be listed. - - self.services["vpc"]["cidr"] = "10.1.1.1/16" - self.debug("creating a VPC network in the account: %s" % - self.account.name) - vpc_1 = VPC.create( - self.apiclient, - self.services["vpc"], - vpcofferingid=self.vpc_off.id, - zoneid=self.zone.id, - account=self.account.name, - domainid=self.account.domainid - ) - self.validate_vpc_network(vpc_1) - - self.services["vpc"]["cidr"] = "10.1.46.1/16" - vpc_2 = VPC.create( - self.apiclient, - self.services["vpc"], - vpcofferingid=self.vpc_off.id, - zoneid=self.zone.id, - account=self.account.name, - domainid=self.account.domainid - ) - self.validate_vpc_network(vpc_2) - - self.debug("Check list VPC API by Name?") - vpcs = VPC.list( - self.apiclient, - name=vpc_1.name, - listall=True - ) - self.assertEqual( - isinstance(vpcs, list), - True, - "List VPC shall return a valid resposne" - ) - vpc = vpcs[0] - self.assertEqual( - vpc.name, - vpc_1.name, - "VPC name should match with the existing one" - ) - - self.debug("Check list VPC API by displayText?") - vpcs = VPC.list( - self.apiclient, - displaytext=vpc_1.displaytext, - listall=True - ) - self.assertEqual( - isinstance(vpcs, list), - True, - "List VPC shall return a valid resposne" - ) - vpc = vpcs[0] - self.assertEqual( - vpc.displaytext, - vpc_1.displaytext, - "VPC displaytext should match with the existing one" - ) - - self.debug("Check list VPC API by cidr?") - vpcs = VPC.list( - self.apiclient, - cidr=vpc_2.cidr, - listall=True - ) - self.assertEqual( - isinstance(vpcs, list), - True, - "List VPC shall return a valid resposne" - ) - vpc = vpcs[0] - self.assertEqual( - vpc.cidr, - vpc_2.cidr, - "VPC cidr should match with the existing one" - ) - self.debug("Validating list VPC by Id") - self.validate_vpc_network(vpc_1) - - self.debug("Validating list VPC by vpcofferingId") - vpcs = VPC.list( - self.apiclient, - vpcofferingid=self.vpc_off.id, - listall=True - ) - self.assertEqual( - isinstance(vpcs, list), - True, - "List VPC by vpcofferingId should return a valid response" - ) - self.debug("Length of list VPC response: %s" % len(vpcs)) - self.assertEqual( - len(vpcs), - 2, - "List VPC should return 3 enabled VPCs" - ) - for vpc in vpcs: - self.assertEqual( - vpc.vpcofferingid, - self.vpc_off.id, - "VPC offering ID should match with that of resposne" - ) - - self.debug("Validating list VPC by supportedservices") - vpcs = VPC.list( - self.apiclient, - supportedservices='Vpn,Dhcp,Dns,SourceNat,PortForwarding,Lb,UserData,StaticNat,NetworkACL', - listall=True, - account=self.account.name, - domainid=self.account.domainid - ) - self.assertEqual( - isinstance(vpcs, list), - True, - "List VPC by vpcofferingId should return a valid response" - ) - for vpc in vpcs: - self.assertIn( - vpc.id, - [vpc_1.id, vpc_2.id], - "VPC offering ID should match with that of resposne" - ) - self.debug("Validating list VPC by restart required") - vpcs = VPC.list( - self.apiclient, - restartrequired=True, - listall=True, - account=self.account.name, - domainid=self.account.domainid - ) - if vpcs is not None: - for vpc in vpcs: - self.assertEqual( - vpc.restartrequired, - True, - "RestartRequired should be set as True" - ) - self.debug("Validating list VPC by restart required") - vpcs = VPC.list( - self.apiclient, - restartrequired=False, - listall=True, - account=self.account.name, - domainid=self.account.domainid - ) - self.assertEqual( - isinstance(vpcs, list), - True, - "List VPC by vpcofferingId should return a valid response" - ) - if vpcs is not None: - for vpc in vpcs: - self.assertEqual( - vpc.restartrequired, - False, - "RestartRequired should be set as False" - ) - return - @attr(tags=["advanced", "intervlan"]) def test_06_list_vpc_apis_admin(self): """ Test list VPC APIs for different user roles @@ -2404,4 +2405,4 @@ class TestVPC(cloudstackTestCase): self.assertEqual(vpc_networks[0].displaytext, new_display_text, - "Updation of VPC display text failed.") \ No newline at end of file + "Updation of VPC display text failed.") From ecfeaa1037b18920ce3c734fa67f0ab309d46956 Mon Sep 17 00:00:00 2001 From: Sanjay Tripathi Date: Fri, 19 Jul 2013 20:39:02 +0530 Subject: [PATCH 10/74] CLOUDSTACK-3620: [Automation] API removevpnuser failed, in test case test_project_usage.TestVpnUsage.test_01_vpn_usage. Signed-off-by: Prasanna Santhanam --- test/integration/component/test_project_usage.py | 5 ++++- tools/marvin/marvin/integration/lib/base.py | 9 ++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/test/integration/component/test_project_usage.py b/test/integration/component/test_project_usage.py index bb253e1c04a..1422febf975 100644 --- a/test/integration/component/test_project_usage.py +++ b/test/integration/component/test_project_usage.py @@ -1659,7 +1659,10 @@ class TestVpnUsage(cloudstackTestCase): # Remove VPN user self.debug("Deleting VPN user: %s" % vpnuser.id) - vpnuser.delete(self.apiclient) + vpnuser.delete( + self.apiclient, + projectid=self.project.id + ) # Delete VPN access self.debug("Deleting VPN: %s" % vpn.publicipid) diff --git a/tools/marvin/marvin/integration/lib/base.py b/tools/marvin/marvin/integration/lib/base.py index 13507bc8ac4..03c0707d335 100755 --- a/tools/marvin/marvin/integration/lib/base.py +++ b/tools/marvin/marvin/integration/lib/base.py @@ -2100,13 +2100,16 @@ class VpnUser: cmd.projectid = projectid return VpnUser(apiclient.addVpnUser(cmd).__dict__) - def delete(self, apiclient): + def delete(self, apiclient, projectid=None): """Remove VPN user""" cmd = removeVpnUser.removeVpnUserCmd() cmd.username = self.username - cmd.account = self.account - cmd.domainid = self.domainid + if projectid: + cmd.projectid = projectid + else: + cmd.account = self.account + cmd.domainid = self.domainid apiclient.removeVpnUser(cmd) @classmethod From 4f8c43fc2089e455aaad8203c01d44ed409d0c32 Mon Sep 17 00:00:00 2001 From: Gaurav Aradhye Date: Fri, 19 Jul 2013 02:16:16 -0400 Subject: [PATCH 11/74] CLOUDSTACK:3452: Check if security groups feature is enabled in basic zone before creating security group while creating VM Signed-off-by: Prasanna Santhanam (cherry picked from commit 3c360ce02807240586d471ab4c0cbd24d76ed7e6) --- tools/marvin/marvin/integration/lib/base.py | 57 ++++++++++++--------- 1 file changed, 34 insertions(+), 23 deletions(-) diff --git a/tools/marvin/marvin/integration/lib/base.py b/tools/marvin/marvin/integration/lib/base.py index 03c0707d335..0938333c06c 100755 --- a/tools/marvin/marvin/integration/lib/base.py +++ b/tools/marvin/marvin/integration/lib/base.py @@ -294,40 +294,51 @@ class VirtualMachine: cmd.securitygroupids = [str(sg_id) for sg_id in securitygroupids] if mode.lower() == 'basic': - list_security_groups = SecurityGroup.list( - apiclient, - securitygroupname="basic_sec_grp" - ) - if not isinstance(list_security_groups, list): - basic_mode_security_group = SecurityGroup.create( + zone_list = Zone.list( + apiclient, + id = cmd.zoneid if cmd.zoneid else None, + domainid = cmd.domainid if cmd.domainid else None + ) + + zone = zone_list[0] + + #check if security groups settings is enabled for the zone + if zone.securitygroupsenabled: + list_security_groups = SecurityGroup.list( + apiclient, + securitygroupname="basic_sec_grp" + ) + + if not isinstance(list_security_groups, list): + basic_mode_security_group = SecurityGroup.create( apiclient, {"name":"basic_sec_grp"} ) - sec_grp_services = {"protocol": "TCP", + sec_grp_services = {"protocol": "TCP", "startport": 22, "endport":22, "cidrlist": "0.0.0.0/0" } - #Authorize security group for above ingress rule - cmd_auth = authorizeSecurityGroupIngress.authorizeSecurityGroupIngressCmd() - cmd_auth.domainid = cmd.domainid - cmd_auth.account = cmd.account - cmd_auth.securitygroupid = basic_mode_security_group.id - cmd_auth.protocol = sec_grp_services["protocol"] - cmd_auth.startport = sec_grp_services["startport"] - cmd_auth.endport = sec_grp_services["endport"] - cmd_auth.cidrlist = sec_grp_services["cidrlist"] - apiclient.authorizeSecurityGroupIngress(cmd_auth) + #Authorize security group for above ingress rule + cmd_auth = authorizeSecurityGroupIngress.authorizeSecurityGroupIngressCmd() + cmd_auth.domainid = cmd.domainid + cmd_auth.account = cmd.account + cmd_auth.securitygroupid = basic_mode_security_group.id + cmd_auth.protocol = sec_grp_services["protocol"] + cmd_auth.startport = sec_grp_services["startport"] + cmd_auth.endport = sec_grp_services["endport"] + cmd_auth.cidrlist = sec_grp_services["cidrlist"] + apiclient.authorizeSecurityGroupIngress(cmd_auth) - else: - basic_mode_security_group = list_security_groups[0] + else: + basic_mode_security_group = list_security_groups[0] - if isinstance(cmd.securitygroupids, list): - cmd.securitygroupids.append(basic_mode_security_group.id) - else: - cmd.securitygroupids = [basic_mode_security_group.id] + if isinstance(cmd.securitygroupids, list): + cmd.securitygroupids.append(basic_mode_security_group.id) + else: + cmd.securitygroupids = [basic_mode_security_group.id] if "affinitygroupnames" in services: cmd.affinitygroupnames = services["affinitygroupnames"] From b8148c6220afbea119d70715d0771faaacd3ff9b Mon Sep 17 00:00:00 2001 From: Prasanna Santhanam Date: Sat, 20 Jul 2013 13:29:17 +0530 Subject: [PATCH 12/74] CLOUDSTACK-3452: Refactor VirtualMachine.create() When creating a VM if it's going to a basic zone program sec.group rules so as to allow SSH access for any tests requiring ssh access to the guest. Similarly method used to program the NAT and PF for SSH access is refactored and extracted into a separate method. By default no SSH access is allowed if the mode is set to 'default' Signed-off-by: Prasanna Santhanam (cherry picked from commit 9c9003a0dba755135f643777083b80ec5fa3d910) --- tools/marvin/marvin/integration/lib/base.py | 172 +++++++++----------- 1 file changed, 80 insertions(+), 92 deletions(-) diff --git a/tools/marvin/marvin/integration/lib/base.py b/tools/marvin/marvin/integration/lib/base.py index 0938333c06c..0fb36cc56a0 100755 --- a/tools/marvin/marvin/integration/lib/base.py +++ b/tools/marvin/marvin/integration/lib/base.py @@ -233,12 +233,83 @@ class VirtualMachine: # extract out the ipaddress self.ipaddress = self.nic[0].ipaddress + @classmethod + def ssh_access_group(cls, apiclient, cmd): + """ + Programs the security group with SSH access before deploying virtualmachine + @return: + """ + zone_list = Zone.list( + apiclient, + id=cmd.zoneid if cmd.zoneid else None, + domainid=cmd.domainid if cmd.domainid else None + ) + zone = zone_list[0] + #check if security groups settings is enabled for the zone + if zone.securitygroupsenabled: + list_security_groups = SecurityGroup.list( + apiclient, + securitygroupname="basic_sec_grp" + ) + + if not isinstance(list_security_groups, list): + basic_mode_security_group = SecurityGroup.create( + apiclient, + {"name": "basic_sec_grp"} + ) + sec_grp_services = { + "protocol": "TCP", + "startport": 22, + "endport": 22, + "cidrlist": "0.0.0.0/0" + } + #Authorize security group for above ingress rule + basic_mode_security_group.authorize(apiclient, sec_grp_services, account=cmd.account, + domainid=cmd.domainid) + else: + basic_mode_security_group = list_security_groups[0] + + if isinstance(cmd.securitygroupids, list): + cmd.securitygroupids.append(basic_mode_security_group.id) + else: + cmd.securitygroupids = [basic_mode_security_group.id] + + @classmethod + def access_ssh_over_nat(cls, apiclient, services, virtual_machine): + """ + Program NAT and PF rules to open up ssh access to deployed guest + @return: + """ + public_ip = PublicIPAddress.create( + apiclient, + virtual_machine.account, + virtual_machine.zoneid, + virtual_machine.domainid, + services + ) + FireWallRule.create( + apiclient, + ipaddressid=public_ip.ipaddress.id, + protocol='TCP', + cidrlist=['0.0.0.0/0'], + startport=22, + endport=22 + ) + nat_rule = NATRule.create( + apiclient, + virtual_machine, + services, + ipaddressid=public_ip.ipaddress.id + ) + virtual_machine.ssh_ip = nat_rule.ipaddress + virtual_machine.public_ip = nat_rule.ipaddress + @classmethod def create(cls, apiclient, services, templateid=None, accountid=None, domainid=None, zoneid=None, networkids=None, serviceofferingid=None, securitygroupids=None, projectid=None, startvm=None, diskofferingid=None, affinitygroupnames=None, affinitygroupids=None, group=None, - hostid=None, keypair=None, mode='basic', method='GET'): + hostid=None, keypair=None, mode='default', method='GET'): """Create the instance""" cmd = deployVirtualMachine.deployVirtualMachineCmd() @@ -293,53 +364,6 @@ class VirtualMachine: if securitygroupids: cmd.securitygroupids = [str(sg_id) for sg_id in securitygroupids] - if mode.lower() == 'basic': - - zone_list = Zone.list( - apiclient, - id = cmd.zoneid if cmd.zoneid else None, - domainid = cmd.domainid if cmd.domainid else None - ) - - zone = zone_list[0] - - #check if security groups settings is enabled for the zone - if zone.securitygroupsenabled: - list_security_groups = SecurityGroup.list( - apiclient, - securitygroupname="basic_sec_grp" - ) - - if not isinstance(list_security_groups, list): - basic_mode_security_group = SecurityGroup.create( - apiclient, - {"name":"basic_sec_grp"} - ) - sec_grp_services = {"protocol": "TCP", - "startport": 22, - "endport":22, - "cidrlist": "0.0.0.0/0" - } - - #Authorize security group for above ingress rule - cmd_auth = authorizeSecurityGroupIngress.authorizeSecurityGroupIngressCmd() - cmd_auth.domainid = cmd.domainid - cmd_auth.account = cmd.account - cmd_auth.securitygroupid = basic_mode_security_group.id - cmd_auth.protocol = sec_grp_services["protocol"] - cmd_auth.startport = sec_grp_services["startport"] - cmd_auth.endport = sec_grp_services["endport"] - cmd_auth.cidrlist = sec_grp_services["cidrlist"] - apiclient.authorizeSecurityGroupIngress(cmd_auth) - - else: - basic_mode_security_group = list_security_groups[0] - - if isinstance(cmd.securitygroupids, list): - cmd.securitygroupids.append(basic_mode_security_group.id) - else: - cmd.securitygroupids = [basic_mode_security_group.id] - if "affinitygroupnames" in services: cmd.affinitygroupnames = services["affinitygroupnames"] elif affinitygroupnames: @@ -363,59 +387,23 @@ class VirtualMachine: if group: cmd.group = group + #program default access to ssh + if mode.lower() == 'basic': + cls.ssh_access_group(apiclient, cmd) + virtual_machine = apiclient.deployVirtualMachine(cmd, method=method) + virtual_machine.ssh_ip = virtual_machine.nic[0].ipaddress if startvm == False: - virtual_machine.ssh_ip = virtual_machine.nic[0].ipaddress virtual_machine.public_ip = virtual_machine.nic[0].ipaddress return VirtualMachine(virtual_machine.__dict__, services) - # VM should be in Running state after deploy - timeout = 10 - while True: - vm_status = VirtualMachine.list( - apiclient, - id=virtual_machine.id - ) - if isinstance(vm_status, list): - if vm_status[0].state == 'Running': - break - elif timeout == 0: - raise Exception( - "TimeOutException: Failed to start VM (ID: %s)" % - virtual_machine.id) - - time.sleep(10) - timeout = timeout - 1 - + #program ssh access over NAT via PF if mode.lower() == 'advanced': - public_ip = PublicIPAddress.create( - apiclient, - virtual_machine.account, - virtual_machine.zoneid, - virtual_machine.domainid, - services - ) - FireWallRule.create( - apiclient, - ipaddressid=public_ip.ipaddress.id, - protocol='TCP', - cidrlist=['0.0.0.0/0'], - startport=22, - endport=22 - ) - nat_rule = NATRule.create( - apiclient, - virtual_machine, - services, - ipaddressid=public_ip.ipaddress.id - ) - virtual_machine.ssh_ip = nat_rule.ipaddress - virtual_machine.public_ip = nat_rule.ipaddress - else: + cls.access_ssh_over_nat(apiclient, services, virtual_machine) + elif mode.lower() == 'basic': virtual_machine.ssh_ip = virtual_machine.nic[0].ipaddress virtual_machine.public_ip = virtual_machine.nic[0].ipaddress - return VirtualMachine(virtual_machine.__dict__, services) def start(self, apiclient): From 2000005f90d09c18735e2d3c57b41f2c1ec3d38d Mon Sep 17 00:00:00 2001 From: Prasanna Santhanam Date: Sat, 20 Jul 2013 15:53:14 +0530 Subject: [PATCH 13/74] CLOUDSTACK-3075: append test case name to account Accounts will be prepended by the testcase name to ease analysis post-test runs. Signed-off-by: Prasanna Santhanam (cherry picked from commit 17af34fd19ba9aa310a416e8e8cb80de37a018c2) --- tools/marvin/marvin/cloudstackTestCase.py | 16 -------- tools/marvin/marvin/cloudstackTestClient.py | 17 ++++++++- tools/marvin/marvin/codegenerator.py | 40 +++++++++++++++----- tools/marvin/marvin/integration/lib/base.py | 2 +- tools/marvin/marvin/integration/lib/utils.py | 7 +++- tools/marvin/marvin/marvinPlugin.py | 4 ++ 6 files changed, 56 insertions(+), 30 deletions(-) diff --git a/tools/marvin/marvin/cloudstackTestCase.py b/tools/marvin/marvin/cloudstackTestCase.py index 114928cdc03..742363d4ba2 100644 --- a/tools/marvin/marvin/cloudstackTestCase.py +++ b/tools/marvin/marvin/cloudstackTestCase.py @@ -15,22 +15,7 @@ # specific language governing permissions and limitations # under the License. -from cloudstackAPI import * import unittest -import cloudstackTestClient - -#class UserName(object): -# def __init__(self, account, domain, type=0): -# self.account = account -# self.domain = domain -# self.accounttype = type -# def __call__(self, cls): -# class Wrapped(cls): -# cls.UserName = self.account -# cls.DomainName = self.domain -# cls.AcctType = self.accounttype -# return Wrapped - def user(Name, DomainName, AcctType): def wrapper(cls): @@ -51,7 +36,6 @@ class cloudstackTestCase(unittest.case.TestCase): def __init__(self, args): unittest.case.TestCase.__init__(self, args) -# self.testClient = cloudstackTestClient.cloudstackTestClient() @classmethod def getClsTestClient(cls): diff --git a/tools/marvin/marvin/cloudstackTestClient.py b/tools/marvin/marvin/cloudstackTestClient.py index ea32b90dcd1..eba53a16e20 100644 --- a/tools/marvin/marvin/cloudstackTestClient.py +++ b/tools/marvin/marvin/cloudstackTestClient.py @@ -37,8 +37,17 @@ class cloudstackTestClient(object): self.dbConnection = None self.asyncJobMgr = None self.ssh = None + self.id = None self.defaultWorkerThreads = defaultWorkerThreads + @property + def identifier(self): + return self.id + + @identifier.setter + def identifier(self, id): + self.id = id + def dbConfigure(self, host="localhost", port=3306, user='cloud', passwd='cloud', db='cloud'): self.dbConnection = dbConnection.dbConnection(host, port, user, passwd, @@ -64,7 +73,10 @@ class cloudstackTestClient(object): def random_gen(self, size=6, chars=string.ascii_uppercase + string.digits): """Generate Random Strings of variable length""" - return ''.join(random.choice(chars) for x in range(size)) + randomstr = ''.join(random.choice(chars) for x in range(size)) + if self.identifier: + return ''.join([self.identifier, '-', randomstr]) + return randomstr def createUserApiClient(self, UserName, DomainName, acctType=0): if not self.isAdminContext(): @@ -153,6 +165,7 @@ class cloudstackTestClient(object): return self.dbConnection.executeSqlFromFile(sqlFile) def getApiClient(self): + self.apiClient.id = self.identifier return self.apiClient def getUserApiClient(self, account, domain, type=0): @@ -189,4 +202,4 @@ class cloudstackTestClient(object): if self.asyncJobMgr is None: self.asyncJobMgr = asyncJobMgr.asyncJobMgr(self.apiClient, self.dbConnection) - self.asyncJobMgr.submitJobs(jobs, nums_threads, interval) + self.asyncJobMgr.submitJobs(jobs, nums_threads, interval) \ No newline at end of file diff --git a/tools/marvin/marvin/codegenerator.py b/tools/marvin/marvin/codegenerator.py index 632b8c670b1..e37dbcc81b1 100644 --- a/tools/marvin/marvin/codegenerator.py +++ b/tools/marvin/marvin/codegenerator.py @@ -48,7 +48,8 @@ class codeGenerator(object): returned by API discovery or from the xml spec of commands generated by the ApiDocWriter. This class provides helper methods for these uses. """ - space = " " + space = ' ' + newline = '\n' cmdsName = [] def __init__(self, outputFolder): @@ -86,11 +87,11 @@ class codeGenerator(object): if desc is not None: self.code += self.space self.code += "''' " + pro.desc + " '''" - self.code += "\n" + self.code += self.newline self.code += self.space self.code += attr + " = " + str(value) - self.code += "\n" + self.code += self.newline def generateSubClass(self, name, properties): '''generate code for sub list''' @@ -114,7 +115,7 @@ class codeGenerator(object): self.cmd = cmd self.cmdsName.append(self.cmd.name) self.code = self.license - self.code += "\n" + self.code += self.newline self.code += '"""%s"""\n' % self.cmd.desc self.code += 'from baseCmd import *\n' self.code += 'from baseResponse import *\n' @@ -147,7 +148,7 @@ class codeGenerator(object): """generate response code""" subItems = {} - self.code += "\n" + self.code += self.newline self.code += 'class %sResponse (baseResponse):\n' % self.cmd.name self.code += self.space + "def __init__(self):\n" if len(self.cmd.response) == 0: @@ -165,7 +166,7 @@ class codeGenerator(object): else: self.code += self.space + self.space self.code += 'self.%s = None\n' % res.name - self.code += '\n' + self.code += self.newline for subclass in self.subclass: self.code += subclass + "\n" @@ -187,12 +188,33 @@ class codeGenerator(object): body += "class CloudStackAPIClient(object):\n" body += self.space + 'def __init__(self, connection):\n' body += self.space + self.space + 'self.connection = connection\n' - body += "\n" + body += self.space + self.space + 'self._id = None\n' + body += self.newline body += self.space + 'def __copy__(self):\n' body += self.space + self.space body += 'return CloudStackAPIClient(copy.copy(self.connection))\n' - body += "\n" + body += self.newline + +# The `id` property will be used to link the test with the cloud resource being created # +# @property +# def id(self): +# return self._id +# +# @id.setter +# def id(self, identifier): +# self._id = identifier + + + body += self.space + '@property' + self.newline + body += self.space + 'def id(self):' + self.newline + body += self.space*2 + 'return self._id' + self.newline + body += self.newline + + body += self.space + '@id.setter' + self.newline + body += self.space + 'def id(self, identifier):' + self.newline + body += self.space*2 + 'self._id = identifier' + self.newline + body += self.newline for cmdName in self.cmdsName: body += self.space @@ -203,7 +225,7 @@ class codeGenerator(object): body += 'response = self.connection.marvin_request(command,' body += ' response_type=response, method=method)\n' body += self.space + self.space + 'return response\n' - body += '\n' + body += self.newline imports += 'from %s import %sResponse\n' % (cmdName, cmdName) initCmdsList += '"%s",' % cmdName diff --git a/tools/marvin/marvin/integration/lib/base.py b/tools/marvin/marvin/integration/lib/base.py index 0fb36cc56a0..00dc506f1b1 100755 --- a/tools/marvin/marvin/integration/lib/base.py +++ b/tools/marvin/marvin/integration/lib/base.py @@ -98,7 +98,7 @@ class Account: cmd.lastname = services["lastname"] cmd.password = services["password"] - cmd.username = "-".join([services["username"], random_gen()]) + cmd.username = "-".join([services["username"], random_gen(id=apiclient.id)]) if "accountUUID" in services: cmd.accountid = "-".join([services["accountUUID"],random_gen()]) diff --git a/tools/marvin/marvin/integration/lib/utils.py b/tools/marvin/marvin/integration/lib/utils.py index 4eca8baab20..f7f39c93006 100644 --- a/tools/marvin/marvin/integration/lib/utils.py +++ b/tools/marvin/marvin/integration/lib/utils.py @@ -95,9 +95,12 @@ def get_first_text_block(email_message_instance): return email_message_instance.get_payload() -def random_gen(size=6, chars=string.ascii_uppercase + string.digits): +def random_gen(id=None, size=6, chars=string.ascii_uppercase + string.digits): """Generate Random Strings of variable length""" - return ''.join(random.choice(chars) for x in range(size)) + randomstr = ''.join(random.choice(chars) for x in range(size)) + if id: + return ''.join([id, '-', randomstr]) + return randomstr def cleanup_resources(api_client, resources): diff --git a/tools/marvin/marvin/marvinPlugin.py b/tools/marvin/marvin/marvinPlugin.py index 5014a2c921e..a0ec3d5eb20 100644 --- a/tools/marvin/marvin/marvinPlugin.py +++ b/tools/marvin/marvin/marvinPlugin.py @@ -125,6 +125,9 @@ class MarvinPlugin(Plugin): if config is not None: self.config = config + def beforeTest(self, test): + self.testclient.identifier = test.__str__().split()[0] + def _injectClients(self, test): testcaselogger = logging.getLogger("testclient.testcase.%s" % test.__name__) @@ -132,6 +135,7 @@ class MarvinPlugin(Plugin): setFormatter(logging. Formatter("%(asctime)s - %(levelname)s - %(name)s" + " - %(message)s")) + testcaselogger.addHandler(self.debug_stream) testcaselogger.setLevel(logging.DEBUG) From 78f1092df12928f06646b3bc42d69cc45dd3b1d3 Mon Sep 17 00:00:00 2001 From: Harikrishna Patnala Date: Fri, 19 Jul 2013 15:38:23 +0530 Subject: [PATCH 14/74] CLOUDSTACK-3365: cluster level parameters cluster.(cpu/memory).allocated.capacity.notificationthreshold is not considering overcommit value --- .../src/com/cloud/alert/AlertManagerImpl.java | 29 +++++++++++++------ 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/server/src/com/cloud/alert/AlertManagerImpl.java b/server/src/com/cloud/alert/AlertManagerImpl.java index 9b7cd274a2e..bff36c711fc 100755 --- a/server/src/com/cloud/alert/AlertManagerImpl.java +++ b/server/src/com/cloud/alert/AlertManagerImpl.java @@ -502,6 +502,18 @@ public class AlertManagerImpl extends ManagerBase implements AlertManager { } } + private float getOverProvisioningFactor(long clusterId, short capacityType) { + float overProvisioinigFactor = 1f; + switch (capacityType) { + case Capacity.CAPACITY_TYPE_CPU: + overProvisioinigFactor = Float.parseFloat(_configServer.getConfigValue(Config.CPUOverprovisioningFactor.key(), Config.ConfigurationParameterScope.cluster.toString(), clusterId)); + break; + case Capacity.CAPACITY_TYPE_MEMORY: + overProvisioinigFactor = Float.parseFloat(_configServer.getConfigValue(Config.MemOverprovisioningFactor.key(), Config.ConfigurationParameterScope.cluster.toString(), clusterId)); + break; + } + return overProvisioinigFactor; + } public void checkForAlerts(){ @@ -561,28 +573,27 @@ public class AlertManagerImpl extends ManagerBase implements AlertManager { for( ClusterVO cluster : clusterList){ for (Short capacityType : clusterCapacityTypes){ List capacity = new ArrayList(); - float overProvFactor = 1f; + float overProvFactor = getOverProvisioningFactor(cluster.getId(), capacityType); capacity = _capacityDao.findCapacityBy(capacityType.intValue(), cluster.getDataCenterId(), null, cluster.getId()); // cpu and memory allocated capacity notification threshold can be defined at cluster level, so getting the value if they are defined at cluster level - double capacityValue = 0; + double threshold = 0; switch (capacityType) { case Capacity.CAPACITY_TYPE_STORAGE: capacity.add(getUsedStats(capacityType, cluster.getDataCenterId(), cluster.getPodId(), cluster.getId())); - capacityValue = Double.parseDouble(_configServer.getConfigValue(Config.StorageCapacityThreshold.key(), Config.ConfigurationParameterScope.cluster.toString(), cluster.getId())); + threshold = Double.parseDouble(_configServer.getConfigValue(Config.StorageCapacityThreshold.key(), Config.ConfigurationParameterScope.cluster.toString(), cluster.getId())); break; case Capacity.CAPACITY_TYPE_STORAGE_ALLOCATED: - capacityValue = Double.parseDouble(_configServer.getConfigValue(Config.StorageAllocatedCapacityThreshold.key(), Config.ConfigurationParameterScope.cluster.toString(), cluster.getId())); + threshold = Double.parseDouble(_configServer.getConfigValue(Config.StorageAllocatedCapacityThreshold.key(), Config.ConfigurationParameterScope.cluster.toString(), cluster.getId())); break; case Capacity.CAPACITY_TYPE_CPU: - overProvFactor = ApiDBUtils.getCpuOverprovisioningFactor(); - capacityValue = Double.parseDouble(_configServer.getConfigValue(Config.CPUCapacityThreshold.key(), Config.ConfigurationParameterScope.cluster.toString(), cluster.getId())); + threshold = Double.parseDouble(_configServer.getConfigValue(Config.CPUCapacityThreshold.key(), Config.ConfigurationParameterScope.cluster.toString(), cluster.getId())); break; case Capacity.CAPACITY_TYPE_MEMORY: - capacityValue = Double.parseDouble(_configServer.getConfigValue(Config.MemoryCapacityThreshold.key(), Config.ConfigurationParameterScope.cluster.toString(), cluster.getId())); + threshold = Double.parseDouble(_configServer.getConfigValue(Config.MemoryCapacityThreshold.key(), Config.ConfigurationParameterScope.cluster.toString(), cluster.getId())); break; default: - capacityValue = _capacityTypeThresholdMap.get(capacityType); + threshold = _capacityTypeThresholdMap.get(capacityType); } if (capacity == null || capacity.size() == 0){ continue; @@ -590,7 +601,7 @@ public class AlertManagerImpl extends ManagerBase implements AlertManager { double totalCapacity = capacity.get(0).getTotalCapacity() * overProvFactor; double usedCapacity = capacity.get(0).getUsedCapacity() + capacity.get(0).getReservedCapacity(); - if (totalCapacity != 0 && usedCapacity/totalCapacity > capacityValue){ + if (totalCapacity != 0 && usedCapacity/totalCapacity > threshold){ generateEmailAlert(ApiDBUtils.findZoneById(cluster.getDataCenterId()), ApiDBUtils.findPodById(cluster.getPodId()), cluster, totalCapacity, usedCapacity, capacityType); } From f8b5a4159bc51c6f5ca40374c145dceb4dcbf246 Mon Sep 17 00:00:00 2001 From: Min Chen Date: Sat, 20 Jul 2013 11:42:20 -0700 Subject: [PATCH 15/74] CLOUDSTACK-3419: [Object_Store_Refactor] Uploaded volume is being deleted while attaching it to guest VM. --- .../storage/volume/VolumeServiceImpl.java | 2 +- .../resource/NfsSecondaryStorageResource.java | 156 ++++++++++-------- 2 files changed, 86 insertions(+), 72 deletions(-) diff --git a/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java b/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java index 89313e4b338..9338d3807e9 100644 --- a/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java +++ b/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java @@ -639,7 +639,7 @@ public class VolumeServiceImpl implements VolumeService { srcVolume.processEvent(Event.OperationSuccessed); destVolume.processEvent(Event.OperationSuccessed, result.getAnswer()); - srcVolume.getDataStore().delete(srcVolume); + // srcVolume.getDataStore().delete(srcVolume); future.complete(res); } catch (Exception e) { res.setResult(e.toString()); diff --git a/services/secondary-storage/src/org/apache/cloudstack/storage/resource/NfsSecondaryStorageResource.java b/services/secondary-storage/src/org/apache/cloudstack/storage/resource/NfsSecondaryStorageResource.java index 054edd9fe72..003c87acd5b 100755 --- a/services/secondary-storage/src/org/apache/cloudstack/storage/resource/NfsSecondaryStorageResource.java +++ b/services/secondary-storage/src/org/apache/cloudstack/storage/resource/NfsSecondaryStorageResource.java @@ -273,7 +273,11 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S newTemplTO.setSize(size); newDestTO = newTemplTO; } else { - return new CopyCmdAnswer("not implemented yet"); + VolumeObjectTO newVolTO = new VolumeObjectTO(); + newVolTO.setPath(finalDownloadPath); + newVolTO.setName(finalFileName); + newVolTO.setSize(size); + newDestTO = newVolTO; } return new CopyCmdAnswer(newDestTO); @@ -313,11 +317,11 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S File destFile = S3Utils.getFile(s3, s3.getBucketName(), srcData.getPath(), downloadDirectory, new FileNamingStrategy() { - @Override - public String determineFileName(final String key) { - return substringAfterLast(key, S3Utils.SEPARATOR); - } - }); + @Override + public String determineFileName(final String key) { + return substringAfterLast(key, S3Utils.SEPARATOR); + } + }); if (destFile == null) { return new CopyCmdAnswer("Can't find template"); @@ -589,10 +593,10 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S DownloadAnswer answer = new DownloadAnswer(null, 100, null, VMTemplateStorageResourceAssoc.Status.DOWNLOADED, swiftPath, swiftPath, file.length(), file.length(), md5sum - ); + ); return answer; } catch (Exception e) { - s_logger.debug("Failed to register template into swift", e); + s_logger.debug("Failed to register template into swift", e); return new DownloadAnswer(e.toString(), VMTemplateStorageResourceAssoc.Status.DOWNLOAD_ERROR); } finally { if (file != null) { @@ -650,16 +654,17 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S ext = filePath.substring(i + 1); } if (ext != null) { - if (ext.equalsIgnoreCase("vhd")) + if (ext.equalsIgnoreCase("vhd")) { return ImageFormat.VHD; - else if (ext.equalsIgnoreCase("qcow2")) + } else if (ext.equalsIgnoreCase("qcow2")) { return ImageFormat.QCOW2; - else if (ext.equalsIgnoreCase("ova")) + } else if (ext.equalsIgnoreCase("ova")) { return ImageFormat.OVA; - else if (ext.equalsIgnoreCase("tar")) + } else if (ext.equalsIgnoreCase("tar")) { return ImageFormat.TAR; - else if (ext.equalsIgnoreCase("img")) + } else if (ext.equalsIgnoreCase("img")) { return ImageFormat.RAW; + } } return null; @@ -921,16 +926,16 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S } else if (dstore instanceof SwiftTO) { String path = cmd.getDirectory(); String volumeId = StringUtils.substringAfterLast(path, "/"); // assuming - // that - // the - // filename - // is - // the - // last - // section - // in - // the - // path + // that + // the + // filename + // is + // the + // last + // section + // in + // the + // path String result = swiftDelete((SwiftTO) dstore, "V-" + volumeId.toString(), ""); if (result != null) { String errMsg = "failed to delete snapshot for volume " + volumeId + " , err=" + result; @@ -971,12 +976,12 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S final File targetFile = S3Utils.getFile(s3, s3.getBucketName(), key, _storage.getFile(directoryName), new FileNamingStrategy() { - @Override - public String determineFileName(String key) { - return snapshotFileName; - } + @Override + public String determineFileName(String key) { + return snapshotFileName; + } - }); + }); if (cmd.getParent() != null) { @@ -1125,8 +1130,9 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S return new Answer(cmd, false, checksum); } finally { try { - if (is != null) + if (is != null) { is.close(); + } } catch (IOException e) { if (s_logger.isDebugEnabled()) { s_logger.debug("Could not close the file " + absoluteTemplatePath); @@ -1239,24 +1245,24 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S final String result = executeWithNoWaitLock(determineSnapshotLockId(accountId, volumeId), new Callable() { - @Override - public String call() throws Exception { + @Override + public String call() throws Exception { - if (deleteAllFlag) { - S3Utils.deleteDirectory(s3, bucket, determineSnapshotS3Directory(accountId, volumeId)); - } else { - S3Utils.deleteObject( - s3, - bucket, - determineSnapshotS3Key(accountId, volumeId, - determineSnapshotBackupFilename(name))); - } + if (deleteAllFlag) { + S3Utils.deleteDirectory(s3, bucket, determineSnapshotS3Directory(accountId, volumeId)); + } else { + S3Utils.deleteObject( + s3, + bucket, + determineSnapshotS3Key(accountId, volumeId, + determineSnapshotBackupFilename(name))); + } - return null; + return null; - } + } - }); + }); return result; @@ -1330,16 +1336,16 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S } else if (dstore instanceof SwiftTO) { String path = obj.getPath(); String filename = StringUtils.substringAfterLast(path, "/"); // assuming - // that - // the - // filename - // is - // the - // last - // section - // in - // the - // path + // that + // the + // filename + // is + // the + // last + // section + // in + // the + // path String volumeId = StringUtils.substringAfterLast(StringUtils.substringBeforeLast(path, "/"), "/"); String result = swiftDelete((SwiftTO) dstore, "V-" + volumeId, filename); if (result != null) { @@ -1391,8 +1397,9 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S String bucket = s3.getBucketName(); // List the objects in the source directory on S3 final List objectSummaries = S3Utils.getDirectory(s3, bucket, this.TEMPLATE_ROOT_DIR); - if (objectSummaries == null) + if (objectSummaries == null) { return null; + } Map tmpltInfos = new HashMap(); for (S3ObjectSummary objectSummary : objectSummaries) { String key = objectSummary.getKey(); @@ -1412,8 +1419,9 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S String bucket = s3.getBucketName(); // List the objects in the source directory on S3 final List objectSummaries = S3Utils.getDirectory(s3, bucket, this.VOLUME_ROOT_DIR); - if (objectSummaries == null) + if (objectSummaries == null) { return null; + } Map tmpltInfos = new HashMap(); for (S3ObjectSummary objectSummary : objectSummaries) { String key = objectSummary.getKey(); @@ -1596,8 +1604,9 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S boolean success = true; String result; result = configureIpFirewall(ipList, cmd.getIsAppendAIp()); - if (result != null) + if (result != null) { success = false; + } return new Answer(cmd, success, result); } @@ -1807,16 +1816,16 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S Long volumeId = obj.getId(); String path = obj.getPath(); String filename = StringUtils.substringAfterLast(path, "/"); // assuming - // that - // the - // filename - // is - // the - // last - // section - // in - // the - // path + // that + // the + // filename + // is + // the + // last + // section + // in + // the + // path String result = swiftDelete((SwiftTO) dstore, "V-" + volumeId.toString(), filename); if (result != null) { String errMsg = "failed to delete volume " + filename + " , err=" + result; @@ -1882,8 +1891,9 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S @Override public Type getType() { - if (SecondaryStorageVm.Role.templateProcessor.toString().equals(_role)) + if (SecondaryStorageVm.Role.templateProcessor.toString().equals(_role)) { return Host.Type.SecondaryStorage; + } return Host.Type.SecondaryStorageCmdExecutor; } @@ -1946,8 +1956,9 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S } } - if (_inSystemVM) + if (_inSystemVM) { _storage.mkdirs(_parent); + } _configSslScr = Script.findScript(getDefaultScriptsDir(), "config_ssl.sh"); if (_configSslScr != null) { @@ -1972,8 +1983,9 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S } _role = (String) params.get("role"); - if (_role == null) + if (_role == null) { _role = SecondaryStorageVm.Role.templateProcessor.toString(); + } s_logger.info("Secondary storage runs in role " + _role); _guid = (String) params.get("guid"); @@ -2189,8 +2201,9 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S if (result != null) { s_logger.warn("Unable to mount " + nfsPath + " due to " + result); file = new File(root); - if (file.exists()) + if (file.exists()) { file.delete(); + } return null; } @@ -2223,8 +2236,9 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S final StartupSecondaryStorageCommand cmd = new StartupSecondaryStorageCommand(); fillNetworkInformation(cmd); - if (_publicIp != null) + if (_publicIp != null) { cmd.setPublicIpAddress(_publicIp); + } if (_inSystemVM) { Script command = new Script("/bin/bash", s_logger); From ad269304f661e7883eeec9b20752a2d4639a286f Mon Sep 17 00:00:00 2001 From: Min Chen Date: Sat, 20 Jul 2013 12:21:16 -0700 Subject: [PATCH 16/74] CLOUDSTACK-3684:Failed to start MS due to missing UCS configuration values in DB. --- setup/db/db/schema-410to420.sql | 2 ++ 1 file changed, 2 insertions(+) diff --git a/setup/db/db/schema-410to420.sql b/setup/db/db/schema-410to420.sql index dd8c75a1237..8eea6f3cd09 100644 --- a/setup/db/db/schema-410to420.sql +++ b/setup/db/db/schema-410to420.sql @@ -2257,3 +2257,5 @@ ALTER TABLE `cloud`.`network_offerings` ADD COLUMN `concurrent_connections` int( ALTER TABLE `cloud`.`sync_queue` MODIFY `queue_size` smallint(6) NOT NULL DEFAULT '0' COMMENT 'number of items being processed by the queue'; ALTER TABLE `cloud`.`sync_queue` MODIFY `queue_size_limit` smallint(6) NOT NULL DEFAULT '1' COMMENT 'max number of items the queue can process concurrently'; + +INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'management-server', 'ucs.sync.blade.interval', '3600', 'the interval cloudstack sync with UCS manager for available blades in case user remove blades from chassis without notifying CloudStack'); From 6689e83d7f8c5af834e2d730d74654318e93b2a4 Mon Sep 17 00:00:00 2001 From: Min Chen Date: Sat, 20 Jul 2013 15:15:52 -0700 Subject: [PATCH 17/74] CLOUDSTACK-3513: ListIsos/ListTemplates does not return correct results when id and zoneid are passed. --- .../com/cloud/api/query/QueryManagerImpl.java | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/server/src/com/cloud/api/query/QueryManagerImpl.java b/server/src/com/cloud/api/query/QueryManagerImpl.java index cef5ddf01de..33327db9038 100644 --- a/server/src/com/cloud/api/query/QueryManagerImpl.java +++ b/server/src/com/cloud/api/query/QueryManagerImpl.java @@ -2876,17 +2876,6 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { sc.addAnd("state", SearchCriteria.Op.SC, readySc); } - if (zoneId != null) { - SearchCriteria zoneSc = _templateJoinDao.createSearchCriteria(); - zoneSc.addOr("dataCenterId", SearchCriteria.Op.EQ, zoneId); - zoneSc.addOr("dataStoreScope", SearchCriteria.Op.EQ, ScopeType.REGION); - // handle the case where xs-tools.iso and vmware-tools.iso do not have data_center information in template_view - SearchCriteria isoPerhostSc = _templateJoinDao.createSearchCriteria(); - isoPerhostSc.addAnd("format", SearchCriteria.Op.EQ, ImageFormat.ISO); - isoPerhostSc.addAnd("templateType", SearchCriteria.Op.EQ, TemplateType.PERHOST); - zoneSc.addOr("templateType", SearchCriteria.Op.SC, isoPerhostSc); - sc.addAnd("dataCenterId", SearchCriteria.Op.SC, zoneSc); - } if (!showDomr) { // excluding system template @@ -2894,6 +2883,19 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { } } + if (zoneId != null) { + SearchCriteria zoneSc = _templateJoinDao.createSearchCriteria(); + zoneSc.addOr("dataCenterId", SearchCriteria.Op.EQ, zoneId); + zoneSc.addOr("dataStoreScope", SearchCriteria.Op.EQ, ScopeType.REGION); + // handle the case where xs-tools.iso and vmware-tools.iso do not + // have data_center information in template_view + SearchCriteria isoPerhostSc = _templateJoinDao.createSearchCriteria(); + isoPerhostSc.addAnd("format", SearchCriteria.Op.EQ, ImageFormat.ISO); + isoPerhostSc.addAnd("templateType", SearchCriteria.Op.EQ, TemplateType.PERHOST); + zoneSc.addOr("templateType", SearchCriteria.Op.SC, isoPerhostSc); + sc.addAnd("dataCenterId", SearchCriteria.Op.SC, zoneSc); + } + // don't return removed template, this should not be needed since we // changed annotation for removed field in TemplateJoinVO. // sc.addAnd("removed", SearchCriteria.Op.NULL); From 98dd501a818beef03b5f593822b525348874f007 Mon Sep 17 00:00:00 2001 From: Mike Tutkowski Date: Sat, 20 Jul 2013 17:44:23 -0600 Subject: [PATCH 18/74] Changes related to Review Board comments --- .../vmware/resource/VmwareResource.java | 273 ++++++++++-------- 1 file changed, 148 insertions(+), 125 deletions(-) diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java index bbac725eb0e..c7f487e833e 100755 --- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java +++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java @@ -28,6 +28,7 @@ import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Comparator; +import java.util.concurrent.*; import java.util.Date; import java.util.GregorianCalendar; import java.util.HashMap; @@ -4073,33 +4074,6 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa return str.replace('/', '-'); } - // This methd can be used to determine if the datastore is active yet. - // When an iSCSI target is created on a host and that target already contains - // the metadata that represents a datastore, the datastore shows up within - // vCenter as existent, but not necessarily active. - // Call this method and pass in the datastore's name to wait, if necessary, - // for the datastore to become active. - private boolean datastoreFileExists(DatastoreMO dsMo, String volumeDatastorePath) { - for (int i = 0; i < 10; i++) { - try { - return dsMo.fileExists(volumeDatastorePath); - } - catch (Exception e) { - if (!e.getMessage().contains("is not accessible")) { - break; - } - } - - try { - Thread.sleep(5000); - } - catch (Exception e) { - } - } - - return false; - } - @Override public ManagedObjectReference handleDatastoreAndVmdkAttach(Command cmd, String iqn, String storageHost, int storagePort, String initiatorUsername, String initiatorPassword, String targetUsername, String targetPassword) throws Exception { @@ -4115,7 +4089,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa String volumeDatastorePath = String.format("[%s] %s.vmdk", dsMo.getName(), dsMo.getName()); - if (!datastoreFileExists(dsMo, volumeDatastorePath)) { + if (!dsMo.fileExists(volumeDatastorePath)) { String dummyVmName = getWorkerName(context, cmd, 0); VirtualMachineMO vmMo = prepareVolumeHostDummyVm(hyperHost, dsMo, dummyVmName); @@ -4209,6 +4183,126 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa } } + private void addRemoveInternetScsiTargetsToAllHosts(final boolean add, final List lstTargets, + final List> lstHosts) throws Exception { + VmwareContext context = getServiceContext(); + + ExecutorService executorService = Executors.newFixedThreadPool(lstHosts.size()); + + final List exceptions = new ArrayList(); + + for (Pair hostPair : lstHosts) { + HostMO host = new HostMO(context, hostPair.first()); + HostStorageSystemMO hostStorageSystem = host.getHostStorageSystemMO(); + + boolean iScsiHbaConfigured = false; + + for (HostHostBusAdapter hba : hostStorageSystem.getStorageDeviceInfo().getHostBusAdapter()) { + if (hba instanceof HostInternetScsiHba) { + // just finding an instance of HostInternetScsiHba means that we have found at least one configured iSCSI HBA + // at least one iSCSI HBA must be configured before a CloudStack user can use this host for iSCSI storage + iScsiHbaConfigured = true; + + final String iScsiHbaDevice = hba.getDevice(); + + final HostStorageSystemMO hss = hostStorageSystem; + + executorService.submit(new Thread() { + @Override + public void run() { + try { + if (add) { + hss.addInternetScsiStaticTargets(iScsiHbaDevice, lstTargets); + } + else { + hss.removeInternetScsiStaticTargets(iScsiHbaDevice, lstTargets); + } + + hss.rescanHba(iScsiHbaDevice); + hss.rescanVmfs(); + } + catch (Exception ex) { + synchronized (exceptions) { + exceptions.add(ex); + } + } + } + }); + } + } + + if (!iScsiHbaConfigured) { + throw new Exception("An iSCSI HBA must be configured before a host can use iSCSI storage."); + } + } + + executorService.shutdown(); + + if (!executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.MINUTES)) { + throw new Exception("The system timed out before completing the task 'rescanAllHosts'."); + } + + if (exceptions.size() > 0) { + throw new Exception(exceptions.get(0).getMessage()); + } + } + + private void rescanAllHosts(final List> lstHosts) throws Exception { + VmwareContext context = getServiceContext(); + + ExecutorService executorService = Executors.newFixedThreadPool(lstHosts.size()); + + final List exceptions = new ArrayList(); + + for (Pair hostPair : lstHosts) { + HostMO host = new HostMO(context, hostPair.first()); + HostStorageSystemMO hostStorageSystem = host.getHostStorageSystemMO(); + + boolean iScsiHbaConfigured = false; + + for (HostHostBusAdapter hba : hostStorageSystem.getStorageDeviceInfo().getHostBusAdapter()) { + if (hba instanceof HostInternetScsiHba) { + // just finding an instance of HostInternetScsiHba means that we have found at least one configured iSCSI HBA + // at least one iSCSI HBA must be configured before a CloudStack user can use this host for iSCSI storage + iScsiHbaConfigured = true; + + final String iScsiHbaDevice = hba.getDevice(); + + final HostStorageSystemMO hss = hostStorageSystem; + + executorService.submit(new Thread() { + @Override + public void run() { + try { + hss.rescanHba(iScsiHbaDevice); + hss.rescanVmfs(); + } + catch (Exception ex) { + synchronized (exceptions) { + exceptions.add(ex); + } + } + } + }); + } + } + + if (!iScsiHbaConfigured) { + throw new Exception("An iSCSI HBA must be configured before a host can use iSCSI storage."); + } + } + + executorService.shutdown(); + + if (!executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.MINUTES)) { + throw new Exception("The system timed out before completing the task 'rescanAllHosts'."); + } + + if (exceptions.size() > 0) { + throw new Exception(exceptions.get(0).getMessage()); + } + } + private ManagedObjectReference createVmfsDatastore(VmwareHypervisorHost hyperHost, String datastoreName, String storageIpAddress, int storagePortNumber, String iqn, String chapName, String chapSecret, String mutualChapName, String mutualChapSecret) throws Exception { VmwareContext context = getServiceContext(); @@ -4242,80 +4336,46 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa lstTargets.add(target); - HostDatastoreSystemMO hostDatastoreSystem = null; - HostStorageSystemMO hostStorageSystem = null; + addRemoveInternetScsiTargetsToAllHosts(true, lstTargets, lstHosts); - final List threads = new ArrayList(); - final List exceptions = new ArrayList(); + rescanAllHosts(lstHosts); - for (Pair hostPair : lstHosts) { - HostMO host = new HostMO(context, hostPair.first()); - hostDatastoreSystem = host.getHostDatastoreSystemMO(); - hostStorageSystem = host.getHostStorageSystemMO(); + HostMO host = new HostMO(context, lstHosts.get(0).first()); + HostDatastoreSystemMO hostDatastoreSystem = host.getHostDatastoreSystemMO(); - boolean iScsiHbaConfigured = false; - - for (HostHostBusAdapter hba : hostStorageSystem.getStorageDeviceInfo().getHostBusAdapter()) { - if (hba instanceof HostInternetScsiHba) { - // just finding an instance of HostInternetScsiHba means that we have found at least one configured iSCSI HBA - // at least one iSCSI HBA must be configured before a CloudStack user can use this host for iSCSI storage - iScsiHbaConfigured = true; - - final String iScsiHbaDevice = hba.getDevice(); - - final HostStorageSystemMO hss = hostStorageSystem; - - threads.add(new Thread() { - @Override - public void run() { - try { - hss.addInternetScsiStaticTargets(iScsiHbaDevice, lstTargets); - - hss.rescanHba(iScsiHbaDevice); - hss.rescanVmfs(); - } - catch (Exception ex) { - synchronized (exceptions) { - exceptions.add(ex); - } - } - } - }); - } - } - - if (!iScsiHbaConfigured) { - throw new Exception("An iSCSI HBA must be configured before a host can use iSCSI storage."); - } - } - - for (Thread thread : threads) { - thread.start(); - } - - for (Thread thread : threads) { - thread.join(); - } - - if (exceptions.size() > 0) { - throw new Exception(exceptions.get(0).getMessage()); - } - - ManagedObjectReference morDs = hostDatastoreSystem.findDatastoreByName(iqn); + ManagedObjectReference morDs = hostDatastoreSystem.findDatastoreByName(datastoreName); if (morDs != null) { return morDs; } + rescanAllHosts(lstHosts); + + HostStorageSystemMO hostStorageSystem = host.getHostStorageSystemMO(); List lstHostScsiDisks = hostDatastoreSystem.queryAvailableDisksForVmfs(); HostScsiDisk hostScsiDisk = getHostScsiDisk(hostStorageSystem.getStorageDeviceInfo().getScsiTopology(), lstHostScsiDisks, iqn); if (hostScsiDisk == null) { + // check to see if the datastore actually does exist already + morDs = hostDatastoreSystem.findDatastoreByName(datastoreName); + + if (morDs != null) { + return morDs; + } + throw new Exception("A relevant SCSI disk could not be located to use to create a datastore."); } - return hostDatastoreSystem.createVmfsDatastore(datastoreName, hostScsiDisk); + morDs = hostDatastoreSystem.createVmfsDatastore(datastoreName, hostScsiDisk); + + if (morDs != null) { + rescanAllHosts(lstHosts); + + return morDs; + } + + throw new Exception("Unable to create a datastore"); } // the purpose of this method is to find the HostScsiDisk in the passed-in array that exists (if any) because @@ -4363,46 +4423,9 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa lstTargets.add(target); - final List threads = new ArrayList(); - final List exceptions = new ArrayList(); + addRemoveInternetScsiTargetsToAllHosts(false, lstTargets, lstHosts); - for (Pair hostPair : lstHosts) { - final HostMO host = new HostMO(context, hostPair.first()); - final HostStorageSystemMO hostStorageSystem = host.getHostStorageSystemMO(); - - for (HostHostBusAdapter hba : hostStorageSystem.getStorageDeviceInfo().getHostBusAdapter()) { - if (hba instanceof HostInternetScsiHba) { - final String iScsiHbaDevice = hba.getDevice(); - - Thread thread = new Thread() { - @Override - public void run() { - try { - hostStorageSystem.removeInternetScsiStaticTargets(iScsiHbaDevice, lstTargets); - - hostStorageSystem.rescanHba(iScsiHbaDevice); - hostStorageSystem.rescanVmfs(); - } - catch (Exception ex) { - exceptions.add(ex); - } - } - }; - - threads.add(thread); - - thread.start(); - } - } - } - - for (Thread thread : threads) { - thread.join(); - } - - if (exceptions.size() > 0) { - throw new Exception(exceptions.get(0).getMessage()); - } + rescanAllHosts(lstHosts); } protected Answer execute(AttachIsoCommand cmd) { From d423a755f51814dcd5b09cb987704a1ef174b7f4 Mon Sep 17 00:00:00 2001 From: Min Chen Date: Sat, 20 Jul 2013 18:01:49 -0700 Subject: [PATCH 19/74] CLOUDSTACK-3274: API Refactoring: secretkey and accesskey of the backing store is found in plaintext in the logs. Conflicts: server/src/com/cloud/api/ApiServer.java server/src/com/cloud/api/ApiServlet.java --- api/src/com/cloud/agent/api/to/S3TO.java | 10 +- server/src/com/cloud/api/ApiServer.java | 25 +++-- server/src/com/cloud/api/ApiServlet.java | 17 +-- utils/src/com/cloud/utils/StringUtils.java | 16 +-- .../test/com/cloud/utils/StringUtilsTest.java | 104 +++++++++++++++++- 5 files changed, 141 insertions(+), 31 deletions(-) diff --git a/api/src/com/cloud/agent/api/to/S3TO.java b/api/src/com/cloud/agent/api/to/S3TO.java index 8a2f09dc5ab..b1b692a8bad 100644 --- a/api/src/com/cloud/agent/api/to/S3TO.java +++ b/api/src/com/cloud/agent/api/to/S3TO.java @@ -18,6 +18,8 @@ package com.cloud.agent.api.to; import java.util.Date; +import com.cloud.agent.api.LogLevel; +import com.cloud.agent.api.LogLevel.Log4jLevel; import com.cloud.storage.DataStoreRole; import com.cloud.utils.S3Utils; @@ -25,7 +27,9 @@ public final class S3TO implements S3Utils.ClientOptions, DataStoreTO { private Long id; private String uuid; + @LogLevel(Log4jLevel.Off) private String accessKey; + @LogLevel(Log4jLevel.Off) private String secretKey; private String endPoint; private String bucketName; @@ -68,10 +72,12 @@ public final class S3TO implements S3Utils.ClientOptions, DataStoreTO { @Override public boolean equals(final Object thatObject) { - if (this == thatObject) + if (this == thatObject) { return true; - if (thatObject == null || getClass() != thatObject.getClass()) + } + if (thatObject == null || getClass() != thatObject.getClass()) { return false; + } final S3TO thatS3TO = (S3TO) thatObject; diff --git a/server/src/com/cloud/api/ApiServer.java b/server/src/com/cloud/api/ApiServer.java index 95f17af53b9..57a4eaf036a 100755 --- a/server/src/com/cloud/api/ApiServer.java +++ b/server/src/com/cloud/api/ApiServer.java @@ -189,14 +189,14 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer public static ApiServer getInstance() { return s_instance; } - - @Override - public boolean configure(String name, Map params) - throws ConfigurationException { - init(); - return true; - } - + + @Override + public boolean configure(String name, Map params) + throws ConfigurationException { + init(); + return true; + } + public void init() { Integer apiPort = null; // api port, null by default SearchCriteria sc = _configDao.createSearchCriteria(); @@ -293,12 +293,13 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer parameterMap.put(param.getName(), new String[] { param.getValue() }); } - // Get the type of http method being used. + // Get the type of http method being used. parameterMap.put("httpmethod", new String[] { request.getRequestLine().getMethod() }); // Check responseType, if not among valid types, fallback to JSON - if (!(responseType.equals(BaseCmd.RESPONSE_TYPE_JSON) || responseType.equals(BaseCmd.RESPONSE_TYPE_XML))) + if (!(responseType.equals(BaseCmd.RESPONSE_TYPE_JSON) || responseType.equals(BaseCmd.RESPONSE_TYPE_XML))) { responseType = BaseCmd.RESPONSE_TYPE_XML; + } try { // always trust commands from API port, user context will always be UID_SYSTEM/ACCOUNT_ID_SYSTEM @@ -318,7 +319,7 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer throw e; } } finally { - s_accessLogger.info(sb.toString()); + s_accessLogger.info(StringUtils.cleanString(sb.toString())); CallContext.unregister(); } } @@ -370,7 +371,7 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer cmdObj.configure(); cmdObj.setFullUrlParams(paramMap); cmdObj.setResponseType(responseType); - cmdObj.setHttpMethod(paramMap.get("httpmethod").toString()); + cmdObj.setHttpMethod(paramMap.get("httpmethod").toString()); // This is where the command is either serialized, or directly dispatched response = queueCommand(cmdObj, paramMap); diff --git a/server/src/com/cloud/api/ApiServlet.java b/server/src/com/cloud/api/ApiServlet.java index 4b49ee4c232..22047ffa901 100755 --- a/server/src/com/cloud/api/ApiServlet.java +++ b/server/src/com/cloud/api/ApiServlet.java @@ -63,9 +63,9 @@ public class ApiServlet extends HttpServlet { @Override public void init(ServletConfig config) throws ServletException { - SpringBeanAutowiringSupport.processInjectionBasedOnServletContext(this, config.getServletContext()); + SpringBeanAutowiringSupport.processInjectionBasedOnServletContext(this, config.getServletContext()); } - + @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) { processRequest(req, resp); @@ -77,8 +77,9 @@ public class ApiServlet extends HttpServlet { } private void utf8Fixup(HttpServletRequest req, Map params) { - if (req.getQueryString() == null) + if (req.getQueryString() == null) { return; + } String[] paramsInQueryString = req.getQueryString().split("&"); if (paramsInQueryString != null) { @@ -325,14 +326,14 @@ public class ApiServlet extends HttpServlet { } } catch (ServerApiException se) { String serializedResponseText = _apiServer.getSerializedApiError(se, params, responseType); - resp.setHeader("X-Description", se.getDescription()); + resp.setHeader("X-Description", se.getDescription()); writeResponse(resp, serializedResponseText, se.getErrorCode().getHttpCode(), responseType); - auditTrailSb.append(" " + se.getErrorCode() + " " + se.getDescription()); + auditTrailSb.append(" " + se.getErrorCode() + " " + se.getDescription()); } catch (Exception ex) { - s_logger.error("unknown exception writing api response", ex); - auditTrailSb.append(" unknown exception writing api response"); + s_logger.error("unknown exception writing api response", ex); + auditTrailSb.append(" unknown exception writing api response"); } finally { - s_accessLogger.info(auditTrailSb.toString()); + s_accessLogger.info(StringUtils.cleanString(auditTrailSb.toString())); if (s_logger.isDebugEnabled()) { s_logger.debug("===END=== " + StringUtils.cleanString(reqStr)); } diff --git a/utils/src/com/cloud/utils/StringUtils.java b/utils/src/com/cloud/utils/StringUtils.java index db32dd42869..21c7220259e 100644 --- a/utils/src/com/cloud/utils/StringUtils.java +++ b/utils/src/com/cloud/utils/StringUtils.java @@ -91,10 +91,10 @@ public class StringUtils { tags += ","; } } - } + } return tags; - } + } public static String getExceptionStackInfo(Throwable e) { StringBuffer sb = new StringBuffer(); @@ -131,22 +131,24 @@ public class StringUtils { } public static String getMaskedPasswordForDisplay(String password) { - if(password == null || password.isEmpty()) + if(password == null || password.isEmpty()) { return "*"; + } StringBuffer sb = new StringBuffer(); sb.append(password.charAt(0)); - for(int i = 1; i < password.length(); i++) + for(int i = 1; i < password.length(); i++) { sb.append("*"); + } return sb.toString(); } // removes a password request param and it's value - private static final Pattern REGEX_PASSWORD_QUERYSTRING = Pattern.compile("&?password=.*?(?=[&'\"])"); + private static final Pattern REGEX_PASSWORD_QUERYSTRING = Pattern.compile("&?(password|accesskey|secretkey)=.*?(?=[&'\"])"); - // removes a password property from a response json object - private static final Pattern REGEX_PASSWORD_JSON = Pattern.compile("\"password\":\".*?\",?"); + // removes a password/accesskey/ property from a response json object + private static final Pattern REGEX_PASSWORD_JSON = Pattern.compile("\"(password|accesskey|secretkey)\":\".*?\",?"); // Responsible for stripping sensitive content from request and response strings public static String cleanString(String stringToClean){ diff --git a/utils/test/com/cloud/utils/StringUtilsTest.java b/utils/test/com/cloud/utils/StringUtilsTest.java index 796efbaacd7..ae37c24f991 100644 --- a/utils/test/com/cloud/utils/StringUtilsTest.java +++ b/utils/test/com/cloud/utils/StringUtilsTest.java @@ -24,7 +24,7 @@ public class StringUtilsTest { @Test public void testCleanPasswordFromJsonObjectAtEnd() { String input = "{\"foo\":\"bar\",\"password\":\"test\"}"; - //TODO: It would be nice to clean up the regex in question to not + //TODO: It would be nice to clean up the regex in question to not //have to return the trailing comma in the expected string below String expected = "{\"foo\":\"bar\",}"; String result = StringUtils.cleanString(input); @@ -78,7 +78,7 @@ public class StringUtilsTest { String result = StringUtils.cleanString(input); assertEquals(result, expected); } - + @Test public void testCleanPasswordFromRequestStringMatchedAtEndSingleQuote() { String input = "'username=foo&password=bar'"; @@ -108,4 +108,104 @@ public class StringUtilsTest { assertEquals("a-b-c", StringUtils.join("-", "a", "b", "c")); assertEquals("", StringUtils.join("-")); } + + @Test + public void testCleanSecretkeyFromJsonObjectAtEnd() { + String input = "{\"foo\":\"bar\",\"secretkey\":\"test\"}"; + // TODO: It would be nice to clean up the regex in question to not + // have to return the trailing comma in the expected string below + String expected = "{\"foo\":\"bar\",}"; + String result = StringUtils.cleanString(input); + assertEquals(result, expected); + } + + @Test + public void testCleanSecretkeyFromJsonObjectInMiddle() { + String input = "{\"foo\":\"bar\",\"secretkey\":\"test\",\"test\":\"blah\"}"; + String expected = "{\"foo\":\"bar\",\"test\":\"blah\"}"; + String result = StringUtils.cleanString(input); + assertEquals(result, expected); + } + + @Test + public void testCleanSecretkeyFromJsonObjectAlone() { + String input = "{\"secretkey\":\"test\"}"; + String expected = "{}"; + String result = StringUtils.cleanString(input); + assertEquals(result, expected); + } + + @Test + public void testCleanSecretkeyFromJsonObjectAtStart() { + String input = "{\"secretkey\":\"test\",\"test\":\"blah\"}"; + String expected = "{\"test\":\"blah\"}"; + String result = StringUtils.cleanString(input); + assertEquals(result, expected); + } + + @Test + public void testCleanSecretkeyFromJsonObjectWithMultiplePasswords() { + String input = "{\"description\":\"foo\"}],\"secretkey\":\"bar\",\"nic\":[{\"secretkey\":\"bar2\",\"id\":\"1\"}]}"; + String expected = "{\"description\":\"foo\"}],\"nic\":[{\"id\":\"1\"}]}"; + String result = StringUtils.cleanString(input); + assertEquals(result, expected); + } + + @Test + public void testCleanAccesskeyFromJsonObjectAtEnd() { + String input = "{\"foo\":\"bar\",\"accesskey\":\"test\"}"; + // TODO: It would be nice to clean up the regex in question to not + // have to return the trailing comma in the expected string below + String expected = "{\"foo\":\"bar\",}"; + String result = StringUtils.cleanString(input); + assertEquals(result, expected); + } + + @Test + public void testCleanAccesskeyFromJsonObjectInMiddle() { + String input = "{\"foo\":\"bar\",\"accesskey\":\"test\",\"test\":\"blah\"}"; + String expected = "{\"foo\":\"bar\",\"test\":\"blah\"}"; + String result = StringUtils.cleanString(input); + assertEquals(result, expected); + } + + @Test + public void testCleanAccesskeyFromJsonObjectAlone() { + String input = "{\"accesskey\":\"test\"}"; + String expected = "{}"; + String result = StringUtils.cleanString(input); + assertEquals(result, expected); + } + + @Test + public void testCleanAccesskeyFromJsonObjectAtStart() { + String input = "{\"accesskey\":\"test\",\"test\":\"blah\"}"; + String expected = "{\"test\":\"blah\"}"; + String result = StringUtils.cleanString(input); + assertEquals(result, expected); + } + + @Test + public void testCleanAccesskeyFromJsonObjectWithMultiplePasswords() { + String input = "{\"description\":\"foo\"}],\"accesskey\":\"bar\",\"nic\":[{\"accesskey\":\"bar2\",\"id\":\"1\"}]}"; + String expected = "{\"description\":\"foo\"}],\"nic\":[{\"id\":\"1\"}]}"; + String result = StringUtils.cleanString(input); + assertEquals(result, expected); + } + + @Test + public void testCleanAccesskeyFromRequestString() { + String input = "username=foo&accesskey=bar&url=foobar"; + String expected = "username=foo&url=foobar"; + String result = StringUtils.cleanString(input); + assertEquals(result, expected); + } + + @Test + public void testCleanSecretkeyFromRequestString() { + String input = "username=foo&secretkey=bar&url=foobar"; + String expected = "username=foo&url=foobar"; + String result = StringUtils.cleanString(input); + assertEquals(result, expected); + } } From 2df1d7f328b97700c6b2b6ede5a890daeb0fde6b Mon Sep 17 00:00:00 2001 From: Sheng Yang Date: Sun, 21 Jul 2013 17:09:19 -0700 Subject: [PATCH 20/74] Revert "CLOUDSTACK-3357: dnsmasq on vpc-routervm" This reverts commit f99d599930a4bc1bfcdfd44d4f088cdae58890e5. Due to it break vpc function and block regression test. Conflicts: server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java server/src/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImpl.java server/test/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImplTest.java --- .../VirtualNetworkApplianceManagerImpl.java | 22 +--- ...VpcVirtualNetworkApplianceManagerImpl.java | 70 ++-------- ...irtualNetworkApplianceManagerImplTest.java | 121 ------------------ .../test/resources/VpcVirtNetAppContext.xml | 41 ------ 4 files changed, 11 insertions(+), 243 deletions(-) delete mode 100644 server/test/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImplTest.java delete mode 100644 server/test/resources/VpcVirtNetAppContext.xml diff --git a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java index dda2df8fa87..6c0f7a1d4bc 100755 --- a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java +++ b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java @@ -1320,7 +1320,7 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V } } } - + protected class CheckRouterTask implements Runnable { public CheckRouterTask() { @@ -1589,12 +1589,6 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V InsufficientAddressCapacityException, InsufficientServerCapacityException, InsufficientCapacityException, StorageUnavailableException, ResourceUnavailableException { - if(s_logger.isTraceEnabled()) { - s_logger.trace("deployRouter(" + owner.getAccountName() + ", " + dest.getHost() + ", " + plan.toString() + ", " + params.toString() - + ", " + isRedundant + ", " + vrProvider.getUuid() + ", " + svcOffId + ", " + vpcId - + ", list_of_" + networks.size() + "networks, " + startRouter + ", " + supportedHypervisors + ")"); - } - ServiceOfferingVO routerOffering = _serviceOfferingDao.findById(svcOffId); // Router is the network element, we don't know the hypervisor type yet. @@ -1872,11 +1866,7 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V private DomainRouterVO startVirtualRouter(DomainRouterVO router, User user, Account caller, Map params) throws StorageUnavailableException, InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException { - - if(s_logger.isTraceEnabled()) { - s_logger.trace("startVirtualRouter(" + router.getHostName() + ", " + user.getUsername() + ", " + caller.getAccountName() + ", " + params.toString() + ")"); - } - + if (router.getRole() != Role.VIRTUAL_ROUTER || !router.getIsRedundantRouter()) { return this.start(router, user, caller, params, null); } @@ -2510,7 +2500,6 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V createIpAlias(router, activeIpAliasTOs, guestNetworkId, cmds); configDnsMasq(router, _networkDao.findById(guestNetworkId), cmds); } - } } } @@ -2912,9 +2901,6 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V public boolean applyDhcpEntry(Network network, final NicProfile nic, VirtualMachineProfile profile, DeployDestination dest, List routers) throws ResourceUnavailableException { - if(s_logger.isTraceEnabled()) { - s_logger.trace("applyDhcpEntry(" + network.getCidr() + ", " + nic.getMacAddress() + ", " + profile.getUuid() + ", " + dest.getHost() + ", " + routers + ")"); - } _userVmDao.loadDetails((UserVmVO) profile.getVirtualMachine()); final VirtualMachineProfile updatedProfile = profile; @@ -3448,9 +3434,6 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V } private void configDnsMasq(VirtualRouter router, Network network, Commands cmds) { - if (s_logger.isTraceEnabled()) { - s_logger.trace("configDnsMasq(" + router.getHostName() + ", " + network.getNetworkDomain() + ", " + cmds + ")"); - } DataCenterVO dcVo = _dcDao.findById(router.getDataCenterId()); List ipAliasVOList = _nicIpAliasDao.listByNetworkIdAndState(network.getId(), NicIpAlias.state.active); List ipList = new ArrayList(); @@ -3482,7 +3465,6 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V dnsMasqConfigCmd.setDomainSuffix(domain_suffix); dnsMasqConfigCmd.setIfDnsProvided(dnsProvided); cmds.addCommand("dnsMasqConfig" ,dnsMasqConfigCmd); - //To change body of created methods use File | Settings | File Templates. } diff --git a/server/src/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImpl.java b/server/src/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImpl.java index 3ca4331eedf..5dbecb77577 100644 --- a/server/src/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImpl.java +++ b/server/src/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImpl.java @@ -167,9 +167,6 @@ public class VpcVirtualNetworkApplianceManagerImpl extends VirtualNetworkApplian public List deployVirtualRouterInVpc(Vpc vpc, DeployDestination dest, Account owner, Map params) throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException { - if(s_logger.isTraceEnabled()) { - s_logger.trace("deployVirtualRouterInVpc(" + vpc.getName() +", "+dest.getHost()+", "+owner.getAccountName()+", "+params.toString()+")"); - } List routers = findOrDeployVirtualRouterInVpc(vpc, dest, owner, params); @@ -247,9 +244,7 @@ public class VpcVirtualNetworkApplianceManagerImpl extends VirtualNetworkApplian @Override public boolean addVpcRouterToGuestNetwork(VirtualRouter router, Network network, boolean isRedundant) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException { - if (s_logger.isTraceEnabled()) { - s_logger.trace("addVpcRouterToGuestNetwork(" + router.getUuid() + ", " + network.getCidr() + ", " + isRedundant + ")"); - } + if (network.getTrafficType() != TrafficType.Guest) { s_logger.warn("Network " + network + " is not of type " + TrafficType.Guest); return false; @@ -321,10 +316,7 @@ public class VpcVirtualNetworkApplianceManagerImpl extends VirtualNetworkApplian Long vpcId, PublicIp sourceNatIp) throws ConcurrentOperationException, InsufficientAddressCapacityException, InsufficientServerCapacityException, InsufficientCapacityException, StorageUnavailableException, ResourceUnavailableException { - if(s_logger.isTraceEnabled()) { - s_logger.trace("deployVpcRouter(" + owner.getAccountName() + ", " + dest.getHost() + ", " + plan.toString() + ", " + params.toString() - + ", " + isRedundant + ", " + vrProvider.getUuid() + ", " + svcOffId + ", " + vpcId + ", " + sourceNatIp + ")"); - } + List> networks = createVpcRouterNetworks(owner, isRedundant, plan, new Pair(true, sourceNatIp), vpcId); DomainRouterVO router = @@ -705,15 +697,12 @@ public class VpcVirtualNetworkApplianceManagerImpl extends VirtualNetworkApplian @Override public boolean finalizeCommandsOnStart(Commands cmds, VirtualMachineProfile profile) { DomainRouterVO router = profile.getVirtualMachine(); - if(s_logger.isTraceEnabled()) { - s_logger.trace("finalizeCommandsOnStart(" + cmds + ", " + profile.getHostName() + ")"); - } boolean isVpc = (router.getVpcId() != null); if (!isVpc) { return super.finalizeCommandsOnStart(cmds, profile); } - + //1) FORM SSH CHECK COMMAND NicProfile controlNic = getControlNic(profile); if (controlNic == null) { @@ -722,7 +711,7 @@ public class VpcVirtualNetworkApplianceManagerImpl extends VirtualNetworkApplian } finalizeSshAndVersionAndNetworkUsageOnStart(cmds, profile, router, controlNic); - + //2) FORM PLUG NIC COMMANDS List> guestNics = new ArrayList>(); List> publicNics = new ArrayList>(); @@ -875,49 +864,15 @@ public class VpcVirtualNetworkApplianceManagerImpl extends VirtualNetworkApplian //Add network usage commands cmds.addCommands(usageCmds); - configDnsMasq(router, cmds); - + return true; } - protected void configDnsMasq(VirtualRouter router, Commands cmds) { - if (s_logger.isTraceEnabled()) { - s_logger.trace("configDnsMasq(" + router.getHostName() + ", " + cmds + ")"); - } - VpcVO vpc = _vpcDao.findById(router.getVpcId()); - DataCenterVO dcVo = _dcDao.findById(router.getDataCenterId()); - List ipList = new ArrayList(); - - String cidr = vpc.getCidr(); - String[] cidrPair = cidr.split("\\/"); - String cidrAddress = cidrPair[0]; - long cidrSize = Long.parseLong(cidrPair[1]); - String startIpOfSubnet = NetUtils.getIpRangeStartIpFromCidr(cidrAddress, cidrSize); - DhcpTO DhcpTO = new DhcpTO(router.getPrivateIpAddress(), router.getPublicIpAddress(), NetUtils.getCidrNetmask(cidrSize), startIpOfSubnet); - ipList.add(DhcpTO); - - NicVO nic = _nicDao.findByIp4AddressAndVmId(_routerDao.findById(router.getId()).getPrivateIpAddress(), router.getId()); - DataCenterVO dcvo = _dcDao.findById(router.getDataCenterId()); - boolean dnsProvided = _networkModel.isProviderSupportServiceInNetwork(nic.getNetworkId(), Service.Dns, Provider.VirtualRouter); - String domain_suffix = dcvo.getDetail(ZoneConfig.DnsSearchOrder.getName()); - DnsMasqConfigCommand dnsMasqConfigCmd = new DnsMasqConfigCommand(vpc.getNetworkDomain(),ipList, dcVo.getDns1(), dcVo.getDns2(), dcVo.getInternalDns1(), dcVo.getInternalDns2()); - dnsMasqConfigCmd.setAccessDetail(NetworkElementCommand.ROUTER_IP, getRouterControlIp(router.getId())); - dnsMasqConfigCmd.setAccessDetail(NetworkElementCommand.ROUTER_NAME, router.getInstanceName()); - dnsMasqConfigCmd.setAccessDetail(NetworkElementCommand.ROUTER_GUEST_IP, router.getPublicIpAddress()); - dnsMasqConfigCmd.setAccessDetail(NetworkElementCommand.ZONE_NETWORK_TYPE, dcVo.getNetworkType().toString()); - dnsMasqConfigCmd.setDomainSuffix(domain_suffix); - dnsMasqConfigCmd.setIfDnsProvided(dnsProvided); - - cmds.addCommand("dnsMasqConfig" ,dnsMasqConfigCmd); - } - - @Override protected void finalizeNetworkRulesForNetwork(Commands cmds, DomainRouterVO router, Provider provider, Long guestNetworkId) { - if(s_logger.isTraceEnabled()) { - s_logger.trace("finalizing network config for "+ router.getHostName()); - } + super.finalizeNetworkRulesForNetwork(cmds, router, provider, guestNetworkId); + if (router.getVpcId() != null) { if (_networkModel.isProviderSupportServiceInNetwork(guestNetworkId, Service.NetworkACL, Provider.VPCVirtualRouter)) { List networkACLs = _networkACLMgr.listNetworkACLItems(guestNetworkId); @@ -927,10 +882,6 @@ public class VpcVirtualNetworkApplianceManagerImpl extends VirtualNetworkApplian createNetworkACLsCommands(networkACLs, router, cmds, guestNetworkId, false); } } - - if(s_logger.isDebugEnabled()) { - s_logger.debug("setup the vpc domain on router " + router.getHostName()); - } } } @@ -975,10 +926,7 @@ public class VpcVirtualNetworkApplianceManagerImpl extends VirtualNetworkApplian */ protected boolean setupVpcPrivateNetwork(VirtualRouter router, boolean add, NicProfile privateNic) throws ResourceUnavailableException { - if(s_logger.isTraceEnabled()) { - s_logger.trace("deployVpcRouter(" + router.getHostName() + ", " + add + ", " + privateNic.getMacAddress() + ")"); - } - + if (router.getState() == State.Running) { PrivateIpVO ipVO = _privateIpDao.findByIpAndSourceNetworkId(privateNic.getNetworkId(), privateNic.getIp4Address()); Network network = _networkDao.findById(privateNic.getNetworkId()); @@ -990,7 +938,7 @@ public class VpcVirtualNetworkApplianceManagerImpl extends VirtualNetworkApplian privateIps.add(ip); Commands cmds = new Commands(OnError.Stop); createVpcAssociatePrivateIPCommands(router, privateIps, cmds, add); - + if (sendCommandsToRouter(router, cmds)) { s_logger.debug("Successfully applied ip association for ip " + ip + " in vpc network " + network); return true; diff --git a/server/test/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImplTest.java b/server/test/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImplTest.java deleted file mode 100644 index 071f658f056..00000000000 --- a/server/test/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImplTest.java +++ /dev/null @@ -1,121 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -package com.cloud.network.router; - - -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyLong; -import static org.mockito.Matchers.anyString; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.mockingDetails; -import static org.mockito.Mockito.when; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map; - -import com.cloud.configuration.ZoneConfig; -import com.cloud.network.Network; -import com.cloud.network.NetworkModel; -import com.cloud.vm.VirtualMachine; -import org.apache.log4j.Logger; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -import com.cloud.agent.AgentManager.OnError; -import com.cloud.agent.api.routing.DnsMasqConfigCommand; -import com.cloud.agent.manager.Commands; -import com.cloud.dc.DataCenter.NetworkType; -import com.cloud.dc.DataCenterVO; -import com.cloud.dc.dao.DataCenterDao; -import com.cloud.hypervisor.Hypervisor.HypervisorType; -import com.cloud.network.NetworkManager; -import com.cloud.network.router.VirtualRouter.RedundantState; -import com.cloud.network.vpc.VpcVO; -import com.cloud.network.vpc.dao.VpcDao; -import com.cloud.vm.DomainRouterVO; -import com.cloud.vm.NicVO; -import com.cloud.vm.dao.DomainRouterDao; -import com.cloud.vm.dao.NicDao; - -@RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(locations="classpath:/VpcVirtNetAppContext.xml") -public class VpcVirtualNetworkApplianceManagerImplTest { - private static final Logger s_logger = Logger.getLogger(VpcVirtualNetworkApplianceManagerImplTest.class); - - @Mock DataCenterDao _dcDao; - @Mock VpcDao _vpcDao; - @Mock VirtualRouter router; - @Mock NicDao _nicDao; - @Mock DomainRouterDao _routerDao; - @Mock NetworkModel _networkmodel; - @Mock NicVO nicVO; - @Mock DataCenterVO dcVO; - - @Before - public void setup() { - MockitoAnnotations.initMocks(this); - - } - - @Test - public void testConfigDnsMasq() { - VpcVirtualNetworkApplianceManagerImpl vpcVirtNetAppMgr = new VpcVirtualNetworkApplianceManagerImpl(); - vpcVirtNetAppMgr._vpcDao = _vpcDao; - vpcVirtNetAppMgr._dcDao = _dcDao; - vpcVirtNetAppMgr._nicDao = _nicDao; - vpcVirtNetAppMgr._routerDao = _routerDao; - when(router.getId()).thenReturn(1L); - when(router.getVpcId()).thenReturn(1L); - when(router.getDataCenterId()).thenReturn(1L); - VpcVO vpc = new VpcVO(1L,"bla","bla",1L,1L,1L,"10.0.0.0/8","blieb.net"); - when( _vpcDao.findById(1L)).thenReturn(vpc); - DataCenterVO dcVo = new DataCenterVO(1L,"dc","dc","8.8.8.8",null,null,null,"10.0.0.0/8","bla.net",new Long(1L),NetworkType.Advanced,null,".net"); - Map map = new HashMap(); - dcVo.setDetails(map); - dcVo.setDetail(ZoneConfig.DnsSearchOrder.getName(), "dummy"); - when(_dcDao.findById(1L)).thenReturn(dcVo); - DomainRouterVO routerVo = new DomainRouterVO(1L,1L,1L,"brr",1L,HypervisorType.Any,1L,1L,1L,false,0,false,RedundantState.MASTER,false,false,1L); - when( _routerDao.findById(1L)).thenReturn(routerVo); -// when( vpcVirtNetAppMgr.getRouterControlIp(1L)).thenReturn("10.0.0.1"); - when( router.getInstanceName()).thenReturn("r-vm-1"); - when( router.getPublicIpAddress()).thenReturn("11.11.11.11"); - NicVO nicvo = new NicVO("server", 1l, 1l, VirtualMachine.Type.DomainRouter); - nicvo.setNetworkId(1l); - when(_nicDao.findByIp4AddressAndVmId(anyString(), anyLong())).thenReturn(nicvo); - NetworkManager netMgr = mock(NetworkManager.class); - vpcVirtNetAppMgr._networkMgr = netMgr; - vpcVirtNetAppMgr._networkModel = _networkmodel; - when(nicVO.getNetworkId()).thenReturn(1l); - when(_networkmodel.isProviderSupportServiceInNetwork(1l, Network.Service.Dhcp, Network.Provider.VirtualRouter)).thenReturn(true); - when(dcVO.getDetail(anyString())).thenReturn(null); - Commands cmds = new Commands(OnError.Stop); - - vpcVirtNetAppMgr.configDnsMasq(router, cmds); - Assert.assertEquals("expected one command",1, cmds.size()); - - DnsMasqConfigCommand cmd = cmds.getCommand(DnsMasqConfigCommand.class); - } - -} diff --git a/server/test/resources/VpcVirtNetAppContext.xml b/server/test/resources/VpcVirtNetAppContext.xml deleted file mode 100644 index f8a8aa4ea4d..00000000000 --- a/server/test/resources/VpcVirtNetAppContext.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - - From 982c0b5dfb41b90ba5ee7f2c478f26384e89c316 Mon Sep 17 00:00:00 2001 From: Sheng Yang Date: Sun, 21 Jul 2013 19:40:10 -0700 Subject: [PATCH 21/74] CLOUDSTACK-3643: Automation: Fix wrong network acl rule for ping --- test/integration/component/test_vpc.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/test/integration/component/test_vpc.py b/test/integration/component/test_vpc.py index c503be8045c..3a661d59b8e 100644 --- a/test/integration/component/test_vpc.py +++ b/test/integration/component/test_vpc.py @@ -143,11 +143,11 @@ class Services: # Any network (For creating FW rule) "protocol": "TCP" }, - "http_rule": { - "startport": 80, - "endport": 80, + "icmp_rule": { + "icmptype": -1, + "icmpcode": -1, "cidrlist": '0.0.0.0/0', - "protocol": "TCP" + "protocol": "ICMP" }, "virtual_machine": { "displayname": "Test VM", @@ -1066,13 +1066,13 @@ class TestVPC(cloudstackTestCase): nwacl_internet_1 = NetworkACL.create( self.apiclient, networkid=network_1.id, - services=self.services["http_rule"], + services=self.services["icmp_rule"], traffictype='Egress' ) nwacl_internet_2 = NetworkACL.create( self.apiclient, networkid=network_2.id, - services=self.services["http_rule"], + services=self.services["icmp_rule"], traffictype='Egress' ) @@ -1411,13 +1411,13 @@ class TestVPC(cloudstackTestCase): nwacl_internet_1 = NetworkACL.create( self.apiclient, networkid=network_1.id, - services=self.services["http_rule"], + services=self.services["icmp_rule"], traffictype='Egress' ) nwacl_internet_2 = NetworkACL.create( self.apiclient, networkid=network_2.id, - services=self.services["http_rule"], + services=self.services["icmp_rule"], traffictype='Egress' ) From a102853fb9cf7a74fccf80f1ea42513f11316d8e Mon Sep 17 00:00:00 2001 From: Sheng Yang Date: Sun, 21 Jul 2013 20:11:16 -0700 Subject: [PATCH 22/74] CLOUDSTACK-3643: Automation: Fix test_vpc_network.py 1. Port 80 won't help on ICMP 2. RvR doesn't support VPC now. --- test/integration/component/test_vpc_network.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/test/integration/component/test_vpc_network.py b/test/integration/component/test_vpc_network.py index d76996ae85b..477c79e58e8 100644 --- a/test/integration/component/test_vpc_network.py +++ b/test/integration/component/test_vpc_network.py @@ -148,9 +148,9 @@ class Services: # Any network (For creating FW rule) "protocol": "TCP" }, - "http_rule": { - "startport": 80, - "endport": 80, + "icmp_rule": { + "icmptype": -1, + "icmpcode": -1, "cidrlist": '0.0.0.0/0', "protocol": "ICMP" }, @@ -690,6 +690,7 @@ class TestVPCNetwork(cloudstackTestCase): self.debug("Network creation failed") return + @unittest.skip("skipped - RvR didn't support VPC currently ") @attr(tags=["advanced", "intervlan"]) def test_06_create_network_with_rvr(self): """ Test create network with redundant router capability @@ -1823,7 +1824,7 @@ class TestVPCNetworkUpgrade(cloudstackTestCase): nwacl_internet_1 = NetworkACL.create( self.apiclient, networkid=network_1.id, - services=self.services["http_rule"], + services=self.services["icmp_rule"], traffictype='Egress' ) @@ -2212,7 +2213,7 @@ class TestVPCNetworkGc(cloudstackTestCase): cls.nwacl_internet_1 = NetworkACL.create( cls.api_client, networkid=cls.network_1.id, - services=cls.services["http_rule"], + services=cls.services["icmp_rule"], traffictype='Egress' ) cls._cleanup = [ From d893cb48a51ffe08236dcfafaedf882af2ee9a5e Mon Sep 17 00:00:00 2001 From: Sheng Yang Date: Sun, 21 Jul 2013 22:15:22 -0700 Subject: [PATCH 23/74] CLOUDSTACK-3699: Fix ARP broadcast of VPC router Every new public IP should be send out ARP broadcast. --- patches/systemvm/debian/config/opt/cloud/bin/vpc_ipassoc.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/patches/systemvm/debian/config/opt/cloud/bin/vpc_ipassoc.sh b/patches/systemvm/debian/config/opt/cloud/bin/vpc_ipassoc.sh index f2f8a49339e..a5b02398086 100755 --- a/patches/systemvm/debian/config/opt/cloud/bin/vpc_ipassoc.sh +++ b/patches/systemvm/debian/config/opt/cloud/bin/vpc_ipassoc.sh @@ -76,8 +76,9 @@ add_an_ip () { if [ $old_state -eq 0 ] then sudo ip link set $ethDev up - sudo arping -c 3 -I $ethDev -A -U -s $pubIp $pubIp fi + sudo arping -c 1 -I $ethDev -A -U -s $pubIp $pubIp + sudo arping -c 1 -I $ethDev -A -U -s $pubIp $pubIp local tableNo=${ethDev:3} sudo iptables-save -t mangle | grep "PREROUTING -i $ethDev -m state --state NEW -j CONNMARK --set-xmark" 2>/dev/null if [ $? -gt 0 ] From 2d55914e70dd7589e9cb2c3e105c4d91369a08b5 Mon Sep 17 00:00:00 2001 From: Prasanna Santhanam Date: Mon, 22 Jul 2013 12:15:12 +0530 Subject: [PATCH 24/74] CLOUDSTACK-3075: append module/suite name If the test doesn't create the account within the testXxx method we miss the trail of the accountname because the setUpClass() created the account. Append the module name in advance in such cases to identify the account that was created in the suite before any tests were executed. Signed-off-by: Prasanna Santhanam (cherry picked from commit 6a8608a916eec2551797e93634d9716e9d15c783) --- tools/marvin/marvin/marvinPlugin.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/tools/marvin/marvin/marvinPlugin.py b/tools/marvin/marvin/marvinPlugin.py index a0ec3d5eb20..19930d43186 100644 --- a/tools/marvin/marvin/marvinPlugin.py +++ b/tools/marvin/marvin/marvinPlugin.py @@ -110,12 +110,16 @@ class MarvinPlugin(Plugin): return self.testrunner def wantClass(self, cls): + if cls.__name__ == 'cloudstackTestCase': + return False if issubclass(cls, cloudstackTestCase): return True return None def loadTestsFromTestCase(self, cls): - self._injectClients(cls) + if cls.__name__ != 'cloudstackTestCase': + self.testclient.identifier = cls.__name__ + self._injectClients(cls) def setClient(self, client): if client is not None: @@ -126,11 +130,14 @@ class MarvinPlugin(Plugin): self.config = config def beforeTest(self, test): - self.testclient.identifier = test.__str__().split()[0] + testname = test.__str__().split()[0] + self.testclient.identifier = '-'.join([self.testclient.identifier, testname]) def _injectClients(self, test): testcaselogger = logging.getLogger("testclient.testcase.%s" % test.__name__) + + self.debug_stream. \ setFormatter(logging. Formatter("%(asctime)s - %(levelname)s - %(name)s" + From a75a62a318a6238df69dec7674ea7a587069e1e9 Mon Sep 17 00:00:00 2001 From: Prasanna Santhanam Date: Mon, 22 Jul 2013 12:49:42 +0530 Subject: [PATCH 25/74] CLOUDSTACK-3075: Test names appended with - Prevent chained appending of the testclass/testnames to the accounnt names. Signed-off-by: Prasanna Santhanam (cherry picked from commit fb75f51755a2a0f28766f3e15b3e349151c85334) --- tools/marvin/marvin/marvinPlugin.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/marvin/marvin/marvinPlugin.py b/tools/marvin/marvin/marvinPlugin.py index 19930d43186..ca226f85635 100644 --- a/tools/marvin/marvin/marvinPlugin.py +++ b/tools/marvin/marvin/marvinPlugin.py @@ -104,6 +104,7 @@ class MarvinPlugin(Plugin): Plugin.options(self, parser, env) def __init__(self): + self.identifier = None Plugin.__init__(self) def prepareTestRunner(self, runner): @@ -118,7 +119,7 @@ class MarvinPlugin(Plugin): def loadTestsFromTestCase(self, cls): if cls.__name__ != 'cloudstackTestCase': - self.testclient.identifier = cls.__name__ + self.identifier = cls.__name__ self._injectClients(cls) def setClient(self, client): @@ -131,7 +132,7 @@ class MarvinPlugin(Plugin): def beforeTest(self, test): testname = test.__str__().split()[0] - self.testclient.identifier = '-'.join([self.testclient.identifier, testname]) + self.testclient.identifier = '-'.join([self.identifier, testname]) def _injectClients(self, test): testcaselogger = logging.getLogger("testclient.testcase.%s" % From 39a730ccd1977d13221a0897beb5047828aa24ae Mon Sep 17 00:00:00 2001 From: Isaac Chiang Date: Mon, 22 Jul 2013 15:33:48 +0800 Subject: [PATCH 26/74] CLOUDSTACK-3388:No error message shows when a dedicate operation failed during the creation of a pod/cluster --- ui/scripts/system.js | 35 ++++++++++++++++--------------- ui/scripts/ui/widgets/listView.js | 22 +++++++++++-------- 2 files changed, 31 insertions(+), 26 deletions(-) diff --git a/ui/scripts/system.js b/ui/scripts/system.js index 4da35115630..eb15362bdcf 100644 --- a/ui/scripts/system.js +++ b/ui/scripts/system.js @@ -10126,7 +10126,9 @@ jobId: jid }, notification: { - poll: pollAsyncJobResult + poll: pollAsyncJobResult, + interval: 4500, + desc: "Dedicate Pod" }, data: item @@ -10141,12 +10143,10 @@ }); } - } else { - args.response.success({ - data: item - }); } - + args.response.success({ + data: item + }); }, error: function(XMLHttpResponse) { var errorMsg = parseXMLHttpResponse(XMLHttpResponse); @@ -11226,7 +11226,9 @@ jobId: jid }, notification: { - poll: pollAsyncJobResult + poll: pollAsyncJobResult, + interval: 4500, + desc: "Dedicate Cluster" }, data: $.extend(item, { @@ -11240,11 +11242,10 @@ } }); } - } else { - args.response.success({ - data: item - }); } + args.response.success({ + data: item + }); }, error: function(XMLHttpResponse) { var errorMsg = parseXMLHttpResponse(XMLHttpResponse); @@ -12458,7 +12459,9 @@ jobId: jid }, notification: { - poll: pollAsyncJobResult + poll: pollAsyncJobResult, + interval: 4500, + desc: "Dedicate Host" }, data: item @@ -12472,12 +12475,10 @@ } }); } - } else { - args.response.success({ - data: item - }); } - + args.response.success({ + data: item + }); }, error: function(XMLHttpResponse) { diff --git a/ui/scripts/ui/widgets/listView.js b/ui/scripts/ui/widgets/listView.js index 4fd0b7ff3f1..a2d9063e5b7 100644 --- a/ui/scripts/ui/widgets/listView.js +++ b/ui/scripts/ui/widgets/listView.js @@ -185,6 +185,8 @@ return false; }); + if(args.notification) notification = args.notification; + notification._custom = args._custom; if (additional && additional.success) additional.success(args); @@ -250,25 +252,27 @@ // Error - function(args) { + function(errorArgs) { if (!isHeader) { if ($instanceRow.data('list-view-new-item')) { // For create forms $instanceRow.remove(); } else { // For standard actions - replaceItem( - $instanceRow, - $.extend($instanceRow.data('json-obj'), args.data), - args.actionFilter ? - args.actionFilter : - $instanceRow.data('list-view-action-filter') - ); + if(!args.notification) { + replaceItem( + $instanceRow, + $.extend($instanceRow.data('json-obj'), errorArgs.data), + errorArgs.actionFilter ? + errorArgs.actionFilter : + $instanceRow.data('list-view-action-filter') + ); + } } } if (options.error) { - options.error(args); + options.error(errorArgs); } } ); From d2c1ed4865a975b10eaa95953743e1a9da22316c Mon Sep 17 00:00:00 2001 From: Wei Zhou Date: Mon, 22 Jul 2013 16:06:10 +0200 Subject: [PATCH 27/74] ui change: Disk I/O polling statistics --- .../xen/resource/CitrixResourceBase.java | 79 ------------------- ui/scripts/instances.js | 8 +- 2 files changed, 4 insertions(+), 83 deletions(-) diff --git a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java index f80d4b62940..6462ff6c100 100644 --- a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java +++ b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java @@ -139,8 +139,6 @@ import com.cloud.agent.api.GetHostStatsAnswer; import com.cloud.agent.api.GetHostStatsCommand; import com.cloud.agent.api.GetStorageStatsAnswer; import com.cloud.agent.api.GetStorageStatsCommand; -import com.cloud.agent.api.GetVmDiskStatsAnswer; -import com.cloud.agent.api.GetVmDiskStatsCommand; import com.cloud.agent.api.GetVmStatsAnswer; import com.cloud.agent.api.GetVmStatsCommand; import com.cloud.agent.api.GetVncPortAnswer; @@ -195,7 +193,6 @@ import com.cloud.agent.api.UnPlugNicAnswer; import com.cloud.agent.api.UnPlugNicCommand; import com.cloud.agent.api.UpdateHostPasswordCommand; import com.cloud.agent.api.UpgradeSnapshotCommand; -import com.cloud.agent.api.VmDiskStatsEntry; import com.cloud.agent.api.VmStatsEntry; import com.cloud.agent.api.check.CheckSshAnswer; import com.cloud.agent.api.check.CheckSshCommand; @@ -498,8 +495,6 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return execute((GetHostStatsCommand) cmd); } else if (clazz == GetVmStatsCommand.class) { return execute((GetVmStatsCommand) cmd); - } else if (cmd instanceof GetVmDiskStatsCommand) { - return execute((GetVmDiskStatsCommand) cmd); } else if (clazz == CheckHealthCommand.class) { return execute((CheckHealthCommand) cmd); } else if (clazz == StopCommand.class) { @@ -2636,80 +2631,6 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return hostStats; } - protected GetVmDiskStatsAnswer execute( GetVmDiskStatsCommand cmd) { - Connection conn = getConnection(); - List vmNames = cmd.getVmNames(); - HashMap> vmDiskStatsNameMap = new HashMap>(); - if( vmNames.size() == 0 ) { - return new GetVmDiskStatsAnswer(cmd, "", cmd.getHostName(),vmDiskStatsNameMap); - } - try { - - // Determine the UUIDs of the requested VMs - List vmUUIDs = new ArrayList(); - - for (String vmName : vmNames) { - VM vm = getVM(conn, vmName); - vmUUIDs.add(vm.getUuid(conn)); - } - - HashMap> vmDiskStatsUUIDMap = getVmDiskStats(conn, cmd, vmUUIDs, cmd.getHostGuid()); - if( vmDiskStatsUUIDMap == null ) { - return new GetVmDiskStatsAnswer(cmd, "", cmd.getHostName(), vmDiskStatsNameMap); - } - - for (String vmUUID : vmDiskStatsUUIDMap.keySet()) { - List vmDiskStatsUUID = vmDiskStatsUUIDMap.get(vmUUID); - String vmName = vmNames.get(vmUUIDs.indexOf(vmUUID)); - for (VmDiskStatsEntry vmDiskStat : vmDiskStatsUUID) { - vmDiskStat.setVmName(vmName); - } - vmDiskStatsNameMap.put(vmName, vmDiskStatsUUID); - } - - return new GetVmDiskStatsAnswer(cmd, "", cmd.getHostName(),vmDiskStatsNameMap); - } catch (XenAPIException e) { - String msg = "Unable to get VM disk stats" + e.toString(); - s_logger.warn(msg, e); - return new GetVmDiskStatsAnswer(cmd, "", cmd.getHostName(),vmDiskStatsNameMap); - } catch (XmlRpcException e) { - String msg = "Unable to get VM disk stats" + e.getMessage(); - s_logger.warn(msg, e); - return new GetVmDiskStatsAnswer(cmd, "", cmd.getHostName(),vmDiskStatsNameMap); - } - } - - private HashMap> getVmDiskStats(Connection conn, GetVmDiskStatsCommand cmd, List vmUUIDs, String hostGuid) { - HashMap> vmResponseMap = new HashMap>(); - - for (String vmUUID : vmUUIDs) { - vmResponseMap.put(vmUUID, new ArrayList()); - } - - try { - for (String vmUUID : vmUUIDs) { - VM vm = VM.getByUuid(conn, vmUUID); - List vmDiskStats = new ArrayList(); - for (VBD vbd : vm.getVBDs(conn)) { - if (!vbd.getType(conn).equals(Types.VbdType.CD)) { - VmDiskStatsEntry stats = new VmDiskStatsEntry(); - VBDMetrics record = vbd.getMetrics(conn); - stats.setPath(vbd.getVDI(conn).getUuid(conn)); - stats.setBytesRead((long)(record.getIoReadKbs(conn) * 1024)); - stats.setBytesWrite((long)(record.getIoWriteKbs(conn) * 1024)); - vmDiskStats.add(stats); - } - } - vmResponseMap.put(vmUUID, vmDiskStats); - } - } catch (Exception e) { - s_logger.warn("Error while collecting disk stats from : ", e); - return null; - } - - return vmResponseMap; - } - protected GetVmStatsAnswer execute( GetVmStatsCommand cmd) { Connection conn = getConnection(); List vmNames = cmd.getVmNames(); diff --git a/ui/scripts/instances.js b/ui/scripts/instances.js index c53223c3f68..12adfbb66c3 100644 --- a/ui/scripts/instances.js +++ b/ui/scripts/instances.js @@ -1831,10 +1831,10 @@ cpuused: jsonObj.cpuused, networkkbsread: (jsonObj.networkkbsread == null) ? "N/A" : cloudStack.converters.convertBytes(jsonObj.networkkbsread * 1024), networkkbswrite: (jsonObj.networkkbswrite == null) ? "N/A" : cloudStack.converters.convertBytes(jsonObj.networkkbswrite * 1024), - diskkbsread: (jsonObj.diskkbsread == null) ? "N/A" : cloudStack.converters.convertBytes(jsonObj.diskkbsread * 1024), - diskkbswrite: (jsonObj.diskkbswrite == null) ? "N/A" : cloudStack.converters.convertBytes(jsonObj.diskkbswrite * 1024), - diskioread: (jsonObj.diskioread == null) ? "N/A" : jsonObj.diskioread, - diskiowrite: (jsonObj.diskiowrite == null) ? "N/A" : jsonObj.diskiowrite + diskkbsread: (jsonObj.diskkbsread == null) ? "N/A" : ((jsonObj.hypervisor == "KVM") ? cloudStack.converters.convertBytes(jsonObj.diskkbsread * 1024) : ((jsonObj.hypervisor == "XenServer") ? cloudStack.converters.convertBytes(jsonObj.diskkbsread * 1024) + "/s" : "N/A")), + diskkbswrite: (jsonObj.diskkbswrite == null) ? "N/A" : ((jsonObj.hypervisor == "KVM") ? cloudStack.converters.convertBytes(jsonObj.diskkbswrite * 1024) : ((jsonObj.hypervisor == "XenServer") ? cloudStack.converters.convertBytes(jsonObj.diskkbswrite * 1024) + "/s" : "N/A")), + diskioread: (jsonObj.diskioread == null) ? "N/A" : ((jsonObj.hypervisor == "KVM") ? jsonObj.diskioread : "N/A"), + diskiowrite: (jsonObj.diskiowrite == null) ? "N/A" : ((jsonObj.hypervisor == "KVM") ? jsonObj.diskiowrite : "N/A") } }); } From e245718837c30caa651d3d5017256adb810602b9 Mon Sep 17 00:00:00 2001 From: Gaurav Aradhye Date: Sun, 21 Jul 2013 21:34:12 -0400 Subject: [PATCH 28/74] CLOUDSTACK-3679: Added subsequent change that was needed after change in try_ssh function Signed-off-by: Prasanna Santhanam (cherry picked from commit 233456d95f80effa293e21e199886d61b17dbd19) --- test/integration/smoke/test_loadbalance.py | 54 +++++++++++----------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/test/integration/smoke/test_loadbalance.py b/test/integration/smoke/test_loadbalance.py index 4e1f0c109d4..f5405da5e1f 100644 --- a/test/integration/smoke/test_loadbalance.py +++ b/test/integration/smoke/test_loadbalance.py @@ -323,11 +323,11 @@ class TestLoadBalance(cloudstackTestCase): hostnames = [] - self.try_ssh(src_nat_ip_addr, hostnames) - self.try_ssh(src_nat_ip_addr, hostnames) - self.try_ssh(src_nat_ip_addr, hostnames) - self.try_ssh(src_nat_ip_addr, hostnames) - self.try_ssh(src_nat_ip_addr, hostnames) + self.try_ssh(src_nat_ip_addr.ipaddress, hostnames) + self.try_ssh(src_nat_ip_addr.ipaddress, hostnames) + self.try_ssh(src_nat_ip_addr.ipaddress, hostnames) + self.try_ssh(src_nat_ip_addr.ipaddress, hostnames) + self.try_ssh(src_nat_ip_addr.ipaddress, hostnames) self.debug("Hostnames: %s" % str(hostnames)) self.assertIn( @@ -354,7 +354,7 @@ class TestLoadBalance(cloudstackTestCase): self.vm_2.id )) - self.try_ssh(src_nat_ip_addr, hostnames) + self.try_ssh(src_nat_ip_addr.ipaddress, hostnames) self.assertIn( self.vm_1.name, hostnames, @@ -368,7 +368,7 @@ class TestLoadBalance(cloudstackTestCase): with self.assertRaises(Exception): self.debug("Removed all VMs, trying to SSH") - self.try_ssh(src_nat_ip_addr, hostnames) + self.try_ssh(src_nat_ip_addr.ipaddress, hostnames) return @attr(tags = ["advanced", "advancedns", "smoke"]) @@ -440,11 +440,11 @@ class TestLoadBalance(cloudstackTestCase): ) try: hostnames = [] - self.try_ssh(self.non_src_nat_ip.ipaddress, hostnames) - self.try_ssh(self.non_src_nat_ip.ipaddress, hostnames) - self.try_ssh(self.non_src_nat_ip.ipaddress, hostnames) - self.try_ssh(self.non_src_nat_ip.ipaddress, hostnames) - self.try_ssh(self.non_src_nat_ip.ipaddress, hostnames) + self.try_ssh(self.non_src_nat_ip.ipaddress.ipaddress, hostnames) + self.try_ssh(self.non_src_nat_ip.ipaddress.ipaddress, hostnames) + self.try_ssh(self.non_src_nat_ip.ipaddress.ipaddress, hostnames) + self.try_ssh(self.non_src_nat_ip.ipaddress.ipaddress, hostnames) + self.try_ssh(self.non_src_nat_ip.ipaddress.ipaddress, hostnames) self.debug("Hostnames: %s" % str(hostnames)) self.assertIn( @@ -468,7 +468,7 @@ class TestLoadBalance(cloudstackTestCase): # Making host list empty hostnames[:] = [] - self.try_ssh(self.non_src_nat_ip.ipaddress, hostnames) + self.try_ssh(self.non_src_nat_ip.ipaddress.ipaddress, hostnames) self.assertIn( self.vm_1.name, hostnames, @@ -486,7 +486,7 @@ class TestLoadBalance(cloudstackTestCase): self.non_src_nat_ip.ipaddress.ipaddress, self.vm_1.id )) - self.try_ssh(self.non_src_nat_ip, hostnames) + self.try_ssh(self.non_src_nat_ip.ipaddress.ipaddress, hostnames) return @attr(tags = ["advanced", "advancedns", "smoke"]) @@ -535,11 +535,11 @@ class TestLoadBalance(cloudstackTestCase): lb_rule.assign(self.apiclient, [self.vm_1, self.vm_2]) hostnames = [] - self.try_ssh(self.non_src_nat_ip.ipaddress, hostnames) - self.try_ssh(self.non_src_nat_ip.ipaddress, hostnames) - self.try_ssh(self.non_src_nat_ip.ipaddress, hostnames) - self.try_ssh(self.non_src_nat_ip.ipaddress, hostnames) - self.try_ssh(self.non_src_nat_ip.ipaddress, hostnames) + self.try_ssh(self.non_src_nat_ip.ipaddress.ipaddress, hostnames) + self.try_ssh(self.non_src_nat_ip.ipaddress.ipaddress, hostnames) + self.try_ssh(self.non_src_nat_ip.ipaddress.ipaddress, hostnames) + self.try_ssh(self.non_src_nat_ip.ipaddress.ipaddress, hostnames) + self.try_ssh(self.non_src_nat_ip.ipaddress.ipaddress, hostnames) self.debug("Hostnames: %s" % str(hostnames)) self.assertIn( @@ -561,10 +561,10 @@ class TestLoadBalance(cloudstackTestCase): try: self.debug("SSHing again into IP address: %s with VM (ID: %s) added to LB rule" % ( - self.non_src_nat_ip.ipaddress, + self.non_src_nat_ip.ipaddress.ipaddress, self.vm_1.id, )) - self.try_ssh(self.non_src_nat_ip.ipaddress, hostnames) + self.try_ssh(self.non_src_nat_ip.ipaddress.ipaddress, hostnames) self.assertIn( self.vm_1.name, @@ -573,17 +573,17 @@ class TestLoadBalance(cloudstackTestCase): ) except Exception as e: self.fail("SSH failed for VM with IP: %s" % - self.non_src_nat_ip.ipaddress) + self.non_src_nat_ip.ipaddress.ipaddress) lb_rule.assign(self.apiclient, [self.vm_3]) # # Making hostnames list empty hostnames[:] = [] - self.try_ssh(self.non_src_nat_ip.ipaddress, hostnames) - self.try_ssh(self.non_src_nat_ip.ipaddress, hostnames) - self.try_ssh(self.non_src_nat_ip.ipaddress, hostnames) - self.try_ssh(self.non_src_nat_ip.ipaddress, hostnames) - self.try_ssh(self.non_src_nat_ip.ipaddress, hostnames) + self.try_ssh(self.non_src_nat_ip.ipaddress.ipaddress, hostnames) + self.try_ssh(self.non_src_nat_ip.ipaddress.ipaddress, hostnames) + self.try_ssh(self.non_src_nat_ip.ipaddress.ipaddress, hostnames) + self.try_ssh(self.non_src_nat_ip.ipaddress.ipaddress, hostnames) + self.try_ssh(self.non_src_nat_ip.ipaddress.ipaddress, hostnames) self.debug("Hostnames: %s" % str(hostnames)) self.assertIn( self.vm_1.name, From 5fa77f3099e0e1c422df94368ac81ee75f95395f Mon Sep 17 00:00:00 2001 From: Prasanna Santhanam Date: Mon, 22 Jul 2013 14:48:56 +0530 Subject: [PATCH 29/74] Minor fixes to the test_accounts when an account is deleted listAccounts raises an exception. Signed-off-by: Prasanna Santhanam (cherry picked from commit aa9bc4413efad4eccdf8e336f66ea8c8168fbbda) --- test/integration/component/test_accounts.py | 26 ++++++++------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/test/integration/component/test_accounts.py b/test/integration/component/test_accounts.py index 7d0aeb1e352..b5861766f5e 100644 --- a/test/integration/component/test_accounts.py +++ b/test/integration/component/test_accounts.py @@ -24,8 +24,7 @@ from marvin.integration.lib.base import * from marvin.integration.lib.common import * from marvin import remoteSSHClient from nose.plugins.attrib import attr -import datetime - +from marvin.cloudstackException import cloudstackAPIException class Services: """Test Account Services @@ -831,12 +830,12 @@ class TestServiceOfferingHierarchy(cloudstackTestCase): return -class TesttemplateHierarchy(cloudstackTestCase): +class TestTemplateHierarchy(cloudstackTestCase): @classmethod def setUpClass(cls): cls.api_client = super( - TesttemplateHierarchy, + TestTemplateHierarchy, cls).getClsTestClient().getApiClient() cls.services = Services().services # Get Zone settings @@ -1788,18 +1787,13 @@ class TestDomainForceRemove(cloudstackTestCase): # Sleep to ensure that all resources are deleted time.sleep(int(configurations[0].value) * 2) self.debug("Checking if the resources in domain are deleted or not..") - accounts = Account.list( - self.apiclient, - name=self.account_1.name, - domainid=self.account_1.domainid, - listall=True - ) - - self.assertEqual( - accounts, - None, - "Account should get automatically deleted after domain removal" - ) + with self.assertRaises(cloudstackAPIException): + Account.list( + self.apiclient, + name=self.account_1.name, + domainid=self.account_1.domainid, + listall=True + ) return @attr(tags=["domains", "advanced", "advancedns", "simulator"]) From 323db5c51737f995a8edfd2ba23afbf2836c971c Mon Sep 17 00:00:00 2001 From: Prasanna Santhanam Date: Mon, 22 Jul 2013 14:50:45 +0530 Subject: [PATCH 30/74] CLOUDSTACK-3672: Multiple minor fixes to tags tests - SourceHost is an id - Invalid format in debug() message corrected Signed-off-by: Prasanna Santhanam (cherry picked from commit ce4dd723ab486894523f08f48b6054f614be4d85) --- test/integration/component/test_tags.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/integration/component/test_tags.py b/test/integration/component/test_tags.py index 52df6da5554..f10641b762c 100644 --- a/test/integration/component/test_tags.py +++ b/test/integration/component/test_tags.py @@ -1083,12 +1083,12 @@ class TestResourceTags(cloudstackTestCase): 'CentOS', 'The tag should have original value' ) - isos = Iso.list( self.apiclient, - listall=True, key='OS', - value='CentOS' + value='CentOS', + account=self.account.name, + domainid=self.account.domainid ) self.assertEqual( @@ -1096,7 +1096,7 @@ class TestResourceTags(cloudstackTestCase): True, "List isos should not return an empty response" ) - + self.debug("Deleting the created tag..") try: tag.delete( @@ -1454,14 +1454,14 @@ class TestResourceTags(cloudstackTestCase): self.debug("Available hosts: ") for host in hosts: - self.debug("Host: %s", host.id) + self.debug("Host: %s" % host.id) # Filtering out the source host from list host response temp_hosts = [host for host in hosts if host.id != source_host] dest_host = temp_hosts[0] self.debug("Destination host is: %s" % dest_host.id) - self.debug("Source host is: %s" % source_host.id) + self.debug("Source host is: %s" % source_host) self.debug("Creating a tag for user VM") tag = Tag.create( From 4956e468842f8b59a2b165351ac233c01dca15bf Mon Sep 17 00:00:00 2001 From: Prasanna Santhanam Date: Mon, 22 Jul 2013 14:52:04 +0530 Subject: [PATCH 31/74] CLOUDSTACK-3075: When only setUpClass() is creating account Missed scenario for appending test case names to accounts when setUpClass calls the account.creation integration library. Signed-off-by: Prasanna Santhanam (cherry picked from commit 9a5d2e9e36411ac5df17baca13874e0575233dac) --- tools/marvin/marvin/marvinPlugin.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/marvin/marvin/marvinPlugin.py b/tools/marvin/marvin/marvinPlugin.py index ca226f85635..8a548cd63de 100644 --- a/tools/marvin/marvin/marvinPlugin.py +++ b/tools/marvin/marvin/marvinPlugin.py @@ -150,6 +150,8 @@ class MarvinPlugin(Plugin): setattr(test, "testClient", self.testclient) setattr(test, "config", self.config) setattr(test, "debug", partial(testCaseLogger, logger=testcaselogger)) + if self.testclient.identifier is None: + self.testclient.identifier = self.identifier setattr(test, "clstestclient", self.testclient) if hasattr(test, "user"): # when the class-level attr applied. all test runs as 'user' From 95e1f6324f75f873e277b27e6c449d3ae197f6c6 Mon Sep 17 00:00:00 2001 From: Sanjay Tripathi Date: Mon, 22 Jul 2013 14:32:25 +0530 Subject: [PATCH 32/74] CLOUDSTACK-3695: test_add_user_to_project failed with missing attribute "email". Signed-off-by: Prasanna Santhanam --- test/integration/component/test_project_configs.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/integration/component/test_project_configs.py b/test/integration/component/test_project_configs.py index 641649702e1..a9654c82f57 100644 --- a/test/integration/component/test_project_configs.py +++ b/test/integration/component/test_project_configs.py @@ -537,7 +537,7 @@ class TestProjectInviteRequired(cloudstackTestCase): project.addAccount( self.apiclient, self.user.name, - self.user.email + self.user.user[0].email ) # listProjectAccount to verify the user is added to project or not @@ -690,7 +690,7 @@ class TestProjectInviteRequiredTrue(cloudstackTestCase): project.addAccount( self.apiclient, self.user.name, - self.user.email + self.user.user[0].email ) # listProjectAccount to verify the user is added to project or not @@ -859,7 +859,7 @@ class TestProjectInviteTimeout(cloudstackTestCase): project.addAccount( self.apiclient, self.user.name, - self.user.email + self.user.user[0].email ) # listProjectAccount to verify the user is added to project or not From 18fbbcfc5a3bea98576cc819a37b00b227616cae Mon Sep 17 00:00:00 2001 From: Girish Shilamkar Date: Mon, 22 Jul 2013 19:13:11 +0530 Subject: [PATCH 33/74] CLOUDSTACK-3610: Fix regression test "test_accounts.TestUserLogin" Now password is sent as clear text as per CLOUDSTACK-1734 So changed marvin to handle this. Plus domainid was not passed in the testcase and marvin used "domainid" instead of "domainId" as a parameter. Fixed these two errors. Signed-off-by: Prasanna Santhanam (cherry picked from commit dba09791fc99c342974d8ca1c69609c04f1a5512) --- test/integration/component/test_accounts.py | 5 ++--- tools/marvin/marvin/integration/lib/base.py | 12 +++--------- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/test/integration/component/test_accounts.py b/test/integration/component/test_accounts.py index b5861766f5e..3c284bd0fcd 100644 --- a/test/integration/component/test_accounts.py +++ b/test/integration/component/test_accounts.py @@ -1559,9 +1559,8 @@ class TestUserLogin(cloudstackTestCase): respose = User.login( self.apiclient, username=self.account.name, - password=self.services["account"]["password"] - ) - self.assertEqual(respose, None, "Login response should not be none") + password=self.services["account"]["password"], + domainid=domain.id) self.debug("Login API response: %s" % respose) self.assertNotEqual( diff --git a/tools/marvin/marvin/integration/lib/base.py b/tools/marvin/marvin/integration/lib/base.py index 00dc506f1b1..6e49ae5e70a 100755 --- a/tools/marvin/marvin/integration/lib/base.py +++ b/tools/marvin/marvin/integration/lib/base.py @@ -148,10 +148,7 @@ class User: if "userUUID" in services: cmd.userid = "-".join([services["userUUID"],random_gen()]) - # Password Encoding - mdf = hashlib.md5() - mdf.update(services["password"]) - cmd.password = mdf.hexdigest() + cmd.password = services["password"] cmd.username = "-".join([services["username"], random_gen()]) user = apiclient.createUser(cmd) @@ -201,14 +198,11 @@ class User: cmd = login.loginCmd() cmd.username = username - # MD5 hashcoded password - mdf = hashlib.md5() - mdf.update(password) - cmd.password = mdf.hexdigest() + cmd.password = password if domain: cmd.domain = domain if domainid: - cmd.domainid = domainid + cmd.domainId = domainid return apiclient.login(cmd) From d0422904d741c4b533a94a46194991574cbd91ae Mon Sep 17 00:00:00 2001 From: Alena Prokharchyk Date: Mon, 22 Jul 2013 10:24:22 -0700 Subject: [PATCH 34/74] CLOUDSTACK-3711: return descriptive error message to the regular user when his resource limit has exceed. No harm in returning this info as the user aware of the resource limits/number of resources available for allocation, for his account Conflicts: server/src/com/cloud/api/ApiServer.java --- server/src/com/cloud/api/ApiServer.java | 38 +++++++------------------ 1 file changed, 11 insertions(+), 27 deletions(-) diff --git a/server/src/com/cloud/api/ApiServer.java b/server/src/com/cloud/api/ApiServer.java index 57a4eaf036a..08af964b6ba 100755 --- a/server/src/com/cloud/api/ApiServer.java +++ b/server/src/com/cloud/api/ApiServer.java @@ -385,16 +385,13 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer } } } - } - catch (InvalidParameterValueException ex){ + } catch (InvalidParameterValueException ex){ s_logger.info(ex.getMessage()); throw new ServerApiException(ApiErrorCode.PARAM_ERROR, ex.getMessage(), ex); - } - catch (IllegalArgumentException ex){ + } catch (IllegalArgumentException ex){ s_logger.info(ex.getMessage()); throw new ServerApiException(ApiErrorCode.PARAM_ERROR, ex.getMessage(), ex); - } - catch (PermissionDeniedException ex){ + } catch (PermissionDeniedException ex){ ArrayList idList = ex.getIdProxyList(); if (idList != null) { StringBuffer buf = new StringBuffer(); @@ -409,31 +406,21 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer s_logger.info("PermissionDenied: " + ex.getMessage()); } throw new ServerApiException(ApiErrorCode.ACCOUNT_ERROR, ex.getMessage(), ex); - } - catch (AccountLimitException ex){ + } catch (AccountLimitException ex){ s_logger.info(ex.getMessage()); throw new ServerApiException(ApiErrorCode.ACCOUNT_RESOURCE_LIMIT_ERROR, ex.getMessage(), ex); - } - catch (InsufficientCapacityException ex){ + } catch (InsufficientCapacityException ex){ s_logger.info(ex.getMessage()); String errorMsg = ex.getMessage(); if (CallContext.current().getCallingAccount().getType() != Account.ACCOUNT_TYPE_ADMIN){ // hide internal details to non-admin user for security reason errorMsg = BaseCmd.USER_ERROR_MESSAGE; - } throw new ServerApiException(ApiErrorCode.INSUFFICIENT_CAPACITY_ERROR, errorMsg, ex); - } - catch (ResourceAllocationException ex){ + } catch (ResourceAllocationException ex){ s_logger.info(ex.getMessage()); - String errorMsg = ex.getMessage(); - if (CallContext.current().getCallingAccount().getType() != Account.ACCOUNT_TYPE_ADMIN){ - // hide internal details to non-admin user for security reason - errorMsg = BaseCmd.USER_ERROR_MESSAGE; - } - throw new ServerApiException(ApiErrorCode.RESOURCE_ALLOCATION_ERROR, errorMsg, ex); - } - catch (ResourceUnavailableException ex){ + throw new ServerApiException(ApiErrorCode.RESOURCE_ALLOCATION_ERROR, ex.getMessage(), ex); + } catch (ResourceUnavailableException ex){ s_logger.info(ex.getMessage()); String errorMsg = ex.getMessage(); if (CallContext.current().getCallingAccount().getType() != Account.ACCOUNT_TYPE_ADMIN){ @@ -441,16 +428,13 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer errorMsg = BaseCmd.USER_ERROR_MESSAGE; } throw new ServerApiException(ApiErrorCode.RESOURCE_UNAVAILABLE_ERROR, errorMsg, ex); - } - catch (AsyncCommandQueued ex){ + } catch (AsyncCommandQueued ex){ s_logger.error("unhandled exception executing api command: " + ((command == null) ? "null" : command[0]), ex); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Internal server error, unable to execute request."); - } - catch (ServerApiException ex){ + } catch (ServerApiException ex){ s_logger.info(ex.getDescription()); throw ex; - } - catch (Exception ex){ + } catch (Exception ex){ s_logger.error("unhandled exception executing api command: " + ((command == null) ? "null" : command[0]), ex); String errorMsg = ex.getMessage(); if (CallContext.current().getCallingAccount().getType() != Account.ACCOUNT_TYPE_ADMIN){ From 4aa9e0a69696b821303b30cc6da2669e01529285 Mon Sep 17 00:00:00 2001 From: Brian Federle Date: Mon, 22 Jul 2013 11:19:13 -0700 Subject: [PATCH 35/74] CLOUDSTACK-2162: Fix missing provider field on secondary storage step --- ui/scripts/ui-custom/installWizard.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/ui/scripts/ui-custom/installWizard.js b/ui/scripts/ui-custom/installWizard.js index 99db57e0cd2..f7ed074e774 100644 --- a/ui/scripts/ui-custom/installWizard.js +++ b/ui/scripts/ui-custom/installWizard.js @@ -763,6 +763,16 @@ required: true } }, + provider: { + label: 'label.provider', + select: function(args) { + args.response.success({ + data: [ + { id: 'NFS', description: 'NFS' } + ] + }); + } + }, path: { label: 'label.path', validation: { From 7928963d16430d2b4aed5a502a1d9b3e57412e77 Mon Sep 17 00:00:00 2001 From: Alex Huang Date: Sat, 20 Jul 2013 10:10:30 -0700 Subject: [PATCH 36/74] Changed start to use uuid instead of generic vm start --- .../cloud/entity/api/VMEntityManagerImpl.java | 17 +- .../lb/ElasticLoadBalancerManagerImpl.java | 7 +- .../lb/InternalLoadBalancerVMManagerImpl.java | 17 +- .../InternalLBVMServiceTest.java | 13 -- .../consoleproxy/ConsoleProxyManagerImpl.java | 13 +- .../cloud/ha/HighAvailabilityManagerImpl.java | 126 ++++++++------- .../VirtualNetworkApplianceManagerImpl.java | 27 ++-- .../storage/StoragePoolAutomationImpl.java | 145 ++++++------------ .../SecondaryStorageManagerImpl.java | 3 +- .../src/com/cloud/vm/SystemVmLoadScanner.java | 7 +- .../src/com/cloud/vm/UserVmManagerImpl.java | 5 +- .../com/cloud/vm/VirtualMachineManager.java | 10 +- .../cloud/vm/VirtualMachineManagerImpl.java | 59 ++++--- .../vm/snapshot/VMSnapshotManagerImpl.java | 33 ++-- .../test/com/cloud/vm/UserVmManagerTest.java | 3 - 15 files changed, 218 insertions(+), 267 deletions(-) diff --git a/engine/orchestration/src/org/apache/cloudstack/engine/cloud/entity/api/VMEntityManagerImpl.java b/engine/orchestration/src/org/apache/cloudstack/engine/cloud/entity/api/VMEntityManagerImpl.java index 6dd5844cbc9..ee5ae2df804 100755 --- a/engine/orchestration/src/org/apache/cloudstack/engine/cloud/entity/api/VMEntityManagerImpl.java +++ b/engine/orchestration/src/org/apache/cloudstack/engine/cloud/entity/api/VMEntityManagerImpl.java @@ -22,6 +22,9 @@ import java.util.UUID; import javax.inject.Inject; +import org.apache.log4j.Logger; +import org.springframework.stereotype.Component; + import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao; import org.apache.cloudstack.engine.cloud.entity.api.db.VMEntityVO; import org.apache.cloudstack.engine.cloud.entity.api.db.VMReservationVO; @@ -29,16 +32,14 @@ import org.apache.cloudstack.engine.cloud.entity.api.db.dao.VMEntityDao; import org.apache.cloudstack.engine.cloud.entity.api.db.dao.VMReservationDao; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; -import org.apache.log4j.Logger; -import org.springframework.stereotype.Component; import com.cloud.dc.DataCenter; import com.cloud.deploy.DataCenterDeployment; import com.cloud.deploy.DeployDestination; import com.cloud.deploy.DeploymentPlan; import com.cloud.deploy.DeploymentPlanner; -import com.cloud.deploy.DeploymentPlanningManager; import com.cloud.deploy.DeploymentPlanner.ExcludeList; +import com.cloud.deploy.DeploymentPlanningManager; import com.cloud.exception.AffinityConflictException; import com.cloud.exception.AgentUnavailableException; import com.cloud.exception.ConcurrentOperationException; @@ -156,7 +157,7 @@ public class VMEntityManagerImpl implements VMEntityManager { List vols = _volsDao.findReadyRootVolumesByInstance(vm.getId()); if(!vols.isEmpty()){ VolumeVO vol = vols.get(0); - StoragePool pool = (StoragePool)this.dataStoreMgr.getPrimaryDataStore(vol.getPoolId()); + StoragePool pool = (StoragePool)dataStoreMgr.getPrimaryDataStore(vol.getPoolId()); if (!pool.isInMaintenance()) { long rootVolDcId = pool.getDataCenterId(); @@ -224,8 +225,7 @@ public class VMEntityManagerImpl implements VMEntityManager { DataCenterDeployment reservedPlan = new DataCenterDeployment(vm.getDataCenterId(), vmReservation.getPodId(), vmReservation.getClusterId(), vmReservation.getHostId(), null, null); try { - VMInstanceVO vmDeployed = _itMgr.start(vm, params, _userDao.findById(new Long(caller)), - _accountDao.findById(vm.getAccountId()), reservedPlan); + _itMgr.start(vm.getUuid(), params, reservedPlan); } catch (Exception ex) { // Retry the deployment without using the reservation plan DataCenterDeployment plan = new DataCenterDeployment(0, null, null, null, null, null); @@ -234,12 +234,11 @@ public class VMEntityManagerImpl implements VMEntityManager { plan.setAvoids(reservedPlan.getAvoids()); } - _itMgr.start(vm, params, _userDao.findById(new Long(caller)), _accountDao.findById(vm.getAccountId()), - plan); + _itMgr.start(vm.getUuid(), params, plan); } } else { // no reservation found. Let VirtualMachineManager retry - _itMgr.start(vm, params, _userDao.findById(new Long(caller)), _accountDao.findById(vm.getAccountId()), null); + _itMgr.start(vm.getUuid(), params, null); } } diff --git a/plugins/network-elements/elastic-loadbalancer/src/com/cloud/network/lb/ElasticLoadBalancerManagerImpl.java b/plugins/network-elements/elastic-loadbalancer/src/com/cloud/network/lb/ElasticLoadBalancerManagerImpl.java index 601b0343c22..24ec87a27b6 100644 --- a/plugins/network-elements/elastic-loadbalancer/src/com/cloud/network/lb/ElasticLoadBalancerManagerImpl.java +++ b/plugins/network-elements/elastic-loadbalancer/src/com/cloud/network/lb/ElasticLoadBalancerManagerImpl.java @@ -538,11 +538,8 @@ ElasticLoadBalancerManager, VirtualMachineGuru { private DomainRouterVO start(DomainRouterVO elbVm, User user, Account caller, Map params) throws StorageUnavailableException, InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException { s_logger.debug("Starting ELB VM " + elbVm); - if (_itMgr.start(elbVm, params, user, caller) != null) { - return _routerDao.findById(elbVm.getId()); - } else { - return null; - } + _itMgr.start(elbVm.getUuid(), params); + return _routerDao.findById(elbVm.getId()); } private DomainRouterVO stop(DomainRouterVO elbVm, boolean forced, User user, Account caller) throws ConcurrentOperationException, ResourceUnavailableException { diff --git a/plugins/network-elements/internal-loadbalancer/src/org/apache/cloudstack/network/lb/InternalLoadBalancerVMManagerImpl.java b/plugins/network-elements/internal-loadbalancer/src/org/apache/cloudstack/network/lb/InternalLoadBalancerVMManagerImpl.java index 06d3f708ac1..90ff9bc0b49 100644 --- a/plugins/network-elements/internal-loadbalancer/src/org/apache/cloudstack/network/lb/InternalLoadBalancerVMManagerImpl.java +++ b/plugins/network-elements/internal-loadbalancer/src/org/apache/cloudstack/network/lb/InternalLoadBalancerVMManagerImpl.java @@ -467,7 +467,7 @@ public class InternalLoadBalancerVMManagerImpl extends ManagerBase implements maxconn = offering.getConcurrentConnections().toString(); } LoadBalancerConfigCommand cmd = new LoadBalancerConfigCommand(lbs, guestNic.getIp4Address(), - guestNic.getIp4Address(), internalLbVm.getPrivateIpAddress(), + guestNic.getIp4Address(), internalLbVm.getPrivateIpAddress(), _itMgr.toNicTO(guestNicProfile, internalLbVm.getHypervisorType()), internalLbVm.getVpcId(), maxconn); cmd.lbStatsVisibility = _configDao.getValue(Config.NetworkLBHaproxyStatsVisbility.key()); @@ -815,16 +815,13 @@ public class InternalLoadBalancerVMManagerImpl extends ManagerBase implements throws StorageUnavailableException, InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException { s_logger.debug("Starting Internal LB VM " + internalLbVm); - if (_itMgr.start(internalLbVm, params, _accountMgr.getUserIncludingRemoved(callerUserId), caller, null) != null) { - if (internalLbVm.isStopPending()) { - s_logger.info("Clear the stop pending flag of Internal LB VM " + internalLbVm.getHostName() + " after start router successfully!"); - internalLbVm.setStopPending(false); - internalLbVm = _internalLbVmDao.persist(internalLbVm); - } - return _internalLbVmDao.findById(internalLbVm.getId()); - } else { - return null; + _itMgr.start(internalLbVm.getUuid(), params, null); + if (internalLbVm.isStopPending()) { + s_logger.info("Clear the stop pending flag of Internal LB VM " + internalLbVm.getHostName() + " after start router successfully!"); + internalLbVm.setStopPending(false); + internalLbVm = _internalLbVmDao.persist(internalLbVm); } + return _internalLbVmDao.findById(internalLbVm.getId()); } diff --git a/plugins/network-elements/internal-loadbalancer/test/org/apache/cloudstack/internallbvmmgr/InternalLBVMServiceTest.java b/plugins/network-elements/internal-loadbalancer/test/org/apache/cloudstack/internallbvmmgr/InternalLBVMServiceTest.java index 70dafa307e4..a74f6b02c02 100644 --- a/plugins/network-elements/internal-loadbalancer/test/org/apache/cloudstack/internallbvmmgr/InternalLBVMServiceTest.java +++ b/plugins/network-elements/internal-loadbalancer/test/org/apache/cloudstack/internallbvmmgr/InternalLBVMServiceTest.java @@ -17,7 +17,6 @@ package org.apache.cloudstack.internallbvmmgr; import java.lang.reflect.Field; -import java.util.Map; import javax.inject.Inject; @@ -34,7 +33,6 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.network.lb.InternalLoadBalancerVMService; -import com.cloud.deploy.DeploymentPlan; import com.cloud.exception.ConcurrentOperationException; import com.cloud.exception.InsufficientCapacityException; import com.cloud.exception.InvalidParameterValueException; @@ -113,17 +111,6 @@ public class InternalLBVMServiceTest extends TestCase { Mockito.when(_domainRouterDao.findById(nonExistingVmId)).thenReturn(null); Mockito.when(_domainRouterDao.findById(nonInternalLbVmId)).thenReturn(nonInternalLbVm); - try { - Mockito.when(_itMgr.start(Mockito.any(DomainRouterVO.class), - Mockito.any(Map.class), Mockito.any(User.class), Mockito.any(Account.class), Mockito.any(DeploymentPlan.class))).thenReturn(validVm); - } catch (InsufficientCapacityException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (ResourceUnavailableException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - try { Mockito.when(_itMgr.advanceStop(Mockito.any(DomainRouterVO.class), Mockito.any(Boolean.class), Mockito.any(User.class), Mockito.any(Account.class))).thenReturn(true); } catch (ResourceUnavailableException e) { diff --git a/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java b/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java index 30fbb4806f2..5d6719d720c 100755 --- a/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java +++ b/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java @@ -65,6 +65,7 @@ import com.cloud.deploy.DataCenterDeployment; import com.cloud.deploy.DeployDestination; import com.cloud.exception.ConcurrentOperationException; import com.cloud.exception.InsufficientCapacityException; +import com.cloud.exception.OperationTimedoutException; import com.cloud.exception.ResourceUnavailableException; import com.cloud.exception.StorageUnavailableException; import com.cloud.host.Host; @@ -110,7 +111,6 @@ import com.cloud.storage.dao.VMTemplateDao; import com.cloud.template.TemplateManager; import com.cloud.user.Account; import com.cloud.user.AccountManager; -import com.cloud.user.User; import com.cloud.utils.DateUtil; import com.cloud.utils.NumbersUtil; import com.cloud.utils.Pair; @@ -540,8 +540,6 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy public ConsoleProxyVO startProxy(long proxyVmId) { try { ConsoleProxyVO proxy = _consoleProxyDao.findById(proxyVmId); - Account systemAcct = _accountMgr.getSystemAccount(); - User systemUser = _accountMgr.getSystemUser(); if (proxy.getState() == VirtualMachine.State.Running) { return proxy; } @@ -552,7 +550,8 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy } if (proxy.getState() == VirtualMachine.State.Stopped) { - return _itMgr.start(proxy, null, systemUser, systemAcct); + _itMgr.advanceStart(proxy.getUuid(), null); + proxy = _consoleProxyDao.findById(proxy.getId()); } // For VMs that are in Stopping, Starting, Migrating state, let client to wait by returning null @@ -574,6 +573,12 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy } catch (CloudRuntimeException e) { s_logger.warn("Runtime Exception while trying to start console proxy", e); return null; + } catch (ConcurrentOperationException e) { + s_logger.warn("Runtime Exception while trying to start console proxy", e); + return null; + } catch (OperationTimedoutException e) { + s_logger.warn("Runtime Exception while trying to start console proxy", e); + return null; } } diff --git a/server/src/com/cloud/ha/HighAvailabilityManagerImpl.java b/server/src/com/cloud/ha/HighAvailabilityManagerImpl.java index 25c5a043b6c..fcc4792aac1 100755 --- a/server/src/com/cloud/ha/HighAvailabilityManagerImpl.java +++ b/server/src/com/cloud/ha/HighAvailabilityManagerImpl.java @@ -32,6 +32,8 @@ import javax.naming.ConfigurationException; import org.apache.log4j.Logger; import org.apache.log4j.NDC; +import org.apache.cloudstack.context.ServerContexts; + import com.cloud.agent.AgentManager; import com.cloud.alert.AlertManager; import com.cloud.cluster.ClusterManagerListener; @@ -294,7 +296,7 @@ public class HighAvailabilityManagerImpl extends ManagerBase implements HighAvai } catch (ConcurrentOperationException e) { assert false : "How do we hit this when force is true?"; throw new CloudRuntimeException("Caught exception even though it should be handled.", e); - } + } return; } @@ -338,7 +340,7 @@ public class HighAvailabilityManagerImpl extends ManagerBase implements HighAvai } catch (ConcurrentOperationException e) { assert false : "How do we hit this when force is true?"; throw new CloudRuntimeException("Caught exception even though it should be handled.", e); - } + } } List items = _haDao.findPreviousHA(vm.getId()); @@ -513,7 +515,7 @@ public class HighAvailabilityManagerImpl extends ManagerBase implements HighAvai return null; // VM doesn't require HA } - if (!this.volumeMgr.canVmRestartOnAnotherServer(vm.getId())) { + if (!volumeMgr.canVmRestartOnAnotherServer(vm.getId())) { if (s_logger.isDebugEnabled()) { s_logger.debug("VM can not restart on another server."); } @@ -530,9 +532,10 @@ public class HighAvailabilityManagerImpl extends ManagerBase implements HighAvai if (_haTag != null) { params.put(VirtualMachineProfile.Param.HaTag, _haTag); } - VMInstanceVO started = _itMgr.advanceStart(vm, params, _accountMgr.getSystemUser(), _accountMgr.getSystemAccount()); - - if (started != null) { + _itMgr.advanceStart(vm.getUuid(), params); + + VMInstanceVO started = _instanceDao.findById(vm.getId()); + if (started != null && started.getState() == VirtualMachine.State.Running) { s_logger.info("VM is now restarted: " + vmId + " on " + started.getHostId()); return null; } @@ -801,66 +804,71 @@ public class HighAvailabilityManagerImpl extends ManagerBase implements HighAvai @Override public void run() { - s_logger.info("Starting work"); - while (!_stopped) { - HaWorkVO work = null; - try { - s_logger.trace("Checking the database"); - work = _haDao.take(_serverId); - if (work == null) { + ServerContexts.registerSystemContext(); + try { + s_logger.info("Starting work"); + while (!_stopped) { + HaWorkVO work = null; try { - synchronized (this) { - wait(_timeToSleep); + s_logger.trace("Checking the database"); + work = _haDao.take(_serverId); + if (work == null) { + try { + synchronized (this) { + wait(_timeToSleep); + } + continue; + } catch (final InterruptedException e) { + s_logger.info("Interrupted"); + continue; } - continue; - } catch (final InterruptedException e) { - s_logger.info("Interrupted"); - continue; - } - } - - NDC.push("work-" + work.getId()); - s_logger.info("Processing " + work); - - try { - final WorkType wt = work.getWorkType(); - Long nextTime = null; - if (wt == WorkType.Migration) { - nextTime = migrate(work); - } else if (wt == WorkType.HA) { - nextTime = restart(work); - } else if (wt == WorkType.Stop || wt == WorkType.CheckStop || wt == WorkType.ForceStop) { - nextTime = stopVM(work); - } else if (wt == WorkType.Destroy) { - nextTime = destroyVM(work); - } else { - assert false : "How did we get here with " + wt.toString(); - continue; } - if (nextTime == null) { - s_logger.info("Completed " + work); - work.setStep(Step.Done); - } else { - s_logger.info("Rescheduling " + work + " to try again at " + new Date(nextTime << 10)); - work.setTimeToTry(nextTime); - work.setServerId(null); - work.setDateTaken(null); + NDC.push("work-" + work.getId()); + s_logger.info("Processing " + work); + + try { + final WorkType wt = work.getWorkType(); + Long nextTime = null; + if (wt == WorkType.Migration) { + nextTime = migrate(work); + } else if (wt == WorkType.HA) { + nextTime = restart(work); + } else if (wt == WorkType.Stop || wt == WorkType.CheckStop || wt == WorkType.ForceStop) { + nextTime = stopVM(work); + } else if (wt == WorkType.Destroy) { + nextTime = destroyVM(work); + } else { + assert false : "How did we get here with " + wt.toString(); + continue; + } + + if (nextTime == null) { + s_logger.info("Completed " + work); + work.setStep(Step.Done); + } else { + s_logger.info("Rescheduling " + work + " to try again at " + new Date(nextTime << 10)); + work.setTimeToTry(nextTime); + work.setServerId(null); + work.setDateTaken(null); + } + } catch (Exception e) { + s_logger.error("Terminating " + work, e); + work.setStep(Step.Error); + } + _haDao.update(work.getId(), work); + } catch (final Throwable th) { + s_logger.error("Caught this throwable, ", th); + } finally { + if (work != null) { + NDC.pop(); + } } - } catch (Exception e) { - s_logger.error("Terminating " + work, e); - work.setStep(Step.Error); } - _haDao.update(work.getId(), work); - } catch (final Throwable th) { - s_logger.error("Caught this throwable, ", th); - } finally { - if (work != null) { - NDC.pop(); - } - } + s_logger.info("Time to go home!"); + } finally { + ServerContexts.unregisterSystemContext(); } - s_logger.info("Time to go home!"); } public synchronized void wakup() { diff --git a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java index 6c0f7a1d4bc..d05d8e88bea 100755 --- a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java +++ b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java @@ -2735,22 +2735,19 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V throws StorageUnavailableException, InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException { s_logger.debug("Starting router " + router); - if (_itMgr.start(router, params, user, caller, planToDeploy) != null) { - if (router.isStopPending()) { - s_logger.info("Clear the stop pending flag of router " + router.getHostName() + " after start router successfully!"); - router.setStopPending(false); - router = _routerDao.persist(router); - } - // We don't want the failure of VPN Connection affect the status of router, so we try to make connection - // only after router start successfully - Long vpcId = router.getVpcId(); - if (vpcId != null) { - _s2sVpnMgr.reconnectDisconnectedVpnByVpc(vpcId); - } - return _routerDao.findById(router.getId()); - } else { - return null; + _itMgr.start(router.getUuid(), params, planToDeploy); + if (router.isStopPending()) { + s_logger.info("Clear the stop pending flag of router " + router.getHostName() + " after start router successfully!"); + router.setStopPending(false); + router = _routerDao.persist(router); } + // We don't want the failure of VPN Connection affect the status of router, so we try to make connection + // only after router start successfully + Long vpcId = router.getVpcId(); + if (vpcId != null) { + _s2sVpnMgr.reconnectDisconnectedVpnByVpc(vpcId); + } + return _routerDao.findById(router.getId()); } @Override diff --git a/server/src/com/cloud/storage/StoragePoolAutomationImpl.java b/server/src/com/cloud/storage/StoragePoolAutomationImpl.java index 5c971837ab1..7b931035fba 100644 --- a/server/src/com/cloud/storage/StoragePoolAutomationImpl.java +++ b/server/src/com/cloud/storage/StoragePoolAutomationImpl.java @@ -23,22 +23,22 @@ import java.util.List; import javax.inject.Inject; -import org.apache.cloudstack.context.CallContext; -import org.apache.cloudstack.engine.subsystem.api.storage.*; -import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; -import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; - import org.apache.log4j.Logger; import org.springframework.stereotype.Component; +import org.apache.cloudstack.context.CallContext; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreProviderManager; +import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; +import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; + import com.cloud.agent.AgentManager; import com.cloud.agent.api.Answer; import com.cloud.agent.api.ModifyStoragePoolCommand; import com.cloud.alert.AlertManager; -import com.cloud.host.Host; import com.cloud.host.HostVO; import com.cloud.host.Status; -import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.resource.ResourceManager; import com.cloud.server.ManagementServer; import com.cloud.storage.dao.StoragePoolHostDao; @@ -48,7 +48,6 @@ import com.cloud.user.Account; import com.cloud.user.User; import com.cloud.user.dao.UserDao; import com.cloud.utils.exception.CloudRuntimeException; -import com.cloud.utils.exception.ExecutionException; import com.cloud.vm.ConsoleProxyVO; import com.cloud.vm.DomainRouterVO; import com.cloud.vm.SecondaryStorageVmVO; @@ -100,18 +99,19 @@ public class StoragePoolAutomationImpl implements StoragePoolAutomation { VMInstanceDao vmDao; @Inject ManagementServer server; - @Inject DataStoreProviderManager providerMgr; + @Inject + DataStoreProviderManager providerMgr; @Override public boolean maintain(DataStore store) { Long userId = CallContext.current().getCallingUserId(); User user = _userDao.findById(userId); Account account = CallContext.current().getCallingAccount(); - StoragePoolVO pool = this.primaryDataStoreDao.findById(store.getId()); + StoragePoolVO pool = primaryDataStoreDao.findById(store.getId()); try { List spes = null; // Handling Zone and Cluster wide storage scopes. - // if the storage is ZONE wide then we pass podid and cluster id as null as they will be empty for ZWPS + // if the storage is ZONE wide then we pass podid and cluster id as null as they will be empty for ZWPS if (pool.getScope() == ScopeType.ZONE) { spes = primaryDataStoreDao.listBy( pool.getDataCenterId(), null, @@ -128,14 +128,14 @@ public class StoragePoolAutomationImpl implements StoragePoolAutomation { + " is already in PrepareForMaintenance mode "); } } - StoragePool storagePool = (StoragePool) store; + StoragePool storagePool = (StoragePool)store; //Handeling the Zone wide and cluster wide primay storage List hosts = new ArrayList(); // if the storage scope is ZONE wide, then get all the hosts for which hypervisor ZWSP created to send Modifystoragepoolcommand //TODO: if it's zone wide, this code will list a lot of hosts in the zone, which may cause performance/OOM issue. if (pool.getScope().equals(ScopeType.ZONE)) { - hosts = _resourceMgr.listAllUpAndEnabledHostsInOneZoneByHypervisor(pool.getHypervisor() , pool.getDataCenterId()); + hosts = _resourceMgr.listAllUpAndEnabledHostsInOneZoneByHypervisor(pool.getHypervisor(), pool.getDataCenterId()); } else { hosts = _resourceMgr.listHostsInClusterByStatus( pool.getClusterId(), Status.Up); @@ -159,7 +159,7 @@ public class StoragePoolAutomationImpl implements StoragePoolAutomation { if (s_logger.isDebugEnabled()) { s_logger.debug("ModifyStoragePool false failed due to " + ((answer == null) ? "answer null" : answer - .getDetails())); + .getDetails())); } } else { if (s_logger.isDebugEnabled()) { @@ -179,7 +179,7 @@ public class StoragePoolAutomationImpl implements StoragePoolAutomation { } // 2. Get a list of all the ROOT volumes within this storage pool - List allVolumes = this.volumeDao.findByPoolId(pool + List allVolumes = volumeDao.findByPoolId(pool .getId()); // 3. Enqueue to the work queue @@ -250,22 +250,15 @@ public class StoragePoolAutomationImpl implements StoragePoolAutomation { if (restart) { - if (this.vmMgr.advanceStart(consoleProxy, null, user, - account) == null) { - String errorMsg = "There was an error starting the console proxy id: " - + vmInstance.getId() - + " on another storage pool, cannot enable primary storage maintenance"; - s_logger.warn(errorMsg); - } else { - // update work status - work.setStartedAfterMaintenance(true); - _storagePoolWorkDao.update(work.getId(), work); - } + vmMgr.advanceStart(consoleProxy.getUuid(), null); + // update work status + work.setStartedAfterMaintenance(true); + _storagePoolWorkDao.update(work.getId(), work); } } // if the instance is of type uservm, call the user vm manager - if (vmInstance.getType().equals(VirtualMachine.Type.User)) { + if (vmInstance.getType() == VirtualMachine.Type.User) { UserVmVO userVm = userVmDao.findById(vmInstance.getId()); if (!vmMgr.advanceStop(userVm, true, user, account)) { String errorMsg = "There was an error stopping the user vm id: " @@ -299,16 +292,10 @@ public class StoragePoolAutomationImpl implements StoragePoolAutomation { } if (restart) { - if (vmMgr.advanceStart(secStrgVm, null, user, account) == null) { - String errorMsg = "There was an error starting the ssvm id: " - + vmInstance.getId() - + " on another storage pool, cannot enable primary storage maintenance"; - s_logger.warn(errorMsg); - } else { - // update work status - work.setStartedAfterMaintenance(true); - _storagePoolWorkDao.update(work.getId(), work); - } + vmMgr.advanceStart(secStrgVm.getUuid(), null); + // update work status + work.setStartedAfterMaintenance(true); + _storagePoolWorkDao.update(work.getId(), work); } } @@ -330,24 +317,18 @@ public class StoragePoolAutomationImpl implements StoragePoolAutomation { } if (restart) { - if (vmMgr.advanceStart(domR, null, user, account) == null) { - String errorMsg = "There was an error starting the domain router id: " - + vmInstance.getId() - + " on another storage pool, cannot enable primary storage maintenance"; - s_logger.warn(errorMsg); - } else { - // update work status - work.setStartedAfterMaintenance(true); - _storagePoolWorkDao.update(work.getId(), work); - } + vmMgr.advanceStart(domR.getUuid(), null); + // update work status + work.setStartedAfterMaintenance(true); + _storagePoolWorkDao.update(work.getId(), work); } } } - } catch(Exception e) { + } catch (Exception e) { s_logger.error( "Exception in enabling primary storage maintenance:", e); pool.setStatus(StoragePoolStatus.ErrorInMaintenance); - this.primaryDataStoreDao.update(pool.getId(), pool); + primaryDataStoreDao.update(pool.getId(), pool); throw new CloudRuntimeException(e.getMessage()); } return true; @@ -359,7 +340,7 @@ public class StoragePoolAutomationImpl implements StoragePoolAutomation { Long userId = CallContext.current().getCallingUserId(); User user = _userDao.findById(userId); Account account = CallContext.current().getCallingAccount(); - StoragePoolVO poolVO = this.primaryDataStoreDao + StoragePoolVO poolVO = primaryDataStoreDao .findById(store.getId()); StoragePool pool = (StoragePool)store; @@ -370,7 +351,7 @@ public class StoragePoolAutomationImpl implements StoragePoolAutomation { hosts = _resourceMgr.listAllUpAndEnabledHostsInOneZoneByHypervisor(poolVO.getHypervisor(), pool.getDataCenterId()); } else { hosts = _resourceMgr.listHostsInClusterByStatus( - pool.getClusterId(), Status.Up); + pool.getClusterId(), Status.Up); } if (hosts == null || hosts.size() == 0) { @@ -385,7 +366,7 @@ public class StoragePoolAutomationImpl implements StoragePoolAutomation { if (s_logger.isDebugEnabled()) { s_logger.debug("ModifyStoragePool add failed due to " + ((answer == null) ? "answer null" : answer - .getDetails())); + .getDetails())); } } else { if (s_logger.isDebugEnabled()) { @@ -414,17 +395,10 @@ public class StoragePoolAutomationImpl implements StoragePoolAutomation { ConsoleProxyVO consoleProxy = _consoleProxyDao .findById(vmInstance.getId()); - if (vmMgr.advanceStart(consoleProxy, null, user, account) == null) { - String msg = "There was an error starting the console proxy id: " - + vmInstance.getId() - + " on storage pool, cannot complete primary storage maintenance"; - s_logger.warn(msg); - throw new ExecutionException(msg); - } else { - // update work queue - work.setStartedAfterMaintenance(true); - _storagePoolWorkDao.update(work.getId(), work); - } + vmMgr.advanceStart(consoleProxy.getUuid(), null); + // update work queue + work.setStartedAfterMaintenance(true); + _storagePoolWorkDao.update(work.getId(), work); } // if the instance is of type ssvm, call the ssvm manager @@ -432,52 +406,29 @@ public class StoragePoolAutomationImpl implements StoragePoolAutomation { VirtualMachine.Type.SecondaryStorageVm)) { SecondaryStorageVmVO ssVm = _secStrgDao.findById(vmInstance .getId()); - if (vmMgr.advanceStart(ssVm, null, user, account) == null) { - String msg = "There was an error starting the ssvm id: " - + vmInstance.getId() - + " on storage pool, cannot complete primary storage maintenance"; - s_logger.warn(msg); - throw new ExecutionException(msg); - } else { - // update work queue - work.setStartedAfterMaintenance(true); - _storagePoolWorkDao.update(work.getId(), work); - } + vmMgr.advanceStart(ssVm.getUuid(), null); + // update work queue + work.setStartedAfterMaintenance(true); + _storagePoolWorkDao.update(work.getId(), work); } // if the instance is of type ssvm, call the ssvm manager if (vmInstance.getType().equals( VirtualMachine.Type.DomainRouter)) { DomainRouterVO domR = _domrDao.findById(vmInstance.getId()); - if (vmMgr.advanceStart(domR, null, user, account) == null) { - String msg = "There was an error starting the domR id: " - + vmInstance.getId() - + " on storage pool, cannot complete primary storage maintenance"; - s_logger.warn(msg); - throw new ExecutionException(msg); - } else { - // update work queue - work.setStartedAfterMaintenance(true); - _storagePoolWorkDao.update(work.getId(), work); - } + vmMgr.advanceStart(domR.getUuid(), null); + // update work queue + work.setStartedAfterMaintenance(true); + _storagePoolWorkDao.update(work.getId(), work); } // if the instance is of type user vm, call the user vm manager if (vmInstance.getType().equals(VirtualMachine.Type.User)) { UserVmVO userVm = userVmDao.findById(vmInstance.getId()); - if (vmMgr.advanceStart(userVm, null, user, account) == null) { - - String msg = "There was an error starting the user vm id: " - + vmInstance.getId() - + " on storage pool, cannot complete primary storage maintenance"; - s_logger.warn(msg); - throw new ExecutionException(msg); - } else { - // update work queue - work.setStartedAfterMaintenance(true); - _storagePoolWorkDao.update(work.getId(), work); - } + vmMgr.advanceStart(userVm.getUuid(), null); // update work queue + work.setStartedAfterMaintenance(true); + _storagePoolWorkDao.update(work.getId(), work); } return true; } catch (Exception e) { diff --git a/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java b/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java index b80892a7641..f7a72190097 100755 --- a/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java +++ b/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java @@ -259,7 +259,8 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar SecondaryStorageVmVO secStorageVm = _secStorageVmDao.findById(secStorageVmId); Account systemAcct = _accountMgr.getSystemAccount(); User systemUser = _accountMgr.getSystemUser(); - return _itMgr.start(secStorageVm, null, systemUser, systemAcct); + _itMgr.advanceStart(secStorageVm.getUuid(), null); + return _secStorageVmDao.findById(secStorageVm.getId()); } catch (StorageUnavailableException e) { s_logger.warn("Exception while trying to start secondary storage vm", e); return null; diff --git a/server/src/com/cloud/vm/SystemVmLoadScanner.java b/server/src/com/cloud/vm/SystemVmLoadScanner.java index 4251b405e1b..3932c3b9641 100644 --- a/server/src/com/cloud/vm/SystemVmLoadScanner.java +++ b/server/src/com/cloud/vm/SystemVmLoadScanner.java @@ -22,10 +22,11 @@ import java.util.concurrent.TimeUnit; import org.apache.log4j.Logger; +import org.apache.cloudstack.context.ServerContexts; + import com.cloud.utils.Pair; import com.cloud.utils.concurrency.NamedThreadFactory; import com.cloud.utils.db.GlobalLock; -import com.cloud.utils.db.Transaction; // // TODO: simple load scanner, to minimize code changes required in console proxy manager and SSVM, we still leave most of work at handler @@ -67,13 +68,13 @@ public class SystemVmLoadScanner { @Override public void run() { - Transaction txn = Transaction.open(Transaction.CLOUD_DB); + ServerContexts.registerSystemContext(); try { reallyRun(); } catch (Throwable e) { s_logger.warn("Unexpected exception " + e.getMessage(), e); } finally { - txn.close(); + ServerContexts.unregisterSystemContext(); } } diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java b/server/src/com/cloud/vm/UserVmManagerImpl.java index adcf4759f8f..f353bb74d74 100755 --- a/server/src/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/com/cloud/vm/UserVmManagerImpl.java @@ -4588,7 +4588,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use if (needRestart) { try { - _itMgr.start(vm, null, user, caller); + _itMgr.start(vm.getUuid(), null); } catch (Exception e) { s_logger.debug("Unable to start VM " + vm.getUuid(), e); CloudRuntimeException ex = new CloudRuntimeException( @@ -4598,8 +4598,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use } } - s_logger.debug("Restore VM " + vmId + " with template " - + template.getUuid() + " done successfully"); + s_logger.debug("Restore VM " + vmId + " with template " + template.getUuid() + " done successfully"); return vm; } diff --git a/server/src/com/cloud/vm/VirtualMachineManager.java b/server/src/com/cloud/vm/VirtualMachineManager.java index bf6af442876..49953b97331 100644 --- a/server/src/com/cloud/vm/VirtualMachineManager.java +++ b/server/src/com/cloud/vm/VirtualMachineManager.java @@ -72,9 +72,9 @@ public interface VirtualMachineManager extends Manager { DeploymentPlan plan, HypervisorType hyperType) throws InsufficientCapacityException; - T start(T vm, Map params, User caller, Account account) throws InsufficientCapacityException, ResourceUnavailableException; + void start(String vmUuid, Map params); - T start(T vm, Map params, User caller, Account account, DeploymentPlan planToDeploy) throws InsufficientCapacityException, ResourceUnavailableException; + void start(String vmUuid, Map params, DeploymentPlan planToDeploy); boolean stop(T vm, User caller, Account account) throws ResourceUnavailableException; @@ -84,9 +84,11 @@ public interface VirtualMachineManager extends Manager { boolean stateTransitTo(VMInstanceVO vm, VirtualMachine.Event e, Long hostId) throws NoTransitionException; - T advanceStart(T vm, Map params, User caller, Account account) throws InsufficientCapacityException, ResourceUnavailableException, ConcurrentOperationException, OperationTimedoutException; + void advanceStart(String vmUuid, Map params) throws InsufficientCapacityException, ResourceUnavailableException, + ConcurrentOperationException, OperationTimedoutException; - T advanceStart(T vm, Map params, User caller, Account account, DeploymentPlan planToDeploy) throws InsufficientCapacityException, ResourceUnavailableException, ConcurrentOperationException, OperationTimedoutException; + void advanceStart(String vmUuid, Map params, DeploymentPlan planToDeploy) throws InsufficientCapacityException, + ResourceUnavailableException, ConcurrentOperationException, OperationTimedoutException; boolean advanceStop(T vm, boolean forced, User caller, Account account) throws ResourceUnavailableException, OperationTimedoutException, ConcurrentOperationException; diff --git a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java index 7a4bf50f128..363bb454e61 100755 --- a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java +++ b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java @@ -39,6 +39,7 @@ import javax.naming.ConfigurationException; import org.apache.log4j.Logger; import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao; +import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; import org.apache.cloudstack.engine.subsystem.api.storage.StoragePoolAllocator; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory; @@ -603,17 +604,20 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac } @Override - public T start(T vm, Map params, User caller, Account account) throws InsufficientCapacityException, ResourceUnavailableException { - return start(vm, params, caller, account, null); + public void start(String vmUuid, Map params) { + start(vmUuid, params, null); } @Override - public T start(T vm, Map params, User caller, Account account, DeploymentPlan planToDeploy) throws InsufficientCapacityException, - ResourceUnavailableException { + public void start(String vmUuid, Map params, DeploymentPlan planToDeploy) { try { - return advanceStart(vm, params, caller, account, planToDeploy); + advanceStart(vmUuid, params, planToDeploy); } catch (ConcurrentOperationException e) { - throw new CloudRuntimeException("Unable to start a VM due to concurrent operation", e); + throw new CloudRuntimeException("Unable to start a VM due to concurrent operation", e).add(VirtualMachine.class, vmUuid); + } catch (InsufficientCapacityException e) { + throw new CloudRuntimeException("Unable to start a VM due to insufficient capacity", e).add(VirtualMachine.class, vmUuid); + } catch (ResourceUnavailableException e) { + throw new CloudRuntimeException("Unable to start a VM due to concurrent operation", e).add(VirtualMachine.class, vmUuid); } } @@ -651,7 +655,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac } @DB - protected Ternary changeToStartState(VirtualMachineGuru vmGuru, T vm, User caller, Account account) + protected Ternary changeToStartState(VirtualMachineGuru vmGuru, VMInstanceVO vm, User caller, Account account) throws ConcurrentOperationException { long vmId = vm.getId(); @@ -659,7 +663,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac int retry = _lockStateRetry; while (retry-- != 0) { Transaction txn = Transaction.currentTxn(); - Ternary result = null; + Ternary result = null; txn.start(); try { Journal journal = new Journal.LogJournal("Creating " + vm, s_logger); @@ -670,7 +674,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac if (s_logger.isDebugEnabled()) { s_logger.debug("Successfully transitioned to start state for " + vm + " reservation id = " + work.getId()); } - result = new Ternary(vmGuru.findById(vmId), context, work); + result = new Ternary(vm, context, work); txn.commit(); return result; } @@ -744,28 +748,33 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac } @Override - public T advanceStart(T vm, Map params, User caller, Account account) throws InsufficientCapacityException, - ConcurrentOperationException, ResourceUnavailableException { - return advanceStart(vm, params, caller, account, null); + public void advanceStart(String vmUuid, Map params) + throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException { + advanceStart(vmUuid, params, null); } @Override - public T advanceStart(T vm, Map params, User caller, Account account, DeploymentPlan planToDeploy) + public void advanceStart(String vmUuid, Map params, DeploymentPlan planToDeploy) throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException { - long vmId = vm.getId(); - VirtualMachineGuru vmGuru = getVmGuru(vm); + CallContext cctxt = CallContext.current(); + Account account = cctxt.getCallingAccount(); + User caller = cctxt.getCallingUser(); + + VMInstanceVO vm = _vmDao.findByUuid(vmUuid); - vm = vmGuru.findById(vm.getId()); - Ternary start = changeToStartState(vmGuru, vm, caller, account); + long vmId = vm.getId(); + VirtualMachineGuru vmGuru = getVmGuru(vm); + + Ternary start = changeToStartState(vmGuru, vm, caller, account); if (start == null) { - return vmGuru.findById(vmId); + return; } vm = start.first(); ReservationContext ctx = start.second(); ItWorkVO work = start.third(); - T startedVm = null; + VMInstanceVO startedVm = null; ServiceOfferingVO offering = _offeringDao.findById(vm.getServiceOfferingId()); VMTemplateVO template = _templateDao.findById(vm.getTemplateId()); @@ -845,7 +854,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac } } plan = new DataCenterDeployment(planToDeploy.getDataCenterId(), planToDeploy.getPodId(), planToDeploy.getClusterId(), planToDeploy.getHostId(), vol.getPoolId(), null, ctx); - }else{ + } else { plan = new DataCenterDeployment(rootVolDcId, rootVolPodId, rootVolClusterId, null, vol.getPoolId(), null, ctx); if (s_logger.isDebugEnabled()) { s_logger.debug(vol + " is READY, changing deployment plan to use this pool's dcId: " + rootVolDcId + " , podId: " + rootVolPodId + " , and clusterId: " + rootVolClusterId); @@ -856,7 +865,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac } } - VirtualMachineProfileImpl vmProfile = new VirtualMachineProfileImpl(vm, template, offering, account, params); + VirtualMachineProfileImpl vmProfile = new VirtualMachineProfileImpl(vm, template, offering, account, params); DeployDestination dest = null; try { dest = _dpMgr.planDeployment(vmProfile, plan, avoids); @@ -955,7 +964,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac if (s_logger.isDebugEnabled()) { s_logger.debug("Start completed for VM " + vm); } - return startedVm; + return; } else { if (s_logger.isDebugEnabled()) { s_logger.info("The guru did not like the answers so stopping " + vm); @@ -1037,7 +1046,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac + "' (" + vm.getUuid() + "), see management server log for details"); } - return startedVm; + return; } @Override @@ -1075,8 +1084,8 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac return true; } - protected boolean cleanup(VirtualMachineGuru guru, VirtualMachineProfile profile, ItWorkVO work, Event event, boolean force, User user, Account account) { - T vm = profile.getVirtualMachine(); + protected boolean cleanup(VirtualMachineGuru guru, VirtualMachineProfile profile, ItWorkVO work, Event event, boolean force, User user, Account account) { + VirtualMachine vm = profile.getVirtualMachine(); State state = vm.getState(); s_logger.debug("Cleaning up resources for the vm " + vm + " in " + state + " state"); if (state == State.Starting) { diff --git a/server/src/com/cloud/vm/snapshot/VMSnapshotManagerImpl.java b/server/src/com/cloud/vm/snapshot/VMSnapshotManagerImpl.java index 686c6888ca1..b07231896d4 100644 --- a/server/src/com/cloud/vm/snapshot/VMSnapshotManagerImpl.java +++ b/server/src/com/cloud/vm/snapshot/VMSnapshotManagerImpl.java @@ -27,15 +27,15 @@ import javax.ejb.Local; import javax.inject.Inject; import javax.naming.ConfigurationException; +import org.apache.log4j.Logger; +import org.springframework.stereotype.Component; + import org.apache.cloudstack.api.command.user.vmsnapshot.ListVMSnapshotCmd; import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; -import org.apache.log4j.Logger; -import org.springframework.stereotype.Component; - import com.cloud.agent.AgentManager; import com.cloud.agent.api.Answer; import com.cloud.agent.api.Command; @@ -61,8 +61,8 @@ import com.cloud.host.Host; import com.cloud.host.HostVO; import com.cloud.host.dao.HostDao; import com.cloud.hypervisor.Hypervisor.HypervisorType; -import com.cloud.hypervisor.dao.HypervisorCapabilitiesDao; import com.cloud.hypervisor.HypervisorGuruManager; +import com.cloud.hypervisor.dao.HypervisorCapabilitiesDao; import com.cloud.projects.Project.ListProjectResourcesCriteria; import com.cloud.storage.GuestOSVO; import com.cloud.storage.Snapshot; @@ -205,7 +205,7 @@ public class VMSnapshotManagerImpl extends ManagerBase implements VMSnapshotMana } if (state == null) { - VMSnapshot.State[] status = { VMSnapshot.State.Ready, VMSnapshot.State.Creating, VMSnapshot.State.Allocated, + VMSnapshot.State[] status = { VMSnapshot.State.Ready, VMSnapshot.State.Creating, VMSnapshot.State.Allocated, VMSnapshot.State.Error, VMSnapshot.State.Expunging, VMSnapshot.State.Reverting }; sc.setParameters("status", (Object[]) status); } else { @@ -237,7 +237,7 @@ public class VMSnapshotManagerImpl extends ManagerBase implements VMSnapshotMana } @Override - public VMSnapshot allocVMSnapshot(Long vmId, String vsDisplayName, String vsDescription, Boolean snapshotMemory) + public VMSnapshot allocVMSnapshot(Long vmId, String vsDisplayName, String vsDescription, Boolean snapshotMemory) throws ResourceAllocationException { Account caller = getCaller(); @@ -265,7 +265,7 @@ public class VMSnapshotManagerImpl extends ManagerBase implements VMSnapshotMana vsDisplayName = vmSnapshotName; } if(_vmSnapshotDao.findByName(vmId,vsDisplayName) != null){ - throw new InvalidParameterValueException("Creating VM snapshot failed due to VM snapshot with name" + vsDisplayName + " already exists"); + throw new InvalidParameterValueException("Creating VM snapshot failed due to VM snapshot with name" + vsDisplayName + " already exists"); } // check VM state @@ -322,7 +322,7 @@ public class VMSnapshotManagerImpl extends ManagerBase implements VMSnapshotMana } catch (Exception e) { String msg = e.getMessage(); s_logger.error("Create vm snapshot record failed for vm: " + vmId + " due to: " + msg); - } + } return null; } @@ -352,7 +352,7 @@ public class VMSnapshotManagerImpl extends ManagerBase implements VMSnapshotMana } protected VMSnapshot createVmSnapshotInternal(UserVmVO userVm, VMSnapshotVO vmSnapshot, Long hostId) { - try { + try { CreateVMSnapshotAnswer answer = null; GuestOSVO guestOS = _guestOSDao.findById(userVm.getGuestOSId()); @@ -412,7 +412,7 @@ public class VMSnapshotManagerImpl extends ManagerBase implements VMSnapshotMana List volumeVos = _volumeDao.findByInstance(vmId); for (VolumeVO volume : volumeVos) { - StoragePool pool = (StoragePool)this.dataStoreMgr.getPrimaryDataStore(volume.getPoolId()); + StoragePool pool = (StoragePool)dataStoreMgr.getPrimaryDataStore(volume.getPoolId()); VolumeTO volumeTO = new VolumeTO(volume, pool); volumeTOs.add(volumeTO); } @@ -488,7 +488,7 @@ public class VMSnapshotManagerImpl extends ManagerBase implements VMSnapshotMana _vmSnapshotDao.persist(child); } - // update current snapshot + // update current snapshot VMSnapshotVO current = _vmSnapshotDao.findCurrentSnapshotByVmId(vmSnapshot.getVmId()); if(current != null && current.getId() == vmSnapshot.getId() && vmSnapshot.getParent() != null){ VMSnapshotVO parent = _vmSnapshotDao.findById(vmSnapshot.getParent()); @@ -550,7 +550,7 @@ public class VMSnapshotManagerImpl extends ManagerBase implements VMSnapshotMana @Override public boolean hasActiveVMSnapshotTasks(Long vmId){ - List activeVMSnapshots = _vmSnapshotDao.listByInstanceId(vmId, + List activeVMSnapshots = _vmSnapshotDao.listByInstanceId(vmId, VMSnapshot.State.Creating, VMSnapshot.State.Expunging,VMSnapshot.State.Reverting,VMSnapshot.State.Allocated); return activeVMSnapshots.size() > 0; } @@ -602,7 +602,7 @@ public class VMSnapshotManagerImpl extends ManagerBase implements VMSnapshotMana // prepare DeleteVMSnapshotCommand String vmInstanceName = userVm.getInstanceName(); VMSnapshotTO parent = getSnapshotWithParents(vmSnapshot).getParent(); - VMSnapshotTO vmSnapshotTO = new VMSnapshotTO(vmSnapshot.getId(), vmSnapshot.getName(), vmSnapshot.getType(), + VMSnapshotTO vmSnapshotTO = new VMSnapshotTO(vmSnapshot.getId(), vmSnapshot.getName(), vmSnapshot.getType(), vmSnapshot.getCreated().getTime(), vmSnapshot.getDescription(), vmSnapshot.getCurrent(), parent); GuestOSVO guestOS = _guestOSDao.findById(userVm.getGuestOSId()); DeleteVMSnapshotCommand deleteSnapshotCommand = new DeleteVMSnapshotCommand(vmInstanceName, vmSnapshotTO, volumeTOs,guestOS.getDisplayName()); @@ -673,7 +673,8 @@ public class VMSnapshotManagerImpl extends ManagerBase implements VMSnapshotMana // start or stop VM first, if revert from stopped state to running state, or from running to stopped if(userVm.getState() == VirtualMachine.State.Stopped && vmSnapshotVo.getType() == VMSnapshot.Type.DiskAndMemory){ try { - vm = _itMgr.advanceStart(userVm, new HashMap(), callerUser, owner); + _itMgr.advanceStart(userVm.getUuid(), new HashMap()); + vm = _userVMDao.findById(userVm.getId()); hostId = vm.getHostId(); } catch (Exception e) { s_logger.error("Start VM " + userVm.getInstanceName() + " before reverting failed due to " + e.getMessage()); @@ -715,7 +716,7 @@ public class VMSnapshotManagerImpl extends ManagerBase implements VMSnapshotMana List volumeTOs = getVolumeTOList(userVm.getId()); String vmInstanceName = userVm.getInstanceName(); VMSnapshotTO parent = getSnapshotWithParents(snapshot).getParent(); - VMSnapshotTO vmSnapshotTO = new VMSnapshotTO(snapshot.getId(), snapshot.getName(), snapshot.getType(), + VMSnapshotTO vmSnapshotTO = new VMSnapshotTO(snapshot.getId(), snapshot.getName(), snapshot.getType(), snapshot.getCreated().getTime(), snapshot.getDescription(), snapshot.getCurrent(), parent); GuestOSVO guestOS = _guestOSDao.findById(userVm.getGuestOSId()); @@ -746,7 +747,7 @@ public class VMSnapshotManagerImpl extends ManagerBase implements VMSnapshotMana String errMsg = "revert vm: " + userVm.getInstanceName() + " to snapshot " + vmSnapshotVo.getName() + " failed due to " + e.getMessage(); s_logger.error(errMsg); throw new CloudRuntimeException(e.getMessage()); - } + } return userVm; } diff --git a/server/test/com/cloud/vm/UserVmManagerTest.java b/server/test/com/cloud/vm/UserVmManagerTest.java index 0eb9a089609..6b0f688a1e1 100755 --- a/server/test/com/cloud/vm/UserVmManagerTest.java +++ b/server/test/com/cloud/vm/UserVmManagerTest.java @@ -198,7 +198,6 @@ public class UserVmManagerTest { doReturn(3L).when(_volumeMock).getTemplateId(); when(_templateDao.findById(anyLong())).thenReturn(_templateMock); when(_itMgr.stop(_vmMock, _userMock, _account)).thenReturn(true); - when(_itMgr.start(_vmMock, null, _userMock, _account)).thenReturn(_vmMock); when(_storageMgr.allocateDuplicateVolume(_volumeMock, null)).thenReturn(_volumeMock); doNothing().when(_volsDao).attachVolume(anyLong(), anyLong(), anyLong()); when(_volumeMock.getId()).thenReturn(3L); @@ -237,7 +236,6 @@ public class UserVmManagerTest { doNothing().when(_vmMock).setGuestOSId(anyLong()); doNothing().when(_vmMock).setTemplateId(3L); when(_vmDao.update(314L, _vmMock)).thenReturn(true); - when(_itMgr.start(_vmMock, null, _userMock, _account)).thenReturn(_vmMock); when(_storageMgr.allocateDuplicateVolume(_volumeMock, null)).thenReturn(_volumeMock); doNothing().when(_volsDao).attachVolume(anyLong(), anyLong(), anyLong()); when(_volumeMock.getId()).thenReturn(3L); @@ -278,7 +276,6 @@ public class UserVmManagerTest { doNothing().when(_vmMock).setGuestOSId(anyLong()); doNothing().when(_vmMock).setTemplateId(3L); when(_vmDao.update(314L, _vmMock)).thenReturn(true); - when(_itMgr.start(_vmMock, null, _userMock, _account)).thenReturn(_vmMock); when(_storageMgr.allocateDuplicateVolume(_volumeMock, null)).thenReturn(_volumeMock); doNothing().when(_volsDao).attachVolume(anyLong(), anyLong(), anyLong()); when(_volumeMock.getId()).thenReturn(3L); From 1325014a03efbe8d698f55c17ed70ecb8817c1b4 Mon Sep 17 00:00:00 2001 From: Alex Huang Date: Mon, 22 Jul 2013 11:08:39 -0700 Subject: [PATCH 37/74] Changed VirtualMachineProfile to be non-generic. From here on VirtualMachineManager will only manage vm instance. It doesn't understand the difference between different types of VMs. This makes the vmsync code to be generic across all vms. --- .../manager/allocator/HostAllocator.java | 6 +- .../deploy/DeploymentClusterPlanner.java | 6 +- .../com/cloud/deploy/DeploymentPlanner.java | 7 +- .../com/cloud/hypervisor/HypervisorGuru.java | 2 +- .../network/NetworkMigrationResponder.java | 6 +- .../network/element/DhcpServiceProvider.java | 4 +- .../cloud/network/element/NetworkElement.java | 4 +- .../element/UserDataServiceProvider.java | 8 +- .../com/cloud/network/guru/NetworkGuru.java | 8 +- .../com/cloud/vm/VirtualMachineProfile.java | 8 +- .../affinity/AffinityGroupProcessor.java | 5 +- .../affinity/AffinityProcessorBase.java | 5 +- .../api/storage/StoragePoolAllocator.java | 3 +- .../cloud/entity/api/VMEntityManagerImpl.java | 6 +- .../AbstractStoragePoolAllocator.java | 10 +- .../ClusterScopeStoragePoolAllocator.java | 10 +- ...GarbageCollectingStoragePoolAllocator.java | 2 +- .../allocator/LocalStoragePoolAllocator.java | 2 +- .../allocator/UseLocalForRootAllocator.java | 2 +- .../ZoneWideStoragePoolAllocator.java | 2 +- .../affinity/ExplicitDedicationProcessor.java | 5 +- .../affinity/HostAntiAffinityProcessor.java | 4 +- .../deploy/ImplicitDedicationPlanner.java | 4 +- .../implicitplanner/ImplicitPlannerTest.java | 16 +- .../deploy/UserConcentratedPodPlanner.java | 4 +- .../cloud/deploy/UserDispersingPlanner.java | 4 +- .../allocator/impl/RandomAllocator.java | 6 +- .../baremetal/manager/BareMetalGuru.java | 11 +- .../baremetal/manager/BareMetalPlanner.java | 16 +- .../BareMetalPingServiceImpl.java | 20 +- .../networkservice/BaremetaNetworkGuru.java | 4 +- .../networkservice/BaremetalDhcpElement.java | 8 +- .../networkservice/BaremetalDhcpManager.java | 2 +- .../BaremetalDhcpManagerImpl.java | 2 +- .../BaremetalKickStartServiceImpl.java | 10 +- .../networkservice/BaremetalPxeElement.java | 4 +- .../networkservice/BaremetalPxeManager.java | 11 +- .../BaremetalPxeManagerImpl.java | 13 +- .../networkservice/BaremetalPxeService.java | 14 +- .../BaremetalUserdataElement.java | 14 +- .../src/com/cloud/ovm/hypervisor/OvmGuru.java | 6 +- .../com/cloud/simulator/SimulatorGuru.java | 9 +- .../com/cloud/hypervisor/guru/VMwareGuru.java | 2 +- .../network/element/CiscoNexusVSMElement.java | 4 +- .../com/cloud/hypervisor/XenServerGuru.java | 6 +- .../network/element/BigSwitchVnsElement.java | 4 +- .../guru/BigSwitchVnsGuestNetworkGuru.java | 4 +- .../network/element/CiscoVnmcElement.java | 4 +- .../network/element/DnsNotifier.java | 4 +- .../element/ElasticLoadBalancerElement.java | 4 +- .../lb/ElasticLoadBalancerManagerImpl.java | 21 +- .../F5ExternalLoadBalancerElement.java | 4 +- .../element/InternalLoadBalancerElement.java | 4 +- .../lb/InternalLoadBalancerVMManagerImpl.java | 23 +- .../JuniperSRXExternalFirewallElement.java | 4 +- .../cloud/network/element/MidoNetElement.java | 8 +- .../network/guru/MidoNetGuestNetworkGuru.java | 4 +- .../guru/MidoNetPublicNetworkGuru.java | 10 +- .../network/element/MidoNetElementTest.java | 4 +- .../network/element/NetscalerElement.java | 4 +- .../network/element/NiciraNvpElement.java | 4 +- .../guru/NiciraNvpGuestNetworkGuru.java | 4 +- .../com/cloud/network/element/OvsElement.java | 4 +- .../cloud/network/ovs/OvsTunnelManager.java | 2 +- .../network/ovs/OvsTunnelManagerImpl.java | 2 +- .../network/element/SspElement.java | 10 +- .../network/guru/SspGuestNetworkGuru.java | 10 +- .../allocator/RandomStoragePoolAllocator.java | 2 +- .../allocator/impl/FirstFitAllocator.java | 6 +- .../impl/FirstFitRoutingAllocator.java | 2 +- .../allocator/impl/RecreateHostAllocator.java | 2 +- .../allocator/impl/TestingAllocator.java | 6 +- .../consoleproxy/ConsoleProxyManagerImpl.java | 18 +- .../deploy/DeploymentPlanningManager.java | 5 +- .../deploy/DeploymentPlanningManagerImpl.java | 14 +- .../src/com/cloud/deploy/FirstFitPlanner.java | 20 +- .../cloud/hypervisor/HypervisorGuruBase.java | 2 +- server/src/com/cloud/hypervisor/KVMGuru.java | 4 +- server/src/com/cloud/hypervisor/LXCGuru.java | 4 +- .../src/com/cloud/network/NetworkManager.java | 49 +- .../com/cloud/network/NetworkManagerImpl.java | 42 +- .../element/CloudZonesNetworkElement.java | 31 +- .../network/element/SecurityGroupElement.java | 4 +- .../network/element/VirtualRouterElement.java | 36 +- .../element/VpcVirtualRouterElement.java | 2 +- .../network/guru/ControlNetworkGuru.java | 8 +- .../cloud/network/guru/DirectNetworkGuru.java | 10 +- .../guru/DirectPodBasedNetworkGuru.java | 6 +- .../guru/ExternalGuestNetworkGuru.java | 8 +- .../cloud/network/guru/GuestNetworkGuru.java | 8 +- .../network/guru/PodBasedNetworkGuru.java | 8 +- .../network/guru/PrivateNetworkGuru.java | 8 +- .../cloud/network/guru/PublicNetworkGuru.java | 10 +- .../network/guru/StorageNetworkGuru.java | 8 +- .../VirtualNetworkApplianceManager.java | 12 +- .../VirtualNetworkApplianceManagerImpl.java | 86 +- ...VpcVirtualNetworkApplianceManagerImpl.java | 18 +- .../cloud/server/ManagementServerImpl.java | 6 +- .../com/cloud/storage/StorageManagerImpl.java | 2 +- .../src/com/cloud/storage/VolumeManager.java | 13 +- .../com/cloud/storage/VolumeManagerImpl.java | 12 +- .../SecondaryStorageManagerImpl.java | 23 +- .../src/com/cloud/vm/UserVmManagerImpl.java | 37 +- .../src/com/cloud/vm/VirtualMachineGuru.java | 14 +- .../com/cloud/vm/VirtualMachineManager.java | 2 +- .../cloud/vm/VirtualMachineManagerImpl.java | 47 +- .../cloud/vm/VirtualMachineProfileImpl.java | 20 +- .../cloud/network/MockNetworkManagerImpl.java | 962 ------------------ .../vm/VirtualMachineManagerImplTest.java | 2 +- .../com/cloud/vpc/MockNetworkManagerImpl.java | 62 +- ...MockVpcVirtualNetworkApplianceManager.java | 12 +- 111 files changed, 548 insertions(+), 1552 deletions(-) delete mode 100755 server/test/com/cloud/network/MockNetworkManagerImpl.java diff --git a/api/src/com/cloud/agent/manager/allocator/HostAllocator.java b/api/src/com/cloud/agent/manager/allocator/HostAllocator.java index fcd1fc10072..14525aa52de 100755 --- a/api/src/com/cloud/agent/manager/allocator/HostAllocator.java +++ b/api/src/com/cloud/agent/manager/allocator/HostAllocator.java @@ -47,7 +47,7 @@ public interface HostAllocator extends Adapter { * @return List List of hosts that are suitable for VM allocation **/ - public List allocateTo(VirtualMachineProfile vmProfile, DeploymentPlan plan, Type type, ExcludeList avoid, int returnUpTo); + public List allocateTo(VirtualMachineProfile vmProfile, DeploymentPlan plan, Type type, ExcludeList avoid, int returnUpTo); /** * Determines which physical hosts are suitable to @@ -62,7 +62,7 @@ public interface HostAllocator extends Adapter { * @return List List of hosts that are suitable for VM allocation **/ - public List allocateTo(VirtualMachineProfile vmProfile, DeploymentPlan plan, Type type, ExcludeList avoid, int returnUpTo, boolean considerReservedCapacity); + public List allocateTo(VirtualMachineProfile vmProfile, DeploymentPlan plan, Type type, ExcludeList avoid, int returnUpTo, boolean considerReservedCapacity); /** * Determines which physical hosts are suitable to @@ -77,7 +77,7 @@ public interface HostAllocator extends Adapter { * @param boolean considerReservedCapacity (default should be true, set to false if host capacity calculation should not look at reserved capacity) * @return List List of hosts that are suitable for VM allocation **/ - public List allocateTo(VirtualMachineProfile vmProfile, DeploymentPlan plan, Type type, ExcludeList avoid, List hosts, + public List allocateTo(VirtualMachineProfile vmProfile, DeploymentPlan plan, Type type, ExcludeList avoid, List hosts, int returnUpTo, boolean considerReservedCapacity); public static int RETURN_UPTO_ALL = -1; diff --git a/api/src/com/cloud/deploy/DeploymentClusterPlanner.java b/api/src/com/cloud/deploy/DeploymentClusterPlanner.java index 8b15ea56e8f..ca73267e732 100644 --- a/api/src/com/cloud/deploy/DeploymentClusterPlanner.java +++ b/api/src/com/cloud/deploy/DeploymentClusterPlanner.java @@ -18,9 +18,7 @@ package com.cloud.deploy; import java.util.List; -import com.cloud.deploy.DeploymentPlanner.ExcludeList; import com.cloud.exception.InsufficientServerCapacityException; -import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachineProfile; /** @@ -38,10 +36,10 @@ public interface DeploymentClusterPlanner extends DeploymentPlanner { * avoid these data centers, pods, clusters, or hosts. * @return DeployDestination for that virtual machine. */ - List orderClusters(VirtualMachineProfile vm, DeploymentPlan plan, ExcludeList avoid) + List orderClusters(VirtualMachineProfile vm, DeploymentPlan plan, ExcludeList avoid) throws InsufficientServerCapacityException; - PlannerResourceUsage getResourceUsage(VirtualMachineProfile vmProfile, + PlannerResourceUsage getResourceUsage(VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid) throws InsufficientServerCapacityException; } diff --git a/api/src/com/cloud/deploy/DeploymentPlanner.java b/api/src/com/cloud/deploy/DeploymentPlanner.java index 769da39f3ff..741a8048a0a 100644 --- a/api/src/com/cloud/deploy/DeploymentPlanner.java +++ b/api/src/com/cloud/deploy/DeploymentPlanner.java @@ -29,7 +29,6 @@ import com.cloud.host.Host; import com.cloud.org.Cluster; import com.cloud.storage.StoragePool; import com.cloud.utils.component.Adapter; -import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachineProfile; /** @@ -48,7 +47,7 @@ public interface DeploymentPlanner extends Adapter { * @return DeployDestination for that virtual machine. */ @Deprecated - DeployDestination plan(VirtualMachineProfile vm, DeploymentPlan plan, ExcludeList avoid) throws InsufficientServerCapacityException; + DeployDestination plan(VirtualMachineProfile vm, DeploymentPlan plan, ExcludeList avoid) throws InsufficientServerCapacityException; /** * check() is called right before the virtual machine starts to make sure @@ -65,7 +64,7 @@ public interface DeploymentPlanner extends Adapter { * @return true if it's okay to start; false if not. If false, the exclude list will include what should be * excluded. */ - boolean check(VirtualMachineProfile vm, DeploymentPlan plan, DeployDestination dest, ExcludeList exclude); + boolean check(VirtualMachineProfile vm, DeploymentPlan plan, DeployDestination dest, ExcludeList exclude); /** * canHandle is called before plan to determine if the plan can do the allocation. Planers should be exclusive so @@ -80,7 +79,7 @@ public interface DeploymentPlanner extends Adapter { * avoid these data centers, pods, clusters, or hosts. * @return true if it's okay to allocate; false or not */ - boolean canHandle(VirtualMachineProfile vm, DeploymentPlan plan, ExcludeList avoid); + boolean canHandle(VirtualMachineProfile vm, DeploymentPlan plan, ExcludeList avoid); public enum AllocationAlgorithm { random, diff --git a/api/src/com/cloud/hypervisor/HypervisorGuru.java b/api/src/com/cloud/hypervisor/HypervisorGuru.java index 47ca17a84a3..182f06ae968 100644 --- a/api/src/com/cloud/hypervisor/HypervisorGuru.java +++ b/api/src/com/cloud/hypervisor/HypervisorGuru.java @@ -36,7 +36,7 @@ public interface HypervisorGuru extends Adapter { * @param vm * @return */ - VirtualMachineTO implement(VirtualMachineProfile vm); + VirtualMachineTO implement(VirtualMachineProfile vm); /** * Give hypervisor guru opportunity to decide if certain command needs to be delegated to other host, mainly to secondary storage VM host diff --git a/api/src/com/cloud/network/NetworkMigrationResponder.java b/api/src/com/cloud/network/NetworkMigrationResponder.java index 6283cc54128..951e1c2b4d2 100644 --- a/api/src/com/cloud/network/NetworkMigrationResponder.java +++ b/api/src/com/cloud/network/NetworkMigrationResponder.java @@ -38,7 +38,7 @@ public interface NetworkMigrationResponder { * @param context * @return true when operation was successful. */ - public boolean prepareMigration(NicProfile nic, Network network, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context); + public boolean prepareMigration(NicProfile nic, Network network, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context); /** * Cancel for migration preparation. @@ -52,7 +52,7 @@ public interface NetworkMigrationResponder { * @param src The context nic migrates from. * @param dst The context nic migrates to. */ - public void rollbackMigration(NicProfile nic, Network network, VirtualMachineProfile vm, ReservationContext src, ReservationContext dst); + public void rollbackMigration(NicProfile nic, Network network, VirtualMachineProfile vm, ReservationContext src, ReservationContext dst); /** * Commit the migration resource. @@ -66,5 +66,5 @@ public interface NetworkMigrationResponder { * @param src the context nic migrates from. * @param dst the context nic migrates to. */ - public void commitMigration(NicProfile nic, Network network, VirtualMachineProfile vm, ReservationContext src, ReservationContext dst); + public void commitMigration(NicProfile nic, Network network, VirtualMachineProfile vm, ReservationContext src, ReservationContext dst); } diff --git a/api/src/com/cloud/network/element/DhcpServiceProvider.java b/api/src/com/cloud/network/element/DhcpServiceProvider.java index 6363d7cd22e..62c650be313 100644 --- a/api/src/com/cloud/network/element/DhcpServiceProvider.java +++ b/api/src/com/cloud/network/element/DhcpServiceProvider.java @@ -27,7 +27,7 @@ import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachineProfile; public interface DhcpServiceProvider extends NetworkElement { - boolean addDhcpEntry(Network network, NicProfile nic, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException; - boolean configDhcpSupportForSubnet(Network network, NicProfile nic, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException; + boolean addDhcpEntry(Network network, NicProfile nic, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException; + boolean configDhcpSupportForSubnet(Network network, NicProfile nic, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException; boolean removeDhcpSupportForSubnet(Network network) throws ResourceUnavailableException; } diff --git a/api/src/com/cloud/network/element/NetworkElement.java b/api/src/com/cloud/network/element/NetworkElement.java index d89c2a3c403..5f603ce6fbd 100644 --- a/api/src/com/cloud/network/element/NetworkElement.java +++ b/api/src/com/cloud/network/element/NetworkElement.java @@ -71,7 +71,7 @@ public interface NetworkElement extends Adapter { * @throws ResourceUnavailableException * @throws InsufficientNetworkCapacityException */ - boolean prepare(Network network, NicProfile nic, VirtualMachineProfile vm, + boolean prepare(Network network, NicProfile nic, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException; @@ -85,7 +85,7 @@ public interface NetworkElement extends Adapter { * @throws ConcurrentOperationException * @throws ResourceUnavailableException */ - boolean release(Network network, NicProfile nic, VirtualMachineProfile vm, + boolean release(Network network, NicProfile nic, VirtualMachineProfile vm, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException; /** diff --git a/api/src/com/cloud/network/element/UserDataServiceProvider.java b/api/src/com/cloud/network/element/UserDataServiceProvider.java index d9ddf9329ff..29cd5ae9377 100644 --- a/api/src/com/cloud/network/element/UserDataServiceProvider.java +++ b/api/src/com/cloud/network/element/UserDataServiceProvider.java @@ -27,8 +27,8 @@ import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachineProfile; public interface UserDataServiceProvider extends NetworkElement { - public boolean addPasswordAndUserdata(Network network, NicProfile nic, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException; - boolean savePassword(Network network, NicProfile nic, VirtualMachineProfile vm) throws ResourceUnavailableException; - boolean saveUserData(Network network, NicProfile nic, VirtualMachineProfile vm) throws ResourceUnavailableException; - boolean saveSSHKey(Network network, NicProfile nic, VirtualMachineProfile vm, String SSHPublicKey) throws ResourceUnavailableException; + public boolean addPasswordAndUserdata(Network network, NicProfile nic, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException; + boolean savePassword(Network network, NicProfile nic, VirtualMachineProfile vm) throws ResourceUnavailableException; + boolean saveUserData(Network network, NicProfile nic, VirtualMachineProfile vm) throws ResourceUnavailableException; + boolean saveSSHKey(Network network, NicProfile nic, VirtualMachineProfile vm, String SSHPublicKey) throws ResourceUnavailableException; } diff --git a/api/src/com/cloud/network/guru/NetworkGuru.java b/api/src/com/cloud/network/guru/NetworkGuru.java index 4a9b871e240..4127233d3aa 100755 --- a/api/src/com/cloud/network/guru/NetworkGuru.java +++ b/api/src/com/cloud/network/guru/NetworkGuru.java @@ -127,7 +127,7 @@ public interface NetworkGuru extends Adapter { * @throws InsufficientAddressCapacityException if there are not addresses * to be assigned. */ - NicProfile allocate(Network network, NicProfile nic, VirtualMachineProfile vm) throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException, ConcurrentOperationException; + NicProfile allocate(Network network, NicProfile nic, VirtualMachineProfile vm) throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException, ConcurrentOperationException; /** * Once a guest network is implemented, then the virtual machine must @@ -147,7 +147,7 @@ public interface NetworkGuru extends Adapter { * @throws ConcurrentOperationException if there are multiple operations * happening on this guest network or vm. */ - void reserve(NicProfile nic, Network network, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException, ConcurrentOperationException; + void reserve(NicProfile nic, Network network, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException, ConcurrentOperationException; /** * When a virtual machine is stopped, the NetworkGuru is informed via the @@ -158,7 +158,7 @@ public interface NetworkGuru extends Adapter { * @param reservationId reservation id passed to it in the ReservationContext * @return true if release is successful or false if unsuccessful. */ - boolean release(NicProfile nic, VirtualMachineProfile vm, String reservationId); + boolean release(NicProfile nic, VirtualMachineProfile vm, String reservationId); /** * When a virtual machine is destroyed, the NetworkGuru is informed via @@ -169,7 +169,7 @@ public interface NetworkGuru extends Adapter { * @param nic nic that the vm was using to access the guest network. * @param vm virtual machine being destroyed. */ - void deallocate(Network network, NicProfile nic, VirtualMachineProfile vm); + void deallocate(Network network, NicProfile nic, VirtualMachineProfile vm); /** * @deprecated This method should not be here in the first place. What does this really mean? Is it always persisted diff --git a/api/src/com/cloud/vm/VirtualMachineProfile.java b/api/src/com/cloud/vm/VirtualMachineProfile.java index 6861372d08d..3da8397fd0e 100644 --- a/api/src/com/cloud/vm/VirtualMachineProfile.java +++ b/api/src/com/cloud/vm/VirtualMachineProfile.java @@ -19,9 +19,7 @@ package com.cloud.vm; import java.util.List; import java.util.Map; -import com.cloud.agent.api.to.DataTO; import com.cloud.agent.api.to.DiskTO; -import com.cloud.agent.api.to.VolumeTO; import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.offering.ServiceOffering; import com.cloud.template.VirtualMachineTemplate; @@ -33,10 +31,8 @@ import com.cloud.user.Account; * on what the virtual machine profile should look like before it is * actually started on the hypervisor. * - * @param - * a VirtualMachine */ -public interface VirtualMachineProfile { +public interface VirtualMachineProfile { public static class Param { @@ -69,7 +65,7 @@ public interface VirtualMachineProfile { /** * @return the virtual machine that backs up this profile. */ - T getVirtualMachine(); + VirtualMachine getVirtualMachine(); /** * @return service offering for this virtual machine. diff --git a/api/src/org/apache/cloudstack/affinity/AffinityGroupProcessor.java b/api/src/org/apache/cloudstack/affinity/AffinityGroupProcessor.java index e3a9b62c6ce..8e9fabd3f60 100644 --- a/api/src/org/apache/cloudstack/affinity/AffinityGroupProcessor.java +++ b/api/src/org/apache/cloudstack/affinity/AffinityGroupProcessor.java @@ -21,7 +21,6 @@ import com.cloud.deploy.DeploymentPlan; import com.cloud.deploy.DeploymentPlanner.ExcludeList; import com.cloud.exception.AffinityConflictException; import com.cloud.utils.component.Adapter; -import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachineProfile; public interface AffinityGroupProcessor extends Adapter { @@ -37,7 +36,7 @@ public interface AffinityGroupProcessor extends Adapter { * @param avoid * avoid these data centers, pods, clusters, or hosts. */ - void process(VirtualMachineProfile vm, DeploymentPlan plan, ExcludeList avoid) + void process(VirtualMachineProfile vm, DeploymentPlan plan, ExcludeList avoid) throws AffinityConflictException; /** @@ -57,6 +56,6 @@ public interface AffinityGroupProcessor extends Adapter { * @param plannedDestination * deployment destination where VM is planned to be deployed */ - boolean check(VirtualMachineProfile vm, DeployDestination plannedDestination) + boolean check(VirtualMachineProfile vm, DeployDestination plannedDestination) throws AffinityConflictException; } \ No newline at end of file diff --git a/api/src/org/apache/cloudstack/affinity/AffinityProcessorBase.java b/api/src/org/apache/cloudstack/affinity/AffinityProcessorBase.java index 325ab80e047..779ca326b3a 100644 --- a/api/src/org/apache/cloudstack/affinity/AffinityProcessorBase.java +++ b/api/src/org/apache/cloudstack/affinity/AffinityProcessorBase.java @@ -21,7 +21,6 @@ import com.cloud.deploy.DeploymentPlan; import com.cloud.deploy.DeploymentPlanner.ExcludeList; import com.cloud.exception.AffinityConflictException; import com.cloud.utils.component.AdapterBase; -import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachineProfile; public class AffinityProcessorBase extends AdapterBase implements AffinityGroupProcessor { @@ -29,7 +28,7 @@ public class AffinityProcessorBase extends AdapterBase implements AffinityGroupP protected String _type; @Override - public void process(VirtualMachineProfile vm, DeploymentPlan plan, ExcludeList avoid) + public void process(VirtualMachineProfile vm, DeploymentPlan plan, ExcludeList avoid) throws AffinityConflictException { } @@ -44,7 +43,7 @@ public class AffinityProcessorBase extends AdapterBase implements AffinityGroupP } @Override - public boolean check(VirtualMachineProfile vm, DeployDestination plannedDestination) + public boolean check(VirtualMachineProfile vm, DeployDestination plannedDestination) throws AffinityConflictException { return true; } diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/StoragePoolAllocator.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/StoragePoolAllocator.java index eccf0f4f6e1..54808c195c5 100644 --- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/StoragePoolAllocator.java +++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/StoragePoolAllocator.java @@ -23,7 +23,6 @@ import com.cloud.deploy.DeploymentPlanner.ExcludeList; import com.cloud.storage.StoragePool; import com.cloud.utils.component.Adapter; import com.cloud.vm.DiskProfile; -import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachineProfile; /** @@ -44,7 +43,7 @@ public interface StoragePoolAllocator extends Adapter { * @return List List of storage pools that are suitable for the * VM **/ - List allocateToPool(DiskProfile dskCh, VirtualMachineProfile vmProfile, + List allocateToPool(DiskProfile dskCh, VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo); static int RETURN_UPTO_ALL = -1; diff --git a/engine/orchestration/src/org/apache/cloudstack/engine/cloud/entity/api/VMEntityManagerImpl.java b/engine/orchestration/src/org/apache/cloudstack/engine/cloud/entity/api/VMEntityManagerImpl.java index ee5ae2df804..aae0962ee3a 100755 --- a/engine/orchestration/src/org/apache/cloudstack/engine/cloud/entity/api/VMEntityManagerImpl.java +++ b/engine/orchestration/src/org/apache/cloudstack/engine/cloud/entity/api/VMEntityManagerImpl.java @@ -129,7 +129,7 @@ public class VMEntityManagerImpl implements VMEntityManager { } - protected boolean areAffinityGroupsAssociated(VirtualMachineProfile vmProfile) { + protected boolean areAffinityGroupsAssociated(VirtualMachineProfile vmProfile) { VirtualMachine vm = vmProfile.getVirtualMachine(); long vmGroupCount = _affinityGroupVMMapDao.countAffinityGroupsForVm(vm.getId()); @@ -147,7 +147,7 @@ public class VMEntityManagerImpl implements VMEntityManager { //load vm instance and offerings and call virtualMachineManagerImpl //FIXME: profile should work on VirtualMachineEntity VMInstanceVO vm = _vmDao.findByUuid(vmEntityVO.getUuid()); - VirtualMachineProfileImpl vmProfile = new VirtualMachineProfileImpl(vm); + VirtualMachineProfileImpl vmProfile = new VirtualMachineProfileImpl(vm); DataCenterDeployment plan = new DataCenterDeployment(vm.getDataCenterId(), vm.getPodIdToDeployIn(), null, null, null, null); if(planToDeploy != null && planToDeploy.getDataCenterId() != 0){ plan = new DataCenterDeployment(planToDeploy.getDataCenterId(), planToDeploy.getPodId(), planToDeploy.getClusterId(), planToDeploy.getHostId(), planToDeploy.getPoolId(), planToDeploy.getPhysicalNetworkId()); @@ -256,8 +256,6 @@ public class VMEntityManagerImpl implements VMEntityManager { VMInstanceVO vm = _vmDao.findByUuid(vmEntityVO.getUuid()); return _itMgr.destroy(vm, _userDao.findById(new Long(caller)), _accountDao.findById(vm.getAccountId())); - - } } diff --git a/engine/storage/src/org/apache/cloudstack/storage/allocator/AbstractStoragePoolAllocator.java b/engine/storage/src/org/apache/cloudstack/storage/allocator/AbstractStoragePoolAllocator.java index 89e09748ea3..851377e8d74 100755 --- a/engine/storage/src/org/apache/cloudstack/storage/allocator/AbstractStoragePoolAllocator.java +++ b/engine/storage/src/org/apache/cloudstack/storage/allocator/AbstractStoragePoolAllocator.java @@ -27,10 +27,11 @@ import java.util.Random; import javax.inject.Inject; import javax.naming.ConfigurationException; +import org.apache.log4j.Logger; + import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; import org.apache.cloudstack.engine.subsystem.api.storage.StoragePoolAllocator; import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; -import org.apache.log4j.Logger; import com.cloud.configuration.dao.ConfigurationDao; import com.cloud.dc.ClusterVO; @@ -49,7 +50,6 @@ import com.cloud.user.Account; import com.cloud.utils.NumbersUtil; import com.cloud.utils.component.AdapterBase; import com.cloud.vm.DiskProfile; -import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachineProfile; public abstract class AbstractStoragePoolAllocator extends AdapterBase implements StoragePoolAllocator { @@ -99,12 +99,12 @@ public abstract class AbstractStoragePoolAllocator extends AdapterBase implement } protected abstract List select(DiskProfile dskCh, - VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, + VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo); @Override public List allocateToPool(DiskProfile dskCh, - VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, + VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo) { List pools = select(dskCh, vmProfile, plan, avoid, returnUpTo); return reOrder(pools, vmProfile, plan); @@ -144,7 +144,7 @@ public abstract class AbstractStoragePoolAllocator extends AdapterBase implement } protected List reOrder(List pools, - VirtualMachineProfile vmProfile, DeploymentPlan plan) { + VirtualMachineProfile vmProfile, DeploymentPlan plan) { if (pools == null) { return null; } diff --git a/engine/storage/src/org/apache/cloudstack/storage/allocator/ClusterScopeStoragePoolAllocator.java b/engine/storage/src/org/apache/cloudstack/storage/allocator/ClusterScopeStoragePoolAllocator.java index 41afa837b52..b1105ba31a7 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/allocator/ClusterScopeStoragePoolAllocator.java +++ b/engine/storage/src/org/apache/cloudstack/storage/allocator/ClusterScopeStoragePoolAllocator.java @@ -25,18 +25,18 @@ import javax.ejb.Local; import javax.inject.Inject; import javax.naming.ConfigurationException; -import org.apache.cloudstack.engine.subsystem.api.storage.StoragePoolAllocator; -import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; import org.apache.log4j.Logger; import org.springframework.stereotype.Component; +import org.apache.cloudstack.engine.subsystem.api.storage.StoragePoolAllocator; +import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; + import com.cloud.deploy.DeploymentPlan; import com.cloud.deploy.DeploymentPlanner.ExcludeList; import com.cloud.offering.ServiceOffering; import com.cloud.storage.StoragePool; import com.cloud.storage.dao.DiskOfferingDao; import com.cloud.vm.DiskProfile; -import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachineProfile; @Component @@ -49,7 +49,7 @@ public class ClusterScopeStoragePoolAllocator extends AbstractStoragePoolAllocat DiskOfferingDao _diskOfferingDao; @Override - protected List select(DiskProfile dskCh, VirtualMachineProfile vmProfile, + protected List select(DiskProfile dskCh, VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo) { s_logger.debug("ClusterScopeStoragePoolAllocator looking for storage pool"); @@ -91,7 +91,7 @@ public class ClusterScopeStoragePoolAllocator extends AbstractStoragePoolAllocat if (suitablePools.size() == returnUpTo) { break; } - StoragePool pol = (StoragePool) this.dataStoreMgr.getPrimaryDataStore(pool.getId()); + StoragePool pol = (StoragePool) dataStoreMgr.getPrimaryDataStore(pool.getId()); if (filter(avoid, pol, dskCh, plan)) { suitablePools.add(pol); } else { diff --git a/engine/storage/src/org/apache/cloudstack/storage/allocator/GarbageCollectingStoragePoolAllocator.java b/engine/storage/src/org/apache/cloudstack/storage/allocator/GarbageCollectingStoragePoolAllocator.java index 979ea73cd23..15b44071f81 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/allocator/GarbageCollectingStoragePoolAllocator.java +++ b/engine/storage/src/org/apache/cloudstack/storage/allocator/GarbageCollectingStoragePoolAllocator.java @@ -49,7 +49,7 @@ public class GarbageCollectingStoragePoolAllocator extends AbstractStoragePoolAl boolean _storagePoolCleanupEnabled; @Override - public List select(DiskProfile dskCh, VirtualMachineProfile vmProfile, + public List select(DiskProfile dskCh, VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo) { s_logger.debug("GarbageCollectingStoragePoolAllocator looking for storage pool"); if (!_storagePoolCleanupEnabled) { diff --git a/engine/storage/src/org/apache/cloudstack/storage/allocator/LocalStoragePoolAllocator.java b/engine/storage/src/org/apache/cloudstack/storage/allocator/LocalStoragePoolAllocator.java index 4056fe756a1..310f4a1ff64 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/allocator/LocalStoragePoolAllocator.java +++ b/engine/storage/src/org/apache/cloudstack/storage/allocator/LocalStoragePoolAllocator.java @@ -65,7 +65,7 @@ public class LocalStoragePoolAllocator extends AbstractStoragePoolAllocator { ConfigurationDao _configDao; @Override - protected List select(DiskProfile dskCh, VirtualMachineProfile vmProfile, + protected List select(DiskProfile dskCh, VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo) { List suitablePools = new ArrayList(); diff --git a/engine/storage/src/org/apache/cloudstack/storage/allocator/UseLocalForRootAllocator.java b/engine/storage/src/org/apache/cloudstack/storage/allocator/UseLocalForRootAllocator.java index d0571382191..6d7ac9300a1 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/allocator/UseLocalForRootAllocator.java +++ b/engine/storage/src/org/apache/cloudstack/storage/allocator/UseLocalForRootAllocator.java @@ -42,7 +42,7 @@ public class UseLocalForRootAllocator extends LocalStoragePoolAllocator implemen @Override public List allocateToPool(DiskProfile dskCh, - VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, + VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo) { DataCenterVO dc = _dcDao.findById(plan.getDataCenterId()); if (!dc.isLocalStorageEnabled()) { diff --git a/engine/storage/src/org/apache/cloudstack/storage/allocator/ZoneWideStoragePoolAllocator.java b/engine/storage/src/org/apache/cloudstack/storage/allocator/ZoneWideStoragePoolAllocator.java index 300d932a31c..0288b172ca2 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/allocator/ZoneWideStoragePoolAllocator.java +++ b/engine/storage/src/org/apache/cloudstack/storage/allocator/ZoneWideStoragePoolAllocator.java @@ -56,7 +56,7 @@ public class ZoneWideStoragePoolAllocator extends AbstractStoragePoolAllocator { @Override protected List select(DiskProfile dskCh, - VirtualMachineProfile vmProfile, + VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo) { s_logger.debug("ZoneWideStoragePoolAllocator to find storage pool"); List suitablePools = new ArrayList(); diff --git a/plugins/affinity-group-processors/explicit-dedication/src/org/apache/cloudstack/affinity/ExplicitDedicationProcessor.java b/plugins/affinity-group-processors/explicit-dedication/src/org/apache/cloudstack/affinity/ExplicitDedicationProcessor.java index a0eb56cbb8a..21693592e69 100644 --- a/plugins/affinity-group-processors/explicit-dedication/src/org/apache/cloudstack/affinity/ExplicitDedicationProcessor.java +++ b/plugins/affinity-group-processors/explicit-dedication/src/org/apache/cloudstack/affinity/ExplicitDedicationProcessor.java @@ -23,9 +23,10 @@ import java.util.Set; import javax.ejb.Local; import javax.inject.Inject; +import org.apache.log4j.Logger; + import org.apache.cloudstack.affinity.dao.AffinityGroupDao; import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao; -import org.apache.log4j.Logger; import com.cloud.dc.ClusterVO; import com.cloud.dc.DataCenter; @@ -82,7 +83,7 @@ public class ExplicitDedicationProcessor extends AffinityProcessorBase implement * This IncludeList is then used to update the avoid list for a given data center. */ @Override - public void process(VirtualMachineProfile vmProfile, DeploymentPlan plan, + public void process(VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid) throws AffinityConflictException { VirtualMachine vm = vmProfile.getVirtualMachine(); List vmGroupMappings = _affinityGroupVMMapDao.findByVmIdType(vm.getId(), getType()); diff --git a/plugins/affinity-group-processors/host-anti-affinity/src/org/apache/cloudstack/affinity/HostAntiAffinityProcessor.java b/plugins/affinity-group-processors/host-anti-affinity/src/org/apache/cloudstack/affinity/HostAntiAffinityProcessor.java index 1569c7ecd69..c4a847d5e0b 100644 --- a/plugins/affinity-group-processors/host-anti-affinity/src/org/apache/cloudstack/affinity/HostAntiAffinityProcessor.java +++ b/plugins/affinity-group-processors/host-anti-affinity/src/org/apache/cloudstack/affinity/HostAntiAffinityProcessor.java @@ -66,7 +66,7 @@ public class HostAntiAffinityProcessor extends AffinityProcessorBase implements protected VMReservationDao _reservationDao; @Override - public void process(VirtualMachineProfile vmProfile, DeploymentPlan plan, + public void process(VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid) throws AffinityConflictException { VirtualMachine vm = vmProfile.getVirtualMachine(); @@ -118,7 +118,7 @@ public class HostAntiAffinityProcessor extends AffinityProcessorBase implements } @Override - public boolean check(VirtualMachineProfile vmProfile, DeployDestination plannedDestination) + public boolean check(VirtualMachineProfile vmProfile, DeployDestination plannedDestination) throws AffinityConflictException { if (plannedDestination.getHost() == null) { diff --git a/plugins/deployment-planners/implicit-dedication/src/com/cloud/deploy/ImplicitDedicationPlanner.java b/plugins/deployment-planners/implicit-dedication/src/com/cloud/deploy/ImplicitDedicationPlanner.java index be016cb2507..6eee28d7a94 100644 --- a/plugins/deployment-planners/implicit-dedication/src/com/cloud/deploy/ImplicitDedicationPlanner.java +++ b/plugins/deployment-planners/implicit-dedication/src/com/cloud/deploy/ImplicitDedicationPlanner.java @@ -67,7 +67,7 @@ public class ImplicitDedicationPlanner extends FirstFitPlanner implements Deploy } @Override - public List orderClusters(VirtualMachineProfile vmProfile, + public List orderClusters(VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid) throws InsufficientServerCapacityException { List clusterList = super.orderClusters(vmProfile, plan, avoid); Set hostsToAvoid = avoid.getHostsToAvoid(); @@ -251,7 +251,7 @@ public class ImplicitDedicationPlanner extends FirstFitPlanner implements Deploy } @Override - public PlannerResourceUsage getResourceUsage(VirtualMachineProfile vmProfile, + public PlannerResourceUsage getResourceUsage(VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid) throws InsufficientServerCapacityException { // Check if strict or preferred mode should be used. boolean preferred = isServiceOfferingUsingPlannerInPreferredMode(vmProfile.getServiceOfferingId()); diff --git a/plugins/deployment-planners/implicit-dedication/test/org/apache/cloudstack/implicitplanner/ImplicitPlannerTest.java b/plugins/deployment-planners/implicit-dedication/test/org/apache/cloudstack/implicitplanner/ImplicitPlannerTest.java index 02124a2ff20..73fd2490c29 100644 --- a/plugins/deployment-planners/implicit-dedication/test/org/apache/cloudstack/implicitplanner/ImplicitPlannerTest.java +++ b/plugins/deployment-planners/implicit-dedication/test/org/apache/cloudstack/implicitplanner/ImplicitPlannerTest.java @@ -176,8 +176,7 @@ public class ImplicitPlannerTest { public void checkWhenDcInAvoidList() throws InsufficientServerCapacityException { DataCenterVO mockDc = mock(DataCenterVO.class); ExcludeList avoids = mock(ExcludeList.class); - @SuppressWarnings("unchecked") - VirtualMachineProfileImpl vmProfile = mock(VirtualMachineProfileImpl.class); + VirtualMachineProfileImpl vmProfile = mock(VirtualMachineProfileImpl.class); VMInstanceVO vm = mock(VMInstanceVO.class); DataCenterDeployment plan = mock(DataCenterDeployment.class); @@ -193,8 +192,7 @@ public class ImplicitPlannerTest { @Test public void checkStrictModeWithCurrentAccountVmsPresent() throws InsufficientServerCapacityException { - @SuppressWarnings("unchecked") - VirtualMachineProfileImpl vmProfile = mock(VirtualMachineProfileImpl.class); + VirtualMachineProfileImpl vmProfile = mock(VirtualMachineProfileImpl.class); DataCenterDeployment plan = mock(DataCenterDeployment.class); ExcludeList avoids = new ExcludeList(); @@ -230,7 +228,7 @@ public class ImplicitPlannerTest { @Test public void checkStrictModeHostWithCurrentAccountVmsFull() throws InsufficientServerCapacityException { @SuppressWarnings("unchecked") - VirtualMachineProfileImpl vmProfile = mock(VirtualMachineProfileImpl.class); + VirtualMachineProfileImpl vmProfile = mock(VirtualMachineProfileImpl.class); DataCenterDeployment plan = mock(DataCenterDeployment.class); ExcludeList avoids = new ExcludeList(); @@ -268,7 +266,7 @@ public class ImplicitPlannerTest { @Test public void checkStrictModeNoHostsAvailable() throws InsufficientServerCapacityException { @SuppressWarnings("unchecked") - VirtualMachineProfileImpl vmProfile = mock(VirtualMachineProfileImpl.class); + VirtualMachineProfileImpl vmProfile = mock(VirtualMachineProfileImpl.class); DataCenterDeployment plan = mock(DataCenterDeployment.class); ExcludeList avoids = new ExcludeList(); @@ -289,7 +287,7 @@ public class ImplicitPlannerTest { @Test public void checkPreferredModePreferredHostAvailable() throws InsufficientServerCapacityException { @SuppressWarnings("unchecked") - VirtualMachineProfileImpl vmProfile = mock(VirtualMachineProfileImpl.class); + VirtualMachineProfileImpl vmProfile = mock(VirtualMachineProfileImpl.class); DataCenterDeployment plan = mock(DataCenterDeployment.class); ExcludeList avoids = new ExcludeList(); @@ -328,7 +326,7 @@ public class ImplicitPlannerTest { @Test public void checkPreferredModeNoHostsAvailable() throws InsufficientServerCapacityException { @SuppressWarnings("unchecked") - VirtualMachineProfileImpl vmProfile = mock(VirtualMachineProfileImpl.class); + VirtualMachineProfileImpl vmProfile = mock(VirtualMachineProfileImpl.class); DataCenterDeployment plan = mock(DataCenterDeployment.class); ExcludeList avoids = new ExcludeList(); @@ -347,7 +345,7 @@ public class ImplicitPlannerTest { assertTrue("Cluster list should not be null/empty", (clusterList == null || clusterList.isEmpty())); } - private void initializeForTest(VirtualMachineProfileImpl vmProfile, DataCenterDeployment plan) { + private void initializeForTest(VirtualMachineProfileImpl vmProfile, DataCenterDeployment plan) { DataCenterVO mockDc = mock(DataCenterVO.class); VMInstanceVO vm = mock(VMInstanceVO.class); UserVmVO userVm = mock(UserVmVO.class); diff --git a/plugins/deployment-planners/user-concentrated-pod/src/com/cloud/deploy/UserConcentratedPodPlanner.java b/plugins/deployment-planners/user-concentrated-pod/src/com/cloud/deploy/UserConcentratedPodPlanner.java index d917893719e..2d734259ef5 100644 --- a/plugins/deployment-planners/user-concentrated-pod/src/com/cloud/deploy/UserConcentratedPodPlanner.java +++ b/plugins/deployment-planners/user-concentrated-pod/src/com/cloud/deploy/UserConcentratedPodPlanner.java @@ -41,7 +41,7 @@ public class UserConcentratedPodPlanner extends FirstFitPlanner implements Deplo * @return List ordered list of Cluster Ids */ @Override - protected List reorderClusters(long id, boolean isZone, Pair, Map> clusterCapacityInfo, VirtualMachineProfile vmProfile, DeploymentPlan plan){ + protected List reorderClusters(long id, boolean isZone, Pair, Map> clusterCapacityInfo, VirtualMachineProfile vmProfile, DeploymentPlan plan){ List clusterIdsByCapacity = clusterCapacityInfo.first(); if(vmProfile.getOwner() == null || !isZone){ return clusterIdsByCapacity; @@ -118,7 +118,7 @@ public class UserConcentratedPodPlanner extends FirstFitPlanner implements Deplo * @return List ordered list of Pod Ids */ @Override - protected List reorderPods(Pair, Map> podCapacityInfo, VirtualMachineProfile vmProfile, DeploymentPlan plan){ + protected List reorderPods(Pair, Map> podCapacityInfo, VirtualMachineProfile vmProfile, DeploymentPlan plan){ List podIdsByCapacity = podCapacityInfo.first(); if(vmProfile.getOwner() == null){ return podIdsByCapacity; diff --git a/plugins/deployment-planners/user-dispersing/src/com/cloud/deploy/UserDispersingPlanner.java b/plugins/deployment-planners/user-dispersing/src/com/cloud/deploy/UserDispersingPlanner.java index 2b0b1588802..d70eb319e42 100755 --- a/plugins/deployment-planners/user-dispersing/src/com/cloud/deploy/UserDispersingPlanner.java +++ b/plugins/deployment-planners/user-dispersing/src/com/cloud/deploy/UserDispersingPlanner.java @@ -46,7 +46,7 @@ public class UserDispersingPlanner extends FirstFitPlanner implements Deployment * @return List ordered list of Cluster Ids */ @Override - protected List reorderClusters(long id, boolean isZone, Pair, Map> clusterCapacityInfo, VirtualMachineProfile vmProfile, DeploymentPlan plan){ + protected List reorderClusters(long id, boolean isZone, Pair, Map> clusterCapacityInfo, VirtualMachineProfile vmProfile, DeploymentPlan plan){ List clusterIdsByCapacity = clusterCapacityInfo.first(); if(vmProfile.getOwner() == null){ return clusterIdsByCapacity; @@ -76,7 +76,7 @@ public class UserDispersingPlanner extends FirstFitPlanner implements Deployment * @return List ordered list of Pod Ids */ @Override - protected List reorderPods(Pair, Map> podCapacityInfo, VirtualMachineProfile vmProfile, DeploymentPlan plan){ + protected List reorderPods(Pair, Map> podCapacityInfo, VirtualMachineProfile vmProfile, DeploymentPlan plan){ List podIdsByCapacity = podCapacityInfo.first(); if(vmProfile.getOwner() == null){ return podIdsByCapacity; diff --git a/plugins/host-allocators/random/src/com/cloud/agent/manager/allocator/impl/RandomAllocator.java b/plugins/host-allocators/random/src/com/cloud/agent/manager/allocator/impl/RandomAllocator.java index 303e438419a..d4a62779df1 100755 --- a/plugins/host-allocators/random/src/com/cloud/agent/manager/allocator/impl/RandomAllocator.java +++ b/plugins/host-allocators/random/src/com/cloud/agent/manager/allocator/impl/RandomAllocator.java @@ -47,13 +47,13 @@ public class RandomAllocator extends AdapterBase implements HostAllocator { @Inject private ResourceManager _resourceMgr; @Override - public List allocateTo(VirtualMachineProfile vmProfile, DeploymentPlan plan, Type type, + public List allocateTo(VirtualMachineProfile vmProfile, DeploymentPlan plan, Type type, ExcludeList avoid, int returnUpTo) { return allocateTo(vmProfile, plan, type, avoid, returnUpTo, true); } @Override - public List allocateTo(VirtualMachineProfile vmProfile, DeploymentPlan plan, Type type, + public List allocateTo(VirtualMachineProfile vmProfile, DeploymentPlan plan, Type type, ExcludeList avoid, List hosts, int returnUpTo, boolean considerReservedCapacity) { long dcId = plan.getDataCenterId(); Long podId = plan.getPodId(); @@ -109,7 +109,7 @@ public class RandomAllocator extends AdapterBase implements HostAllocator { } @Override - public List allocateTo(VirtualMachineProfile vmProfile, DeploymentPlan plan, Type type, + public List allocateTo(VirtualMachineProfile vmProfile, DeploymentPlan plan, Type type, ExcludeList avoid, int returnUpTo, boolean considerReservedCapacity) { long dcId = plan.getDataCenterId(); diff --git a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/manager/BareMetalGuru.java b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/manager/BareMetalGuru.java index 03ba3fae61b..b2f12879bd0 100755 --- a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/manager/BareMetalGuru.java +++ b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/manager/BareMetalGuru.java @@ -5,20 +5,20 @@ // 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. -// +// // Automatically generated by addcopyright.py at 01/29/2013 // Apache License, Version 2.0 (the "License"); you may not use this // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// +// // Automatically generated by addcopyright.py at 04/03/2012 package com.cloud.baremetal.manager; @@ -38,7 +38,6 @@ import com.cloud.hypervisor.HypervisorGuruBase; import com.cloud.storage.GuestOSVO; import com.cloud.storage.dao.GuestOSDao; import com.cloud.vm.VMInstanceVO; -import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachineProfile; import com.cloud.vm.dao.VMInstanceDao; @@ -59,7 +58,7 @@ public class BareMetalGuru extends HypervisorGuruBase implements HypervisorGuru } @Override - public VirtualMachineTO implement(VirtualMachineProfile vm) { + public VirtualMachineTO implement(VirtualMachineProfile vm) { VirtualMachineTO to = toVirtualMachineTO(vm); VMInstanceVO vo = _vmDao.findById(vm.getId()); diff --git a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/manager/BareMetalPlanner.java b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/manager/BareMetalPlanner.java index e6ddcbeae41..cf3ceedfe81 100755 --- a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/manager/BareMetalPlanner.java +++ b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/manager/BareMetalPlanner.java @@ -23,20 +23,21 @@ import javax.ejb.Local; import javax.inject.Inject; import javax.naming.ConfigurationException; -import com.cloud.dc.*; -import com.cloud.dc.ClusterDetailsDao; import org.apache.log4j.Logger; import com.cloud.capacity.CapacityManager; -import com.cloud.configuration.Config; import com.cloud.configuration.dao.ConfigurationDao; +import com.cloud.dc.ClusterDetailsDao; +import com.cloud.dc.ClusterDetailsVO; +import com.cloud.dc.ClusterVO; +import com.cloud.dc.DataCenter; +import com.cloud.dc.Pod; import com.cloud.dc.dao.ClusterDao; import com.cloud.dc.dao.DataCenterDao; import com.cloud.dc.dao.HostPodDao; import com.cloud.deploy.DeployDestination; import com.cloud.deploy.DeploymentPlan; import com.cloud.deploy.DeploymentPlanner; -import com.cloud.deploy.DeploymentPlanner.ExcludeList; import com.cloud.exception.InsufficientServerCapacityException; import com.cloud.host.Host; import com.cloud.host.HostVO; @@ -45,7 +46,6 @@ import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.offering.ServiceOffering; import com.cloud.org.Cluster; import com.cloud.resource.ResourceManager; -import com.cloud.utils.NumbersUtil; import com.cloud.utils.component.AdapterBase; import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachineProfile; @@ -63,7 +63,7 @@ public class BareMetalPlanner extends AdapterBase implements DeploymentPlanner { @Inject protected ClusterDetailsDao _clusterDetailsDao; @Override - public DeployDestination plan(VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid) throws InsufficientServerCapacityException { + public DeployDestination plan(VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid) throws InsufficientServerCapacityException { VirtualMachine vm = vmProfile.getVirtualMachine(); ServiceOffering offering = vmProfile.getServiceOffering(); String hostTag = null; @@ -143,7 +143,7 @@ public class BareMetalPlanner extends AdapterBase implements DeploymentPlanner { } @Override - public boolean canHandle(VirtualMachineProfile vm, DeploymentPlan plan, ExcludeList avoid) { + public boolean canHandle(VirtualMachineProfile vm, DeploymentPlan plan, ExcludeList avoid) { return vm.getHypervisorType() == HypervisorType.BareMetal; } @@ -163,7 +163,7 @@ public class BareMetalPlanner extends AdapterBase implements DeploymentPlanner { } @Override - public boolean check(VirtualMachineProfile vm, DeploymentPlan plan, DeployDestination dest, ExcludeList exclude) { + public boolean check(VirtualMachineProfile vm, DeploymentPlan plan, DeployDestination dest, ExcludeList exclude) { // TODO Auto-generated method stub return false; } diff --git a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BareMetalPingServiceImpl.java b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BareMetalPingServiceImpl.java index 77958ae6a1c..772898dca2b 100755 --- a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BareMetalPingServiceImpl.java +++ b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BareMetalPingServiceImpl.java @@ -5,20 +5,20 @@ // 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. -// +// // Automatically generated by addcopyright.py at 01/29/2013 // Apache License, Version 2.0 (the "License"); you may not use this // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// +// // Automatically generated by addcopyright.py at 04/03/2012 package com.cloud.baremetal.networkservice; @@ -31,10 +31,11 @@ import java.util.Map; import javax.ejb.Local; import javax.inject.Inject; +import org.apache.log4j.Logger; + import org.apache.cloudstack.api.AddBaremetalPxeCmd; import org.apache.cloudstack.api.AddBaremetalPxePingServerCmd; import org.apache.cloudstack.api.ListBaremetalPxePingServersCmd; -import org.apache.log4j.Logger; import com.cloud.agent.api.Answer; import com.cloud.agent.api.baremetal.IpmISetBootDevCommand; @@ -68,7 +69,6 @@ import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.vm.NicProfile; import com.cloud.vm.NicVO; import com.cloud.vm.ReservationContext; -import com.cloud.vm.UserVmVO; import com.cloud.vm.VirtualMachineProfile; @Local(value=BaremetalPxeService.class) @@ -82,7 +82,7 @@ public class BareMetalPingServiceImpl extends BareMetalPxeServiceBase implements @Override - public boolean prepare(VirtualMachineProfile profile, NicProfile pxeNic, DeployDestination dest, ReservationContext context) { + public boolean prepare(VirtualMachineProfile profile, NicProfile pxeNic, DeployDestination dest, ReservationContext context) { SearchCriteriaService sc = SearchCriteria2.create(BaremetalPxeVO.class); sc.addAnd(sc.getEntity().getDeviceType(), Op.EQ, BaremetalPxeType.PING.toString()); sc.addAnd(sc.getEntity().getPodId(), Op.EQ, dest.getPod().getId()); @@ -127,7 +127,7 @@ public class BareMetalPingServiceImpl extends BareMetalPxeServiceBase implements @Override - public boolean prepareCreateTemplate(Long pxeServerId, UserVm vm, String templateUrl) { + public boolean prepareCreateTemplate(Long pxeServerId, UserVm vm, String templateUrl) { List nics = _nicDao.listByVmId(vm.getId()); if (nics.size() != 1) { throw new CloudRuntimeException("Wrong nic number " + nics.size() + " of vm " + vm.getId()); @@ -168,7 +168,7 @@ public class BareMetalPingServiceImpl extends BareMetalPxeServiceBase implements if (cmd.getPhysicalNetworkId() == null || cmd.getUrl() == null || cmd.getUsername() == null || cmd.getPassword() == null) { throw new IllegalArgumentException("At least one of the required parameters(physical network id, url, username, password) is null"); - } + } pNetwork = _physicalNetworkDao.findById(cmd.getPhysicalNetworkId()); if (pNetwork == null) { @@ -188,7 +188,7 @@ public class BareMetalPingServiceImpl extends BareMetalPxeServiceBase implements HostPodVO pod = _podDao.findById(cmd.getPodId()); if (pod == null) { throw new IllegalArgumentException("Could not find pod with ID: " + cmd.getPodId()); - } + } List pxes = _resourceMgr.listAllUpAndEnabledHosts(Host.Type.BaremetalPxe, null, cmd.getPodId(), zoneId); if (pxes.size() != 0) { diff --git a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetaNetworkGuru.java b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetaNetworkGuru.java index 6d14e3f1a0c..7501882df28 100755 --- a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetaNetworkGuru.java +++ b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetaNetworkGuru.java @@ -76,7 +76,7 @@ public class BaremetaNetworkGuru extends DirectPodBasedNetworkGuru { PodVlanMapDao _podVlanDao; @Override - public void reserve(NicProfile nic, Network network, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) + public void reserve(NicProfile nic, Network network, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException, ConcurrentOperationException { if (dest.getHost().getHypervisorType() != HypervisorType.BareMetal) { super.reserve(nic, network, vm, dest, context); @@ -149,7 +149,7 @@ public class BaremetaNetworkGuru extends DirectPodBasedNetworkGuru { s_logger.debug("Allocated a nic " + nic + " for " + vm); } - private void getBaremetalIp(NicProfile nic, Pod pod, VirtualMachineProfile vm, Network network, String requiredIp) + private void getBaremetalIp(NicProfile nic, Pod pod, VirtualMachineProfile vm, Network network, String requiredIp) throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException, ConcurrentOperationException { DataCenter dc = _dcDao.findById(pod.getDataCenterId()); if (nic.getIp4Address() == null) { diff --git a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalDhcpElement.java b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalDhcpElement.java index 96d702d7501..1eb1c74d2b3 100755 --- a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalDhcpElement.java +++ b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalDhcpElement.java @@ -103,7 +103,7 @@ public class BaremetalDhcpElement extends AdapterBase implements DhcpServiceProv @Override @DB - public boolean prepare(Network network, NicProfile nic, VirtualMachineProfile vm, DeployDestination dest, + public boolean prepare(Network network, NicProfile nic, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException { Host host = dest.getHost(); if (vm.getType() != Type.User || vm.getHypervisorType() != HypervisorType.BareMetal) { @@ -122,7 +122,7 @@ public class BaremetalDhcpElement extends AdapterBase implements DhcpServiceProv } @Override - public boolean release(Network network, NicProfile nic, VirtualMachineProfile vm, ReservationContext context) + public boolean release(Network network, NicProfile nic, VirtualMachineProfile vm, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException { return true; } @@ -158,7 +158,7 @@ public class BaremetalDhcpElement extends AdapterBase implements DhcpServiceProv return true; } - public boolean addDhcpEntry(Network network, NicProfile nic, VirtualMachineProfile vm, DeployDestination dest, + public boolean addDhcpEntry(Network network, NicProfile nic, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException { if (vm.getHypervisorType() != HypervisorType.BareMetal || !canHandle(dest, network.getTrafficType(), network.getGuestType())) { return false; @@ -167,7 +167,7 @@ public class BaremetalDhcpElement extends AdapterBase implements DhcpServiceProv } @Override - public boolean configDhcpSupportForSubnet(Network network, NicProfile nic, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException { + public boolean configDhcpSupportForSubnet(Network network, NicProfile nic, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException { //TODO Add support for baremetal return true; } diff --git a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalDhcpManager.java b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalDhcpManager.java index 9c007318368..8a83c329552 100644 --- a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalDhcpManager.java +++ b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalDhcpManager.java @@ -47,7 +47,7 @@ public interface BaremetalDhcpManager extends Manager, PluggableService { DHCPD, } - boolean addVirtualMachineIntoNetwork(Network network, NicProfile nic, VirtualMachineProfile profile, DeployDestination dest, ReservationContext context) throws ResourceUnavailableException; + boolean addVirtualMachineIntoNetwork(Network network, NicProfile nic, VirtualMachineProfile profile, DeployDestination dest, ReservationContext context) throws ResourceUnavailableException; BaremetalDhcpVO addDchpServer(AddBaremetalDhcpCmd cmd); diff --git a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalDhcpManagerImpl.java b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalDhcpManagerImpl.java index 17e4481c535..1e2ad54157c 100755 --- a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalDhcpManagerImpl.java +++ b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalDhcpManagerImpl.java @@ -133,7 +133,7 @@ public class BaremetalDhcpManagerImpl extends ManagerBase implements BaremetalDh } @Override - public boolean addVirtualMachineIntoNetwork(Network network, NicProfile nic, VirtualMachineProfile profile, + public boolean addVirtualMachineIntoNetwork(Network network, NicProfile nic, VirtualMachineProfile profile, DeployDestination dest, ReservationContext context) throws ResourceUnavailableException { Long zoneId = profile.getVirtualMachine().getDataCenterId(); Long podId = profile.getVirtualMachine().getPodIdToDeployIn(); diff --git a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalKickStartServiceImpl.java b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalKickStartServiceImpl.java index 5858e7ebd61..9a6c1c69a11 100755 --- a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalKickStartServiceImpl.java +++ b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalKickStartServiceImpl.java @@ -5,9 +5,9 @@ // 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 @@ -27,10 +27,11 @@ import java.util.Map; import javax.ejb.Local; import javax.inject.Inject; +import org.apache.log4j.Logger; + import org.apache.cloudstack.api.AddBaremetalKickStartPxeCmd; import org.apache.cloudstack.api.AddBaremetalPxeCmd; import org.apache.cloudstack.api.ListBaremetalPxePingServersCmd; -import org.apache.log4j.Logger; import com.cloud.agent.api.Answer; import com.cloud.agent.api.baremetal.IpmISetBootDevCommand; @@ -62,7 +63,6 @@ import com.cloud.utils.db.Transaction; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.vm.NicProfile; import com.cloud.vm.ReservationContext; -import com.cloud.vm.UserVmVO; import com.cloud.vm.VirtualMachineProfile; @Local(value = BaremetalPxeService.class) @@ -84,7 +84,7 @@ public class BaremetalKickStartServiceImpl extends BareMetalPxeServiceBase imple VMTemplateDao _tmpDao; @Override - public boolean prepare(VirtualMachineProfile profile, NicProfile nic, DeployDestination dest, ReservationContext context) { + public boolean prepare(VirtualMachineProfile profile, NicProfile nic, DeployDestination dest, ReservationContext context) { NetworkVO nwVO = _nwDao.findById(nic.getNetworkId()); SearchCriteriaService sc = SearchCriteria2.create(BaremetalPxeVO.class); sc.addAnd(sc.getEntity().getDeviceType(), Op.EQ, BaremetalPxeType.KICK_START.toString()); diff --git a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalPxeElement.java b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalPxeElement.java index 7b8d528b4b4..82094d8ff46 100755 --- a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalPxeElement.java +++ b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalPxeElement.java @@ -111,7 +111,7 @@ public class BaremetalPxeElement extends AdapterBase implements NetworkElement { @Override @DB - public boolean prepare(Network network, NicProfile nic, VirtualMachineProfile vm, DeployDestination dest, + public boolean prepare(Network network, NicProfile nic, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException { if (vm.getType() != Type.User || vm.getHypervisorType() != HypervisorType.BareMetal) { return false; @@ -138,7 +138,7 @@ public class BaremetalPxeElement extends AdapterBase implements NetworkElement { } @Override - public boolean release(Network network, NicProfile nic, VirtualMachineProfile vm, ReservationContext context) + public boolean release(Network network, NicProfile nic, VirtualMachineProfile vm, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException { return true; } diff --git a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalPxeManager.java b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalPxeManager.java index 7984ddd9750..73243b5657b 100755 --- a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalPxeManager.java +++ b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalPxeManager.java @@ -5,20 +5,20 @@ // 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. -// +// // Automatically generated by addcopyright.py at 01/29/2013 // Apache License, Version 2.0 (the "License"); you may not use this // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// +// // Automatically generated by addcopyright.py at 04/03/2012 package com.cloud.baremetal.networkservice; @@ -37,7 +37,6 @@ import com.cloud.utils.component.Manager; import com.cloud.utils.component.PluggableService; import com.cloud.vm.NicProfile; import com.cloud.vm.ReservationContext; -import com.cloud.vm.UserVmVO; import com.cloud.vm.VirtualMachineProfile; public interface BaremetalPxeManager extends Manager, PluggableService { @@ -58,7 +57,7 @@ public interface BaremetalPxeManager extends Manager, PluggableService { List listPxeServers(ListBaremetalPxePingServersCmd cmd); - boolean addUserData(NicProfile nic, VirtualMachineProfile vm); + boolean addUserData(NicProfile nic, VirtualMachineProfile vm); public static final Network.Service BAREMETAL_PXE_SERVICE = new Network.Service("BaremetalPxeService"); public static final String BAREMETAL_PXE_CAPABILITY = "BaremetalPxe"; diff --git a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalPxeManagerImpl.java b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalPxeManagerImpl.java index 555adf792d0..4e9a11dcf96 100755 --- a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalPxeManagerImpl.java +++ b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalPxeManagerImpl.java @@ -5,20 +5,20 @@ // 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. -// +// // Automatically generated by addcopyright.py at 01/29/2013 // Apache License, Version 2.0 (the "License"); you may not use this // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// +// // Automatically generated by addcopyright.py at 04/03/2012 package com.cloud.baremetal.networkservice; @@ -31,11 +31,12 @@ import javax.ejb.Local; import javax.inject.Inject; import javax.naming.ConfigurationException; +import org.apache.log4j.Logger; + import org.apache.cloudstack.api.AddBaremetalKickStartPxeCmd; import org.apache.cloudstack.api.AddBaremetalPxeCmd; import org.apache.cloudstack.api.AddBaremetalPxePingServerCmd; import org.apache.cloudstack.api.ListBaremetalPxePingServersCmd; -import org.apache.log4j.Logger; import com.cloud.agent.AgentManager; import com.cloud.agent.api.Answer; @@ -183,7 +184,7 @@ public class BaremetalPxeManagerImpl extends ManagerBase implements BaremetalPxe } @Override - public boolean addUserData(NicProfile nic, VirtualMachineProfile profile) { + public boolean addUserData(NicProfile nic, VirtualMachineProfile profile) { UserVmVO vm = (UserVmVO) profile.getVirtualMachine(); _vmDao.loadDetails(vm); diff --git a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalPxeService.java b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalPxeService.java index af6a6c8043c..d74e31d501b 100755 --- a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalPxeService.java +++ b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalPxeService.java @@ -5,20 +5,20 @@ // 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. -// +// // Automatically generated by addcopyright.py at 01/29/2013 // Apache License, Version 2.0 (the "License"); you may not use this // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// +// // Automatically generated by addcopyright.py at 04/03/2012 package com.cloud.baremetal.networkservice; @@ -29,17 +29,15 @@ import org.apache.cloudstack.api.ListBaremetalPxePingServersCmd; import com.cloud.baremetal.database.BaremetalPxeVO; import com.cloud.deploy.DeployDestination; -import com.cloud.host.Host; import com.cloud.uservm.UserVm; import com.cloud.utils.component.Adapter; import com.cloud.vm.NicProfile; import com.cloud.vm.ReservationContext; -import com.cloud.vm.UserVmVO; import com.cloud.vm.VirtualMachineProfile; public interface BaremetalPxeService extends Adapter { - public boolean prepare(VirtualMachineProfile profile, NicProfile nic, DeployDestination dest, ReservationContext context); + public boolean prepare(VirtualMachineProfile profile, NicProfile nic, DeployDestination dest, ReservationContext context); public boolean prepareCreateTemplate(Long pxeServerId, UserVm vm, String templateUrl); @@ -62,5 +60,5 @@ public interface BaremetalPxeService extends Adapter { public static final String PXE_PARAM_PING_STORAGE_SERVER_IP = "pingStorageServerIp"; public static final String PXE_PARAM_PING_ROOT_DIR = "pingDir"; public static final String PXE_PARAM_PING_STORAGE_SERVER_USERNAME = "pingStorageServerUserName"; - public static final String PXE_PARAM_PING_STORAGE_SERVER_PASSWORD = "pingStorageServerPassword"; + public static final String PXE_PARAM_PING_STORAGE_SERVER_PASSWORD = "pingStorageServerPassword"; } diff --git a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalUserdataElement.java b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalUserdataElement.java index 49c6fd9b957..524db26d0ee 100755 --- a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalUserdataElement.java +++ b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalUserdataElement.java @@ -72,7 +72,7 @@ public class BaremetalUserdataElement extends AdapterBase implements NetworkElem } @Override - public boolean addPasswordAndUserdata(Network network, NicProfile nic, VirtualMachineProfile vm, DeployDestination dest, + public boolean addPasswordAndUserdata(Network network, NicProfile nic, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException { if (!canHandle(dest)) { return false; @@ -82,17 +82,17 @@ public class BaremetalUserdataElement extends AdapterBase implements NetworkElem return false; } - return pxeMgr.addUserData(nic, (VirtualMachineProfile) vm); + return pxeMgr.addUserData(nic, (VirtualMachineProfile) vm); } @Override - public boolean savePassword(Network network, NicProfile nic, VirtualMachineProfile vm) throws ResourceUnavailableException { + public boolean savePassword(Network network, NicProfile nic, VirtualMachineProfile vm) throws ResourceUnavailableException { // TODO Auto-generated method stub return false; } @Override - public boolean saveSSHKey(Network network, NicProfile nic, VirtualMachineProfile vm, String SSHPublicKey) throws ResourceUnavailableException { + public boolean saveSSHKey(Network network, NicProfile nic, VirtualMachineProfile vm, String SSHPublicKey) throws ResourceUnavailableException { // TODO Auto-generated method stub return false; } @@ -115,14 +115,14 @@ public class BaremetalUserdataElement extends AdapterBase implements NetworkElem } @Override - public boolean prepare(Network network, NicProfile nic, VirtualMachineProfile vm, DeployDestination dest, + public boolean prepare(Network network, NicProfile nic, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException { // TODO Auto-generated method stub return false; } @Override - public boolean release(Network network, NicProfile nic, VirtualMachineProfile vm, ReservationContext context) + public boolean release(Network network, NicProfile nic, VirtualMachineProfile vm, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException { // TODO Auto-generated method stub return false; @@ -154,7 +154,7 @@ public class BaremetalUserdataElement extends AdapterBase implements NetworkElem @Override - public boolean saveUserData(Network network, NicProfile nic, VirtualMachineProfile vm) + public boolean saveUserData(Network network, NicProfile nic, VirtualMachineProfile vm) throws ResourceUnavailableException { // TODO Auto-generated method stub return false; diff --git a/plugins/hypervisors/ovm/src/com/cloud/ovm/hypervisor/OvmGuru.java b/plugins/hypervisors/ovm/src/com/cloud/ovm/hypervisor/OvmGuru.java index cb2cb13f915..206454b1240 100755 --- a/plugins/hypervisors/ovm/src/com/cloud/ovm/hypervisor/OvmGuru.java +++ b/plugins/hypervisors/ovm/src/com/cloud/ovm/hypervisor/OvmGuru.java @@ -20,12 +20,11 @@ import javax.ejb.Local; import javax.inject.Inject; import com.cloud.agent.api.to.VirtualMachineTO; +import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.hypervisor.HypervisorGuru; import com.cloud.hypervisor.HypervisorGuruBase; -import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.storage.GuestOSVO; import com.cloud.storage.dao.GuestOSDao; -import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachineProfile; @Local(value=HypervisorGuru.class) @@ -41,8 +40,7 @@ public class OvmGuru extends HypervisorGuruBase implements HypervisorGuru { } @Override - public VirtualMachineTO implement( - VirtualMachineProfile vm) { + public VirtualMachineTO implement(VirtualMachineProfile vm) { VirtualMachineTO to = toVirtualMachineTO(vm); to.setBootloader(vm.getBootLoaderType()); diff --git a/plugins/hypervisors/simulator/src/com/cloud/simulator/SimulatorGuru.java b/plugins/hypervisors/simulator/src/com/cloud/simulator/SimulatorGuru.java index 57a38f1d3d8..8f36e1663e6 100644 --- a/plugins/hypervisors/simulator/src/com/cloud/simulator/SimulatorGuru.java +++ b/plugins/hypervisors/simulator/src/com/cloud/simulator/SimulatorGuru.java @@ -16,18 +16,17 @@ // under the License. package com.cloud.simulator; +import javax.ejb.Local; +import javax.inject.Inject; + import com.cloud.agent.api.to.VirtualMachineTO; import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.hypervisor.HypervisorGuru; import com.cloud.hypervisor.HypervisorGuruBase; import com.cloud.storage.GuestOSVO; import com.cloud.storage.dao.GuestOSDao; -import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachineProfile; -import javax.ejb.Local; -import javax.inject.Inject; - @Local(value=HypervisorGuru.class) public class SimulatorGuru extends HypervisorGuruBase implements HypervisorGuru { @@ -43,7 +42,7 @@ public class SimulatorGuru extends HypervisorGuruBase implements HypervisorGuru } @Override - public VirtualMachineTO implement(VirtualMachineProfile vm) { + public VirtualMachineTO implement(VirtualMachineProfile vm) { VirtualMachineTO to = toVirtualMachineTO(vm); // Determine the VM's OS description diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/guru/VMwareGuru.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/guru/VMwareGuru.java index b86b6d97b6f..78a596e9266 100644 --- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/guru/VMwareGuru.java +++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/guru/VMwareGuru.java @@ -122,7 +122,7 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru { } @Override - public VirtualMachineTO implement(VirtualMachineProfile vm) { + public VirtualMachineTO implement(VirtualMachineProfile vm) { VirtualMachineTO to = toVirtualMachineTO(vm); to.setBootloader(BootloaderType.HVM); diff --git a/plugins/hypervisors/vmware/src/com/cloud/network/element/CiscoNexusVSMElement.java b/plugins/hypervisors/vmware/src/com/cloud/network/element/CiscoNexusVSMElement.java index 4629b6c2d3e..e1f4a274e29 100644 --- a/plugins/hypervisors/vmware/src/com/cloud/network/element/CiscoNexusVSMElement.java +++ b/plugins/hypervisors/vmware/src/com/cloud/network/element/CiscoNexusVSMElement.java @@ -100,7 +100,7 @@ public class CiscoNexusVSMElement extends CiscoNexusVSMDeviceManagerImpl impleme @Override public boolean prepare(Network network, NicProfile nic, - VirtualMachineProfile vm, + VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException { @@ -109,7 +109,7 @@ public class CiscoNexusVSMElement extends CiscoNexusVSMDeviceManagerImpl impleme @Override public boolean release(Network network, NicProfile nic, - VirtualMachineProfile vm, + VirtualMachineProfile vm, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException { return true; diff --git a/plugins/hypervisors/xen/src/com/cloud/hypervisor/XenServerGuru.java b/plugins/hypervisors/xen/src/com/cloud/hypervisor/XenServerGuru.java index c52020e84e8..6dd6f3fb422 100644 --- a/plugins/hypervisors/xen/src/com/cloud/hypervisor/XenServerGuru.java +++ b/plugins/hypervisors/xen/src/com/cloud/hypervisor/XenServerGuru.java @@ -11,7 +11,7 @@ // 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 +// KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. package com.cloud.hypervisor; @@ -24,9 +24,7 @@ import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.storage.GuestOSVO; import com.cloud.storage.dao.GuestOSDao; import com.cloud.template.VirtualMachineTemplate.BootloaderType; -import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachineProfile; -import com.cloud.vm.VirtualMachineProfileImpl; @Local(value=HypervisorGuru.class) public class XenServerGuru extends HypervisorGuruBase implements HypervisorGuru { @@ -42,7 +40,7 @@ public class XenServerGuru extends HypervisorGuruBase implements HypervisorGuru } @Override - public VirtualMachineTO implement(VirtualMachineProfile vm) { + public VirtualMachineTO implement(VirtualMachineProfile vm) { BootloaderType bt = BootloaderType.PyGrub; if (vm.getBootLoaderType() == BootloaderType.CD) { bt = vm.getBootLoaderType(); diff --git a/plugins/network-elements/bigswitch-vns/src/com/cloud/network/element/BigSwitchVnsElement.java b/plugins/network-elements/bigswitch-vns/src/com/cloud/network/element/BigSwitchVnsElement.java index 411feab7339..54623e9d080 100644 --- a/plugins/network-elements/bigswitch-vns/src/com/cloud/network/element/BigSwitchVnsElement.java +++ b/plugins/network-elements/bigswitch-vns/src/com/cloud/network/element/BigSwitchVnsElement.java @@ -182,7 +182,7 @@ public class BigSwitchVnsElement extends AdapterBase implements @Override public boolean prepare(Network network, NicProfile nic, - VirtualMachineProfile vm, + VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException { @@ -228,7 +228,7 @@ public class BigSwitchVnsElement extends AdapterBase implements @Override public boolean release(Network network, NicProfile nic, - VirtualMachineProfile vm, + VirtualMachineProfile vm, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException { diff --git a/plugins/network-elements/bigswitch-vns/src/com/cloud/network/guru/BigSwitchVnsGuestNetworkGuru.java b/plugins/network-elements/bigswitch-vns/src/com/cloud/network/guru/BigSwitchVnsGuestNetworkGuru.java index f660b7c7838..52303a43fa1 100644 --- a/plugins/network-elements/bigswitch-vns/src/com/cloud/network/guru/BigSwitchVnsGuestNetworkGuru.java +++ b/plugins/network-elements/bigswitch-vns/src/com/cloud/network/guru/BigSwitchVnsGuestNetworkGuru.java @@ -211,7 +211,7 @@ public class BigSwitchVnsGuestNetworkGuru extends GuestNetworkGuru { @Override public void reserve(NicProfile nic, Network network, - VirtualMachineProfile vm, + VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException { @@ -221,7 +221,7 @@ public class BigSwitchVnsGuestNetworkGuru extends GuestNetworkGuru { @Override public boolean release(NicProfile nic, - VirtualMachineProfile vm, + VirtualMachineProfile vm, String reservationId) { // TODO Auto-generated method stub return super.release(nic, vm, reservationId); diff --git a/plugins/network-elements/cisco-vnmc/src/com/cloud/network/element/CiscoVnmcElement.java b/plugins/network-elements/cisco-vnmc/src/com/cloud/network/element/CiscoVnmcElement.java index de52c21d405..5291ad18ab9 100644 --- a/plugins/network-elements/cisco-vnmc/src/com/cloud/network/element/CiscoVnmcElement.java +++ b/plugins/network-elements/cisco-vnmc/src/com/cloud/network/element/CiscoVnmcElement.java @@ -422,7 +422,7 @@ public class CiscoVnmcElement extends AdapterBase implements SourceNatServicePro @Override public boolean prepare(Network network, NicProfile nic, - VirtualMachineProfile vm, + VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException { @@ -441,7 +441,7 @@ public class CiscoVnmcElement extends AdapterBase implements SourceNatServicePro @Override public boolean release(Network network, NicProfile nic, - VirtualMachineProfile vm, + VirtualMachineProfile vm, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException { return true; diff --git a/plugins/network-elements/dns-notifier/src/org/apache/cloudstack/network/element/DnsNotifier.java b/plugins/network-elements/dns-notifier/src/org/apache/cloudstack/network/element/DnsNotifier.java index c421344baba..4a403c4e658 100644 --- a/plugins/network-elements/dns-notifier/src/org/apache/cloudstack/network/element/DnsNotifier.java +++ b/plugins/network-elements/dns-notifier/src/org/apache/cloudstack/network/element/DnsNotifier.java @@ -71,7 +71,7 @@ public class DnsNotifier extends AdapterBase implements NetworkElement { } @Override - public boolean prepare(Network network, NicProfile nic, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException, + public boolean prepare(Network network, NicProfile nic, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException { // signal to the dns server that this vm is up and running and set the ip address to hostname mapping. vm.getHostName(); @@ -81,7 +81,7 @@ public class DnsNotifier extends AdapterBase implements NetworkElement { } @Override - public boolean release(Network network, NicProfile nic, VirtualMachineProfile vm, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException { + public boolean release(Network network, NicProfile nic, VirtualMachineProfile vm, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException { vm.getHostName(); nic.getIp4Address(); nic.getIp6Address(); diff --git a/plugins/network-elements/elastic-loadbalancer/src/com/cloud/network/element/ElasticLoadBalancerElement.java b/plugins/network-elements/elastic-loadbalancer/src/com/cloud/network/element/ElasticLoadBalancerElement.java index 8b1b4140a8d..fd7274d8e2b 100644 --- a/plugins/network-elements/elastic-loadbalancer/src/com/cloud/network/element/ElasticLoadBalancerElement.java +++ b/plugins/network-elements/elastic-loadbalancer/src/com/cloud/network/element/ElasticLoadBalancerElement.java @@ -123,14 +123,14 @@ public class ElasticLoadBalancerElement extends AdapterBase implements LoadBalan } @Override - public boolean prepare(Network network, NicProfile nic, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) + public boolean prepare(Network network, NicProfile nic, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException { return true; } @Override - public boolean release(Network network, NicProfile nic, VirtualMachineProfile vm, ReservationContext context) throws ConcurrentOperationException, + public boolean release(Network network, NicProfile nic, VirtualMachineProfile vm, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException { return true; diff --git a/plugins/network-elements/elastic-loadbalancer/src/com/cloud/network/lb/ElasticLoadBalancerManagerImpl.java b/plugins/network-elements/elastic-loadbalancer/src/com/cloud/network/lb/ElasticLoadBalancerManagerImpl.java index 24ec87a27b6..8d32f4369a2 100644 --- a/plugins/network-elements/elastic-loadbalancer/src/com/cloud/network/lb/ElasticLoadBalancerManagerImpl.java +++ b/plugins/network-elements/elastic-loadbalancer/src/com/cloud/network/lb/ElasticLoadBalancerManagerImpl.java @@ -127,7 +127,6 @@ import com.cloud.utils.net.Ip; import com.cloud.vm.DomainRouterVO; import com.cloud.vm.NicProfile; import com.cloud.vm.ReservationContext; -import com.cloud.vm.VMInstanceVO; import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachine.State; import com.cloud.vm.VirtualMachineGuru; @@ -783,8 +782,7 @@ ElasticLoadBalancerManager, VirtualMachineGuru { } @Override - public boolean finalizeVirtualMachineProfile(VirtualMachineProfile profile, DeployDestination dest, ReservationContext context) { - DomainRouterVO elbVm = profile.getVirtualMachine(); + public boolean finalizeVirtualMachineProfile(VirtualMachineProfile profile, DeployDestination dest, ReservationContext context) { List elbNics = profile.getNics(); Long guestNtwkId = null; @@ -864,8 +862,8 @@ ElasticLoadBalancerManager, VirtualMachineGuru { } @Override - public boolean finalizeDeployment(Commands cmds, VirtualMachineProfile profile, DeployDestination dest, ReservationContext context) throws ResourceUnavailableException { - DomainRouterVO elbVm = profile.getVirtualMachine(); + public boolean finalizeDeployment(Commands cmds, VirtualMachineProfile profile, DeployDestination dest, ReservationContext context) throws ResourceUnavailableException { + DomainRouterVO elbVm = _routerDao.findById(profile.getVirtualMachine().getId()); List nics = profile.getNics(); for (NicProfile nic : nics) { @@ -885,7 +883,7 @@ ElasticLoadBalancerManager, VirtualMachineGuru { } @Override - public boolean finalizeStart(VirtualMachineProfile profile, long hostId, Commands cmds, ReservationContext context) { + public boolean finalizeStart(VirtualMachineProfile profile, long hostId, Commands cmds, ReservationContext context) { CheckSshAnswer answer = (CheckSshAnswer) cmds.getAnswer("checkSsh"); if (answer == null || !answer.getResult()) { s_logger.warn("Unable to ssh to the ELB VM: " + answer.getDetails()); @@ -896,8 +894,8 @@ ElasticLoadBalancerManager, VirtualMachineGuru { } @Override - public boolean finalizeCommandsOnStart(Commands cmds, VirtualMachineProfile profile) { - DomainRouterVO elbVm = profile.getVirtualMachine(); + public boolean finalizeCommandsOnStart(Commands cmds, VirtualMachineProfile profile) { + DomainRouterVO elbVm = _routerDao.findById(profile.getVirtualMachine().getId()); DataCenterVO dcVo = _dcDao.findById(elbVm.getDataCenterId()); NicProfile controlNic = null; @@ -950,10 +948,9 @@ ElasticLoadBalancerManager, VirtualMachineGuru { } @Override - public void finalizeStop(VirtualMachineProfile profile, StopAnswer answer) { + public void finalizeStop(VirtualMachineProfile profile, StopAnswer answer) { if (answer != null) { - VMInstanceVO vm = profile.getVirtualMachine(); - DomainRouterVO elbVm = _routerDao.findById(vm.getId()); + DomainRouterVO elbVm = _routerDao.findById(profile.getVirtualMachine().getId()); processStopOrRebootAnswer(elbVm, answer); } } @@ -969,7 +966,7 @@ ElasticLoadBalancerManager, VirtualMachineGuru { } @Override - public void prepareStop(VirtualMachineProfile profile) { + public void prepareStop(VirtualMachineProfile profile) { } } diff --git a/plugins/network-elements/f5/src/com/cloud/network/element/F5ExternalLoadBalancerElement.java b/plugins/network-elements/f5/src/com/cloud/network/element/F5ExternalLoadBalancerElement.java index 80b42e030d8..8ea4d61d9d9 100644 --- a/plugins/network-elements/f5/src/com/cloud/network/element/F5ExternalLoadBalancerElement.java +++ b/plugins/network-elements/f5/src/com/cloud/network/element/F5ExternalLoadBalancerElement.java @@ -159,13 +159,13 @@ public class F5ExternalLoadBalancerElement extends ExternalLoadBalancerDeviceMan } @Override - public boolean prepare(Network config, NicProfile nic, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException, + public boolean prepare(Network config, NicProfile nic, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException, InsufficientNetworkCapacityException, ResourceUnavailableException { return true; } @Override - public boolean release(Network config, NicProfile nic, VirtualMachineProfile vm, ReservationContext context) { + public boolean release(Network config, NicProfile nic, VirtualMachineProfile vm, ReservationContext context) { return true; } diff --git a/plugins/network-elements/internal-loadbalancer/src/org/apache/cloudstack/network/element/InternalLoadBalancerElement.java b/plugins/network-elements/internal-loadbalancer/src/org/apache/cloudstack/network/element/InternalLoadBalancerElement.java index 18ac13baef4..2376038b135 100644 --- a/plugins/network-elements/internal-loadbalancer/src/org/apache/cloudstack/network/element/InternalLoadBalancerElement.java +++ b/plugins/network-elements/internal-loadbalancer/src/org/apache/cloudstack/network/element/InternalLoadBalancerElement.java @@ -170,7 +170,7 @@ public class InternalLoadBalancerElement extends AdapterBase implements LoadBala @Override - public boolean prepare(Network network, NicProfile nic, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException, + public boolean prepare(Network network, NicProfile nic, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException { if (!canHandle(network, null)) { @@ -218,7 +218,7 @@ public class InternalLoadBalancerElement extends AdapterBase implements LoadBala } @Override - public boolean release(Network network, NicProfile nic, VirtualMachineProfile vm, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException { + public boolean release(Network network, NicProfile nic, VirtualMachineProfile vm, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException { return true; } diff --git a/plugins/network-elements/internal-loadbalancer/src/org/apache/cloudstack/network/lb/InternalLoadBalancerVMManagerImpl.java b/plugins/network-elements/internal-loadbalancer/src/org/apache/cloudstack/network/lb/InternalLoadBalancerVMManagerImpl.java index 90ff9bc0b49..481bbca2458 100644 --- a/plugins/network-elements/internal-loadbalancer/src/org/apache/cloudstack/network/lb/InternalLoadBalancerVMManagerImpl.java +++ b/plugins/network-elements/internal-loadbalancer/src/org/apache/cloudstack/network/lb/InternalLoadBalancerVMManagerImpl.java @@ -156,7 +156,7 @@ public class InternalLoadBalancerVMManagerImpl extends ManagerBase implements } @Override - public boolean finalizeVirtualMachineProfile(VirtualMachineProfile profile, + public boolean finalizeVirtualMachineProfile(VirtualMachineProfile profile, DeployDestination dest, ReservationContext context) { //Internal LB vm starts up with 2 Nics @@ -231,8 +231,9 @@ public class InternalLoadBalancerVMManagerImpl extends ManagerBase implements } @Override - public boolean finalizeDeployment(Commands cmds, VirtualMachineProfile profile, DeployDestination dest, ReservationContext context) throws ResourceUnavailableException { - DomainRouterVO internalLbVm = profile.getVirtualMachine(); + public boolean finalizeDeployment(Commands cmds, VirtualMachineProfile profile, DeployDestination dest, ReservationContext context) throws ResourceUnavailableException { + + DomainRouterVO internalLbVm = _internalLbVmDao.findById(profile.getId()); List nics = profile.getNics(); for (NicProfile nic : nics) { @@ -248,8 +249,8 @@ public class InternalLoadBalancerVMManagerImpl extends ManagerBase implements } @Override - public boolean finalizeStart(VirtualMachineProfile profile, long hostId, Commands cmds, ReservationContext context) { - DomainRouterVO internalLbVm = profile.getVirtualMachine(); + public boolean finalizeStart(VirtualMachineProfile profile, long hostId, Commands cmds, ReservationContext context) { + DomainRouterVO internalLbVm = _internalLbVmDao.findById(profile.getId()); boolean result = true; @@ -297,8 +298,8 @@ public class InternalLoadBalancerVMManagerImpl extends ManagerBase implements } @Override - public boolean finalizeCommandsOnStart(Commands cmds, VirtualMachineProfile profile) { - DomainRouterVO internalLbVm = profile.getVirtualMachine(); + public boolean finalizeCommandsOnStart(Commands cmds, VirtualMachineProfile profile) { + DomainRouterVO internalLbVm = _internalLbVmDao.findById(profile.getId()); NicProfile controlNic = getNicProfileByTrafficType(profile, TrafficType.Control); if (controlNic == null) { @@ -334,7 +335,7 @@ public class InternalLoadBalancerVMManagerImpl extends ManagerBase implements } @Override - public void finalizeStop(VirtualMachineProfile profile, StopAnswer answer) { + public void finalizeStop(VirtualMachineProfile profile, StopAnswer answer) { } @Override @@ -342,7 +343,7 @@ public class InternalLoadBalancerVMManagerImpl extends ManagerBase implements } @Override - public void prepareStop(VirtualMachineProfile profile) { + public void prepareStop(VirtualMachineProfile profile) { } @Override @@ -391,7 +392,7 @@ public class InternalLoadBalancerVMManagerImpl extends ManagerBase implements return _name; } - protected NicProfile getNicProfileByTrafficType(VirtualMachineProfile profile, TrafficType trafficType) { + protected NicProfile getNicProfileByTrafficType(VirtualMachineProfile profile, TrafficType trafficType) { for (NicProfile nic : profile.getNics()) { if (nic.getTrafficType() == trafficType && nic.getIp4Address() != null) { return nic; @@ -400,7 +401,7 @@ public class InternalLoadBalancerVMManagerImpl extends ManagerBase implements return null; } - protected void finalizeSshAndVersionOnStart(Commands cmds, VirtualMachineProfile profile, DomainRouterVO router, NicProfile controlNic) { + protected void finalizeSshAndVersionOnStart(Commands cmds, VirtualMachineProfile profile, DomainRouterVO router, NicProfile controlNic) { cmds.addCommand("checkSsh", new CheckSshCommand(profile.getInstanceName(), controlNic.getIp4Address(), 3922)); // Update internal lb vm template/scripts version diff --git a/plugins/network-elements/juniper-srx/src/com/cloud/network/element/JuniperSRXExternalFirewallElement.java b/plugins/network-elements/juniper-srx/src/com/cloud/network/element/JuniperSRXExternalFirewallElement.java index c00d99abf88..85d6de6817b 100644 --- a/plugins/network-elements/juniper-srx/src/com/cloud/network/element/JuniperSRXExternalFirewallElement.java +++ b/plugins/network-elements/juniper-srx/src/com/cloud/network/element/JuniperSRXExternalFirewallElement.java @@ -145,13 +145,13 @@ PortForwardingServiceProvider, RemoteAccessVPNServiceProvider, IpDeployer, Junip } @Override - public boolean prepare(Network config, NicProfile nic, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException, + public boolean prepare(Network config, NicProfile nic, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException, InsufficientNetworkCapacityException, ResourceUnavailableException { return true; } @Override - public boolean release(Network config, NicProfile nic, VirtualMachineProfile vm, ReservationContext context) { + public boolean release(Network config, NicProfile nic, VirtualMachineProfile vm, ReservationContext context) { return true; } diff --git a/plugins/network-elements/midonet/src/com/cloud/network/element/MidoNetElement.java b/plugins/network-elements/midonet/src/com/cloud/network/element/MidoNetElement.java index ab6a6def405..b02e51ddb2c 100644 --- a/plugins/network-elements/midonet/src/com/cloud/network/element/MidoNetElement.java +++ b/plugins/network-elements/midonet/src/com/cloud/network/element/MidoNetElement.java @@ -391,7 +391,7 @@ public class MidoNetElement extends AdapterBase implements * From interface DHCPServiceProvider */ @Override - public boolean addDhcpEntry(Network network, NicProfile nic, VirtualMachineProfile vm, + public boolean addDhcpEntry(Network network, NicProfile nic, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException { @@ -455,7 +455,7 @@ public class MidoNetElement extends AdapterBase implements } @Override - public boolean configDhcpSupportForSubnet(Network network, NicProfile nic, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException { + public boolean configDhcpSupportForSubnet(Network network, NicProfile nic, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException { return false; //To change body of implemented methods use File | Settings | File Templates. } @@ -768,7 +768,7 @@ public class MidoNetElement extends AdapterBase implements } @Override - public boolean prepare(Network network, NicProfile nic, VirtualMachineProfile vm, + public boolean prepare(Network network, NicProfile nic, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException { s_logger.debug("prepare called with network: " + network.toString() + " nic: " + nic.toString() + " vm: " + vm.toString()); @@ -832,7 +832,7 @@ public class MidoNetElement extends AdapterBase implements } @Override - public boolean release(Network network, NicProfile nic, VirtualMachineProfile vm, + public boolean release(Network network, NicProfile nic, VirtualMachineProfile vm, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException { s_logger.debug("release called with network: " + network.toString() + " nic: " + nic.toString() + " vm: " + vm.toString()); diff --git a/plugins/network-elements/midonet/src/com/cloud/network/guru/MidoNetGuestNetworkGuru.java b/plugins/network-elements/midonet/src/com/cloud/network/guru/MidoNetGuestNetworkGuru.java index d57affc5827..ac77cf6e07e 100644 --- a/plugins/network-elements/midonet/src/com/cloud/network/guru/MidoNetGuestNetworkGuru.java +++ b/plugins/network-elements/midonet/src/com/cloud/network/guru/MidoNetGuestNetworkGuru.java @@ -145,7 +145,7 @@ public class MidoNetGuestNetworkGuru extends GuestNetworkGuru { @Override public void reserve(NicProfile nic, Network network, - VirtualMachineProfile vm, + VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException { @@ -156,7 +156,7 @@ public class MidoNetGuestNetworkGuru extends GuestNetworkGuru { @Override public boolean release(NicProfile nic, - VirtualMachineProfile vm, + VirtualMachineProfile vm, String reservationId) { s_logger.debug("release called with nic: " + nic.toString() + " vm: " + vm.toString()); return super.release(nic, vm, reservationId); diff --git a/plugins/network-elements/midonet/src/com/cloud/network/guru/MidoNetPublicNetworkGuru.java b/plugins/network-elements/midonet/src/com/cloud/network/guru/MidoNetPublicNetworkGuru.java index 1daf0bad040..38da02bf6f9 100644 --- a/plugins/network-elements/midonet/src/com/cloud/network/guru/MidoNetPublicNetworkGuru.java +++ b/plugins/network-elements/midonet/src/com/cloud/network/guru/MidoNetPublicNetworkGuru.java @@ -78,7 +78,7 @@ public class MidoNetPublicNetworkGuru extends PublicNetworkGuru { super(); } - protected void getIp(NicProfile nic, DataCenter dc, VirtualMachineProfile vm, Network network) throws InsufficientVirtualNetworkCapcityException, + protected void getIp(NicProfile nic, DataCenter dc, VirtualMachineProfile vm, Network network) throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException, ConcurrentOperationException { if (nic.getIp4Address() == null) { PublicIp ip = _networkMgr.assignPublicIpAddress(dc.getId(), null, vm.getOwner(), Vlan.VlanType.VirtualNetwork, null, null, false); @@ -117,7 +117,7 @@ public class MidoNetPublicNetworkGuru extends PublicNetworkGuru { } @Override - public NicProfile allocate(Network network, NicProfile nic, VirtualMachineProfile vm) + public NicProfile allocate(Network network, NicProfile nic, VirtualMachineProfile vm) throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException, ConcurrentOperationException { @@ -148,7 +148,7 @@ public class MidoNetPublicNetworkGuru extends PublicNetworkGuru { } @Override - public void reserve(NicProfile nic, Network network, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) + public void reserve(NicProfile nic, Network network, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException, ConcurrentOperationException { s_logger.debug("reserve called with network: " + network.toString() + " nic: " + nic.toString() + " vm: " + vm.toString()); if (nic.getIp4Address() == null) { @@ -157,7 +157,7 @@ public class MidoNetPublicNetworkGuru extends PublicNetworkGuru { } @Override - public boolean release(NicProfile nic, VirtualMachineProfile vm, String reservationId) { + public boolean release(NicProfile nic, VirtualMachineProfile vm, String reservationId) { s_logger.debug("release called with nic: " + nic.toString() + " vm: " + vm.toString()); return true; } @@ -189,7 +189,7 @@ public class MidoNetPublicNetworkGuru extends PublicNetworkGuru { } @Override @DB - public void deallocate(Network network, NicProfile nic, VirtualMachineProfile vm) { + public void deallocate(Network network, NicProfile nic, VirtualMachineProfile vm) { s_logger.debug("deallocate called with network: " + network.toString() + " nic: " + nic.toString() + " vm: " + vm.toString()); if (s_logger.isDebugEnabled()) { s_logger.debug("public network deallocate network: networkId: " + nic.getNetworkId() + ", ip: " + nic.getIp4Address()); diff --git a/plugins/network-elements/midonet/test/com/cloud/network/element/MidoNetElementTest.java b/plugins/network-elements/midonet/test/com/cloud/network/element/MidoNetElementTest.java index a7d96b0c310..9023c6eefce 100644 --- a/plugins/network-elements/midonet/test/com/cloud/network/element/MidoNetElementTest.java +++ b/plugins/network-elements/midonet/test/com/cloud/network/element/MidoNetElementTest.java @@ -97,8 +97,8 @@ public class MidoNetElementTest extends TestCase { //mockVm @SuppressWarnings("unchecked") - VirtualMachineProfile mockVm = - (VirtualMachineProfile)mock(VirtualMachineProfile.class); + VirtualMachineProfile mockVm = + (VirtualMachineProfile)mock(VirtualMachineProfile.class); when(mockVm.getType()).thenReturn(VirtualMachine.Type.User); MidoNetElement elem = new MidoNetElement(); diff --git a/plugins/network-elements/netscaler/src/com/cloud/network/element/NetscalerElement.java b/plugins/network-elements/netscaler/src/com/cloud/network/element/NetscalerElement.java index e7f634772fc..fa51fdcbb8b 100644 --- a/plugins/network-elements/netscaler/src/com/cloud/network/element/NetscalerElement.java +++ b/plugins/network-elements/netscaler/src/com/cloud/network/element/NetscalerElement.java @@ -200,13 +200,13 @@ public class NetscalerElement extends ExternalLoadBalancerDeviceManagerImpl impl } @Override - public boolean prepare(Network config, NicProfile nic, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException, + public boolean prepare(Network config, NicProfile nic, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException, InsufficientNetworkCapacityException, ResourceUnavailableException { return true; } @Override - public boolean release(Network config, NicProfile nic, VirtualMachineProfile vm, ReservationContext context) { + public boolean release(Network config, NicProfile nic, VirtualMachineProfile vm, ReservationContext context) { return true; } diff --git a/plugins/network-elements/nicira-nvp/src/com/cloud/network/element/NiciraNvpElement.java b/plugins/network-elements/nicira-nvp/src/com/cloud/network/element/NiciraNvpElement.java index c22f669796c..754e7b1c1db 100644 --- a/plugins/network-elements/nicira-nvp/src/com/cloud/network/element/NiciraNvpElement.java +++ b/plugins/network-elements/nicira-nvp/src/com/cloud/network/element/NiciraNvpElement.java @@ -296,7 +296,7 @@ NiciraNvpElementService, ResourceStateAdapter, IpDeployer { @Override public boolean prepare(Network network, NicProfile nic, - VirtualMachineProfile vm, + VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException { @@ -373,7 +373,7 @@ NiciraNvpElementService, ResourceStateAdapter, IpDeployer { @Override public boolean release(Network network, NicProfile nic, - VirtualMachineProfile vm, + VirtualMachineProfile vm, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException { diff --git a/plugins/network-elements/nicira-nvp/src/com/cloud/network/guru/NiciraNvpGuestNetworkGuru.java b/plugins/network-elements/nicira-nvp/src/com/cloud/network/guru/NiciraNvpGuestNetworkGuru.java index b78d165ddd6..ff238edc600 100644 --- a/plugins/network-elements/nicira-nvp/src/com/cloud/network/guru/NiciraNvpGuestNetworkGuru.java +++ b/plugins/network-elements/nicira-nvp/src/com/cloud/network/guru/NiciraNvpGuestNetworkGuru.java @@ -212,7 +212,7 @@ public class NiciraNvpGuestNetworkGuru extends GuestNetworkGuru { @Override public void reserve(NicProfile nic, Network network, - VirtualMachineProfile vm, + VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException { @@ -222,7 +222,7 @@ public class NiciraNvpGuestNetworkGuru extends GuestNetworkGuru { @Override public boolean release(NicProfile nic, - VirtualMachineProfile vm, + VirtualMachineProfile vm, String reservationId) { // TODO Auto-generated method stub return super.release(nic, vm, reservationId); diff --git a/plugins/network-elements/ovs/src/com/cloud/network/element/OvsElement.java b/plugins/network-elements/ovs/src/com/cloud/network/element/OvsElement.java index 40be5ff7b45..0366143a7e7 100644 --- a/plugins/network-elements/ovs/src/com/cloud/network/element/OvsElement.java +++ b/plugins/network-elements/ovs/src/com/cloud/network/element/OvsElement.java @@ -72,7 +72,7 @@ public class OvsElement extends AdapterBase implements NetworkElement { @Override public boolean prepare(Network network, NicProfile nic, - VirtualMachineProfile vm, + VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException { @@ -92,7 +92,7 @@ public class OvsElement extends AdapterBase implements NetworkElement { @Override public boolean release(Network network, NicProfile nic, - VirtualMachineProfile vm, + VirtualMachineProfile vm, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException { if (nic.getBroadcastType() != Networks.BroadcastDomainType.Vswitch) { diff --git a/plugins/network-elements/ovs/src/com/cloud/network/ovs/OvsTunnelManager.java b/plugins/network-elements/ovs/src/com/cloud/network/ovs/OvsTunnelManager.java index 2a2a935d65a..36fd25fbea3 100644 --- a/plugins/network-elements/ovs/src/com/cloud/network/ovs/OvsTunnelManager.java +++ b/plugins/network-elements/ovs/src/com/cloud/network/ovs/OvsTunnelManager.java @@ -26,7 +26,7 @@ public interface OvsTunnelManager extends Manager { boolean isOvsTunnelEnabled(); - public void VmCheckAndCreateTunnel(VirtualMachineProfile vm, + public void VmCheckAndCreateTunnel(VirtualMachineProfile vm, Network nw, DeployDestination dest); public void CheckAndDestroyTunnel(VirtualMachine vm, Network nw); diff --git a/plugins/network-elements/ovs/src/com/cloud/network/ovs/OvsTunnelManagerImpl.java b/plugins/network-elements/ovs/src/com/cloud/network/ovs/OvsTunnelManagerImpl.java index b1ecaaccd76..d3db89fb1c5 100644 --- a/plugins/network-elements/ovs/src/com/cloud/network/ovs/OvsTunnelManagerImpl.java +++ b/plugins/network-elements/ovs/src/com/cloud/network/ovs/OvsTunnelManagerImpl.java @@ -383,7 +383,7 @@ public class OvsTunnelManagerImpl extends ManagerBase implements OvsTunnelManage @Override public void VmCheckAndCreateTunnel( - VirtualMachineProfile vm, + VirtualMachineProfile vm, Network nw, DeployDestination dest) { CheckAndCreateTunnel(vm.getVirtualMachine(), nw, dest); } diff --git a/plugins/network-elements/stratosphere-ssp/src/org/apache/cloudstack/network/element/SspElement.java b/plugins/network-elements/stratosphere-ssp/src/org/apache/cloudstack/network/element/SspElement.java index 823c16b15e8..6e1461a9778 100644 --- a/plugins/network-elements/stratosphere-ssp/src/org/apache/cloudstack/network/element/SspElement.java +++ b/plugins/network-elements/stratosphere-ssp/src/org/apache/cloudstack/network/element/SspElement.java @@ -509,7 +509,7 @@ public class SspElement extends AdapterBase implements ConnectivityProvider, Ssp */ @Override public boolean prepare(Network network, NicProfile nic, - VirtualMachineProfile vm, + VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException { @@ -526,7 +526,7 @@ public class SspElement extends AdapterBase implements ConnectivityProvider, Ssp */ @Override public boolean release(Network network, NicProfile nic, - VirtualMachineProfile vm, + VirtualMachineProfile vm, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException { s_logger.trace("release"); @@ -569,7 +569,7 @@ public class SspElement extends AdapterBase implements ConnectivityProvider, Ssp @Override public boolean prepareMigration(NicProfile nic, Network network, - VirtualMachineProfile vm, + VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) { try { prepare(network, nic, vm, dest, context); @@ -588,7 +588,7 @@ public class SspElement extends AdapterBase implements ConnectivityProvider, Ssp @Override public void rollbackMigration(NicProfile nic, Network network, - VirtualMachineProfile vm, + VirtualMachineProfile vm, ReservationContext src, ReservationContext dst) { try { release(network, nic, vm, dst); @@ -601,7 +601,7 @@ public class SspElement extends AdapterBase implements ConnectivityProvider, Ssp @Override public void commitMigration(NicProfile nic, Network network, - VirtualMachineProfile vm, + VirtualMachineProfile vm, ReservationContext src, ReservationContext dst) { try { release(network, nic, vm, src); diff --git a/plugins/network-elements/stratosphere-ssp/src/org/apache/cloudstack/network/guru/SspGuestNetworkGuru.java b/plugins/network-elements/stratosphere-ssp/src/org/apache/cloudstack/network/guru/SspGuestNetworkGuru.java index 6d5d871eb99..3deded92632 100644 --- a/plugins/network-elements/stratosphere-ssp/src/org/apache/cloudstack/network/guru/SspGuestNetworkGuru.java +++ b/plugins/network-elements/stratosphere-ssp/src/org/apache/cloudstack/network/guru/SspGuestNetworkGuru.java @@ -119,7 +119,7 @@ public class SspGuestNetworkGuru extends GuestNetworkGuru implements NetworkMigr @Override public void reserve(NicProfile nic, Network network, - VirtualMachineProfile vm, + VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException { @@ -129,7 +129,7 @@ public class SspGuestNetworkGuru extends GuestNetworkGuru implements NetworkMigr @Override public boolean release(NicProfile nic, - VirtualMachineProfile vm, + VirtualMachineProfile vm, String reservationId) { Network network = _networkDao.findById(nic.getNetworkId()); _sspMgr.deleteNicEnv(network, nic, new ReservationContextImpl(reservationId, null, null)); @@ -143,7 +143,7 @@ public class SspGuestNetworkGuru extends GuestNetworkGuru implements NetworkMigr @Override public boolean prepareMigration(NicProfile nic, Network network, - VirtualMachineProfile vm, + VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) { try { reserve(nic, network, vm, dest, context); @@ -159,14 +159,14 @@ public class SspGuestNetworkGuru extends GuestNetworkGuru implements NetworkMigr @Override public void rollbackMigration(NicProfile nic, Network network, - VirtualMachineProfile vm, + VirtualMachineProfile vm, ReservationContext src, ReservationContext dst) { release(nic, vm, dst.getReservationId()); } @Override public void commitMigration(NicProfile nic, Network network, - VirtualMachineProfile vm, + VirtualMachineProfile vm, ReservationContext src, ReservationContext dst) { release(nic, vm, src.getReservationId()); } diff --git a/plugins/storage-allocators/random/src/org/apache/cloudstack/storage/allocator/RandomStoragePoolAllocator.java b/plugins/storage-allocators/random/src/org/apache/cloudstack/storage/allocator/RandomStoragePoolAllocator.java index fda787f479d..025a9693f98 100644 --- a/plugins/storage-allocators/random/src/org/apache/cloudstack/storage/allocator/RandomStoragePoolAllocator.java +++ b/plugins/storage-allocators/random/src/org/apache/cloudstack/storage/allocator/RandomStoragePoolAllocator.java @@ -38,7 +38,7 @@ public class RandomStoragePoolAllocator extends AbstractStoragePoolAllocator { private static final Logger s_logger = Logger.getLogger(RandomStoragePoolAllocator.class); @Override - public List select(DiskProfile dskCh, VirtualMachineProfile vmProfile, + public List select(DiskProfile dskCh, VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo) { List suitablePools = new ArrayList(); diff --git a/server/src/com/cloud/agent/manager/allocator/impl/FirstFitAllocator.java b/server/src/com/cloud/agent/manager/allocator/impl/FirstFitAllocator.java index 4329c7017e6..088591fee8d 100755 --- a/server/src/com/cloud/agent/manager/allocator/impl/FirstFitAllocator.java +++ b/server/src/com/cloud/agent/manager/allocator/impl/FirstFitAllocator.java @@ -105,13 +105,13 @@ public class FirstFitAllocator extends AdapterBase implements HostAllocator { CapacityManager _capacityMgr; @Override - public List allocateTo(VirtualMachineProfile vmProfile, DeploymentPlan plan, Type type, + public List allocateTo(VirtualMachineProfile vmProfile, DeploymentPlan plan, Type type, ExcludeList avoid, int returnUpTo) { return allocateTo(vmProfile, plan, type, avoid, returnUpTo, true); } @Override - public List allocateTo(VirtualMachineProfile vmProfile, DeploymentPlan plan, Type type, ExcludeList avoid, int returnUpTo, + public List allocateTo(VirtualMachineProfile vmProfile, DeploymentPlan plan, Type type, ExcludeList avoid, int returnUpTo, boolean considerReservedCapacity) { long dcId = plan.getDataCenterId(); @@ -195,7 +195,7 @@ public class FirstFitAllocator extends AdapterBase implements HostAllocator { } @Override - public List allocateTo(VirtualMachineProfile vmProfile, DeploymentPlan plan, + public List allocateTo(VirtualMachineProfile vmProfile, DeploymentPlan plan, Type type, ExcludeList avoid, List hosts, int returnUpTo, boolean considerReservedCapacity) { long dcId = plan.getDataCenterId(); Long podId = plan.getPodId(); diff --git a/server/src/com/cloud/agent/manager/allocator/impl/FirstFitRoutingAllocator.java b/server/src/com/cloud/agent/manager/allocator/impl/FirstFitRoutingAllocator.java index 102c6a56358..912a3257046 100644 --- a/server/src/com/cloud/agent/manager/allocator/impl/FirstFitRoutingAllocator.java +++ b/server/src/com/cloud/agent/manager/allocator/impl/FirstFitRoutingAllocator.java @@ -32,7 +32,7 @@ import com.cloud.vm.VirtualMachineProfile; @Local(value={HostAllocator.class}) public class FirstFitRoutingAllocator extends FirstFitAllocator { @Override - public List allocateTo(VirtualMachineProfile vmProfile, DeploymentPlan plan, Type type, + public List allocateTo(VirtualMachineProfile vmProfile, DeploymentPlan plan, Type type, ExcludeList avoid, int returnUpTo) { try { NDC.push("FirstFitRoutingAllocator"); diff --git a/server/src/com/cloud/agent/manager/allocator/impl/RecreateHostAllocator.java b/server/src/com/cloud/agent/manager/allocator/impl/RecreateHostAllocator.java index 3b659c02741..bb4051f94c4 100755 --- a/server/src/com/cloud/agent/manager/allocator/impl/RecreateHostAllocator.java +++ b/server/src/com/cloud/agent/manager/allocator/impl/RecreateHostAllocator.java @@ -69,7 +69,7 @@ public class RecreateHostAllocator extends FirstFitRoutingAllocator { @Inject ResourceManager _resourceMgr; @Override - public List allocateTo(VirtualMachineProfile vm,DeploymentPlan plan, Type type, + public List allocateTo(VirtualMachineProfile vm,DeploymentPlan plan, Type type, ExcludeList avoid, int returnUpTo) { List hosts = super.allocateTo(vm, plan, type, avoid, returnUpTo); diff --git a/server/src/com/cloud/agent/manager/allocator/impl/TestingAllocator.java b/server/src/com/cloud/agent/manager/allocator/impl/TestingAllocator.java index 3c69694346c..6b586d11694 100755 --- a/server/src/com/cloud/agent/manager/allocator/impl/TestingAllocator.java +++ b/server/src/com/cloud/agent/manager/allocator/impl/TestingAllocator.java @@ -42,19 +42,19 @@ public class TestingAllocator extends AdapterBase implements HostAllocator { Long _routingHost; @Override - public List allocateTo(VirtualMachineProfile vmProfile, DeploymentPlan plan, Type type, + public List allocateTo(VirtualMachineProfile vmProfile, DeploymentPlan plan, Type type, ExcludeList avoid, int returnUpTo) { return allocateTo(vmProfile, plan, type, avoid, returnUpTo, true); } @Override - public List allocateTo(VirtualMachineProfile vmProfile, DeploymentPlan plan, Type type, + public List allocateTo(VirtualMachineProfile vmProfile, DeploymentPlan plan, Type type, ExcludeList avoid, List hosts, int returnUpTo, boolean considerReservedCapacity) { return allocateTo(vmProfile, plan, type, avoid, returnUpTo, considerReservedCapacity); } @Override - public List allocateTo(VirtualMachineProfile vmProfile, DeploymentPlan plan, Type type, + public List allocateTo(VirtualMachineProfile vmProfile, DeploymentPlan plan, Type type, ExcludeList avoid, int returnUpTo, boolean considerReservedCapacity) { List availableHosts = new ArrayList(); Host host = null; diff --git a/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java b/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java index 5d6719d720c..5aeb6dc0307 100755 --- a/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java +++ b/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java @@ -1310,9 +1310,9 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy } @Override - public boolean finalizeVirtualMachineProfile(VirtualMachineProfile profile, DeployDestination dest, ReservationContext context) { + public boolean finalizeVirtualMachineProfile(VirtualMachineProfile profile, DeployDestination dest, ReservationContext context) { - ConsoleProxyVO vm = profile.getVirtualMachine(); + ConsoleProxyVO vm = _consoleProxyDao.findById(profile.getId()); Map details = _vmDetailsDao.findDetails(vm.getId()); vm.setDetails(details); @@ -1388,11 +1388,11 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy } @Override - public boolean finalizeDeployment(Commands cmds, VirtualMachineProfile profile, DeployDestination dest, ReservationContext context) { + public boolean finalizeDeployment(Commands cmds, VirtualMachineProfile profile, DeployDestination dest, ReservationContext context) { finalizeCommandsOnStart(cmds, profile); - ConsoleProxyVO proxy = profile.getVirtualMachine(); + ConsoleProxyVO proxy = _consoleProxyDao.findById(profile.getId()); DataCenter dc = dest.getDataCenter(); List nics = profile.getNics(); for (NicProfile nic : nics) { @@ -1411,7 +1411,7 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy } @Override - public boolean finalizeCommandsOnStart(Commands cmds, VirtualMachineProfile profile) { + public boolean finalizeCommandsOnStart(Commands cmds, VirtualMachineProfile profile) { NicProfile managementNic = null; NicProfile controlNic = null; @@ -1438,7 +1438,7 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy } @Override - public boolean finalizeStart(VirtualMachineProfile profile, long hostId, Commands cmds, ReservationContext context) { + public boolean finalizeStart(VirtualMachineProfile profile, long hostId, Commands cmds, ReservationContext context) { CheckSshAnswer answer = (CheckSshAnswer) cmds.getAnswer("checkSsh"); if (answer == null || !answer.getResult()) { if (answer != null) { @@ -1454,7 +1454,7 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy _rulesMgr.getSystemIpAndEnableStaticNatForVm(profile.getVirtualMachine(), false); IPAddressVO ipaddr = _ipAddressDao.findByAssociatedVmId(profile.getVirtualMachine().getId()); if (ipaddr != null && ipaddr.getSystem()) { - ConsoleProxyVO consoleVm = profile.getVirtualMachine(); + ConsoleProxyVO consoleVm = _consoleProxyDao.findById(profile.getId()); // override CPVM guest IP with EIP, so that console url's will be prepared with EIP consoleVm.setPublicIpAddress(ipaddr.getAddress().addr()); _consoleProxyDao.update(consoleVm.getId(), consoleVm); @@ -1483,7 +1483,7 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy } @Override - public void finalizeStop(VirtualMachineProfile profile, StopAnswer answer) { + public void finalizeStop(VirtualMachineProfile profile, StopAnswer answer) { //release elastic IP here if assigned IPAddressVO ip = _ipAddressDao.findByAssociatedVmId(profile.getId()); if (ip != null && ip.getSystem()) { @@ -1685,7 +1685,7 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy } @Override - public void prepareStop(VirtualMachineProfile profile) { + public void prepareStop(VirtualMachineProfile profile) { } } diff --git a/server/src/com/cloud/deploy/DeploymentPlanningManager.java b/server/src/com/cloud/deploy/DeploymentPlanningManager.java index 9458df2946f..7dde8158bb1 100644 --- a/server/src/com/cloud/deploy/DeploymentPlanningManager.java +++ b/server/src/com/cloud/deploy/DeploymentPlanningManager.java @@ -20,7 +20,6 @@ import com.cloud.deploy.DeploymentPlanner.ExcludeList; import com.cloud.exception.AffinityConflictException; import com.cloud.exception.InsufficientServerCapacityException; import com.cloud.utils.component.Manager; -import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachineProfile; public interface DeploymentPlanningManager extends Manager { @@ -40,11 +39,11 @@ public interface DeploymentPlanningManager extends Manager { * * */ - DeployDestination planDeployment(VirtualMachineProfile vmProfile, DeploymentPlan plan, + DeployDestination planDeployment(VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoids) throws InsufficientServerCapacityException, AffinityConflictException; String finalizeReservation(DeployDestination plannedDestination, - VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoids) + VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoids) throws InsufficientServerCapacityException, AffinityConflictException; void cleanupVMReservations(); diff --git a/server/src/com/cloud/deploy/DeploymentPlanningManagerImpl.java b/server/src/com/cloud/deploy/DeploymentPlanningManagerImpl.java index 975f80b6355..5336d30fe07 100644 --- a/server/src/com/cloud/deploy/DeploymentPlanningManagerImpl.java +++ b/server/src/com/cloud/deploy/DeploymentPlanningManagerImpl.java @@ -207,7 +207,7 @@ public class DeploymentPlanningManagerImpl extends ManagerBase implements Deploy } @Override - public DeployDestination planDeployment(VirtualMachineProfile vmProfile, + public DeployDestination planDeployment(VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoids) throws InsufficientServerCapacityException, AffinityConflictException { @@ -449,7 +449,7 @@ public class DeploymentPlanningManagerImpl extends ManagerBase implements Deploy return dest; } - private void checkForNonDedicatedResources(VirtualMachineProfile vmProfile, DataCenter dc, ExcludeList avoids) { + private void checkForNonDedicatedResources(VirtualMachineProfile vmProfile, DataCenter dc, ExcludeList avoids) { boolean isExplicit = false; VirtualMachine vm = vmProfile.getVirtualMachine(); // check affinity group of type Explicit dedication exists @@ -534,7 +534,7 @@ public class DeploymentPlanningManagerImpl extends ManagerBase implements Deploy } } - private PlannerResourceUsage getPlannerUsage(DeploymentPlanner planner, VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoids) throws InsufficientServerCapacityException { + private PlannerResourceUsage getPlannerUsage(DeploymentPlanner planner, VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoids) throws InsufficientServerCapacityException { if (planner != null && planner instanceof DeploymentClusterPlanner) { return ((DeploymentClusterPlanner) planner).getResourceUsage(vmProfile, plan, avoids); } else { @@ -843,7 +843,7 @@ public class DeploymentPlanningManagerImpl extends ManagerBase implements Deploy // /refactoring planner methods private DeployDestination checkClustersforDestination(List clusterList, - VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, + VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, DataCenter dc, DeploymentPlanner.PlannerResourceUsage resourceUsageRequired, ExcludeList PlannerAvoidOutput) { if (s_logger.isTraceEnabled()) { @@ -1035,7 +1035,7 @@ public class DeploymentPlanningManagerImpl extends ManagerBase implements Deploy return hostCanAccessSPool; } - protected List findSuitableHosts(VirtualMachineProfile vmProfile, + protected List findSuitableHosts(VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo) { List suitableHosts = new ArrayList(); for (HostAllocator allocator : _hostAllocators) { @@ -1052,7 +1052,7 @@ public class DeploymentPlanningManagerImpl extends ManagerBase implements Deploy } protected Pair>, List> findSuitablePoolsForVolumes( - VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, + VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo) { List volumesTobeCreated = _volsDao.findUsableVolumesForInstance(vmProfile.getId()); Map> suitableVolumeStoragePools = new HashMap>(); @@ -1219,7 +1219,7 @@ public class DeploymentPlanningManagerImpl extends ManagerBase implements Deploy @DB @Override public String finalizeReservation(DeployDestination plannedDestination, - VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoids) + VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoids) throws InsufficientServerCapacityException, AffinityConflictException { VirtualMachine vm = vmProfile.getVirtualMachine(); diff --git a/server/src/com/cloud/deploy/FirstFitPlanner.java b/server/src/com/cloud/deploy/FirstFitPlanner.java index 7124de28d7b..d2e0c14cb52 100755 --- a/server/src/com/cloud/deploy/FirstFitPlanner.java +++ b/server/src/com/cloud/deploy/FirstFitPlanner.java @@ -110,7 +110,7 @@ public class FirstFitPlanner extends PlannerBase implements DeploymentClusterPla @Override - public List orderClusters(VirtualMachineProfile vmProfile, + public List orderClusters(VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid) throws InsufficientServerCapacityException { VirtualMachine vm = vmProfile.getVirtualMachine(); @@ -178,7 +178,7 @@ public class FirstFitPlanner extends PlannerBase implements DeploymentClusterPla } - private List scanPodsForDestination(VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid){ + private List scanPodsForDestination(VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid){ ServiceOffering offering = vmProfile.getServiceOffering(); int requiredCpu = offering.getCpu() * offering.getSpeed(); @@ -264,7 +264,7 @@ public class FirstFitPlanner extends PlannerBase implements DeploymentClusterPla } private void removeClustersCrossingThreshold(List clusterListForVmAllocation, ExcludeList avoid, - VirtualMachineProfile vmProfile, DeploymentPlan plan) { + VirtualMachineProfile vmProfile, DeploymentPlan plan) { List capacityList = getCapacitiesForCheckingThreshold(); List clustersCrossingThreshold = new ArrayList(); @@ -302,7 +302,7 @@ public class FirstFitPlanner extends PlannerBase implements DeploymentClusterPla } private List scanClustersForDestinationInZoneOrPod(long id, boolean isZone, - VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid) { + VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid) { VirtualMachine vm = vmProfile.getVirtualMachine(); ServiceOffering offering = vmProfile.getServiceOffering(); @@ -362,7 +362,7 @@ public class FirstFitPlanner extends PlannerBase implements DeploymentClusterPla * other than the capacity based ordering which is done by default. * @return List ordered list of Cluster Ids */ - protected List reorderClusters(long id, boolean isZone, Pair, Map> clusterCapacityInfo, VirtualMachineProfile vmProfile, DeploymentPlan plan){ + protected List reorderClusters(long id, boolean isZone, Pair, Map> clusterCapacityInfo, VirtualMachineProfile vmProfile, DeploymentPlan plan){ List reordersClusterIds = clusterCapacityInfo.first(); return reordersClusterIds; } @@ -374,7 +374,7 @@ public class FirstFitPlanner extends PlannerBase implements DeploymentClusterPla * other than the capacity based ordering which is done by default. * @return List ordered list of Pod Ids */ - protected List reorderPods(Pair, Map> podCapacityInfo, VirtualMachineProfile vmProfile, DeploymentPlan plan){ + protected List reorderPods(Pair, Map> podCapacityInfo, VirtualMachineProfile vmProfile, DeploymentPlan plan){ List podIdsByCapacity = podCapacityInfo.first(); return podIdsByCapacity; } @@ -476,14 +476,14 @@ public class FirstFitPlanner extends PlannerBase implements DeploymentClusterPla } @Override - public boolean check(VirtualMachineProfile vm, DeploymentPlan plan, + public boolean check(VirtualMachineProfile vm, DeploymentPlan plan, DeployDestination dest, ExcludeList exclude) { // TODO Auto-generated method stub return false; } @Override - public boolean canHandle(VirtualMachineProfile vm, DeploymentPlan plan, ExcludeList avoid) { + public boolean canHandle(VirtualMachineProfile vm, DeploymentPlan plan, ExcludeList avoid) { // check what the ServiceOffering says. If null, check the global config ServiceOffering offering = vm.getServiceOffering(); if (vm.getHypervisorType() != HypervisorType.BareMetal) { @@ -510,14 +510,14 @@ public class FirstFitPlanner extends PlannerBase implements DeploymentClusterPla @Override - public DeployDestination plan(VirtualMachineProfile vm, DeploymentPlan plan, + public DeployDestination plan(VirtualMachineProfile vm, DeploymentPlan plan, ExcludeList avoid) throws InsufficientServerCapacityException { // TODO Auto-generated method stub return null; } @Override - public PlannerResourceUsage getResourceUsage(VirtualMachineProfile vmProfile, + public PlannerResourceUsage getResourceUsage(VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid) throws InsufficientServerCapacityException { return PlannerResourceUsage.Shared; } diff --git a/server/src/com/cloud/hypervisor/HypervisorGuruBase.java b/server/src/com/cloud/hypervisor/HypervisorGuruBase.java index 2ffd6821d3e..34584ab7a81 100644 --- a/server/src/com/cloud/hypervisor/HypervisorGuruBase.java +++ b/server/src/com/cloud/hypervisor/HypervisorGuruBase.java @@ -85,7 +85,7 @@ public abstract class HypervisorGuruBase extends AdapterBase implements Hypervis } - protected VirtualMachineTO toVirtualMachineTO(VirtualMachineProfile vmProfile) { + protected VirtualMachineTO toVirtualMachineTO(VirtualMachineProfile vmProfile) { ServiceOffering offering = vmProfile.getServiceOffering(); VirtualMachine vm = vmProfile.getVirtualMachine(); diff --git a/server/src/com/cloud/hypervisor/KVMGuru.java b/server/src/com/cloud/hypervisor/KVMGuru.java index 662ee3e836b..58e46e12979 100644 --- a/server/src/com/cloud/hypervisor/KVMGuru.java +++ b/server/src/com/cloud/hypervisor/KVMGuru.java @@ -23,7 +23,6 @@ import com.cloud.agent.api.to.VirtualMachineTO; import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.storage.GuestOSVO; import com.cloud.storage.dao.GuestOSDao; -import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachineProfile; @Local(value=HypervisorGuru.class) @@ -40,8 +39,7 @@ public class KVMGuru extends HypervisorGuruBase implements HypervisorGuru { } @Override - public VirtualMachineTO implement( - VirtualMachineProfile vm) { + public VirtualMachineTO implement(VirtualMachineProfile vm) { VirtualMachineTO to = toVirtualMachineTO(vm); // Determine the VM's OS description diff --git a/server/src/com/cloud/hypervisor/LXCGuru.java b/server/src/com/cloud/hypervisor/LXCGuru.java index 7a530b5a203..dd61b20a0a7 100644 --- a/server/src/com/cloud/hypervisor/LXCGuru.java +++ b/server/src/com/cloud/hypervisor/LXCGuru.java @@ -23,7 +23,6 @@ import com.cloud.agent.api.to.VirtualMachineTO; import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.storage.GuestOSVO; import com.cloud.storage.dao.GuestOSDao; -import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachineProfile; @Local(value=HypervisorGuru.class) @@ -40,8 +39,7 @@ public class LXCGuru extends HypervisorGuruBase implements HypervisorGuru { } @Override - public VirtualMachineTO implement( - VirtualMachineProfile vm) { + public VirtualMachineTO implement(VirtualMachineProfile vm) { VirtualMachineTO to = toVirtualMachineTO(vm); // Determine the VM's OS description diff --git a/server/src/com/cloud/network/NetworkManager.java b/server/src/com/cloud/network/NetworkManager.java index 8dc7743e706..f6dbb198945 100755 --- a/server/src/com/cloud/network/NetworkManager.java +++ b/server/src/com/cloud/network/NetworkManager.java @@ -5,7 +5,7 @@ // 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, @@ -55,7 +55,6 @@ import com.cloud.vm.Nic; import com.cloud.vm.NicProfile; import com.cloud.vm.NicVO; import com.cloud.vm.ReservationContext; -import com.cloud.vm.VMInstanceVO; import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachine.Type; import com.cloud.vm.VirtualMachineProfile; @@ -82,7 +81,7 @@ public interface NetworkManager { * @throws InsufficientAddressCapacityException */ - PublicIp assignPublicIpAddress(long dcId, Long podId, Account owner, VlanType type, Long networkId, String requestedIp, + PublicIp assignPublicIpAddress(long dcId, Long podId, Account owner, VlanType type, Long networkId, String requestedIp, boolean isSystem) throws InsufficientAddressCapacityException; @@ -103,17 +102,17 @@ public interface NetworkManager { List setupNetwork(Account owner, NetworkOffering offering, Network predefined, DeploymentPlan plan, String name, String displayText, boolean errorIfAlreadySetup, Long domainId, ACLType aclType, Boolean subdomainAccess, Long vpcId, Boolean isDisplayNetworkEnabled) throws ConcurrentOperationException; - void allocate(VirtualMachineProfile vm, List> networks) throws InsufficientCapacityException, ConcurrentOperationException; + void allocate(VirtualMachineProfile vm, List> networks) throws InsufficientCapacityException, ConcurrentOperationException; - void prepare(VirtualMachineProfile profile, DeployDestination dest, ReservationContext context) throws InsufficientCapacityException, ConcurrentOperationException, + void prepare(VirtualMachineProfile profile, DeployDestination dest, ReservationContext context) throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException; - void release(VirtualMachineProfile vmProfile, boolean forced) throws + void release(VirtualMachineProfile vmProfile, boolean forced) throws ConcurrentOperationException, ResourceUnavailableException; - void cleanupNics(VirtualMachineProfile vm); + void cleanupNics(VirtualMachineProfile vm); - void expungeNics(VirtualMachineProfile vm); + void expungeNics(VirtualMachineProfile vm); List getNicProfiles(VirtualMachine vm); @@ -129,27 +128,27 @@ public interface NetworkManager { * @param vm * @param dest */ - void prepareNicForMigration(VirtualMachineProfile vm, DeployDestination dest); + void prepareNicForMigration(VirtualMachineProfile vm, DeployDestination dest); /** * commit vm nic change for migration * - * This method will be called in migration transaction after the successful + * This method will be called in migration transaction after the successful * vm migration. * @param src * @param dst */ - void commitNicForMigration(VirtualMachineProfile src, VirtualMachineProfile dst); + void commitNicForMigration(VirtualMachineProfile src, VirtualMachineProfile dst); /** * rollback vm nic change for migration * - * This method will be called in migaration transaction after vm migration + * This method will be called in migaration transaction after vm migration * failure. * @param src * @param dst */ - void rollbackNicForMigration(VirtualMachineProfile src, VirtualMachineProfile dst); + void rollbackNicForMigration(VirtualMachineProfile src, VirtualMachineProfile dst); boolean shutdownNetwork(long networkId, ReservationContext context, boolean cleanupElements); @@ -193,8 +192,7 @@ public interface NetworkManager { boolean applyStaticNats(List staticNats, boolean continueOnError, boolean forRevoke) throws ResourceUnavailableException; - boolean reallocate(VirtualMachineProfile vm, - DataCenterDeployment dest) throws InsufficientCapacityException, ConcurrentOperationException; + boolean reallocate(VirtualMachineProfile vm, DataCenterDeployment dest) throws InsufficientCapacityException, ConcurrentOperationException; IpAddress assignSystemIp(long networkId, Account owner, boolean forElasticLb, boolean forElasticIp) @@ -203,7 +201,7 @@ public interface NetworkManager { boolean handleSystemIpRelease(IpAddress ip); void allocateDirectIp(NicProfile nic, DataCenter dc, - VirtualMachineProfile vm, + VirtualMachineProfile vm, Network network, String requestedIpv4, String requestedIpv6) throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException; @@ -212,8 +210,8 @@ public interface NetworkManager { * @param owner * @param guestNetwork * @return - * @throws ConcurrentOperationException - * @throws InsufficientAddressCapacityException + * @throws ConcurrentOperationException + * @throws InsufficientAddressCapacityException */ PublicIp assignSourceNatIpAddressToGuestNetwork(Account owner, Network guestNetwork) throws InsufficientAddressCapacityException, ConcurrentOperationException; @@ -229,8 +227,8 @@ public interface NetworkManager { * @throws InsufficientAddressCapacityException * @throws ConcurrentOperationException */ - Pair allocateNic(NicProfile requested, Network network, Boolean isDefaultNic, int deviceId, - VirtualMachineProfile vm) throws InsufficientVirtualNetworkCapcityException, + Pair allocateNic(NicProfile requested, Network network, Boolean isDefaultNic, int deviceId, + VirtualMachineProfile vm) throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException, ConcurrentOperationException; @@ -247,7 +245,7 @@ public interface NetworkManager { * @throws InsufficientCapacityException * @throws ResourceUnavailableException */ - NicProfile prepareNic(VirtualMachineProfile vmProfile, DeployDestination dest, + NicProfile prepareNic(VirtualMachineProfile vmProfile, DeployDestination dest, ReservationContext context, long nicId, NetworkVO network) throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException, ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException; @@ -256,7 +254,7 @@ public interface NetworkManager { * @param vm * @param nic TODO */ - void removeNic(VirtualMachineProfile vm, Nic nic); + void removeNic(VirtualMachineProfile vm, Nic nic); /** @@ -264,7 +262,7 @@ public interface NetworkManager { * @param networkId * @param releaseOnFailure TODO */ - IPAddressVO associateIPToGuestNetwork(long ipAddrId, long networkId, boolean releaseOnFailure) throws ResourceAllocationException, ResourceUnavailableException, + IPAddressVO associateIPToGuestNetwork(long ipAddrId, long networkId, boolean releaseOnFailure) throws ResourceAllocationException, ResourceUnavailableException, InsufficientAddressCapacityException, ConcurrentOperationException; IpAddress allocatePortableIp(Account ipOwner, Account caller, long dcId, Long networkId, Long vpcID) @@ -297,7 +295,7 @@ public interface NetworkManager { * @throws ConcurrentOperationException * @throws ResourceUnavailableException */ - void releaseNic(VirtualMachineProfile vmProfile, Nic nic) + void releaseNic(VirtualMachineProfile vmProfile, Nic nic) throws ConcurrentOperationException, ResourceUnavailableException; @@ -314,7 +312,8 @@ public interface NetworkManager { * @throws InsufficientCapacityException * @throws ResourceUnavailableException */ - NicProfile createNicForVm(Network network, NicProfile requested, ReservationContext context, VirtualMachineProfile vmProfile, boolean prepare) throws InsufficientVirtualNetworkCapcityException, + NicProfile createNicForVm(Network network, NicProfile requested, ReservationContext context, VirtualMachineProfile vmProfile, boolean prepare) + throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException, ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException; diff --git a/server/src/com/cloud/network/NetworkManagerImpl.java b/server/src/com/cloud/network/NetworkManagerImpl.java index 279ea848a8d..30c4242c8e9 100755 --- a/server/src/com/cloud/network/NetworkManagerImpl.java +++ b/server/src/com/cloud/network/NetworkManagerImpl.java @@ -1615,7 +1615,7 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L @Override @DB - public void allocate(VirtualMachineProfile vm, List> networks) + public void allocate(VirtualMachineProfile vm, List> networks) throws InsufficientCapacityException, ConcurrentOperationException { Transaction txn = Transaction.currentTxn(); txn.start(); @@ -1690,7 +1690,7 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L @DB @Override public Pair allocateNic(NicProfile requested, Network network, Boolean isDefaultNic, - int deviceId, VirtualMachineProfile vm) throws InsufficientVirtualNetworkCapcityException, + int deviceId, VirtualMachineProfile vm) throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException, ConcurrentOperationException{ NetworkVO ntwkVO = _networksDao.findById(network.getId()); @@ -1997,7 +1997,7 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L } protected boolean prepareElement(NetworkElement element, NetworkVO network, - NicProfile profile, VirtualMachineProfile vmProfile, + NicProfile profile, VirtualMachineProfile vmProfile, DeployDestination dest, ReservationContext context) throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException { element.prepare(network, profile, vmProfile, dest, context); @@ -2044,7 +2044,7 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L } @Override - public void prepare(VirtualMachineProfile vmProfile, DeployDestination dest, ReservationContext context) throws InsufficientCapacityException, + public void prepare(VirtualMachineProfile vmProfile, DeployDestination dest, ReservationContext context) throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException { List nics = _nicDao.listByVmId(vmProfile.getId()); @@ -2072,7 +2072,7 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L } @Override - public NicProfile prepareNic(VirtualMachineProfile vmProfile, DeployDestination + public NicProfile prepareNic(VirtualMachineProfile vmProfile, DeployDestination dest, ReservationContext context, long nicId, NetworkVO network) throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException, ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException { @@ -2136,7 +2136,7 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L } @Override - public void prepareNicForMigration(VirtualMachineProfile vm, DeployDestination dest) { + public void prepareNicForMigration(VirtualMachineProfile vm, DeployDestination dest) { List nics = _nicDao.listByVmId(vm.getId()); ReservationContext context = new ReservationContextImpl(UUID.randomUUID().toString(), null, null); for (NicVO nic : nics) { @@ -2163,7 +2163,7 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L } } - private NicProfile findNicProfileById(VirtualMachineProfile vm, long id){ + private NicProfile findNicProfileById(VirtualMachineProfile vm, long id){ for(NicProfile nic: vm.getNics()){ if(nic.getId() == id){ return nic; @@ -2174,8 +2174,8 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L @Override public void commitNicForMigration( - VirtualMachineProfile src, - VirtualMachineProfile dst) { + VirtualMachineProfile src, + VirtualMachineProfile dst) { for(NicProfile nicSrc: src.getNics()){ NetworkVO network = _networksDao.findById(nicSrc.getNetworkId()); NetworkGuru guru = AdapterBase.getAdapterByName(_networkGurus, network.getGuruName()); @@ -2200,8 +2200,8 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L @Override public void rollbackNicForMigration( - VirtualMachineProfile src, - VirtualMachineProfile dst) { + VirtualMachineProfile src, + VirtualMachineProfile dst) { for(NicProfile nicDst: dst.getNics()){ NetworkVO network = _networksDao.findById(nicDst.getNetworkId()); NetworkGuru guru = AdapterBase.getAdapterByName(_networkGurus, network.getGuruName()); @@ -2222,7 +2222,7 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L @Override @DB - public void release(VirtualMachineProfile vmProfile, boolean forced) throws + public void release(VirtualMachineProfile vmProfile, boolean forced) throws ConcurrentOperationException, ResourceUnavailableException { List nics = _nicDao.listByVmId(vmProfile.getId()); for (NicVO nic : nics) { @@ -2233,14 +2233,14 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L @Override @DB - public void releaseNic(VirtualMachineProfile vmProfile, Nic nic) + public void releaseNic(VirtualMachineProfile vmProfile, Nic nic) throws ConcurrentOperationException, ResourceUnavailableException { NicVO nicVO = _nicDao.findById(nic.getId()); releaseNic(vmProfile, nicVO); } @DB - protected void releaseNic(VirtualMachineProfile vmProfile, NicVO nicVO) + protected void releaseNic(VirtualMachineProfile vmProfile, NicVO nicVO) throws ConcurrentOperationException, ResourceUnavailableException { //lock the nic Transaction txn = Transaction.currentTxn(); @@ -2292,7 +2292,7 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L } @Override - public void cleanupNics(VirtualMachineProfile vm) { + public void cleanupNics(VirtualMachineProfile vm) { if (s_logger.isDebugEnabled()) { s_logger.debug("Cleaning network for vm: " + vm.getId()); } @@ -2305,12 +2305,12 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L @Override - public void removeNic(VirtualMachineProfile vm, Nic nic) { + public void removeNic(VirtualMachineProfile vm, Nic nic) { removeNic(vm, _nicDao.findById(nic.getId())); } - protected void removeNic(VirtualMachineProfile vm, NicVO nic) { + protected void removeNic(VirtualMachineProfile vm, NicVO nic) { nic.setState(Nic.State.Deallocating); _nicDao.update(nic.getId(), nic); NetworkVO network = _networksDao.findById(nic.getNetworkId()); @@ -2347,7 +2347,7 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L } @Override - public void expungeNics(VirtualMachineProfile vm) { + public void expungeNics(VirtualMachineProfile vm) { List nics = _nicDao.listByVmIdIncludingRemoved(vm.getId()); for (NicVO nic : nics) { _nicDao.expunge(nic.getId()); @@ -3704,7 +3704,7 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L @DB @Override - public boolean reallocate(VirtualMachineProfile vm, DataCenterDeployment dest) throws InsufficientCapacityException, ConcurrentOperationException { + public boolean reallocate(VirtualMachineProfile vm, DataCenterDeployment dest) throws InsufficientCapacityException, ConcurrentOperationException { VMInstanceVO vmInstance = _vmDao.findById(vm.getId()); DataCenterVO dc = _dcDao.findById(vmInstance.getDataCenterId()); if (dc.getNetworkType() == NetworkType.Basic) { @@ -4198,7 +4198,7 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L @Override @DB - public void allocateDirectIp(NicProfile nic, DataCenter dc, VirtualMachineProfile vm, Network network, + public void allocateDirectIp(NicProfile nic, DataCenter dc, VirtualMachineProfile vm, Network network, String requestedIpv4, String requestedIpv6) throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException { //This method allocates direct ip for the Shared network in Advance zones @@ -4300,7 +4300,7 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L } @Override - public NicProfile createNicForVm(Network network, NicProfile requested, ReservationContext context, VirtualMachineProfile vmProfile, boolean prepare) + public NicProfile createNicForVm(Network network, NicProfile requested, ReservationContext context, VirtualMachineProfile vmProfile, boolean prepare) throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException, ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException { diff --git a/server/src/com/cloud/network/element/CloudZonesNetworkElement.java b/server/src/com/cloud/network/element/CloudZonesNetworkElement.java index bdd8e61bbc2..5c7f333a687 100644 --- a/server/src/com/cloud/network/element/CloudZonesNetworkElement.java +++ b/server/src/com/cloud/network/element/CloudZonesNetworkElement.java @@ -50,7 +50,6 @@ import com.cloud.network.PhysicalNetworkServiceProvider; import com.cloud.network.dao.NetworkDao; import com.cloud.offering.NetworkOffering; import com.cloud.service.dao.ServiceOfferingDao; -import com.cloud.uservm.UserVm; import com.cloud.utils.PasswordGenerator; import com.cloud.utils.component.AdapterBase; import com.cloud.vm.NicProfile; @@ -112,13 +111,13 @@ public class CloudZonesNetworkElement extends AdapterBase implements NetworkElem } @Override - public boolean prepare(Network network, NicProfile nic, VirtualMachineProfile vmProfile, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException, + public boolean prepare(Network network, NicProfile nic, VirtualMachineProfile vmProfile, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException { return true; } @Override - public boolean release(Network network, NicProfile nic, VirtualMachineProfile vm, ReservationContext context) { + public boolean release(Network network, NicProfile nic, VirtualMachineProfile vm, ReservationContext context) { return true; } @@ -200,7 +199,7 @@ public class CloudZonesNetworkElement extends AdapterBase implements NetworkElem } @Override - public boolean addPasswordAndUserdata(Network network, NicProfile nic, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) + public boolean addPasswordAndUserdata(Network network, NicProfile nic, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException { if (canHandle(dest, network.getTrafficType())) { @@ -208,16 +207,16 @@ public class CloudZonesNetworkElement extends AdapterBase implements NetworkElem return false; } @SuppressWarnings("unchecked") - VirtualMachineProfile uservm = (VirtualMachineProfile) vm; - _userVmDao.loadDetails((UserVmVO) uservm.getVirtualMachine()); - String password = (String) uservm.getParameter(VirtualMachineProfile.Param.VmPassword); - String userData = uservm.getVirtualMachine().getUserData(); - String sshPublicKey = uservm.getVirtualMachine().getDetail("SSH.PublicKey"); + UserVmVO uservm = _userVmDao.findById(vm.getId()); + _userVmDao.loadDetails(uservm); + String password = (String)vm.getParameter(VirtualMachineProfile.Param.VmPassword); + String userData = uservm.getUserData(); + String sshPublicKey = uservm.getDetail("SSH.PublicKey"); Commands cmds = new Commands(OnError.Continue); if (password != null && nic.isDefaultNic()) { final String encodedPassword = PasswordGenerator.rot13(password); - SavePasswordCommand cmd = new SavePasswordCommand(encodedPassword, nic.getIp4Address(), uservm.getVirtualMachine().getHostName(), _networkMgr.getExecuteInSeqNtwkElmtCmd()); + SavePasswordCommand cmd = new SavePasswordCommand(encodedPassword, nic.getIp4Address(), uservm.getHostName(), _networkMgr.getExecuteInSeqNtwkElmtCmd()); cmds.addCommand("password", cmd); } String serviceOffering = _serviceOfferingDao.findByIdIncludingRemoved(uservm.getServiceOfferingId()).getDisplayText(); @@ -225,7 +224,7 @@ public class CloudZonesNetworkElement extends AdapterBase implements NetworkElem cmds.addCommand( "vmdata", - generateVmDataCommand(nic.getIp4Address(), userData, serviceOffering, zoneName, nic.getIp4Address(), uservm.getVirtualMachine().getHostName(), + generateVmDataCommand(nic.getIp4Address(), userData, serviceOffering, zoneName, nic.getIp4Address(), uservm.getHostName(), uservm.getInstanceName(), uservm.getId(), uservm.getUuid(), sshPublicKey)); try { _agentManager.send(dest.getHost().getId(), cmds); @@ -235,29 +234,29 @@ public class CloudZonesNetworkElement extends AdapterBase implements NetworkElem } Answer dataAnswer = cmds.getAnswer("vmdata"); if (dataAnswer != null && dataAnswer.getResult()) { - s_logger.info("Sent vm data successfully to vm " + uservm.getVirtualMachine().getInstanceName()); + s_logger.info("Sent vm data successfully to vm " + uservm.getInstanceName()); return true; } - s_logger.info("Failed to send vm data to vm " + uservm.getVirtualMachine().getInstanceName()); + s_logger.info("Failed to send vm data to vm " + uservm.getInstanceName()); return false; } return false; } @Override - public boolean savePassword(Network network, NicProfile nic, VirtualMachineProfile vm) throws ResourceUnavailableException { + public boolean savePassword(Network network, NicProfile nic, VirtualMachineProfile vm) throws ResourceUnavailableException { // TODO Auto-generated method stub return false; } @Override - public boolean saveSSHKey(Network network, NicProfile nic, VirtualMachineProfile vm, String SSHPublicKey) throws ResourceUnavailableException { + public boolean saveSSHKey(Network network, NicProfile nic, VirtualMachineProfile vm, String SSHPublicKey) throws ResourceUnavailableException { // TODO Auto-generated method stub return false; } @Override - public boolean saveUserData(Network network, NicProfile nic, VirtualMachineProfile vm) throws ResourceUnavailableException { + public boolean saveUserData(Network network, NicProfile nic, VirtualMachineProfile vm) throws ResourceUnavailableException { // TODO Auto-generated method stub return false; } diff --git a/server/src/com/cloud/network/element/SecurityGroupElement.java b/server/src/com/cloud/network/element/SecurityGroupElement.java index 0659db781e3..4a740c0c186 100644 --- a/server/src/com/cloud/network/element/SecurityGroupElement.java +++ b/server/src/com/cloud/network/element/SecurityGroupElement.java @@ -68,13 +68,13 @@ public class SecurityGroupElement extends AdapterBase implements NetworkElement } @Override @DB - public boolean prepare(Network network, NicProfile nic, VirtualMachineProfile vm, DeployDestination dest, + public boolean prepare(Network network, NicProfile nic, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException { return true; } @Override - public boolean release(Network network, NicProfile nic, VirtualMachineProfile vm, ReservationContext context) + public boolean release(Network network, NicProfile nic, VirtualMachineProfile vm, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException { return true; } diff --git a/server/src/com/cloud/network/element/VirtualRouterElement.java b/server/src/com/cloud/network/element/VirtualRouterElement.java index d26c1e111cd..15b7f13ee62 100755 --- a/server/src/com/cloud/network/element/VirtualRouterElement.java +++ b/server/src/com/cloud/network/element/VirtualRouterElement.java @@ -212,7 +212,7 @@ public class VirtualRouterElement extends AdapterBase implements VirtualRouterEl } @Override - public boolean prepare(Network network, NicProfile nic, VirtualMachineProfile vm, + public boolean prepare(Network network, NicProfile nic, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException { if (vm.getType() != VirtualMachine.Type.User || vm.getHypervisorType() == HypervisorType.BareMetal) { @@ -232,7 +232,7 @@ public class VirtualRouterElement extends AdapterBase implements VirtualRouterEl } @SuppressWarnings("unchecked") - VirtualMachineProfile uservm = (VirtualMachineProfile) vm; + VirtualMachineProfile uservm = (VirtualMachineProfile) vm; List routers = _routerMgr.deployVirtualRouterInGuestNetwork(network, dest, _accountMgr.getAccount(network.getAccountId()), uservm.getParameters(), offering.getRedundantRouter()); @@ -685,7 +685,7 @@ public class VirtualRouterElement extends AdapterBase implements VirtualRouterEl } @Override - public boolean savePassword(Network network, NicProfile nic, VirtualMachineProfile vm) + public boolean savePassword(Network network, NicProfile nic, VirtualMachineProfile vm) throws ResourceUnavailableException { if (!canHandle(network, null)) { return false; @@ -697,13 +697,13 @@ public class VirtualRouterElement extends AdapterBase implements VirtualRouterEl } @SuppressWarnings("unchecked") - VirtualMachineProfile uservm = (VirtualMachineProfile) vm; + VirtualMachineProfile uservm = (VirtualMachineProfile) vm; return _routerMgr.savePasswordToRouter(network, nic, uservm, routers); } @Override - public boolean saveSSHKey(Network network, NicProfile nic, VirtualMachineProfile vm, String SSHPublicKey) + public boolean saveSSHKey(Network network, NicProfile nic, VirtualMachineProfile vm, String SSHPublicKey) throws ResourceUnavailableException { if (!canHandle(network, null)) { return false; @@ -715,13 +715,13 @@ public class VirtualRouterElement extends AdapterBase implements VirtualRouterEl } @SuppressWarnings("unchecked") - VirtualMachineProfile uservm = (VirtualMachineProfile) vm; + VirtualMachineProfile uservm = (VirtualMachineProfile) vm; return _routerMgr.saveSSHPublicKeyToRouter(network, nic, uservm, routers, SSHPublicKey); } @Override - public boolean saveUserData(Network network, NicProfile nic, VirtualMachineProfile vm) + public boolean saveUserData(Network network, NicProfile nic, VirtualMachineProfile vm) throws ResourceUnavailableException { if (!canHandle(network, null)) { return false; @@ -733,7 +733,7 @@ public class VirtualRouterElement extends AdapterBase implements VirtualRouterEl } @SuppressWarnings("unchecked") - VirtualMachineProfile uservm = (VirtualMachineProfile) vm; + VirtualMachineProfile uservm = (VirtualMachineProfile) vm; return _routerMgr.saveUserDataToRouter(network, nic, uservm, routers); } @@ -848,21 +848,21 @@ public class VirtualRouterElement extends AdapterBase implements VirtualRouterEl } @Override - public boolean release(Network network, NicProfile nic, VirtualMachineProfile vm, + public boolean release(Network network, NicProfile nic, VirtualMachineProfile vm, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException { return true; } @Override - public boolean configDhcpSupportForSubnet(Network network, NicProfile nic, VirtualMachineProfile vm, + public boolean configDhcpSupportForSubnet(Network network, NicProfile nic, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException { if (canHandle(network, Service.Dhcp)) { if (vm.getType() != VirtualMachine.Type.User) { return false; } @SuppressWarnings("unchecked") - VirtualMachineProfile uservm = (VirtualMachineProfile) vm; + VirtualMachineProfile uservm = (VirtualMachineProfile) vm; List routers = getRouters(network, dest); @@ -893,7 +893,7 @@ public class VirtualRouterElement extends AdapterBase implements VirtualRouterEl } @Override - public boolean addDhcpEntry(Network network, NicProfile nic, VirtualMachineProfile vm, + public boolean addDhcpEntry(Network network, NicProfile nic, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException { if (canHandle(network, Service.Dhcp)) { @@ -902,7 +902,7 @@ public class VirtualRouterElement extends AdapterBase implements VirtualRouterEl } @SuppressWarnings("unchecked") - VirtualMachineProfile uservm = (VirtualMachineProfile) vm; + VirtualMachineProfile uservm = (VirtualMachineProfile) vm; List routers = getRouters(network, dest); @@ -916,7 +916,7 @@ public class VirtualRouterElement extends AdapterBase implements VirtualRouterEl } @Override - public boolean addPasswordAndUserdata(Network network, NicProfile nic, VirtualMachineProfile vm, + public boolean addPasswordAndUserdata(Network network, NicProfile nic, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException { if (canHandle(network, Service.UserData)) { @@ -930,7 +930,7 @@ public class VirtualRouterElement extends AdapterBase implements VirtualRouterEl } @SuppressWarnings("unchecked") - VirtualMachineProfile uservm = (VirtualMachineProfile) vm; + VirtualMachineProfile uservm = (VirtualMachineProfile) vm; List routers = getRouters(network, dest); @@ -1049,7 +1049,7 @@ public class VirtualRouterElement extends AdapterBase implements VirtualRouterEl @Override public boolean prepareMigration(NicProfile nic, Network network, - VirtualMachineProfile vm, + VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) { if (nic.getBroadcastType() != Networks.BroadcastDomainType.Pvlan) { return true; @@ -1068,7 +1068,7 @@ public class VirtualRouterElement extends AdapterBase implements VirtualRouterEl @Override public void rollbackMigration(NicProfile nic, Network network, - VirtualMachineProfile vm, + VirtualMachineProfile vm, ReservationContext src, ReservationContext dst) { if (nic.getBroadcastType() != Networks.BroadcastDomainType.Pvlan) { return; @@ -1086,7 +1086,7 @@ public class VirtualRouterElement extends AdapterBase implements VirtualRouterEl @Override public void commitMigration(NicProfile nic, Network network, - VirtualMachineProfile vm, + VirtualMachineProfile vm, ReservationContext src, ReservationContext dst) { if (nic.getBroadcastType() != Networks.BroadcastDomainType.Pvlan) { return; diff --git a/server/src/com/cloud/network/element/VpcVirtualRouterElement.java b/server/src/com/cloud/network/element/VpcVirtualRouterElement.java index 966710c36c9..979d8fe2d3d 100644 --- a/server/src/com/cloud/network/element/VpcVirtualRouterElement.java +++ b/server/src/com/cloud/network/element/VpcVirtualRouterElement.java @@ -185,7 +185,7 @@ public class VpcVirtualRouterElement extends VirtualRouterElement implements Vpc } @Override - public boolean prepare(Network network, NicProfile nic, VirtualMachineProfile vm, + public boolean prepare(Network network, NicProfile nic, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException { diff --git a/server/src/com/cloud/network/guru/ControlNetworkGuru.java b/server/src/com/cloud/network/guru/ControlNetworkGuru.java index e7c5cba132d..6060dac4b8f 100755 --- a/server/src/com/cloud/network/guru/ControlNetworkGuru.java +++ b/server/src/com/cloud/network/guru/ControlNetworkGuru.java @@ -106,7 +106,7 @@ public class ControlNetworkGuru extends PodBasedNetworkGuru implements NetworkGu } @Override - public NicProfile allocate(Network config, NicProfile nic, VirtualMachineProfile vm) throws InsufficientVirtualNetworkCapcityException, + public NicProfile allocate(Network config, NicProfile nic, VirtualMachineProfile vm) throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException { if(vm.getHypervisorType() == HypervisorType.VMware && vm.getType() != VirtualMachine.Type.DomainRouter) { @@ -124,11 +124,11 @@ public class ControlNetworkGuru extends PodBasedNetworkGuru implements NetworkGu } @Override - public void deallocate(Network config, NicProfile nic, VirtualMachineProfile vm) { + public void deallocate(Network config, NicProfile nic, VirtualMachineProfile vm) { } @Override - public void reserve(NicProfile nic, Network config, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) throws InsufficientVirtualNetworkCapcityException, + public void reserve(NicProfile nic, Network config, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException { assert nic.getTrafficType() == TrafficType.Control; @@ -163,7 +163,7 @@ public class ControlNetworkGuru extends PodBasedNetworkGuru implements NetworkGu } @Override - public boolean release(NicProfile nic, VirtualMachineProfile vm, String reservationId) { + public boolean release(NicProfile nic, VirtualMachineProfile vm, String reservationId) { assert nic.getTrafficType() == TrafficType.Control; if (vm.getHypervisorType() == HypervisorType.VMware && vm.getType() == VirtualMachine.Type.DomainRouter) { diff --git a/server/src/com/cloud/network/guru/DirectNetworkGuru.java b/server/src/com/cloud/network/guru/DirectNetworkGuru.java index b4577ac096a..5d0e7b1d9cf 100755 --- a/server/src/com/cloud/network/guru/DirectNetworkGuru.java +++ b/server/src/com/cloud/network/guru/DirectNetworkGuru.java @@ -188,7 +188,7 @@ public class DirectNetworkGuru extends AdapterBase implements NetworkGuru { } @Override - public NicProfile allocate(Network network, NicProfile nic, VirtualMachineProfile vm) throws InsufficientVirtualNetworkCapcityException, + public NicProfile allocate(Network network, NicProfile nic, VirtualMachineProfile vm) throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException, ConcurrentOperationException { DataCenter dc = _dcDao.findById(network.getDataCenterId()); @@ -208,7 +208,7 @@ public class DirectNetworkGuru extends AdapterBase implements NetworkGuru { } @Override - public void reserve(NicProfile nic, Network network, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) + public void reserve(NicProfile nic, Network network, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException, ConcurrentOperationException { if (nic.getIp4Address() == null && nic.getIp6Address() == null) { allocateDirectIp(nic, network, vm, dest.getDataCenter(), null, null); @@ -217,7 +217,7 @@ public class DirectNetworkGuru extends AdapterBase implements NetworkGuru { } @DB - protected void allocateDirectIp(NicProfile nic, Network network, VirtualMachineProfile vm, DataCenter dc, String requestedIp4Addr, String requestedIp6Addr) + protected void allocateDirectIp(NicProfile nic, Network network, VirtualMachineProfile vm, DataCenter dc, String requestedIp4Addr, String requestedIp6Addr) throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException { @@ -236,7 +236,7 @@ public class DirectNetworkGuru extends AdapterBase implements NetworkGuru { } @Override - public boolean release(NicProfile nic, VirtualMachineProfile vm, String reservationId) { + public boolean release(NicProfile nic, VirtualMachineProfile vm, String reservationId) { return true; } @@ -246,7 +246,7 @@ public class DirectNetworkGuru extends AdapterBase implements NetworkGuru { } @Override @DB - public void deallocate(Network network, NicProfile nic, VirtualMachineProfile vm) { + public void deallocate(Network network, NicProfile nic, VirtualMachineProfile vm) { if (s_logger.isDebugEnabled()) { s_logger.debug("Deallocate network: networkId: " + nic.getNetworkId() + ", ip: " + nic.getIp4Address()); } diff --git a/server/src/com/cloud/network/guru/DirectPodBasedNetworkGuru.java b/server/src/com/cloud/network/guru/DirectPodBasedNetworkGuru.java index f21e352ff76..110096b7147 100755 --- a/server/src/com/cloud/network/guru/DirectPodBasedNetworkGuru.java +++ b/server/src/com/cloud/network/guru/DirectPodBasedNetworkGuru.java @@ -88,7 +88,7 @@ public class DirectPodBasedNetworkGuru extends DirectNetworkGuru { } @Override - public NicProfile allocate(Network network, NicProfile nic, VirtualMachineProfile vm) throws InsufficientVirtualNetworkCapcityException, + public NicProfile allocate(Network network, NicProfile nic, VirtualMachineProfile vm) throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException, ConcurrentOperationException { DataCenterVO dc = _dcDao.findById(network.getDataCenterId()); @@ -119,7 +119,7 @@ public class DirectPodBasedNetworkGuru extends DirectNetworkGuru { } @Override @DB - public void reserve(NicProfile nic, Network network, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) + public void reserve(NicProfile nic, Network network, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException, ConcurrentOperationException { String oldIp = nic.getIp4Address(); @@ -159,7 +159,7 @@ public class DirectPodBasedNetworkGuru extends DirectNetworkGuru { } @DB - protected void getIp(NicProfile nic, Pod pod, VirtualMachineProfile vm, Network network) throws InsufficientVirtualNetworkCapcityException, + protected void getIp(NicProfile nic, Pod pod, VirtualMachineProfile vm, Network network) throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException, ConcurrentOperationException { DataCenter dc = _dcDao.findById(pod.getDataCenterId()); if (nic.getIp4Address() == null) { diff --git a/server/src/com/cloud/network/guru/ExternalGuestNetworkGuru.java b/server/src/com/cloud/network/guru/ExternalGuestNetworkGuru.java index 36ea6a5b359..9355d7795e6 100644 --- a/server/src/com/cloud/network/guru/ExternalGuestNetworkGuru.java +++ b/server/src/com/cloud/network/guru/ExternalGuestNetworkGuru.java @@ -198,7 +198,7 @@ public class ExternalGuestNetworkGuru extends GuestNetworkGuru { } @Override - public NicProfile allocate(Network config, NicProfile nic, VirtualMachineProfile vm) throws InsufficientVirtualNetworkCapcityException, + public NicProfile allocate(Network config, NicProfile nic, VirtualMachineProfile vm) throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException { if (_networkModel.networkIsConfiguredForExternalNetworking(config.getDataCenterId(), config.getId()) && nic != null && nic.getRequestedIpv4() != null) { @@ -224,7 +224,7 @@ public class ExternalGuestNetworkGuru extends GuestNetworkGuru { } @Override @DB - public void deallocate(Network config, NicProfile nic, VirtualMachineProfile vm) { + public void deallocate(Network config, NicProfile nic, VirtualMachineProfile vm) { super.deallocate(config, nic, vm); if (Boolean.parseBoolean(_configDao.getValue(Config.OvsTunnelNetwork.key()))) { @@ -241,7 +241,7 @@ public class ExternalGuestNetworkGuru extends GuestNetworkGuru { } @Override - public void reserve(NicProfile nic, Network config, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) + public void reserve(NicProfile nic, Network config, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException { assert (nic.getReservationStrategy() == ReservationStrategy.Start) : "What can I do for nics that are not allocated at start? "; boolean _isEnabled = Boolean.parseBoolean(_configDao.getValue(Config.OvsTunnelNetwork.key())); @@ -278,7 +278,7 @@ public class ExternalGuestNetworkGuru extends GuestNetworkGuru { } @Override - public boolean release(NicProfile nic, VirtualMachineProfile vm, String reservationId) { + public boolean release(NicProfile nic, VirtualMachineProfile vm, String reservationId) { if (Boolean.parseBoolean(_configDao.getValue(Config.OvsTunnelNetwork.key()))) { return true; diff --git a/server/src/com/cloud/network/guru/GuestNetworkGuru.java b/server/src/com/cloud/network/guru/GuestNetworkGuru.java index 9adffa222e0..f2eeb1252f7 100755 --- a/server/src/com/cloud/network/guru/GuestNetworkGuru.java +++ b/server/src/com/cloud/network/guru/GuestNetworkGuru.java @@ -216,7 +216,7 @@ public abstract class GuestNetworkGuru extends AdapterBase implements NetworkGur } @Override @DB - public void deallocate(Network network, NicProfile nic, VirtualMachineProfile vm) { + public void deallocate(Network network, NicProfile nic, VirtualMachineProfile vm) { if (network.getSpecifyIpRanges()) { if (s_logger.isDebugEnabled()) { s_logger.debug("Deallocate network: networkId: " + nic.getNetworkId() + ", ip: " + nic.getIp4Address()); @@ -316,7 +316,7 @@ public abstract class GuestNetworkGuru extends AdapterBase implements NetworkGur } @Override - public NicProfile allocate(Network network, NicProfile nic, VirtualMachineProfile vm) + public NicProfile allocate(Network network, NicProfile nic, VirtualMachineProfile vm) throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException { @@ -393,7 +393,7 @@ public abstract class GuestNetworkGuru extends AdapterBase implements NetworkGur } @Override - public void reserve(NicProfile nic, Network network, VirtualMachineProfile vm, + public void reserve(NicProfile nic, Network network, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException { assert (nic.getReservationStrategy() == ReservationStrategy.Start) : "What can I do for nics that are not allocated at start? "; @@ -403,7 +403,7 @@ public abstract class GuestNetworkGuru extends AdapterBase implements NetworkGur } @Override - public boolean release(NicProfile nic, VirtualMachineProfile vm, String reservationId) { + public boolean release(NicProfile nic, VirtualMachineProfile vm, String reservationId) { nic.setBroadcastUri(null); nic.setIsolationUri(null); return true; diff --git a/server/src/com/cloud/network/guru/PodBasedNetworkGuru.java b/server/src/com/cloud/network/guru/PodBasedNetworkGuru.java index 5a24fe56305..38624652c1b 100755 --- a/server/src/com/cloud/network/guru/PodBasedNetworkGuru.java +++ b/server/src/com/cloud/network/guru/PodBasedNetworkGuru.java @@ -90,11 +90,11 @@ public class PodBasedNetworkGuru extends AdapterBase implements NetworkGuru { } @Override - public void deallocate(Network config, NicProfile nic, VirtualMachineProfile vm) { + public void deallocate(Network config, NicProfile nic, VirtualMachineProfile vm) { } @Override - public NicProfile allocate(Network config, NicProfile nic, VirtualMachineProfile vm) throws InsufficientVirtualNetworkCapcityException, + public NicProfile allocate(Network config, NicProfile nic, VirtualMachineProfile vm) throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException { TrafficType trafficType = config.getTrafficType(); assert trafficType == TrafficType.Management || trafficType == TrafficType.Storage: "Well, I can't take care of this config now can I? " + config; @@ -112,7 +112,7 @@ public class PodBasedNetworkGuru extends AdapterBase implements NetworkGuru { } @Override - public void reserve(NicProfile nic, Network config, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) throws InsufficientVirtualNetworkCapcityException, + public void reserve(NicProfile nic, Network config, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException { Pod pod = dest.getPod(); @@ -144,7 +144,7 @@ public class PodBasedNetworkGuru extends AdapterBase implements NetworkGuru { } @Override - public boolean release(NicProfile nic, VirtualMachineProfile vm, String reservationId) { + public boolean release(NicProfile nic, VirtualMachineProfile vm, String reservationId) { _dcDao.releasePrivateIpAddress(nic.getId(), nic.getReservationId()); nic.deallocate(); diff --git a/server/src/com/cloud/network/guru/PrivateNetworkGuru.java b/server/src/com/cloud/network/guru/PrivateNetworkGuru.java index 2e266e7b780..6521cf4e1dd 100644 --- a/server/src/com/cloud/network/guru/PrivateNetworkGuru.java +++ b/server/src/com/cloud/network/guru/PrivateNetworkGuru.java @@ -132,7 +132,7 @@ public class PrivateNetworkGuru extends AdapterBase implements NetworkGuru { } @Override - public void deallocate(Network network, NicProfile nic, VirtualMachineProfile vm) { + public void deallocate(Network network, NicProfile nic, VirtualMachineProfile vm) { if (s_logger.isDebugEnabled()) { s_logger.debug("Deallocate network: networkId: " + nic.getNetworkId() + ", ip: " + nic.getIp4Address()); } @@ -153,7 +153,7 @@ public class PrivateNetworkGuru extends AdapterBase implements NetworkGuru { } @Override - public NicProfile allocate(Network network, NicProfile nic, VirtualMachineProfile vm) + public NicProfile allocate(Network network, NicProfile nic, VirtualMachineProfile vm) throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException { DataCenter dc = _configMgr.getZone(network.getDataCenterId()); NetworkOffering offering = _configMgr.getNetworkOffering(network.getNetworkOfferingId()); @@ -212,7 +212,7 @@ public class PrivateNetworkGuru extends AdapterBase implements NetworkGuru { } @Override - public void reserve(NicProfile nic, Network network, VirtualMachineProfile vm, + public void reserve(NicProfile nic, Network network, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException { if (nic.getIp4Address() == null) { @@ -222,7 +222,7 @@ public class PrivateNetworkGuru extends AdapterBase implements NetworkGuru { } @Override - public boolean release(NicProfile nic, VirtualMachineProfile vm, String reservationId) { + public boolean release(NicProfile nic, VirtualMachineProfile vm, String reservationId) { return true; } diff --git a/server/src/com/cloud/network/guru/PublicNetworkGuru.java b/server/src/com/cloud/network/guru/PublicNetworkGuru.java index a83cdb37c69..8beb42e5831 100755 --- a/server/src/com/cloud/network/guru/PublicNetworkGuru.java +++ b/server/src/com/cloud/network/guru/PublicNetworkGuru.java @@ -107,7 +107,7 @@ public class PublicNetworkGuru extends AdapterBase implements NetworkGuru { super(); } - protected void getIp(NicProfile nic, DataCenter dc, VirtualMachineProfile vm, Network network) throws InsufficientVirtualNetworkCapcityException, + protected void getIp(NicProfile nic, DataCenter dc, VirtualMachineProfile vm, Network network) throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException, ConcurrentOperationException { if (nic.getIp4Address() == null) { PublicIp ip = _networkMgr.assignPublicIpAddress(dc.getId(), null, vm.getOwner(), VlanType.VirtualNetwork, null, null, false); @@ -136,7 +136,7 @@ public class PublicNetworkGuru extends AdapterBase implements NetworkGuru { } @Override - public NicProfile allocate(Network network, NicProfile nic, VirtualMachineProfile vm) + public NicProfile allocate(Network network, NicProfile nic, VirtualMachineProfile vm) throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException, ConcurrentOperationException { @@ -164,7 +164,7 @@ public class PublicNetworkGuru extends AdapterBase implements NetworkGuru { } @Override - public void reserve(NicProfile nic, Network network, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) + public void reserve(NicProfile nic, Network network, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException, ConcurrentOperationException { if (nic.getIp4Address() == null) { getIp(nic, dest.getDataCenter(), vm, network); @@ -172,7 +172,7 @@ public class PublicNetworkGuru extends AdapterBase implements NetworkGuru { } @Override - public boolean release(NicProfile nic, VirtualMachineProfile vm, String reservationId) { + public boolean release(NicProfile nic, VirtualMachineProfile vm, String reservationId) { return true; } @@ -183,7 +183,7 @@ public class PublicNetworkGuru extends AdapterBase implements NetworkGuru { } @Override @DB - public void deallocate(Network network, NicProfile nic, VirtualMachineProfile vm) { + public void deallocate(Network network, NicProfile nic, VirtualMachineProfile vm) { if (s_logger.isDebugEnabled()) { s_logger.debug("public network deallocate network: networkId: " + nic.getNetworkId() + ", ip: " + nic.getIp4Address()); } diff --git a/server/src/com/cloud/network/guru/StorageNetworkGuru.java b/server/src/com/cloud/network/guru/StorageNetworkGuru.java index 1d01184e0c5..86dd5f6b996 100755 --- a/server/src/com/cloud/network/guru/StorageNetworkGuru.java +++ b/server/src/com/cloud/network/guru/StorageNetworkGuru.java @@ -103,7 +103,7 @@ public class StorageNetworkGuru extends PodBasedNetworkGuru implements NetworkGu } @Override - public NicProfile allocate(Network network, NicProfile nic, VirtualMachineProfile vm) + public NicProfile allocate(Network network, NicProfile nic, VirtualMachineProfile vm) throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException { assert network.getTrafficType() == TrafficType.Storage : "Well, I can't take care of this config now can I? " + network; if (!_sNwMgr.isStorageIpRangeAvailable(network.getDataCenterId())) { @@ -114,7 +114,7 @@ public class StorageNetworkGuru extends PodBasedNetworkGuru implements NetworkGu } @Override - public void reserve(NicProfile nic, Network network, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) + public void reserve(NicProfile nic, Network network, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException { if (!_sNwMgr.isStorageIpRangeAvailable(dest.getDataCenter().getId())) { super.reserve(nic, network, vm, dest, context); @@ -146,7 +146,7 @@ public class StorageNetworkGuru extends PodBasedNetworkGuru implements NetworkGu } @Override - public boolean release(NicProfile nic, VirtualMachineProfile vm, String reservationId) { + public boolean release(NicProfile nic, VirtualMachineProfile vm, String reservationId) { Network nw = _nwDao.findById(nic.getNetworkId()); if (!_sNwMgr.isStorageIpRangeAvailable(nw.getDataCenterId())) { return super.release(nic, vm, reservationId); @@ -159,7 +159,7 @@ public class StorageNetworkGuru extends PodBasedNetworkGuru implements NetworkGu } @Override - public void deallocate(Network network, NicProfile nic, VirtualMachineProfile vm) { + public void deallocate(Network network, NicProfile nic, VirtualMachineProfile vm) { // TODO Auto-generated method stub } diff --git a/server/src/com/cloud/network/router/VirtualNetworkApplianceManager.java b/server/src/com/cloud/network/router/VirtualNetworkApplianceManager.java index 72fddf4f87d..dbbc2d543ed 100644 --- a/server/src/com/cloud/network/router/VirtualNetworkApplianceManager.java +++ b/server/src/com/cloud/network/router/VirtualNetworkApplianceManager.java @@ -61,13 +61,13 @@ public interface VirtualNetworkApplianceManager extends Manager, VirtualNetworkA * @param routers TODO * */ - boolean savePasswordToRouter(Network network, NicProfile nic, VirtualMachineProfile profile, + boolean savePasswordToRouter(Network network, NicProfile nic, VirtualMachineProfile profile, List routers) throws ResourceUnavailableException; - boolean saveSSHPublicKeyToRouter(Network network, NicProfile nic, VirtualMachineProfile profile, + boolean saveSSHPublicKeyToRouter(Network network, NicProfile nic, VirtualMachineProfile profile, List routers, String SSHPublicKey) throws ResourceUnavailableException; - boolean saveUserDataToRouter(Network network, NicProfile nic, VirtualMachineProfile profile, + boolean saveUserDataToRouter(Network network, NicProfile nic, VirtualMachineProfile profile, List routers) throws ResourceUnavailableException; List deployVirtualRouterInGuestNetwork(Network guestNetwork, DeployDestination dest, Account owner, @@ -99,16 +99,16 @@ public interface VirtualNetworkApplianceManager extends Manager, VirtualNetworkA boolean applyStaticNats(Network network, final List rules, List routers) throws ResourceUnavailableException; - boolean applyDhcpEntry(Network config, NicProfile nic, VirtualMachineProfile vm, DeployDestination dest, + boolean applyDhcpEntry(Network config, NicProfile nic, VirtualMachineProfile vm, DeployDestination dest, List routers) throws ResourceUnavailableException; - boolean applyUserData(Network config, NicProfile nic, VirtualMachineProfile vm, DeployDestination dest, + boolean applyUserData(Network config, NicProfile nic, VirtualMachineProfile vm, DeployDestination dest, List routers) throws ResourceUnavailableException; boolean applyLoadBalancingRules(Network network, List rules, List routers) throws ResourceUnavailableException; - boolean configDhcpForSubnet(Network network, NicProfile nic, VirtualMachineProfile uservm, DeployDestination dest, List routers) throws ResourceUnavailableException ; + boolean configDhcpForSubnet(Network network, NicProfile nic, VirtualMachineProfile uservm, DeployDestination dest, List routers) throws ResourceUnavailableException ; boolean removeDhcpSupportForSubnet(Network network, List routers) throws ResourceUnavailableException; diff --git a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java index d05d8e88bea..ef7f50b85e1 100755 --- a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java +++ b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java @@ -485,10 +485,10 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V } @Override - public boolean savePasswordToRouter(Network network, final NicProfile nic, VirtualMachineProfile profile, List routers) throws ResourceUnavailableException { + public boolean savePasswordToRouter(Network network, final NicProfile nic, VirtualMachineProfile profile, List routers) throws ResourceUnavailableException { _userVmDao.loadDetails((UserVmVO) profile.getVirtualMachine()); - final VirtualMachineProfile updatedProfile = profile; + final VirtualMachineProfile updatedProfile = profile; return applyRules(network, routers, "save password entry", false, null, false, new RuleApplier() { @Override @@ -503,10 +503,11 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V } @Override - public boolean saveSSHPublicKeyToRouter(Network network, final NicProfile nic, VirtualMachineProfile profile, List routers, final String SSHPublicKey) throws ResourceUnavailableException { - _userVmDao.loadDetails((UserVmVO) profile.getVirtualMachine()); + public boolean saveSSHPublicKeyToRouter(Network network, final NicProfile nic, VirtualMachineProfile profile, List routers, final String SSHPublicKey) throws ResourceUnavailableException { + final UserVmVO vm = _userVmDao.findById(profile.getVirtualMachine().getId()); + _userVmDao.loadDetails(vm); - final VirtualMachineProfile updatedProfile = profile; + final VirtualMachineProfile updatedProfile = profile; return applyRules(network, routers, "save SSHkey entry", false, null, false, new RuleApplier() { @Override @@ -518,17 +519,16 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V if(template != null && template.getEnablePassword()) { createPasswordCommand(router, updatedProfile, nicVo, cmds); } - createVmDataCommand(router, updatedProfile.getVirtualMachine(), nicVo, SSHPublicKey, cmds); + createVmDataCommand(router, vm, nicVo, SSHPublicKey, cmds); return sendCommandsToRouter(router, cmds); } }); } @Override - public boolean saveUserDataToRouter(Network network, final NicProfile nic, VirtualMachineProfile profile, List routers) throws ResourceUnavailableException { - _userVmDao.loadDetails((UserVmVO) profile.getVirtualMachine()); - - final VirtualMachineProfile updatedProfile = profile; + public boolean saveUserDataToRouter(Network network, final NicProfile nic, VirtualMachineProfile profile, List routers) throws ResourceUnavailableException { + final UserVmVO vm = _userVmDao.findById(profile.getVirtualMachine().getId()); + _userVmDao.loadDetails(vm); return applyRules(network, routers, "save userdata entry", false, null, false, new RuleApplier() { @Override @@ -536,7 +536,7 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V // for basic zone, send vm data/password information only to the router in the same pod Commands cmds = new Commands(OnError.Stop); NicVO nicVo = _nicDao.findById(nic.getId()); - createVmDataCommand(router, updatedProfile.getVirtualMachine(), nicVo, null, cmds); + createVmDataCommand(router, vm, nicVo, null, cmds); return sendCommandsToRouter(router, cmds); } }); @@ -1979,7 +1979,7 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V } @Override - public boolean finalizeVirtualMachineProfile(VirtualMachineProfile profile, DeployDestination dest, + public boolean finalizeVirtualMachineProfile(VirtualMachineProfile profile, DeployDestination dest, ReservationContext context) { boolean dnsProvided = true; @@ -1989,7 +1989,7 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V _dcDao.loadDetails(dc); //1) Set router details - DomainRouterVO router = profile.getVirtualMachine(); + DomainRouterVO router = _routerDao.findById(profile.getVirtualMachine().getId()); Map details = _vmDetailsDao.findDetails(router.getId()); router.setDetails(details); @@ -2262,9 +2262,9 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V } @Override - public boolean finalizeDeployment(Commands cmds, VirtualMachineProfile profile, + public boolean finalizeDeployment(Commands cmds, VirtualMachineProfile profile, DeployDestination dest, ReservationContext context) throws ResourceUnavailableException { - DomainRouterVO router = profile.getVirtualMachine(); + DomainRouterVO router = _routerDao.findById(profile.getId()); List nics = profile.getNics(); for (NicProfile nic : nics) { @@ -2284,8 +2284,8 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V } @Override - public boolean finalizeCommandsOnStart(Commands cmds, VirtualMachineProfile profile) { - DomainRouterVO router = profile.getVirtualMachine(); + public boolean finalizeCommandsOnStart(Commands cmds, VirtualMachineProfile profile) { + DomainRouterVO router = _routerDao.findById(profile.getId()); NicProfile controlNic = getControlNic(profile); if (controlNic == null) { @@ -2324,8 +2324,8 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V return true; } - protected NicProfile getControlNic(VirtualMachineProfile profile) { - DomainRouterVO router = profile.getVirtualMachine(); + protected NicProfile getControlNic(VirtualMachineProfile profile) { + DomainRouterVO router = _routerDao.findById(profile.getId()); DataCenterVO dcVo = _dcDao.findById(router.getDataCenterId()); NicProfile controlNic = null; if (profile.getHypervisorType() == HypervisorType.VMware && dcVo.getNetworkType() == NetworkType.Basic) { @@ -2346,7 +2346,8 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V return controlNic; } - protected void finalizeSshAndVersionAndNetworkUsageOnStart(Commands cmds, VirtualMachineProfile profile, DomainRouterVO router, NicProfile controlNic) { + protected void finalizeSshAndVersionAndNetworkUsageOnStart(Commands cmds, VirtualMachineProfile profile, DomainRouterVO router, NicProfile controlNic) { + DomainRouterVO vr = _routerDao.findById(profile.getId()); cmds.addCommand("checkSsh", new CheckSshCommand(profile.getInstanceName(), controlNic.getIp4Address(), 3922)); // Update router template/scripts version @@ -2356,7 +2357,7 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V cmds.addCommand("getDomRVersion", command); // Network usage command to create iptables rules - boolean forVpc = profile.getVirtualMachine().getVpcId() != null; + boolean forVpc = vr.getVpcId() != null; if (!forVpc) cmds.addCommand("networkUsage", new NetworkUsageCommand(controlNic.getIp4Address(), router.getHostName(), "create", forVpc)); } @@ -2561,9 +2562,9 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V } @Override - public boolean finalizeStart(VirtualMachineProfile profile, long hostId, Commands cmds, + public boolean finalizeStart(VirtualMachineProfile profile, long hostId, Commands cmds, ReservationContext context) { - DomainRouterVO router = profile.getVirtualMachine(); + DomainRouterVO router = _routerDao.findById(profile.getId()); boolean result = true; @@ -2620,9 +2621,9 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V } @Override - public void finalizeStop(VirtualMachineProfile profile, StopAnswer answer) { + public void finalizeStop(VirtualMachineProfile profile, StopAnswer answer) { if (answer != null) { - VMInstanceVO vm = profile.getVirtualMachine(); + VirtualMachine vm = profile.getVirtualMachine(); DomainRouterVO domR = _routerDao.findById(vm.getId()); processStopOrRebootAnswer(domR, answer); List routerNics = _nicDao.listByVmId(profile.getId()); @@ -2765,10 +2766,10 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V } @Override - public boolean configDhcpForSubnet(Network network, final NicProfile nic, VirtualMachineProfile profile, DeployDestination dest, List routers) throws ResourceUnavailableException { - _userVmDao.loadDetails((UserVmVO) profile.getVirtualMachine()); + public boolean configDhcpForSubnet(Network network, final NicProfile nic, VirtualMachineProfile profile, DeployDestination dest, List routers) throws ResourceUnavailableException { + UserVmVO vm = _userVmDao.findById(profile.getId()); + _userVmDao.loadDetails(vm); - final VirtualMachineProfile updatedProfile = profile; final boolean isZoneBasic = (dest.getDataCenter().getNetworkType() == NetworkType.Basic); final Long podId = isZoneBasic ? dest.getPod().getId() : null; @@ -2780,7 +2781,6 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V router.getState(), DataCenter.class, network.getDataCenterId()); } //check if this is not the primary subnet. - UserVm vm = updatedProfile.getVirtualMachine(); NicVO domr_guest_nic = _nicDao.findByInstanceIdAndIpAddressAndVmtype(router.getId(), _nicDao.getIpAddress(nic.getNetworkId(), router.getId()), VirtualMachine.Type.DomainRouter); //check if the router ip address and the vm ip address belong to same subnet. //if they do not belong to same netwoek check for the alias ips. if not create one. @@ -2895,12 +2895,16 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V @Override - public boolean applyDhcpEntry(Network network, final NicProfile nic, VirtualMachineProfile profile, + public boolean applyDhcpEntry(Network network, final NicProfile nic, VirtualMachineProfile profile, DeployDestination dest, List routers) throws ResourceUnavailableException { - _userVmDao.loadDetails((UserVmVO) profile.getVirtualMachine()); + if(s_logger.isTraceEnabled()) { + s_logger.trace("applyDhcpEntry(" + network.getCidr() + ", " + nic.getMacAddress() + ", " + profile.getUuid() + ", " + dest.getHost() + ", " + routers + ")"); + } + final UserVmVO vm = _userVmDao.findById(profile.getId()); + _userVmDao.loadDetails(vm); - final VirtualMachineProfile updatedProfile = profile; + final VirtualMachineProfile updatedProfile = profile; final boolean isZoneBasic = (dest.getDataCenter().getNetworkType() == NetworkType.Basic); final Long podId = isZoneBasic ? dest.getPod().getId() : null; @@ -2918,7 +2922,7 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V Commands cmds = new Commands(OnError.Stop); if (!(isZoneBasic && router.getPodIdToDeployIn().longValue() != podId.longValue() && _dnsBasicZoneUpdates.equalsIgnoreCase("pod"))) { NicVO nicVo = _nicDao.findById(nic.getId()); - createDhcpEntryCommand(router, updatedProfile.getVirtualMachine(), nicVo, cmds); + createDhcpEntryCommand(router, vm, nicVo, cmds); return sendCommandsToRouter(router, cmds); } return true; @@ -2970,11 +2974,12 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V } @Override - public boolean applyUserData(Network network, final NicProfile nic, VirtualMachineProfile profile, DeployDestination dest, List routers) + public boolean applyUserData(Network network, final NicProfile nic, VirtualMachineProfile profile, DeployDestination dest, List routers) throws ResourceUnavailableException { - _userVmDao.loadDetails((UserVmVO) profile.getVirtualMachine()); + final UserVmVO vm = _userVmDao.findById(profile.getId()); + _userVmDao.loadDetails(vm); - final VirtualMachineProfile updatedProfile = profile; + final VirtualMachineProfile updatedProfile = profile; final boolean isZoneBasic = (dest.getDataCenter().getNetworkType() == NetworkType.Basic); final Long podId = isZoneBasic ? dest.getPod().getId() : null; @@ -2993,7 +2998,7 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V if (!(isZoneBasic && router.getPodIdToDeployIn().longValue() != podId.longValue())) { NicVO nicVo = _nicDao.findById(nic.getId()); createPasswordCommand(router, updatedProfile, nicVo, cmds); - createVmDataCommand(router, updatedProfile.getVirtualMachine(), nicVo, updatedProfile.getVirtualMachine().getDetail("SSH.PublicKey"), cmds); + createVmDataCommand(router, vm, nicVo, vm.getDetail("SSH.PublicKey"), cmds); return sendCommandsToRouter(router, cmds); } return true; @@ -3352,7 +3357,7 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V cmds.addCommand("startVpn", startVpnCmd); } - private void createPasswordCommand(VirtualRouter router, VirtualMachineProfile profile, NicVO nic, Commands cmds) { + private void createPasswordCommand(VirtualRouter router, VirtualMachineProfile profile, NicVO nic, Commands cmds) { String password = (String) profile.getParameter(VirtualMachineProfile.Param.VmPassword); DataCenterVO dcVo = _dcDao.findById(router.getDataCenterId()); @@ -3960,11 +3965,10 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V @Override - public void prepareStop(VirtualMachineProfile profile){ + public void prepareStop(VirtualMachineProfile profile){ //Collect network usage before stopping Vm - VMInstanceVO vm = profile.getVirtualMachine(); - DomainRouterVO router = _routerDao.findById(vm.getId()); + DomainRouterVO router = _routerDao.findById(profile.getVirtualMachine().getId()); if(router == null){ return; } diff --git a/server/src/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImpl.java b/server/src/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImpl.java index 5dbecb77577..6fafa3e40fc 100644 --- a/server/src/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImpl.java +++ b/server/src/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImpl.java @@ -27,7 +27,6 @@ import java.util.TreeSet; import javax.ejb.Local; import javax.inject.Inject; -import com.cloud.configuration.ZoneConfig; import org.apache.log4j.Logger; import org.springframework.stereotype.Component; @@ -38,14 +37,12 @@ import com.cloud.agent.api.PlugNicCommand; import com.cloud.agent.api.SetupGuestNetworkAnswer; import com.cloud.agent.api.SetupGuestNetworkCommand; import com.cloud.agent.api.StopAnswer; -import com.cloud.agent.api.routing.DnsMasqConfigCommand; import com.cloud.agent.api.routing.IpAssocVpcCommand; import com.cloud.agent.api.routing.NetworkElementCommand; import com.cloud.agent.api.routing.SetNetworkACLCommand; import com.cloud.agent.api.routing.SetSourceNatCommand; import com.cloud.agent.api.routing.SetStaticRouteCommand; import com.cloud.agent.api.routing.Site2SiteVpnCfgCommand; -import com.cloud.agent.api.to.DhcpTO; import com.cloud.agent.api.to.IpAddressTO; import com.cloud.agent.api.to.NetworkACLTO; import com.cloud.agent.api.to.NicTO; @@ -599,10 +596,11 @@ public class VpcVirtualNetworkApplianceManagerImpl extends VirtualNetworkApplian @Override - public boolean finalizeVirtualMachineProfile(VirtualMachineProfile profile, DeployDestination dest, + public boolean finalizeVirtualMachineProfile(VirtualMachineProfile profile, DeployDestination dest, ReservationContext context) { + DomainRouterVO vr = _routerDao.findById(profile.getId()); - if (profile.getVirtualMachine().getVpcId() != null) { + if (vr.getVpcId() != null) { String defaultDns1 = null; String defaultDns2 = null; //remove public and guest nics as we will plug them later @@ -623,7 +621,7 @@ public class VpcVirtualNetworkApplianceManagerImpl extends VirtualNetworkApplian //add vpc cidr/dns/networkdomain to the boot load args StringBuilder buf = profile.getBootArgsBuilder(); - Vpc vpc = _vpcMgr.getVpc(profile.getVirtualMachine().getVpcId()); + Vpc vpc = _vpcMgr.getVpc(vr.getVpcId()); buf.append(" vpccidr=" + vpc.getCidr() + " domain=" + vpc.getNetworkDomain()); buf.append(" dns1=").append(defaultDns1); @@ -695,8 +693,8 @@ public class VpcVirtualNetworkApplianceManagerImpl extends VirtualNetworkApplian } @Override - public boolean finalizeCommandsOnStart(Commands cmds, VirtualMachineProfile profile) { - DomainRouterVO router = profile.getVirtualMachine(); + public boolean finalizeCommandsOnStart(Commands cmds, VirtualMachineProfile profile) { + DomainRouterVO router = _routerDao.findById(profile.getId()); boolean isVpc = (router.getVpcId() != null); if (!isVpc) { @@ -1319,10 +1317,10 @@ public class VpcVirtualNetworkApplianceManagerImpl extends VirtualNetworkApplian } @Override - public void finalizeStop(VirtualMachineProfile profile, StopAnswer answer) { + public void finalizeStop(VirtualMachineProfile profile, StopAnswer answer) { super.finalizeStop(profile, answer); //Mark VPN connections as Disconnected - DomainRouterVO router = profile.getVirtualMachine(); + DomainRouterVO router = _routerDao.findById(profile.getId()); Long vpcId = router.getVpcId(); if (vpcId != null) { _s2sVpnMgr.markDisconnectVpnConnByVpc(vpcId); diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java index 8d979c7d1c2..23e2ca1f036 100755 --- a/server/src/com/cloud/server/ManagementServerImpl.java +++ b/server/src/com/cloud/server/ManagementServerImpl.java @@ -1060,7 +1060,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe } // Check if the vm is using any disks on local storage. - VirtualMachineProfile vmProfile = new VirtualMachineProfileImpl(vm); + VirtualMachineProfile vmProfile = new VirtualMachineProfileImpl(vm); List volumes = _volumeDao.findCreatedByInstance(vmProfile.getId()); boolean usesLocal = false; for (VolumeVO volume : volumes) { @@ -1156,7 +1156,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe suitableHosts, requiresStorageMotion); } - private Map> findSuitablePoolsForVolumes(VirtualMachineProfile vmProfile, + private Map> findSuitablePoolsForVolumes(VirtualMachineProfile vmProfile, Host host) { List volumes = _volumeDao.findCreatedByInstance(vmProfile.getId()); Map> suitableVolumeStoragePools = new HashMap>(); @@ -1284,7 +1284,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe // Volume stays in the same cluster after migration. DataCenterDeployment plan = new DataCenterDeployment(volume.getDataCenterId(), srcVolumePool.getPodId(), srcVolumePool.getClusterId(), null, null, null); - VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm); + VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm); DiskOfferingVO diskOffering = _diskOfferingDao.findById(volume.getDiskOfferingId()); DiskProfile diskProfile = new DiskProfile(volume, diskOffering, profile.getHypervisorType()); diff --git a/server/src/com/cloud/storage/StorageManagerImpl.java b/server/src/com/cloud/storage/StorageManagerImpl.java index 8a5085ef1f3..cd966cdd565 100755 --- a/server/src/com/cloud/storage/StorageManagerImpl.java +++ b/server/src/com/cloud/storage/StorageManagerImpl.java @@ -403,7 +403,7 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C public StoragePool findStoragePool(DiskProfile dskCh, final DataCenterVO dc, Pod pod, Long clusterId, Long hostId, VMInstanceVO vm, final Set avoid) { - VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm); + VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm); for (StoragePoolAllocator allocator : _storagePoolAllocators) { ExcludeList avoidList = new ExcludeList(); diff --git a/server/src/com/cloud/storage/VolumeManager.java b/server/src/com/cloud/storage/VolumeManager.java index 2e44a3c35b3..d9bbd541713 100644 --- a/server/src/com/cloud/storage/VolumeManager.java +++ b/server/src/com/cloud/storage/VolumeManager.java @@ -41,7 +41,6 @@ import com.cloud.storage.Volume.Type; import com.cloud.user.Account; import com.cloud.vm.DiskProfile; import com.cloud.vm.VMInstanceVO; -import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachineProfile; public interface VolumeManager extends VolumeApiService { @@ -85,7 +84,7 @@ public interface VolumeManager extends VolumeApiService { @Override Volume detachVolumeFromVM(DetachVolumeCmd cmmd); - void release(VirtualMachineProfile profile); + void release(VirtualMachineProfile profile); void cleanupVolumes(long vmId) throws ConcurrentOperationException; @@ -95,15 +94,11 @@ public interface VolumeManager extends VolumeApiService { void migrateVolumes(T vm, VirtualMachineTO vmTo, Host srcHost, Host destHost, Map volumeToPool); - boolean storageMigration( - VirtualMachineProfile vm, - StoragePool destPool); + boolean storageMigration(VirtualMachineProfile vm, StoragePool destPool); - void prepareForMigration( - VirtualMachineProfile vm, - DeployDestination dest); + void prepareForMigration(VirtualMachineProfile vm, DeployDestination dest); - void prepare(VirtualMachineProfile vm, + void prepare(VirtualMachineProfile vm, DeployDestination dest) throws StorageUnavailableException, InsufficientStorageCapacityException, ConcurrentOperationException; diff --git a/server/src/com/cloud/storage/VolumeManagerImpl.java b/server/src/com/cloud/storage/VolumeManagerImpl.java index 7b44c5c29d8..fa7a33a51b9 100644 --- a/server/src/com/cloud/storage/VolumeManagerImpl.java +++ b/server/src/com/cloud/storage/VolumeManagerImpl.java @@ -2031,7 +2031,7 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { @DB protected VolumeVO switchVolume(VolumeVO existingVolume, - VirtualMachineProfile vm) + VirtualMachineProfile vm) throws StorageUnavailableException { Transaction txn = Transaction.currentTxn(); @@ -2070,7 +2070,7 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { @Override - public void release(VirtualMachineProfile profile) { + public void release(VirtualMachineProfile profile) { // add code here } @@ -2269,7 +2269,7 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { @Override public boolean storageMigration( - VirtualMachineProfile vm, + VirtualMachineProfile vm, StoragePool destPool) { List vols = _volsDao.findUsableVolumesForInstance(vm.getId()); List volumesNeedToMigrate = new ArrayList(); @@ -2307,7 +2307,7 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { @Override public void prepareForMigration( - VirtualMachineProfile vm, + VirtualMachineProfile vm, DeployDestination dest) { List vols = _volsDao.findUsableVolumesForInstance(vm.getId()); if (s_logger.isDebugEnabled()) { @@ -2439,7 +2439,7 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { return tasks; } - private Pair recreateVolume(VolumeVO vol, VirtualMachineProfile vm, + private Pair recreateVolume(VolumeVO vol, VirtualMachineProfile vm, DeployDestination dest) throws StorageUnavailableException { VolumeVO newVol; boolean recreate = _recreateSystemVmEnabled; @@ -2506,7 +2506,7 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { } @Override - public void prepare(VirtualMachineProfile vm, + public void prepare(VirtualMachineProfile vm, DeployDestination dest) throws StorageUnavailableException, InsufficientStorageCapacityException, ConcurrentOperationException { diff --git a/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java b/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java index f7a72190097..037eb258323 100755 --- a/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java +++ b/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java @@ -107,7 +107,6 @@ import com.cloud.storage.template.TemplateConstants; import com.cloud.template.TemplateManager; import com.cloud.user.Account; import com.cloud.user.AccountService; -import com.cloud.user.User; import com.cloud.utils.DateUtil; import com.cloud.utils.NumbersUtil; import com.cloud.utils.Pair; @@ -257,8 +256,6 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar public SecondaryStorageVmVO startSecStorageVm(long secStorageVmId) { try { SecondaryStorageVmVO secStorageVm = _secStorageVmDao.findById(secStorageVmId); - Account systemAcct = _accountMgr.getSystemAccount(); - User systemUser = _accountMgr.getSystemUser(); _itMgr.advanceStart(secStorageVm.getUuid(), null); return _secStorageVmDao.findById(secStorageVm.getId()); } catch (StorageUnavailableException e) { @@ -1011,9 +1008,9 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar } @Override - public boolean finalizeVirtualMachineProfile(VirtualMachineProfile profile, DeployDestination dest, ReservationContext context) { + public boolean finalizeVirtualMachineProfile(VirtualMachineProfile profile, DeployDestination dest, ReservationContext context) { - SecondaryStorageVmVO vm = profile.getVirtualMachine(); + SecondaryStorageVmVO vm = _secStorageVmDao.findById(profile.getId()); Map details = _vmDetailsDao.findDetails(vm.getId()); vm.setDetails(details); @@ -1044,7 +1041,7 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar } buf.append(" instance=SecStorage"); buf.append(" sslcopy=").append(Boolean.toString(_useSSlCopy)); - buf.append(" role=").append(profile.getVirtualMachine().getRole().toString()); + buf.append(" role=").append(vm.getRole().toString()); buf.append(" mtu=").append(_secStorageVmMtuSize); boolean externalDhcp = false; @@ -1110,11 +1107,11 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar } @Override - public boolean finalizeDeployment(Commands cmds, VirtualMachineProfile profile, DeployDestination dest, ReservationContext context) { + public boolean finalizeDeployment(Commands cmds, VirtualMachineProfile profile, DeployDestination dest, ReservationContext context) { finalizeCommandsOnStart(cmds, profile); - SecondaryStorageVmVO secVm = profile.getVirtualMachine(); + SecondaryStorageVmVO secVm = _secStorageVmDao.findById(profile.getId()); DataCenter dc = dest.getDataCenter(); List nics = profile.getNics(); for (NicProfile nic : nics) { @@ -1133,7 +1130,7 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar } @Override - public boolean finalizeCommandsOnStart(Commands cmds, VirtualMachineProfile profile) { + public boolean finalizeCommandsOnStart(Commands cmds, VirtualMachineProfile profile) { NicProfile managementNic = null; NicProfile controlNic = null; @@ -1160,7 +1157,7 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar } @Override - public boolean finalizeStart(VirtualMachineProfile profile, long hostId, Commands cmds, ReservationContext context) { + public boolean finalizeStart(VirtualMachineProfile profile, long hostId, Commands cmds, ReservationContext context) { CheckSshAnswer answer = (CheckSshAnswer) cmds.getAnswer("checkSsh"); if (!answer.getResult()) { s_logger.warn("Unable to ssh to the VM: " + answer.getDetails()); @@ -1172,7 +1169,7 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar _rulesMgr.getSystemIpAndEnableStaticNatForVm(profile.getVirtualMachine(), false); IPAddressVO ipaddr = _ipAddressDao.findByAssociatedVmId(profile.getVirtualMachine().getId()); if (ipaddr != null && ipaddr.getSystem()) { - SecondaryStorageVmVO secVm = profile.getVirtualMachine(); + SecondaryStorageVmVO secVm = _secStorageVmDao.findById(profile.getId()); // override SSVM guest IP with EIP, so that download url's with be prepared with EIP secVm.setPublicIpAddress(ipaddr.getAddress().addr()); _secStorageVmDao.update(secVm.getId(), secVm); @@ -1186,7 +1183,7 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar } @Override - public void finalizeStop(VirtualMachineProfile profile, StopAnswer answer) { + public void finalizeStop(VirtualMachineProfile profile, StopAnswer answer) { //release elastic IP here IPAddressVO ip = _ipAddressDao.findByAssociatedVmId(profile.getId()); if (ip != null && ip.getSystem()) { @@ -1381,7 +1378,7 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar } @Override - public void prepareStop(VirtualMachineProfile profile) { + public void prepareStop(VirtualMachineProfile profile) { } } diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java b/server/src/com/cloud/vm/UserVmManagerImpl.java index f353bb74d74..14938717672 100755 --- a/server/src/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/com/cloud/vm/UserVmManagerImpl.java @@ -539,7 +539,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use Network defaultNetwork = _networkDao.findById(defaultNic.getNetworkId()); NicProfile defaultNicProfile = new NicProfile(defaultNic, defaultNetwork, null, null, null, _networkModel.isSecurityGroupSupportedInNetwork(defaultNetwork), _networkModel.getNetworkTag(template.getHypervisorType(), defaultNetwork)); - VirtualMachineProfile vmProfile = new VirtualMachineProfileImpl(vmInstance); + VirtualMachineProfile vmProfile = new VirtualMachineProfileImpl(vmInstance); vmProfile.setParameter(VirtualMachineProfile.Param.VmPassword, password); UserDataServiceProvider element = _networkMgr.getPasswordResetProvider(defaultNetwork); @@ -656,7 +656,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use _networkModel.isSecurityGroupSupportedInNetwork(defaultNetwork), _networkModel.getNetworkTag(template.getHypervisorType(), defaultNetwork)); - VirtualMachineProfile vmProfile = new VirtualMachineProfileImpl(vmInstance); + VirtualMachineProfile vmProfile = new VirtualMachineProfileImpl(vmInstance); if (template != null && template.getEnablePassword()) { vmProfile.setParameter(VirtualMachineProfile.Param.VmPassword, password); @@ -1831,7 +1831,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use _networkModel.isSecurityGroupSupportedInNetwork(network), _networkModel.getNetworkTag(template.getHypervisorType(), network)); - VirtualMachineProfile vmProfile = new VirtualMachineProfileImpl((VMInstanceVO)vm); + VirtualMachineProfile vmProfile = new VirtualMachineProfileImpl(vm); UserDataServiceProvider element = _networkModel.getUserDataUpdateProvider(network); if (element == null) { @@ -2888,10 +2888,8 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use } @Override - public boolean finalizeVirtualMachineProfile( - VirtualMachineProfile profile, DeployDestination dest, - ReservationContext context) { - UserVmVO vm = profile.getVirtualMachine(); + public boolean finalizeVirtualMachineProfile(VirtualMachineProfile profile, DeployDestination dest, ReservationContext context) { + UserVmVO vm = _vmDao.findById(profile.getId()); Map details = _vmDetailsDao.findDetails(vm.getId()); vm.setDetails(details); @@ -2959,9 +2957,9 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use @Override public boolean finalizeDeployment(Commands cmds, - VirtualMachineProfile profile, DeployDestination dest, + VirtualMachineProfile profile, DeployDestination dest, ReservationContext context) { - UserVmVO userVm = profile.getVirtualMachine(); + UserVmVO userVm = _vmDao.findById(profile.getId()); List nics = _nicDao.listByVmId(userVm.getId()); for (NicVO nic : nics) { NetworkVO network = _networkDao.findById(nic.getNetworkId()); @@ -2987,14 +2985,14 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use @Override public boolean finalizeCommandsOnStart(Commands cmds, - VirtualMachineProfile profile) { + VirtualMachineProfile profile) { return true; } @Override - public boolean finalizeStart(VirtualMachineProfile profile, + public boolean finalizeStart(VirtualMachineProfile profile, long hostId, Commands cmds, ReservationContext context) { - UserVmVO vm = profile.getVirtualMachine(); + UserVmVO vm = _vmDao.findById(profile.getId()); Answer[] answersToCmds = cmds.getAnswers(); if (answersToCmds == null) { @@ -3055,7 +3053,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use } if (ipChanged) { DataCenterVO dc = _dcDao.findById(vm.getDataCenterId()); - UserVmVO userVm = profile.getVirtualMachine(); + UserVmVO userVm = _vmDao.findById(profile.getId()); // dc.getDhcpProvider().equalsIgnoreCase(Provider.ExternalDhcpServer.getName()) if (_ntwkSrvcDao.canProviderSupportServiceInNetwork( guestNetwork.getId(), Service.Dhcp, @@ -3135,8 +3133,8 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use } @Override - public void finalizeStop(VirtualMachineProfile profile, - StopAnswer answer) { + public void finalizeStop(VirtualMachineProfile profile, StopAnswer answer) { + VirtualMachine vm = profile.getVirtualMachine(); // release elastic IP here IPAddressVO ip = _ipAddressDao.findByAssociatedVmId(profile.getId()); if (ip != null && ip.getSystem()) { @@ -3156,7 +3154,6 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use } } - VMInstanceVO vm = profile.getVirtualMachine(); List nics = _nicDao.listByVmId(vm.getId()); for (NicVO nic : nics) { NetworkVO network = _networkDao.findById(nic.getNetworkId()); @@ -4210,7 +4207,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use txn.commit(); VMInstanceVO vmoi = _itMgr.findByIdAndType(vm.getType(), vm.getId()); - VirtualMachineProfileImpl vmOldProfile = new VirtualMachineProfileImpl( + VirtualMachineProfileImpl vmOldProfile = new VirtualMachineProfileImpl( vmoi); // OS 3: update the network @@ -4288,7 +4285,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use profile)); VMInstanceVO vmi = _itMgr.findByIdAndType(vm.getType(), vm.getId()); - VirtualMachineProfileImpl vmProfile = new VirtualMachineProfileImpl( + VirtualMachineProfileImpl vmProfile = new VirtualMachineProfileImpl( vmi); _networkMgr.allocate(vmProfile, networks); @@ -4423,7 +4420,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use } VMInstanceVO vmi = _itMgr.findByIdAndType(vm.getType(), vm.getId()); - VirtualMachineProfileImpl vmProfile = new VirtualMachineProfileImpl( + VirtualMachineProfileImpl vmProfile = new VirtualMachineProfileImpl( vmi); _networkMgr.allocate(vmProfile, networks); s_logger.debug("AssignVM: Advance virtual, adding networks no " @@ -4604,7 +4601,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use } @Override - public void prepareStop(VirtualMachineProfile profile) { + public void prepareStop(VirtualMachineProfile profile) { UserVmVO vm = _vmDao.findById(profile.getId()); if (vm.getState() == State.Running) collectVmDiskStatistics(vm); diff --git a/server/src/com/cloud/vm/VirtualMachineGuru.java b/server/src/com/cloud/vm/VirtualMachineGuru.java index df34e0eafa7..3318b461451 100644 --- a/server/src/com/cloud/vm/VirtualMachineGuru.java +++ b/server/src/com/cloud/vm/VirtualMachineGuru.java @@ -5,7 +5,7 @@ // 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, @@ -28,7 +28,7 @@ import com.cloud.exception.ResourceUnavailableException; public interface VirtualMachineGuru { T findById(long id); - boolean finalizeVirtualMachineProfile(VirtualMachineProfile profile, DeployDestination dest, ReservationContext context); + boolean finalizeVirtualMachineProfile(VirtualMachineProfile profile, DeployDestination dest, ReservationContext context); /** * finalize the virtual machine deployment. @@ -37,7 +37,7 @@ public interface VirtualMachineGuru { * @param dest destination to send the command. * @return true if everything checks out. false if not and we should try again. */ - boolean finalizeDeployment(Commands cmds, VirtualMachineProfile profile, DeployDestination dest, ReservationContext context) throws ResourceUnavailableException; + boolean finalizeDeployment(Commands cmds, VirtualMachineProfile profile, DeployDestination dest, ReservationContext context) throws ResourceUnavailableException; /** * Check the deployment results. @@ -46,11 +46,11 @@ public interface VirtualMachineGuru { * @param dest destination it was sent to. * @return true if deployment was fine; false if it didn't go well. */ - boolean finalizeStart(VirtualMachineProfile profile, long hostId, Commands cmds, ReservationContext context); + boolean finalizeStart(VirtualMachineProfile profile, long hostId, Commands cmds, ReservationContext context); - boolean finalizeCommandsOnStart(Commands cmds, VirtualMachineProfile profile); + boolean finalizeCommandsOnStart(Commands cmds, VirtualMachineProfile profile); - void finalizeStop(VirtualMachineProfile profile, StopAnswer answer); + void finalizeStop(VirtualMachineProfile profile, StopAnswer answer); void finalizeExpunge(T vm); @@ -59,5 +59,5 @@ public interface VirtualMachineGuru { * @param profile * @return */ - void prepareStop(VirtualMachineProfile profile); + void prepareStop(VirtualMachineProfile profile); } diff --git a/server/src/com/cloud/vm/VirtualMachineManager.java b/server/src/com/cloud/vm/VirtualMachineManager.java index 49953b97331..0086bdb6dbc 100644 --- a/server/src/com/cloud/vm/VirtualMachineManager.java +++ b/server/src/com/cloud/vm/VirtualMachineManager.java @@ -179,7 +179,7 @@ public interface VirtualMachineManager extends Manager { * @param hvGuru * @return */ - VirtualMachineTO toVmTO(VirtualMachineProfile profile); + VirtualMachineTO toVmTO(VirtualMachineProfile profile); VMInstanceVO reConfigureVm(VMInstanceVO vm, ServiceOffering newServiceOffering, boolean sameHost) diff --git a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java index 363bb454e61..88faea00782 100755 --- a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java +++ b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java @@ -470,7 +470,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac removeDhcpServiceInsubnet(vm); } - VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm); + VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm); HypervisorGuru hvGuru = _hvGuruMgr.getGuru(vm.getHypervisorType()); @@ -737,7 +737,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac } } - protected boolean areAffinityGroupsAssociated(VirtualMachineProfile vmProfile) { + protected boolean areAffinityGroupsAssociated(VirtualMachineProfile vmProfile) { VirtualMachine vm = vmProfile.getVirtualMachine(); long vmGroupCount = _affinityGroupVMMapDao.countAffinityGroupsForVm(vm.getId()); @@ -1060,8 +1060,8 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac } } - protected boolean sendStop(VirtualMachineGuru guru, VirtualMachineProfile profile, boolean force) { - VMInstanceVO vm = profile.getVirtualMachine(); + protected boolean sendStop(VirtualMachineGuru guru, VirtualMachineProfile profile, boolean force) { + VirtualMachine vm = profile.getVirtualMachine(); StopCommand stop = new StopCommand(vm, _mgmtServer.getExecuteInSequence()); try { Answer answer = _agentMgr.send(vm.getHostId(), stop); @@ -1195,7 +1195,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac } VirtualMachineGuru vmGuru = getVmGuru(vm); - VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm); + VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm); try { if (!stateTransitTo(vm, Event.StopRequested, vm.getHostId())) { @@ -1223,7 +1223,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac } if (doCleanup) { - if (cleanup(vmGuru, new VirtualMachineProfileImpl(vm), work, Event.StopRequested, forced, user, account)) { + if (cleanup(vmGuru, new VirtualMachineProfileImpl(vm), work, Event.StopRequested, forced, user, account)) { try { if (s_logger.isDebugEnabled()) { s_logger.debug("Updating work item to Done, id:" + work.getId()); @@ -1440,7 +1440,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac throw new CloudRuntimeException("Unable to migrate vm: " + e.toString()); } - VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm); + VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm); boolean migrationResult = false; try { migrationResult = volumeMgr.storageMigration(profile, destPool); @@ -1450,7 +1450,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac if (!vm.getPodIdToDeployIn().equals(destPool.getPodId())) { DataCenterDeployment plan = new DataCenterDeployment(vm.getDataCenterId(), destPool.getPodId(), null, null, null, null); - VirtualMachineProfileImpl vmProfile = new VirtualMachineProfileImpl(vm, null, null, null, null); + VirtualMachineProfileImpl vmProfile = new VirtualMachineProfileImpl(vm, null, null, null, null); _networkMgr.reallocate(vmProfile, plan); } @@ -1526,12 +1526,12 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac alertType = AlertManager.ALERT_TYPE_CONSOLE_PROXY_MIGRATE; } - VirtualMachineProfile vmSrc = new VirtualMachineProfileImpl(vm); + VirtualMachineProfile vmSrc = new VirtualMachineProfileImpl(vm); for(NicProfile nic: _networkMgr.getNicProfiles(vm)){ vmSrc.addNic(nic); } - VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm); + VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm); _networkMgr.prepareNicForMigration(profile, dest); volumeMgr.prepareForMigration(profile, dest); @@ -1611,7 +1611,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac } catch (AgentUnavailableException e) { s_logger.error("AgentUnavailableException while cleanup on source host: " + srcHostId); } - cleanup(vmGuru, new VirtualMachineProfileImpl(vm), work, Event.AgentReportStopped, true, _accountMgr.getSystemUser(), _accountMgr.getSystemAccount()); + cleanup(vmGuru, new VirtualMachineProfileImpl(vm), work, Event.AgentReportStopped, true, _accountMgr.getSystemUser(), _accountMgr.getSystemAccount()); return null; } } catch (OperationTimedoutException e) { @@ -1646,7 +1646,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac } } - private Map getPoolListForVolumesForMigration(VirtualMachineProfile profile, + private Map getPoolListForVolumesForMigration(VirtualMachineProfile profile, Host host, Map volumeToPool) { List allVolumes = _volsDao.findUsableVolumesForInstance(profile.getId()); for (VolumeVO volume : allVolumes) { @@ -1750,7 +1750,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac // Create a map of which volume should go in which storage pool. long vmId = vm.getId(); vm = vmGuru.findById(vmId); - VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm); + VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm); volumeToPool = getPoolListForVolumesForMigration(profile, destHost, volumeToPool); // If none of the volumes have to be migrated, fail the call. Administrator needs to make a call for migrating @@ -1798,7 +1798,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac } catch (AgentUnavailableException e) { s_logger.error("AgentUnavailableException while cleanup on source host: " + srcHostId); } - cleanup(vmGuru, new VirtualMachineProfileImpl(vm), work, Event.AgentReportStopped, true, + cleanup(vmGuru, new VirtualMachineProfileImpl(vm), work, Event.AgentReportStopped, true, _accountMgr.getSystemUser(), _accountMgr.getSystemAccount()); return null; } @@ -1829,8 +1829,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac } } - @Override - public VirtualMachineTO toVmTO(VirtualMachineProfile profile) { + public VirtualMachineTO toVmTO(VirtualMachineProfile profile) { HypervisorGuru hvGuru = _hvGuruMgr.getGuru(profile.getVirtualMachine().getHypervisorType()); VirtualMachineTO to = hvGuru.implement(profile); return to; @@ -1884,7 +1883,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac return true; } - VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm); + VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm); Long hostId = vm.getHostId(); if (hostId == null) { @@ -2563,7 +2562,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac vm = vmGuru.findById(vm.getId()); // this should ensure vm has the most // up to date info - VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm); + VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm); List nics = _nicsDao.listByVmId(profile.getId()); for (NicVO nic : nics) { Network network = _networkModel.getNetwork(nic.getNetworkId()); @@ -2878,7 +2877,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac ReservationContext context = new ReservationContextImpl(null, null, _accountMgr.getActiveUser(User.UID_SYSTEM), _accountMgr.getAccount(Account.ACCOUNT_ID_SYSTEM)); - VirtualMachineProfileImpl vmProfile = new VirtualMachineProfileImpl(vmVO, null, + VirtualMachineProfileImpl vmProfile = new VirtualMachineProfileImpl(vmVO, null, null, null, null); DataCenter dc = _configMgr.getZone(network.getDataCenterId()); @@ -2947,7 +2946,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac ReservationContext context = new ReservationContextImpl(null, null, _accountMgr.getActiveUser(User.UID_SYSTEM), _accountMgr.getAccount(Account.ACCOUNT_ID_SYSTEM)); - VirtualMachineProfileImpl vmProfile = new VirtualMachineProfileImpl(vmVO, null, + VirtualMachineProfileImpl vmProfile = new VirtualMachineProfileImpl(vmVO, null, null, null, null); DataCenter dc = _configMgr.getZone(network.getDataCenterId()); @@ -3011,7 +3010,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac ReservationContext context = new ReservationContextImpl(null, null, _accountMgr.getActiveUser(User.UID_SYSTEM), _accountMgr.getAccount(Account.ACCOUNT_ID_SYSTEM)); - VirtualMachineProfileImpl vmProfile = new VirtualMachineProfileImpl(vmVO, null, + VirtualMachineProfileImpl vmProfile = new VirtualMachineProfileImpl(vmVO, null, null, null, null); DataCenter dc = _configMgr.getZone(network.getDataCenterId()); @@ -3075,7 +3074,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac public VMInstanceVO findHostAndMigrate(VirtualMachine.Type vmType, VMInstanceVO vm, Long newSvcOfferingId, ExcludeList excludes) throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException, VirtualMachineMigrationException, ManagementServerException { - VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm); + VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm); Long srcHostId = vm.getHostId(); Long oldSvcOfferingId = vm.getServiceOfferingId(); @@ -3179,7 +3178,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac alertType = AlertManager.ALERT_TYPE_CONSOLE_PROXY_MIGRATE; } - VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm); + VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm); _networkMgr.prepareNicForMigration(profile, dest); volumeMgr.prepareForMigration(profile, dest); @@ -3259,7 +3258,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac } catch (AgentUnavailableException e) { s_logger.error("AgentUnavailableException while cleanup on source host: " + srcHostId); } - cleanup(vmGuru, new VirtualMachineProfileImpl(vm), work, Event.AgentReportStopped, true, _accountMgr.getSystemUser(), _accountMgr.getSystemAccount()); + cleanup(vmGuru, new VirtualMachineProfileImpl(vm), work, Event.AgentReportStopped, true, _accountMgr.getSystemUser(), _accountMgr.getSystemAccount()); return null; } } catch (OperationTimedoutException e) { diff --git a/server/src/com/cloud/vm/VirtualMachineProfileImpl.java b/server/src/com/cloud/vm/VirtualMachineProfileImpl.java index 033daf33422..5e84c1f235d 100644 --- a/server/src/com/cloud/vm/VirtualMachineProfileImpl.java +++ b/server/src/com/cloud/vm/VirtualMachineProfileImpl.java @@ -21,9 +21,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; - import com.cloud.agent.api.to.DiskTO; - import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.offering.ServiceOffering; import com.cloud.service.ServiceOfferingVO; @@ -39,9 +37,9 @@ import com.cloud.user.dao.AccountDao; * Implementation of VirtualMachineProfile. * */ -public class VirtualMachineProfileImpl implements VirtualMachineProfile { +public class VirtualMachineProfileImpl implements VirtualMachineProfile { - T _vm; + VirtualMachine _vm; ServiceOfferingVO _offering; VMTemplateVO _template; UserVmDetailVO _userVmDetails; @@ -56,7 +54,7 @@ public class VirtualMachineProfileImpl implements Virtua VirtualMachine.Type _type; - public VirtualMachineProfileImpl(T vm, VMTemplateVO template, ServiceOfferingVO offering, Account owner, Map params) { + public VirtualMachineProfileImpl(VirtualMachine vm, VMTemplateVO template, ServiceOfferingVO offering, Account owner, Map params) { _vm = vm; _template = template; _offering = offering; @@ -69,7 +67,7 @@ public class VirtualMachineProfileImpl implements Virtua _type = vm.getType(); } - public VirtualMachineProfileImpl(T vm) { + public VirtualMachineProfileImpl(VirtualMachine vm) { this(vm, null, null, null, null); } @@ -83,7 +81,7 @@ public class VirtualMachineProfileImpl implements Virtua } @Override - public T getVirtualMachine() { + public VirtualMachine getVirtualMachine() { return _vm; } @@ -102,7 +100,7 @@ public class VirtualMachineProfileImpl implements Virtua @Override public void setBootLoaderType(BootloaderType bootLoader) { - this._bootloader = bootLoader; + _bootloader = bootLoader; } @Override @@ -232,7 +230,7 @@ public class VirtualMachineProfileImpl implements Virtua @Override public BootloaderType getBootLoaderType() { - return this._bootloader; + return _bootloader; } @Override @@ -256,11 +254,11 @@ public class VirtualMachineProfileImpl implements Virtua @Override public Float getCpuOvercommitRatio() { - return this.cpuOvercommitRatio; + return cpuOvercommitRatio; } @Override public Float getMemoryOvercommitRatio() { - return this.memoryOvercommitRatio; + return memoryOvercommitRatio; } } diff --git a/server/test/com/cloud/network/MockNetworkManagerImpl.java b/server/test/com/cloud/network/MockNetworkManagerImpl.java deleted file mode 100755 index 4577d0ae781..00000000000 --- a/server/test/com/cloud/network/MockNetworkManagerImpl.java +++ /dev/null @@ -1,962 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. -package com.cloud.network; - -import java.util.List; -import java.util.Map; -import java.util.Set; - -import javax.ejb.Local; -import javax.naming.ConfigurationException; - -import org.apache.cloudstack.acl.ControlledEntity.ACLType; -import org.apache.cloudstack.api.command.admin.usage.ListTrafficTypeImplementorsCmd; -import org.apache.cloudstack.api.command.user.network.CreateNetworkCmd; -import org.apache.cloudstack.api.command.user.network.ListNetworksCmd; -import org.apache.cloudstack.api.command.user.network.RestartNetworkCmd; -import org.apache.cloudstack.api.command.user.vm.ListNicsCmd; -import org.springframework.stereotype.Component; - -import com.cloud.dc.DataCenter; -import com.cloud.dc.Pod; -import com.cloud.dc.Vlan.VlanType; -import com.cloud.deploy.DataCenterDeployment; -import com.cloud.deploy.DeployDestination; -import com.cloud.deploy.DeploymentPlan; -import com.cloud.exception.ConcurrentOperationException; -import com.cloud.exception.InsufficientAddressCapacityException; -import com.cloud.exception.InsufficientCapacityException; -import com.cloud.exception.InsufficientVirtualNetworkCapcityException; -import com.cloud.exception.ResourceAllocationException; -import com.cloud.exception.ResourceUnavailableException; -import com.cloud.network.Network.Provider; -import com.cloud.network.Network.Service; -import com.cloud.network.Networks.TrafficType; -import com.cloud.network.addr.PublicIp; -import com.cloud.network.dao.IPAddressVO; -import com.cloud.network.dao.NetworkVO; -import com.cloud.network.GuestVlan; -import com.cloud.network.element.DhcpServiceProvider; -import com.cloud.network.element.LoadBalancingServiceProvider; -import com.cloud.network.element.StaticNatServiceProvider; -import com.cloud.network.element.UserDataServiceProvider; -import com.cloud.network.guru.NetworkGuru; -import com.cloud.network.rules.FirewallRule; -import com.cloud.network.rules.FirewallRule.Purpose; -import com.cloud.network.rules.FirewallRule.State; -import com.cloud.network.rules.LoadBalancerContainer.Scheme; -import com.cloud.network.rules.StaticNat; -import com.cloud.offering.NetworkOffering; -import com.cloud.offerings.NetworkOfferingVO; -import com.cloud.user.Account; -import com.cloud.user.User; -import com.cloud.utils.Pair; -import com.cloud.utils.component.ManagerBase; -import com.cloud.vm.*; -import com.cloud.vm.VirtualMachine.Type; -import org.apache.cloudstack.api.command.admin.network.DedicateGuestVlanRangeCmd; -import org.apache.cloudstack.api.command.admin.network.ListDedicatedGuestVlanRangesCmd; -import org.apache.cloudstack.api.command.admin.usage.ListTrafficTypeImplementorsCmd; -import org.apache.cloudstack.api.command.user.network.*; -import org.apache.cloudstack.api.command.user.vm.ListNicsCmd; -import org.springframework.stereotype.Component; - -import javax.ejb.Local; -import javax.naming.ConfigurationException; -import java.util.List; -import java.util.Map; -import java.util.Set; - -@Component -@Local(value = { NetworkManager.class, NetworkService.class }) -public class MockNetworkManagerImpl extends ManagerBase implements NetworkManager, NetworkService { - - @Override - public List getIsolatedNetworksOwnedByAccountInZone(long zoneId, Account owner) { - // TODO Auto-generated method stub - return null; - } - - @Override - public IPAddressVO associateIPToGuestNetwork(long ipId, long networkId, boolean releaseOnFailure) throws ResourceAllocationException, InsufficientAddressCapacityException, ConcurrentOperationException, ResourceUnavailableException { - // TODO Auto-generated method stub - return null; - } - - @Override - public IPAddressVO associatePortableIPToGuestNetwork(long ipAddrId, long networkId, boolean releaseOnFailure) throws ResourceAllocationException, ResourceUnavailableException { - return null;// TODO Auto-generated method stub - } - - @Override - public IPAddressVO disassociatePortableIPToGuestNetwork(long ipAddrId, long networkId) throws ResourceAllocationException, ResourceUnavailableException, InsufficientAddressCapacityException, ConcurrentOperationException { - return null; // TODO Auto-generated method stub - } - - @Override - public boolean isPortableIpTransferableFromNetwork(long ipAddrId, long networkId) { - return false; - } - - @Override - public void transferPortableIP(long ipAddrId, long currentNetworkId, long newNetworkId) throws ResourceAllocationException, ResourceUnavailableException, - InsufficientAddressCapacityException, ConcurrentOperationException { - - } - - @Override - public boolean releaseIpAddress(long ipAddressId) { - // TODO Auto-generated method stub - return false; - } - - @Override - public Network createGuestNetwork(CreateNetworkCmd cmd) throws InsufficientCapacityException, ConcurrentOperationException, ResourceAllocationException { - // TODO Auto-generated method stub - return null; - } - - @Override - public List searchForNetworks(ListNetworksCmd cmd) { - // TODO Auto-generated method stub - return null; - } - - @Override - public boolean deleteNetwork(long networkId) { - // TODO Auto-generated method stub - return false; - } - - @Override - public int getActiveNicsInNetwork(long networkId) { - // TODO Auto-generated method stub - return 0; - } - - @Override - public Network getNetwork(long networkId) { - // TODO Auto-generated method stub - return null; - } - - @Override - public Network getNetwork(String networkUuid) { - // TODO Auto-generated method stub - return null; - } - - @Override - public IpAddress getIp(long id) { - // TODO Auto-generated method stub - return null; - } - - @Override - public NetworkProfile convertNetworkToNetworkProfile(long networkId) { - // TODO Auto-generated method stub - return null; - } - - - @Override - public boolean configure(String name, Map params) throws ConfigurationException { - return true; - } - - @Override - public boolean start() { - return true; - } - - @Override - public boolean stop() { - // TODO Auto-generated method stub - return false; - } - - @Override - public String getName() { - // TODO Auto-generated method stub - return null; - } - - - @Override - public boolean disassociatePublicIpAddress(long id, long userId, Account caller) { - // TODO Auto-generated method stub - return false; - } - - - - @Override - public List setupNetwork(Account owner, NetworkOffering offering, DeploymentPlan plan, String name, String displayText, boolean isDefault) - throws ConcurrentOperationException { - // TODO Auto-generated method stub - return null; - } - - @Override - public List setupNetwork(Account owner, NetworkOffering offering, Network predefined, DeploymentPlan plan, String name, String displayText, boolean errorIfAlreadySetup, Long domainId, - ACLType aclType, Boolean subdomainAccess, Long vpcId, Boolean isDisplayNetworkEnabled) throws ConcurrentOperationException { - // TODO Auto-generated method stub - return null; - } - - - - @Override - public void allocate(VirtualMachineProfile vm, List> networks) throws InsufficientCapacityException, ConcurrentOperationException { - // TODO Auto-generated method stub - - } - - @Override - public void prepare(VirtualMachineProfile profile, DeployDestination dest, ReservationContext context) throws InsufficientCapacityException, ConcurrentOperationException, - ResourceUnavailableException { - // TODO Auto-generated method stub - - } - - @Override - public void release(VirtualMachineProfile vmProfile, boolean forced) { - // TODO Auto-generated method stub - - } - - @Override - public void cleanupNics(VirtualMachineProfile vm) { - // TODO Auto-generated method stub - - } - - @Override - public void expungeNics(VirtualMachineProfile vm) { - // TODO Auto-generated method stub - - } - - - @Override - public List getNicProfiles(VirtualMachine vm) { - // TODO Auto-generated method stub - return null; - } - - - - - - @Override - public Pair implementNetwork(long networkId, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException, - InsufficientCapacityException { - // TODO Auto-generated method stub - return null; - } - - - @Override - public boolean destroyNetwork(long networkId, ReservationContext context) { - // TODO Auto-generated method stub - return false; - } - - @Override - public Network createGuestNetwork(long networkOfferingId, String name, String displayText, String gateway, String cidr, String vlanId, String networkDomain, Account owner, Long domainId, - PhysicalNetwork physicalNetwork, long zoneId, ACLType aclType, Boolean subdomainAccess, Long vpcId, String gatewayv6, String cidrv6, Boolean displayNetworkEnabled, String isolatedPvlan) throws ConcurrentOperationException, InsufficientCapacityException, ResourceAllocationException { - // TODO Auto-generated method stub - return null; - } - - @Override - public boolean associateIpAddressListToAccount(long userId, long accountId, long zoneId, Long vlanId, Network networkToAssociateWith) throws InsufficientCapacityException, - ConcurrentOperationException, ResourceUnavailableException { - // TODO Auto-generated method stub - return false; - } - - - - - - @Override - public boolean applyIpAssociations(Network network, boolean continueOnError) throws ResourceUnavailableException { - // TODO Auto-generated method stub - return false; - } - - - - @Override - public boolean startNetwork(long networkId, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException { - // TODO Auto-generated method stub - return false; - } - - - @Override - public IPAddressVO markIpAsUnavailable(long addrId) { - // TODO Auto-generated method stub - return null; - } - - @Override - public String acquireGuestIpAddress(Network network, String requestedIp) { - // TODO Auto-generated method stub - return null; - } - - - @Override - public boolean applyStaticNats(List staticNats, boolean continueOnError, boolean forRevoke) throws ResourceUnavailableException { - // TODO Auto-generated method stub - return false; - } - - - - public Map> getNetworkOfferingServiceProvidersMap(long networkOfferingId) { - return null; - } - - - - - - @Override - public PhysicalNetwork createPhysicalNetwork(Long zoneId, String vnetRange, String networkSpeed, List isolationMethods, String broadcastDomainRange, Long domainId, List tags, String name) { - // TODO Auto-generated method stub - return null; - } - - @Override - public Pair, Integer> searchPhysicalNetworks(Long id, Long zoneId, String keyword, Long startIndex, Long pageSize, String name) { - // TODO Auto-generated method stub - return null; - } - - @Override - public PhysicalNetwork updatePhysicalNetwork(Long id, String networkSpeed, List tags, String newVnetRangeString, String state, String removeVlan) { - // TODO Auto-generated method stub - return null; - } - - @Override - public boolean deletePhysicalNetwork(Long id) { - // TODO Auto-generated method stub - return false; - } - - @Override - public GuestVlan dedicateGuestVlanRange(DedicateGuestVlanRangeCmd cmd) { - // TODO Auto-generated method stub - return null; - } - - @Override - public Pair, Integer> listDedicatedGuestVlanRanges(ListDedicatedGuestVlanRangesCmd cmd) { - // TODO Auto-generated method stub - return null; - } - - @Override - public boolean releaseDedicatedGuestVlanRange(Long dedicatedGuestVlanRangeId) { - // TODO Auto-generated method stub - return true; - } - - @Override - public List listNetworkServices(String providerName) { - // TODO Auto-generated method stub - return null; - } - - - @Override - public PhysicalNetworkServiceProvider addProviderToPhysicalNetwork(Long physicalNetworkId, String providerName, Long destinationPhysicalNetworkId, List enabledServices) { - // TODO Auto-generated method stub - return null; - } - - @Override - public Pair, Integer> listNetworkServiceProviders(Long physicalNetworkId, String name, String state, Long startIndex, Long pageSize) { - // TODO Auto-generated method stub - return null; - } - - @Override - public boolean deleteNetworkServiceProvider(Long id) { - // TODO Auto-generated method stub - return false; - } - - @Override - public PhysicalNetwork getPhysicalNetwork(Long physicalNetworkId) { - // TODO Auto-generated method stub - return null; - } - - @Override - public PhysicalNetwork getCreatedPhysicalNetwork(Long physicalNetworkId) { - // TODO Auto-generated method stub - return null; - } - - @Override - public PhysicalNetworkServiceProvider getPhysicalNetworkServiceProvider(Long providerId) { - // TODO Auto-generated method stub - return null; - } - - @Override - public PhysicalNetworkServiceProvider getCreatedPhysicalNetworkServiceProvider(Long providerId) { - // TODO Auto-generated method stub - return null; - } - - @Override - public long findPhysicalNetworkId(long zoneId, String tag, TrafficType trafficType) { - // TODO Auto-generated method stub - return 0; - } - - @Override - public PhysicalNetworkTrafficType getPhysicalNetworkTrafficType(Long id) { - // TODO Auto-generated method stub - return null; - } - - @Override - public PhysicalNetworkTrafficType updatePhysicalNetworkTrafficType(Long id, String xenLabel, String kvmLabel, String vmwareLabel) { - // TODO Auto-generated method stub - return null; - } - - @Override - public boolean deletePhysicalNetworkTrafficType(Long id) { - // TODO Auto-generated method stub - return false; - } - - @Override - public Pair, Integer> listTrafficTypes(Long physicalNetworkId) { - // TODO Auto-generated method stub - return null; - } - - - @Override - public Network getExclusiveGuestNetwork(long zoneId) { - // TODO Auto-generated method stub - return null; - } - - @Override - public UserDataServiceProvider getPasswordResetProvider(Network network) { - // TODO Auto-generated method stub - return null; - } - - @Override - public UserDataServiceProvider getSSHKeyResetProvider(Network network) { - // TODO Auto-generated method stub - return null; - } - - @Override - public PhysicalNetworkServiceProvider updateNetworkServiceProvider(Long id, String state, List enabledServices) { - // TODO Auto-generated method stub - return null; - } - - @Override - public PhysicalNetworkTrafficType addTrafficTypeToPhysicalNetwork(Long physicalNetworkId, String trafficType, String xenLabel, String kvmLabel, String vmwareLabel, String simulatorLabel, String vlan) { - // TODO Auto-generated method stub - return null; - } - - - /* (non-Javadoc) - * @see com.cloud.network.NetworkManager#applyRules(java.util.List, com.cloud.network.rules.FirewallRule.Purpose, com.cloud.network.NetworkRuleApplier, boolean) - */ - @Override - public boolean applyRules(List rules, Purpose purpose, NetworkRuleApplier applier, - boolean continueOnError) throws ResourceUnavailableException { - // TODO Auto-generated method stub - return false; - } - - /* (non-Javadoc) - * @see com.cloud.network.NetworkManager#applyIpAssociations(com.cloud.network.Network, boolean, boolean, java.util.List) - */ - @Override - public boolean applyIpAssociations(Network network, boolean rulesRevoked, boolean continueOnError, - List publicIps) throws ResourceUnavailableException { - // TODO Auto-generated method stub - return false; - } - - - /* (non-Javadoc) - * @see com.cloud.network.NetworkManager#restartNetwork(java.lang.Long, com.cloud.user.Account, com.cloud.user.User, boolean) - */ - @Override - public boolean restartNetwork(Long networkId, Account callerAccount, User callerUser, boolean cleanup) - throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException { - // TODO Auto-generated method stub - return false; - } - - /* (non-Javadoc) - * @see com.cloud.network.NetworkManager#shutdownNetworkElementsAndResources(com.cloud.vm.ReservationContext, boolean, com.cloud.network.NetworkVO) - */ - @Override - public boolean shutdownNetworkElementsAndResources(ReservationContext context, boolean b, NetworkVO network) { - // TODO Auto-generated method stub - return false; - } - - /* (non-Javadoc) - * @see com.cloud.network.NetworkManager#implementNetworkElementsAndResources(com.cloud.deploy.DeployDestination, com.cloud.vm.ReservationContext, com.cloud.network.NetworkVO, com.cloud.offerings.NetworkOfferingVO) - */ - @Override - public void implementNetworkElementsAndResources(DeployDestination dest, ReservationContext context, - NetworkVO network, NetworkOfferingVO findById) throws ConcurrentOperationException, - InsufficientAddressCapacityException, ResourceUnavailableException, InsufficientCapacityException { - // TODO Auto-generated method stub - - } - - /* (non-Javadoc) - * @see com.cloud.network.NetworkManager#allocateIp(com.cloud.user.Account, boolean, com.cloud.user.Account, com.cloud.dc.DataCenter) - */ - @Override - public IpAddress allocateIp(Account ipOwner, boolean isSystem, Account caller, long callerId, DataCenter zone) - throws ConcurrentOperationException, ResourceAllocationException, InsufficientAddressCapacityException { - // TODO Auto-generated method stub - return null; - } - - /* (non-Javadoc) - * @see com.cloud.network.NetworkManager#finalizeServicesAndProvidersForNetwork(com.cloud.offering.NetworkOffering, java.lang.Long) - */ - @Override - public Map finalizeServicesAndProvidersForNetwork(NetworkOffering offering, Long physicalNetworkId) { - // TODO Auto-generated method stub - return null; - } - - /* (non-Javadoc) - * @see com.cloud.network.NetworkManager#getNicProfileForVm(com.cloud.network.Network, com.cloud.vm.NicProfile, com.cloud.vm.VirtualMachine) - */ - protected NicProfile getNicProfileForVm(Network network, NicProfile requested, VirtualMachine vm) { - return null; - } - - /* (non-Javadoc) - * @see com.cloud.network.NetworkManager#getOnePhysicalNetworkByZoneAndTrafficType(long, com.cloud.network.Networks.TrafficType) - */ - protected PhysicalNetwork getOnePhysicalNetworkByZoneAndTrafficType(long zoneId, TrafficType trafficType) { - return null; - } - - /* (non-Javadoc) - * @see com.cloud.network.NetworkManager#getZoneNetworkDomain(long) - */ - protected String getZoneNetworkDomain(long zoneId) { - return null; - } - - /* (non-Javadoc) - * @see com.cloud.network.NetworkManager#getNicInNetworkIncludingRemoved(long, long) - */ - protected Nic getNicInNetworkIncludingRemoved(long vmId, long networkId) { - return null; - } - - - /* (non-Javadoc) - * @see com.cloud.network.NetworkService#restartNetwork(com.cloud.api.commands.RestartNetworkCmd, boolean) - */ - @Override - public boolean restartNetwork(RestartNetworkCmd cmd, boolean cleanup) throws ConcurrentOperationException, - ResourceUnavailableException, InsufficientCapacityException { - // TODO Auto-generated method stub - return false; - } - - /* (non-Javadoc) - * @see com.cloud.network.NetworkService#updateGuestNetwork(long, java.lang.String, java.lang.String, com.cloud.user.Account, com.cloud.user.User, java.lang.String, java.lang.Long, java.lang.Boolean) - */ - @Override - public Network updateGuestNetwork(long networkId, String name, String displayText, Account callerAccount, - User callerUser, String domainSuffix, Long networkOfferingId, Boolean changeCidr, String guestVmCidr, Boolean displayNetwork) { - // TODO Auto-generated method stub - return null; - } - - /* (non-Javadoc) - * @see com.cloud.network.NetworkService#listTrafficTypeImplementor(com.cloud.api.commands.ListTrafficTypeImplementorsCmd) - */ - @Override - public List> listTrafficTypeImplementor(ListTrafficTypeImplementorsCmd cmd) { - // TODO Auto-generated method stub - return null; - } - - /* (non-Javadoc) - * @see com.cloud.network.NetworkService#getIsolatedNetworksWithSourceNATOwnedByAccountInZone(long, com.cloud.user.Account) - */ - @Override - public List getIsolatedNetworksWithSourceNATOwnedByAccountInZone(long zoneId, Account owner) { - // TODO Auto-generated method stub - return null; - } - - /* (non-Javadoc) - * @see com.cloud.network.NetworkService#associateIPToNetwork(long, long) - */ - @Override - public IpAddress associateIPToNetwork(long ipId, long networkId) throws InsufficientAddressCapacityException, - ResourceAllocationException, ResourceUnavailableException, ConcurrentOperationException { - // TODO Auto-generated method stub - return null; - } - - @Override - - public Network createPrivateNetwork(String networkName, String displayText, long physicalNetworkId, String vlan, - String startIp, String endIP, String gateway, String netmask, long networkOwnerId, Long vpcId, Boolean sourceNat) - throws ResourceAllocationException, ConcurrentOperationException, InsufficientCapacityException { - // TODO Auto-generated method stub - return null; - } - - /* (non-Javadoc) - * @see com.cloud.network.NetworkManager#assignPublicIpAddress(long, java.lang.Long, com.cloud.user.Account, com.cloud.dc.Vlan.VlanType, java.lang.Long, java.lang.String, boolean) - */ - @Override - public PublicIp assignPublicIpAddress(long dcId, Long podId, Account owner, VlanType type, Long networkId, - String requestedIp, boolean isSystem) throws InsufficientAddressCapacityException { - // TODO Auto-generated method stub - return null; - } - - /* (non-Javadoc) - * @see com.cloud.network.NetworkManager#shutdownNetwork(long, com.cloud.vm.ReservationContext, boolean) - */ - @Override - public boolean shutdownNetwork(long networkId, ReservationContext context, boolean cleanupElements) { - // TODO Auto-generated method stub - return false; - } - - /* (non-Javadoc) - * @see com.cloud.network.NetworkManager#reallocate(com.cloud.vm.VirtualMachineProfile, com.cloud.deploy.DataCenterDeployment) - */ - @Override - public boolean reallocate(VirtualMachineProfile vm, DataCenterDeployment dest) - throws InsufficientCapacityException, ConcurrentOperationException { - // TODO Auto-generated method stub - return false; - } - - /* (non-Javadoc) - * @see com.cloud.network.NetworkManager#assignSystemIp(long, com.cloud.user.Account, boolean, boolean) - */ - @Override - public IpAddress assignSystemIp(long networkId, Account owner, boolean forElasticLb, boolean forElasticIp) - throws InsufficientAddressCapacityException { - // TODO Auto-generated method stub - return null; - } - - /* (non-Javadoc) - * @see com.cloud.network.NetworkManager#handleSystemIpRelease(com.cloud.network.IpAddress) - */ - @Override - public boolean handleSystemIpRelease(IpAddress ip) { - // TODO Auto-generated method stub - return false; - } - - /* (non-Javadoc) - * @see com.cloud.network.NetworkManager#allocateDirectIp(com.cloud.vm.NicProfile, com.cloud.dc.DataCenter, com.cloud.vm.VirtualMachineProfile, com.cloud.network.Network, java.lang.String) - */ - @Override - public void allocateDirectIp(NicProfile nic, DataCenter dc, VirtualMachineProfile vm, - Network network, String requestedIpv4, String requestedIpv6) throws InsufficientVirtualNetworkCapcityException, - InsufficientAddressCapacityException { - // TODO Auto-generated method stub - - } - - /* (non-Javadoc) - * @see com.cloud.network.NetworkManager#assignSourceNatIpAddressToGuestNetwork(com.cloud.user.Account, com.cloud.network.Network) - */ - @Override - public PublicIp assignSourceNatIpAddressToGuestNetwork(Account owner, Network guestNetwork) - throws InsufficientAddressCapacityException, ConcurrentOperationException { - // TODO Auto-generated method stub - return null; - } - - /* (non-Javadoc) - * @see com.cloud.network.NetworkManager#allocateNic(com.cloud.vm.NicProfile, com.cloud.network.Network, java.lang.Boolean, int, com.cloud.vm.VirtualMachineProfile) - */ - @Override - public Pair allocateNic(NicProfile requested, Network network, Boolean isDefaultNic, - int deviceId, VirtualMachineProfile vm) - throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException, - ConcurrentOperationException { - // TODO Auto-generated method stub - return null; - } - - /* (non-Javadoc) - * @see com.cloud.network.NetworkManager#prepareNic(com.cloud.vm.VirtualMachineProfile, com.cloud.deploy.DeployDestination, com.cloud.vm.ReservationContext, long, com.cloud.network.NetworkVO) - */ - @Override - public NicProfile prepareNic(VirtualMachineProfile vmProfile, DeployDestination dest, - ReservationContext context, long nicId, NetworkVO network) - throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException, - ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException { - // TODO Auto-generated method stub - return null; - } - - /* (non-Javadoc) - * @see com.cloud.network.NetworkManager#removeNic(com.cloud.vm.VirtualMachineProfile, com.cloud.vm.Nic) - */ - @Override - public void removeNic(VirtualMachineProfile vm, Nic nic) { - // TODO Auto-generated method stub - - } - - /* (non-Javadoc) - * @see com.cloud.network.NetworkManager#setupDns(com.cloud.network.Network, com.cloud.network.Network.Provider) - */ - @Override - public boolean setupDns(Network network, Provider provider) { - // TODO Auto-generated method stub - return false; - } - - /* (non-Javadoc) - * @see com.cloud.network.NetworkManager#releaseNic(com.cloud.vm.VirtualMachineProfile, com.cloud.vm.Nic) - */ - @Override - public void releaseNic(VirtualMachineProfile vmProfile, Nic nic) - throws ConcurrentOperationException, ResourceUnavailableException { - // TODO Auto-generated method stub - - } - - /* (non-Javadoc) - * @see com.cloud.network.NetworkManager#createNicForVm(com.cloud.network.Network, com.cloud.vm.NicProfile, com.cloud.vm.ReservationContext, com.cloud.vm.VirtualMachineProfileImpl, boolean) - */ - @Override - public NicProfile createNicForVm(Network network, NicProfile requested, ReservationContext context, - VirtualMachineProfile vmProfile, boolean prepare) - throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException, - ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException { - // TODO Auto-generated method stub - return null; - } - - - /* (non-Javadoc) - * @see com.cloud.network.NetworkManager#markPublicIpAsAllocated(com.cloud.network.IPAddressVO) - */ - @Override - public void markPublicIpAsAllocated(IPAddressVO addr) { - // TODO Auto-generated method stub - - } - - /* (non-Javadoc) - * @see com.cloud.network.NetworkManager#assignDedicateIpAddress(com.cloud.user.Account, java.lang.Long, java.lang.Long, long, boolean) - */ - @Override - public PublicIp assignDedicateIpAddress(Account owner, Long guestNtwkId, Long vpcId, long dcId, boolean isSourceNat) - throws ConcurrentOperationException, InsufficientAddressCapacityException { - // TODO Auto-generated method stub - return null; - } - - /* (non-Javadoc) - * @see com.cloud.network.NetworkManager#getNetworkLockTimeout() - */ - @Override - public int getNetworkLockTimeout() { - // TODO Auto-generated method stub - return 0; - } - - @Override - public boolean isNetworkInlineMode(Network network) { - // TODO Auto-generated method stub - return false; - } - - @Override - public StaticNatServiceProvider getStaticNatProviderForNetwork(Network network) { - // TODO Auto-generated method stub - return null; - } - - @Override - public List getProvidersForServiceInNetwork(Network network, - Service service) { - // TODO Auto-generated method stub - return null; - } - - @Override - public int getRuleCountForIp(Long addressId, Purpose purpose, State state) { - // TODO Auto-generated method stub - return 0; - } - - @Override - public LoadBalancingServiceProvider getLoadBalancingProviderForNetwork(Network network, Scheme lbScheme) { - // TODO Auto-generated method stub - return null; - } - - /* (non-Javadoc) - * @see com.cloud.network.NetworkService#allocateIP(com.cloud.user.Account, boolean, long) - */ - @Override - public IpAddress allocateIP(Account ipOwner, long zoneId, Long networkId) throws ResourceAllocationException, - InsufficientAddressCapacityException, ConcurrentOperationException { - // TODO Auto-generated method stub - return null; - } - - @Override - public IpAddress allocatePortableIp(Account ipOwner, Account caller, long dcId, Long networkId, Long vpcID) - throws ConcurrentOperationException, ResourceAllocationException, InsufficientAddressCapacityException { - return null;// TODO Auto-generated method stub - } - - @Override - public IpAddress allocatePortableIP(Account ipOwner, int regionId, Long zoneId, Long networkId, Long vpcId) throws ResourceAllocationException, - InsufficientAddressCapacityException, ConcurrentOperationException { - return null; - } - - @Override - public boolean releasePortableIpAddress(long ipAddressId) { - return false;// TODO Auto-generated method stub - } - - @Override - public boolean isSecondaryIpSetForNic(long nicId) { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean releaseSecondaryIpFromNic(long ipAddressId) { - // TODO Auto-generated method stub - return false; - } - - @Override - public NicSecondaryIp allocateSecondaryGuestIP(Account account, long zoneId, - Long nicId, Long networkId, String ipaddress) { - // TODO Auto-generated method stub - return null; - } - - @Override - public String allocateGuestIP(Account ipOwner, boolean isSystem, - long zoneId, Long networkId, String requestedIp) - throws InsufficientAddressCapacityException { - // TODO Auto-generated method stub - return null; - } - - - @Override - public List listVmNics(Long vmId, Long nicId) { - // TODO Auto-generated method stub - return null; - } - - @Override - public List listNics(ListNicsCmd listNicsCmd) { - // TODO Auto-generated method stub - return null; - } - - @Override - public Map getNetworkOfferingServiceCapabilities(NetworkOffering offering, Service service) { - return null; //To change body of implemented methods use File | Settings | File Templates. - } - - @Override - public String allocatePublicIpForGuestNic(Long networkId, DataCenter dc, - Pod pod, Account caller, String requestedIp) - throws InsufficientAddressCapacityException { - // TODO Auto-generated method stub - return null; - } - - - @Override - public NicVO savePlaceholderNic(Network network, String ip4Address, String ip6Address, Type vmType) { - // TODO Auto-generated method stub - return null; - } - - @Override - public DhcpServiceProvider getDhcpServiceProvider(Network network) { - return null; //To change body of implemented methods use File | Settings | File Templates. - } - - @Override - public PublicIp assignPublicIpAddressFromVlans(long dcId, Long podId, Account owner, VlanType type, List vlanDbIds, Long networkId, String requestedIp, boolean isSystem) throws InsufficientAddressCapacityException { - return null; //To change body of implemented methods use File | Settings | File Templates. - } - - @Override - public void prepareNicForMigration( - VirtualMachineProfile vm, - DeployDestination dest) { - // TODO Auto-generated method stub - - } - - @Override - public void commitNicForMigration( - VirtualMachineProfile src, - VirtualMachineProfile dst) { - // TODO Auto-generated method stub - - } - - @Override - public void rollbackNicForMigration( - VirtualMachineProfile src, - VirtualMachineProfile dst) { - // TODO Auto-generated method stub - } -} diff --git a/server/test/com/cloud/vm/VirtualMachineManagerImplTest.java b/server/test/com/cloud/vm/VirtualMachineManagerImplTest.java index 1e6d005ca60..a49b0e0fcd7 100644 --- a/server/test/com/cloud/vm/VirtualMachineManagerImplTest.java +++ b/server/test/com/cloud/vm/VirtualMachineManagerImplTest.java @@ -270,7 +270,7 @@ public class VirtualMachineManagerImplTest { @Test (expected=CloudRuntimeException.class) public void testScaleVM3() throws Exception { - /*VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm); + /*VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm); Long srcHostId = vm.getHostId(); Long oldSvcOfferingId = vm.getServiceOfferingId(); diff --git a/server/test/com/cloud/vpc/MockNetworkManagerImpl.java b/server/test/com/cloud/vpc/MockNetworkManagerImpl.java index fd61bc65c90..c10ec328d9c 100644 --- a/server/test/com/cloud/vpc/MockNetworkManagerImpl.java +++ b/server/test/com/cloud/vpc/MockNetworkManagerImpl.java @@ -24,7 +24,9 @@ import javax.ejb.Local; import javax.inject.Inject; import javax.naming.ConfigurationException; -import com.cloud.vm.*; +import org.apache.log4j.Logger; +import org.springframework.stereotype.Component; + import org.apache.cloudstack.acl.ControlledEntity.ACLType; import org.apache.cloudstack.api.command.admin.network.DedicateGuestVlanRangeCmd; import org.apache.cloudstack.api.command.admin.network.ListDedicatedGuestVlanRangesCmd; @@ -33,8 +35,6 @@ import org.apache.cloudstack.api.command.user.network.CreateNetworkCmd; import org.apache.cloudstack.api.command.user.network.ListNetworksCmd; import org.apache.cloudstack.api.command.user.network.RestartNetworkCmd; import org.apache.cloudstack.api.command.user.vm.ListNicsCmd; -import org.apache.log4j.Logger; -import org.springframework.stereotype.Component; import com.cloud.dc.DataCenter; import com.cloud.dc.Pod; @@ -66,7 +66,11 @@ import com.cloud.network.addr.PublicIp; import com.cloud.network.dao.IPAddressVO; import com.cloud.network.dao.NetworkServiceMapDao; import com.cloud.network.dao.NetworkVO; -import com.cloud.network.element.*; +import com.cloud.network.element.DhcpServiceProvider; +import com.cloud.network.element.LoadBalancingServiceProvider; +import com.cloud.network.element.NetworkElement; +import com.cloud.network.element.StaticNatServiceProvider; +import com.cloud.network.element.UserDataServiceProvider; import com.cloud.network.guru.NetworkGuru; import com.cloud.network.rules.FirewallRule; import com.cloud.network.rules.FirewallRule.Purpose; @@ -80,19 +84,15 @@ import com.cloud.user.Account; import com.cloud.user.User; import com.cloud.utils.Pair; import com.cloud.utils.component.ManagerBase; +import com.cloud.vm.Nic; +import com.cloud.vm.NicProfile; +import com.cloud.vm.NicSecondaryIp; +import com.cloud.vm.NicVO; +import com.cloud.vm.ReservationContext; +import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachine.Type; - import com.cloud.vm.VirtualMachineProfile; -import org.apache.cloudstack.acl.ControlledEntity.ACLType; -import org.apache.cloudstack.api.command.admin.network.DedicateGuestVlanRangeCmd; -import org.apache.cloudstack.api.command.admin.network.ListDedicatedGuestVlanRangesCmd; -import org.apache.cloudstack.api.command.admin.usage.ListTrafficTypeImplementorsCmd; -import org.apache.cloudstack.api.command.user.network.*; -import org.apache.cloudstack.api.command.user.vm.ListNicsCmd; -import org.apache.log4j.Logger; -import org.springframework.stereotype.Component; - @Component @Local(value = { NetworkManager.class, NetworkService.class }) @@ -738,7 +738,7 @@ public class MockNetworkManagerImpl extends ManagerBase implements NetworkManage * @see com.cloud.network.NetworkManager#allocate(com.cloud.vm.VirtualMachineProfile, java.util.List) */ @Override - public void allocate(VirtualMachineProfile vm, List> networks) + public void allocate(VirtualMachineProfile vm, List> networks) throws InsufficientCapacityException, ConcurrentOperationException { // TODO Auto-generated method stub @@ -752,7 +752,7 @@ public class MockNetworkManagerImpl extends ManagerBase implements NetworkManage * @see com.cloud.network.NetworkManager#prepare(com.cloud.vm.VirtualMachineProfile, com.cloud.deploy.DeployDestination, com.cloud.vm.ReservationContext) */ @Override - public void prepare(VirtualMachineProfile profile, DeployDestination dest, + public void prepare(VirtualMachineProfile profile, DeployDestination dest, ReservationContext context) throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException { // TODO Auto-generated method stub @@ -767,7 +767,7 @@ public class MockNetworkManagerImpl extends ManagerBase implements NetworkManage * @see com.cloud.network.NetworkManager#release(com.cloud.vm.VirtualMachineProfile, boolean) */ @Override - public void release(VirtualMachineProfile vmProfile, boolean forced) + public void release(VirtualMachineProfile vmProfile, boolean forced) throws ConcurrentOperationException, ResourceUnavailableException { // TODO Auto-generated method stub @@ -781,7 +781,7 @@ public class MockNetworkManagerImpl extends ManagerBase implements NetworkManage * @see com.cloud.network.NetworkManager#cleanupNics(com.cloud.vm.VirtualMachineProfile) */ @Override - public void cleanupNics(VirtualMachineProfile vm) { + public void cleanupNics(VirtualMachineProfile vm) { // TODO Auto-generated method stub } @@ -794,7 +794,7 @@ public class MockNetworkManagerImpl extends ManagerBase implements NetworkManage * @see com.cloud.network.NetworkManager#expungeNics(com.cloud.vm.VirtualMachineProfile) */ @Override - public void expungeNics(VirtualMachineProfile vm) { + public void expungeNics(VirtualMachineProfile vm) { // TODO Auto-generated method stub } @@ -1001,7 +1001,7 @@ public class MockNetworkManagerImpl extends ManagerBase implements NetworkManage * @see com.cloud.network.NetworkManager#reallocate(com.cloud.vm.VirtualMachineProfile, com.cloud.deploy.DataCenterDeployment) */ @Override - public boolean reallocate(VirtualMachineProfile vm, DataCenterDeployment dest) + public boolean reallocate(VirtualMachineProfile vm, DataCenterDeployment dest) throws InsufficientCapacityException, ConcurrentOperationException { // TODO Auto-generated method stub return false; @@ -1042,7 +1042,7 @@ public class MockNetworkManagerImpl extends ManagerBase implements NetworkManage * @see com.cloud.network.NetworkManager#allocateDirectIp(com.cloud.vm.NicProfile, com.cloud.dc.DataCenter, com.cloud.vm.VirtualMachineProfile, com.cloud.network.Network, java.lang.String) */ @Override - public void allocateDirectIp(NicProfile nic, DataCenter dc, VirtualMachineProfile vm, + public void allocateDirectIp(NicProfile nic, DataCenter dc, VirtualMachineProfile vm, Network network, String requestedIpv4, String requestedIpv6) throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException { // TODO Auto-generated method stub @@ -1071,7 +1071,7 @@ public class MockNetworkManagerImpl extends ManagerBase implements NetworkManage */ @Override public Pair allocateNic(NicProfile requested, Network network, Boolean isDefaultNic, - int deviceId, VirtualMachineProfile vm) + int deviceId, VirtualMachineProfile vm) throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException, ConcurrentOperationException { // TODO Auto-generated method stub @@ -1086,7 +1086,7 @@ public class MockNetworkManagerImpl extends ManagerBase implements NetworkManage * @see com.cloud.network.NetworkManager#prepareNic(com.cloud.vm.VirtualMachineProfile, com.cloud.deploy.DeployDestination, com.cloud.vm.ReservationContext, long, com.cloud.network.NetworkVO) */ @Override - public NicProfile prepareNic(VirtualMachineProfile vmProfile, DeployDestination dest, + public NicProfile prepareNic(VirtualMachineProfile vmProfile, DeployDestination dest, ReservationContext context, long nicId, NetworkVO network) throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException, ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException { @@ -1102,7 +1102,7 @@ public class MockNetworkManagerImpl extends ManagerBase implements NetworkManage * @see com.cloud.network.NetworkManager#removeNic(com.cloud.vm.VirtualMachineProfile, com.cloud.vm.Nic) */ @Override - public void removeNic(VirtualMachineProfile vm, Nic nic) { + public void removeNic(VirtualMachineProfile vm, Nic nic) { // TODO Auto-generated method stub } @@ -1147,7 +1147,7 @@ public class MockNetworkManagerImpl extends ManagerBase implements NetworkManage * @see com.cloud.network.NetworkManager#releaseNic(com.cloud.vm.VirtualMachineProfile, com.cloud.vm.Nic) */ @Override - public void releaseNic(VirtualMachineProfile vmProfile, Nic nic) + public void releaseNic(VirtualMachineProfile vmProfile, Nic nic) throws ConcurrentOperationException, ResourceUnavailableException { // TODO Auto-generated method stub @@ -1158,7 +1158,7 @@ public class MockNetworkManagerImpl extends ManagerBase implements NetworkManage */ @Override public NicProfile createNicForVm(Network network, NicProfile requested, ReservationContext context, - VirtualMachineProfile vmProfile, boolean prepare) + VirtualMachineProfile vmProfile, boolean prepare) throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException, ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException { // TODO Auto-generated method stub @@ -1419,7 +1419,7 @@ public class MockNetworkManagerImpl extends ManagerBase implements NetworkManage @Override public void prepareNicForMigration( - VirtualMachineProfile vm, + VirtualMachineProfile vm, DeployDestination dest) { // TODO Auto-generated method stub @@ -1431,8 +1431,8 @@ public class MockNetworkManagerImpl extends ManagerBase implements NetworkManage @Override public void commitNicForMigration( - VirtualMachineProfile src, - VirtualMachineProfile dst) { + VirtualMachineProfile src, + VirtualMachineProfile dst) { // TODO Auto-generated method stub } @@ -1443,8 +1443,8 @@ public class MockNetworkManagerImpl extends ManagerBase implements NetworkManage @Override public void rollbackNicForMigration( - VirtualMachineProfile src, - VirtualMachineProfile dst) { + VirtualMachineProfile src, + VirtualMachineProfile dst) { // TODO Auto-generated method stub } diff --git a/server/test/com/cloud/vpc/MockVpcVirtualNetworkApplianceManager.java b/server/test/com/cloud/vpc/MockVpcVirtualNetworkApplianceManager.java index f325c4af077..7f1048fa616 100644 --- a/server/test/com/cloud/vpc/MockVpcVirtualNetworkApplianceManager.java +++ b/server/test/com/cloud/vpc/MockVpcVirtualNetworkApplianceManager.java @@ -72,14 +72,14 @@ VpcVirtualNetworkApplianceService { * @see com.cloud.network.router.VirtualNetworkApplianceManager#savePasswordToRouter(com.cloud.network.Network, com.cloud.vm.NicProfile, com.cloud.vm.VirtualMachineProfile, java.util.List) */ @Override - public boolean savePasswordToRouter(Network network, NicProfile nic, VirtualMachineProfile profile, + public boolean savePasswordToRouter(Network network, NicProfile nic, VirtualMachineProfile profile, List routers) throws ResourceUnavailableException { // TODO Auto-generated method stub return false; } @Override - public boolean saveSSHPublicKeyToRouter(Network network, NicProfile nic, VirtualMachineProfile profile, List routers, String SSHPublicKey) throws ResourceUnavailableException { + public boolean saveSSHPublicKeyToRouter(Network network, NicProfile nic, VirtualMachineProfile profile, List routers, String SSHPublicKey) throws ResourceUnavailableException { return false; //To change body of implemented methods use File | Settings | File Templates. } @@ -87,7 +87,7 @@ VpcVirtualNetworkApplianceService { * @see com.cloud.network.router.VirtualNetworkApplianceManager#saveUserDataToRouter(com.cloud.network.Network, com.cloud.vm.NicProfile, com.cloud.vm.VirtualMachineProfile, java.util.List) */ @Override - public boolean saveUserDataToRouter(Network network, NicProfile nic, VirtualMachineProfile profile, + public boolean saveUserDataToRouter(Network network, NicProfile nic, VirtualMachineProfile profile, List routers) throws ResourceUnavailableException { // TODO Auto-generated method stub return false; @@ -196,7 +196,7 @@ VpcVirtualNetworkApplianceService { * @see com.cloud.network.router.VirtualNetworkApplianceManager#applyDhcpEntry(com.cloud.network.Network, com.cloud.vm.NicProfile, com.cloud.vm.VirtualMachineProfile, com.cloud.deploy.DeployDestination, java.util.List) */ @Override - public boolean applyDhcpEntry(Network config, NicProfile nic, VirtualMachineProfile vm, + public boolean applyDhcpEntry(Network config, NicProfile nic, VirtualMachineProfile vm, DeployDestination dest, List routers) throws ResourceUnavailableException { // TODO Auto-generated method stub return false; @@ -206,14 +206,14 @@ VpcVirtualNetworkApplianceService { * @see com.cloud.network.router.VirtualNetworkApplianceManager#applyUserData(com.cloud.network.Network, com.cloud.vm.NicProfile, com.cloud.vm.VirtualMachineProfile, com.cloud.deploy.DeployDestination, java.util.List) */ @Override - public boolean applyUserData(Network config, NicProfile nic, VirtualMachineProfile vm, + public boolean applyUserData(Network config, NicProfile nic, VirtualMachineProfile vm, DeployDestination dest, List routers) throws ResourceUnavailableException { // TODO Auto-generated method stub return false; } @Override - public boolean configDhcpForSubnet(Network network, NicProfile nic, VirtualMachineProfile uservm, DeployDestination dest, List routers) throws ResourceUnavailableException { + public boolean configDhcpForSubnet(Network network, NicProfile nic, VirtualMachineProfile uservm, DeployDestination dest, List routers) throws ResourceUnavailableException { return false; //To change body of implemented methods use File | Settings | File Templates. } From 02236576c0d3bc28c5ec9c806d11adf7af2ec9e9 Mon Sep 17 00:00:00 2001 From: Alex Huang Date: Mon, 22 Jul 2013 11:46:21 -0700 Subject: [PATCH 38/74] Changed some debug logs to trace --- .../org/apache/cloudstack/context/CallContext.java | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/api/src/org/apache/cloudstack/context/CallContext.java b/api/src/org/apache/cloudstack/context/CallContext.java index 9689a994fcd..e3c1bf2a7b9 100644 --- a/api/src/org/apache/cloudstack/context/CallContext.java +++ b/api/src/org/apache/cloudstack/context/CallContext.java @@ -110,7 +110,9 @@ public class CallContext { CallContext callingContext = new CallContext(callingUser, callingAccount, contextId); s_currentContext.set(callingContext); NDC.push("ctx-" + UuidUtils.first(contextId)); - s_logger.debug("Setting calling context: " + callingContext); + if (s_logger.isTraceEnabled()) { + s_logger.trace("Registered: " + callingContext); + } return callingContext; } @@ -161,11 +163,13 @@ public class CallContext { public static CallContext unregister() { CallContext context = s_currentContext.get(); if (context == null) { - s_logger.trace("No context to remove"); + s_logger.debug("No context to remove"); return null; } s_currentContext.remove(); - s_logger.debug("Context removed " + context); + if (s_logger.isTraceEnabled()) { + s_logger.trace("Unregistered: " + context); + } String contextId = context.getContextId(); String sessionIdOnStack = null; String sessionIdPushedToNDC = "ctx-" + UuidUtils.first(contextId); @@ -210,9 +214,9 @@ public class CallContext { @Override public String toString() { - return new StringBuffer("CallContext[acct=").append(account.getId()) + return new StringBuffer("CCtxt[acct=").append(account.getId()) .append("; user=").append(user.getId()) - .append("; session=").append(contextId) + .append("; id=").append(contextId) .append("]").toString(); } } From 6c22c7b6141e627ff18e6edc737d0dd314209f04 Mon Sep 17 00:00:00 2001 From: Alena Prokharchyk Date: Mon, 22 Jul 2013 13:23:52 -0700 Subject: [PATCH 39/74] CLOUDSTACK-3720: fixed API doc for listResourceLimits API --- .../user/resource/ListResourceLimitsCmd.java | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/api/src/org/apache/cloudstack/api/command/user/resource/ListResourceLimitsCmd.java b/api/src/org/apache/cloudstack/api/command/user/resource/ListResourceLimitsCmd.java index 191e9589a65..4d5d4f4429e 100644 --- a/api/src/org/apache/cloudstack/api/command/user/resource/ListResourceLimitsCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/resource/ListResourceLimitsCmd.java @@ -28,6 +28,7 @@ import org.apache.cloudstack.api.response.ResourceLimitResponse; import org.apache.log4j.Logger; import com.cloud.configuration.ResourceLimit; +import com.cloud.configuration.Resource.ResourceOwnerType; @APICommand(name = "listResourceLimits", description="Lists resource limits.", responseObject=ResourceLimitResponse.class) public class ListResourceLimitsCmd extends BaseListProjectAndAccountResourcesCmd { @@ -42,11 +43,19 @@ public class ListResourceLimitsCmd extends BaseListProjectAndAccountResourcesCmd @Parameter(name=ApiConstants.ID, type=CommandType.LONG, description="Lists resource limits by ID.") private Long id; - @Parameter(name=ApiConstants.RESOURCE_TYPE, type=CommandType.INTEGER, description="Type of resource to update. Values are 0, 1, 2, 3, and 4. 0 - Instance. Number of instances a user can create. " + - "1 - IP. Number of public IP addresses a user can own. " + - "2 - Volume. Number of disk volumes a user can create." + - "3 - Snapshot. Number of snapshots a user can create." + - "4 - Template. Number of templates that a user can register/create.") + @Parameter(name=ApiConstants.RESOURCE_TYPE, type=CommandType.INTEGER, description="Type of resource to update. Values are 0, 1, 2, 3, and 4." + + "0 - Instance. Number of instances a user can create. " + + "1 - IP. Number of public IP addresses an account can own. " + + "2 - Volume. Number of disk volumes an account can own." + + "3 - Snapshot. Number of snapshots an account can own." + + "4 - Template. Number of templates an account can register/create." + + "5 - Project. Number of projects an account can own." + + "6 - Network. Number of networks an account can own." + + "7 - VPC. Number of VPC an account can own." + + "8 - CPU. Number of CPU an account can allocate for his resources." + + "9 - Memory. Amount of RAM an account can allocate for his resources." + + "10 - Primary Storage. Amount of Primary storage an account can allocate for his resoruces." + + "11 - Secondary Storage. Amount of Secondary storage an account can allocate for his resources.") private Integer resourceType; ///////////////////////////////////////////////////// From f1e242f53126e614356a0399835b719f4d8847e8 Mon Sep 17 00:00:00 2001 From: Jessica Wang Date: Mon, 22 Jul 2013 11:54:10 -0700 Subject: [PATCH 40/74] CLOUDSTACK-3427: UI > UCS manager > implement listUcsManager API since it has been fixed at server-side. --- ui/scripts/system.js | 63 ++++++++++++++++++++++++++------------------ 1 file changed, 38 insertions(+), 25 deletions(-) diff --git a/ui/scripts/system.js b/ui/scripts/system.js index eb15362bdcf..f4f4047bd6f 100644 --- a/ui/scripts/system.js +++ b/ui/scripts/system.js @@ -14128,30 +14128,33 @@ label: 'label.url' } }, - dataProvider: function(args) { - /* - $.ajax({ - url: createURL('listUcsManager'), - data: { - zoneid: args.context.physicalResources[0].id - }, - success: function(json) { - - } - }); - */ - - args.response.success({ - data: [{ - id: '11', - name: 'UCS Manager 1', - url: '10.196.72.1' - }, { - id: '11', - name: 'UCS Manager 2', - url: '10.196.72.2' - }] - }); + dataProvider: function(args) { + $.ajax({ + url: createURL('listUcsManager'), + data: { + zoneid: args.context.physicalResources[0].id + }, + success: function(json) { + /* + json = //override json (for testing only) + { + "listucsmanagerreponse": { + "count": 1, + "ucsmanager": [ + { + "id": "07b5b813-83ed-4859-952c-c95cafb63ac4", + "name": "ucsmanager", + "url": "10.223.184.2", + "zoneid": "54c9a65c-ba89-4380-96e9-1d429c5372e3" + } + ] + } + }; + */ + var items = json.listucsmanagerreponse.ucsmanager; + args.response.success({ data: items }); + } + }); }, actions: { add: { @@ -14362,7 +14365,17 @@ bladeid: args.context.blades[0].id }, success: function(json) { - //json.associateucsprofiletobladeresponse.ucsblade + /* + { + "associateucsprofiletobladeresponse": { + "ucsblade": { + "id": "8f63030a-033c-458e-890f-b2c8863d9542", + "ucsmanagerid": "9d8566c0-f870-4e89-9864-7a3e0b332558", + "bladedn": "sys/chassis-1/blade-2" + } + } + } + */ args.response.success({ data: { associatedProfileDn: args.data.profiledn From 1731e5bf86c43821c4700e0fc9f822279d376c7d Mon Sep 17 00:00:00 2001 From: Brian Federle Date: Mon, 22 Jul 2013 14:06:03 -0700 Subject: [PATCH 41/74] CLOUDSTACK-3104: Fix view all button alignment in IE --- ui/css/cloudstack3.css | 1 + 1 file changed, 1 insertion(+) diff --git a/ui/css/cloudstack3.css b/ui/css/cloudstack3.css index 4545e96d100..db5ddbab72b 100644 --- a/ui/css/cloudstack3.css +++ b/ui/css/cloudstack3.css @@ -2108,6 +2108,7 @@ div.detail-group.actions td { display: block; width: 99%; border-bottom: 1px solid #AAAAAA; + float: left; } .detail-group table td.detail-actions .action.text { From 8a6892d54249f4e0fac16bbd57ddd97ffd87a603 Mon Sep 17 00:00:00 2001 From: Brian Federle Date: Mon, 22 Jul 2013 14:15:46 -0700 Subject: [PATCH 42/74] CLOUDSTACK-3391: Add missing action icons --- ui/css/cloudstack3.css | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/ui/css/cloudstack3.css b/ui/css/cloudstack3.css index db5ddbab72b..50cfbd483ce 100644 --- a/ui/css/cloudstack3.css +++ b/ui/css/cloudstack3.css @@ -11821,11 +11821,13 @@ div.ui-dialog div.autoscaler div.field-group div.form-container form div.form-it background-position: -169px -583px; } -.stop .icon { +.stop .icon, +.removeVmwareDc .icon { background-position: 0px -31px; } -.stop:hover .icon { +.stop:hover .icon, +.removeVmwareDc:hover .icon { background-position: 0px -613px; } @@ -12056,11 +12058,13 @@ div.ui-dialog div.autoscaler div.field-group div.form-container form div.form-it background-position: -100px -614px; } -.addVlanRange .icon { +.addVlanRange .icon, +.addVmwareDc .icon { background-position: -37px -62px; } -.addVlanRange:hover .icon { +.addVlanRange:hover .icon, +.addVmwareDc:hover .icon { background-position: -37px -62px; } From 04cdd90a84f4be5ba02778fe0cd352a4b1c39a13 Mon Sep 17 00:00:00 2001 From: Anthony Xu Date: Mon, 22 Jul 2013 14:16:20 -0700 Subject: [PATCH 43/74] in one zone, Admin should not be allowed to add a Shared Network with a subnet that is already associated with another Vlan. --- .../ConfigurationManagerImpl.java | 115 ++++++------------ .../com/cloud/network/NetworkServiceImpl.java | 7 +- 2 files changed, 41 insertions(+), 81 deletions(-) diff --git a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java index 92178c9966c..9bc8efd465b 100755 --- a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java +++ b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java @@ -2978,30 +2978,16 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati } if (ipv4) { - String newVlanSubnet = NetUtils.getSubNet(vlanGateway, vlanNetmask); + String newCidr = NetUtils.getCidrFromGatewayAndNetmask(vlanGateway, vlanNetmask); // Check if the new VLAN's subnet conflicts with the guest network // in // the specified zone (guestCidr is null for basic zone) String guestNetworkCidr = zone.getGuestNetworkCidr(); - if (guestNetworkCidr != null) { - String[] cidrPair = guestNetworkCidr.split("\\/"); - String guestIpNetwork = NetUtils.getIpRangeStartIpFromCidr(cidrPair[0], Long.parseLong(cidrPair[1])); - long guestCidrSize = Long.parseLong(cidrPair[1]); - long vlanCidrSize = NetUtils.getCidrSize(vlanNetmask); - - long cidrSizeToUse = -1; - if (vlanCidrSize < guestCidrSize) { - cidrSizeToUse = vlanCidrSize; - } else { - cidrSizeToUse = guestCidrSize; - } - - String guestSubnet = NetUtils.getCidrSubNet(guestIpNetwork, cidrSizeToUse); - - if (newVlanSubnet.equals(guestSubnet)) { + if ( guestNetworkCidr != null ) { + if (NetUtils.isNetworksOverlap(newCidr, guestNetworkCidr)) { throw new InvalidParameterValueException( - "The new IP range you have specified has the same subnet as the guest network in zone: " + "The new IP range you have specified has overlapped with the guest network in zone: " + zone.getName() + ". Please specify a different gateway/netmask."); } } @@ -3009,29 +2995,36 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati // Check if there are any errors with the IP range checkPublicIpRangeErrors(zoneId, vlanId, vlanGateway, vlanNetmask, startIP, endIP); - // Throw an exception if any of the following is true: - // 1. Another VLAN in the same zone has a different tag but the same - // subnet as the new VLAN. Make an exception for the - // case when both vlans are Direct. - // 2. Another VLAN in the same zone that has the same tag and subnet - // as - // the new VLAN has IPs that overlap with the IPs - // being added - // 3. Another VLAN in the same zone that has the same tag and subnet - // as - // the new VLAN has a different gateway than the - // new VLAN - // 4. If VLAN is untagged and Virtual, and there is existing - // UNTAGGED - // vlan with different subnet + // Throw an exception if this subnet overlaps with subnet on other VLAN, + // if this is ip range extension, gateway, network mask should be same and ip range should not overlap + List vlans = _vlanDao.listByZone(zone.getId()); for (VlanVO vlan : vlans) { String otherVlanGateway = vlan.getVlanGateway(); + String otherVlanNetmask = vlan.getVlanNetmask(); // Continue if it's not IPv4 - if (otherVlanGateway == null) { + if ( otherVlanGateway == null || otherVlanNetmask == null ) { continue; } - String otherVlanSubnet = NetUtils.getSubNet(vlan.getVlanGateway(), vlan.getVlanNetmask()); + if ( vlan.getNetworkId() == null ) { + continue; + } + String otherCidr = NetUtils.getCidrFromGatewayAndNetmask(otherVlanGateway, otherVlanNetmask); + if( !NetUtils.isNetworksOverlap(newCidr, otherCidr)) { + continue; + } + // from here, subnet overlaps + if ( !vlanId.equals(vlan.getVlanTag()) ) { + throw new InvalidParameterValueException("The IP range with tag: " + vlan.getVlanTag() + + " in zone " + zone.getName() + + " has overlapped with the subnet. Please specify a different gateway/netmask."); + } + if ( vlan.getNetworkId() != networkId) { + throw new InvalidParameterValueException("This subnet is overlapped with subnet in other network " + vlan.getNetworkId() + + " in zone " + zone.getName() + + " . Please specify a different gateway/netmask."); + + } String[] otherVlanIpRange = vlan.getIpRange().split("\\-"); String otherVlanStartIP = otherVlanIpRange[0]; String otherVlanEndIP = null; @@ -3039,34 +3032,15 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati otherVlanEndIP = otherVlanIpRange[1]; } - if (forVirtualNetwork && !vlanId.equals(vlan.getVlanTag()) && newVlanSubnet.equals(otherVlanSubnet) - && !allowIpRangeOverlap(vlan, forVirtualNetwork, networkId)) { - throw new InvalidParameterValueException("The IP range with tag: " + vlan.getVlanTag() - + " in zone " + zone.getName() - + " has the same subnet. Please specify a different gateway/netmask."); + //extend IP range + if (!vlanGateway.equals(otherVlanGateway) || !vlanNetmask.equals(vlan.getVlanNetmask())) { + throw new InvalidParameterValueException("The IP range has already been added with gateway " + + otherVlanGateway + " ,and netmask " + otherVlanNetmask + + ", Please specify the gateway/netmask if you want to extend ip range" ); } - - boolean vlansUntaggedAndVirtual = (vlanId.equals(Vlan.UNTAGGED) && vlanId.equals(vlan.getVlanTag()) - && forVirtualNetwork && vlan.getVlanType() == VlanType.VirtualNetwork); - - if (vlansUntaggedAndVirtual && !newVlanSubnet.equals(otherVlanSubnet)) { - throw new InvalidParameterValueException( - "The Untagged ip range with different subnet already exists in zone " + zone.getId()); - } - - if (vlanId.equals(vlan.getVlanTag()) && newVlanSubnet.equals(otherVlanSubnet)) { - if (NetUtils.ipRangesOverlap(startIP, endIP, otherVlanStartIP, otherVlanEndIP)) { - throw new InvalidParameterValueException( - "The IP range with tag: " - + vlan.getVlanTag() - + " already has IPs that overlap with the new range. Please specify a different start IP/end IP."); - } - - if (!vlanGateway.equals(otherVlanGateway)) { - throw new InvalidParameterValueException("The IP range with tag: " + vlan.getVlanTag() - + " has already been added with gateway " + otherVlanGateway - + ". Please specify a different tag."); - } + if (NetUtils.ipRangesOverlap(startIP, endIP, otherVlanStartIP, otherVlanEndIP)) { + throw new InvalidParameterValueException("The IP range already has IPs that overlap with the new range." + + " Please specify a different start IP/end IP."); } } } @@ -3085,15 +3059,12 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati } if (vlanId.equals(vlan.getVlanTag())) { if (NetUtils.isIp6RangeOverlap(ipv6Range, vlan.getIp6Range())) { - throw new InvalidParameterValueException( - "The IPv6 range with tag: " - + vlan.getVlanTag() - + " already has IPs that overlap with the new range. Please specify a different start IP/end IP."); + throw new InvalidParameterValueException("The IPv6 range with tag: " + vlan.getVlanTag() + + " already has IPs that overlap with the new range. Please specify a different start IP/end IP."); } if (!vlanIp6Gateway.equals(vlan.getIp6Gateway())) { - throw new InvalidParameterValueException("The IP range with tag: " + vlan.getVlanTag() - + " has already been added with gateway " + vlan.getIp6Gateway() + throw new InvalidParameterValueException("The IP range with tag: " + vlan.getVlanTag() + " has already been added with gateway " + vlan.getIp6Gateway() + ". Please specify a different tag."); } } @@ -4911,14 +4882,6 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati } } - private boolean allowIpRangeOverlap(VlanVO vlan, boolean forVirtualNetwork, long networkId) { - // FIXME - delete restriction for virtual network in the future - if (vlan.getVlanType() == VlanType.DirectAttached && !forVirtualNetwork) { - return true; - } else { - return false; - } - } @Override public ServiceOffering getServiceOffering(long serviceOfferingId) { diff --git a/server/src/com/cloud/network/NetworkServiceImpl.java b/server/src/com/cloud/network/NetworkServiceImpl.java index f1f71ca4078..23bed01d87a 100755 --- a/server/src/com/cloud/network/NetworkServiceImpl.java +++ b/server/src/com/cloud/network/NetworkServiceImpl.java @@ -1233,13 +1233,10 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { } } - // Vlan is created in 2 cases - works in Advance zone only: + // Vlan is created in 1 cases - works in Advance zone only: // 1) GuestType is Shared - // 2) GuestType is Isolated, but SourceNat service is disabled boolean createVlan = (startIP != null && endIP != null && zone.getNetworkType() == NetworkType.Advanced - && ((ntwkOff.getGuestType() == Network.GuestType.Shared) - || (ntwkOff.getGuestType() == GuestType.Isolated && - !areServicesSupportedByNetworkOffering(ntwkOff.getId(), Service.SourceNat)))); + && (ntwkOff.getGuestType() == Network.GuestType.Shared)); if (!createVlan) { // Only support advance shared network in IPv6, which means createVlan is a must From 5ff83e9c313bb8889b0d4ecf936323e32fa01fbf Mon Sep 17 00:00:00 2001 From: Amogh Vasekar Date: Fri, 19 Jul 2013 16:17:45 -0700 Subject: [PATCH 44/74] Adding encryption flag CLOUDSTACK-3308 UCS:DB: UCS Manager password should not get stored in plain text. --- .../src/com/cloud/ucs/database/UcsManagerVO.java | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/plugins/hypervisors/ucs/src/com/cloud/ucs/database/UcsManagerVO.java b/plugins/hypervisors/ucs/src/com/cloud/ucs/database/UcsManagerVO.java index 416ba959e32..45abf23edd3 100644 --- a/plugins/hypervisors/ucs/src/com/cloud/ucs/database/UcsManagerVO.java +++ b/plugins/hypervisors/ucs/src/com/cloud/ucs/database/UcsManagerVO.java @@ -5,9 +5,9 @@ // 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 @@ -27,6 +27,8 @@ import javax.persistence.Table; import org.apache.cloudstack.api.Identity; import org.apache.cloudstack.api.InternalIdentity; +import com.cloud.utils.db.Encrypt; + @Entity @Table(name="ucs_manager") public class UcsManagerVO implements InternalIdentity, Identity { @@ -50,16 +52,19 @@ public class UcsManagerVO implements InternalIdentity, Identity { @Column(name="username") private String username; + @Encrypt @Column(name="password") private String password; - public long getId() { + @Override + public long getId() { return id; } public void setId(long id) { this.id = id; } - public String getUuid() { + @Override + public String getUuid() { return uuid; } public void setUuid(String uuid) { From 668089d575d0d2ef64360d7ab5cbd49b02e13404 Mon Sep 17 00:00:00 2001 From: Anthony Xu Date: Mon, 22 Jul 2013 15:22:00 -0700 Subject: [PATCH 45/74] correct the log message --- .../cloud/hypervisor/xen/discoverer/XcpServerDiscoverer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/discoverer/XcpServerDiscoverer.java b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/discoverer/XcpServerDiscoverer.java index e360c984619..bbb077c3b2b 100755 --- a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/discoverer/XcpServerDiscoverer.java +++ b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/discoverer/XcpServerDiscoverer.java @@ -579,7 +579,7 @@ public class XcpServerDiscoverer extends DiscovererBase implements Discoverer, L cluster.setGuid(startup.getPool()); _clusterDao.update(cluster.getId(), cluster); } else if (! cluster.getGuid().equals(startup.getPool()) ) { - String msg = "pool uuid for cluster " + cluster.getId() + " changed from " + cluster.getGuid() + " to " + cmd.getPod(); + String msg = "pool uuid for cluster " + cluster.getId() + " changed from " + cluster.getGuid() + " to " + startup.getPool(); s_logger.warn(msg); throw new CloudRuntimeException(msg); } From eff27e1f839de57b4c9f5bba3c07b8907e0f0bf9 Mon Sep 17 00:00:00 2001 From: Anthony Xu Date: Mon, 22 Jul 2013 15:49:11 -0700 Subject: [PATCH 46/74] don't update VM state if the state doesn't really change. updating VM state increases the update count, which might cause real VM update fail --- engine/schema/src/com/cloud/vm/dao/VMInstanceDaoImpl.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/engine/schema/src/com/cloud/vm/dao/VMInstanceDaoImpl.java b/engine/schema/src/com/cloud/vm/dao/VMInstanceDaoImpl.java index 8cbc6b64dea..e8f98e9ca26 100644 --- a/engine/schema/src/com/cloud/vm/dao/VMInstanceDaoImpl.java +++ b/engine/schema/src/com/cloud/vm/dao/VMInstanceDaoImpl.java @@ -398,6 +398,10 @@ public class VMInstanceDaoImpl extends GenericDaoBase implem Long oldHostId = vmi.getHostId(); Long oldUpdated = vmi.getUpdated(); Date oldUpdateDate = vmi.getUpdateTime(); + if ( newState.equals(oldState) && newHostId != null && newHostId.equals(oldHostId) ) { + // state is same, don't need to update + return true; + } SearchCriteria sc = StateChangeSearch.create(); sc.setParameters("id", vmi.getId()); From 7f59d6c9ee6708d22e5ddce750adbb4487e954d2 Mon Sep 17 00:00:00 2001 From: Brian Federle Date: Mon, 22 Jul 2013 16:07:40 -0700 Subject: [PATCH 47/74] CLOUDSTACK-2990: Before scape-up, present prompt to user if on VMware --- ui/scripts/autoscaler.js | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/ui/scripts/autoscaler.js b/ui/scripts/autoscaler.js index d30ace89458..b2aa56b05ff 100644 --- a/ui/scripts/autoscaler.js +++ b/ui/scripts/autoscaler.js @@ -1341,6 +1341,7 @@ array1.push("&interval=" + args.data.interval); array1.push("&scaleuppolicyids=" + args.scaleUpPolicyResponse.id); array1.push("&scaledownpolicyids=" + args.scaleDownPolicyResponse.id); + $.ajax({ url: createURL('createAutoScaleVmGroup' + array1.join("")), dataType: 'json', @@ -1414,8 +1415,35 @@ } }; - //*** API calls start!!! ******** - scaleUp(args); + // Get hypervisor; + // if VMware, show notification to user about additional configuration required + $.ajax({ + url: createURL('listTemplates'), + data: { + id: args.data.templateNames, + templatefilter: 'all' + }, + async: false, + success: function(json) { + var template = json.listtemplatesresponse.template; + + if (template && template[0].hypervisor === 'VMware') { + cloudStack.dialog.confirm({ + message: 'For VMware-based VMs, please read the dynamic scaling section in the admin guide before scaling. Would you like to continue?,', + action: function() { + //*** API calls start!!! ******** + scaleUp(args); + }, + cancelAction: function() { + $('.loading-overlay').remove(); + } + }); + } else { + //*** API calls start!!! ******** + scaleUp(args); + } + } + }); }, destroy: function(args) { From 3d05fb0b3e76ee5254892c014372b005926c74b6 Mon Sep 17 00:00:00 2001 From: Anthony Xu Date: Mon, 22 Jul 2013 16:12:44 -0700 Subject: [PATCH 48/74] throw exception if stopping VM fails, then UI can show the error message in stead of fails silently --- server/src/com/cloud/vm/VirtualMachineManagerImpl.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java index 88faea00782..7edd7d2d848 100755 --- a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java +++ b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java @@ -1270,8 +1270,10 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac } catch (AgentUnavailableException e) { s_logger.warn("Unable to stop vm, agent unavailable: " + e.toString()); + throw e; } catch (OperationTimedoutException e) { s_logger.warn("Unable to stop vm, operation timed out: " + e.toString()); + throw e; } finally { if (!stopped) { if (!forced) { From 0fb3286cb1cfcf255768eb34f49658f6993d78ad Mon Sep 17 00:00:00 2001 From: Min Chen Date: Mon, 22 Jul 2013 16:09:57 -0700 Subject: [PATCH 49/74] CLOUDSTACK-3513:[Automation] Failed to copy iso and template between zones. Failed to pass generated copy url to DownloadCommand. --- .../storage/image/TemplateDataFactoryImpl.java | 9 ++++++++- .../com/cloud/storage/download/DownloadMonitorImpl.java | 9 +++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/engine/storage/image/src/org/apache/cloudstack/storage/image/TemplateDataFactoryImpl.java b/engine/storage/image/src/org/apache/cloudstack/storage/image/TemplateDataFactoryImpl.java index e369c1c033e..be0ce4e6b99 100644 --- a/engine/storage/image/src/org/apache/cloudstack/storage/image/TemplateDataFactoryImpl.java +++ b/engine/storage/image/src/org/apache/cloudstack/storage/image/TemplateDataFactoryImpl.java @@ -100,6 +100,13 @@ public class TemplateDataFactoryImpl implements TemplateDataFactory { @Override public TemplateInfo getTemplate(DataObject obj, DataStore store) { - return this.getTemplate(obj.getId(), store); + TemplateObject tmpObj = (TemplateObject) this.getTemplate(obj.getId(), store); + // carry over url set in passed in data object, for copyTemplate case + // where url is generated on demand and not persisted in DB. + // need to think of a more generic way to pass these runtime information + // carried through DataObject post 4.2 + TemplateObject origTmpl = (TemplateObject) obj; + tmpObj.setUrl(origTmpl.getUrl()); + return tmpObj; } } diff --git a/server/src/com/cloud/storage/download/DownloadMonitorImpl.java b/server/src/com/cloud/storage/download/DownloadMonitorImpl.java index 4918bf55f1f..f0550855bb5 100755 --- a/server/src/com/cloud/storage/download/DownloadMonitorImpl.java +++ b/server/src/com/cloud/storage/download/DownloadMonitorImpl.java @@ -55,6 +55,7 @@ import com.cloud.agent.api.storage.Proxy; import com.cloud.configuration.Config; import com.cloud.configuration.dao.ConfigurationDao; import com.cloud.storage.RegisterVolumePayload; +import com.cloud.storage.VMTemplateStorageResourceAssoc; import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.VMTemplateStorageResourceAssoc.Status; import com.cloud.storage.Volume; @@ -215,7 +216,15 @@ public class DownloadMonitorImpl extends ManagerBase implements DownloadMonitor if (isTemplateUpdateable(templateId, store.getId())) { if (template != null && template.getUri() != null) { initiateTemplateDownload(template, callback); + } else { + s_logger.info("Template url is null, cannot download"); + DownloadAnswer ans = new DownloadAnswer("Template url is null", VMTemplateStorageResourceAssoc.Status.DOWNLOAD_ERROR.UNKNOWN); + callback.complete(ans); } + } else { + s_logger.info("Template download is already in progress or already downloaded"); + DownloadAnswer ans = new DownloadAnswer("Template download is already in progress or already downloaded", VMTemplateStorageResourceAssoc.Status.DOWNLOAD_ERROR.UNKNOWN); + callback.complete(ans); } } From db8b9ea53a66c6ceac9eb28fbd0d75e14c50c755 Mon Sep 17 00:00:00 2001 From: Min Chen Date: Mon, 22 Jul 2013 16:15:20 -0700 Subject: [PATCH 50/74] Remove CLOUDSTACK-3513 debugging messages. --- .../storage/endpoint/DefaultEndPointSelector.java | 3 ++- server/src/com/cloud/agent/manager/AgentAttache.java | 12 ------------ .../com/cloud/agent/manager/AgentManagerImpl.java | 4 +--- 3 files changed, 3 insertions(+), 16 deletions(-) diff --git a/engine/storage/src/org/apache/cloudstack/storage/endpoint/DefaultEndPointSelector.java b/engine/storage/src/org/apache/cloudstack/storage/endpoint/DefaultEndPointSelector.java index bbd6b6e12d1..c3f52ffcf29 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/endpoint/DefaultEndPointSelector.java +++ b/engine/storage/src/org/apache/cloudstack/storage/endpoint/DefaultEndPointSelector.java @@ -191,8 +191,9 @@ public class DefaultEndPointSelector implements EndPointSelector { // we can arbitrarily pick one ssvm to do that task List ssAHosts = listUpAndConnectingSecondaryStorageVmHost(dcId); if (ssAHosts == null || ssAHosts.isEmpty()) { + s_logger.info("No running ssvm is found, so command will be sent to LocalHostEndPoint"); return LocalHostEndpoint.getEndpoint(); // use local host as endpoint in - // case of no ssvm existing + // case of no ssvm existing } Collections.shuffle(ssAHosts); HostVO host = ssAHosts.get(0); diff --git a/server/src/com/cloud/agent/manager/AgentAttache.java b/server/src/com/cloud/agent/manager/AgentAttache.java index 2cedc4d474f..92ce17bc6d3 100755 --- a/server/src/com/cloud/agent/manager/AgentAttache.java +++ b/server/src/com/cloud/agent/manager/AgentAttache.java @@ -337,26 +337,14 @@ public abstract class AgentAttache { checkAvailability(req.getCommands()); long seq = req.getSequence(); - if (s_logger.isDebugEnabled()) { - s_logger.debug("Request seq: " + seq); - } - if (listener != null) { registerListener(seq, listener); } else if (s_logger.isDebugEnabled()) { s_logger.debug(log(seq, "Routed from " + req.getManagementServerId())); } - if (s_logger.isDebugEnabled()) { - s_logger.debug("waiting to send " + seq); - } - synchronized(this) { try { - if (s_logger.isDebugEnabled()) { - s_logger.debug("entering synchronize block for sending " + seq); - } - if (isClosed()) { throw new AgentUnavailableException("The link to the agent has been closed", _id); } diff --git a/server/src/com/cloud/agent/manager/AgentManagerImpl.java b/server/src/com/cloud/agent/manager/AgentManagerImpl.java index edc0d9d4c5c..46b864485fe 100755 --- a/server/src/com/cloud/agent/manager/AgentManagerImpl.java +++ b/server/src/com/cloud/agent/manager/AgentManagerImpl.java @@ -538,9 +538,7 @@ public class AgentManagerImpl extends ManagerBase implements AgentManager, Handl } Request req = new Request(hostId, _nodeId, cmds, commands.stopOnError(), true); req.setSequence(agent.getNextSequence()); - if (s_logger.isDebugEnabled()) { - s_logger.debug("AgentManager sending request"); - } + agent.send(req, listener); return req.getSequence(); } From c9fdee8f212a327f53cd845268a2de131fc2a3e9 Mon Sep 17 00:00:00 2001 From: Brian Federle Date: Mon, 22 Jul 2013 16:14:45 -0700 Subject: [PATCH 51/74] CLOUDSTACK-3710: Remove over-commit ratio fields from edit cluster UI Removes over-commit fields as editable. This also removes the 'edit cluster' action, as there are no longer any fields to edit. --- ui/scripts/system.js | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/ui/scripts/system.js b/ui/scripts/system.js index f4f4047bd6f..a56397e0c7a 100644 --- a/ui/scripts/system.js +++ b/ui/scripts/system.js @@ -11300,21 +11300,12 @@ action: function(args) { var array1 = []; - if (args.data.cpuovercommitratio != "" && args.data.cpuovercommitratio > 0) - array1.push("&cpuovercommitratio=" + args.data.cpuovercommitratio); - - if (args.data.memoryovercommitratio != "" && args.data.memoryovercommitratio > 0) - array1.push("&memoryovercommitratio=" + args.data.memoryovercommitratio); - $.ajax({ - url: createURL("updateCluster&id=" + args.context.clusters[0].id + array1.join("")), dataType: "json", async: true, success: function(json) { var item = json.updateclusterresponse.cluster; - args.context.clusters[0].cpuovercommitratio = item.cpuovercommitratio; - args.context.clusters[0].memoryovercommitratio = item.memoryovercommitratio; addExtraPropertiesToClusterObject(item); args.response.success({ actionFilter: clusterActionfilter, @@ -16319,12 +16310,12 @@ if (jsonObj.state == "Enabled") { //managed, allocation enabled allowedActions.push("unmanage"); allowedActions.push("disable"); - allowedActions.push("edit"); + //allowedActions.push("edit"); // No fields to edit } else if (jsonObj.state == "Disabled") { //managed, allocation disabled allowedActions.push("unmanage"); allowedActions.push("enable"); - allowedActions.push("edit"); + //allowedActions.push("edit"); // No fields to edit } else { //Unmanaged, PrepareUnmanaged , PrepareUnmanagedError allowedActions.push("manage"); From 6ac361e6a297b54e025ac1b121601e653557190f Mon Sep 17 00:00:00 2001 From: Alex Huang Date: Mon, 22 Jul 2013 16:32:39 -0700 Subject: [PATCH 52/74] Removed VM generic from VirtualMachineGuru. Part of the cleanup to make vmsync a simple vm manager that doesn't understand the different types of vms --- .../lb/ElasticLoadBalancerManagerImpl.java | 13 +-- .../lb/InternalLoadBalancerVMManagerImpl.java | 9 +- .../consoleproxy/ConsoleProxyManagerImpl.java | 10 +-- .../VirtualNetworkApplianceManagerImpl.java | 9 +- .../SecondaryStorageManagerImpl.java | 19 ++-- server/src/com/cloud/vm/UserVmManager.java | 8 +- .../src/com/cloud/vm/UserVmManagerImpl.java | 9 +- .../src/com/cloud/vm/VirtualMachineGuru.java | 5 +- .../com/cloud/vm/VirtualMachineManager.java | 2 +- .../cloud/vm/VirtualMachineManagerImpl.java | 90 ++++++++----------- .../vm/VirtualMachineManagerImplTest.java | 4 +- 11 files changed, 69 insertions(+), 109 deletions(-) diff --git a/plugins/network-elements/elastic-loadbalancer/src/com/cloud/network/lb/ElasticLoadBalancerManagerImpl.java b/plugins/network-elements/elastic-loadbalancer/src/com/cloud/network/lb/ElasticLoadBalancerManagerImpl.java index 8d32f4369a2..63663fef394 100644 --- a/plugins/network-elements/elastic-loadbalancer/src/com/cloud/network/lb/ElasticLoadBalancerManagerImpl.java +++ b/plugins/network-elements/elastic-loadbalancer/src/com/cloud/network/lb/ElasticLoadBalancerManagerImpl.java @@ -139,10 +139,8 @@ import com.cloud.vm.dao.NicDao; @Component @Local(value = { ElasticLoadBalancerManager.class }) -public class ElasticLoadBalancerManagerImpl extends ManagerBase implements -ElasticLoadBalancerManager, VirtualMachineGuru { - private static final Logger s_logger = Logger - .getLogger(ElasticLoadBalancerManagerImpl.class); +public class ElasticLoadBalancerManagerImpl extends ManagerBase implements ElasticLoadBalancerManager, VirtualMachineGuru { + private static final Logger s_logger = Logger.getLogger(ElasticLoadBalancerManagerImpl.class); @Inject IPAddressDao _ipAddressDao; @@ -776,11 +774,6 @@ ElasticLoadBalancerManager, VirtualMachineGuru { } } - @Override - public DomainRouterVO findById(long id) { - return _routerDao.findById(id); - } - @Override public boolean finalizeVirtualMachineProfile(VirtualMachineProfile profile, DeployDestination dest, ReservationContext context) { @@ -960,7 +953,7 @@ ElasticLoadBalancerManager, VirtualMachineGuru { } @Override - public void finalizeExpunge(DomainRouterVO vm) { + public void finalizeExpunge(VirtualMachine vm) { // no-op } diff --git a/plugins/network-elements/internal-loadbalancer/src/org/apache/cloudstack/network/lb/InternalLoadBalancerVMManagerImpl.java b/plugins/network-elements/internal-loadbalancer/src/org/apache/cloudstack/network/lb/InternalLoadBalancerVMManagerImpl.java index 481bbca2458..a731f562ebb 100644 --- a/plugins/network-elements/internal-loadbalancer/src/org/apache/cloudstack/network/lb/InternalLoadBalancerVMManagerImpl.java +++ b/plugins/network-elements/internal-loadbalancer/src/org/apache/cloudstack/network/lb/InternalLoadBalancerVMManagerImpl.java @@ -120,7 +120,7 @@ import com.cloud.vm.dao.NicDao; @Component @Local(value = { InternalLoadBalancerVMManager.class, InternalLoadBalancerVMService.class}) public class InternalLoadBalancerVMManagerImpl extends ManagerBase implements - InternalLoadBalancerVMManager, VirtualMachineGuru { + InternalLoadBalancerVMManager, VirtualMachineGuru { private static final Logger s_logger = Logger .getLogger(InternalLoadBalancerVMManagerImpl.class); static final private String _internalLbVmNamePrefix = "b"; @@ -150,11 +150,6 @@ public class InternalLoadBalancerVMManagerImpl extends ManagerBase implements @Inject ResourceManager _resourceMgr; @Inject ConfigurationServer _configServer; - @Override - public DomainRouterVO findById(long id) { - return _internalLbVmDao.findById(id); - } - @Override public boolean finalizeVirtualMachineProfile(VirtualMachineProfile profile, DeployDestination dest, ReservationContext context) { @@ -339,7 +334,7 @@ public class InternalLoadBalancerVMManagerImpl extends ManagerBase implements } @Override - public void finalizeExpunge(DomainRouterVO vm) { + public void finalizeExpunge(VirtualMachine vm) { } @Override diff --git a/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java b/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java index 5aeb6dc0307..1c31177a884 100755 --- a/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java +++ b/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java @@ -155,7 +155,7 @@ import com.cloud.vm.dao.VMInstanceDao; // @Local(value = { ConsoleProxyManager.class, ConsoleProxyService.class }) public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxyManager, - VirtualMachineGuru, SystemVmLoadScanHandler, ResourceStateAdapter { + VirtualMachineGuru, SystemVmLoadScanHandler, ResourceStateAdapter { private static final Logger s_logger = Logger.getLogger(ConsoleProxyManagerImpl.class); private static final int DEFAULT_CAPACITY_SCAN_INTERVAL = 30000; // 30 seconds @@ -1468,7 +1468,8 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy } @Override - public void finalizeExpunge(ConsoleProxyVO proxy) { + public void finalizeExpunge(VirtualMachine vm) { + ConsoleProxyVO proxy = _consoleProxyDao.findById(vm.getId()); proxy.setPublicIpAddress(null); proxy.setPublicMacAddress(null); proxy.setPublicNetmask(null); @@ -1477,11 +1478,6 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy _consoleProxyDao.update(proxy.getId(), proxy); } - @Override - public ConsoleProxyVO findById(long id) { - return _consoleProxyDao.findById(id); - } - @Override public void finalizeStop(VirtualMachineProfile profile, StopAnswer answer) { //release elastic IP here if assigned diff --git a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java index ef7f50b85e1..89db3c23a46 100755 --- a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java +++ b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java @@ -261,7 +261,7 @@ import com.cloud.vm.dao.VMInstanceDao; @Component @Local(value = { VirtualNetworkApplianceManager.class, VirtualNetworkApplianceService.class }) public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements VirtualNetworkApplianceManager, VirtualNetworkApplianceService, - VirtualMachineGuru, Listener { + VirtualMachineGuru, Listener { private static final Logger s_logger = Logger.getLogger(VirtualNetworkApplianceManagerImpl.class); @Inject @@ -2639,7 +2639,7 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V } @Override - public void finalizeExpunge(DomainRouterVO vm) { + public void finalizeExpunge(VirtualMachine vm) { } @@ -3065,11 +3065,6 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V return result; } - @Override - public DomainRouterVO findById(long id) { - return _routerDao.findById(id); - } - @Override @ActionEvent(eventType = EventTypes.EVENT_ROUTER_START, eventDescription = "starting router Vm", async = true) public VirtualRouter startRouter(long id) throws ResourceUnavailableException, InsufficientCapacityException, ConcurrentOperationException{ return startRouter(id, true); diff --git a/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java b/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java index 037eb258323..127a824e794 100755 --- a/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java +++ b/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java @@ -155,7 +155,7 @@ import com.cloud.vm.dao.VMInstanceDao; // because sooner or later, it will be driven into Running state // @Local(value = { SecondaryStorageVmManager.class }) -public class SecondaryStorageManagerImpl extends ManagerBase implements SecondaryStorageVmManager, VirtualMachineGuru, SystemVmLoadScanHandler, ResourceStateAdapter { +public class SecondaryStorageManagerImpl extends ManagerBase implements SecondaryStorageVmManager, VirtualMachineGuru, SystemVmLoadScanHandler, ResourceStateAdapter { private static final Logger s_logger = Logger.getLogger(SecondaryStorageManagerImpl.class); private static final int DEFAULT_CAPACITY_SCAN_INTERVAL = 30000; // 30 @@ -1002,11 +1002,6 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar return "secStorageVm." + id; } - @Override - public SecondaryStorageVmVO findById(long id) { - return _secStorageVmDao.findById(id); - } - @Override public boolean finalizeVirtualMachineProfile(VirtualMachineProfile profile, DeployDestination dest, ReservationContext context) { @@ -1197,11 +1192,13 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar } @Override - public void finalizeExpunge(SecondaryStorageVmVO vm) { - vm.setPublicIpAddress(null); - vm.setPublicMacAddress(null); - vm.setPublicNetmask(null); - _secStorageVmDao.update(vm.getId(), vm); + public void finalizeExpunge(VirtualMachine vm) { + SecondaryStorageVmVO ssvm = _secStorageVmDao.findByUuid(vm.getUuid()); + + ssvm.setPublicIpAddress(null); + ssvm.setPublicMacAddress(null); + ssvm.setPublicNetmask(null); + _secStorageVmDao.update(ssvm.getId(), ssvm); } @Override diff --git a/server/src/com/cloud/vm/UserVmManager.java b/server/src/com/cloud/vm/UserVmManager.java index 348017a0a44..635d15e76e1 100755 --- a/server/src/com/cloud/vm/UserVmManager.java +++ b/server/src/com/cloud/vm/UserVmManager.java @@ -23,7 +23,11 @@ import java.util.Map; import com.cloud.agent.api.VmDiskStatsEntry; import com.cloud.agent.api.VmStatsEntry; import com.cloud.api.query.vo.UserVmJoinVO; -import com.cloud.exception.*; +import com.cloud.exception.ConcurrentOperationException; +import com.cloud.exception.InsufficientCapacityException; +import com.cloud.exception.ManagementServerException; +import com.cloud.exception.ResourceUnavailableException; +import com.cloud.exception.VirtualMachineMigrationException; import com.cloud.projects.Project.ListProjectResourcesCriteria; import com.cloud.server.Criteria; import com.cloud.user.Account; @@ -34,7 +38,7 @@ import com.cloud.utils.Pair; * * */ -public interface UserVmManager extends VirtualMachineGuru, UserVmService{ +public interface UserVmManager extends UserVmService { static final int MAX_USER_DATA_LENGTH_BYTES = 2048; /** diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java b/server/src/com/cloud/vm/UserVmManagerImpl.java index 14938717672..a4508eef528 100755 --- a/server/src/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/com/cloud/vm/UserVmManagerImpl.java @@ -254,7 +254,7 @@ import com.cloud.vm.snapshot.VMSnapshotVO; import com.cloud.vm.snapshot.dao.VMSnapshotDao; @Local(value = { UserVmManager.class, UserVmService.class }) -public class UserVmManagerImpl extends ManagerBase implements UserVmManager, UserVmService { +public class UserVmManagerImpl extends ManagerBase implements UserVmManager, VirtualMachineGuru, UserVmService { private static final Logger s_logger = Logger .getLogger(UserVmManagerImpl.class); @@ -3083,12 +3083,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use } @Override - public void finalizeExpunge(UserVmVO vm) { - } - - @Override - public UserVmVO findById(long id) { - return _vmDao.findById(id); + public void finalizeExpunge(VirtualMachine vm) { } @Override diff --git a/server/src/com/cloud/vm/VirtualMachineGuru.java b/server/src/com/cloud/vm/VirtualMachineGuru.java index 3318b461451..3fb065bcd24 100644 --- a/server/src/com/cloud/vm/VirtualMachineGuru.java +++ b/server/src/com/cloud/vm/VirtualMachineGuru.java @@ -25,8 +25,7 @@ import com.cloud.exception.ResourceUnavailableException; * A VirtualMachineGuru knows how to process a certain type of virtual machine. * */ -public interface VirtualMachineGuru { - T findById(long id); +public interface VirtualMachineGuru { boolean finalizeVirtualMachineProfile(VirtualMachineProfile profile, DeployDestination dest, ReservationContext context); @@ -52,7 +51,7 @@ public interface VirtualMachineGuru { void finalizeStop(VirtualMachineProfile profile, StopAnswer answer); - void finalizeExpunge(T vm); + void finalizeExpunge(VirtualMachine vm); /** * Prepare Vm for Stop diff --git a/server/src/com/cloud/vm/VirtualMachineManager.java b/server/src/com/cloud/vm/VirtualMachineManager.java index 0086bdb6dbc..4982bcb2279 100644 --- a/server/src/com/cloud/vm/VirtualMachineManager.java +++ b/server/src/com/cloud/vm/VirtualMachineManager.java @@ -80,7 +80,7 @@ public interface VirtualMachineManager extends Manager { boolean expunge(T vm, User caller, Account account) throws ResourceUnavailableException; - void registerGuru(VirtualMachine.Type type, VirtualMachineGuru guru); + void registerGuru(VirtualMachine.Type type, VirtualMachineGuru guru); boolean stateTransitTo(VMInstanceVO vm, VirtualMachine.Event e, Long hostId) throws NoTransitionException; diff --git a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java index 7edd7d2d848..fc55ee5d565 100755 --- a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java +++ b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java @@ -19,7 +19,6 @@ package com.cloud.vm; import java.net.URI; import java.util.ArrayList; -import java.util.Collection; import java.util.Collections; import java.util.Date; import java.util.HashMap; @@ -325,7 +324,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac @Inject DeploymentPlanningManager _dpMgr; - Map> _vmGurus = new HashMap>(); + Map _vmGurus = new HashMap(); protected StateMachine2 _stateMachine; ScheduledExecutorService _executor = null; @@ -341,7 +340,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac protected boolean _forceStop; @Override - public void registerGuru(VirtualMachine.Type type, VirtualMachineGuru guru) { + public void registerGuru(VirtualMachine.Type type, VirtualMachineGuru guru) { synchronized (_vmGurus) { _vmGurus.put(type, guru); } @@ -414,9 +413,8 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac allocate(vmInstanceName, template, serviceOffering, new Pair(serviceOffering, null), null, networks, null, plan, hyperType); } - @SuppressWarnings("unchecked") - private VirtualMachineGuru getVmGuru(T vm) { - return (VirtualMachineGuru) _vmGurus.get(vm.getType()); + private VirtualMachineGuru getVmGuru(VirtualMachine vm) { + return _vmGurus.get(vm.getType()); } @Override @@ -482,7 +480,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac List rootVol = _volsDao.findByInstanceAndType(vm.getId(), Volume.Type.ROOT); volumeMgr.cleanupVolumes(vm.getId()); - VirtualMachineGuru guru = getVmGuru(vm); + VirtualMachineGuru guru = getVmGuru(vm); guru.finalizeExpunge(vm); //remove the overcommit detials from the uservm details _uservmDetailsDao.deleteDetails(vm.getId()); @@ -762,8 +760,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac VMInstanceVO vm = _vmDao.findByUuid(vmUuid); - long vmId = vm.getId(); - VirtualMachineGuru vmGuru = getVmGuru(vm); + VirtualMachineGuru vmGuru = getVmGuru(vm); Ternary start = changeToStartState(vmGuru, vm, caller, account); if (start == null) { @@ -1045,8 +1042,6 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac throw new CloudRuntimeException("Unable to start instance '" + vm.getHostName() + "' (" + vm.getUuid() + "), see management server log for details"); } - - return; } @Override @@ -1194,7 +1189,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac return true; } - VirtualMachineGuru vmGuru = getVmGuru(vm); + VirtualMachineGuru vmGuru = getVmGuru(vm); VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm); try { @@ -1429,11 +1424,8 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac } @Override - public T storageMigration(T vm, StoragePool destPool) { - VirtualMachineGuru vmGuru = getVmGuru(vm); - - long vmId = vm.getId(); - vm = vmGuru.findById(vmId); + public T storageMigration(T vmm, StoragePool destPool) { + VMInstanceVO vm = _vmDao.findByUuid(vmm.getUuid()); try { stateTransitTo(vm, VirtualMachine.Event.StorageMigrationRequested, null); @@ -1483,12 +1475,21 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac } } - return vm; + return vmm; } @Override - public T migrate(T vm, long srcHostId, DeployDestination dest) throws ResourceUnavailableException, ConcurrentOperationException, ManagementServerException, + public T migrate(T vmm, long srcHostId, DeployDestination dest) throws ResourceUnavailableException, ConcurrentOperationException, + ManagementServerException, VirtualMachineMigrationException { + VMInstanceVO vm = _vmDao.findByUuid(vmm.getUuid()); + if (vm == null) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Unable to find the vm " + vm); + } + throw new CloudRuntimeException("Unable to find a virtual machine with id " + vmm.getUuid()); + } + s_logger.info("Migrating " + vm + " to " + dest); long dstHostId = dest.getHost().getId(); @@ -1503,16 +1504,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac throw new CloudRuntimeException("Source and destination host are not in same cluster, unable to migrate to host: " + dest.getHost().getId()); } - VirtualMachineGuru vmGuru = getVmGuru(vm); - - long vmId = vm.getId(); - vm = vmGuru.findById(vmId); - if (vm == null) { - if (s_logger.isDebugEnabled()) { - s_logger.debug("Unable to find the vm " + vm); - } - throw new ManagementServerException("Unable to find a virtual machine with id " + vmId); - } + VirtualMachineGuru vmGuru = getVmGuru(vm); if (vm.getState() != State.Running) { if (s_logger.isDebugEnabled()) { @@ -1620,7 +1612,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac } migrated = true; - return vm; + return vmm; } finally { if (!migrated) { s_logger.info("Migration was unsuccessful. Cleaning up: " + vm); @@ -1736,13 +1728,14 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac } @Override - public T migrateWithStorage(T vm, long srcHostId, long destHostId, + public T migrateWithStorage(T vmm, long srcHostId, long destHostId, Map volumeToPool) throws ResourceUnavailableException, ConcurrentOperationException, ManagementServerException, VirtualMachineMigrationException { + VMInstanceVO vm = _vmDao.findByUuid(vmm.getUuid()); HostVO srcHost = _hostDao.findById(srcHostId); HostVO destHost = _hostDao.findById(destHostId); - VirtualMachineGuru vmGuru = getVmGuru(vm); + VirtualMachineGuru vmGuru = getVmGuru(vm); DataCenterVO dc = _dcDao.findById(destHost.getDataCenterId()); HostPodVO pod = _podDao.findById(destHost.getPodId()); @@ -1750,8 +1743,6 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac DeployDestination destination = new DeployDestination(dc, pod, cluster, destHost); // Create a map of which volume should go in which storage pool. - long vmId = vm.getId(); - vm = vmGuru.findById(vmId); VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm); volumeToPool = getPoolListForVolumesForMigration(profile, destHost, volumeToPool); @@ -1809,7 +1800,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac } migrated = true; - return vm; + return vmm; } finally { if (!migrated) { s_logger.info("Migration was unsuccessful. Cleaning up: " + vm); @@ -1831,6 +1822,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac } } + @Override public VirtualMachineTO toVmTO(VirtualMachineProfile profile) { HypervisorGuru hvGuru = _hvGuruMgr.getGuru(profile.getVirtualMachine().getHypervisorType()); VirtualMachineTO to = hvGuru.implement(profile); @@ -1878,8 +1870,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac @Override public boolean migrateAway(VirtualMachine.Type vmType, long vmId, long srcHostId) throws InsufficientServerCapacityException, VirtualMachineMigrationException { - VirtualMachineGuru vmGuru = _vmGurus.get(vmType); - VMInstanceVO vm = vmGuru.findById(vmId); + VMInstanceVO vm = _vmDao.findById(vmId); if (vm == null) { s_logger.debug("Unable to find a VM for " + vmId); return true; @@ -2028,8 +2019,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac @Override public VMInstanceVO findByIdAndType(VirtualMachine.Type type, long vmId) { - VirtualMachineGuru guru = _vmGurus.get(type); - return guru.findById(vmId); + return _vmDao.findById(vmId); } public Command cleanup(VirtualMachine vm) { @@ -2302,7 +2292,6 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac if (newStates == null) { return map; } - Collection> vmGurus = _vmGurus.values(); boolean is_alien_vm = true; long alien_vm_count = -1; for (Map.Entry> entry : newStates.entrySet()) { @@ -2541,10 +2530,10 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac } private void ensureVmRunningContext(long hostId, VMInstanceVO vm, Event cause) throws OperationTimedoutException, ResourceUnavailableException, NoTransitionException, InsufficientAddressCapacityException { - VirtualMachineGuru vmGuru = getVmGuru(vm); + VirtualMachineGuru vmGuru = getVmGuru(vm); s_logger.debug("VM state is starting on full sync so updating it to running"); - vm = findByIdAndType(vm.getType(), vm.getId()); + vm = _vmDao.findById(vm.getId()); // grab outstanding work item if any ItWorkVO work = _workDao.findByOutstandingWork(vm.getId(), vm.getState()); @@ -2561,7 +2550,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac } s_logger.debug("VM's " + vm + " state is starting on full sync so updating it to Running"); - vm = vmGuru.findById(vm.getId()); // this should ensure vm has the most + vm = _vmDao.findById(vm.getId()); // this should ensure vm has the most // up to date info VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm); @@ -2764,7 +2753,6 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac public String hostUuid; public VMInstanceVO vm; - @SuppressWarnings("unchecked") public AgentVmInfo(String name, VMInstanceVO vm, State state, String host) { this.name = name; this.state = state; @@ -2899,8 +2887,6 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac NicTO nicTO = toNicTO(nic, vmProfile.getVirtualMachine().getHypervisorType()); //4) plug the nic to the vm - VirtualMachineGuru vmGuru = getVmGuru(vmVO); - s_logger.debug("Plugging nic for vm " + vm + " in network " + network); boolean result = false; @@ -2954,7 +2940,6 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac DataCenter dc = _configMgr.getZone(network.getDataCenterId()); Host host = _hostDao.findById(vm.getHostId()); DeployDestination dest = new DeployDestination(dc, null, null, host); - VirtualMachineGuru vmGuru = getVmGuru(vmVO); HypervisorGuru hvGuru = _hvGuruMgr.getGuru(vmProfile.getVirtualMachine().getHypervisorType()); VirtualMachineTO vmTO = hvGuru.implement(vmProfile); @@ -3018,7 +3003,6 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac DataCenter dc = _configMgr.getZone(network.getDataCenterId()); Host host = _hostDao.findById(vm.getHostId()); DeployDestination dest = new DeployDestination(dc, null, null, host); - VirtualMachineGuru vmGuru = getVmGuru(vmVO); HypervisorGuru hvGuru = _hvGuruMgr.getGuru(vmProfile.getVirtualMachine().getHypervisorType()); VirtualMachineTO vmTO = hvGuru.implement(vmProfile); @@ -3138,8 +3122,10 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac } @Override - public T migrateForScale(T vm, long srcHostId, DeployDestination dest, Long oldSvcOfferingId) throws ResourceUnavailableException, ConcurrentOperationException, ManagementServerException, + public T migrateForScale(T vmm, long srcHostId, DeployDestination dest, Long oldSvcOfferingId) throws ResourceUnavailableException, + ConcurrentOperationException, ManagementServerException, VirtualMachineMigrationException { + VMInstanceVO vm = _vmDao.findByUuid(vmm.getUuid()); s_logger.info("Migrating " + vm + " to " + dest); vm.getServiceOfferingId(); @@ -3155,10 +3141,10 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac throw new CloudRuntimeException("Source and destination host are not in same cluster, unable to migrate to host: " + dest.getHost().getId()); } - VirtualMachineGuru vmGuru = getVmGuru(vm); + VirtualMachineGuru vmGuru = getVmGuru(vm); long vmId = vm.getId(); - vm = vmGuru.findById(vmId); + vm = _vmDao.findByUuid(vmm.getUuid()); if (vm == null) { if (s_logger.isDebugEnabled()) { s_logger.debug("Unable to find the vm " + vm); @@ -3267,7 +3253,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac } migrated = true; - return vm; + return vmm; } finally { if (!migrated) { s_logger.info("Migration was unsuccessful. Cleaning up: " + vm); diff --git a/server/test/com/cloud/vm/VirtualMachineManagerImplTest.java b/server/test/com/cloud/vm/VirtualMachineManagerImplTest.java index a49b0e0fcd7..fba95b3d265 100644 --- a/server/test/com/cloud/vm/VirtualMachineManagerImplTest.java +++ b/server/test/com/cloud/vm/VirtualMachineManagerImplTest.java @@ -223,6 +223,7 @@ public class VirtualMachineManagerImplTest { when(_workDao.update("1", _work)).thenReturn(true); when(_work.getId()).thenReturn("1"); doNothing().when(_work).setStep(ItWorkVO.Step.Done); + when(_vmInstanceDao.findByUuid(any(String.class))).thenReturn(_vmMock); //doNothing().when(_volsDao).detachVolume(anyLong()); //when(_work.setStep(ItWorkVO.Step.Done)).thenReturn("1"); @@ -332,10 +333,9 @@ public class VirtualMachineManagerImplTest { doNothing().when(_work).setStep(ItWorkVO.Step.Done); // Mock the vm guru and the user vm object that gets returned. - _vmMgr._vmGurus = new HashMap>(); + _vmMgr._vmGurus = new HashMap(); UserVmManagerImpl userVmManager = mock(UserVmManagerImpl.class); _vmMgr.registerGuru(VirtualMachine.Type.User, userVmManager); - when(userVmManager.findById(anyLong())).thenReturn(_vmMock); // Mock the iteration over all the volumes of an instance. Iterator volumeIterator = mock(Iterator.class); From 7974dfe8db4c9a7f85875ac569ca27f2b39d2e05 Mon Sep 17 00:00:00 2001 From: Brian Federle Date: Mon, 22 Jul 2013 16:52:37 -0700 Subject: [PATCH 53/74] CLOUDSTACK-3660: Add isdynamicallyscalable field Add isdynamicallyscalable field to storage -> create template dialog --- ui/scripts/storage.js | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/ui/scripts/storage.js b/ui/scripts/storage.js index 348ba7b79e4..5e1c225891d 100644 --- a/ui/scripts/storage.js +++ b/ui/scripts/storage.js @@ -1075,6 +1075,10 @@ isFeatured: { label: "label.featured", isBoolean: true + }, + isdynamicallyscalable: { + label: "Dynamically Scalable", + isBoolean: true } } }, @@ -1085,7 +1089,9 @@ displayText: args.data.displayText, osTypeId: args.data.osTypeId, isPublic: (args.data.isPublic == "on"), - passwordEnabled: (args.data.isPasswordEnabled == "on") + passwordEnabled: (args.data.isPasswordEnabled == "on"), + isdynamicallyscalable: (args.data.isdynamicallyscalable == "on") + }; if (args.$form.find('.form-item[rel=isFeatured]').css("display") != "none") { @@ -1660,6 +1666,10 @@ isPasswordEnabled: { label: 'label.password.enabled', isBoolean: true + }, + isdynamicallyscalable: { + label: "Dynamically Scalable", + isBoolean: true } } }, @@ -1670,7 +1680,8 @@ displayText: args.data.displayText, osTypeId: args.data.osTypeId, isPublic: (args.data.isPublic == "on"), - passwordEnabled: (args.data.isPasswordEnabled == "on") + passwordEnabled: (args.data.isPasswordEnabled == "on"), + isdynamicallyscalable: (args.data.isdynamicallyscalable == "on") }; $.ajax({ From 181fb03e7e6ed89102a8b5f0acfddf88d148d55c Mon Sep 17 00:00:00 2001 From: Min Chen Date: Mon, 22 Jul 2013 17:12:02 -0700 Subject: [PATCH 54/74] CLOUDSTACK-3716:NPE triggered in DownloadListener --- .../apache/cloudstack/storage/volume/VolumeServiceImpl.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java b/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java index 9338d3807e9..3b544b18023 100644 --- a/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java +++ b/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java @@ -1045,6 +1045,11 @@ public class VolumeServiceImpl implements VolumeService { List toBeDownloaded = new ArrayList(dbVolumes); for (VolumeDataStoreVO volumeStore : dbVolumes) { VolumeVO volume = _volumeDao.findById(volumeStore.getVolumeId()); + if (volume == null ){ + s_logger.warn("Volume_store_ref shows that volume " + volumeStore.getVolumeId() + " is on image store " + storeId + + ", but the volume is not found in volumes table, potentially some bugs in deleteVolume, so we just treat this volume to be deleted"); + continue; + } // Exists then don't download if (volumeInfos.containsKey(volume.getId())) { TemplateProp volInfo = volumeInfos.remove(volume.getId()); From cc99a83d71f399d8679d9bdd81b5f2f7e2cf59ef Mon Sep 17 00:00:00 2001 From: Min Chen Date: Mon, 22 Jul 2013 17:24:09 -0700 Subject: [PATCH 55/74] CLOUDSTACK-3716:NPE triggered in DownloadListener. --- .../apache/cloudstack/storage/volume/VolumeServiceImpl.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java b/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java index 3b544b18023..5919c273bc2 100644 --- a/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java +++ b/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java @@ -1047,7 +1047,9 @@ public class VolumeServiceImpl implements VolumeService { VolumeVO volume = _volumeDao.findById(volumeStore.getVolumeId()); if (volume == null ){ s_logger.warn("Volume_store_ref shows that volume " + volumeStore.getVolumeId() + " is on image store " + storeId - + ", but the volume is not found in volumes table, potentially some bugs in deleteVolume, so we just treat this volume to be deleted"); + + ", but the volume is not found in volumes table, potentially some bugs in deleteVolume, so we just treat this volume to be deleted and mark it as destroyed"); + volumeStore.setDestroyed(true); + _volumeStoreDao.update(volumeStore.getId(), volumeStore); continue; } // Exists then don't download From 9f15779f106a63a8a08702ad3928cbdd90f6b552 Mon Sep 17 00:00:00 2001 From: Sheng Yang Date: Mon, 22 Jul 2013 18:37:26 -0700 Subject: [PATCH 56/74] CLOUDSTACK-3643: Automation: Fix VPC test cases Also add a timeout for network connection testings. Ideally this timeout should be around 30s or even less, but keep it at 60s for now for safe. --- .../component/test_vpc_network_lbrules.py | 17 +-- .../component/test_vpc_network_pfrules.py | 101 ++++++++++-------- .../test_vpc_network_staticnatrule.py | 20 ++-- 3 files changed, 82 insertions(+), 56 deletions(-) diff --git a/test/integration/component/test_vpc_network_lbrules.py b/test/integration/component/test_vpc_network_lbrules.py index ae452c4f0f9..d3c5ce1dee1 100644 --- a/test/integration/component/test_vpc_network_lbrules.py +++ b/test/integration/component/test_vpc_network_lbrules.py @@ -42,6 +42,7 @@ from marvin.integration.lib.common import (get_domain, get_template, cleanup_resources, list_routers) +import socket class Services: """Test VPC network services Load Balancing Rules Test data @@ -179,6 +180,9 @@ class TestVPCNetworkLBRules(cloudstackTestCase): @classmethod def setUpClass(cls): + # We want to fail quicker if it's failure + socket.setdefaulttimeout(60) + cls.api_client = super( TestVPCNetworkLBRules, cls @@ -294,6 +298,7 @@ class TestVPCNetworkLBRules(cloudstackTestCase): def start_VPC_VRouter(self, router): # Start the VPC Router + self.debug("Starting router ID: %s" % router.id) cmd = startRouter.startRouterCmd() cmd.id = router.id self.apiclient.startRouter(cmd) @@ -665,7 +670,7 @@ class TestVPCNetworkLBRules(cloudstackTestCase): self.debug('lb_rule_http=%s' % lb_rule_http.__dict__) self.check_wget_from_vm(vm_1, public_ip_1, testnegative=False) self.check_ssh_into_vm(vm_1, public_ip_1, testnegative=False) - lb_rule_nat.delete() + lb_rule_nat.delete(self.apiclient) self.check_ssh_into_vm(vm_1, public_ip_1, testnegative=True) return @@ -696,7 +701,7 @@ class TestVPCNetworkLBRules(cloudstackTestCase): self.debug('lb_rule_http=%s' % lb_rule_http.__dict__) self.check_wget_from_vm(vm_1, public_ip_1, testnegative=False) self.check_ssh_into_vm(vm_1, public_ip_1, testnegative=False) - lb_rule_nat.delete() + lb_rule_nat.delete(self.apiclient) self.check_ssh_into_vm(vm_1, public_ip_1, testnegative=True) return @@ -727,8 +732,8 @@ class TestVPCNetworkLBRules(cloudstackTestCase): self.debug('lb_rule_http=%s' % lb_rule_http.__dict__) self.check_wget_from_vm(vm_1, public_ip_1, testnegative=False) self.check_ssh_into_vm(vm_1, public_ip_1, testnegative=False) - lb_rule_nat.delete() - lb_rule_http.delete() + lb_rule_nat.delete(self.apiclient) + lb_rule_http.delete(self.apiclient) self.check_ssh_into_vm(vm_1, public_ip_1, testnegative=True) self.check_wget_from_vm(vm_1, public_ip_1, testnegative=True) return @@ -760,8 +765,8 @@ class TestVPCNetworkLBRules(cloudstackTestCase): self.debug('lb_rule_http=%s' % lb_rule_http.__dict__) self.check_wget_from_vm(vm_1, public_ip_1, testnegative=False) self.check_ssh_into_vm(vm_1, public_ip_1, testnegative=False) - lb_rule_nat.delete() - lb_rule_http.delete() + lb_rule_nat.delete(self.apiclient) + lb_rule_http.delete(self.apiclient) self.check_ssh_into_vm(vm_1, public_ip_1, testnegative=True) self.check_wget_from_vm(vm_1, public_ip_1, testnegative=True) return diff --git a/test/integration/component/test_vpc_network_pfrules.py b/test/integration/component/test_vpc_network_pfrules.py index 64a6aa23770..d9a045c4158 100644 --- a/test/integration/component/test_vpc_network_pfrules.py +++ b/test/integration/component/test_vpc_network_pfrules.py @@ -38,6 +38,7 @@ from marvin.integration.lib.common import (get_domain, get_template, cleanup_resources, list_routers) +import socket class Services: @@ -179,6 +180,9 @@ class TestVPCNetworkPFRules(cloudstackTestCase): @classmethod def setUpClass(cls): + # We want to fail quicker if it's failure + socket.setdefaulttimeout(60) + cls.api_client = super( TestVPCNetworkPFRules, cls @@ -294,6 +298,7 @@ class TestVPCNetworkPFRules(cloudstackTestCase): def start_vpcrouter(self, router): # Start the VPC Router + self.debug("Starting router ID: %s" % router.id) cmd = startRouter.startRouterCmd() cmd.id = router.id self.apiclient.startRouter(cmd) @@ -634,7 +639,7 @@ class TestVPCNetworkPFRules(cloudstackTestCase): self.check_ssh_into_vm(vm_1, public_ip_1, testnegative=False) self.check_wget_from_vm(vm_1, public_ip_1, testnegative=False) router = self.stop_vpcrouter() - http_rule.delete() + http_rule.delete(self.apiclient) self.start_vpcrouter(router) self.check_wget_from_vm(vm_1, public_ip_1, testnegative=True) return @@ -663,7 +668,7 @@ class TestVPCNetworkPFRules(cloudstackTestCase): #http_rule = self.create_egress_Internet_Rule(network_1) self.check_ssh_into_vm(vm_1, public_ip_1, testnegative=False) self.check_wget_from_vm(vm_1, public_ip_1, testnegative=False) - http_rule.delete() + http_rule.delete(self.apiclient) self.check_wget_from_vm(vm_1, public_ip_1, testnegative=True) return @@ -695,8 +700,8 @@ class TestVPCNetworkPFRules(cloudstackTestCase): self.check_ssh_into_vm(vm_1, public_ip_1, testnegative=False) self.check_wget_from_vm(vm_1, public_ip_1, testnegative=False) router = self.stop_vpcrouter() - http_rule.delete() - nat_rule.delete() + http_rule.delete(self.apiclient) + nat_rule.delete(self.apiclient) self.start_vpcrouter(router) self.check_ssh_into_vm(vm_1, public_ip_1, testnegative=True) self.check_wget_from_vm(vm_1, public_ip_1, testnegative=True) @@ -727,8 +732,8 @@ class TestVPCNetworkPFRules(cloudstackTestCase): #http_rule = self.create_egress_Internet_Rule(network_1) self.check_ssh_into_vm(vm_1, public_ip_1, testnegative=False) self.check_wget_from_vm(vm_1, public_ip_1, testnegative=False) - http_rule.delete() - nat_rule.delete() + http_rule.delete(self.apiclient) + nat_rule.delete(self.apiclient) self.check_ssh_into_vm(vm_1, public_ip_1, testnegative=True) self.check_wget_from_vm(vm_1, public_ip_1, testnegative=True) return @@ -764,34 +769,40 @@ class TestVPCNetworkPFRules(cloudstackTestCase): public_ip_2 = self.acquire_publicip(network_1) nat_rule1 = self.create_natrule(vm_1, public_ip_1, network_1) nat_rule2 = self.create_natrule(vm_2, public_ip_2, network_1) - http_rule1 = self.open_egress_to_world(network_1) - nat_rule3 = self.create_natrule(vm_3, public_ip_1, network_2) - nat_rule4 = self.create_natrule(vm_4, public_ip_2, network_2) - http_rule2 = self.open_egress_to_world(network_2) + http_rule1 = self.create_natrule(vm_1, public_ip_1, network_1, self.services["http_rule"]) + http_rule2 = self.create_natrule(vm_2, public_ip_2, network_1, self.services["http_rule"]) + public_ip_3 = self.acquire_publicip(network_2) + public_ip_4 = self.acquire_publicip(network_2) + nat_rule3 = self.create_natrule(vm_3, public_ip_3, network_2) + nat_rule4 = self.create_natrule(vm_4, public_ip_4, network_2) + http_rule3 = self.create_natrule(vm_3, public_ip_3, network_2, self.services["http_rule"]) + http_rule4 = self.create_natrule(vm_4, public_ip_4, network_2, self.services["http_rule"]) self.check_ssh_into_vm(vm_1, public_ip_1, testnegative=False) self.check_ssh_into_vm(vm_2, public_ip_2, testnegative=False) - self.check_ssh_into_vm(vm_3, public_ip_1, testnegative=False) - self.check_ssh_into_vm(vm_4, public_ip_2, testnegative=False) + self.check_ssh_into_vm(vm_3, public_ip_3, testnegative=False) + self.check_ssh_into_vm(vm_4, public_ip_4, testnegative=False) self.check_wget_from_vm(vm_1, public_ip_1, testnegative=False) self.check_wget_from_vm(vm_2, public_ip_2, testnegative=False) - self.check_wget_from_vm(vm_3, public_ip_1, testnegative=False) - self.check_wget_from_vm(vm_4, public_ip_2, testnegative=False) + self.check_wget_from_vm(vm_3, public_ip_3, testnegative=False) + self.check_wget_from_vm(vm_4, public_ip_4, testnegative=False) router = self.stop_vpcrouter() - nat_rule1.delete() - nat_rule2.delete() - nat_rule3.delete() - nat_rule4.delete() - http_rule1.delete() - http_rule2.delete() + nat_rule1.delete(self.apiclient) + nat_rule2.delete(self.apiclient) + nat_rule3.delete(self.apiclient) + nat_rule4.delete(self.apiclient) + http_rule1.delete(self.apiclient) + http_rule2.delete(self.apiclient) + http_rule3.delete(self.apiclient) + http_rule4.delete(self.apiclient) self.start_vpcrouter(router) self.check_ssh_into_vm(vm_1, public_ip_1, testnegative=True) self.check_ssh_into_vm(vm_2, public_ip_2, testnegative=True) - self.check_ssh_into_vm(vm_3, public_ip_1, testnegative=True) - self.check_ssh_into_vm(vm_4, public_ip_2, testnegative=True) + self.check_ssh_into_vm(vm_3, public_ip_3, testnegative=True) + self.check_ssh_into_vm(vm_4, public_ip_4, testnegative=True) self.check_wget_from_vm(vm_1, public_ip_1, testnegative=True) self.check_wget_from_vm(vm_2, public_ip_2, testnegative=True) - self.check_wget_from_vm(vm_3, public_ip_1, testnegative=True) - self.check_wget_from_vm(vm_4, public_ip_2, testnegative=True) + self.check_wget_from_vm(vm_3, public_ip_3, testnegative=True) + self.check_wget_from_vm(vm_4, public_ip_4, testnegative=True) return @attr(tags=["advanced", "intervlan"]) @@ -822,30 +833,36 @@ class TestVPCNetworkPFRules(cloudstackTestCase): public_ip_2 = self.acquire_publicip(network_1) nat_rule1 = self.create_natrule(vm_1, public_ip_1, network_1) nat_rule2 = self.create_natrule(vm_2, public_ip_2, network_1) - http_rule1 = self.open_egress_to_world(network_1) - nat_rule3 = self.create_natrule(vm_3, public_ip_1, network_2) - nat_rule4 = self.create_natrule(vm_4, public_ip_2, network_2) - http_rule2 = self.open_egress_to_world(network_2) + http_rule1 = self.create_natrule(vm_1, public_ip_1, network_1, self.services["http_rule"]) + http_rule2 = self.create_natrule(vm_2, public_ip_2, network_1, self.services["http_rule"]) + public_ip_3 = self.acquire_publicip(network_2) + public_ip_4 = self.acquire_publicip(network_2) + nat_rule3 = self.create_natrule(vm_3, public_ip_3, network_2) + nat_rule4 = self.create_natrule(vm_4, public_ip_4, network_2) + http_rule3 = self.create_natrule(vm_3, public_ip_3, network_2, self.services["http_rule"]) + http_rule4 = self.create_natrule(vm_4, public_ip_4, network_2, self.services["http_rule"]) self.check_ssh_into_vm(vm_1, public_ip_1, testnegative=False) self.check_ssh_into_vm(vm_2, public_ip_2, testnegative=False) - self.check_ssh_into_vm(vm_3, public_ip_1, testnegative=False) - self.check_ssh_into_vm(vm_4, public_ip_2, testnegative=False) + self.check_ssh_into_vm(vm_3, public_ip_3, testnegative=False) + self.check_ssh_into_vm(vm_4, public_ip_4, testnegative=False) self.check_wget_from_vm(vm_1, public_ip_1, testnegative=False) self.check_wget_from_vm(vm_2, public_ip_2, testnegative=False) - self.check_wget_from_vm(vm_3, public_ip_1, testnegative=False) - self.check_wget_from_vm(vm_4, public_ip_2, testnegative=False) - nat_rule1.delete() - nat_rule2.delete() - nat_rule3.delete() - nat_rule4.delete() - http_rule1.delete() - http_rule2.delete() + self.check_wget_from_vm(vm_3, public_ip_3, testnegative=False) + self.check_wget_from_vm(vm_4, public_ip_4, testnegative=False) + nat_rule1.delete(self.apiclient) + nat_rule2.delete(self.apiclient) + nat_rule3.delete(self.apiclient) + nat_rule4.delete(self.apiclient) + http_rule1.delete(self.apiclient) + http_rule2.delete(self.apiclient) + http_rule3.delete(self.apiclient) + http_rule4.delete(self.apiclient) self.check_ssh_into_vm(vm_1, public_ip_1, testnegative=True) self.check_ssh_into_vm(vm_2, public_ip_2, testnegative=True) - self.check_ssh_into_vm(vm_3, public_ip_1, testnegative=True) - self.check_ssh_into_vm(vm_4, public_ip_2, testnegative=True) + self.check_ssh_into_vm(vm_3, public_ip_3, testnegative=True) + self.check_ssh_into_vm(vm_4, public_ip_4, testnegative=True) self.check_wget_from_vm(vm_1, public_ip_1, testnegative=True) self.check_wget_from_vm(vm_2, public_ip_2, testnegative=True) - self.check_wget_from_vm(vm_3, public_ip_1, testnegative=True) - self.check_wget_from_vm(vm_4, public_ip_2, testnegative=True) + self.check_wget_from_vm(vm_3, public_ip_3, testnegative=True) + self.check_wget_from_vm(vm_4, public_ip_4, testnegative=True) return diff --git a/test/integration/component/test_vpc_network_staticnatrule.py b/test/integration/component/test_vpc_network_staticnatrule.py index 80e8477289c..0d23d0325bc 100644 --- a/test/integration/component/test_vpc_network_staticnatrule.py +++ b/test/integration/component/test_vpc_network_staticnatrule.py @@ -38,6 +38,7 @@ from marvin.integration.lib.common import (get_domain, get_template, cleanup_resources, list_routers) +import socket class Services: @@ -178,6 +179,9 @@ class TestVPCNetworkPFRules(cloudstackTestCase): @classmethod def setUpClass(cls): + # We want to fail quicker if it's failure + socket.setdefaulttimeout(60) + cls.api_client = super( TestVPCNetworkPFRules, cls @@ -634,8 +638,8 @@ class TestVPCNetworkPFRules(cloudstackTestCase): http_rule = self.create_NatRule_For_VM(vm_1, public_ip_1, network_1, self.services["http_rule"]) self.check_ssh_into_vm(vm_1, public_ip_1, testnegative=False) self.check_wget_from_vm(vm_1, public_ip_1, testnegative=False) - http_rule.delete() - nat_rule.delete() + http_rule.delete(self.apiclient) + nat_rule.delete(self.apiclient) self.check_ssh_into_vm(vm_1, public_ip_1, testnegative=True) self.check_wget_from_vm(vm_1, public_ip_1, testnegative=True) return @@ -682,12 +686,12 @@ class TestVPCNetworkPFRules(cloudstackTestCase): self.check_wget_from_vm(vm_2, public_ip_2, testnegative=False) self.check_wget_from_vm(vm_3, public_ip_1, testnegative=False) self.check_wget_from_vm(vm_4, public_ip_2, testnegative=False) - nat_rule1.delete() - nat_rule2.delete() - nat_rule3.delete() - nat_rule4.delete() - http_rule1.delete() - http_rule2.delete() + nat_rule1.delete(self.apiclient) + nat_rule2.delete(self.apiclient) + nat_rule3.delete(self.apiclient) + nat_rule4.delete(self.apiclient) + http_rule1.delete(self.apiclient) + http_rule2.delete(self.apiclient) self.check_ssh_into_vm(vm_1, public_ip_1, testnegative=True) self.check_ssh_into_vm(vm_2, public_ip_2, testnegative=True) self.check_ssh_into_vm(vm_3, public_ip_1, testnegative=True) From 319d91e1c2c22b27adaed0eb65c7b95e3bbb0503 Mon Sep 17 00:00:00 2001 From: Alex Huang Date: Mon, 22 Jul 2013 17:25:48 -0700 Subject: [PATCH 57/74] Removed the getByTypeAndId() method and replace it with getById method --- .../src/com/cloud/ha/FenceBuilder.java | 6 +- .../src/com/cloud/ha/Investigator.java | 8 +-- api/src/com/cloud/vm/VirtualMachine.java | 71 ++++++++++--------- .../com/cloud/ovm/hypervisor/OvmFencer.java | 7 +- .../vmware/src/com/cloud/ha/VmwareFencer.java | 11 ++- .../src/com/cloud/ha/VmwareInvestigator.java | 10 +-- .../xen/src/com/cloud/ha/XenServerFencer.java | 7 +- .../cloud/ha/CheckOnAgentInvestigator.java | 8 +-- .../cloud/ha/HighAvailabilityManagerImpl.java | 10 +-- server/src/com/cloud/ha/KVMFencer.java | 6 +- .../ha/ManagementIPSystemVMInvestigator.java | 12 ++-- .../src/com/cloud/ha/RecreatableFencer.java | 8 +-- .../com/cloud/ha/UserVmDomRInvestigator.java | 9 ++- .../com/cloud/ha/XenServerInvestigator.java | 9 +-- .../cloud/servlet/ConsoleProxyServlet.java | 28 ++++---- .../src/com/cloud/vm/UserVmManagerImpl.java | 16 ++--- .../com/cloud/vm/VirtualMachineManager.java | 4 +- .../cloud/vm/VirtualMachineManagerImpl.java | 5 -- 18 files changed, 115 insertions(+), 120 deletions(-) rename {server => api}/src/com/cloud/ha/FenceBuilder.java (89%) rename {server => api}/src/com/cloud/ha/Investigator.java (85%) diff --git a/server/src/com/cloud/ha/FenceBuilder.java b/api/src/com/cloud/ha/FenceBuilder.java similarity index 89% rename from server/src/com/cloud/ha/FenceBuilder.java rename to api/src/com/cloud/ha/FenceBuilder.java index 6f7413eeddc..41bde71b99d 100644 --- a/server/src/com/cloud/ha/FenceBuilder.java +++ b/api/src/com/cloud/ha/FenceBuilder.java @@ -16,9 +16,9 @@ // under the License. package com.cloud.ha; -import com.cloud.host.HostVO; +import com.cloud.host.Host; import com.cloud.utils.component.Adapter; -import com.cloud.vm.VMInstanceVO; +import com.cloud.vm.VirtualMachine; public interface FenceBuilder extends Adapter { /** @@ -27,5 +27,5 @@ public interface FenceBuilder extends Adapter { * @param vm vm * @param host host where the vm was running on. */ - public Boolean fenceOff(VMInstanceVO vm, HostVO host); + public Boolean fenceOff(VirtualMachine vm, Host host); } diff --git a/server/src/com/cloud/ha/Investigator.java b/api/src/com/cloud/ha/Investigator.java similarity index 85% rename from server/src/com/cloud/ha/Investigator.java rename to api/src/com/cloud/ha/Investigator.java index a414156d389..a5de1ba5e1b 100644 --- a/server/src/com/cloud/ha/Investigator.java +++ b/api/src/com/cloud/ha/Investigator.java @@ -16,10 +16,10 @@ // under the License. package com.cloud.ha; -import com.cloud.host.HostVO; +import com.cloud.host.Host; import com.cloud.host.Status; import com.cloud.utils.component.Adapter; -import com.cloud.vm.VMInstanceVO; +import com.cloud.vm.VirtualMachine; public interface Investigator extends Adapter { /** @@ -27,7 +27,7 @@ public interface Investigator extends Adapter { * * @param vm to work on. */ - public Boolean isVmAlive(VMInstanceVO vm, HostVO host); + public Boolean isVmAlive(VirtualMachine vm, Host host); - public Status isAgentAlive(HostVO agent); + public Status isAgentAlive(Host agent); } diff --git a/api/src/com/cloud/vm/VirtualMachine.java b/api/src/com/cloud/vm/VirtualMachine.java index c172fbff422..0a968bc415f 100755 --- a/api/src/com/cloud/vm/VirtualMachine.java +++ b/api/src/com/cloud/vm/VirtualMachine.java @@ -158,7 +158,7 @@ public interface VirtualMachine extends RunningOn, ControlledEntity, Identity, I } } - public static final String IsDynamicScalingEnabled = "enable.dynamic.scaling"; + static final String IsDynamicScalingEnabled = "enable.dynamic.scaling"; public enum Event { CreateRequested, @@ -182,27 +182,28 @@ public interface VirtualMachine extends RunningOn, ControlledEntity, Identity, I }; public enum Type { - User, - DomainRouter, - ConsoleProxy, - SecondaryStorageVm, - ElasticIpVm, - ElasticLoadBalancerVm, - InternalLoadBalancerVm, + User(false), + DomainRouter(true), + ConsoleProxy(true), + SecondaryStorageVm(true), + ElasticIpVm(true), + ElasticLoadBalancerVm(true), + InternalLoadBalancerVm(true), /* * UserBareMetal is only used for selecting VirtualMachineGuru, there is no * VM with this type. UserBareMetal should treat exactly as User. */ - UserBareMetal; + UserBareMetal(false); - public static boolean isSystemVM(VirtualMachine.Type vmtype) { - if (DomainRouter.equals(vmtype) - || ConsoleProxy.equals(vmtype) - || SecondaryStorageVm.equals(vmtype) || InternalLoadBalancerVm.equals(vmtype)) { - return true; - } - return false; + boolean _isUsedBySystem; + + private Type(boolean isUsedBySystem) { + _isUsedBySystem = isUsedBySystem; + } + + public boolean isUsedBySystem() { + return _isUsedBySystem; } } @@ -211,39 +212,39 @@ public interface VirtualMachine extends RunningOn, ControlledEntity, Identity, I * reference this VM. You can build names that starts with this name and it * guarantees uniqueness for things related to the VM. */ - public String getInstanceName(); + String getInstanceName(); /** * @return the host name of the virtual machine. If the user did not * specify the host name when creating the virtual machine then it is * defaults to the instance name. */ - public String getHostName(); + String getHostName(); /** * @return the ip address of the virtual machine. */ - public String getPrivateIpAddress(); + String getPrivateIpAddress(); /** * @return mac address. */ - public String getPrivateMacAddress(); + String getPrivateMacAddress(); /** * @return password of the host for vnc purposes. */ - public String getVncPassword(); + String getVncPassword(); /** * @return the state of the virtual machine */ - // public State getState(); + // State getState(); /** * @return template id. */ - public long getTemplateId(); + long getTemplateId(); @@ -252,49 +253,51 @@ public interface VirtualMachine extends RunningOn, ControlledEntity, Identity, I * * @return guestOSId */ - public long getGuestOSId(); + long getGuestOSId(); /** * @return pod id. */ - public Long getPodIdToDeployIn(); + Long getPodIdToDeployIn(); /** * @return data center id. */ - public long getDataCenterId(); + long getDataCenterId(); /** * @return id of the host it was assigned last time. */ - public Long getLastHostId(); + Long getLastHostId(); @Override - public Long getHostId(); + Long getHostId(); /** * @return should HA be enabled for this machine? */ - public boolean isHaEnabled(); + boolean isHaEnabled(); /** * @return should limit CPU usage to the service offering? */ - public boolean limitCpuUse(); + boolean limitCpuUse(); /** * @return date when machine was created */ - public Date getCreated(); + Date getCreated(); - public long getServiceOfferingId(); + long getServiceOfferingId(); - public Long getDiskOfferingId(); + Long getDiskOfferingId(); Type getType(); HypervisorType getHypervisorType(); - public Map getDetails(); + Map getDetails(); + + long getUpdated(); } diff --git a/plugins/hypervisors/ovm/src/com/cloud/ovm/hypervisor/OvmFencer.java b/plugins/hypervisors/ovm/src/com/cloud/ovm/hypervisor/OvmFencer.java index 7aefcaa6f12..71d9d0b9ec7 100755 --- a/plugins/hypervisors/ovm/src/com/cloud/ovm/hypervisor/OvmFencer.java +++ b/plugins/hypervisors/ovm/src/com/cloud/ovm/hypervisor/OvmFencer.java @@ -31,12 +31,13 @@ import com.cloud.agent.api.FenceCommand; import com.cloud.exception.AgentUnavailableException; import com.cloud.exception.OperationTimedoutException; import com.cloud.ha.FenceBuilder; +import com.cloud.host.Host; import com.cloud.host.HostVO; import com.cloud.host.Status; import com.cloud.hypervisor.Hypervisor.HypervisorType; -import com.cloud.utils.component.AdapterBase; -import com.cloud.vm.VMInstanceVO; import com.cloud.resource.ResourceManager; +import com.cloud.utils.component.AdapterBase; +import com.cloud.vm.VirtualMachine; @Local(value=FenceBuilder.class) public class OvmFencer extends AdapterBase implements FenceBuilder { @@ -66,7 +67,7 @@ public class OvmFencer extends AdapterBase implements FenceBuilder { } @Override - public Boolean fenceOff(VMInstanceVO vm, HostVO host) { + public Boolean fenceOff(VirtualMachine vm, Host host) { if (host.getHypervisorType() != HypervisorType.Ovm) { s_logger.debug("Don't know how to fence non Ovm hosts " + host.getHypervisorType()); return null; diff --git a/plugins/hypervisors/vmware/src/com/cloud/ha/VmwareFencer.java b/plugins/hypervisors/vmware/src/com/cloud/ha/VmwareFencer.java index 2ed5cafb8e4..dab5064b2d4 100644 --- a/plugins/hypervisors/vmware/src/com/cloud/ha/VmwareFencer.java +++ b/plugins/hypervisors/vmware/src/com/cloud/ha/VmwareFencer.java @@ -11,25 +11,22 @@ // 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 +// KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. package com.cloud.ha; -import java.util.Map; - import javax.ejb.Local; -import javax.naming.ConfigurationException; -import com.cloud.host.HostVO; +import com.cloud.host.Host; import com.cloud.utils.component.AdapterBase; -import com.cloud.vm.VMInstanceVO; +import com.cloud.vm.VirtualMachine; @Local(value=FenceBuilder.class) public class VmwareFencer extends AdapterBase implements FenceBuilder { @Override - public Boolean fenceOff(VMInstanceVO vm, HostVO host) { + public Boolean fenceOff(VirtualMachine vm, Host host) { return null; } diff --git a/plugins/hypervisors/vmware/src/com/cloud/ha/VmwareInvestigator.java b/plugins/hypervisors/vmware/src/com/cloud/ha/VmwareInvestigator.java index a7e67e1bbe1..e5ef5b799cc 100644 --- a/plugins/hypervisors/vmware/src/com/cloud/ha/VmwareInvestigator.java +++ b/plugins/hypervisors/vmware/src/com/cloud/ha/VmwareInvestigator.java @@ -11,18 +11,18 @@ // 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 +// KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. package com.cloud.ha; import javax.ejb.Local; -import com.cloud.host.HostVO; +import com.cloud.host.Host; import com.cloud.host.Status; import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.utils.component.AdapterBase; -import com.cloud.vm.VMInstanceVO; +import com.cloud.vm.VirtualMachine; @Local(value=Investigator.class) public class VmwareInvestigator extends AdapterBase implements Investigator { @@ -30,7 +30,7 @@ public class VmwareInvestigator extends AdapterBase implements Investigator { } @Override - public Status isAgentAlive(HostVO agent) { + public Status isAgentAlive(Host agent) { if(agent.getHypervisorType() == HypervisorType.VMware) return Status.Disconnected; @@ -38,7 +38,7 @@ public class VmwareInvestigator extends AdapterBase implements Investigator { } @Override - public Boolean isVmAlive(VMInstanceVO vm, HostVO host) { + public Boolean isVmAlive(VirtualMachine vm, Host host) { if(vm.getHypervisorType() == HypervisorType.VMware) return true; diff --git a/plugins/hypervisors/xen/src/com/cloud/ha/XenServerFencer.java b/plugins/hypervisors/xen/src/com/cloud/ha/XenServerFencer.java index 737b3b2890b..4708ff3e5bc 100755 --- a/plugins/hypervisors/xen/src/com/cloud/ha/XenServerFencer.java +++ b/plugins/hypervisors/xen/src/com/cloud/ha/XenServerFencer.java @@ -11,7 +11,7 @@ // 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 +// KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. package com.cloud.ha; @@ -31,13 +31,14 @@ import com.cloud.agent.api.FenceAnswer; import com.cloud.agent.api.FenceCommand; import com.cloud.exception.AgentUnavailableException; import com.cloud.exception.OperationTimedoutException; +import com.cloud.host.Host; import com.cloud.host.HostVO; import com.cloud.host.Status; import com.cloud.host.dao.HostDao; import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.resource.ResourceManager; import com.cloud.utils.component.AdapterBase; -import com.cloud.vm.VMInstanceVO; +import com.cloud.vm.VirtualMachine; @Local(value=FenceBuilder.class) public class XenServerFencer extends AdapterBase implements FenceBuilder { @@ -49,7 +50,7 @@ public class XenServerFencer extends AdapterBase implements FenceBuilder { @Inject ResourceManager _resourceMgr; @Override - public Boolean fenceOff(VMInstanceVO vm, HostVO host) { + public Boolean fenceOff(VirtualMachine vm, Host host) { if (host.getHypervisorType() != HypervisorType.XenServer) { s_logger.debug("Don't know how to fence non XenServer hosts " + host.getHypervisorType()); return null; diff --git a/server/src/com/cloud/ha/CheckOnAgentInvestigator.java b/server/src/com/cloud/ha/CheckOnAgentInvestigator.java index 29719105a15..0df324c8bc7 100644 --- a/server/src/com/cloud/ha/CheckOnAgentInvestigator.java +++ b/server/src/com/cloud/ha/CheckOnAgentInvestigator.java @@ -26,10 +26,10 @@ import com.cloud.agent.api.CheckVirtualMachineAnswer; import com.cloud.agent.api.CheckVirtualMachineCommand; import com.cloud.exception.AgentUnavailableException; import com.cloud.exception.OperationTimedoutException; -import com.cloud.host.HostVO; +import com.cloud.host.Host; import com.cloud.host.Status; import com.cloud.utils.component.AdapterBase; -import com.cloud.vm.VMInstanceVO; +import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachine.State; @Local(value=Investigator.class) @@ -42,12 +42,12 @@ public class CheckOnAgentInvestigator extends AdapterBase implements Investigato } @Override - public Status isAgentAlive(HostVO agent) { + public Status isAgentAlive(Host agent) { return null; } @Override - public Boolean isVmAlive(VMInstanceVO vm, HostVO host) { + public Boolean isVmAlive(VirtualMachine vm, Host host) { CheckVirtualMachineCommand cmd = new CheckVirtualMachineCommand(vm.getInstanceName()); try { CheckVirtualMachineAnswer answer = (CheckVirtualMachineAnswer)_agentMgr.send(vm.getHostId(), cmd); diff --git a/server/src/com/cloud/ha/HighAvailabilityManagerImpl.java b/server/src/com/cloud/ha/HighAvailabilityManagerImpl.java index fcc4792aac1..896c4189edf 100755 --- a/server/src/com/cloud/ha/HighAvailabilityManagerImpl.java +++ b/server/src/com/cloud/ha/HighAvailabilityManagerImpl.java @@ -388,7 +388,7 @@ public class HighAvailabilityManagerImpl extends ManagerBase implements HighAvai long vmId = work.getInstanceId(); - VMInstanceVO vm = _itMgr.findByIdAndType(work.getType(), work.getInstanceId()); + VirtualMachine vm = _itMgr.findById(work.getInstanceId()); if (vm == null) { s_logger.info("Unable to find vm: " + vmId); return null; @@ -506,7 +506,7 @@ public class HighAvailabilityManagerImpl extends ManagerBase implements HighAvai } } - vm = _itMgr.findByIdAndType(vm.getType(), vm.getId()); + vm = _itMgr.findById(vm.getId()); if (!_forceHA && !vm.isHaEnabled()) { if (s_logger.isDebugEnabled()) { @@ -560,7 +560,7 @@ public class HighAvailabilityManagerImpl extends ManagerBase implements HighAvai _alertMgr.sendAlert(alertType, vm.getDataCenterId(), vm.getPodIdToDeployIn(), "Unable to restart " + vm.getHostName() + " which was running on host " + hostDesc, "The Storage is unavailable for trying to restart VM, name: " + vm.getHostName() + ", id: " + vmId + " which was running on host " + hostDesc); } - vm = _itMgr.findByIdAndType(vm.getType(), vm.getId()); + vm = _itMgr.findById(vm.getId()); work.setUpdateTime(vm.getUpdated()); work.setPreviousState(vm.getState()); return (System.currentTimeMillis() >> 10) + _restartRetryInterval; @@ -606,7 +606,7 @@ public class HighAvailabilityManagerImpl extends ManagerBase implements HighAvai } protected Long destroyVM(HaWorkVO work) { - final VMInstanceVO vm = _itMgr.findByIdAndType(work.getType(), work.getInstanceId()); + final VirtualMachine vm = _itMgr.findById(work.getInstanceId()); s_logger.info("Destroying " + vm.toString()); try { if (vm.getState() != State.Destroyed) { @@ -639,7 +639,7 @@ public class HighAvailabilityManagerImpl extends ManagerBase implements HighAvai } protected Long stopVM(final HaWorkVO work) throws ConcurrentOperationException { - VMInstanceVO vm = _itMgr.findByIdAndType(work.getType(), work.getInstanceId()); + VirtualMachine vm = _itMgr.findById(work.getInstanceId()); if (vm == null) { s_logger.info("No longer can find VM " + work.getInstanceId() + ". Throwing away " + work); work.setStep(Step.Done); diff --git a/server/src/com/cloud/ha/KVMFencer.java b/server/src/com/cloud/ha/KVMFencer.java index 9fcacd72321..517209e8dad 100755 --- a/server/src/com/cloud/ha/KVMFencer.java +++ b/server/src/com/cloud/ha/KVMFencer.java @@ -17,7 +17,6 @@ package com.cloud.ha; import java.util.List; - import java.util.Map; import javax.ejb.Local; @@ -31,13 +30,14 @@ import com.cloud.agent.api.FenceAnswer; import com.cloud.agent.api.FenceCommand; import com.cloud.exception.AgentUnavailableException; import com.cloud.exception.OperationTimedoutException; +import com.cloud.host.Host; import com.cloud.host.HostVO; import com.cloud.host.Status; import com.cloud.host.dao.HostDao; import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.resource.ResourceManager; import com.cloud.utils.component.AdapterBase; -import com.cloud.vm.VMInstanceVO; +import com.cloud.vm.VirtualMachine; @Local(value=FenceBuilder.class) public class KVMFencer extends AdapterBase implements FenceBuilder { @@ -70,7 +70,7 @@ public class KVMFencer extends AdapterBase implements FenceBuilder { } @Override - public Boolean fenceOff(VMInstanceVO vm, HostVO host) { + public Boolean fenceOff(VirtualMachine vm, Host host) { if (host.getHypervisorType() != HypervisorType.KVM) { s_logger.debug("Don't know how to fence non kvm hosts " + host.getHypervisorType()); return null; diff --git a/server/src/com/cloud/ha/ManagementIPSystemVMInvestigator.java b/server/src/com/cloud/ha/ManagementIPSystemVMInvestigator.java index 17f0355ed96..2b6d261261c 100644 --- a/server/src/com/cloud/ha/ManagementIPSystemVMInvestigator.java +++ b/server/src/com/cloud/ha/ManagementIPSystemVMInvestigator.java @@ -25,13 +25,13 @@ import javax.naming.ConfigurationException; import org.apache.log4j.Logger; +import com.cloud.host.Host; import com.cloud.host.HostVO; import com.cloud.host.Status; import com.cloud.host.dao.HostDao; import com.cloud.network.NetworkModel; import com.cloud.network.Networks.TrafficType; import com.cloud.vm.Nic; -import com.cloud.vm.VMInstanceVO; import com.cloud.vm.VirtualMachine; @Local(value={Investigator.class}) @@ -39,13 +39,13 @@ public class ManagementIPSystemVMInvestigator extends AbstractInvestigatorImpl { private static final Logger s_logger = Logger.getLogger(ManagementIPSystemVMInvestigator.class); private String _name = null; - @Inject private HostDao _hostDao = null; - @Inject private NetworkModel _networkMgr = null; + @Inject private final HostDao _hostDao = null; + @Inject private final NetworkModel _networkMgr = null; @Override - public Boolean isVmAlive(VMInstanceVO vm, HostVO host) { - if (!VirtualMachine.Type.isSystemVM(vm.getType())) { + public Boolean isVmAlive(VirtualMachine vm, Host host) { + if (!vm.getType().isUsedBySystem()) { s_logger.debug("Not a System Vm, unable to determine state of " + vm + " returning null"); } @@ -110,7 +110,7 @@ public class ManagementIPSystemVMInvestigator extends AbstractInvestigatorImpl { } @Override - public Status isAgentAlive(HostVO agent) { + public Status isAgentAlive(Host agent) { return null; } diff --git a/server/src/com/cloud/ha/RecreatableFencer.java b/server/src/com/cloud/ha/RecreatableFencer.java index 50aa1b75762..398bb037cd5 100644 --- a/server/src/com/cloud/ha/RecreatableFencer.java +++ b/server/src/com/cloud/ha/RecreatableFencer.java @@ -21,15 +21,15 @@ import java.util.List; import javax.ejb.Local; import javax.inject.Inject; -import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; import org.apache.log4j.Logger; import org.springframework.stereotype.Component; -import com.cloud.host.HostVO; +import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; + +import com.cloud.host.Host; import com.cloud.storage.VolumeVO; import com.cloud.storage.dao.VolumeDao; import com.cloud.utils.component.AdapterBase; -import com.cloud.vm.VMInstanceVO; import com.cloud.vm.VirtualMachine; @Component @@ -44,7 +44,7 @@ public class RecreatableFencer extends AdapterBase implements FenceBuilder { } @Override - public Boolean fenceOff(VMInstanceVO vm, HostVO host) { + public Boolean fenceOff(VirtualMachine vm, Host host) { VirtualMachine.Type type = vm.getType(); if (type != VirtualMachine.Type.ConsoleProxy && type != VirtualMachine.Type.DomainRouter && type != VirtualMachine.Type.SecondaryStorageVm) { if (s_logger.isDebugEnabled()) { diff --git a/server/src/com/cloud/ha/UserVmDomRInvestigator.java b/server/src/com/cloud/ha/UserVmDomRInvestigator.java index 8b48c09dfa1..195deff5ab0 100644 --- a/server/src/com/cloud/ha/UserVmDomRInvestigator.java +++ b/server/src/com/cloud/ha/UserVmDomRInvestigator.java @@ -29,7 +29,7 @@ import org.apache.log4j.Logger; import com.cloud.agent.AgentManager; import com.cloud.agent.api.Answer; import com.cloud.agent.api.PingTestCommand; -import com.cloud.host.HostVO; +import com.cloud.host.Host; import com.cloud.host.Status; import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.network.NetworkModel; @@ -38,7 +38,6 @@ import com.cloud.network.router.VirtualRouter; import com.cloud.network.router.VpcVirtualNetworkApplianceManager; import com.cloud.vm.Nic; import com.cloud.vm.UserVmVO; -import com.cloud.vm.VMInstanceVO; import com.cloud.vm.VirtualMachine; import com.cloud.vm.dao.UserVmDao; @@ -53,7 +52,7 @@ public class UserVmDomRInvestigator extends AbstractInvestigatorImpl { @Inject private final VpcVirtualNetworkApplianceManager _vnaMgr = null; @Override - public Boolean isVmAlive(VMInstanceVO vm, HostVO host) { + public Boolean isVmAlive(VirtualMachine vm, Host host) { if (vm.getType() != VirtualMachine.Type.User) { if (s_logger.isDebugEnabled()) { s_logger.debug("Not a User Vm, unable to determine state of " + vm + " returning null"); @@ -104,7 +103,7 @@ public class UserVmDomRInvestigator extends AbstractInvestigatorImpl { } @Override - public Status isAgentAlive(HostVO agent) { + public Status isAgentAlive(Host agent) { if (s_logger.isDebugEnabled()) { s_logger.debug("checking if agent (" + agent.getId() + ") is alive"); } @@ -166,7 +165,7 @@ public class UserVmDomRInvestigator extends AbstractInvestigatorImpl { return true; } - private Boolean testUserVM(VMInstanceVO vm, Nic nic, VirtualRouter router) { + private Boolean testUserVM(VirtualMachine vm, Nic nic, VirtualRouter router) { String privateIp = nic.getIp4Address(); String routerPrivateIp = router.getPrivateIpAddress(); diff --git a/server/src/com/cloud/ha/XenServerInvestigator.java b/server/src/com/cloud/ha/XenServerInvestigator.java index 6cbd22ff2da..2b96007b91b 100755 --- a/server/src/com/cloud/ha/XenServerInvestigator.java +++ b/server/src/com/cloud/ha/XenServerInvestigator.java @@ -23,17 +23,18 @@ import javax.inject.Inject; import org.apache.log4j.Logger; +import com.cloud.agent.AgentManager; import com.cloud.agent.api.Answer; import com.cloud.agent.api.CheckOnHostAnswer; import com.cloud.agent.api.CheckOnHostCommand; -import com.cloud.agent.AgentManager; +import com.cloud.host.Host; import com.cloud.host.HostVO; import com.cloud.host.Status; import com.cloud.host.dao.HostDao; import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.resource.ResourceManager; import com.cloud.utils.component.AdapterBase; -import com.cloud.vm.VMInstanceVO; +import com.cloud.vm.VirtualMachine; @Local(value=Investigator.class) public class XenServerInvestigator extends AdapterBase implements Investigator { @@ -46,7 +47,7 @@ public class XenServerInvestigator extends AdapterBase implements Investigator { } @Override - public Status isAgentAlive(HostVO agent) { + public Status isAgentAlive(Host agent) { if (agent.getHypervisorType() != HypervisorType.XenServer) { return null; } @@ -72,7 +73,7 @@ public class XenServerInvestigator extends AdapterBase implements Investigator { } @Override - public Boolean isVmAlive(VMInstanceVO vm, HostVO host) { + public Boolean isVmAlive(VirtualMachine vm, Host host) { Status status = isAgentAlive(host); if (status == null) { return null; diff --git a/server/src/com/cloud/servlet/ConsoleProxyServlet.java b/server/src/com/cloud/servlet/ConsoleProxyServlet.java index 097986bda62..fe2052e7908 100644 --- a/server/src/com/cloud/servlet/ConsoleProxyServlet.java +++ b/server/src/com/cloud/servlet/ConsoleProxyServlet.java @@ -35,12 +35,16 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; -import org.apache.cloudstack.api.IdentityService; import org.apache.commons.codec.binary.Base64; import org.apache.log4j.Logger; import org.springframework.stereotype.Component; import org.springframework.web.context.support.SpringBeanAutowiringSupport; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + +import org.apache.cloudstack.api.IdentityService; + import com.cloud.exception.PermissionDeniedException; import com.cloud.host.HostVO; import com.cloud.server.ManagementServer; @@ -51,12 +55,10 @@ import com.cloud.user.User; import com.cloud.uservm.UserVm; import com.cloud.utils.Pair; import com.cloud.utils.Ternary; +import com.cloud.utils.db.EntityManager; import com.cloud.utils.db.Transaction; -import com.cloud.vm.VMInstanceVO; import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachineManager; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; /** * Thumbnail access : /console?cmd=thumbnail&vm=xxx&w=xxx&h=xxx @@ -74,10 +76,12 @@ public class ConsoleProxyServlet extends HttpServlet { @Inject VirtualMachineManager _vmMgr; @Inject ManagementServer _ms; @Inject IdentityService _identityService; + @Inject + EntityManager _entityMgr; static ManagementServer s_ms; - private Gson _gson = new GsonBuilder().create(); + private final Gson _gson = new GsonBuilder().create(); public ConsoleProxyServlet() { } @@ -179,7 +183,7 @@ public class ConsoleProxyServlet extends HttpServlet { } private void handleThumbnailRequest(HttpServletRequest req, HttpServletResponse resp, long vmId) { - VMInstanceVO vm = _vmMgr.findById(vmId); + VirtualMachine vm = _vmMgr.findById(vmId); if(vm == null) { s_logger.warn("VM " + vmId + " does not exist, sending blank response for thumbnail request"); sendResponse(resp, ""); @@ -230,7 +234,7 @@ public class ConsoleProxyServlet extends HttpServlet { } private void handleAccessRequest(HttpServletRequest req, HttpServletResponse resp, long vmId) { - VMInstanceVO vm = _vmMgr.findById(vmId); + VirtualMachine vm = _vmMgr.findById(vmId); if(vm == null) { s_logger.warn("VM " + vmId + " does not exist, sending blank response for console access request"); sendResponse(resp, ""); @@ -258,7 +262,7 @@ public class ConsoleProxyServlet extends HttpServlet { String vmName = vm.getHostName(); if(vm.getType() == VirtualMachine.Type.User) { - UserVm userVm = (UserVm)_vmMgr.findByIdAndType(VirtualMachine.Type.User, vmId); + UserVm userVm = _entityMgr.findById(UserVm.class, vmId); String displayName = userVm.getDisplayName(); if(displayName != null && !displayName.isEmpty() && !displayName.equals(vmName)) { vmName += "(" + displayName + ")"; @@ -276,7 +280,7 @@ public class ConsoleProxyServlet extends HttpServlet { // TODO authentication channel between console proxy VM and management server needs to be secured, // the data is now being sent through private network, but this is apparently not enough - VMInstanceVO vm = _vmMgr.findById(vmId); + VirtualMachine vm = _vmMgr.findById(vmId); if(vm == null) { s_logger.warn("VM " + vmId + " does not exist, sending failed response for authentication request from console proxy"); sendResponse(resp, "failed"); @@ -339,7 +343,7 @@ public class ConsoleProxyServlet extends HttpServlet { return _gson.toJson(keyIvPair); } - private String composeThumbnailUrl(String rootUrl, VMInstanceVO vm, HostVO hostVo, int w, int h) { + private String composeThumbnailUrl(String rootUrl, VirtualMachine vm, HostVO hostVo, int w, int h) { StringBuffer sb = new StringBuffer(rootUrl); String host = hostVo.getPrivateIpAddress(); @@ -374,7 +378,7 @@ public class ConsoleProxyServlet extends HttpServlet { return sb.toString(); } - private String composeConsoleAccessUrl(String rootUrl, VMInstanceVO vm, HostVO hostVo) { + private String composeConsoleAccessUrl(String rootUrl, VirtualMachine vm, HostVO hostVo) { StringBuffer sb = new StringBuffer(rootUrl); String host = hostVo.getPrivateIpAddress(); @@ -454,7 +458,7 @@ public class ConsoleProxyServlet extends HttpServlet { private boolean checkSessionPermision(HttpServletRequest req, long vmId, Account accountObj) { - VMInstanceVO vm = _vmMgr.findById(vmId); + VirtualMachine vm = _vmMgr.findById(vmId); if(vm == null) { s_logger.debug("Console/thumbnail access denied. VM " + vmId + " does not exist in system any more"); return false; diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java b/server/src/com/cloud/vm/UserVmManagerImpl.java index a4508eef528..0805e6c4ab4 100755 --- a/server/src/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/com/cloud/vm/UserVmManagerImpl.java @@ -4201,9 +4201,8 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir txn.commit(); - VMInstanceVO vmoi = _itMgr.findByIdAndType(vm.getType(), vm.getId()); - VirtualMachineProfileImpl vmOldProfile = new VirtualMachineProfileImpl( - vmoi); + VirtualMachine vmoi = _itMgr.findById(vm.getId()); + VirtualMachineProfileImpl vmOldProfile = new VirtualMachineProfileImpl(vmoi); // OS 3: update the network List networkIdList = cmd.getNetworkIds(); @@ -4279,9 +4278,8 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir networks.add(new Pair(networkList.get(0), profile)); - VMInstanceVO vmi = _itMgr.findByIdAndType(vm.getType(), vm.getId()); - VirtualMachineProfileImpl vmProfile = new VirtualMachineProfileImpl( - vmi); + VirtualMachine vmi = _itMgr.findById(vm.getId()); + VirtualMachineProfileImpl vmProfile = new VirtualMachineProfileImpl(vmi); _networkMgr.allocate(vmProfile, networks); _securityGroupMgr.addInstanceToGroups(vm.getId(), @@ -4413,10 +4411,8 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir networks.add(new Pair(appNet, defaultNic)); } - VMInstanceVO vmi = _itMgr.findByIdAndType(vm.getType(), - vm.getId()); - VirtualMachineProfileImpl vmProfile = new VirtualMachineProfileImpl( - vmi); + VirtualMachine vmi = _itMgr.findById(vm.getId()); + VirtualMachineProfileImpl vmProfile = new VirtualMachineProfileImpl(vmi); _networkMgr.allocate(vmProfile, networks); s_logger.debug("AssignVM: Advance virtual, adding networks no " + networks.size() + " to " + vm.getInstanceName()); diff --git a/server/src/com/cloud/vm/VirtualMachineManager.java b/server/src/com/cloud/vm/VirtualMachineManager.java index 4982bcb2279..6abb91b8941 100644 --- a/server/src/com/cloud/vm/VirtualMachineManager.java +++ b/server/src/com/cloud/vm/VirtualMachineManager.java @@ -108,8 +108,6 @@ public interface VirtualMachineManager extends Manager { T advanceReboot(T vm, Map params, User caller, Account account) throws InsufficientCapacityException, ResourceUnavailableException, ConcurrentOperationException, OperationTimedoutException; - VMInstanceVO findByIdAndType(VirtualMachine.Type type, long vmId); - /** * Check to see if a virtual machine can be upgraded to the given service offering * @@ -119,7 +117,7 @@ public interface VirtualMachineManager extends Manager { */ boolean isVirtualMachineUpgradable(final VirtualMachine vm, final ServiceOffering offering); - VMInstanceVO findById(long vmId); + VirtualMachine findById(long vmId); T storageMigration(T vm, StoragePool storagePoolId); diff --git a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java index fc55ee5d565..413bcb0f31e 100755 --- a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java +++ b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java @@ -2017,11 +2017,6 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac return rebootedVm; } - @Override - public VMInstanceVO findByIdAndType(VirtualMachine.Type type, long vmId) { - return _vmDao.findById(vmId); - } - public Command cleanup(VirtualMachine vm) { return new StopCommand(vm, _mgmtServer.getExecuteInSequence()); } From 5297a071d2c20040878950172b8d0211ac7cb436 Mon Sep 17 00:00:00 2001 From: Alex Huang Date: Mon, 22 Jul 2013 18:24:53 -0700 Subject: [PATCH 58/74] Changed virtual machine stop to use uuid --- .../cloud/entity/api/VMEntityManagerImpl.java | 9 +- .../lb/ElasticLoadBalancerManagerImpl.java | 7 +- .../lb/InternalLoadBalancerVMManagerImpl.java | 7 +- .../InternalLBVMServiceTest.java | 17 --- .../consoleproxy/ConsoleProxyManagerImpl.java | 8 +- .../cloud/ha/HighAvailabilityManagerImpl.java | 37 +++--- .../VirtualNetworkApplianceManagerImpl.java | 7 +- .../cloud/resource/ResourceManagerImpl.java | 14 +-- .../cloud/server/ManagementServerImpl.java | 96 ++++++++++------ .../storage/StoragePoolAutomationImpl.java | 66 +++-------- .../SecondaryStorageManagerImpl.java | 7 +- .../com/cloud/user/AccountManagerImpl.java | 6 +- .../src/com/cloud/vm/UserVmManagerImpl.java | 2 +- .../com/cloud/vm/VirtualMachineManager.java | 6 +- .../cloud/vm/VirtualMachineManagerImpl.java | 105 +++++++++--------- .../vm/snapshot/VMSnapshotManagerImpl.java | 6 +- .../test/com/cloud/vm/UserVmManagerTest.java | 3 - 17 files changed, 174 insertions(+), 229 deletions(-) diff --git a/engine/orchestration/src/org/apache/cloudstack/engine/cloud/entity/api/VMEntityManagerImpl.java b/engine/orchestration/src/org/apache/cloudstack/engine/cloud/entity/api/VMEntityManagerImpl.java index aae0962ee3a..204b832ab4a 100755 --- a/engine/orchestration/src/org/apache/cloudstack/engine/cloud/entity/api/VMEntityManagerImpl.java +++ b/engine/orchestration/src/org/apache/cloudstack/engine/cloud/entity/api/VMEntityManagerImpl.java @@ -245,17 +245,16 @@ public class VMEntityManagerImpl implements VMEntityManager { @Override public boolean stopvirtualmachine(VMEntityVO vmEntityVO, String caller) throws ResourceUnavailableException { - - VMInstanceVO vm = _vmDao.findByUuid(vmEntityVO.getUuid()); - return _itMgr.stop(vm, _userDao.findById(new Long(caller)), _accountDao.findById(vm.getAccountId())); - + _itMgr.stop(vmEntityVO.getUuid()); + return true; } @Override public boolean destroyVirtualMachine(VMEntityVO vmEntityVO, String caller) throws AgentUnavailableException, OperationTimedoutException, ConcurrentOperationException{ VMInstanceVO vm = _vmDao.findByUuid(vmEntityVO.getUuid()); - return _itMgr.destroy(vm, _userDao.findById(new Long(caller)), _accountDao.findById(vm.getAccountId())); + _itMgr.destroy(vm.getUuid()); + return true; } } diff --git a/plugins/network-elements/elastic-loadbalancer/src/com/cloud/network/lb/ElasticLoadBalancerManagerImpl.java b/plugins/network-elements/elastic-loadbalancer/src/com/cloud/network/lb/ElasticLoadBalancerManagerImpl.java index 63663fef394..7c0f87b3f9e 100644 --- a/plugins/network-elements/elastic-loadbalancer/src/com/cloud/network/lb/ElasticLoadBalancerManagerImpl.java +++ b/plugins/network-elements/elastic-loadbalancer/src/com/cloud/network/lb/ElasticLoadBalancerManagerImpl.java @@ -542,11 +542,8 @@ public class ElasticLoadBalancerManagerImpl extends ManagerBase implements Elast private DomainRouterVO stop(DomainRouterVO elbVm, boolean forced, User user, Account caller) throws ConcurrentOperationException, ResourceUnavailableException { s_logger.debug("Stopping ELB vm " + elbVm); try { - if (_itMgr.advanceStop( elbVm, forced, user, caller)) { - return _routerDao.findById(elbVm.getId()); - } else { - return null; - } + _itMgr.advanceStop(elbVm.getUuid(), forced); + return _routerDao.findById(elbVm.getId()); } catch (OperationTimedoutException e) { throw new CloudRuntimeException("Unable to stop " + elbVm, e); } diff --git a/plugins/network-elements/internal-loadbalancer/src/org/apache/cloudstack/network/lb/InternalLoadBalancerVMManagerImpl.java b/plugins/network-elements/internal-loadbalancer/src/org/apache/cloudstack/network/lb/InternalLoadBalancerVMManagerImpl.java index a731f562ebb..1799e60fed1 100644 --- a/plugins/network-elements/internal-loadbalancer/src/org/apache/cloudstack/network/lb/InternalLoadBalancerVMManagerImpl.java +++ b/plugins/network-elements/internal-loadbalancer/src/org/apache/cloudstack/network/lb/InternalLoadBalancerVMManagerImpl.java @@ -534,11 +534,8 @@ public class InternalLoadBalancerVMManagerImpl extends ManagerBase implements protected VirtualRouter stopInternalLbVm(DomainRouterVO internalLbVm, boolean forced, Account caller, long callerUserId) throws ResourceUnavailableException, ConcurrentOperationException { s_logger.debug("Stopping internal lb vm " + internalLbVm); try { - if (_itMgr.advanceStop(internalLbVm, forced, _accountMgr.getActiveUser(callerUserId), caller)) { - return _internalLbVmDao.findById(internalLbVm.getId()); - } else { - return null; - } + _itMgr.advanceStop(internalLbVm.getUuid(), forced); + return _internalLbVmDao.findById(internalLbVm.getId()); } catch (OperationTimedoutException e) { throw new CloudRuntimeException("Unable to stop " + internalLbVm, e); } diff --git a/plugins/network-elements/internal-loadbalancer/test/org/apache/cloudstack/internallbvmmgr/InternalLBVMServiceTest.java b/plugins/network-elements/internal-loadbalancer/test/org/apache/cloudstack/internallbvmmgr/InternalLBVMServiceTest.java index a74f6b02c02..f6a92dd993f 100644 --- a/plugins/network-elements/internal-loadbalancer/test/org/apache/cloudstack/internallbvmmgr/InternalLBVMServiceTest.java +++ b/plugins/network-elements/internal-loadbalancer/test/org/apache/cloudstack/internallbvmmgr/InternalLBVMServiceTest.java @@ -36,7 +36,6 @@ import org.apache.cloudstack.network.lb.InternalLoadBalancerVMService; import com.cloud.exception.ConcurrentOperationException; import com.cloud.exception.InsufficientCapacityException; import com.cloud.exception.InvalidParameterValueException; -import com.cloud.exception.OperationTimedoutException; import com.cloud.exception.ResourceUnavailableException; import com.cloud.exception.StorageUnavailableException; import com.cloud.hypervisor.Hypervisor.HypervisorType; @@ -44,10 +43,8 @@ import com.cloud.network.router.VirtualRouter; import com.cloud.network.router.VirtualRouter.Role; import com.cloud.service.ServiceOfferingVO; import com.cloud.service.dao.ServiceOfferingDao; -import com.cloud.user.Account; import com.cloud.user.AccountManager; import com.cloud.user.AccountVO; -import com.cloud.user.User; import com.cloud.user.UserVO; import com.cloud.user.dao.AccountDao; import com.cloud.utils.component.ComponentContext; @@ -110,20 +107,6 @@ public class InternalLBVMServiceTest extends TestCase { Mockito.when(_domainRouterDao.findById(validVmId)).thenReturn(validVm); Mockito.when(_domainRouterDao.findById(nonExistingVmId)).thenReturn(null); Mockito.when(_domainRouterDao.findById(nonInternalLbVmId)).thenReturn(nonInternalLbVm); - - try { - Mockito.when(_itMgr.advanceStop(Mockito.any(DomainRouterVO.class), Mockito.any(Boolean.class), Mockito.any(User.class), Mockito.any(Account.class))).thenReturn(true); - } catch (ResourceUnavailableException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (OperationTimedoutException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (ConcurrentOperationException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } @Override diff --git a/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java b/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java index 1c31177a884..e1720927aca 100755 --- a/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java +++ b/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java @@ -1025,9 +1025,13 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy } try { - return _itMgr.stop(proxy, _accountMgr.getSystemUser(), _accountMgr.getSystemAccount()); + _itMgr.stop(proxy.getUuid()); + return true; } catch (ResourceUnavailableException e) { - s_logger.warn("Stopping console proxy " + proxy.getHostName() + " failed : exception " + e.toString()); + s_logger.warn("Stopping console proxy " + proxy.getHostName() + " failed : exception ", e); + return false; + } catch (CloudRuntimeException e) { + s_logger.warn("Unable to stop proxy ", e); return false; } } diff --git a/server/src/com/cloud/ha/HighAvailabilityManagerImpl.java b/server/src/com/cloud/ha/HighAvailabilityManagerImpl.java index 896c4189edf..a7e0bd9a77a 100755 --- a/server/src/com/cloud/ha/HighAvailabilityManagerImpl.java +++ b/server/src/com/cloud/ha/HighAvailabilityManagerImpl.java @@ -286,7 +286,7 @@ public class HighAvailabilityManagerImpl extends ManagerBase implements HighAvai if (hostId == null) { try { s_logger.debug("Found a vm that is scheduled to be restarted but has no host id: " + vm); - _itMgr.advanceStop(vm, true, _accountMgr.getSystemUser(), _accountMgr.getSystemAccount()); + _itMgr.advanceStop(vm.getUuid(), true); } catch (ResourceUnavailableException e) { assert false : "How do we hit this when force is true?"; throw new CloudRuntimeException("Caught exception even though it should be handled.", e); @@ -330,7 +330,7 @@ public class HighAvailabilityManagerImpl extends ManagerBase implements HighAvai } try { - _itMgr.advanceStop(vm, true, _accountMgr.getSystemUser(), _accountMgr.getSystemAccount()); + _itMgr.advanceStop(vm.getUuid(), true); } catch (ResourceUnavailableException e) { assert false : "How do we hit this when force is true?"; throw new CloudRuntimeException("Caught exception even though it should be handled.", e); @@ -475,7 +475,7 @@ public class HighAvailabilityManagerImpl extends ManagerBase implements HighAvai } try { - _itMgr.advanceStop(vm, true, _accountMgr.getSystemUser(), _accountMgr.getSystemAccount()); + _itMgr.advanceStop(vm.getUuid(), true); } catch (ResourceUnavailableException e) { assert false : "How do we hit this when force is true?"; throw new CloudRuntimeException("Caught exception even though it should be handled.", e); @@ -492,7 +492,7 @@ public class HighAvailabilityManagerImpl extends ManagerBase implements HighAvai } else { s_logger.debug("How come that HA step is Investigating and the host is removed? Calling forced Stop on Vm anyways"); try { - _itMgr.advanceStop(vm, true, _accountMgr.getSystemUser(), _accountMgr.getSystemAccount()); + _itMgr.advanceStop(vm.getUuid(), true); } catch (ResourceUnavailableException e) { assert false : "How do we hit this when force is true?"; throw new CloudRuntimeException("Caught exception even though it should be handled.", e); @@ -615,11 +615,9 @@ public class HighAvailabilityManagerImpl extends ManagerBase implements HighAvai } if (vm.getHostId() != null) { - if (_itMgr.destroy(vm, _accountMgr.getSystemUser(), _accountMgr.getSystemAccount())) { - s_logger.info("Successfully destroy " + vm); - return null; - } - s_logger.debug("Stop for " + vm + " was unsuccessful."); + _itMgr.destroy(vm.getUuid()); + s_logger.info("Successfully destroy " + vm); + return null; } else { if (s_logger.isDebugEnabled()) { s_logger.debug(vm + " has already been stopped"); @@ -648,28 +646,25 @@ public class HighAvailabilityManagerImpl extends ManagerBase implements HighAvai s_logger.info("Stopping " + vm); try { if (work.getWorkType() == WorkType.Stop) { - if (_itMgr.advanceStop(vm, false, _accountMgr.getSystemUser(), _accountMgr.getSystemAccount())) { - s_logger.info("Successfully stopped " + vm); - return null; - } + _itMgr.advanceStop(vm.getUuid(), false); + s_logger.info("Successfully stopped " + vm); + return null; } else if (work.getWorkType() == WorkType.CheckStop) { if ((vm.getState() != work.getPreviousState()) || vm.getUpdated() != work.getUpdateTime() || vm.getHostId() == null || vm.getHostId().longValue() != work.getHostId()) { s_logger.info(vm + " is different now. Scheduled Host: " + work.getHostId() + " Current Host: " + (vm.getHostId() != null ? vm.getHostId() : "none") + " State: " + vm.getState()); return null; } - if (_itMgr.advanceStop(vm, false, _accountMgr.getSystemUser(), _accountMgr.getSystemAccount())) { - s_logger.info("Stop for " + vm + " was successful"); - return null; - } + _itMgr.advanceStop(vm.getUuid(), false); + s_logger.info("Stop for " + vm + " was successful"); + return null; } else if (work.getWorkType() == WorkType.ForceStop) { if ((vm.getState() != work.getPreviousState()) || vm.getUpdated() != work.getUpdateTime() || vm.getHostId() == null || vm.getHostId().longValue() != work.getHostId()) { s_logger.info(vm + " is different now. Scheduled Host: " + work.getHostId() + " Current Host: " + (vm.getHostId() != null ? vm.getHostId() : "none") + " State: " + vm.getState()); return null; } - if (_itMgr.advanceStop(vm, true, _accountMgr.getSystemUser(), _accountMgr.getSystemAccount())) { - s_logger.info("Stop for " + vm + " was successful"); - return null; - } + _itMgr.advanceStop(vm.getUuid(), true); + s_logger.info("Stop for " + vm + " was successful"); + return null; } else { assert false : "Who decided there's other steps but didn't modify the guy who does the work?"; } diff --git a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java index 89db3c23a46..4859f0de038 100755 --- a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java +++ b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java @@ -2755,11 +2755,8 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V public DomainRouterVO stop(VirtualRouter router, boolean forced, User user, Account caller) throws ConcurrentOperationException, ResourceUnavailableException { s_logger.debug("Stopping router " + router); try { - if (_itMgr.advanceStop((DomainRouterVO) router, forced, user, caller)) { - return _routerDao.findById(router.getId()); - } else { - return null; - } + _itMgr.advanceStop(router.getUuid(), forced); + return _routerDao.findById(router.getId()); } catch (OperationTimedoutException e) { throw new CloudRuntimeException("Unable to stop " + router, e); } diff --git a/server/src/com/cloud/resource/ResourceManagerImpl.java b/server/src/com/cloud/resource/ResourceManagerImpl.java index 830aaa14a28..342b9fd03dc 100755 --- a/server/src/com/cloud/resource/ResourceManagerImpl.java +++ b/server/src/com/cloud/resource/ResourceManagerImpl.java @@ -2043,8 +2043,6 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, s_logger.debug("Deleting Host: " + host.getId() + " Guid:" + host.getGuid()); } - User caller = _accountMgr.getActiveUser(CallContext.current().getCallingUserId()); - if (forceDestroyStorage) { // put local storage into mainenance mode, will set all the VMs on // this local storage into stopped state @@ -2067,11 +2065,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, List vmsOnLocalStorage = _storageMgr.listByStoragePool(storagePool.getId()); for (VMInstanceVO vm : vmsOnLocalStorage) { try { - if (!_vmMgr.destroy(vm, caller, _accountMgr.getAccount(vm.getAccountId()))) { - String errorMsg = "There was an error Destory the vm: " + vm + " as a part of hostDelete id=" + host.getId(); - s_logger.warn(errorMsg); - throw new UnableDeleteHostException(errorMsg); - } + _vmMgr.destroy(vm.getUuid()); } catch (Exception e) { String errorMsg = "There was an error Destory the vm: " + vm + " as a part of hostDelete id=" + host.getId(); s_logger.debug(errorMsg, e); @@ -2090,11 +2084,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, if (!vm.isHaEnabled() || vm.getState() == State.Stopping) { s_logger.debug("Stopping vm: " + vm + " as a part of deleteHost id=" + host.getId()); try { - if (!_vmMgr.advanceStop(vm, true, caller, _accountMgr.getAccount(vm.getAccountId()))) { - String errorMsg = "There was an error stopping the vm: " + vm + " as a part of hostDelete id=" + host.getId(); - s_logger.warn(errorMsg); - throw new UnableDeleteHostException(errorMsg); - } + _vmMgr.advanceStop(vm.getUuid(), false); } catch (Exception e) { String errorMsg = "There was an error stopping the vm: " + vm + " as a part of hostDelete id=" + host.getId(); s_logger.debug(errorMsg, e); diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java index 23e2ca1f036..7ac12547090 100755 --- a/server/src/com/cloud/server/ManagementServerImpl.java +++ b/server/src/com/cloud/server/ManagementServerImpl.java @@ -39,23 +39,15 @@ import javax.crypto.spec.SecretKeySpec; import javax.inject.Inject; import javax.naming.ConfigurationException; -import com.cloud.exception.*; -import com.cloud.vm.*; - -import org.apache.cloudstack.acl.ControlledEntity; -import org.apache.cloudstack.acl.SecurityChecker.AccessType; -import org.apache.cloudstack.api.ApiConstants; - -import com.cloud.event.ActionEventUtils; - -import org.apache.cloudstack.api.BaseUpdateTemplateOrIsoCmd; -import org.apache.cloudstack.api.command.admin.region.*; - import org.apache.commons.codec.binary.Base64; import org.apache.log4j.Logger; +import org.apache.cloudstack.acl.ControlledEntity; +import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.affinity.AffinityGroupProcessor; import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseUpdateTemplateOrIsoCmd; import org.apache.cloudstack.api.command.admin.account.CreateAccountCmd; import org.apache.cloudstack.api.command.admin.account.DeleteAccountCmd; import org.apache.cloudstack.api.command.admin.account.DisableAccountCmd; @@ -69,6 +61,7 @@ import org.apache.cloudstack.api.command.admin.cluster.DeleteClusterCmd; import org.apache.cloudstack.api.command.admin.cluster.ListClustersCmd; import org.apache.cloudstack.api.command.admin.cluster.UpdateClusterCmd; import org.apache.cloudstack.api.command.admin.config.ListCfgsByCmd; +import org.apache.cloudstack.api.command.admin.config.ListDeploymentPlannersCmd; import org.apache.cloudstack.api.command.admin.config.ListHypervisorCapabilitiesCmd; import org.apache.cloudstack.api.command.admin.config.UpdateCfgCmd; import org.apache.cloudstack.api.command.admin.config.UpdateHypervisorCapabilitiesCmd; @@ -129,6 +122,12 @@ import org.apache.cloudstack.api.command.admin.pod.CreatePodCmd; import org.apache.cloudstack.api.command.admin.pod.DeletePodCmd; import org.apache.cloudstack.api.command.admin.pod.ListPodsByCmd; import org.apache.cloudstack.api.command.admin.pod.UpdatePodCmd; +import org.apache.cloudstack.api.command.admin.region.AddRegionCmd; +import org.apache.cloudstack.api.command.admin.region.CreatePortableIpRangeCmd; +import org.apache.cloudstack.api.command.admin.region.DeletePortableIpRangeCmd; +import org.apache.cloudstack.api.command.admin.region.ListPortableIpRangesCmd; +import org.apache.cloudstack.api.command.admin.region.RemoveRegionCmd; +import org.apache.cloudstack.api.command.admin.region.UpdateRegionCmd; import org.apache.cloudstack.api.command.admin.resource.ArchiveAlertsCmd; import org.apache.cloudstack.api.command.admin.resource.CleanVMReservationsCmd; import org.apache.cloudstack.api.command.admin.resource.DeleteAlertsCmd; @@ -159,7 +158,14 @@ import org.apache.cloudstack.api.command.admin.storage.ListStoragePoolsCmd; import org.apache.cloudstack.api.command.admin.storage.ListStorageProvidersCmd; import org.apache.cloudstack.api.command.admin.storage.PreparePrimaryStorageForMaintenanceCmd; import org.apache.cloudstack.api.command.admin.storage.UpdateStoragePoolCmd; -import org.apache.cloudstack.api.command.admin.systemvm.*; +import org.apache.cloudstack.api.command.admin.systemvm.DestroySystemVmCmd; +import org.apache.cloudstack.api.command.admin.systemvm.ListSystemVMsCmd; +import org.apache.cloudstack.api.command.admin.systemvm.MigrateSystemVMCmd; +import org.apache.cloudstack.api.command.admin.systemvm.RebootSystemVmCmd; +import org.apache.cloudstack.api.command.admin.systemvm.ScaleSystemVMCmd; +import org.apache.cloudstack.api.command.admin.systemvm.StartSystemVMCmd; +import org.apache.cloudstack.api.command.admin.systemvm.StopSystemVmCmd; +import org.apache.cloudstack.api.command.admin.systemvm.UpgradeSystemVMCmd; import org.apache.cloudstack.api.command.admin.template.PrepareTemplateCmd; import org.apache.cloudstack.api.command.admin.usage.AddTrafficMonitorCmd; import org.apache.cloudstack.api.command.admin.usage.AddTrafficTypeCmd; @@ -309,8 +315,8 @@ import org.apache.cloudstack.api.command.user.region.ha.gslb.AssignToGlobalLoadB import org.apache.cloudstack.api.command.user.region.ha.gslb.CreateGlobalLoadBalancerRuleCmd; import org.apache.cloudstack.api.command.user.region.ha.gslb.DeleteGlobalLoadBalancerRuleCmd; import org.apache.cloudstack.api.command.user.region.ha.gslb.ListGlobalLoadBalancerRuleCmd; -import org.apache.cloudstack.api.command.user.region.ha.gslb.UpdateGlobalLoadBalancerRuleCmd; import org.apache.cloudstack.api.command.user.region.ha.gslb.RemoveFromGlobalLoadBalancerRuleCmd; +import org.apache.cloudstack.api.command.user.region.ha.gslb.UpdateGlobalLoadBalancerRuleCmd; import org.apache.cloudstack.api.command.user.resource.GetCloudIdentifierCmd; import org.apache.cloudstack.api.command.user.resource.ListHypervisorsCmd; import org.apache.cloudstack.api.command.user.resource.ListResourceLimitsCmd; @@ -372,7 +378,19 @@ import org.apache.cloudstack.api.command.user.vmsnapshot.CreateVMSnapshotCmd; import org.apache.cloudstack.api.command.user.vmsnapshot.DeleteVMSnapshotCmd; import org.apache.cloudstack.api.command.user.vmsnapshot.ListVMSnapshotCmd; import org.apache.cloudstack.api.command.user.vmsnapshot.RevertToVMSnapshotCmd; -import org.apache.cloudstack.api.command.user.volume.*; +import org.apache.cloudstack.api.command.user.volume.AddResourceDetailCmd; +import org.apache.cloudstack.api.command.user.volume.AttachVolumeCmd; +import org.apache.cloudstack.api.command.user.volume.CreateVolumeCmd; +import org.apache.cloudstack.api.command.user.volume.DeleteVolumeCmd; +import org.apache.cloudstack.api.command.user.volume.DetachVolumeCmd; +import org.apache.cloudstack.api.command.user.volume.ExtractVolumeCmd; +import org.apache.cloudstack.api.command.user.volume.ListResourceDetailsCmd; +import org.apache.cloudstack.api.command.user.volume.ListVolumesCmd; +import org.apache.cloudstack.api.command.user.volume.MigrateVolumeCmd; +import org.apache.cloudstack.api.command.user.volume.RemoveResourceDetailCmd; +import org.apache.cloudstack.api.command.user.volume.ResizeVolumeCmd; +import org.apache.cloudstack.api.command.user.volume.UpdateVolumeCmd; +import org.apache.cloudstack.api.command.user.volume.UploadVolumeCmd; import org.apache.cloudstack.api.command.user.vpc.CreateStaticRouteCmd; import org.apache.cloudstack.api.command.user.vpc.CreateVPCCmd; import org.apache.cloudstack.api.command.user.vpc.DeleteStaticRouteCmd; @@ -401,6 +419,7 @@ import org.apache.cloudstack.api.command.user.vpn.RemoveVpnUserCmd; import org.apache.cloudstack.api.command.user.vpn.ResetVpnConnectionCmd; import org.apache.cloudstack.api.command.user.vpn.UpdateVpnCustomerGatewayCmd; import org.apache.cloudstack.api.command.user.zone.ListZonesByCmd; +import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; import org.apache.cloudstack.engine.subsystem.api.storage.StoragePoolAllocator; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory; @@ -451,9 +470,17 @@ import com.cloud.deploy.DeploymentPlanningManager; import com.cloud.domain.DomainVO; import com.cloud.domain.dao.DomainDao; import com.cloud.event.ActionEvent; +import com.cloud.event.ActionEventUtils; import com.cloud.event.EventTypes; import com.cloud.event.EventVO; import com.cloud.event.dao.EventDao; +import com.cloud.exception.ConcurrentOperationException; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.exception.ManagementServerException; +import com.cloud.exception.OperationTimedoutException; +import com.cloud.exception.PermissionDeniedException; +import com.cloud.exception.ResourceUnavailableException; +import com.cloud.exception.VirtualMachineMigrationException; import com.cloud.ha.HighAvailabilityManager; import com.cloud.host.DetailVO; import com.cloud.host.Host; @@ -491,9 +518,9 @@ import com.cloud.storage.GuestOSCategoryVO; import com.cloud.storage.GuestOSVO; import com.cloud.storage.GuestOsCategory; import com.cloud.storage.Storage.ImageFormat; +import com.cloud.storage.Storage.TemplateType; import com.cloud.storage.StorageManager; import com.cloud.storage.StoragePool; -import com.cloud.storage.Storage.TemplateType; import com.cloud.storage.VMTemplateVO; import com.cloud.storage.Volume; import com.cloud.storage.VolumeManager; @@ -542,7 +569,18 @@ import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.net.MacAddress; import com.cloud.utils.net.NetUtils; import com.cloud.utils.ssh.SSHKeysHelper; +import com.cloud.vm.ConsoleProxyVO; +import com.cloud.vm.DiskProfile; +import com.cloud.vm.InstanceGroupVO; +import com.cloud.vm.SecondaryStorageVmVO; +import com.cloud.vm.UserVmManager; +import com.cloud.vm.UserVmVO; +import com.cloud.vm.VMInstanceVO; +import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachine.State; +import com.cloud.vm.VirtualMachineManager; +import com.cloud.vm.VirtualMachineProfile; +import com.cloud.vm.VirtualMachineProfileImpl; import com.cloud.vm.dao.ConsoleProxyDao; import com.cloud.vm.dao.DomainRouterDao; import com.cloud.vm.dao.InstanceGroupDao; @@ -553,12 +591,6 @@ import com.cloud.vm.dao.VMInstanceDao; import edu.emory.mathcs.backport.java.util.Arrays; import edu.emory.mathcs.backport.java.util.Collections; -import org.apache.cloudstack.api.command.admin.region.AddRegionCmd; -import org.apache.cloudstack.api.command.admin.region.RemoveRegionCmd; -import org.apache.cloudstack.api.command.admin.region.UpdateRegionCmd; -import org.apache.cloudstack.api.command.admin.config.ListDeploymentPlannersCmd; -import org.apache.cloudstack.context.CallContext; - public class ManagementServerImpl extends ManagerBase implements ManagementServer { public static final Logger s_logger = Logger.getLogger(ManagementServerImpl.class.getName()); @@ -725,7 +757,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe return _affinityProcessors; } public void setAffinityGroupProcessors(List affinityProcessors) { - this._affinityProcessors = affinityProcessors; + _affinityProcessors = affinityProcessors; } public ManagementServerImpl() { @@ -1272,7 +1304,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe storagePools.remove(srcVolumePool); for (StoragePoolVO pool : storagePools) { if (pool.isShared()) { - allPools.add((StoragePool)this.dataStoreMgr.getPrimaryDataStore(pool.getId())); + allPools.add((StoragePool)dataStoreMgr.getPrimaryDataStore(pool.getId())); } } @@ -2060,12 +2092,8 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe private ConsoleProxyVO stopConsoleProxy(VMInstanceVO systemVm, boolean isForced) throws ResourceUnavailableException, OperationTimedoutException, ConcurrentOperationException { - User caller = _userDao.findById(CallContext.current().getCallingUserId()); - - if (_itMgr.advanceStop(systemVm, isForced, caller, CallContext.current().getCallingAccount())) { - return _consoleProxyDao.findById(systemVm.getId()); - } - return null; + _itMgr.advanceStop(systemVm.getUuid(), isForced); + return _consoleProxyDao.findById(systemVm.getId()); } @ActionEvent(eventType = EventTypes.EVENT_PROXY_REBOOT, eventDescription = "rebooting console proxy Vm", async = true) @@ -2949,12 +2977,8 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe private SecondaryStorageVmVO stopSecondaryStorageVm(VMInstanceVO systemVm, boolean isForced) throws ResourceUnavailableException, OperationTimedoutException, ConcurrentOperationException { - User caller = _userDao.findById(CallContext.current().getCallingUserId()); - - if (_itMgr.advanceStop(systemVm, isForced, caller, CallContext.current().getCallingAccount())) { - return _secStorageVmDao.findById(systemVm.getId()); - } - return null; + _itMgr.advanceStop(systemVm.getUuid(), isForced); + return _secStorageVmDao.findById(systemVm.getId()); } @ActionEvent(eventType = EventTypes.EVENT_SSVM_REBOOT, eventDescription = "rebooting secondary storage Vm", async = true) diff --git a/server/src/com/cloud/storage/StoragePoolAutomationImpl.java b/server/src/com/cloud/storage/StoragePoolAutomationImpl.java index 7b931035fba..f0f6eaf8073 100644 --- a/server/src/com/cloud/storage/StoragePoolAutomationImpl.java +++ b/server/src/com/cloud/storage/StoragePoolAutomationImpl.java @@ -234,19 +234,11 @@ public class StoragePoolAutomationImpl implements StoragePoolAutomation { if (vmInstance.getType().equals( VirtualMachine.Type.ConsoleProxy)) { // call the consoleproxymanager - ConsoleProxyVO consoleProxy = _consoleProxyDao - .findById(vmInstance.getId()); - if (!vmMgr.advanceStop(consoleProxy, true, user, account)) { - String errorMsg = "There was an error stopping the console proxy id: " - + vmInstance.getId() - + " ,cannot enable storage maintenance"; - s_logger.warn(errorMsg); - throw new CloudRuntimeException(errorMsg); - } else { - // update work status - work.setStoppedForMaintenance(true); - _storagePoolWorkDao.update(work.getId(), work); - } + ConsoleProxyVO consoleProxy = _consoleProxyDao.findById(vmInstance.getId()); + vmMgr.advanceStop(consoleProxy.getUuid(), false); + // update work status + work.setStoppedForMaintenance(true); + _storagePoolWorkDao.update(work.getId(), work); if (restart) { @@ -260,36 +252,21 @@ public class StoragePoolAutomationImpl implements StoragePoolAutomation { // if the instance is of type uservm, call the user vm manager if (vmInstance.getType() == VirtualMachine.Type.User) { UserVmVO userVm = userVmDao.findById(vmInstance.getId()); - if (!vmMgr.advanceStop(userVm, true, user, account)) { - String errorMsg = "There was an error stopping the user vm id: " - + vmInstance.getId() - + " ,cannot enable storage maintenance"; - s_logger.warn(errorMsg); - throw new CloudRuntimeException(errorMsg); - } else { - // update work status - work.setStoppedForMaintenance(true); - _storagePoolWorkDao.update(work.getId(), work); - } + vmMgr.advanceStop(userVm.getUuid(), false); + // update work status + work.setStoppedForMaintenance(true); + _storagePoolWorkDao.update(work.getId(), work); } // if the instance is of type secondary storage vm, call the // secondary storage vm manager if (vmInstance.getType().equals( VirtualMachine.Type.SecondaryStorageVm)) { - SecondaryStorageVmVO secStrgVm = _secStrgDao - .findById(vmInstance.getId()); - if (!vmMgr.advanceStop(secStrgVm, true, user, account)) { - String errorMsg = "There was an error stopping the ssvm id: " - + vmInstance.getId() - + " ,cannot enable storage maintenance"; - s_logger.warn(errorMsg); - throw new CloudRuntimeException(errorMsg); - } else { - // update work status - work.setStoppedForMaintenance(true); - _storagePoolWorkDao.update(work.getId(), work); - } + SecondaryStorageVmVO secStrgVm = _secStrgDao.findById(vmInstance.getId()); + vmMgr.advanceStop(secStrgVm.getUuid(), false); + // update work status + work.setStoppedForMaintenance(true); + _storagePoolWorkDao.update(work.getId(), work); if (restart) { vmMgr.advanceStart(secStrgVm.getUuid(), null); @@ -304,17 +281,10 @@ public class StoragePoolAutomationImpl implements StoragePoolAutomation { if (vmInstance.getType().equals( VirtualMachine.Type.DomainRouter)) { DomainRouterVO domR = _domrDao.findById(vmInstance.getId()); - if (!vmMgr.advanceStop(domR, true, user, account)) { - String errorMsg = "There was an error stopping the domain router id: " - + vmInstance.getId() - + " ,cannot enable primary storage maintenance"; - s_logger.warn(errorMsg); - throw new CloudRuntimeException(errorMsg); - } else { - // update work status - work.setStoppedForMaintenance(true); - _storagePoolWorkDao.update(work.getId(), work); - } + vmMgr.advanceStop(domR.getUuid(), false); + // update work status + work.setStoppedForMaintenance(true); + _storagePoolWorkDao.update(work.getId(), work); if (restart) { vmMgr.advanceStart(domR.getUuid(), null); diff --git a/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java b/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java index 127a824e794..56b8dba84f4 100755 --- a/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java +++ b/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java @@ -905,11 +905,8 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar try { if (secStorageVmLock.lock(ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_SYNC)) { try { - boolean result = _itMgr.stop(secStorageVm, _accountMgr.getSystemUser(), _accountMgr.getSystemAccount()); - if (result) { - } - - return result; + _itMgr.stop(secStorageVm.getUuid()); + return true; } finally { secStorageVmLock.unlock(); } diff --git a/server/src/com/cloud/user/AccountManagerImpl.java b/server/src/com/cloud/user/AccountManagerImpl.java index 512f9130a06..53e3f51f262 100755 --- a/server/src/com/cloud/user/AccountManagerImpl.java +++ b/server/src/com/cloud/user/AccountManagerImpl.java @@ -822,11 +822,11 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M try { try { if (vm.getType() == Type.User) { - success = (success && _itMgr.advanceStop(_userVmDao.findById(vm.getId()), false, getSystemUser(), getSystemAccount())); + _itMgr.advanceStop(vm.getUuid(), false); } else if (vm.getType() == Type.DomainRouter) { - success = (success && _itMgr.advanceStop(_routerDao.findById(vm.getId()), false, getSystemUser(), getSystemAccount())); + _itMgr.advanceStop(vm.getUuid(), false); } else { - success = (success && _itMgr.advanceStop(vm, false, getSystemUser(), getSystemAccount())); + _itMgr.advanceStop(vm.getUuid(), false); } } catch (OperationTimedoutException ote) { s_logger.warn("Operation for stopping vm timed out, unable to stop vm " + vm.getHostName(), ote); diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java b/server/src/com/cloud/vm/UserVmManagerImpl.java index 0805e6c4ab4..ca1c2328fe2 100755 --- a/server/src/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/com/cloud/vm/UserVmManagerImpl.java @@ -4523,7 +4523,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir if (needRestart) { try { - _itMgr.stop(vm, user, caller); + _itMgr.stop(vm.getUuid()); } catch (ResourceUnavailableException e) { s_logger.debug("Stop vm " + vm.getUuid() + " failed", e); CloudRuntimeException ex = new CloudRuntimeException( diff --git a/server/src/com/cloud/vm/VirtualMachineManager.java b/server/src/com/cloud/vm/VirtualMachineManager.java index 6abb91b8941..cf0ede2293d 100644 --- a/server/src/com/cloud/vm/VirtualMachineManager.java +++ b/server/src/com/cloud/vm/VirtualMachineManager.java @@ -76,7 +76,7 @@ public interface VirtualMachineManager extends Manager { void start(String vmUuid, Map params, DeploymentPlan planToDeploy); - boolean stop(T vm, User caller, Account account) throws ResourceUnavailableException; + void stop(String vmUuid) throws ResourceUnavailableException; boolean expunge(T vm, User caller, Account account) throws ResourceUnavailableException; @@ -90,13 +90,13 @@ public interface VirtualMachineManager extends Manager { void advanceStart(String vmUuid, Map params, DeploymentPlan planToDeploy) throws InsufficientCapacityException, ResourceUnavailableException, ConcurrentOperationException, OperationTimedoutException; - boolean advanceStop(T vm, boolean forced, User caller, Account account) throws ResourceUnavailableException, OperationTimedoutException, ConcurrentOperationException; + void advanceStop(String vmUuid, boolean cleanupEvenIfUnableToStop) throws ResourceUnavailableException, OperationTimedoutException, ConcurrentOperationException; boolean advanceExpunge(T vm, User caller, Account account) throws ResourceUnavailableException, OperationTimedoutException, ConcurrentOperationException; boolean remove(T vm, User caller, Account account); - boolean destroy(T vm, User caller, Account account) throws AgentUnavailableException, OperationTimedoutException, ConcurrentOperationException; + void destroy(String vmUuid) throws AgentUnavailableException, OperationTimedoutException, ConcurrentOperationException; boolean migrateAway(VirtualMachine.Type type, long vmid, long hostId) throws InsufficientServerCapacityException, VirtualMachineMigrationException; diff --git a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java index 413bcb0f31e..88fb41d1017 100755 --- a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java +++ b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java @@ -444,11 +444,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac return true; } - if (!this.advanceStop(vm, false, caller, account)) { - if (s_logger.isDebugEnabled()) { - s_logger.debug("Unable to stop the VM so we can't expunge it."); - } - } + advanceStop(vm, false); try { if (!stateTransitTo(vm, VirtualMachine.Event.ExpungeOperation, vm.getHostId())) { @@ -1014,10 +1010,10 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac _workDao.updateStep(work, Step.Release); // If previous step was started/ing && we got a valid answer if((prevStep == Step.Started || prevStep == Step.Starting) && (startAnswer != null && startAnswer.getResult())){ //TODO check the response of cleanup and record it in DB for retry - cleanup(vmGuru, vmProfile, work, Event.OperationFailed, false, caller, account); + cleanup(vmGuru, vmProfile, work, Event.OperationFailed, false); } else { //if step is not starting/started, send cleanup command with force=true - cleanup(vmGuru, vmProfile, work, Event.OperationFailed, true, caller, account); + cleanup(vmGuru, vmProfile, work, Event.OperationFailed, true); } } } @@ -1045,11 +1041,11 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac } @Override - public boolean stop(T vm, User user, Account account) throws ResourceUnavailableException { + public void stop(String vmUuid) throws ResourceUnavailableException { try { - return advanceStop(vm, false, user, account); + advanceStop(vmUuid, false); } catch (OperationTimedoutException e) { - throw new AgentUnavailableException("Unable to stop vm because the operation to stop timed out", vm.getHostId(), e); + throw new AgentUnavailableException("Unable to stop vm because the operation to stop timed out", e.getAgentId(), e); } catch (ConcurrentOperationException e) { throw new CloudRuntimeException("Unable to stop vm because of a concurrent operation", e); } @@ -1079,20 +1075,20 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac return true; } - protected boolean cleanup(VirtualMachineGuru guru, VirtualMachineProfile profile, ItWorkVO work, Event event, boolean force, User user, Account account) { + protected boolean cleanup(VirtualMachineGuru guru, VirtualMachineProfile profile, ItWorkVO work, Event event, boolean cleanUpEvenIfUnableToStop) { VirtualMachine vm = profile.getVirtualMachine(); State state = vm.getState(); s_logger.debug("Cleaning up resources for the vm " + vm + " in " + state + " state"); if (state == State.Starting) { Step step = work.getStep(); - if (step == Step.Starting && !force) { + if (step == Step.Starting && !cleanUpEvenIfUnableToStop) { s_logger.warn("Unable to cleanup vm " + vm + "; work state is incorrect: " + step); return false; } if (step == Step.Started || step == Step.Starting || step == Step.Release) { if (vm.getHostId() != null) { - if (!sendStop(guru, profile, force)) { + if (!sendStop(guru, profile, cleanUpEvenIfUnableToStop)) { s_logger.warn("Failed to stop vm " + vm + " in " + State.Starting + " state as a part of cleanup process"); return false; } @@ -1105,33 +1101,33 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac } } else if (state == State.Stopping) { if (vm.getHostId() != null) { - if (!sendStop(guru, profile, force)) { + if (!sendStop(guru, profile, cleanUpEvenIfUnableToStop)) { s_logger.warn("Failed to stop vm " + vm + " in " + State.Stopping + " state as a part of cleanup process"); return false; } } } else if (state == State.Migrating) { if (vm.getHostId() != null) { - if (!sendStop(guru, profile, force)) { + if (!sendStop(guru, profile, cleanUpEvenIfUnableToStop)) { s_logger.warn("Failed to stop vm " + vm + " in " + State.Migrating + " state as a part of cleanup process"); return false; } } if (vm.getLastHostId() != null) { - if (!sendStop(guru, profile, force)) { + if (!sendStop(guru, profile, cleanUpEvenIfUnableToStop)) { s_logger.warn("Failed to stop vm " + vm + " in " + State.Migrating + " state as a part of cleanup process"); return false; } } } else if (state == State.Running) { - if (!sendStop(guru, profile, force)) { + if (!sendStop(guru, profile, cleanUpEvenIfUnableToStop)) { s_logger.warn("Failed to stop vm " + vm + " in " + State.Running + " state as a part of cleanup process"); return false; } } try { - _networkMgr.release(profile, force); + _networkMgr.release(profile, cleanUpEvenIfUnableToStop); s_logger.debug("Successfully released network resources for the vm " + vm); } catch (Exception e) { s_logger.warn("Unable to release some network resources.", e); @@ -1143,20 +1139,23 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac } @Override - public boolean advanceStop(T vm, boolean forced, User user, Account account) throws AgentUnavailableException, OperationTimedoutException, ConcurrentOperationException { + public void advanceStop(String vmUuid, boolean cleanUpEvenIfUnableToStop) throws AgentUnavailableException, OperationTimedoutException, ConcurrentOperationException { + } + + private void advanceStop(VMInstanceVO vm, boolean cleanUpEvenIfUnableToStop) throws AgentUnavailableException, OperationTimedoutException, ConcurrentOperationException { State state = vm.getState(); if (state == State.Stopped) { if (s_logger.isDebugEnabled()) { s_logger.debug("VM is already stopped: " + vm); } - return true; + return; } if (state == State.Destroyed || state == State.Expunging || state == State.Error) { if (s_logger.isDebugEnabled()) { s_logger.debug("Stopped called on " + vm + " but the state is " + state); } - return true; + return; } // grab outstanding work item if any ItWorkVO work = _workDao.findByOutstandingWork(vm.getId(), vm.getState()); @@ -1167,11 +1166,11 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac } Long hostId = vm.getHostId(); if (hostId == null) { - if (!forced) { + if (!cleanUpEvenIfUnableToStop) { if (s_logger.isDebugEnabled()) { s_logger.debug("HostId is null but this is not a forced stop, cannot stop vm " + vm + " with state:" + vm.getState()); } - return false; + throw new CloudRuntimeException("Unable to stop " + vm); } try { stateTransitTo(vm, Event.AgentReportStopped, null, null); @@ -1186,7 +1185,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac work.setStep(Step.Done); _workDao.update(work.getId(), work); } - return true; + return; } VirtualMachineGuru vmGuru = getVmGuru(vm); @@ -1197,7 +1196,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac throw new ConcurrentOperationException("VM is being operated on."); } } catch (NoTransitionException e1) { - if (!forced) { + if (!cleanUpEvenIfUnableToStop) { throw new CloudRuntimeException("We cannot stop " + vm + " when it is in state " + vm.getState()); } boolean doCleanup = false; @@ -1218,15 +1217,17 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac } if (doCleanup) { - if (cleanup(vmGuru, new VirtualMachineProfileImpl(vm), work, Event.StopRequested, forced, user, account)) { + if (cleanup(vmGuru, new VirtualMachineProfileImpl(vm), work, Event.StopRequested, cleanUpEvenIfUnableToStop)) { try { if (s_logger.isDebugEnabled()) { s_logger.debug("Updating work item to Done, id:" + work.getId()); } - return changeState(vm, Event.AgentReportStopped, null, work, Step.Done); + if (!changeState(vm, Event.AgentReportStopped, null, work, Step.Done)) { + throw new CloudRuntimeException("Unable to stop " + vm); + } } catch (NoTransitionException e) { s_logger.warn("Unable to cleanup " + vm); - return false; + throw new CloudRuntimeException("Unable to stop " + vm, e); } } else { if (s_logger.isDebugEnabled()) { @@ -1271,14 +1272,14 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac throw e; } finally { if (!stopped) { - if (!forced) { + if (!cleanUpEvenIfUnableToStop) { s_logger.warn("Unable to stop vm " + vm); try { stateTransitTo(vm, Event.OperationFailed, vm.getHostId()); } catch (NoTransitionException e) { s_logger.warn("Unable to transition the state " + vm); } - return false; + throw new CloudRuntimeException("Unable to stop " + vm); } else { s_logger.warn("Unable to actually stop " + vm + " but continue with release because it's a force stop"); vmGuru.finalizeStop(profile, answer); @@ -1291,7 +1292,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac } try { - _networkMgr.release(profile, forced); + _networkMgr.release(profile, cleanUpEvenIfUnableToStop); s_logger.debug("Successfully released network resources for the vm " + vm); } catch (Exception e) { s_logger.warn("Unable to release some network resources.", e); @@ -1315,10 +1316,12 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac _workDao.update(work.getId(), work); } - return stateTransitTo(vm, Event.OperationSucceeded, null); + if (!stateTransitTo(vm, Event.OperationSucceeded, null)) { + throw new CloudRuntimeException("unable to stop " + vm); + } } catch (NoTransitionException e) { s_logger.warn(e.getMessage()); - return false; + throw new CloudRuntimeException("Unable to stop " + vm); } } @@ -1358,38 +1361,35 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac } @Override - public boolean destroy(T vm, User user, Account caller) throws AgentUnavailableException, OperationTimedoutException, ConcurrentOperationException { - if (s_logger.isDebugEnabled()) { - s_logger.debug("Destroying vm " + vm); - } + public void destroy(String vmUuid) throws AgentUnavailableException, OperationTimedoutException, ConcurrentOperationException { + VMInstanceVO vm = _vmDao.findByUuid(vmUuid); if (vm == null || vm.getState() == State.Destroyed || vm.getState() == State.Expunging || vm.getRemoved() != null) { if (s_logger.isDebugEnabled()) { s_logger.debug("Unable to find vm or vm is destroyed: " + vm); } - return true; + return; } - if (!advanceStop(vm, _forceStop, user, caller)) { - s_logger.debug("Unable to stop " + vm); - return false; + if (s_logger.isDebugEnabled()) { + s_logger.debug("Destroying vm " + vm); } + advanceStop(vm, _forceStop); + if (!_vmSnapshotMgr.deleteAllVMSnapshots(vm.getId(),null)){ s_logger.debug("Unable to delete all snapshots for " + vm); - return false; + throw new CloudRuntimeException("Unable to delete vm snapshots for " + vm); } try { if (!stateTransitTo(vm, VirtualMachine.Event.DestroyRequested, vm.getHostId())) { s_logger.debug("Unable to destroy the vm because it is not in the correct state: " + vm); - return false; + throw new CloudRuntimeException("Unable to destroy " + vm); } } catch (NoTransitionException e) { s_logger.debug(e.getMessage()); - return false; + throw new CloudRuntimeException("Unable to destroy " + vm, e); } - - return true; } //list all the nics which belong to this vm and are the last nics in the subnets. @@ -1605,7 +1605,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac } catch (AgentUnavailableException e) { s_logger.error("AgentUnavailableException while cleanup on source host: " + srcHostId); } - cleanup(vmGuru, new VirtualMachineProfileImpl(vm), work, Event.AgentReportStopped, true, _accountMgr.getSystemUser(), _accountMgr.getSystemAccount()); + cleanup(vmGuru, new VirtualMachineProfileImpl(vm), work, Event.AgentReportStopped, true); return null; } } catch (OperationTimedoutException e) { @@ -1791,8 +1791,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac } catch (AgentUnavailableException e) { s_logger.error("AgentUnavailableException while cleanup on source host: " + srcHostId); } - cleanup(vmGuru, new VirtualMachineProfileImpl(vm), work, Event.AgentReportStopped, true, - _accountMgr.getSystemUser(), _accountMgr.getSystemAccount()); + cleanup(vmGuru, new VirtualMachineProfileImpl(vm), work, Event.AgentReportStopped, true); return null; } } catch (OperationTimedoutException e) { @@ -1935,8 +1934,8 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac return true; } try { - boolean result = advanceStop(vm, true, _accountMgr.getSystemUser(), _accountMgr.getSystemAccount()); - return result; + advanceStop(vm, true); + return true; } catch (ResourceUnavailableException e) { s_logger.debug("Unable to stop VM due to " + e.getMessage()); } catch (ConcurrentOperationException e) { @@ -2461,7 +2460,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac if (agentState == State.Shutdowned) { if (serverState == State.Running || serverState == State.Starting || serverState == State.Stopping) { try { - advanceStop(vm, true, _accountMgr.getSystemUser(), _accountMgr.getSystemAccount()); + advanceStop(vm, true); } catch (AgentUnavailableException e) { assert (false) : "How do we hit this with forced on?"; return null; @@ -3241,7 +3240,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac } catch (AgentUnavailableException e) { s_logger.error("AgentUnavailableException while cleanup on source host: " + srcHostId); } - cleanup(vmGuru, new VirtualMachineProfileImpl(vm), work, Event.AgentReportStopped, true, _accountMgr.getSystemUser(), _accountMgr.getSystemAccount()); + cleanup(vmGuru, new VirtualMachineProfileImpl(vm), work, Event.AgentReportStopped, true); return null; } } catch (OperationTimedoutException e) { diff --git a/server/src/com/cloud/vm/snapshot/VMSnapshotManagerImpl.java b/server/src/com/cloud/vm/snapshot/VMSnapshotManagerImpl.java index b07231896d4..5fea480e89c 100644 --- a/server/src/com/cloud/vm/snapshot/VMSnapshotManagerImpl.java +++ b/server/src/com/cloud/vm/snapshot/VMSnapshotManagerImpl.java @@ -74,7 +74,6 @@ import com.cloud.storage.dao.SnapshotDao; import com.cloud.storage.dao.VolumeDao; import com.cloud.user.Account; import com.cloud.user.AccountManager; -import com.cloud.user.UserVO; import com.cloud.user.dao.AccountDao; import com.cloud.user.dao.UserDao; import com.cloud.uservm.UserVm; @@ -664,11 +663,8 @@ public class VMSnapshotManagerImpl extends ManagerBase implements VMSnapshotMana "VM Snapshot reverting failed due to vm snapshot is not in the state of Created."); } - UserVO callerUser = _userDao.findById(CallContext.current().getCallingUserId()); - UserVmVO vm = null; Long hostId = null; - Account owner = _accountDao.findById(vmSnapshotVo.getAccountId()); // start or stop VM first, if revert from stopped state to running state, or from running to stopped if(userVm.getState() == VirtualMachine.State.Stopped && vmSnapshotVo.getType() == VMSnapshot.Type.DiskAndMemory){ @@ -683,7 +679,7 @@ public class VMSnapshotManagerImpl extends ManagerBase implements VMSnapshotMana }else { if(userVm.getState() == VirtualMachine.State.Running && vmSnapshotVo.getType() == VMSnapshot.Type.Disk){ try { - _itMgr.advanceStop(userVm, true, callerUser, owner); + _itMgr.advanceStop(userVm.getUuid(), true); } catch (Exception e) { s_logger.error("Stop VM " + userVm.getInstanceName() + " before reverting failed due to " + e.getMessage()); throw new CloudRuntimeException(e.getMessage()); diff --git a/server/test/com/cloud/vm/UserVmManagerTest.java b/server/test/com/cloud/vm/UserVmManagerTest.java index 6b0f688a1e1..36ec9350881 100755 --- a/server/test/com/cloud/vm/UserVmManagerTest.java +++ b/server/test/com/cloud/vm/UserVmManagerTest.java @@ -197,7 +197,6 @@ public class UserVmManagerTest { when(_rootVols.get(eq(0))).thenReturn(_volumeMock); doReturn(3L).when(_volumeMock).getTemplateId(); when(_templateDao.findById(anyLong())).thenReturn(_templateMock); - when(_itMgr.stop(_vmMock, _userMock, _account)).thenReturn(true); when(_storageMgr.allocateDuplicateVolume(_volumeMock, null)).thenReturn(_volumeMock); doNothing().when(_volsDao).attachVolume(anyLong(), anyLong(), anyLong()); when(_volumeMock.getId()).thenReturn(3L); @@ -230,7 +229,6 @@ public class UserVmManagerTest { doReturn(ImageFormat.VHD).when(_templateMock).getFormat(); when(_templateDao.findById(anyLong())).thenReturn(_templateMock); doNothing().when(_accountMgr).checkAccess(_account, null, true, _templateMock); - when(_itMgr.stop(_vmMock, _userMock, _account)).thenReturn(true); when(_storageMgr.allocateDuplicateVolume(_volumeMock, 14L)).thenReturn(_volumeMock); when(_templateMock.getGuestOSId()).thenReturn(5L); doNothing().when(_vmMock).setGuestOSId(anyLong()); @@ -269,7 +267,6 @@ public class UserVmManagerTest { doReturn(ImageFormat.ISO).when(_templateMock).getFormat(); when(_templateDao.findById(anyLong())).thenReturn(_templateMock); doNothing().when(_accountMgr).checkAccess(_account, null, true, _templateMock); - when(_itMgr.stop(_vmMock, _userMock, _account)).thenReturn(true); when(_storageMgr.allocateDuplicateVolume(_volumeMock, null)).thenReturn(_volumeMock); doNothing().when(_vmMock).setIsoId(14L); when(_templateMock.getGuestOSId()).thenReturn(5L); From 51377c40f291b94a18b55ffa2c86a626f9ee3fde Mon Sep 17 00:00:00 2001 From: Alex Huang Date: Mon, 22 Jul 2013 20:05:50 -0700 Subject: [PATCH 59/74] Forgot to populate a method to called advanceStop --- server/src/com/cloud/vm/VirtualMachineManagerImpl.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java index 88fb41d1017..c8210b20e98 100755 --- a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java +++ b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java @@ -1140,6 +1140,9 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac @Override public void advanceStop(String vmUuid, boolean cleanUpEvenIfUnableToStop) throws AgentUnavailableException, OperationTimedoutException, ConcurrentOperationException { + VMInstanceVO vm = _vmDao.findByUuid(vmUuid); + + advanceStop(vm, cleanUpEvenIfUnableToStop); } private void advanceStop(VMInstanceVO vm, boolean cleanUpEvenIfUnableToStop) throws AgentUnavailableException, OperationTimedoutException, ConcurrentOperationException { From 7dec27e84479bf89cc13cb4121bf5f864a58c689 Mon Sep 17 00:00:00 2001 From: Devdeep Singh Date: Mon, 22 Jul 2013 15:46:43 +0530 Subject: [PATCH 60/74] CLOUDSTACK-3708, Migration of a volume attached to a running instance isn't working (Storage motion). The request to migrate was coming till ancient data motion strategy but wasn't worked on and forwarded to the resource. The code probably got removed by a bad merge. Bringing it back. --- .../motion/AncientDataMotionStrategy.java | 34 ++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/engine/storage/datamotion/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java b/engine/storage/datamotion/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java index 00c693f0b57..e17306a2b9c 100644 --- a/engine/storage/datamotion/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java +++ b/engine/storage/datamotion/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java @@ -49,6 +49,8 @@ import org.apache.log4j.Logger; import org.springframework.stereotype.Component; import com.cloud.agent.api.Answer; +import com.cloud.agent.api.storage.MigrateVolumeAnswer; +import com.cloud.agent.api.storage.MigrateVolumeCommand; import com.cloud.agent.api.to.DataObjectType; import com.cloud.agent.api.to.DataStoreTO; import com.cloud.agent.api.to.DataTO; @@ -64,6 +66,7 @@ import com.cloud.storage.DataStoreRole; import com.cloud.storage.StorageManager; import com.cloud.storage.StoragePool; import com.cloud.storage.VolumeManager; +import com.cloud.storage.VolumeVO; import com.cloud.storage.dao.DiskOfferingDao; import com.cloud.storage.dao.SnapshotDao; import com.cloud.storage.dao.VMTemplateDao; @@ -330,6 +333,30 @@ public class AncientDataMotionStrategy implements DataMotionStrategy { } + protected Answer migrateVolumeToPool(DataObject srcData, DataObject destData) { + VolumeInfo volume = (VolumeInfo)srcData; + StoragePool destPool = (StoragePool)this.dataStoreMgr.getDataStore(destData.getDataStore().getId(), DataStoreRole.Primary); + MigrateVolumeCommand command = new MigrateVolumeCommand(volume.getId(), volume.getPath(), destPool); + EndPoint ep = selector.select(volume.getDataStore()); + MigrateVolumeAnswer answer = (MigrateVolumeAnswer) ep.sendMessage(command); + + if (answer == null || !answer.getResult()) { + throw new CloudRuntimeException("Failed to migrate volume " + volume + " to storage pool " + destPool); + } else { + // Update the volume details after migration. + VolumeVO volumeVo = this.volDao.findById(volume.getId()); + Long oldPoolId = volume.getPoolId(); + volumeVo.setPath(answer.getVolumePath()); + volumeVo.setFolder(destPool.getPath()); + volumeVo.setPodId(destPool.getPodId()); + volumeVo.setPoolId(destPool.getId()); + volumeVo.setLastPoolId(oldPoolId); + this.volDao.update(volume.getId(), volumeVo); + } + + return answer; + } + @Override public Void copyAsync(DataObject srcData, DataObject destData, AsyncCompletionCallback callback) { Answer answer = null; @@ -347,7 +374,12 @@ public class AncientDataMotionStrategy implements DataMotionStrategy { } else if (destData.getType() == DataObjectType.VOLUME && srcData.getType() == DataObjectType.VOLUME && srcData.getDataStore().getRole() == DataStoreRole.Primary && destData.getDataStore().getRole() == DataStoreRole.Primary) { - answer = copyVolumeBetweenPools(srcData, destData); + if (srcData.getId() == destData.getId()) { + // The volume has to be migrated across storage pools. + answer = migrateVolumeToPool(srcData, destData); + } else { + answer = copyVolumeBetweenPools(srcData, destData); + } } else if (srcData.getType() == DataObjectType.SNAPSHOT && destData.getType() == DataObjectType.SNAPSHOT) { answer = copySnapshot(srcData, destData); } else { From 4585e46a35aa4064f1a3c3544d1a6c82bfab9c37 Mon Sep 17 00:00:00 2001 From: Prasanna Santhanam Date: Tue, 23 Jul 2013 11:37:41 +0530 Subject: [PATCH 61/74] CLOUDSTACK-3719: wrong declaration of random_gen call since random_gen can take an id to prepend a testcase identifier to the created cloud resource, we need to explicitly specify the size param. In vmsnapshot test create the random_data string of size (100) Signed-off-by: Prasanna Santhanam (cherry picked from commit 5bb3a56acac440b022ed6c45f97d0d85dcc94b96) --- test/integration/smoke/test_vm_snapshots.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/smoke/test_vm_snapshots.py b/test/integration/smoke/test_vm_snapshots.py index dd709828a60..b49a37c45b6 100644 --- a/test/integration/smoke/test_vm_snapshots.py +++ b/test/integration/smoke/test_vm_snapshots.py @@ -120,7 +120,7 @@ class TestVmSnapshot(cloudstackTestCase): serviceofferingid=cls.service_offering.id, mode=cls.services["mode"] ) - cls.random_data_0 = random_gen(100) + cls.random_data_0 = random_gen(size=100) cls._cleanup = [ cls.service_offering, cls.account, From f5023af29808d2d254e4b35aa6c099373345c0dc Mon Sep 17 00:00:00 2001 From: Radhika PC Date: Tue, 23 Jul 2013 11:44:18 +0530 Subject: [PATCH 62/74] CLOUDSTACK-3546, CLOUDSTACK-3548, CLOUDSTACK-3549 --- docs/en-US/changed-API-commands-4.2.xml | 1134 +++++++++++++++++++++-- docs/en-US/removed-api-4.2.xml | 144 +++ docs/en-US/whats-new.xml | 2 + 3 files changed, 1214 insertions(+), 66 deletions(-) create mode 100644 docs/en-US/removed-api-4.2.xml diff --git a/docs/en-US/changed-API-commands-4.2.xml b/docs/en-US/changed-API-commands-4.2.xml index 2dd5a3b05ea..b1008875a51 100644 --- a/docs/en-US/changed-API-commands-4.2.xml +++ b/docs/en-US/changed-API-commands-4.2.xml @@ -18,114 +18,1116 @@ specific language governing permissions and limitations under the License. --> -
+
Changed API Commands in 4.2 + + - Parameter Name + API Commands Description + + listNetworkACLs + The following new request parameters are added: aclid (optional), action + (optional), protocol (optional) + The following new response parameters are added: aclid, action, + number + + + copyTemplate + + The following new response parameters are added: isdynamicallyscalable, + sshkeyenabled + + + listRouters + + The following new response parameters are added: ip6dns1, ip6dns2, + role + + + updateConfiguration + The following new request parameters are added: accountid (optional), + clusterid (optional), storageid (optional), zoneid (optional) + The following new response parameters are added: id, scope + + + listVolumes + The following request parameter is removed: details + The following new response parameter is added: displayvolume + + + suspendProject + + The following new response parameters are added: cpuavailable, cpulimit, cputotal, + ipavailable, iplimit, iptotal, memoryavailable, memorylimit, memorytotal, + networkavailable, networklimit, networktotal, primarystorageavailable, + primarystoragelimit, primarystoragetotal, secondarystorageavailable, + secondarystoragelimit, secondarystoragetotal, snapshotavailable, snapshotlimit, + snapshottotal, templateavailable, templatelimit, templatetotal, vmavailable, vmlimit, + vmrunning, vmstopped, vmtotal, volumeavailable, volumelimit, volumetotal, + vpcavailable, vpclimit, vpctotal + + + listRemoteAccessVpns + + The following new response parameters are added: id + + + registerTemplate + The following new request parameters are added: imagestoreuuid (optional), + isdynamicallyscalable (optional), isrouting (optional) + The following new response parameters are added: isdynamicallyscalable, + sshkeyenabled + + + addTrafficMonitor + + The following response parameters are removed: privateinterface, privatezone, + publicinterface, publiczone, usageinterface, username + + + createTemplate + The following response parameters are removed: clusterid, clustername, + disksizeallocated, disksizetotal, disksizeused, ipaddress, path, podid, podname, + state, tags, type + The following new response parameters are added: account, accountid, bootable, + checksum, crossZones, details, displaytext, domain, domainid, format, hostid, + hostname, hypervisor, isdynamicallyscalable, isextractable, isfeatured, ispublic, + isready, ostypeid, ostypename, passwordenabled, project, projectid, removed, size, + sourcetemplateid, sshkeyenabled, status, templatetag, templatetype, + tags + + + listLoadBalancerRuleInstances + + The following new response parameters are added: diskioread, diskiowrite, + diskkbsread, diskkbswrite, displayvm, isdynamicallyscalable, + affinitygroup + + + migrateVolume + The following new request parameters is added: livemigrate (optional) + The following new response parameters is added: displayvolume + + + createAccount + The following new request parameters are added: accountid (optional), userid + (optional) + The following new response parameters are added: accountdetails, cpuavailable, + cpulimit, cputotal, defaultzoneid, ipavailable, iplimit, iptotal, iscleanuprequired, + isdefault, memoryavailable, memorylimit, memorytotal, name, networkavailable, + networkdomain, networklimit, networktotal, primarystorageavailable, + primarystoragelimit, primarystoragetotal, projectavailable, projectlimit, + projecttotal, receivedbytes, secondarystorageavailable, secondarystoragelimit, + secondarystoragetotal, sentbytes, snapshotavailable, snapshotlimit, snapshottotal, + templateavailable, templatelimit, templatetotal, vmavailable, vmlimit, vmrunning, + vmstopped, vmtotal, volumeavailable, volumelimit, volumetotal, vpcavailable, vpclimit, + vpctotal, user + The following parameters are removed: account, accountid, apikey, created, email, + firstname, lastname, secretkey, timezone, username + + + updatePhysicalNetwork + The following new request parameters is added: removevlan (optional) + + + + listTrafficMonitors + + The following response parameters are removed: privateinterface, privatezone, + publicinterface, publiczone, usageinterface, username + + + attachIso + + The following new response parameters are added: diskioread, diskiowrite, + diskkbsread, diskkbswrite, displayvm, isdynamicallyscalable, + affinitygroup + + + listProjects + The following new request parameters are added: cpuavailable, cpulimit, + cputotal, ipavailable, iplimit, iptotal, memoryavailable, memorylimit, memorytotal, + networkavailable, networklimit, networktotal, primarystorageavailable, + primarystoragelimit, primarystoragetotal, secondarystorageavailable, + secondarystoragelimit, secondarystoragetotal, snapshotavailable, snapshotlimit, + snapshottotal, templateavailable, templatelimit, templatetotal, vmavailable, vmlimit, + vmrunning, vmstopped, vmtotal, volumeavailable, volumelimit, volumetotal, + vpcavailable, vpclimit, vpctotal + + + enableAccount + + The following new response parameters are added: cpuavailable, cpulimit, cputotal, + isdefault, memoryavailable, memorylimit, memorytotal, primarystorageavailable, + primarystoragelimit, primarystoragetotal, secondarystorageavailable, + secondarystoragelimit, secondarystoragetotal + + + listPublicIpAddresses + + The following new response parameters are added: isportable, vmipaddress + + + + enableStorageMaintenance + + The following new response parameters are added: hypervisor, scope, + suitableformigration + + + listLoadBalancerRules + The following new request parameters is added: networkid (optional) + The following new response parameters is added: networkid + + + stopRouter + + The following new response parameters are added: ip6dns1, ip6dns2, role + + + + listClusters + + The following new response parameters are added: cpuovercommitratio, + memoryovercommitratio + + + attachVolume + + The following new response parameter is added: displayvolume + + + updateVPCOffering + The following request parameters is made mandatory: id + + + resetSSHKeyForVirtualMachine + The following new request parameter is added: keypair (required) + The following parameter is removed: name + The following new response parameters are added: diskioread, diskiowrite, + diskkbsread, diskkbswrite, displayvm, isdynamicallyscalable, + affinitygroup + + + updateCluster + The following new request parameters are added: cpuovercommitratio + (optional), memoryovercommitratio (optional) + The following new response parameters are added: cpuovercommitratio, + memoryovercommitratio + + + listPrivateGateways + The following new response parameters are added: aclid, sourcenatsupported + + + + ldapConfig + The following new request parameters are added: listall (optional) + The following parameters has been made optional: searchbase, hostname, + queryfilter + The following new response parameter is added: ssl + + + listTemplates + + The following new response parameters are added: isdynamicallyscalable, + sshkeyenabled + + + listNetworks + + The following new response parameters are added: aclid, displaynetwork, ip6cidr, + ip6gateway, ispersistent, networkcidr, reservediprange + + + restartNetwork + + The following new response parameters are added: isportable, vmipaddress + + + + prepareTemplate + + The following new response parameters are added: isdynamicallyscalable, + sshkeyenabled + + + rebootVirtualMachine + + The following new response parameters are added: diskioread, diskiowrite, + diskkbsread, diskkbswrite, displayvm, isdynamicallyscalable, + affinitygroup + + + changeServiceForRouter + The following new request parameters are added: aclid (optional), action + (optional), protocol (optional) + The following new response parameters are added: id, scope + + + updateZone + The following new request parameters are added: ip6dns1 (optional), ip6dns2 + (optional) + The following new response parameters are added: ip6dns1, ip6dns2 + + + ldapRemove + + The following new response parameters are added: ssl + + + updateServiceOffering + + The following new response parameters are added: deploymentplanner, isvolatile + + + + updateStoragePool + + The following new response parameters are added: hypervisor, scope, + suitableformigration + + + listFirewallRules + The following request parameter is removed: traffictype + The following new response parameters are added: networkid + + + updateUser + + The following new response parameters are added: iscallerchilddomain, isdefault + + + + updateProject + + The following new response parameters are added: cpuavailable, cpulimit, cputotal, + ipavailable, iplimit, iptotal, memoryavailable, memorylimit, memorytotal, + networkavailable, networklimit, networktotal, primarystorageavailable, + primarystoragelimit, primarystoragetotal, secondarystorageavailable, + secondarystoragelimit, secondarystoragetotal, snapshotavailable, snapshotlimit, + snapshottotal, templateavailable, templatelimit, templatetotal, vmavailable, vmlimit, + vmrunning, vmstopped, vmtotal, volumeavailable, volumelimit, volumetotal, + vpcavailable, vpclimit, vpctotal + + + updateTemplate + The following new request parameters are added: isdynamicallyscalable + (optional), isrouting (optional) + The following new response parameters are added: isdynamicallyscalable, + sshkeyenabled + + + disableUser + + The following new response parameters are added: iscallerchilddomain, isdefault + + + + activateProject + + The following new response parameters are added: cpuavailable, cpulimit, cputotal, + ipavailable, iplimit, iptotal, memoryavailable, memorylimit, memorytotal, + networkavailable, networklimit, networktotal, primarystorageavailable, + primarystoragelimit, primarystoragetotal, secondarystorageavailable, + secondarystoragelimit, secondarystoragetotal, snapshotavailable, snapshotlimit, + snapshottotal, templateavailable, templatelimit, templatetotal, vmavailable, vmlimit, + vmrunning, vmstopped, vmtotal, volumeavailable, volumelimit, volumetotal, + vpcavailable, vpclimit, vpctotal + + + createNetworkACL + The following new request parameters are added: aclid (optional), action + (optional), number (optional) + The following request parameter is now optional: networkid + The following new response parameters are added: aclid, action, number + + + + enableStaticNat + The following new request parameters are added: vmguestip (optional) + + + + registerIso + The following new request parameters are added: imagestoreuuid (optional), + isdynamicallyscalable (optional) + The following new response parameters are added: isdynamicallyscalable, + sshkeyenabled + + + createIpForwardingRule + + The following new response parameter is added: vmguestip + + + resetPasswordForVirtualMachine + + The following new response parameters are added: diskioread, diskiowrite, + diskkbsread, diskkbswrite, displayvm, isdynamicallyscalable, + affinitygroup + + + createVolume + The following new request parameter is added: displayvolume (optional) + The following new response parameter is added: displayvolume + + + startRouter + + The following new response parameters are added: ip6dns1, ip6dns2, role + + + + listCapabilities + The following new response parameters are added: apilimitinterval and + apilimitmax. + See . + + + createServiceOffering + The following new request parameters are added: deploymentplanner (optional), + isvolatile (optional), serviceofferingdetails (optional). + isvolatie indicates whether the service offering includes Volatile VM capability, + which will discard the VM's root disk and create a new one on reboot. See . + The following new response parameters are added: deploymentplanner, isvolatile + + + + restoreVirtualMachine + The following request parameter is added: templateID (optional). This is used + to point to the new template ID when the base image is updated. See . + The following response parameters are added: diskioread, diskiowrite, diskkbsread, + diskkbswrite, displayvm, isdynamicallyscalable, affinitygroup + + + createNetwork + The following new request parameters are added: aclid (optional), + displaynetwork (optional), endipv6 (optional), ip6cidr (optional), ip6gateway + (optional), isolatedpvlan (optional), startipv6 (optional) + The following new response parameters are added: aclid, displaynetwork, ip6cidr, + ip6gateway, ispersistent, networkcidr, reservediprange + createVlanIpRange + The following new request parameters are added: startipv6, endipv6, + ip6gateway, ip6cidr + Changed parameters: startip (is now optional) + The following new response parameters are added: startipv6, endipv6, ip6gateway, + ip6cidr + + + CreateZone + The following new request parameters are added: ip6dns1, ip6dns2 + The following new response parameters are added: ip6dns1, ip6dns2 + + + deployVirtualMachine + The following request parameters are added: affinitygroupids (optional), + affinitygroupnames (optional), displayvm (optional), ip6address (optional) + The following request parameter is modified: iptonetworklist has a new possible + value, ipv6 + The following new response parameters are added: diskioread, diskiowrite, + diskkbsread, diskkbswrite, displayvm, isdynamicallyscalable, + affinitygroup + + - No new parameter has been added. However, the current functionality has been - extended to add guest IPs from a different subnet in shared networks in a Basic zone. - Ensure that you provide netmask and gateway if you are adding guest IPs from a - different subnet. + createNetworkOffering + + + The following request parameters are added: details (optional), + egressdefaultpolicy (optional), ispersistent (optional) + ispersistent determines if the network or network offering created or listed by + using this offering are persistent or not. + The following response parameters are added: details, egressdefaultpolicy, + ispersistent - updateResourceLimit - Added the following resource types to the resourcetype - request parameter to set the limits: + listNetworks + + + The following request parameters is added: isPersistent. + This parameter determines if the network or network offering created or listed by + using this offering are persistent or not. + + + + + listNetworkOfferings + + + The following request parameters is added: isPersistent. + This parameter determines if the network or network offering created or listed by + using this offering are persistent or not. + For listNetworkOfferings, the following response parameter has been added: + details, egressdefaultpolicy, ispersistent + + + + + addF5LoadBalancer + configureNetscalerLoadBalancer + addNetscalerLoadBalancer + listF5LoadBalancers + configureF5LoadBalancer + listNetscalerLoadBalancers + + + The following response parameter is removed: inline. + + + + + listRouters + + + For nic responses, the following fields have been added. - CPU + ip6address - RAM + ip6gateway - primary storage - - - secondary storage - - - network rate + ip6cidr - updateResourceCount - Added the following resource types to the resourcetype - request parameter to set the limits: - - - CPU - - - RAM - - - primary storage - - - secondary storage - - - network rate - - + listVirtualMachines + + + The following request parameters are added: affinitygroupid (optional), vpcid + (optional) + The following response parameters are added: diskioread, diskiowrite, diskkbsread, + diskkbswrite, displayvm, isdynamicallyscalable, affinitygroup - listResourceLimits - Added the following resource types to the resourcetype - request parameter: + listRouters + listZones + + + For DomainRouter and DataCenter response, the following fields have been + added. - CPU + ip6dns1 - RAM - - - primary storage - - - secondary storage - - - network rate + ip6dns2 + For listZones, the following optional request parameters are added: name, + networktype - UpdatePhysicalNetwork + listFirewallRules + createFirewallRule - Added the following request parameters: - - - vlan (adds a new VLAN range to the existing VLAN range) - - - removelan (removes the specified VLAN range) - - - - The removevlan and vlan parameters can be used together. If the VLAN range that - you are trying to remove is in use, the operation will not succeed. - + The following request parameter is added: traffictype (optional). + The following response parameter is added: networkid + + + + listUsageRecords + The following response parameter is added: virtualsize. + + + + + deleteIso + + + The following request parameter is removed: forced + + + + addCluster + The following request parameters are added: cpuovercommitratio (optional), + guestvswitchtype (optional), guestvswitchtype (optional), memoryovercommitratio + (optional), publicvswitchtype (optional), publicvswitchtype (optional) + See . + The following request parameters are added: cpuovercommitratio, + memoryovercommitratio + + + + updateCluster + The following request parameters are added: cpuovercommitratio, + ramovercommitratio + See . + + + + + createStoragePool + + + The following request parameters are added: hypervisor (optional), provider + (optional), scope (optional) + The following request parameters have been made mandatory: podid, clusterid + See . + The following response parameter has been added: hypervisor, scope, + suitableformigration + + + + listStoragePools + The following request parameter is added: scope (optional) + See . + The following response parameters are added: hypervisor, scope, + suitableformigration + + + + updateDiskOffering + + + The following response parameter is added: displayoffering + + + + + changeServiceForVirtualMachine + + + The following response parameter are added: diskioread, diskiowrite, diskkbsread, + diskkbswrite, displayvm, isdynamicallyscalable, affinitygroup + + + + + recoverVirtualMachine + + + The following response parameters are added: diskioread, diskiowrite, diskkbsread, + diskkbswrite, displayvm, isdynamicallyscalable, affinitygroup + + + + + listCapabilities + + + The following response parameters are added: apilimitinterval, apilimitmax + + + + + createRemoteAccessVpn + + + The following response parameters are added: id + + + + + startVirtualMachine + + + The following response parameters are added: diskioread, diskiowrite, diskkbsread, + diskkbswrite, displayvm, isdynamicallyscalable, affinitygroup + + + + + detachIso + + + The following response parameters are added: diskioread, diskiowrite, diskkbsread, + diskkbswrite, displayvm, isdynamicallyscalable, affinitygroup + + + + + updateVPC + + + The following request parameters has been made mandatory: id, name + + + + + associateIpAddress + + + The following request parameters are added: isportable (optional), regionid + (optional) + The following response parameters are added: isportable, vmipaddress + + + + + listProjectAccounts + + + The following response parameters are added: cpuavailable, cpulimit, cputotal, + ipavailable, iplimit, iptotal, memoryavailable, memorylimit, memorytotal, + networkavailable, networklimit, networktotal, primarystorageavailable, + primarystoragelimit, primarystoragetotal, secondarystorageavailable, + secondarystoragelimit, secondarystoragetotal, snapshotavailable, snapshotlimit, + snapshottotal, templateavailable, templatelimit, templatetotal, vmavailable, vmlimit, + vmrunning, vmstopped, vmtotal, volumeavailable, volumelimit, volumetotal, + vpcavailable, vpclimit, vpctotal + + + + + disableAccount + + + The following response parameters are added: cpuavailable, cpulimit, cputotal, + isdefault, memoryavailable, memorylimit, memorytotal, primarystorageavailable, + primarystoragelimit, primarystoragetotal, secondarystorageavailable, + secondarystoragelimit, secondarystoragetotal + + + + + listPortForwardingRules + + + The following response parameters are added: vmguestip + + + + + migrateVirtualMachine + + + The following response parameters are added: diskioread, diskiowrite, diskkbsread, + diskkbswrite, displayvm, isdynamicallyscalable, affinitygroup + + + + + cancelStorageMaintenance + + + The following response parameters are added: hypervisor, scope, + suitableformigration + + + + + createPortForwardingRule + + The following request parameter is added: vmguestip (optional) The + following response parameter is added: vmguestip + + + + addVpnUser + + + The following response parameter is added: state + + + + + createVPCOffering + + + The following request parameter is added: serviceproviderlist (optional) + + + + + assignVirtualMachine + + + The following response parameters are added: diskioread, diskiowrite, diskkbsread, + diskkbswrite, displayvm, isdynamicallyscalable, affinitygroup + + + + + listConditions + + + The following response parameters are added: account, counter, domain, domainid, + project, projectid, relationaloperator, threshold + Removed response parameters: name, source, value + + + + + createPrivateGateway + + + The following request parameters are added: aclid (optional), sourcenatsupported + (optional) + The following response parameters are added: aclid, sourcenatsupported + + + + + updateVirtualMachine + + + The following request parameters are added: displayvm (optional), + isdynamicallyscalable (optional) + The following response parameters are added: diskioread, diskiowrite, diskkbsread, + diskkbswrite, displayvm, isdynamicallyscalable, affinitygroup + + + + + destroyRouter + + + The following response parameters are added: ip6dns1, ip6dns2, role + + + + + listServiceOfferings + + + The following response parameters are added: deploymentplanner, isvolatile + + + + + listUsageRecords + + + The following response parameters are removed: virtualsize + + + + + createProject + + + The following response parameters are added: cpuavailable, cpulimit, cputotal, + ipavailable, iplimit, iptotal, memoryavailable, memorylimit, memorytotal, + networkavailable, networklimit, networktotal, primarystorageavailable, + primarystoragelimit, primarystoragetotal, secondarystorageavailable, + secondarystoragelimit, secondarystoragetotal, snapshotavailable, snapshotlimit, + snapshottotal, templateavailable, templatelimit, templatetotal, vmavailable, vmlimit, + vmrunning, vmstopped, vmtotal, volumeavailable, volumelimit, volumetotal, + vpcavailable, vpclimit, vpctotal + + + + + enableUser + + + The following response parameters are added: iscallerchilddomain, isdefault + + + + + + createLoadBalancerRule + + + The following response parameter is added: networkid + + + + + updateAccount + + + The following response parameters are added: cpuavailable, cpulimit, cputotal, + isdefault, memoryavailable, memorylimit, memorytotal, primarystorageavailable, + primarystoragelimit, primarystoragetotal, secondarystorageavailable, + secondarystoragelimit, secondarystoragetotal + + + + + copyIso + + + The following response parameters are added: isdynamicallyscalable, sshkeyenabled + + + + + + uploadVolume + + + The following request parameters are added: imagestoreuuid (optional), projectid + (optional + The following response parameters are added: displayvolume + + + + + createDomain + + + The following request parameter is added: domainid (optional) + + + + + stopVirtualMachine + + + The following response parameters are added: diskioread, diskiowrite, diskkbsread, + diskkbswrite, displayvm, isdynamicallyscalable, affinitygroup + + + + + listAccounts + + + The following response parameters are added: cpuavailable, cpulimit, cputotal, + isdefault, memoryavailable, memorylimit, memorytotal, primarystorageavailable, + primarystoragelimit, primarystoragetotal, secondarystorageavailable, + secondarystoragelimit, secondarystoragetotal + + + + + createSnapshot + + + The following response parameter is added: zoneid + + + + + updateIso + + + The following request parameters are added: isdynamicallyscalable (optional), + isrouting (optional) + The following response parameters are added: isdynamicallyscalable, + sshkeyenabled + + + + + listIpForwardingRules + + + The following response parameter is added: vmguestip + + + + + updateNetwork + + + The following request parameters are added: displaynetwork (optional), guestvmcidr + (optional) + The following response parameters are added: aclid, displaynetwork, ip6cidr, + ip6gateway, ispersistent, networkcidr, reservediprange + + + + + destroyVirtualMachine + + + The following response parameters are added: diskioread, diskiowrite, diskkbsread, + diskkbswrite, displayvm, isdynamicallyscalable, affinitygroup + + + + + createDiskOffering + + + The following request parameter is added: displayoffering (optional) + The following response parameter is added: displayoffering + + + + + rebootRouter + + + The following response parameters are added: ip6dns1, ip6dns2, role + + + + + listConfigurations + + + The following request parameters are added: accountid (optional), clusterid + (optional), storageid (optional), zoneid (optional) + The following response parameters are added: id, scope + + + + + createUser + + + The following request parameter is added: userid (optional) + The following response parameters are added: iscallerchilddomain, isdefault + + + + + listDiskOfferings + + + The following response parameter is added: displayoffering + + + + + detachVolume + + + The following response parameter is added: displayvolume + + + + + deleteUser + + + The following response parameters are added: displaytext, success + Removed parameters: id, account, accountid, accounttype, apikey, created, domain, + domainid, email, firstname, lastname, secretkey, state, timezone, username + + + + + listSnapshots + + + The following request parameter is added: zoneid (optional) + The following response parameter is added: zoneid + + + + + markDefaultZoneForAccount + + + The following response parameters are added: cpuavailable, cpulimit, cputotal, + isdefault, memoryavailable, memorylimit, memorytotal, primarystorageavailable, + primarystoragelimit, primarystoragetotal, secondarystorageavailable, + secondarystoragelimit, secondarystoragetotal + + + + + restartVPC + + + The following request parameters are made mandatory: id + + + + + updateHypervisorCapabilities + + + The following response parameters are added: hypervisor, hypervisorversion, + maxdatavolumeslimit, maxguestslimit, maxhostspercluster, securitygroupenabled, + storagemotionenabled + Removed parameters: cpunumber, cpuspeed, created, defaultuse, displaytext, domain, + domainid, hosttags, issystem, limitcpuuse, memory, name, networkrate, offerha, + storagetype, systemvmtype, tags + + + + + updateLoadBalancerRule + + + The following response parameter is added: networkid + + + + + listVlanIpRanges + + + The following response parameters are added: endipv6, ip6cidr, ip6gateway, + startipv6 + + + + + listHypervisorCapabilities + + + The following response parameters are added: maxdatavolumeslimit, + maxhostspercluster, storagemotionenabled + + + + + updateNetworkOffering + + + The following response parameters are added: details, egressdefaultpolicy, + ispersistent + + + + + createVirtualRouterElement + + + The following request parameters are added: providertype (optional) + + + + + listVpnUsers + + + The following response parameter is added: state + + + + + listUsers + + + The following response parameters are added: iscallerchilddomain, isdefault + + + + + + listSupportedNetworkServices + + + The following response parameter is added: provider + + + + + listIsos + + + The following response parameters are added: isdynamicallyscalable, sshkeyenabled + diff --git a/docs/en-US/removed-api-4.2.xml b/docs/en-US/removed-api-4.2.xml new file mode 100644 index 00000000000..cf4ab741cf3 --- /dev/null +++ b/docs/en-US/removed-api-4.2.xml @@ -0,0 +1,144 @@ + + +%BOOK_ENTITIES; +]> + +
+ Removed APIs + + + deleteCiscoNexusVSM (Deletes a Cisco Nexus VSM device) + + + enableCiscoNexusVSM (Enables a Cisco Nexus VSM device) + + + disableCiscoNexusVSM (Disables a Cisco Nexus VSM device) + + + listCiscoNexusVSMs (Retrieves a Cisco Nexus 1000v Virtual Switch Manager device + associated with a Cluster) + + + addBaremetalHost (Adds a new host.) + + + addExternalFirewall (Adds an external firewall appliance) + + + deleteExternalFirewall (Deletes an external firewall appliance.) + + + listExternalFirewalls (Lists external firewall appliances.) + + + addExternalLoadBalancer (Adds F5 external load balancer appliance.) + + + deleteExternalLoadBalancer (Deletes a F5 external load balancer appliance added in a + zone.) + + + listExternalLoadBalancers (Lists F5 external load balancer appliances added in a + zone.) + + + createVolumeOnFiler (Creates a volume.) + + + destroyVolumeOnFiler (Destroys a volume.) + + + listVolumesOnFiler (Lists volumes.) + + + createLunOnFiler (Creates a LUN from a pool.) + + + destroyLunOnFiler (Destroys a LUN.) + + + listLunsOnFiler (Lists LUN.) + + + associateLun (Associates a LUN with a guest IQN.) + + + dissociateLun (Dissociates a LUN.) + + + createPool (Creates a pool.) + + + deletePool (Deletes a pool.) + + + modifyPool (Modifies pool.) + + + listPools (Lists pool.) + + + addF5LoadBalancer (Adds a F5 BigIP load balancer device.) + + + configureF5LoadBalancer (Configures a F5 load balancer device.) + + + deleteF5LoadBalancer (Deletes a F5 load balancer device.) + + + listF5LoadBalancers (Lists F5 load balancer devices.) + + + listF5LoadBalancerNetworks (Lists network that are using a F5 load balancer device.) + + + + addSrxFirewall (Adds a SRX firewall device.) + + + deleteSrxFirewall (Deletes a SRX firewall device.) + + + configureSrxFirewall (Configures a SRX firewall device) + + + listSrxFirewalls (Lists SRX firewall devices in a physical network) + + + listSrxFirewallNetworks (Lists network that are using SRX firewall device) + + + addNetscalerLoadBalancer (Adds a netscaler load balancer device) + + + deleteNetscalerLoadBalancer (Deletes a netscaler load balancer device) + + + configureNetscalerLoadBalancer (Configures a netscaler load balancer device) + + + listNetscalerLoadBalancers (Lists netscaler load balancer devices) + + + listNetscalerLoadBalancerNetworks (Lists network that are using a netscaler load + balancer device) + + +
diff --git a/docs/en-US/whats-new.xml b/docs/en-US/whats-new.xml index 295b53220e1..c129c1e9ff5 100644 --- a/docs/en-US/whats-new.xml +++ b/docs/en-US/whats-new.xml @@ -25,6 +25,8 @@
What's New in the API for 4.2 + +
What's New in the API for 4.1 From 89b94bb7547e3f287c534ba5f07b69beff521aec Mon Sep 17 00:00:00 2001 From: Saksham Srivastava Date: Tue, 23 Jul 2013 13:19:23 +0530 Subject: [PATCH 63/74] CLOUDSTACK-3382. Alert should be raised if a vm is migrated from dedicated to non-dedicated resource and vice versa. Alerts are generated for VM migration between: 1) Source host is dedicated and destination host is not. 2) Source host is not dedicated and destination host is dedicated. 3) Both hosts are dedicated to different accounts/domains --- .../deploy/dao/PlannerHostReservationDao.java | 2 + .../dao/PlannerHostReservationDaoImpl.java | 15 +- .../src/com/cloud/vm/UserVmManagerImpl.java | 238 ++++++++++++++++-- 3 files changed, 236 insertions(+), 19 deletions(-) diff --git a/server/src/com/cloud/deploy/dao/PlannerHostReservationDao.java b/server/src/com/cloud/deploy/dao/PlannerHostReservationDao.java index 69118f13896..e60254b4866 100644 --- a/server/src/com/cloud/deploy/dao/PlannerHostReservationDao.java +++ b/server/src/com/cloud/deploy/dao/PlannerHostReservationDao.java @@ -27,4 +27,6 @@ public interface PlannerHostReservationDao extends GenericDao listAllReservedHosts(); + List listAllDedicatedHosts(); + } diff --git a/server/src/com/cloud/deploy/dao/PlannerHostReservationDaoImpl.java b/server/src/com/cloud/deploy/dao/PlannerHostReservationDaoImpl.java index 41e09647d7e..06cdab22fad 100644 --- a/server/src/com/cloud/deploy/dao/PlannerHostReservationDaoImpl.java +++ b/server/src/com/cloud/deploy/dao/PlannerHostReservationDaoImpl.java @@ -20,6 +20,8 @@ import java.util.List; import javax.annotation.PostConstruct; import javax.ejb.Local; + +import com.cloud.deploy.DeploymentPlanner.PlannerResourceUsage; import com.cloud.deploy.PlannerHostReservationVO; import com.cloud.utils.db.GenericDaoBase; import com.cloud.utils.db.SearchBuilder; @@ -31,6 +33,7 @@ public class PlannerHostReservationDaoImpl extends GenericDaoBase _hostIdSearch; private SearchBuilder _reservedHostSearch; + private SearchBuilder _dedicatedHostSearch;; public PlannerHostReservationDaoImpl() { @@ -45,6 +48,10 @@ public class PlannerHostReservationDaoImpl extends GenericDaoBase listAllDedicatedHosts() { + SearchCriteria sc = _dedicatedHostSearch.create(); + sc.setParameters("usage", PlannerResourceUsage.Dedicated); + return listBy(sc); + } +} \ No newline at end of file diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java b/server/src/com/cloud/vm/UserVmManagerImpl.java index ca1c2328fe2..694ef5bf1c6 100755 --- a/server/src/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/com/cloud/vm/UserVmManagerImpl.java @@ -33,9 +33,6 @@ import javax.ejb.Local; import javax.inject.Inject; import javax.naming.ConfigurationException; -import org.apache.commons.codec.binary.Base64; -import org.apache.log4j.Logger; - import org.apache.cloudstack.acl.ControlledEntity.ACLType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.affinity.AffinityGroupService; @@ -69,6 +66,8 @@ import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo; import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; import org.apache.cloudstack.storage.to.TemplateObjectTO; +import org.apache.commons.codec.binary.Base64; +import org.apache.log4j.Logger; import com.cloud.agent.AgentManager; import com.cloud.agent.api.Answer; @@ -107,6 +106,8 @@ import com.cloud.dc.dao.HostPodDao; import com.cloud.deploy.DataCenterDeployment; import com.cloud.deploy.DeployDestination; import com.cloud.deploy.DeploymentPlanner.ExcludeList; +import com.cloud.deploy.PlannerHostReservationVO; +import com.cloud.deploy.dao.PlannerHostReservationDao; import com.cloud.domain.DomainVO; import com.cloud.domain.dao.DomainDao; import com.cloud.event.ActionEvent; @@ -178,6 +179,7 @@ import com.cloud.server.ConfigurationServer; import com.cloud.server.Criteria; import com.cloud.service.ServiceOfferingVO; import com.cloud.service.dao.ServiceOfferingDao; +import com.cloud.service.dao.ServiceOfferingDetailsDao; import com.cloud.storage.DiskOfferingVO; import com.cloud.storage.GuestOSCategoryVO; import com.cloud.storage.GuestOSVO; @@ -221,6 +223,7 @@ import com.cloud.user.dao.SSHKeyPairDao; import com.cloud.user.dao.UserDao; import com.cloud.user.dao.VmDiskStatisticsDao; import com.cloud.uservm.UserVm; +import com.cloud.utils.DateUtil; import com.cloud.utils.Journal; import com.cloud.utils.NumbersUtil; import com.cloud.utils.Pair; @@ -418,11 +421,16 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir ConfigurationServer _configServer; @Inject AffinityGroupService _affinityGroupService; + @Inject + PlannerHostReservationDao _plannerHostReservationDao; + @Inject + private ServiceOfferingDetailsDao serviceOfferingDetailsDao; protected ScheduledExecutorService _executor = null; protected int _expungeInterval; protected int _expungeDelay; protected boolean _dailyOrHourly = false; + private int capacityReleaseInterval; protected String _name; protected String _instance; @@ -1424,6 +1432,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir String workers = configs.get("expunge.workers"); int wrks = NumbersUtil.parseInt(workers, 10); + capacityReleaseInterval = NumbersUtil.parseInt(_configDao.getValue(Config.CapacitySkipcountingHours.key()), 3600); String time = configs.get("expunge.interval"); _expungeInterval = NumbersUtil.parseInt(time, 86400); @@ -3833,22 +3842,9 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir + destinationHost.getResourceState()); } - HostVO srcHost = _hostDao.findById(srcHostId); - HostVO destHost = _hostDao.findById(destinationHost.getId()); - //if srcHost is dedicated and destination Host is not - if (checkIfHostIsDedicated(srcHost) && !checkIfHostIsDedicated(destHost)) { - //raise an alert - String msg = "VM is migrated on a non-dedicated host " + destinationHost.getName(); - _alertMgr.sendAlert(AlertManager.ALERT_TYPE_USERVM, vm.getDataCenterId(), vm.getPodIdToDeployIn(), msg, msg); - } - //if srcHost is non dedicated but destination Host is. - if (!checkIfHostIsDedicated(srcHost) && checkIfHostIsDedicated(destHost)) { - //raise an alert - String msg = "VM is migrated on a dedicated host " + destinationHost.getName(); - _alertMgr.sendAlert(AlertManager.ALERT_TYPE_USERVM, vm.getDataCenterId(), vm.getPodIdToDeployIn(), msg, msg); - } + checkHostsDedication(vm, srcHostId, destinationHost.getId()); - // call to core process + // call to core process DataCenterVO dcVO = _dcDao.findById(destinationHost.getDataCenterId()); HostPodVO pod = _podDao.findById(destinationHost.getPodId()); Cluster cluster = _clusterDao.findById(destinationHost.getClusterId()); @@ -3891,6 +3887,210 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir } } + private Long accountOfDedicatedHost(HostVO host) { + long hostId = host.getId(); + DedicatedResourceVO dedicatedHost = _dedicatedDao.findByHostId(hostId); + DedicatedResourceVO dedicatedClusterOfHost = _dedicatedDao.findByClusterId(host.getClusterId()); + DedicatedResourceVO dedicatedPodOfHost = _dedicatedDao.findByPodId(host.getPodId()); + if(dedicatedHost != null) { + return dedicatedHost.getAccountId(); + } + if(dedicatedClusterOfHost != null) { + return dedicatedClusterOfHost.getAccountId(); + } + if(dedicatedPodOfHost != null) { + return dedicatedPodOfHost.getAccountId(); + } + return null; + } + + private Long domainOfDedicatedHost(HostVO host) { + long hostId = host.getId(); + DedicatedResourceVO dedicatedHost = _dedicatedDao.findByHostId(hostId); + DedicatedResourceVO dedicatedClusterOfHost = _dedicatedDao.findByClusterId(host.getClusterId()); + DedicatedResourceVO dedicatedPodOfHost = _dedicatedDao.findByPodId(host.getPodId()); + if(dedicatedHost != null) { + return dedicatedHost.getDomainId(); + } + if(dedicatedClusterOfHost != null) { + return dedicatedClusterOfHost.getDomainId(); + } + if(dedicatedPodOfHost != null) { + return dedicatedPodOfHost.getDomainId(); + } + return null; + } + + public void checkHostsDedication (VMInstanceVO vm, long srcHostId, long destHostId) { + HostVO srcHost = _hostDao.findById(srcHostId); + HostVO destHost = _hostDao.findById(destHostId); + boolean srcExplDedicated = checkIfHostIsDedicated(srcHost); + boolean destExplDedicated = checkIfHostIsDedicated(destHost); + //if srcHost is explicitly dedicated and destination Host is not + if (srcExplDedicated && !destExplDedicated) { + //raise an alert + String msg = "VM is being migrated from a explicitly dedicated host " + srcHost.getName() +" to non-dedicated host " + destHost.getName(); + _alertMgr.sendAlert(AlertManager.ALERT_TYPE_USERVM, vm.getDataCenterId(), vm.getPodIdToDeployIn(), msg, msg); + s_logger.warn(msg); + } + //if srcHost is non dedicated but destination Host is explicitly dedicated + if (!srcExplDedicated && destExplDedicated) { + //raise an alert + String msg = "VM is being migrated from a non dedicated host " + srcHost.getName() + " to a explicitly dedicated host "+ destHost.getName(); + _alertMgr.sendAlert(AlertManager.ALERT_TYPE_USERVM, vm.getDataCenterId(), vm.getPodIdToDeployIn(), msg, msg); + s_logger.warn(msg); + } + + //if hosts are dedicated to different account/domains, raise an alert + if (srcExplDedicated && destExplDedicated) { + if((accountOfDedicatedHost(srcHost) != null) && (accountOfDedicatedHost(srcHost)!= accountOfDedicatedHost(destHost))) { + String msg = "VM is being migrated from host " + srcHost.getName() + " explicitly dedicated to account " + accountOfDedicatedHost(srcHost) + + " to host " + destHost.getName() + " explicitly dedicated to account " + accountOfDedicatedHost(destHost); + _alertMgr.sendAlert(AlertManager.ALERT_TYPE_USERVM, vm.getDataCenterId(), vm.getPodIdToDeployIn(), msg, msg); + s_logger.warn(msg); + } + if((domainOfDedicatedHost(srcHost) != null) && (domainOfDedicatedHost(srcHost)!= domainOfDedicatedHost(destHost))) { + String msg = "VM is being migrated from host " + srcHost.getName() + " explicitly dedicated to domain " + domainOfDedicatedHost(srcHost) + + " to host " + destHost.getName() + " explicitly dedicated to domain " + domainOfDedicatedHost(destHost); + _alertMgr.sendAlert(AlertManager.ALERT_TYPE_USERVM, vm.getDataCenterId(), vm.getPodIdToDeployIn(), msg, msg); + s_logger.warn(msg); + } + } + + // Checks for implicitly dedicated hosts + ServiceOfferingVO deployPlanner = _offeringDao.findById(vm.getServiceOfferingId()); + if(deployPlanner.getDeploymentPlanner() != null && deployPlanner.getDeploymentPlanner().equals("ImplicitDedicationPlanner")) { + //VM is deployed using implicit planner + long accountOfVm = vm.getAccountId(); + String msg = "VM of account " + accountOfVm + " with implicit deployment planner being migrated to host " + destHost.getName(); + //Get all vms on destination host + boolean emptyDestination = false; + List vmsOnDest= getVmsOnHost(destHostId); + if (vmsOnDest == null || vmsOnDest.isEmpty()) { + emptyDestination = true; + } + + if (!emptyDestination) { + //Check if vm is deployed using strict implicit planner + if(!isServiceOfferingUsingPlannerInPreferredMode(vm.getServiceOfferingId())) { + //Check if all vms on destination host are created using strict implicit mode + if(!checkIfAllVmsCreatedInStrictMode(accountOfVm, vmsOnDest)) { + msg = "VM of account " + accountOfVm + " with strict implicit deployment planner being migrated to host " + destHost.getName() + + " not having all vms strict implicitly dedicated to account " + accountOfVm; + } + } else { + //If vm is deployed using preferred implicit planner, check if all vms on destination host must be + //using implicit planner and must belong to same account + for (VMInstanceVO vmsDest : vmsOnDest) { + ServiceOfferingVO destPlanner = _offeringDao.findById(vmsDest.getServiceOfferingId()); + if (!((destPlanner.getDeploymentPlanner() != null && destPlanner.getDeploymentPlanner().equals("ImplicitDedicationPlanner")) && + vmsDest.getAccountId()==accountOfVm)) { + msg = "VM of account " + accountOfVm + " with preffered implicit deployment planner being migrated to host " + destHost.getName() + + " not having all vms implicitly dedicated to account " + accountOfVm; + } + } + } + } + _alertMgr.sendAlert(AlertManager.ALERT_TYPE_USERVM, vm.getDataCenterId(), vm.getPodIdToDeployIn(), msg, msg); + s_logger.warn(msg); + + } else { + //VM is not deployed using implicit planner, check if it migrated between dedicated hosts + List reservedHosts = _plannerHostReservationDao.listAllDedicatedHosts(); + boolean srcImplDedicated = false; + boolean destImplDedicated = false; + String msg = null; + for (PlannerHostReservationVO reservedHost : reservedHosts) { + if(reservedHost.getHostId() == srcHostId) { + srcImplDedicated = true; + } + if(reservedHost.getHostId() == destHostId) { + destImplDedicated = true; + } + } + if(srcImplDedicated) { + if(destImplDedicated){ + msg = "VM is being migrated from implicitly dedicated host " + srcHost.getName() + " to another implicitly dedicated host " + destHost.getName(); + } else { + msg = "VM is being migrated from implicitly dedicated host " + srcHost.getName() + " to shared host " + destHost.getName(); + } + _alertMgr.sendAlert(AlertManager.ALERT_TYPE_USERVM, vm.getDataCenterId(), vm.getPodIdToDeployIn(), msg, msg); + s_logger.warn(msg); + } else { + if (destImplDedicated) { + msg = "VM is being migrated from shared host " + srcHost.getName() + " to implicitly dedicated host " + destHost.getName(); + _alertMgr.sendAlert(AlertManager.ALERT_TYPE_USERVM, vm.getDataCenterId(), vm.getPodIdToDeployIn(), msg, msg); + s_logger.warn(msg); + } + } + } + } + + private List getVmsOnHost(long hostId) { + List vms = _vmInstanceDao.listUpByHostId(hostId); + List vmsByLastHostId = _vmInstanceDao.listByLastHostId(hostId); + if (vmsByLastHostId.size() > 0) { + // check if any VMs are within skip.counting.hours, if yes we have to consider the host. + for (VMInstanceVO stoppedVM : vmsByLastHostId) { + long secondsSinceLastUpdate = (DateUtil.currentGMTTime().getTime() - stoppedVM.getUpdateTime() + .getTime()) / 1000; + if (secondsSinceLastUpdate < capacityReleaseInterval) { + vms.add(stoppedVM); + } + } + } + + return vms; + } + private boolean isServiceOfferingUsingPlannerInPreferredMode(long serviceOfferingId) { + boolean preferred = false; + Map details = serviceOfferingDetailsDao.findDetails(serviceOfferingId); + if (details != null && !details.isEmpty()) { + String preferredAttribute = details.get("ImplicitDedicationMode"); + if (preferredAttribute != null && preferredAttribute.equals("Preferred")) { + preferred = true; + } + } + return preferred; + } + + private boolean checkIfAllVmsCreatedInStrictMode(Long accountId, List allVmsOnHost) { + boolean createdByImplicitStrict = true; + if (allVmsOnHost.isEmpty()) + return false; + for (VMInstanceVO vm : allVmsOnHost) { + if (!isImplicitPlannerUsedByOffering(vm.getServiceOfferingId()) || vm.getAccountId()!= accountId) { + s_logger.info("Host " + vm.getHostId() + " found to be running a vm created by a planner other" + + " than implicit, or running vms of other account"); + createdByImplicitStrict = false; + break; + } else if (isServiceOfferingUsingPlannerInPreferredMode(vm.getServiceOfferingId()) || vm.getAccountId()!= accountId) { + s_logger.info("Host " + vm.getHostId() + " found to be running a vm created by an implicit planner" + + " in preferred mode, or running vms of other account"); + createdByImplicitStrict = false; + break; + } + } + return createdByImplicitStrict; + } + + private boolean isImplicitPlannerUsedByOffering(long offeringId) { + boolean implicitPlannerUsed = false; + ServiceOfferingVO offering = _serviceOfferingDao.findByIdIncludingRemoved(offeringId); + if (offering == null) { + s_logger.error("Couldn't retrieve the offering by the given id : " + offeringId); + } else { + String plannerName = offering.getDeploymentPlanner(); + if (plannerName != null) { + if(plannerName.equals("ImplicitDedicationPlanner")) { + implicitPlannerUsed = true; + } + } + } + + return implicitPlannerUsed; + } + @Override @ActionEvent(eventType = EventTypes.EVENT_VM_MIGRATE, eventDescription = "migrating VM", async = true) public VirtualMachine migrateVirtualMachineWithVolume(Long vmId, Host destinationHost, @@ -4008,6 +4208,8 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir " migrate to this host"); } + checkHostsDedication(vm, srcHostId, destinationHost.getId()); + VMInstanceVO migratedVm = _itMgr.migrateWithStorage(vm, srcHostId, destinationHost.getId(), volToPoolObjectMap); return migratedVm; } From 821bbe06107d72b62c086c6047f7c355725293ad Mon Sep 17 00:00:00 2001 From: Prasanna Santhanam Date: Tue, 23 Jul 2013 14:04:03 +0530 Subject: [PATCH 64/74] CLOUDSTACK-3728: same issue as CLOUDSTACK-3719 Make the size explicit parameter to random_gen() for snapshot data Signed-off-by: Prasanna Santhanam (cherry picked from commit 874d59847aa6bfd12e6967891a21f1746987b566) --- test/integration/component/test_snapshots.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/integration/component/test_snapshots.py b/test/integration/component/test_snapshots.py index 18dcefd7672..7b480e57397 100644 --- a/test/integration/component/test_snapshots.py +++ b/test/integration/component/test_snapshots.py @@ -375,8 +375,8 @@ class TestSnapshots(cloudstackTestCase): #6. Mount/Attach volume to another server #7. Compare data - random_data_0 = random_gen(100) - random_data_1 = random_gen(100) + random_data_0 = random_gen(size=100) + random_data_1 = random_gen(size=100) volume = Volume.create( self.apiclient, @@ -644,8 +644,8 @@ class TestSnapshots(cloudstackTestCase): "Check list response returns a valid list" ) volume = volumes[0] - random_data_0 = random_gen(100) - random_data_1 = random_gen(100) + random_data_0 = random_gen(size=100) + random_data_1 = random_gen(size=100) try: ssh_client = self.virtual_machine.get_ssh_client() @@ -838,8 +838,8 @@ class TestSnapshots(cloudstackTestCase): #5. Login to newly created virtual machine #6. Compare data - random_data_0 = random_gen(100) - random_data_1 = random_gen(100) + random_data_0 = random_gen(size=100) + random_data_1 = random_gen(size=100) try: #Login to virtual machine From 63cf7aa8cea2439225ee50cdd04b4e621f9e4630 Mon Sep 17 00:00:00 2001 From: Prasanna Santhanam Date: Tue, 23 Jul 2013 17:59:19 +0530 Subject: [PATCH 65/74] CLOUDSTACK-3678: Multiple fixes to shared network tests - No need to cleanup offerings as they are lightweight entities - Cleanup order changed to clean accounts, networks and then the domains Signed-off-by: Prasanna Santhanam (cherry picked from commit c44fa2cc20ca137dd5524c619c32fd49d3382c86) --- .../component/test_shared_networks.py | 126 +++++++++--------- 1 file changed, 60 insertions(+), 66 deletions(-) diff --git a/test/integration/component/test_shared_networks.py b/test/integration/component/test_shared_networks.py index 8f59dfe82cb..cfe97a4838e 100644 --- a/test/integration/component/test_shared_networks.py +++ b/test/integration/component/test_shared_networks.py @@ -136,7 +136,6 @@ class Services: }, "ostype": 'CentOS 5.3 (64-bit)', # Cent OS 5.3 (64 bit) - "sleep": 90, "timeout": 10, "mode": 'advanced' } @@ -207,33 +206,35 @@ class TestSharedNetworks(cloudstackTestCase): vm.delete(self.api_client) except Exception as e: raise Exception("Warning: Exception during virtual machines cleanup : %s" % e) - + try: for project in self.cleanup_projects: project.delete(self.api_client) except Exception as e: raise Exception("Warning: Exception during project cleanup : %s" % e) - + try: for account in self.cleanup_accounts: account.delete(self.api_client) except Exception as e: raise Exception("Warning: Exception during account cleanup : %s" % e) + #Wait till all resources created are cleaned up completely and then attempt to delete domains + wait_for_cleanup(self.api_client, ["account.cleanup.interval"]) + + try: + for network in self.cleanup_networks: + network.delete(self.api_client) + except Exception: + self.debug("Network %s failed to delete. Moving on" % network.id) + pass #because domain/account deletion will get rid of the network + try: for domain in self.cleanup_domains: domain.delete(self.api_client) except Exception as e: raise Exception("Warning: Exception during domain cleanup : %s" % e) - - #Wait till all resources created are cleaned up completely and then attempt to delete Network - time.sleep(self.services["sleep"]) - - try: - for network in self.cleanup_networks: - network.delete(self.api_client) - except Exception as e: - raise Exception("Warning: Exception during network cleanup : %s" % e) + return @attr(tags=["advanced", "advancedns"]) @@ -322,9 +323,7 @@ class TestSharedNetworks(cloudstackTestCase): conservemode=False ) - self.cleanup.append(self.shared_network_offering) - - #Verify that the network offering got created + #Verify that the network offering got created list_network_offerings_response = NetworkOffering.list( self.api_client, id=self.shared_network_offering.id @@ -565,7 +564,7 @@ class TestSharedNetworks(cloudstackTestCase): # - conservemode = false # - specifyVlan = true # - specifyIpRanges = true - # 4. Enable network offering - updateNetworkOffering - state=Enabled + # 4. Create network offering - updateNetworkOffering - state=Enabled # 5. createNetwork # - name = mysharednetwork, displaytext = mysharednetwork # - vlan = 123 (say) @@ -683,8 +682,8 @@ class TestSharedNetworks(cloudstackTestCase): conservemode=False ) - self.cleanup.append(self.shared_network_offering) - + + #Verify that the network offering got created list_network_offerings_response = NetworkOffering.list( self.api_client, @@ -750,7 +749,7 @@ class TestSharedNetworks(cloudstackTestCase): ) self.cleanup_networks.append(self.network) - + list_networks_response = Network.list( self.api_client, id=self.network.id @@ -836,7 +835,7 @@ class TestSharedNetworks(cloudstackTestCase): @attr(tags=["advanced", "advancedns"]) def test_createSharedNetwork_accountSpecific(self): - """ Test Shared Networm with scope account """ + """ Test Shared Network with scope account """ # Steps, # 1. create an Admin Account - admin-XABU1 @@ -966,9 +965,7 @@ class TestSharedNetworks(cloudstackTestCase): conservemode=False ) - self.cleanup.append(self.shared_network_offering) - - #Verify that the network offering got created + #Verify that the network offering got created list_network_offerings_response = NetworkOffering.list( self.api_client, id=self.shared_network_offering.id @@ -1292,8 +1289,7 @@ class TestSharedNetworks(cloudstackTestCase): conservemode=False ) - self.cleanup.append(self.shared_network_offering) - + #Verify that the network offering got created list_network_offerings_response = NetworkOffering.list( self.api_client, @@ -1354,6 +1350,7 @@ class TestSharedNetworks(cloudstackTestCase): self.network = Network.create( self.api_client, self.services["network"], + accountid=self.domain_admin_account.name, domainid=self.dom_domain.id, networkofferingid=self.shared_network_offering.id, zoneid=self.zone.id @@ -1405,6 +1402,7 @@ class TestSharedNetworks(cloudstackTestCase): networkids=self.network.id, serviceofferingid=self.service_offering.id ) + self.cleanup_vms.append(self.domain_user_account_virtual_machine) vms = VirtualMachine.list( self.api_client, id=self.domain_user_account_virtual_machine.id, @@ -1433,6 +1431,7 @@ class TestSharedNetworks(cloudstackTestCase): networkids=self.network.id, serviceofferingid=self.service_offering.id ) + self.cleanup_vms.append(self.domain_admin_account_virtual_machine) vms = VirtualMachine.list( self.api_client, id=self.domain_admin_account_virtual_machine.id, @@ -1612,8 +1611,7 @@ class TestSharedNetworks(cloudstackTestCase): conservemode=False ) - self.cleanup.append(self.shared_network_offering) - + #Verify that the network offering got created list_network_offerings_response = NetworkOffering.list( self.api_client, @@ -1836,8 +1834,7 @@ class TestSharedNetworks(cloudstackTestCase): conservemode=False ) - self.cleanup.append(self.shared_network_offering) - + #Verify that the network offering got created list_network_offerings_response = NetworkOffering.list( self.api_client, @@ -1996,8 +1993,7 @@ class TestSharedNetworks(cloudstackTestCase): conservemode=False ) - self.cleanup.append(self.shared_network_offering) - + #Verify that the network offering got created list_network_offerings_response = NetworkOffering.list( self.api_client, @@ -2115,7 +2111,7 @@ class TestSharedNetworks(cloudstackTestCase): # Validations, # 1. shared networks should be created successfully # 2. a. VM should deploy successfully - # b. VM should bedeployed in both networks and have IP in both the networks + # b. VM should be deployed in both networks and have IP in both the networks #Create admin account self.admin_account = Account.create( @@ -2181,8 +2177,7 @@ class TestSharedNetworks(cloudstackTestCase): conservemode=False ) - self.cleanup.append(self.shared_network_offering) - + #Verify that the network offering got created list_network_offerings_response = NetworkOffering.list( self.api_client, @@ -2377,7 +2372,7 @@ class TestSharedNetworks(cloudstackTestCase): # 2. isolated network should be created successfully # 3. # a. VM should deploy successfully - # b. VM should bedeployed in both networks and have IP in both the networks + # b. VM should be deployed in both networks and have IP in both the networks # 4. FW and PF should apply successfully, ssh into the VM should work over isolated network #Create admin account @@ -2394,7 +2389,7 @@ class TestSharedNetworks(cloudstackTestCase): list_accounts_response = Account.list( self.api_client, id=self.admin_account.id, - liistall=True + listall=True ) self.assertEqual( isinstance(list_accounts_response, list), @@ -2424,8 +2419,7 @@ class TestSharedNetworks(cloudstackTestCase): conservemode=False ) - self.cleanup.append(self.shared_network_offering) - + #Verify that the network offering got created list_network_offerings_response = NetworkOffering.list( self.api_client, @@ -2484,8 +2478,7 @@ class TestSharedNetworks(cloudstackTestCase): conservemode=False ) - self.cleanup.append(self.isolated_network_offering) - + #Update network offering state from disabled to enabled. network_offering_update_response = NetworkOffering.update( self.isolated_network_offering, @@ -2534,13 +2527,14 @@ class TestSharedNetworks(cloudstackTestCase): physical_network = list_physical_networks_response[0] - #create network using the shared network offering created + #create network using the shared network offering created self.services["network"]["acltype"] = "domain" self.services["network"]["networkofferingid"] = self.shared_network_offering.id self.services["network"]["physicalnetworkid"] = physical_network.id self.shared_network = Network.create( self.api_client, self.services["network"], + accountid=self.admin_account.name, domainid=self.admin_account.domainid, networkofferingid=self.shared_network_offering.id, zoneid=self.zone.id @@ -2597,15 +2591,16 @@ class TestSharedNetworks(cloudstackTestCase): ) self.debug("Isolated Network created: %s" % self.isolated_network.id) - - self.shared_network_admin_account_virtual_machine = VirtualMachine.create( - self.api_client, - self.services["virtual_machine"], - accountid=self.admin_account.name, - domainid=self.admin_account.domainid, - networkids=self.shared_network.id, - serviceofferingid=self.service_offering.id - ) + + self.shared_network_admin_account_virtual_machine =\ + VirtualMachine.create( + self.api_client, + self.services["virtual_machine"], + accountid=self.admin_account.name, + domainid=self.admin_account.domainid, + networkids=self.shared_network.id, + serviceofferingid=self.service_offering.id + ) vms = VirtualMachine.list( self.api_client, id=self.shared_network_admin_account_virtual_machine.id, @@ -2623,16 +2618,18 @@ class TestSharedNetworks(cloudstackTestCase): ) self.debug("Virtual Machine created: %s" % self.shared_network_admin_account_virtual_machine.id) - self.assertTrue(self.shared_network_admin_account_virtual_machine.nic[0].ipaddress is not None, "ip should be assigned to running virtual machine") - - self.isolated_network_admin_account_virtual_machine = VirtualMachine.create( - self.api_client, - self.services["virtual_machine"], - accountid=self.admin_account.name, - domainid=self.admin_account.domainid, - networkids=self.isolated_network.id, - serviceofferingid=self.service_offering.id - ) + self.assertTrue(self.shared_network_admin_account_virtual_machine.nic[0].ipaddress is not None, + "ip should be assigned to running virtual machine") + + self.isolated_network_admin_account_virtual_machine = \ + VirtualMachine.create( + self.api_client, + self.services["virtual_machine"], + accountid=self.admin_account.name, + domainid=self.admin_account.domainid, + networkids=self.isolated_network.id, + serviceofferingid=self.service_offering.id + ) vms = VirtualMachine.list( self.api_client, id=self.isolated_network_admin_account_virtual_machine.id, @@ -2678,7 +2675,7 @@ class TestSharedNetworks(cloudstackTestCase): #Create Firewall rule on source NAT fw_rule = FireWallRule.create( self.api_client, - ipaddressid=self.public_ip.ipaddress, + ipaddressid=self.public_ip.ipaddress.id, protocol='TCP', cidrlist=[self.services["fw_rule"]["cidr"]], startport=self.services["fw_rule"]["startport"], @@ -2782,8 +2779,7 @@ class TestSharedNetworks(cloudstackTestCase): conservemode=False ) - self.cleanup.append(self.shared_network_offering) - + #Verify that the network offering got created list_network_offerings_response = NetworkOffering.list( self.api_client, @@ -2927,9 +2923,7 @@ class TestSharedNetworks(cloudstackTestCase): conservemode=False ) - self.cleanup.append(self.shared_network_offering) - - #Verify that the network offering got created + #Verify that the network offering got created list_network_offerings_response = NetworkOffering.list( self.api_client, id=self.shared_network_offering.id From 3e6e66fee1bf73844e0ab7158e18f038aac7071d Mon Sep 17 00:00:00 2001 From: Sanjay Tripathi Date: Mon, 22 Jul 2013 20:41:34 +0530 Subject: [PATCH 66/74] CLOUDSTACK-3689: Test case test_accounts.TesttemplateHierarchy.test_01_template_hierarchy failed during ListTemplate call. Signed-off-by: Prasanna Santhanam (cherry picked from commit 6b2c9bf3ae1653693381431ed2554e7b7e4dfae4) --- test/integration/component/test_accounts.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/test/integration/component/test_accounts.py b/test/integration/component/test_accounts.py index 3c284bd0fcd..92f7a6fa8b9 100644 --- a/test/integration/component/test_accounts.py +++ b/test/integration/component/test_accounts.py @@ -876,10 +876,17 @@ class TestTemplateHierarchy(cloudstackTestCase): account=cls.account_1.name, domainid=cls.domain_1.id ) + + # Wait for template to download + cls.template.download(cls.api_client) + + # Wait for template status to be changed across + time.sleep(60) + cls._cleanup = [ cls.account_2, cls.domain_2, - cls.template, + cls.template, cls.account_1, cls.domain_1, ] @@ -945,7 +952,8 @@ class TestTemplateHierarchy(cloudstackTestCase): # Verify private service offering is not visible to other domain templates = list_templates( self.apiclient, - templatefilter='self', + id=self.template.id, + templatefilter='all', account=self.account_2.name, domainid=self.domain_2.id ) From 7e8722137271a89c475b73ba98a3d2157ab29f10 Mon Sep 17 00:00:00 2001 From: Likitha Shetty Date: Tue, 23 Jul 2013 17:17:32 +0530 Subject: [PATCH 67/74] CLOUDSTACK-3526. When volume upload is in progress the state of the volume is UploadError. Update volume_view to join volumes table with volume_store_ref table instead of volume_host_ref table. --- .../api/query/dao/VolumeJoinDaoImpl.java | 4 +- .../com/cloud/api/query/vo/VolumeJoinVO.java | 34 ++--- setup/db/db/schema-410to420.sql | 123 +----------------- 3 files changed, 21 insertions(+), 140 deletions(-) diff --git a/server/src/com/cloud/api/query/dao/VolumeJoinDaoImpl.java b/server/src/com/cloud/api/query/dao/VolumeJoinDaoImpl.java index 90bb8c05dae..c9dc5aad419 100644 --- a/server/src/com/cloud/api/query/dao/VolumeJoinDaoImpl.java +++ b/server/src/com/cloud/api/query/dao/VolumeJoinDaoImpl.java @@ -111,8 +111,8 @@ public class VolumeJoinDaoImpl extends GenericDaoBase implem // com.cloud.storage.VolumeHostVO volumeHostRef = // ApiDBUtils.findVolumeHostRef(volume.getId(), // volume.getDataCenterId()); - volResponse.setSize(volume.getVolumeHostSize()); - volResponse.setCreated(volume.getVolumeHostCreated()); + volResponse.setSize(volume.getVolumeStoreSize()); + volResponse.setCreated(volume.getCreatedOnStore()); if (caller.getType() == Account.ACCOUNT_TYPE_ADMIN || caller.getType() == Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN) volResponse.setHypervisor(ApiDBUtils.getHypervisorTypeFromFormat(volume.getFormat()).toString()); diff --git a/server/src/com/cloud/api/query/vo/VolumeJoinVO.java b/server/src/com/cloud/api/query/vo/VolumeJoinVO.java index 701e195461d..c7b43ba1569 100644 --- a/server/src/com/cloud/api/query/vo/VolumeJoinVO.java +++ b/server/src/com/cloud/api/query/vo/VolumeJoinVO.java @@ -144,11 +144,11 @@ public class VolumeJoinVO extends BaseViewVO implements ControlledViewEntity { @Enumerated(value=EnumType.STRING) protected VirtualMachine.Type vmType; - @Column (name="volume_host_size") - private long volumeHostSize; + @Column(name = "volume_store_size") + private long volumeStoreSize; - @Column(name="volume_host_created") - private Date volumeHostCreated; + @Column(name = "created_on_store") + private Date createdOnStore; @Column(name="format") private Storage.ImageFormat format; @@ -625,32 +625,22 @@ public class VolumeJoinVO extends BaseViewVO implements ControlledViewEntity { this.vmType = vmType; } - - - public long getVolumeHostSize() { - return volumeHostSize; + public long getVolumeStoreSize() { + return volumeStoreSize; } - - - public void setVolumeHostSize(long volumeHostSize) { - this.volumeHostSize = volumeHostSize; + public void setVolumeStoreSize(long volumeStoreSize) { + this.volumeStoreSize = volumeStoreSize; } - - - public Date getVolumeHostCreated() { - return volumeHostCreated; + public Date getCreatedOnStore() { + return createdOnStore; } - - - public void setVolumeHostCreated(Date volumeHostCreated) { - this.volumeHostCreated = volumeHostCreated; + public void setCreatedOnStore(Date createdOnStore) { + this.createdOnStore = createdOnStore; } - - public Storage.ImageFormat getFormat() { return format; } diff --git a/setup/db/db/schema-410to420.sql b/setup/db/db/schema-410to420.sql index 8eea6f3cd09..664e9b0b2de 100644 --- a/setup/db/db/schema-410to420.sql +++ b/setup/db/db/schema-410to420.sql @@ -892,114 +892,6 @@ CREATE VIEW `cloud`.`host_view` AS and async_job.instance_type = 'Host' and async_job.job_status = 0; -DROP VIEW IF EXISTS `cloud`.`volume_view`; -CREATE VIEW `cloud`.`volume_view` AS - select - volumes.id, - volumes.uuid, - volumes.name, - volumes.device_id, - volumes.volume_type, - volumes.size, - volumes.min_iops, - volumes.max_iops, - volumes.created, - volumes.state, - volumes.attached, - volumes.removed, - volumes.pod_id, - account.id account_id, - account.uuid account_uuid, - account.account_name account_name, - account.type account_type, - domain.id domain_id, - domain.uuid domain_uuid, - domain.name domain_name, - domain.path domain_path, - projects.id project_id, - projects.uuid project_uuid, - projects.name project_name, - data_center.id data_center_id, - data_center.uuid data_center_uuid, - data_center.name data_center_name, - data_center.networktype data_center_type, - vm_instance.id vm_id, - vm_instance.uuid vm_uuid, - vm_instance.name vm_name, - vm_instance.state vm_state, - vm_instance.vm_type, - user_vm.display_name vm_display_name, - volume_host_ref.size volume_host_size, - volume_host_ref.created volume_host_created, - volume_host_ref.format, - volume_host_ref.download_pct, - volume_host_ref.download_state, - volume_host_ref.error_str, - disk_offering.id disk_offering_id, - disk_offering.uuid disk_offering_uuid, - disk_offering.name disk_offering_name, - disk_offering.display_text disk_offering_display_text, - disk_offering.use_local_storage, - disk_offering.system_use, - disk_offering.bytes_read_rate, - disk_offering.bytes_write_rate, - disk_offering.iops_read_rate, - disk_offering.iops_write_rate, - storage_pool.id pool_id, - storage_pool.uuid pool_uuid, - storage_pool.name pool_name, - cluster.hypervisor_type, - vm_template.id template_id, - vm_template.uuid template_uuid, - vm_template.extractable, - vm_template.type template_type, - resource_tags.id tag_id, - resource_tags.uuid tag_uuid, - resource_tags.key tag_key, - resource_tags.value tag_value, - resource_tags.domain_id tag_domain_id, - resource_tags.account_id tag_account_id, - resource_tags.resource_id tag_resource_id, - resource_tags.resource_uuid tag_resource_uuid, - resource_tags.resource_type tag_resource_type, - resource_tags.customer tag_customer, - async_job.id job_id, - async_job.uuid job_uuid, - async_job.job_status job_status, - async_job.account_id job_account_id - from - `cloud`.`volumes` - inner join - `cloud`.`account` ON volumes.account_id = account.id - inner join - `cloud`.`domain` ON volumes.domain_id = domain.id - left join - `cloud`.`projects` ON projects.project_account_id = account.id - left join - `cloud`.`data_center` ON volumes.data_center_id = data_center.id - left join - `cloud`.`vm_instance` ON volumes.instance_id = vm_instance.id - left join - `cloud`.`user_vm` ON user_vm.id = vm_instance.id - left join - `cloud`.`volume_host_ref` ON volumes.id = volume_host_ref.volume_id - and volumes.data_center_id = volume_host_ref.zone_id - left join - `cloud`.`disk_offering` ON volumes.disk_offering_id = disk_offering.id - left join - `cloud`.`storage_pool` ON volumes.pool_id = storage_pool.id - left join - `cloud`.`cluster` ON storage_pool.cluster_id = cluster.id - left join - `cloud`.`vm_template` ON volumes.template_id = vm_template.id - left join - `cloud`.`resource_tags` ON resource_tags.resource_id = volumes.id - and resource_tags.resource_type = 'Volume' - left join - `cloud`.`async_job` ON async_job.instance_id = volumes.id - and async_job.instance_type = 'Volume' - and async_job.job_status = 0; - DROP VIEW IF EXISTS `cloud`.`storage_pool_view`; CREATE VIEW `cloud`.`storage_pool_view` AS select @@ -1780,6 +1672,7 @@ CREATE VIEW `cloud`.`volume_view` AS volumes.removed, volumes.pod_id, volumes.display_volume, + volumes.format, account.id account_id, account.uuid account_uuid, account.account_name account_name, @@ -1801,12 +1694,11 @@ CREATE VIEW `cloud`.`volume_view` AS vm_instance.state vm_state, vm_instance.vm_type, user_vm.display_name vm_display_name, - volume_host_ref.size volume_host_size, - volume_host_ref.created volume_host_created, - volume_host_ref.format, - volume_host_ref.download_pct, - volume_host_ref.download_state, - volume_host_ref.error_str, + volume_store_ref.size volume_store_size, + volume_store_ref.download_pct, + volume_store_ref.download_state, + volume_store_ref.error_str, + volume_store_ref.created created_on_store, disk_offering.id disk_offering_id, disk_offering.uuid disk_offering_uuid, disk_offering.name disk_offering_name, @@ -1854,8 +1746,7 @@ CREATE VIEW `cloud`.`volume_view` AS left join `cloud`.`user_vm` ON user_vm.id = vm_instance.id left join - `cloud`.`volume_host_ref` ON volumes.id = volume_host_ref.volume_id - and volumes.data_center_id = volume_host_ref.zone_id + `cloud`.`volume_store_ref` ON volumes.id = volume_store_ref.volume_id left join `cloud`.`disk_offering` ON volumes.disk_offering_id = disk_offering.id left join From a7084b2dac594a5851e32be692863fb9f7b23d9d Mon Sep 17 00:00:00 2001 From: Sanjay Tripathi Date: Tue, 23 Jul 2013 18:15:07 +0530 Subject: [PATCH 68/74] CLOUDSTACK-3727: Resource Count calculation happens for deleted accounts on restart of managment server. Signed-off-by: Prasanna Santhanam --- server/src/com/cloud/server/ConfigurationServerImpl.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/src/com/cloud/server/ConfigurationServerImpl.java b/server/src/com/cloud/server/ConfigurationServerImpl.java index 9a9b1456d1d..febb6d2fe7e 100755 --- a/server/src/com/cloud/server/ConfigurationServerImpl.java +++ b/server/src/com/cloud/server/ConfigurationServerImpl.java @@ -1299,8 +1299,8 @@ public class ConfigurationServerImpl extends ManagerBase implements Configuratio @DB public void updateResourceCount() { ResourceType[] resourceTypes = Resource.ResourceType.values(); - List accounts = _accountDao.listAllIncludingRemoved(); - List domains = _domainDao.listAllIncludingRemoved(); + List accounts = _accountDao.listAll(); + List domains = _domainDao.listAll(); List domainResourceCount = _resourceCountDao.listResourceCountByOwnerType(ResourceOwnerType.Domain); List accountResourceCount = _resourceCountDao.listResourceCountByOwnerType(ResourceOwnerType.Account); From d2ce17ea73248ed92cda58df85d27c771dbfdfb3 Mon Sep 17 00:00:00 2001 From: Sowmya Krishnan Date: Tue, 23 Jul 2013 20:26:44 +0530 Subject: [PATCH 69/74] Fixed account objects CLOUDSTACK-3726 Signed-off-by: Prasanna Santhanam (cherry picked from commit 1cd435e25a36e8737d37edce1bb5da70d9b670c9) --- .../component/test_netscaler_nw_off.py | 96 +++++++++---------- 1 file changed, 48 insertions(+), 48 deletions(-) diff --git a/test/integration/component/test_netscaler_nw_off.py b/test/integration/component/test_netscaler_nw_off.py index c328f48ea64..5fd21950fe7 100644 --- a/test/integration/component/test_netscaler_nw_off.py +++ b/test/integration/component/test_netscaler_nw_off.py @@ -783,21 +783,21 @@ class TestNetScalerSharedMode(cloudstackTestCase): self.network_3 = Network.create( self.apiclient, self.services["network"], - accountid=self.account_3.account.name, - domainid=self.account_3.account.domainid, + accountid=self.account_3.name, + domainid=self.account_3.domainid, networkofferingid=self.network_offering.id, zoneid=self.zone.id ) self.debug("Created network with ID: %s" % self.network_3.id) - self.debug("Deploying VM in account: %s" % self.account_3.account.name) + self.debug("Deploying VM in account: %s" % self.account_3.name) with self.assertRaises(Exception): # Spawn an instance in that network virtual_machine_3 = VirtualMachine.create( self.apiclient, self.services["virtual_machine"], - accountid=self.account_3.account.name, - domainid=self.account_3.account.domainid, + accountid=self.account_3.name, + domainid=self.account_3.domainid, serviceofferingid=self.service_offering.id, networkids=[str(self.network_3.id)] ) @@ -857,8 +857,8 @@ class TestNetScalerSharedMode(cloudstackTestCase): self.network_offering.id) networks = Network.list( self.apiclient, - account=self.account_3.account.name, - domainid=self.account_3.account.domainid, + account=self.account_3.name, + domainid=self.account_3.domainid, zoneid=self.zone.id, listall=True ) @@ -866,19 +866,19 @@ class TestNetScalerSharedMode(cloudstackTestCase): isinstance(networks, list), True, "Network should be present for the account: %s" % - self.account_3.account.name + self.account_3.name ) self.network_3 = networks[0] self.debug("Created network with ID: %s" % self.network_3.id) - self.debug("Deploying VM in account: %s" % self.account_3.account.name) + self.debug("Deploying VM in account: %s" % self.account_3.name) # Spawn an instance in that network virtual_machine_3 = VirtualMachine.create( self.apiclient, self.services["virtual_machine"], - accountid=self.account_3.account.name, - domainid=self.account_3.account.domainid, + accountid=self.account_3.name, + domainid=self.account_3.domainid, serviceofferingid=self.service_offering.id, networkids=[str(self.network_3.id)] ) @@ -923,21 +923,21 @@ class TestNetScalerSharedMode(cloudstackTestCase): self.network_4 = Network.create( self.apiclient, self.services["network"], - accountid=self.account_4.account.name, - domainid=self.account_4.account.domainid, + accountid=self.account_4.name, + domainid=self.account_4.domainid, networkofferingid=self.network_offering.id, zoneid=self.zone.id ) self.debug("Created network with ID: %s" % self.network_4.id) - self.debug("Deploying VM in account: %s" % self.account_4.account.name) + self.debug("Deploying VM in account: %s" % self.account_4.name) # Spawn an instance in that network virtual_machine_4 = VirtualMachine.create( self.apiclient, self.services["virtual_machine"], - accountid=self.account_4.account.name, - domainid=self.account_4.account.domainid, + accountid=self.account_4.name, + domainid=self.account_4.domainid, serviceofferingid=self.service_offering.id, networkids=[str(self.network_4.id)] ) @@ -970,22 +970,22 @@ class TestNetScalerSharedMode(cloudstackTestCase): self.network_5 = Network.create( self.apiclient, self.services["network"], - accountid=self.account_5.account.name, - domainid=self.account_5.account.domainid, + accountid=self.account_5.name, + domainid=self.account_5.domainid, networkofferingid=self.network_offering.id, zoneid=self.zone.id ) self.debug("Created network with ID: %s" % self.network_5.id) - self.debug("Deploying VM in account: %s" % self.account_5.account.name) + self.debug("Deploying VM in account: %s" % self.account_5.name) with self.assertRaises(Exception): # Spawn an instance in that network virtual_machine_5 = VirtualMachine.create( self.apiclient, self.services["virtual_machine"], - accountid=self.account_5.account.name, - domainid=self.account_5.account.domainid, + accountid=self.account_5.name, + domainid=self.account_5.domainid, serviceofferingid=self.service_offering.id, networkids=[str(self.network_5.id)] ) @@ -1005,9 +1005,9 @@ class TestNetScalerSharedMode(cloudstackTestCase): # 2. Create an instance from another account # 3. Deploy instance should succeed - self.debug("Delete account: %s" % self.account_4.account.name) + self.debug("Delete account: %s" % self.account_4.name) self.account_4.delete(self.apiclient) - self.debug("Account: %s is deleted" % self.account_4.account.name) + self.debug("Account: %s is deleted" % self.account_4.name) interval = list_configurations( self.apiclient, @@ -1027,21 +1027,21 @@ class TestNetScalerSharedMode(cloudstackTestCase): self.network_5 = Network.create( self.apiclient, self.services["network"], - accountid=self.account_5.account.name, - domainid=self.account_5.account.domainid, + accountid=self.account_5.name, + domainid=self.account_5.domainid, networkofferingid=self.network_offering.id, zoneid=self.zone.id ) self.debug("Created network with ID: %s" % self.network_5.id) - self.debug("Deploying VM in account: %s" % self.account_5.account.name) + self.debug("Deploying VM in account: %s" % self.account_5.name) # Spawn an instance in that network virtual_machine_5 = VirtualMachine.create( self.apiclient, self.services["virtual_machine"], - accountid=self.account_5.account.name, - domainid=self.account_5.account.domainid, + accountid=self.account_5.name, + domainid=self.account_5.domainid, serviceofferingid=self.service_offering.id, networkids=[str(self.network_5.id)] ) @@ -1504,21 +1504,21 @@ class TestNwOffNetscaler(cloudstackTestCase): self.network_3 = Network.create( self.apiclient, self.services["network"], - accountid=self.account_3.account.name, - domainid=self.account_3.account.domainid, + accountid=self.account_3.name, + domainid=self.account_3.domainid, networkofferingid=self.network_offering_shared.id, zoneid=self.zone.id ) self.debug("Created network with ID: %s" % self.network_3.id) - self.debug("Deploying VM in account: %s" % self.account_3.account.name) + self.debug("Deploying VM in account: %s" % self.account_3.name) # Spawn an instance in that network virtual_machine_3 = VirtualMachine.create( self.apiclient, self.services["virtual_machine"], - accountid=self.account_3.account.name, - domainid=self.account_3.account.domainid, + accountid=self.account_3.name, + domainid=self.account_3.domainid, serviceofferingid=self.service_offering.id, networkids=[str(self.network_3.id)] ) @@ -1803,20 +1803,20 @@ class TestNwOffSToDUpgrade(cloudstackTestCase): self.network_3 = Network.create( self.apiclient, self.services["network"], - accountid=self.account_3.account.name, - domainid=self.account_3.account.domainid, + accountid=self.account_3.name, + domainid=self.account_3.domainid, networkofferingid=self.network_offering_dedicated.id, zoneid=self.zone.id ) self.debug("Created network with ID: %s" % self.network_3.id) - self.debug("Deploying VM in account: %s" % self.account_3.account.name) + self.debug("Deploying VM in account: %s" % self.account_3.name) # Spawn an instance in that network virtual_machine_3 = VirtualMachine.create( self.apiclient, self.services["virtual_machine"], - accountid=self.account_3.account.name, - domainid=self.account_3.account.domainid, + accountid=self.account_3.name, + domainid=self.account_3.domainid, serviceofferingid=self.service_offering.id, networkids=[str(self.network_3.id)] ) @@ -2220,20 +2220,20 @@ class TestNwOffDToSUpgrade(cloudstackTestCase): self.network_3 = Network.create( self.apiclient, self.services["network"], - accountid=self.account_3.account.name, - domainid=self.account_3.account.domainid, + accountid=self.account_3.name, + domainid=self.account_3.domainid, networkofferingid=self.network_offering_dedicated.id, zoneid=self.zone.id ) self.debug("Created network with ID: %s" % self.network_3.id) - self.debug("Deploying VM in account: %s" % self.account_3.account.name) + self.debug("Deploying VM in account: %s" % self.account_3.name) # Spawn an instance in that network virtual_machine_3 = VirtualMachine.create( self.apiclient, self.services["virtual_machine"], - accountid=self.account_3.account.name, - domainid=self.account_3.account.domainid, + accountid=self.account_3.name, + domainid=self.account_3.domainid, serviceofferingid=self.service_offering.id, networkids=[str(self.network_3.id)] ) @@ -2261,7 +2261,7 @@ class TestNwOffDToSUpgrade(cloudstackTestCase): "VM state should be running after deployment" ) - self.debug("Stopping all VMs in account: %s" % self.account_3.account.name) + self.debug("Stopping all VMs in account: %s" % self.account_3.name) virtual_machine_3.stop(self.apiclient) list_vm_response = VirtualMachine.list( @@ -2314,7 +2314,7 @@ class TestNwOffDToSUpgrade(cloudstackTestCase): self.network_offering_shared.id, "Network offering ID should match with new offering ID" ) - self.debug("Starting instances in account: %s" % self.account_3.account.name) + self.debug("Starting instances in account: %s" % self.account_3.name) virtual_machine_3.start(self.apiclient) list_vm_response = VirtualMachine.list( @@ -2346,9 +2346,9 @@ class TestNwOffDToSUpgrade(cloudstackTestCase): public_ip = PublicIPAddress.create( self.apiclient, - accountid=self.account_3.account.name, + accountid=self.account_3.name, zoneid=self.zone.id, - domainid=self.account_3.account.domainid, + domainid=self.account_3.domainid, networkid=self.network_3.id ) self.debug( @@ -2359,7 +2359,7 @@ class TestNwOffDToSUpgrade(cloudstackTestCase): self.apiclient, self.services["lbrule"], ipaddressid=public_ip.ipaddress.id, - accountid=self.account_3.account.name, + accountid=self.account_3.name, networkid=self.network_3.id ) self.debug("Created the load balancing rule for public IP: %s" % From 06484061f39f27dd3249572016e8a9adbf95851a Mon Sep 17 00:00:00 2001 From: Ian Duffy Date: Tue, 23 Jul 2013 14:13:39 +0100 Subject: [PATCH 70/74] add midterm review --- docs/en-US/gsoc-midsummer-ian.xml | 319 +++++++++++++++++- docs/en-US/gsoc-midsummer.xml | 4 +- .../images/add-ldap-configuration-failure.png | Bin 0 -> 27841 bytes docs/en-US/images/add-ldap-configuration.png | Bin 0 -> 27393 bytes .../delete-ldap-configuration-failure.png | Bin 0 -> 29262 bytes docs/en-US/images/delete-ldap.png | Bin 0 -> 27832 bytes docs/en-US/images/jenkins-pipeline.png | Bin 0 -> 29136 bytes docs/en-US/images/ldap-account-addition.png | Bin 0 -> 69225 bytes docs/en-US/images/ldap-configuration.png | Bin 0 -> 33360 bytes docs/en-US/images/ldap-global-settings.png | Bin 0 -> 31145 bytes docs/en-US/images/ldap-list-users.png | Bin 0 -> 56047 bytes docs/en-US/images/list-ldap-configuration.png | Bin 0 -> 30977 bytes 12 files changed, 317 insertions(+), 6 deletions(-) create mode 100644 docs/en-US/images/add-ldap-configuration-failure.png create mode 100644 docs/en-US/images/add-ldap-configuration.png create mode 100644 docs/en-US/images/delete-ldap-configuration-failure.png create mode 100644 docs/en-US/images/delete-ldap.png create mode 100644 docs/en-US/images/jenkins-pipeline.png create mode 100644 docs/en-US/images/ldap-account-addition.png create mode 100644 docs/en-US/images/ldap-configuration.png create mode 100644 docs/en-US/images/ldap-global-settings.png create mode 100644 docs/en-US/images/ldap-list-users.png create mode 100644 docs/en-US/images/list-ldap-configuration.png diff --git a/docs/en-US/gsoc-midsummer-ian.xml b/docs/en-US/gsoc-midsummer-ian.xml index 348418f6969..c62cdc3545e 100644 --- a/docs/en-US/gsoc-midsummer-ian.xml +++ b/docs/en-US/gsoc-midsummer-ian.xml @@ -11,9 +11,9 @@ 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 @@ -23,6 +23,317 @@ -->
- Mid-Summer Progress Updates - This section describes ... + Mid-Summer Progress Updates for Ian Duffy - "Ldap User Provisioning" + This section describes my progress with the project titled "LDAP User Provisioning". +
+ Introduction + + Progress on my project is moving along smoothly. The Cloudstack community along with my mentor Abhi have been very accomodating. Since the community bonding period communication has been consistent and the expectations have been clear. Sebastien, head mentor has given us great guidance. I have enjoyed their teaching style. I found it was a nice gradual build up starting with creating a simple document update patch to eventually submitting a new Cloudstack Plugin. + + + I am pleased with my progress on the project to date. I feel as if the goals set out in my proposal are very doable and that they should be achieved. + +
+
+ Continuous Integration with Jenkins + + In order to try deliver working solutions of good quality I felt it would be a good idea to implement a continuous integration environment using Jenkins. The idea of this would be to automatically build and test my code. This was welcomed and aided by community members greatly. + + + The pipeline for this is as follows: + + + + + + + jenkins-pipeline.png: Screenshot of the build pipeline. + + + + + + Acquire Code Base - This pulls down the latest Cloudstack codebase and builds it executing all unit tests. + + + + + Static Analysis - This runs tests on my code to ensure quality and good practice. This is being achieved with sonar source. + + + + + Integration Tests - This deploys the Cloudstack database. Brings up the Cloudstack Manager with jetty and their simulator. All checkin/integration tests are ran and then the jetty server is shutdown. + + + + + Package(Only exists on my local Jenkins) - The codebase is packaged up into an RPM and placed onto a local yum repo. If the time allows this will be used for future automated acceptance testing. + + + + + If your are interested in this I have created a screencast on youtube which walks through it: Continuous testing environment + +
+
+ Ldap Plugin implementation + + At the start of the coding stage I began to review the current LDAP implementation. This includes: + + + + + The user authenticator - This enables LDAP users to login to Cloudstack once the user exists within the internal Cloudstack database. + + + + + LDAPConfig -This allows for adding LDAP configuration. This is detailed over here: ldapConfig API reference This did not allow multiple configurations. + + + + + LDAPRemove - This allows for removing the LDAP configuration + + + + + UI features. Global settings -> LDAP configuration allowed for the addition of a single LDAP server using the LDAPConfig command and the removal of an LDAP server using the LDAPRemove command. + + + + + After reviewing this code and implementation for some time I realised that it wasn't the most maintainable code. I realised I could extend it if required. But it would involve creating more unmaintainable code and it would be messy. This goes against my own principles of developing quality. This made me make the steep but justified decision to completely redo the LDAP implementation within Cloudstack. By doing this I did expanded the scope of the project. + + + I began to research the most appropriate way of structuring this. I started of by redoing the implementation. This meant creating the following classes(Excluding DAOs): + + + + + LdapManager: Manages all LDAP connections. + + + + + LdapConfiguration: Supplies all configuration from within the Cloudstack database or defaults where required. + + + + + LdapUserManager: Handles any interaction with LDAP user information. + + + + + LdapUtils: Supplies static helpers, e.g. escape search queries, get attributes from search queries. + + + + + LdapContextFactory: Manages the creation of contexts. + + + + + LdapAuthenticator: Supplies an authenticator to Cloudstack using the LdapManager. + + + + + From this I had a solid foundation for creating API commands to allow the user to interact with an LDAP server. I went on to create the following commands: + + + + + LdapAddConfiguration - This allows for adding multiple LDAP configurations. Each configuration is just seen as a hostname and port. + + + + + + + add-ldap-configuration.png: Screenshot of API response. + + + + + + + + add-ldap-configuration-failure.png: Screenshot of API response. + + + + + + LdapDeleteConfiguration - This allows for the deletion of an LDAP configuration based on its hostname. + + + + + + + delete-ldap-configuration.png: Screenshot of API response. + + + + + + + + delete-ldap-configuration-failure.png: Screenshot of API response. + + + + + + LdapListConfiguration - This lists all of the LDAP configurations that exist within the database. + + + + + + + list-ldap-configuration.png: Screenshot of the build pipeline. + + + + + + LdapListAllUsers - This lists all the users within LDAP. + + + + + + + ldap-list-users.png: Screenshot of the build pipeline. + + + + + + Along with this global configuration options were added, this includes: + + + + + LDAP basedn: This allows the user to set the basedn for their LDAP configuration + + + + + LDAP bind password: This allows the user to set the password to use for binding to LDAP for creating the system context. If this is left blank along with bind principal then anonymous binding is used. + + + + + LDAP bind principal: This allows the user to set the principle to use for binding with LDAP for creating the system context. If this is left blank along with the bind password then anonymous binding is used. + + + + + LDAP email attribute: This sets out the attribute to use for getting the users email address. Within both OpenLDAP and ActiveDirectory this is mail. For this reason this is set to mail by default. + + + + + LDAP realname attribute: This sets out the attribute to use for getting the users realname. Within both OpenLDAP and ActiveDiretory this is cn. For this reason this is set to cn by default. + + + + + LDAP username attribute: This sets out the attribute to use for getting the users username. Within OpenLDAP this is uid and within ActiveDirectory this is samAccountName. In order to comply with posix standards this is set as uid by default. + + + + + LDAP user object: This sets out the object type of user accounts within LDAP. Within OpenLDAP this is inetOrgPerson and within ActiveDirectory this is user. Again, in order to comply with posix standards this is set as inetOrgperson by default. + + + + + With this implementation I believe it allows for a much more extendable and flexible approach. The whole implementation is abstracted from the Cloudstack codebase using the "plugin" model. This allows all of the LDAP features to be contained within one place. Along with this the implementation supplies a good foundation. A side affect of redoing the implementation allowed me to add support for multiple LDAP servers. This means failover is support, so for example, if you have a standard ActiveDirectory with primary and secondary domain controller. Both can be added to Cloudstack which will allow it to failover to either one assume one of them is down. + + + The API changes required me to update the UI interface within Cloudstack. With the improved API implementation this was easier. The Global Settings -> Ldap Configuration page has support for multiple LDAP servers however it only requires a hostname and port. All "global" ldap settings are set within the global settings page. + + + + + + + ldap-global-settings.png: Screenshot the LDAP related settings within global settings. + + + + + + + + ldap-configuration.png: Screenshot of the LDAP configuration page. + + +
+
+ Add accounts UI + + Extending the UI to allow for easy provisioning of LDAP users is currently a work in progress. At the moment I have a 'working' implementation, see below screenshot. I am in need of assistance with it and am waiting on a review to be looked at. + + + + + + + ldap-account-addition.png: Screenshot of add user screen when LDAP is enabled. + + +
+
+ Testing + + Unit tests have 92% code coverage within the LDAP Plugin. The unit tests were wrote in groovy using the spock framework. This allowed for a BDD style of of testing. + + + Integration tests have been wrote in python using the marvin test framework for Cloudstack. This test configures a LDAP server and attempts to login as an LDAP user. The plugin comes with an embedded LDAP server for testing purposes. + + Execute integration tests: + nosetests --with-marvin --marvin-config=setup/dev/local.cfg test/integration/component/test_ldap.py --loa + Start embedded LDAP server: + mvn -pl :cloud-plugin-user-authenticator-ldap ldap:run +
+
+ Conclusion + + I am very pleased with the learning outcomes of this project so far. I have been exposed to many things that my college's computer science curriculum does not cover. This includes: + + + + Usage of source control management tools(git) and dealing with code collaboration + + + Usage of a dependency manager and build tool(maven) + + + Usage of continous testing environments(jenkins) + + + Usage of an IDE(eclipse) + + + Exposure to testing, both unit and integration tests + + + Exposure to a functional programming language(groovy) + + + Exposure to web development libraries(jQuery) + + + + The experience gained from this project is invalueable and it is great that the Google Summer Of Code program exist. + +
diff --git a/docs/en-US/gsoc-midsummer.xml b/docs/en-US/gsoc-midsummer.xml index ffb031a90c7..74ca62a107e 100644 --- a/docs/en-US/gsoc-midsummer.xml +++ b/docs/en-US/gsoc-midsummer.xml @@ -11,9 +11,9 @@ 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 diff --git a/docs/en-US/images/add-ldap-configuration-failure.png b/docs/en-US/images/add-ldap-configuration-failure.png new file mode 100644 index 0000000000000000000000000000000000000000..4da295a8eb9b53024bb54d9300182ced908eb9db GIT binary patch literal 27841 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 J7fU^R@n61@;XD8U literal 0 HcmV?d00001 diff --git a/docs/en-US/images/delete-ldap-configuration-failure.png b/docs/en-US/images/delete-ldap-configuration-failure.png new file mode 100644 index 0000000000000000000000000000000000000000..b5b50e0b7e563544ac044e0ad06019da984d9fd7 GIT binary patch literal 29262 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

epQ@_{N5-eA~|Res0&C@b7HMUtI zoR*{F>s)kAkK5MHI!YyZwc>*zwV`h@%8DoaE!^xyU+;&RKVHyj$Z$&Oz!NQsw|%=o zNl$7o2bd%M0`C7~vRiiJwAz9(5_)Yv4!@Myn>Sik(r65z9NSR5$o_hOL)puPEbxWp ziB)G~jqKEdsPLUAXTxUam|WQ$Dhyw3ut6E^7weaq_;JC|PNls`J8J=Sv!PyGRQ}1zo~&*sx9oFRFus zYekR;Al+JJy*rjeolj}lujH5wrw_?&Z;biE{y%Z_#r-6Yh!Nc;C1qmSumRm=I&rIi zV$3OdsjqE)>69X{WfRD&MM9ZA+ZCB+B4r4?RMe{r+Z@~eZ(b~K3$HlNE-Y{+H|lqG z?;bnIOr6*6vND!9=TQv^htYI!+mU$qCkB#lTEu1kV?O>Js{!~q%%c1_Op5q52@Km^ zt9yccjRNd!;^G(6AXfm|`$%$SF`>#VAt*}4%67m`fSQnGuv=fgt)d|mSJG_j zqg!&XM?*u&7xl;8eHDg7t~&w$WXObX`q$KzGIRBv_W($FA=U;eUOsP~@XdE{&1bPH zv6<{Xr4Xp}3Eg^CMtt%=Al(D*V-gdL9QNl<%ac1Dn_MWrpJhR;U#B>pBF*IE+kkg? zVf%||NuGDDS$gYn2+@IDoS1tq*E^vPmxo@M@YS!oTDsygi)8z5SxQjD#M^u5sL@MX zU(Z3n*!%~){E_$M>@N{vQ?6Kz_vwTh-&Z&4cO5P0QYYjFQN7Crxbwtc2v`q?Bqc(v zFK$p(26g>2JG*HH*ZZjJrn7&v>Xmv}hjl*X`iPC?od9MZ(f07E_>Pp`PuabhTTwJ; zm0pQy7;YLFA*;%M<#&4U$j~3;{g0i?Hz@Nh;?Zl%;qI!Hx5N?TJ5{AQQ_XoTe>l;J z!+BtT*YzlQTOEA+yOfIWzboiN;>Xes(*3(dhS4yHEcgOR(H| literal 0 HcmV?d00001 diff --git a/docs/en-US/images/delete-ldap.png b/docs/en-US/images/delete-ldap.png new file mode 100644 index 0000000000000000000000000000000000000000..c97bb4c47c3eeddf91ccee1517ce526284857908 GIT binary patch literal 27832 zcmZsDWk8hO+Vy~RE8PeRNOyNCT~ZPXNOyN5DpJy2(m8aaG}7JO-Cf_-=Q-y+Kfd{) zFwWeu_Z4fcYu$cPQjkVRAwq#bAn0#iOQ=8~uvg&cIwV-|=g91w8u;spgV-B2BqXHS zWyK{3gaYzLLR8H)c`wC96Gxi(=O&-6tz*Q(Q>7QqI9NDOq4Y154MV;##^w!6WObIX zvL?dyntbUb=*atwE+JCz6&?o%^|fkZWtOhZ?LE}EVqyP)^fT1R8xwPIVXu$>@K#}Z zI$>IOCgEEFe2B)J;sOi>77`q+pU47pyp6WsrC)S!+(ISFKkp&Ehh38|JkmQlrWyV3 zn`3_Ld?`|f;`d4FFyMO>SlzNLFc4dn+zJ-<8rM-e@D4cOH6q^#VOFx?7x)y4puo1= z@A_%B5MLF^b^jfA(GZavZCu~KA3RBX-@M|9;qSZOWs_X1bJTNmkdhrmr29>6(USM< z{%J6N^+t&>#>&rkn< zuHL3~@5nPulQOME5GoJr?zN2*+IY3^RXzf=mqEY z+9ry1Lq7bD*ZWS|#`XYBl`vvgOfS$R3=i$QP=4?ATnWTS}yLUG0O>Tw9<$=jyYExL?WBDkbaiZt4h1leZ@6qSeQ$$r^Mb+-lkfCVo#3*T*ueJ^!4f zijNmi0=x9q*bxg32GYHb!U1>B>$DRs{J_I!JvZgzu4gh=Yu6Txna1zJw5;_-;(KhY zy1F`bR8L=D-`)Mapr9bMf|r-qi~g8X3JvQRo_YIG@z__V(7()6?d3adxgQ+gducqftn< zb#XZy&BYW_x-9D95XD;S3?&XH6EwH7;$&q-#=vm4v)hjUge9UPmzd1&64thiMlN*6 znLj);lbDinf3~d}`MQ1GJ|!jP_VRGiPyKP}SHQ-`MgqG@`Lrcp%EA7A|8nDkZh$$4 zXAJcdNM1pKjJ&*+r6mUo%hCBcDa(5in*3{6(vVwuWo>Qu%Y*ru8SO6;Y!(v?R8&-Z zIFjKmyA#EknVFrPQq)n~dwV3$p0%#q&%PvyxJ($kXP0t!ze(YDDNCDga3SZij8|W- zFO+tE-re8dN*CJW9H5Ldefm`}#U<>jduFBdyig#nQ!o=AG&J zpkD_1%z0$^TO}%V`~pKTkUTXy2*f{ctTk6Y>E`xOnp%$FQ6b!k_O-lxaeh9bpnGLT z#`68`u&&Mx1c{E$+}ZZ%aHtYKlTJkMdSqlI1K#e< z`R?XmS{jcXC0$u@@qYUkY%(&k)vj<87J~D0=BBFGl#v2H51xBd(E6>3I#Pp%a_Uiu z45hL0@r?Po;&(MndW}3b3j);G%^N$UIr;gosHrsuI@D}QwEWoe( zxZ^W3=4NJJbYDiy5X;H4?CiQiM;HM-fONEm$#>fy86YEQkHGI}#s;Q`O zaB`BDl~v`J9A1ryjdcbaEE~rJ>qkLPzk7Fm8bvK{9%uViC@RxOy{)6;B?}9d;Kb7D)S=hVbh<#H5FB1;R{WItOTPQJ!h6;8koE0`c?ntE;OE4GlFFulKktNlQx$4n~B$pDO!sd$I3v zbCzFGQStgkK~d4SuV2O3(NR%nD@+vS<-r%wAxoe@I6FIo3Y6!`ftA(R*a&vdlwU1h zjoW(8^=QdYiFWPSH2?wK-o>R$TFC3BvZ8{0#-&iLV0W@q*z-z>0q>o*_NTzWshJsA zh=GAYa!ShX?k+t&y%vMIt!-Iu?q;@ZTtVTV7dt!q`Po_X)e34=5xIb??dAZfP}-mY zR6sxg0h8<-p0%9Zw}1d~U0q#6L#h-7ObiUEx2+r>pqf)k`5L8qK|w(V(5de3&qH{1 zI;o(f>gW_H(IzJ+i;0V)qoWV&%+1a1?C#3S$hZpVxw`U%bjZla6qJ_MR8^4*x^oo# z2pgug96m#Xh|tAQ)6m4l#@g4-i3T7jYnTZbA@_Vm!2CecZ!jVmt?o7Ru2!Q&hn1Z@ z1gsc87Ah(#4Gj%c6AhA1D=NR3%I{M0;|Cn1%&<#X|3xyZ;irUz1PRJFGBR|`%+hb= zWn_pzs%K@bW{3yFK6wK5INRFVvRm!s<>6^>Z|C9To0y!`c>DJJV19OSF>Q!e9&sf} zt|3~w_ca5a%i+R&dpjKDy_Hq*hHagW_x4COjbiH7?yg~ex4qlhmNM8aPzi(E>>M3Q zIL)JTs*MtrqSKieGj*$w6emk`VIYa(Fgs+J#K#Z_0b1vDg~`ij$liIPj3i1I2{`u^ zMDFhHv9YoH&q}h~jqqV1zTx4Rc%faZq(YvxRaN72bIB~Ix~5%>tJi&*X<_rWPIhCf zM3tY{u2d7VUc$kke7voGu;h!l>#d1uxz%5BNee0wjxWDB%`kebAyc?_I*$&=+q*Kn z#XqpNt~dE*%uXHbvb%2Zqs!oG>XvA$$;jJIa&#mu3gP0Mb=|JG?;EVw{uBd(lAng# z7D~#n=;ISeyFpJdxp!bnljHVxHM()WA+2W5>i|T|FjD@`b^8{OcloNh)GuESoBqi= z-DXd>*=j4$3fI@y*%HA1=8jGlzuVl|(Nr{@(VWoCA^q}6wlG|o^d zR16F*PEK$i^78Uc&imT7wk+;D2lEZe%F0|^T#9Kzf*u!p(XUjIW{YLA>)lRsKu){g zDwxXJ+uQ5v&R-p`PFp%_YiomMG?uSAyauWZSeGY=7>#bH#s&tNk&(*p->0Xh>VbTB zcD?{h;S?_QAtc9yheQD!LREG2$D1fqj+q#GjkObeT?uV%qGf6{&^0RQX=Gn3bBuN5 zYRT1qZlxH_)eW+E|Ndxix&l$*qh?z1hKcFo=osB&G(J8Kfrwclb7s(r>T1JjF^*`r z^`svhA9b(WQ%6lNyg~;JtjLEN=NTz!zX4Q7N5?-P02+zs6kLS+6%|G(QI49PmX?K; zRaCl%RBAH6cNVj7lDyB>wmcU)6nlEB{ zDr@)zKo={%)o-m~7gOJ_JKH~7vbogJ=A<$jmwm(@e(cSGv*L+3JFSVz#M{d&D47rp z2@&?@p#C}C7h(1@gOIR{pjNjNy+8AMmibHe*WDVj)JEHVO`VBf*k&GKIo&uiDVr|H zB6{g!kD%XzB0DThoWz9WPm6(@vS3OYJE7M7ujiE5w62YU6Q*K%?%aQH2!%0N=q*Vi+>tNx~t zyScd;^>J)$Od@L-l;`5&;`#aco)d;9vhi=3Z_ zCt1(~FX@Ri){mkhwD~d07@5QQ25!eKC478*kU)rth*hxx(sVH!o14MG!Lw6SN3M;{ zUbl%!N#FxnCQVIE!(?5(y&=Eek4;RN%ltG!ha4RrgWAf$##UZYfr^IKE&&4(5EN84 zQ~3Kzba+pDe0*#GB}jQsRVm4UhmVJcLCDq)0Q}sX07yds+Y1U%|Wy^?XJIMt@^QVe*)ZYM7|IL1asMp|1bU%Y@Lp1a(g zw4r;tb%UxUwv#!WeKkXj9@HA)jBD-Szz*>}!b_-!bINy$PhMGBc`p7*Q&TfODG8HI zfIv0IzeKlzkB`s4rL+`BD)Qru-a2T!y}iBLjyFN5_+<@YfN;gc#AI|?TU!gdpRsUq zf^DS;l@c$+{=oF?OQ2L%U41>k7KsT7PKOFNCtPCkwBN>OC~3`~I-%$KW_Gnv#q|O_ zA$+wI;M}AeR6qD)H*LJEriNU|^9lgdU^GG%EiJc;JuTh9UD%EwNOno+2gY!Ne z1A~M{mm_}3my+ZbR;TbZe#D#pM)-VLpA27SELi^&$;1IJRkD?wf=%d{ z9Hj;=`Z<5|;o%`6sR8%y2y0Aqbe>uP*p4jW;-VsenNkJZ#BxV*Q96G5JsDqFZ1(av z-ROshhu?a^yIhY8`8hjFEcl*+UM8wq8R7q(lPdN)INdh$5VJ(?x zfZ;!V`jnSP%M^Eeb!_P9M>uQo3DKvQ-+U}DFfb6**&$O7OiWCGAnvqWTrNREK_Cd| zL~82l7e~u&>FE>@5qWv^q<*POOHM8>5a^CF>hzvM`q?V?54VR`B74nnrHsLCkuu17 z5ut-b5Z{5cNdW6tHSTmsy=4=Ef+TfyQ*tUn>;M|=bun#X$(7U>o0CHgCtAkq0P=11 z806Y8F&hJZ<+rjoR9;?QjSuw_S!I%=?4Cm8qF9ayWPiX$sFR!yQ=BdKOO!t$_iMyF zG|Pj--0LSjJ`;iy@{YS}8N00I!?ySzP?d8RD#_bQ~X z+7h~L`56ZQu*hVev<9K-FmY2*q(3?7xsfBiHL)CC1h+Rebu|SwbaHaijG@9_U>!pP z)FX+{so?dC-ynTMLT=Zh6!ktn@#b&VYc?|Q5f{8jiz9c0R>6?uOhCiL^6%-wOwNnS zoE~N8Shy|E7k-2~v`ySGCmcO~3dm2|lxDbHUR!WVb3R-s*43&+{#YS|@u5ObZus+$ zuctk{r&%|yeDN@lDLIUSYPFJ;vIMreg7nIV*{$ek!L&+xd;xP=jX)Frr%+7+tC>n( zhYb=w$L_JQGXSqa08xL-zZH_;OYuHg>jAjg#Mt=ZX1BEE?xc6UH*Waco(<3jKzxVx z0UQG_aJ&Bg{=U8tuvVD5MWqASm`EdV?9CcK`aZ+NU zK|W|`aIi4$I@;PZP?P8(QZ-b3rWbom<3wa)l_}_HRbm;RLqc}v8!o{zo}Zu7)6oqi z^9FRZ$8l=ap~At6i;MSvbe&foO|bMxm@ply#&Z88m95I?YO%1ehGu5Ia+1u;=M0+yFoKJV3&2Pdz;OLZ+_`cIt<>%ni8+1FZ_WDgM3qA- zCu~u=-34&6Roou#+yKuaB>cA*XZqw|eGapknVBgnD$3(G(oJv1fB-kEITxmEa`dVtH1m%tzWH>fI}pTe#QlN(UHQf zH_niotg+l`xcmGz>iDsykNjc(p#4vrkju?;Fy9rDE0E3b&7yMqq*Ecm@{maB7_<8O zetsCJImE-<-DG21%1$Zhhn-#s2{MG8gMZeM8pZ3lLEj(Wbn`7NDTz2mVX(hn(&7Uk zIFgb5o4oVSsB@`+e z_e2T6xiZ!4?Cf|rK*RV_^t80zKn;TYq?qXGsXQycV^zUW3hjcrk*_wBt4MyP0L{pN zA+N~ELGbz3Pq<`fXZK4VAK8kPlQVnR6yPOOnwK~z`gTcV&&R4w{Rgm*u07Avv$Nsf zMeR?Prj?eK8b4EG(-PDD`iT;wIezBtZ=;*a8e0%|q@<*Wb9JlB%YHUU2GH6HnW4Tu zG|`CqdOpXVT5!%&UQi5O_Fy0qluxH`c!HFTxW)G0ruG|;npRFssFQ_v89+P3$$eHp zv!PJ{T1l|2Zzd-`QRoIBSzB8??|=FN^+-cQgP)&&*M4?lfvy-qk}k22#9_c{~;)bBej;++b{M%w^mc|F%#aa2t>=jM|mmv$G90i_HLUfWq>ykz_N3 z2w$q(04SZYiAk4ng{lgeA%IT<1#eRKZTYv8(^H`3J+Adcfph^hh8_o{@)E$g{{H^r z!b0&v4`t=2&cW@*75n@9;5h1l0L;yKu6Bmr+_+nISr4WPo}Qkj3AnXxo-*qTsb6FlI6#&nX};-QS#pcyjbzoS2vZgr@j# z3xKwpn?KYWM0-^gXpTjVjmdpRKo1obZUJBs5Zy{ZLC42+Tf9^Dc;DbqQDyDym}e-_ zM!p^^=VD_sU?Bh@4DkgVYi>@*vla9_u-S?fSRggP_pz**^GZrOTdMqr@Vvb40Tjx~ z$r18-XoNzKfpiLVE+b-OezYpaM8KyT8XEMQ+~4M_(Z&2O)F?HW&jZNq<zd zRHpB0GkNV@7yIT`x^bc8!Pi$j?;N2l5~kmtAP0&0ZFMKe1&RGyw(W#-b7WwSR?w=y z0qFh@(SH*~-Lrm@o}Nx69hNRQ3EC-G;g*{ndZDz#rKK|Wb8|z(RnR)YUOUg%JN+|( z0O8YgF!Rh9NZBA8oDb#zZP3-x$;`?cre?KSXoN?_`%^f&R&jA~z$EI8^7g~@i)0c0F6)Bu|bDDdOM{c*T54?jO9 zDIW(wH^s&MAaQ^QyCvviW|p6oMfI>@cC_@11cL?;R|Y(=?5fPf!GVDU1O(}dRUjLH zAQZ80E(Rh>QB15A@C05G1rZU5kcFUN)6vn$4{=PoGc`8kalPl4m&|l@lyV9mq7$DS z=g$-h%vdU>@C9Auf!zUpK_4(@V`J(L3nU~5AnSen_z~zB5j{pAOP@Y{y7k^)?49nn z@yLq{Tmn$Q0L$94v$SORLpV{I@}kaN>0(g4a(@Ca!NR-64-bJbGBQpHv7r13^7Os5 zG>2#jbHs$($RP^PznbldjS=X~djMr;UC;8grpJ2m40#7u-Sfcg6i^Mr<7w1@0LV zBO?sv*4U%lz8%YDJU1K&suRBzr_Yg-vO6NcI92GuNZU}nDdAdn_ZZxhbl4r#cG2EN;ngbnR(fiiw zVsCovc9SCFkwOkm)bViw*PlWrTP0s5Kl(T3Twk@<)3g2sIa~u+2o_Qx1VV&91a2~A z0Kf<|1n2Y+TSq+wrZ{#2G^l2uaRofAUvu-X#Q9@khLkdcuIZ_!-fw8=U??C*Z3vx) zh!UVlHAo43Mp2tMief)}1vAn=-q|&pk)uT!Mc>~ik8UJ`iYk#W)~*utx&RC5Woyo- zk5M-kr0Yrn7&CqS@~;NO^x!=_JgP2X9`MUQi9jHOX~J*q$r9x*p^uSq+y=ujw;5t@VUM4`pKya|xu3687Apa>6c?==HMS_0E&?A)kiS&c zn-|Z3bTcuLlbbs^H`ljrPfWDK-A`Tz?tDq-iQs%P(Gm%p5$=) zi!4aR!`X0B!zfD!QG6~eUap?@YT=L0Qlm3<ABxqkJ8hQ}=b>-3VwZ~}3{<(BERFk1jXJFmF!+g25^90+P#0|h!NZdEh|fRy=0B*@toIx{^{?SzvWwrjg%D71-IS; zZv84o2BZZY2xNP176>z@uaaY$wJ0}pR;e*72ZtIh4j7PaO}Hn>bsAUTq6FoC`J$2! z1fk4fQ&IxYA=Ap|_j6zxyORVcbMLwjbK5Ic_#wrwWmA?p0}UbFLw3oC|CkFnhr_t3 zRz4(H#4!@+JF=~+r)V3I%l?>oJ+kNVP3`52J=Jsr}Tu0IAM@4sddjV*}xIQD<8W9}Q;zu$(( zaQyd*YJOgB{q;z|y4hq<*(U#cd_j07UD3ZE0dJ2wx`tqck}xwfiy;I3d5rD?v@y_? zIEVmzWfT@BheRYL?XIkdWev~G&l?&V4p#(Yl2glhFa3l8lwfTw8i1>WgfCLnRaN%@ zQoLgOGgAPAukbGM7zSEeTL*{H4rFry_p|Q#`KBkx&y6^^xuf3ZUiw~4aO~g(mUcc8 z)pP9B_zjGlzMZK}#NeB-n&&(eNh{(nb9h2pAo*yI3E=I<{(iBcGimck6HPl9ie4st zQ)088Rw+Zt)zvlcqkP^MBG5eWU(&qR!HQnil`6IG;MP zm5NbawT9@uGod={AV)rwVDdKNBEz|?HZ(8ECk;|iMfG_3`DDt z4g)}Ei{EiG%mALTzqhB!pbliW9;43ob_q$z=SXa3BR}Hf399x=^jjW&A(AgW0nn$k z)CMr&1_VB!haR1sNo+#V(9n)#3=qLAgi7k$`-*8`n*h_4Kzr}oeQs%KX@r2`Y+1k` zKLvrA)MMaytt7CweT3c5Jg&!rdB7;<2#pO@ZMFYTffGO|!urxU# zA>p#q&{)Kftm{|-wpI?i$p9P#>^2w?)z;U;LhzV$UT3fenIL(E^(e~9imwmGvx>`y zY4fgxzLYJIm2az|ke@#q2gBs=Zf}c~fSxFkJ1Qt30M4+tx7U1s@$O7hUtgG+IlPZO zUJ_8bwi^6al2-*xL8qMauL;EBseb!CLA12A)MSVSB82v)_=l(3&wFJ2ib4%zN46aS z8_Ue3WGG8dhcIq+cfXcHtlI0|sn*U=t+9}=yy!7~pX*}X-8&$S^@4%|@-_zw9q#Q# z6`aUEFx!#ROz9Q~z?|F*LqeZ~!cfjIeMmIvkx3})QBwO6E_Cxcj!QCk6rgcUhKa4= zti#2Y@E~lWyeeeX-K>P$1~D2mM+gJ}Rg|EWxjKg}S9tRNfdM8O8tE6$`V-iL#r6R2 z2lfgs?>pDlJ#goafY2};fsXFZ{l({%tuhS;?_k_WiDVB3?Us6?6*i*XyVW_t`gVf;ELjSNbCrDLHW*Ix zRAcfM{WK2#+Wj;*B_2W#;AO0a5qMmoH;XUXor5 z$|7bfWt!|Ue=O`bXRqX(2$+8 zv$eUo7?#9eE@VM{d3xI0*EbeD1g>&r#o+7;DD+M4=b2cq_p#-2RPx8@T6C#bsTP|& z@QFzxf-KHIG2OF0;3VJ%9v_c?VQDS@*z5gpZ2~9CWj*(KUwycMz3Ra=jaj$e5r`5< z{+^Hbm$I=8!*V5BVXi^QQM-Dhc}}Apg+|3sm=S&CQus5)ttRPWSy1J<%|At~^H@w2 zfkK{$KJ`Q+KA#6WyHv^ohPPna*-cKUP@8i5TB?2K9Td4q8kjKgE2^DJ}edP zo`%61JnP-#GfNM^8sDoh86+YgV9=?J7~E9-oWfx?0wfFY(E^oxq@dgDYao0)N3vi4 z9Rmi>*mS2mPe}1X;B8H*Cr3xIQGybmfoNE>=XGZQ64u!nEu6}2pprP-wGs8^+8P`@ zJRvbL0QIdxV$@O4Y0Dj3vGppM9G2idl;RC+V=(L?#KZeU@mfUWC!n{l9IfL_%2q2Y zE5T6qInpyQ4N6WfdL;wG)gI};%ZO7f?n2{I%e8ah`Og9p;Ndx6pM0#+ajf}VhSNR6 zlM1FIS{25iQ2RXGfi=rGw_W<_2PmJCZ1(tmVB+pbjPhs7zPwR>Zu8BkgscW@ZAr8K zII-FT^oaU~oCCPZ8>P#y62|;OM?FzA!19EH&|EKcNV_FsqQd{I(jgsSW#F`_GwOLZ z_AwAl;1m+r;6)?A3O}BWDh9TOlM9E*Afcl-*{`Eyu+^VojLm=*e&3<^8ZcHPwuBrw z&n95N12cOZ*nF?ds+6VmsD!=M)r!BSL*}?%^5fNHAa)rD`^&Xs!2rW@Oa(?PQ zwG5@H>FKv>YL43@@E%Nx7Rct~i`ymHUo4fkQ1uW#=I-*Sbx%cdtrW8le<#S z((&>e6Yn#1fb`8-0g*wwNRZQs9tAG05xr)*WBuvm4)K?w>8k+ra}0G$qKOu)(F z=2q9#BW+EhIx&VW*FHECA^ErJLqp143kmMvJoVdfnf|1NNFU*SIK7M44LP2|K(UX?0!pV(+< zB3NPIr~%UBe2b5Mh7xFX)sz3kq&dheVC^zAdR64;V2IF*uTMVeLo}L=|;Wow5U!@lO>jcB|GU<@vMhl|T{jusL(<1NBaY z;A-c_v^dm;hJspo(r+M^@tviW6$}K3TJNeYf#C$52o3^_rIJ`bfYJ+r`1ts^xVS)k z8yY--9|Z(*yj%{@OE=yYgMqr2(nNp%K5*+G`2*u47`F#VWof;82O@TUdYTZj1h_y% zgfGQsO@>bAaL}80czIzUz^yjSO_ddS4D4$w6&64}<#cp%ny)m&F8C1;5CAm197cZ% z;rp{F0QEqXys0gxM#Llor4hK|0Bqyn;_Bo=10(dGV6flWxdE&&S67L!uRPg2uWUJe z43c`0))#B-0y+%N4;S@S-vBs`iW&lH>^m(jbRrHUQ7ocRV{7X$p`C=()G$eER2nrs zRW@xzKxU3>0*r{hyCF+f@MUaZCk9Y_7NJ-=b_G_7F+Np~PpzAtLTL)Q8tUrizePX) zR_@pIJOR1y*^oYjP0r53q9k7v5rI`i1m^PbeTC*h{tsst7fi2SfvAFk0R1^SE-tGp zuQgCXit*(9{H>}UyEF>73QyWlXdrrErdL8zl0)6xE7hDl-h@`lqHq7;il<0$KzaxE z4ABVS>?I2iUP#T~_WdZWUc-q>nue0mSh+PtV@TK(Hh}IRL^J}tr0?G^?d>%h_Y+|R zV`E{Z%g&FEg%Uh4ZF z%Dgt7L1m-;q`L*dA1jVa>&hnqIH>?v12#=Z;JBs-|2`hD0E_tFZ^qY4WDYM0k^S?9 zLo!>b{~ie&vLCMdOA+p0zKjo^u=vmUwrnra|2f0|lJx(j*?t)R{yQGe&|ek~cd{TB zym%J)&l3vGuqOXU$^U!p$s64htBu`Z;o@PvT)cXf zWX-dRUM~5M3(wA37P!0?ye}}bGJH~)svY2)9Z;}NoXz3=L>?+w^exiPu-OsZ_hzSacS$fwn$O}|0%#b5G49h(IwJ&A?Hl{{oX^A@~)SCb}I$QNQ@ zD1R9K^wU5TA%@o)%`3vW*s|*!VEUx}T7BY_ke#imNs*s7g@EU%HJ0((0Q#M;XE>_^ z1_nPlSpg1ChsV1ykgr@KbFTURAzk!%V8F-CE#={Cw6Ca08{(Uy+jp{FbHsXF(Age6 zHQmwP9=$Y}=@S-4b9X;zvye;^Nt?f3XyzY8!l$-&=(EtX-R=vsiAnD5k018f_DtoL z5Z0~cJtgGlEi+EG+#8eDNOHIng-j)i(+%BsWj{^sZyLr}YiwGC&A!iW^m`Q*pYQIz z6n@lUv012E^dXnPdtB-GD(FFWFi*U-YIw3FIyzT3DJReS^y!7sF+St(jpHflFf@Bx z7E6n$`TDml9+v^>6c!K>cXxRO1@SZ?yu^Ga{SqR!cCJ_X<|8k-8OjRGpFu>JG;r~% zEvIZ<#tV|uymu6zr$w-v{0=8)=5;iU2u3{YiJG`RElofqKkPg+ z11u8YDRtDdlN0R<<51(ZiGm4f=p}h_Blqc!0Gl5QlyW;Mu+;&Rz;eU)rQek*rs85t zJ!4Z|tEEoIBc}oUsj!G^x zO|m&d8AXV%9EGel-s9ScA;fp{_2CEMFe5vyykxsz;onn^+3RLe2@M_Kuv|@+FbAFR zfn7OeyTDD)u(?daL z`xy?htpo2AOsuZm&T(?qE}YX~{S_M8!%l=UzKQPMN*un?L9(Fh^ zw&^71Ifur zKC-<%I>L{fEZ(g$=-6*>U+#-@LI2$Gdv9-MZSCoY56A{k75y|n;a-E`1{d!6CJ)d% zg8q%sEa{NRlKt&fLs($XW7TS?HgP;_gBs2XdU(;=+SG)*UrAgOO`psp;la8EY;pLp zx*X^f`;Fkec^KwrH4M8Ga@ALTCG2==i{eL^RMHJMQs;v2lPcJ9VhsPFW+r2&*0=U@ zoqqn48#M!8c#y_?NxYNc!(2m1w$%s-3)A-p5AR&O8w4rc_cU-9z3q=j3uc)mvP)&v zyKx*2nNmGAWfPQQo1eo+sp34Eo?H`#$ZEJMZh5;+OL80~byjT+!SE}gYEW5NBz|U2 zjH)ob=!e(L(ax`ZaFl87yM~vQRr#8~|8^8{)K4z$Vn#M+@SIeO(`}qxWs||PQ71e% zu9=GvU6_4eqEzvg!L`zIdo)J8295cOo*Y|DlWBiESWYNG$OtDn)Z5lu@u*y!eGs+t zF8cUx*=gsB8`Bd+6%8q4(wTI=4nwV*Exgm+Y;bc-$SgG}W=UYk;!Jn9@bk_P`r(BOmD;UG>rH%Kl!`t{getyu5O&xL zD^d*8P@il5k)>;{bXB*fJ-3xMV$#l87cAFzbKX(>^aAV2L--5;T8R#usSkG*!cH7w z-@g|ipp|8Q1}?m{!$-wHm?uSK0;ZXt7YpM$RywA+Z6>nl zx|TkC{q6-R7OY<*i~&>J?3IF8rQKS0WDidm39rAfhw+U5u-@z{elp`5x6Ekz@eyyE zY6Zp@GaeqNqts`$b&YS>Vf`uWp`H!<)N-xD$7x*qI~UmQjWwIhPMGGLqf#DCFN9}2 z_^G9p=taVDpLKBcqK~2vydA$LZ0$6UQEAduqS1KWfhfI` z)n(+okNV`}(wCI?`5DJGGLz9bTIh8-fXPNU&qu|c+Thl9OPZ;CdjxA_j{zZ4N z`V|A*c}%G(eo&g^-6r#1%$ti~b|Pt5(VL zH>}EJqliYV_u5b*Wh&+E?HkgraC7%oTlW(S@GMMUOMpT^?%j=#vL0_Rn2PM_Wms4c z==wH}q3(FrCJ4!&MBvJGdxY5hQ}=qo?d5f3W$Q@3iv3_g&1Im&%BviN}~_Q9rME50f5rc%&mc5+ig{+c``(cWV6JUZsf z-FK;27>g-PD$p0j6`#h+dYnH8lo^xIzuts8Y@xm@u5yf6o3~M^Z$xxXN0C&2PA51# zTv)Q!oZUdy;9+}z^3r=+MXP;m6@g)D9q;aG&|SSWw>8OCea2Oo7-f5~>Xg%Cp90rp zE!$>!*HFIpIjh4lc$#&WY!MErb!0V>*G0N5D0H00xOP>gW$bGmp0jyE^&}ID@NQD` zlve9|JFFOgF(lxf&`IO!eKQ^5m1;IUNU$2)8Y79nBJy8W>U&D}AyQu5?# zu5B+x3x6Z^m}Gljup~*f4AnihGoAhgilqiR#Mk2El=}Q{2NncK<=ZNQWfNgRPE)76 zuFoYTRAEK()uV3o&L|;^+T#ZAKlmb??744YBckTAZrMjBfBXpxL9&3?URRpBg_YRP6qhrZwlFe0n;vJLlCrF_MP=@N+5ot= z8p?RoRaabGhv5^_R(rEjA)}L?v*&F?zca36*z~1 z@rTSciJo*~-uBO}aM&`;`qJQ6k&<?_f%{gDtO*2 zF@ccgm04|mer%}ze0{<~{aaznsSudOP~vm&Yi8G29SZ@6jZGAIYSPsstuuHqbsv{F zDLz^)=%KIQ%G5IY;_z`$#>?7Te6cx}G`93pT-+OPZ$l*|{4*0hy{z!?SCXD=sm9TQ ze7EVe50R1@z1HLxNb@)YtP`WDXs~Xhm8;LQK7U36E^NTQ!4LfvB!+@5W=+)k@vKx< zVP7h?W8Qw5dR1sWacOvhwJt1JI(cQiy{q~{-hfpuWr7EXSA8$y`@OS38;+lMPP(9is)F+qjbqbV09-4bdg46?BlYT& z@=@nA-G7ucGZf&&d-@YoGa0BHg{n*pTgJES!Pf5%p=1I7@d9A|U*Tw8 z#m}{QtX%FPjZt}?SK58Ep1psxQ6h*EkE-KNzfxV;PD9qi zjsvCF5|j_8#J6!Dj_1XMny+V37=)_WAih_)ZFJVU-$UT(>eQH?vhXsaU!BPprOh|P z*FS8ZK6-!LH42h|t6b*WY8xpU%}&ULqVqu@ zrJo1ceNq|oJaSaJEy#^&yty~t?u`V3NP7Qn^vDP2xUhhF`SEA(>XRzOTo?!xy8iU( zmk%GDrNcj&hS_th4#qFndEckpc{b~m{2tu2nX=s+Rm`szmz31~5?%^|hA!r{QhUfG3+`2lRu z_@ON&Uv>V~N|fElx0xV3zE$!@G4~xMO`rll$|1^r($8delduUM0shp-IG6{0g!j)s z%u+J-g#yZg`OwUWs)w6+=5)7!>77$S@FWfaH`V8JCrO=$&dyG6|7fDyMdvRIvEwAY z;(N=B%TV>-F?xoc{u)7(11T5Ddkww6`6ZM1I`8r&kRpypr$Eszo$)y}F1*Mjh0>f8N$U&0!?J)i!#G z++m+&G5;}rU6-6xbyq}#MOKkvq2fJnXsHiKEnujzQW_TtVWmb^>F@dj^4c!*_B6Y z)?<;ChEIaa9ySfc_tcm5UU>0SCz?(r_iAoJo%H0XrOvHabrsL~6sn-`yeFgk!||&D zN9u;nA2z+^dDdAl5J75&9{##w=X+PafRF3rK2!BPchlbNHAZ)53ANk2IfF~@u;4xwNt=3?n!rz0MsSv zkGRFC`(Sn6v}&V`O*ck1>s^R7j_QLt({Oamwy(U%zp!EdkA?#gnf!=~BoT$`Fi%S#9Dj;dnAa@Q>P~upD!-@EB)@=J?>y{@kpvow3j1YA|cD@?Yf$$(1{{crtVE)jWyliG%t_C9}b_=@8k}Ujpn&CcnI@ zAe#qzG}YaPJt)V1n(p2)VUZ0Ec0AmId1pQp5xQ*2bnE7Q-mg0e9>iDv9qqW$Pzm?f zL<96cY{!Kz889Qfx`N(lxHUC4P84Zn5!Qhkt-N=SNOP#%7%1~x{e@SQlIsCXKtD;@ zS~jdhzDdk!oYW>N*;lHrp}Tn1R&Wmu*k~ASW8+1K z_)n&!l8X*UJ0I|Z{y$nmraPg4mS@%Fm0wGoS@(*GmHciC%TF6^W{z@Q;b5?sXpjhG zqc^=PX*%v`kRy_9!M(0X1}0Qo{(~cFKv}^SvpLidJQbYCi7Pg4o)Y+)NJJo$&vu;@ zC~XIihT*U@BC4VO(jdg~D*h_%&z0(t$5tHX)V?99r2Mhy?>F{9qvrdETzdR3VTSyT z6~3Vab{OzKcZ?I!T1BprH(|4HbRPy>a>ks9b7SUW#Y4Bh%2A|vxEyazpVHejpP6Nh zM6cw<_sIU%s7F7Q(>xpGHYl*x=&NV-IhgMl;WC?;;1GizEbFG}(j!8279-zAX$Vp| z4YYRkp1ZnlTSOtR8b)+<=_!|9)Vr5ot#4=RN@IIwv3lv2|G&n*IxecNU3(NCK)O4m zk(81SNkxz@DW#>mLu5d5Q0bO#kZur=kVaB!=x&Ctv+z0RyyuPY_xt7#V3^sn_Fil4 zbzk?ruIn1foOsaAjId!3v>bu?crriZOfG70P+PCQ%}esMx0eHNHB5%l%hVS%fosUi zWInu|gbv!akbRW3cro($A_(gC+Tv8v`aHD2j{U$KPnoW`#%qLa~`y zjy4-I1aRTyWMvlzo4dngGl!i$sVnjfx+{2OBO|tNbc*u^@)dNG^t?)CIldG!v@RZP zhX=YyN|qTlYs1y4AwwsPHil`2F2fJ9D;CM)$%DzDdR9_Z_A2c!PeRFV&SmK)Haort zx4wNOAG0eok2{X$esX&z*QG97y-8h_v+vii{;i3Z4AUpmZEf7(ZcrNioDa=RIO51j zNzd2P{O&_&>FDZa;#S!i|08lI@5sWM==oM$AG7ub17cBV+0i!W>uEW(sT_%`FDOf) zlVqKHq`6H%)KXQ@@%_VDW=}^PIwexdJ&5d6*);v@4>ms-!)1+!2=V^%jl*{FhCn1B zH&J9J2Ppyi=$s;(#~y}N_C8KXjZMg_uf@=24Qj`O*a`a?2XY|q#|wzqk~_cl$~eZ} zLx(&nBD9E+TDT={+(zM^vf3L7FPAf?Cg>0^U$^|d(@vG1)V6RMbyq%@R9q7;#>WLU zue%2zuB3a!8W*kc7f&ps^O$Azb2&V1DrfmD8T~IP6qEN~P-q(cKcUcdm^i4bCiNyd zp3K#rNXZU`wn8BPh9SG=mvmh!nyI5cGT$cfe1+M)`3dS6_wCg%Ob(E=pfhJHmN(RH zKfKFSbBgNJDEXJ@A>W;{+@|VH`V0m?r(8WOwp9^T)iNX+Lucs!5+0$oA3HY}#ZLS) zu_PH->4xTr{8-SQ0`_zN$#MnJZ-jNENcG_$H4!a4KDF& zCj)yJik~=#G^Mz^%X+rVTA<7Q;seEGMJB^|hvQ2`AA7!0^JHJY^}H6q*8c{<+AHfn z;{bX02TiP37eWhuO@5}ETu3bsJqS)AnAmVJ?zandh2kdh0!cwd4}IJd-R8$g=HFp_0@ZtX#xLyu z5#{a3Z({&MRG9)P<(9(X`4o!-`Vqy=(K>(e-+Ml#ai^AFktT{O7x}B=;G+h1uhIW( z+T1YAWoH+AUE5>ux0R)(Gj2%&dioXCdYv6y3dH##>!Y0-I9lM3y|(eJP0fz9cI*w3I{ikC<3Iapx3m5Ox_^CmlxWBk&u?b{ z6xTpaC__68cp&(AcrYqaG>A5k9{|Q85HiWos>sU9g7*L#neZdv$RZ#hPzx>xkR0*Q z0s*TYs2TvxM^^T=w)XPM%8Tq@fb8Jp^KALQobRHDZNY@HBk+G5}DwWL0jmw3W=gE?mmhC4LQr((6(C-Rk* z##ZL!CHAYiBoCLlr$@(2SbouE8}hv)j67~(xWmRap1?vzKhSdQcd*!7g`sIT85NEd zFl!V+H4C*1R3G&26pv?n>PrwjlX$|cDf2jk85Q+D8IFGuy+3`_`8C%ZR}lSsnUH;7 zs+;&^!J`2$#v>7@_@4x4T;!-oz6LB!i{<^*4};W}fatq3sr zmQd+q(>TBB@r_f`lS7WknI@yt0ET9Zrm3%TC&tIYDBw`10f|2eiMF!x*UA`W=F0N& z&BL5mYiF&kt!lZic0|@1)6?Gq*1Ny|y#tj$b~Ki?IvE7jy=S8RcXney+?C32M|A+S zi@*en3k=UY*3ZvP-oAa-S0Sq^;@2(tito~Szsz((OEr%m>&9!3e~l0V!LaZ%5u@O~ z;L+=?bn0OEcq_De>($s^f^Ic1wmLB{&^(gtVCxb3RYjr^d3CbKUnV>3E zn!RoG6TTohPsrhewOW*Srwo!IMfxXap0gYCOQ8*u?*^2o^6Sq8V7VW2t2L{-r%VGc zODHeTaCBNq=7*QIT!i~ctKzIuXS^HXHk_~}EjRreyLnu(FnH@;?YC9E@hRsFUmM^4 zK)$s_N>|FG+ot7x!yUac)%)u!x^zI!(Qg(-4Mf2}5-dbr2<(Iab23+0PUCTNL_|L@ zr2#S=z;Xam{c@n6N>>hEI?Ip=duly7G&vdkRvQSaf-uP?B_(-3R+W{dtL6i;%1Dl) zu)`vB6?Eyy=&1UE04U4@&jD7=?@x+KN_K%a5^$DakXKI?&nl|g=s>akOnrIn0VFy| z2~S;}Ri$3h3v`$k$rlb3w`Gy&fUX-JAC+b6oiZ)cgyZ%;eC04BgjLp8yh1O~h1(mF z>1sF^t95H${8i;q*Rs5qipMimQp3;cY!MZ+vg2L!B#f=yf%@a{1%XsvPwd>)^FW=m zq8;-tYC^g`(P|(!TA;rOw$Q+J71X^k! zHgu7Zky%q0Rtqi7%mf4lWfc{g74Y;IM!SE3gARr8SD*yx9NQy28u(V}nW@;w@w#g{aJQj-kp|+X5{k1Nt`Z=0y z6VQ{hvwu%c^78Qk$s;R0Jv}>nvG6^>-2`4t zfE7{=ykT4pyb^PP`XsUoh>TypdL@hMP^X8FkMGD1TXL*xEGe-C7CS(h_W1E*vH@zS z@_`+{KC#bp9`_AQRU{xsfxN#Lm=l=Ui-g6wK3^p+pzG?R^z0&3T~6G5&4Xjl14~T{ z{=H3k=sUmf!~+`oHwT#P7$J@?nONaI)O65gZV!#lfbC$66?8nP zPnj+^5rs^9kGY28?aHB&)}BoT?_i6Ki3y+z zfro^*g1r3UiLaRAI~SK@^E4l`cketdPizk5L`3;K5f&Yh%VS)^!b$yR_$|XgQhUAd zk(!O2y@5JbHWL(^F%P^p1F*%InVI8(5#Yf=PYf#%Z224g#S$X~i2p$Uij%^ExfZFw z#(JGeA70lee7RHlXNoYZ?_9x^2BqQbCJOeR+9W(PqjPMWEH9-@K~FF)841g=nS~{U zhrxUYbM1w2-Ln`^)3X#mxV*tjm!6Q&a$uEW&D@+R*hL&=8Ra*Jh$%*P7OokD_idLq zPcL%mSdE-3xjW`3yKKFX-#_9S^H9;rIWc?Nw?B_~QuB#R-yi}o(6#?K76Oqg88vl_ z&!sDJfIp59Fxvt40oT{pJlxzur;h4agPQMtmzx5bZGJ&P+moW^W?#Tiy)#QfjUeN* z1d$PFV!_CRIl;oxGd89nbp>#riMjdFxp%(0ClE9O${28rQINVyU9AJ`*5j=SVnRX? zc7aPEpxyxCGYu37pdEmr2-e4dx08Uw1DxrA3{=iKWB2N@sKH@#WI*d}JzL`O#1Sx2 zMJ7m8XWZMO;N`03N&RMa2<4078$B@U>()v8yj)F8v;4#hs#S@tvU}6xynO0MC3P3>+HZ=_AHDGZ| zS^#%E;H<+yXD>hjFbGu#HYVnZV;$g@fj5I?7C5;9B!QX^w9J5Z&(F{QG|9%+R?KO& zFFKk4a|bY&9tX76I<3Lt&jIlj*slTFaQ(Xx#*Fq# zV2uRGUO-rtu54j$zP7iQmY7&TpnP!Ey5g>K81dD(HPPwOall>IK~^S4LyLzoiYX1S zB<%7PI9uE{ZND%4rLP6n@gc+S=t!*+Dz$r4?(Q#urVZoCwdIK;gjYMcsj^fJ9KD~@ zN=XTRLlC+{!}q{%iI%_q=O5~$#coN*QYpD_)Yky41Cbj@{O(NUoSkPHJ$SgfBTHgI{0js`Y44}iB2^v-||>!X^s zHZxwxK$@TDX+GibFh*>3v)sqQ#kkz)IdPBEqe8pPicq6zvB{< z`59;gn_MF2%)lN#pF=({szFjaY4BbY;rE;%$zl{0j9>XaM(XUP>H??O>Ux((Ai}97VBemw9mOuD~Z8LyL+ir9o1=|lwJ>f zUR-j*z7}IoP-{P#6H8(?pY^;dC1=%|xv7^LQu!9}f?$=0qldnnu%^X8rBRkPdf6|o zkYw|qs$M1`t+cVGMCg=81@AYRqTWWxUx&w4bJONdmXjz=Um^!Zo!6c_pp@!AX06jR zFf?p=+a3h;%XCm+bO$0|nwSquTrc=Z27Dd}2%tC_%FODUFKc?_U%uq43A5)pn3^QS zXGVj+fLH%H=dEj|sy0`IxeuR5y?j0m6JGKnw`R7+n&w;8a5nh6f%$QVU{hO4^R!;2 zAC4c?X2K3%zxv>myvXQHWVmABn#iLbYy8h4zdTvQ2q?q=<5>XaRHp|Bqve22nbNhi zAV39-jVLJew6uWj1`8`I(*64uyoo`sxX}K#tYNP#+Wgo*9l4HDdB86uFkGn2w~<+v z^04laHzR$l47+4`vaLCrCGKNe$(rm_-g`jYeu=^QQ?nQ5YXkDFG%XR2dkj)zzJYGz1d^V|6eM*b^yj zN5(boExj4a@BPK}=Zr5fZ5lH(yC(_}dPA;J$C(V9qj z9LLS+>vm*N1^cKL2zN$Oy8jUqZurq&I6$H^fI_XatLtM>5SReM!oq%jw*V4Dl`SnT zfhY|4yd?DlDNLH6lbO6cnq>FHgxk&4ImkT#_Y_FBfv+T~n0IZE>w;q=^SSI$+5AAm zZq&(r(52VNE8_Wtx>fG(bs5@WB#u9n{ZtbSeD_9Y-?yVj_gq?efo1hQzwAqDeN1MM zF+_ZfdvJGLseiS2JsB#IIp@w60eJrYX2YgFlV>P(38V7Q2RH57Y_8`Wb>{tI?1^6klS%2|{FsyBh(Wz!g4STac0#q?vXc0e z_ib88h-vOiLywl?nEpKlii@74)B2k1093GYix1Ze3k5!$=xl1GdH%V0SR19&{D8_# z<7&Zee`FNL2_=lb+Kr*nbC>HD&QzQxbbYB45RNR`G@=Y*Q1{p2QXt0$sWgddhT2g4zaRk-fLpaiQy40FZj%LZ%Dwp=U>7J z)VD-XWA|39)s)N*yk}keIxwfjwawvU-sQ{^F%Rqjy+>3dd4-1G0t9age}efO+~c}5 z$6!!G_bzH#+C*L7{XLE&!YTDUGp*z^2d?W}s}hG@@6wn<-|gFtr2T_WT-7P3FU81J zIHAHOt0 zpUYoTgKI52qj&m{-iDIZ)~{*%qK7Fkl2B`GSqwvns9-#9I_WQW6o?Hy_Z!Od6z=0)el`7klxT4sr_i50KILnfl` z-n#k=usKe5l_K0VXs#Fi!sM>04EG3W=AXA5ae5jFDpcMa+gpit$w;!Ma>-hChQQ@n zPPG*)Czu_L^L10BJ>k~)(g2~lr#GlTuCB4}6&DWpJSQp;x!HsT)O&kQ8SL#;2=Z+Q z82s#7qpEkxstuT!>j$K5$olD=h1{CL`cFe9`f^(_sur`ug7V{v(+hmH*Lc$G8HqC= zGsUmJ_6n?+?Rmd@j!BjBxH`bFovdHB$nwYm<=0lPegX zMQ7*TEQA5RM?AYM>a3`$$d;UVJ-ZK%&(LVzMhq!7@7jp&u}m?o)XU6)V^$t2oE^Sz zPm*tD`$7@ij$?>DbIcpR0G9~ouF^!rwn5bDb%E0@LVs`1ob)y6MiQyJ%;5T}CePB% z;F&(YkJ|O%FUf96m#!8$&#Adnk&pdzTP+3F*JpfDI)RaXDWBXK5zB?MehPH}ohjUX zN5BplKw;ui?F}U(R`wKfs5D@~QgIl}Ijc!32@}gAb-w0R9A)FJ=Ant*aOF(Z^{;cyQJ@A^8z+1L{GjD@q)Zq}MO$#k5N3UTof zFf17Eb_jlWTsUdi4ZU5!2XdJIfNIXpp%_-?j=5gK425m zNv#HUKkRc@&2)%$PdtB<$ZIS|LY=h1Mbg(SN_el_x8D;~}ApXf|Ky|unJ znvyx{!||*nuG%ClF>q(*q!+&SxEi7P%O(Fgi?wA#C0}l@02xeN)rDeoXqtgZ00BPtUr2c)>}rA-QMunvIr_UkPs@h?5NQ`l+X z*cx66TkZ5LBfWbm^)E59eJP`ZULavg_qV}CPW+A^Wt8HB zRT|>yui2FhCa=-q7fcIh({BF+C$g>u8A1M0(>zJ1|KQ(oV&%EMJF@Kfj(-s~F3q$jRw&`Eb?vkeq3c~!vhy@pBh1#dP zI~1=2Up!$^WDNow9uW2AEC`^dwp#z2Q)wOW*(O`MTA5Y^?4kBg_xvbN?(Pe%ICViD zW-Lj`s4dub-WZ$ozQIqOt#$Lk7h{~;Cbq)m@tH2#YCwMy()TVkOsR-dkf%L`uEURk zxLVAb(wfKp5LszLhMM+2rDeYu7W;(Hey-SfGz!7M!VW%@io262-!GF=rvy=ny7iqy z)+{!yE;myysnXWcK%MCP)2p(a#jbzJ<;sE8SQ87ra-5RVbRh>dMLW9dlRXOdSX7~) zLC0i#ajnRbk2sdhM*4HHr--L7$NhC8DpSv@x`OKl$eQC)S2H=9>%FlQe(xQIYymXm ztZRJNcaNaH!fFSwE%P(@_yA!X#m!dy?cM=a14ogdR+3?6?Ncio&jWv5`J`=LbLN<3 z+X119<*YmndTXMbpk(EuPgJQ>ug7Su;s|#eT(_5`OrW3&7y25Sp*ftuz{F|OPtz0j z1s&V{=9hL~8$C&BYEs<=n@VcajR>ycD6Imf;O7disBowME^9x(D{J?A6tJ4h8Y<{q z87@>j<C#nWlnJ~*x)Y3=&?h^6I!`oZ$Z3S1%a-nYBU1*LY&wNMQz zX3!r`cZCs2FMYE8r#F-HeNRgbV?Jbv<0tqX-w zf^M&hhfG{(wnO!FH!A1mgu_YQl{DMl?US3|*Es{zi~>yr;;n+P@R5HMpx+Is>7R?m zrPWq(9&VW3<@<%?+{e4Fq5>2#H=oVAIKRAI*jfDth9MsM97P_ z9IwX}+_RURd!83o%0Ufsi2|oWZp|D9fsSl2A|6HHA~0}x(f-Q4*@35lL=i`l08M7h z_}e1fww~kSliAQQDyK@te;0n6+%JZd5l~W}vJKlzb$X2{Xpx<@IqhBg2`Y9(uvnJG znnnUJRJ2;8I^?+MLY_hbjC0bJSF{FI_h? zf;UXLM6)w)>~3mA4fPrm%5JM1h5+OKV2OdhR60^2Hq;lR2jHNQZ{a-QAq4W~Yle!a zFk#(RTDJ>St9ut~XA5@P@^Hxna&Vje`RIpLERD84e0P9G_3Bb=grdd(Dx!l8yc&S|u##Yqa&Q(07u6x2AdvP^6 zZk>H-IDWaqVPZDuyItJ9`LSKi7|%$sg4|k`$JgMWW$Je+*SOH zD@?nOh=-K;r(?c$fnA2uNan$29YE@Y0skDZ2~-4JJD^~`D!P%aa0{k&3>u_8ix$2R zygT*`=G!EaANBIn7AP@hn7tLQxjsDg2xV`Ian@(~f|fMJVbj0C4GTJ{t zv*B%5HDPlQ4>nk?m_+K-2kMXM8O{V$d};TeEAC3YNP4jKonA7e#Gj)sc-?N2^_9C-ScN(GSBjNc4e2zgk~WVA$cIsB^kBpca8x0pqVgQ2?PLU@ zxg#z2&}|U9hpfk%b>HM|t3g4@K$Z&?;aX2{qHo9%ht1E`Ao~b7*TL2J1OR0?Uf) z`e9vM?{erOUHX4YpFRxo?bTJGc{*oFT{opv(g+t?ABm)vyV?~J8X?VSA-}VMDo9Ar zYK|EEOW8z4Vzjy#f?f#sZLG){gEv9eaml#OHu+=>lbaBHGUKnMawn;eMTc7LsCSnH zyh{BHa{+1sn~l*@=DkKFx`km%$1Zm%3k1>>9=h}#tCZ|6Zc6w`cQ}OV-E`(WxeLP( zcc(l@X^)Nx$lbvZ3w{*4>i}8Wu@{M&Sx@8-quqO&+QW&dlEhS-(;85xu*Q zgIF+tBdEZ4MS#g*m_aM;@B8<$43>sWcdtYC>m}s=v~)dwi(;9U+TPsQG;#OB3z=8a JC6aGG{1@Gjd@KL} literal 0 HcmV?d00001 diff --git a/docs/en-US/images/jenkins-pipeline.png b/docs/en-US/images/jenkins-pipeline.png new file mode 100644 index 0000000000000000000000000000000000000000..0788c26a4851bbde70ecf67e23e27cf5d02ff77b GIT binary patch literal 29136 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 literal 0 HcmV?d00001 diff --git a/docs/en-US/images/ldap-configuration.png b/docs/en-US/images/ldap-configuration.png new file mode 100644 index 0000000000000000000000000000000000000000..c840e597e1bb031349dfd234e4998f63b7d0e793 GIT binary patch literal 33360 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 literal 0 HcmV?d00001 diff --git a/docs/en-US/images/ldap-global-settings.png b/docs/en-US/images/ldap-global-settings.png new file mode 100644 index 0000000000000000000000000000000000000000..0567de84374d13ae4b67feaa0df32cdbf45b96a3 GIT binary patch literal 31145 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�?CG3#CADS@w6^&l;!M7 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 P83+Yg6`2xglc)azb$cK& literal 0 HcmV?d00001 From 9985a895a4a9f2c72d93e4e20499c2546a63b12b Mon Sep 17 00:00:00 2001 From: Wei Zhou Date: Tue, 23 Jul 2013 17:37:39 +0200 Subject: [PATCH 71/74] CLOUDSTACK-3734: remove wrong break in 'for' block in VirtualMachineManagerImpl.java --- server/src/com/cloud/vm/VirtualMachineManagerImpl.java | 1 - 1 file changed, 1 deletion(-) diff --git a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java index c8210b20e98..a0c5c3a85ae 100755 --- a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java +++ b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java @@ -2298,7 +2298,6 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac if (vm != null) { map.put(vm.getId(), new AgentVmInfo(entry.getKey(), vm, entry.getValue().second(), entry.getValue().first())); is_alien_vm = false; - break; } // alien VMs if (is_alien_vm){ From 5c45645932f7537aa93f4d060e114a40dc7cbcb6 Mon Sep 17 00:00:00 2001 From: Sanjay Tripathi Date: Tue, 23 Jul 2013 18:04:34 +0530 Subject: [PATCH 72/74] CLOUDSTACK-3724: Test case "test_vpc_vms_deployment.py" failed to find network offering. Signed-off-by: Prasanna Santhanam (cherry picked from commit a06b3f40eba6ebc3af5d7c366ec757703a085f67) --- .../component/test_vpc_vms_deployment.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/test/integration/component/test_vpc_vms_deployment.py b/test/integration/component/test_vpc_vms_deployment.py index c599d96113e..194b4061d4d 100644 --- a/test/integration/component/test_vpc_vms_deployment.py +++ b/test/integration/component/test_vpc_vms_deployment.py @@ -354,7 +354,7 @@ class TestVMDeployVPC(cloudstackTestCase): ) # Enable Network offering nw_off_no_lb.update(self.apiclient, state='Enabled') - self._cleanup.append(nw_off) + self._cleanup.append(nw_off_no_lb) # Creating network using the network offering created self.debug("Creating network with network offering: %s" % @@ -569,7 +569,7 @@ class TestVMDeployVPC(cloudstackTestCase): ) # Enable Network offering nw_off_no_lb.update(self.apiclient, state='Enabled') - self._cleanup.append(nw_off) + self._cleanup.append(nw_off_no_lb) # Creating network using the network offering created self.debug("Creating network with network offering: %s" % @@ -822,7 +822,7 @@ class TestVMDeployVPC(cloudstackTestCase): ) # Enable Network offering nw_off_no_lb.update(self.apiclient, state='Enabled') - self._cleanup.append(nw_off) + self._cleanup.append(nw_off_no_lb) # Creating network using the network offering created self.debug("Creating network with network offering: %s" % @@ -1091,7 +1091,7 @@ class TestVMDeployVPC(cloudstackTestCase): ) # Enable Network offering nw_off_no_lb.update(self.apiclient, state='Enabled') - self._cleanup.append(nw_off) + self._cleanup.append(nw_off_no_lb) # Creating network using the network offering created self.debug("Creating network with network offering: %s" % @@ -1375,7 +1375,7 @@ class TestVMDeployVPC(cloudstackTestCase): ) # Enable Network offering nw_off_no_lb.update(self.apiclient, state='Enabled') - self._cleanup.append(nw_off) + self._cleanup.append(nw_off_no_lb) configs = Configurations.list( self.apiclient, @@ -1546,7 +1546,7 @@ class TestVMDeployVPC(cloudstackTestCase): ) # Enable Network offering nw_off_no_lb.update(self.apiclient, state='Enabled') - self._cleanup.append(nw_off) + self._cleanup.append(nw_off_no_lb) # Creating network using the network offering created self.debug("Creating network with network offering: %s" % @@ -1810,7 +1810,7 @@ class TestVMDeployVPC(cloudstackTestCase): ) # Enable Network offering nw_off_no_lb.update(self.apiclient, state='Enabled') - self._cleanup.append(nw_off) + self._cleanup.append(nw_off_no_lb) # Creating network using the network offering created self.debug("Creating network with network offering: %s" % From 3962f117ac09b02740fad4b89b87dc9fd9df5bb2 Mon Sep 17 00:00:00 2001 From: Alena Prokharchyk Date: Tue, 23 Jul 2013 10:54:28 -0700 Subject: [PATCH 73/74] CLOUDSTACK-3733: fixed migrateVm - no need to cast vm to user vm to retrieve the iso information. Extract iso information from VirtualMachineProfile object passed to the method. Conflicts: server/src/com/cloud/storage/VolumeManagerImpl.java --- .../com/cloud/storage/VolumeManagerImpl.java | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/server/src/com/cloud/storage/VolumeManagerImpl.java b/server/src/com/cloud/storage/VolumeManagerImpl.java index fa7a33a51b9..e8957b4b081 100644 --- a/server/src/com/cloud/storage/VolumeManagerImpl.java +++ b/server/src/com/cloud/storage/VolumeManagerImpl.java @@ -31,10 +31,6 @@ import java.util.concurrent.ExecutionException; import javax.inject.Inject; import javax.naming.ConfigurationException; -import org.apache.commons.lang.StringUtils; -import org.apache.log4j.Logger; -import org.springframework.stereotype.Component; - import org.apache.cloudstack.api.BaseCmd; import org.apache.cloudstack.api.command.user.volume.AttachVolumeCmd; import org.apache.cloudstack.api.command.user.volume.CreateVolumeCmd; @@ -73,7 +69,9 @@ import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO; import org.apache.cloudstack.storage.datastore.db.VolumeDataStoreDao; import org.apache.cloudstack.storage.datastore.db.VolumeDataStoreVO; import org.apache.cloudstack.storage.image.datastore.ImageStoreEntity; - +import org.apache.commons.lang.StringUtils; +import org.apache.log4j.Logger; +import org.springframework.stereotype.Component; import com.cloud.agent.AgentManager; import com.cloud.agent.api.Answer; import com.cloud.agent.api.storage.CreateVolumeOVAAnswer; @@ -2320,13 +2318,10 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { vm.addDisk(disk); } - if (vm.getType() == VirtualMachine.Type.User) { - UserVmVO userVM = (UserVmVO) vm.getVirtualMachine(); - if (userVM.getIsoId() != null) { - DataTO dataTO = tmplFactory.getTemplate(userVM.getIsoId(), DataStoreRole.Image, userVM.getDataCenterId()).getTO(); - DiskTO iso = new DiskTO(dataTO, 3L, null, Volume.Type.ISO); - vm.addDisk(iso); - } + if (vm.getType() == VirtualMachine.Type.User && vm.getTemplate().getFormat() == ImageFormat.ISO) { + DataTO dataTO = tmplFactory.getTemplate(vm.getTemplate().getId(), DataStoreRole.Image, vm.getVirtualMachine().getDataCenterId()).getTO(); + DiskTO iso = new DiskTO(dataTO, 3L, null, Volume.Type.ISO); + vm.addDisk(iso); } } From c02e802170369477548cb71209b4942ad1ecec04 Mon Sep 17 00:00:00 2001 From: Jessica Wang Date: Tue, 23 Jul 2013 11:34:22 -0700 Subject: [PATCH 74/74] CLOUDSTACK-2760: UI > Infrastructure menu > System VMs > fix a bug that Agent State was not mapped correctly between systemVMs and hosts. --- ui/scripts/system.js | 31 +++++++++++++------------------ 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/ui/scripts/system.js b/ui/scripts/system.js index a56397e0c7a..e3392303bd7 100644 --- a/ui/scripts/system.js +++ b/ui/scripts/system.js @@ -7420,34 +7420,29 @@ listAll: true }, success: function(json) { - var items = json.listsystemvmsresponse.systemvm; - if (items != null) { + var systemvmObjs = json.listsystemvmsresponse.systemvm; + if (systemvmObjs != null) { $.ajax({ - url: createURL("listHosts&listAll=true"), - async: false, + url: createURL("listHosts&listAll=true"), success: function(json) { - - var hostObj = json.listhostsresponse.host; - - $(hostObj).each(function(index) { - - $.extend(items[index], { - agentstate: hostObj[index].state - }); - - }); + var hostObjs = json.listhostsresponse.host; + for (var i = 0; i < systemvmObjs.length; i++) { + for (var k = 0; k < hostObjs.length; k++) { + if (hostObjs[k].name == systemvmObjs[i].name) { + systemvmObjs[i].agentstate = hostObjs[k].state; + break; + } + } + } args.response.success({ - data: items + data: systemvmObjs }); }, error: function(json) { args.response.error(parseXMLHttpResponse(json)); - } }); } - - // args.response.success({ data: json.listsystemvmsresponse.systemvm }); }, error: function(json) { args.response.error(parseXMLHttpResponse(json));