You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by bh...@apache.org on 2012/11/15 14:14:12 UTC
[2/3] git commit: CLOUDSTACK-424: Update userdata should propagate to
VR
CLOUDSTACK-424: Update userdata should propagate to VR
The code that would propage userdata to router, when updateVirtualMachine api
is called, was missing. As per the docs [0], userdata should be a base64 encoded
string upto 2KB which is put on domr's html directory adn using HTTP GET the
userdata information can be obtained from the domr.
The updateVirtualMachine api [0] would accept a base64 encoded string
and decoded and put into the domr's /var/www/html/userdata/<uservm ip>/user-data
file. The operation does not require the VM to be in stopped state, though it is
advised to stop and call this api in case the user vm has a script which gets
the userdata information from domr while starting.
For example, this script can be used to fetch the data:
server_ip=$(grep dhcp-server-identifier /var/lib/dhclient-eth0.leases | tail -1 | awk '{print $NF}' | tr '\;' ' ')
wget http://${server_ip}/latest/user-data
This feature can be useful, for example to use into puppet facts [1], or to do
automation and horizontal scaling etc. based on userdata.
[0] http://incubator.apache.org/cloudstack/docs/api/apidocs-4.0.0/domain_admin/updateVirtualMachine.html
[1] http://geek.jasonhancock.com/2011/11/09/cloudstack-userdata-into-puppet-facts/
BUG-ID : CLOUDSTACK-424
Reviewed-by: Rohit Yadav <bh...@apache.org>
Reported-by: Nick Wales
Signed-off-by: Rohit Yadav <bh...@apache.org>
Project: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/commit/4c86b154
Tree: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/tree/4c86b154
Diff: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/diff/4c86b154
Branch: refs/heads/master
Commit: 4c86b1545dda53b74c534d479133692331e12a28
Parents: 7ae8c4a
Author: Rohit Yadav <bh...@apache.org>
Authored: Thu Nov 15 17:53:33 2012 +0530
Committer: Rohit Yadav <bh...@apache.org>
Committed: Thu Nov 15 18:43:51 2012 +0530
----------------------------------------------------------------------
api/src/com/cloud/api/commands/UpdateVMCmd.java | 17 ++++---
.../network/element/UserDataServiceProvider.java | 1 +
api/src/com/cloud/vm/UserVmService.java | 2 +-
server/src/com/cloud/network/NetworkManager.java | 3 +
.../src/com/cloud/network/NetworkManagerImpl.java | 13 +++++
.../network/element/CloudZonesNetworkElement.java | 6 ++
.../network/element/VirtualRouterElement.java | 18 ++++++
.../router/VirtualNetworkApplianceManager.java | 5 ++-
.../router/VirtualNetworkApplianceManagerImpl.java | 18 ++++++
server/src/com/cloud/vm/UserVmManagerImpl.java | 41 ++++++++++++++-
.../com/cloud/network/MockNetworkManagerImpl.java | 6 ++
.../test/com/cloud/vpc/MockNetworkManagerImpl.java | 6 ++
12 files changed, 125 insertions(+), 11 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/4c86b154/api/src/com/cloud/api/commands/UpdateVMCmd.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/api/commands/UpdateVMCmd.java b/api/src/com/cloud/api/commands/UpdateVMCmd.java
index 38d2273..462fe19 100644
--- a/api/src/com/cloud/api/commands/UpdateVMCmd.java
+++ b/api/src/com/cloud/api/commands/UpdateVMCmd.java
@@ -25,18 +25,20 @@ import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
import com.cloud.api.ServerApiException;
import com.cloud.api.response.UserVmResponse;
+import com.cloud.exception.InsufficientCapacityException;
+import com.cloud.exception.ResourceUnavailableException;
import com.cloud.user.Account;
import com.cloud.user.UserContext;
import com.cloud.uservm.UserVm;
@Implementation(description="Updates properties of a virtual machine. The VM has to be stopped and restarted for the " +
- "new properties to take effect. UpdateVirtualMachine does not first check whether the VM is stopped. " +
- "Therefore, stop the VM manually before issuing this call.", responseObject=UserVmResponse.class)
-public class UpdateVMCmd extends BaseCmd{
- public static final Logger s_logger = Logger.getLogger(UpdateVMCmd.class.getName());
- private static final String s_name = "updatevirtualmachineresponse";
-
+ "new properties to take effect. UpdateVirtualMachine does not first check whether the VM is stopped. " +
+ "Therefore, stop the VM manually before issuing this call.", responseObject=UserVmResponse.class)
+public class UpdateVMCmd extends BaseCmd{
+ public static final Logger s_logger = Logger.getLogger(UpdateVMCmd.class.getName());
+ private static final String s_name = "updatevirtualmachineresponse";
+
/////////////////////////////////////////////////////
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////
@@ -114,7 +116,8 @@ public class UpdateVMCmd extends BaseCmd{
}
@Override
- public void execute(){
+ public void execute() throws ResourceUnavailableException,
+ InsufficientCapacityException, ServerApiException {
UserContext.current().setEventDetails("Vm Id: "+getId());
UserVm result = _userVmService.updateVirtualMachine(this);
if (result != null){
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/4c86b154/api/src/com/cloud/network/element/UserDataServiceProvider.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/network/element/UserDataServiceProvider.java b/api/src/com/cloud/network/element/UserDataServiceProvider.java
index d848216..321ccc7 100644
--- a/api/src/com/cloud/network/element/UserDataServiceProvider.java
+++ b/api/src/com/cloud/network/element/UserDataServiceProvider.java
@@ -29,4 +29,5 @@ import com.cloud.vm.VirtualMachineProfile;
public interface UserDataServiceProvider extends NetworkElement {
public boolean addPasswordAndUserdata(Network network, NicProfile nic, VirtualMachineProfile<? extends VirtualMachine> vm, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException;
boolean savePassword(Network network, NicProfile nic, VirtualMachineProfile<? extends VirtualMachine> vm) throws ResourceUnavailableException;
+ boolean saveUserData(Network network, NicProfile nic, VirtualMachineProfile<? extends VirtualMachine> vm) throws ResourceUnavailableException;
}
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/4c86b154/api/src/com/cloud/vm/UserVmService.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/vm/UserVmService.java b/api/src/com/cloud/vm/UserVmService.java
index 02682b0..98d02db 100755
--- a/api/src/com/cloud/vm/UserVmService.java
+++ b/api/src/com/cloud/vm/UserVmService.java
@@ -113,7 +113,7 @@ public interface UserVmService {
UserVm rebootVirtualMachine(RebootVMCmd cmd) throws InsufficientCapacityException, ResourceUnavailableException;
- UserVm updateVirtualMachine(UpdateVMCmd cmd);
+ UserVm updateVirtualMachine(UpdateVMCmd cmd) throws ResourceUnavailableException, InsufficientCapacityException;
UserVm recoverVirtualMachine(RecoverVMCmd cmd) throws ResourceAllocationException;
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/4c86b154/server/src/com/cloud/network/NetworkManager.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/network/NetworkManager.java b/server/src/com/cloud/network/NetworkManager.java
index 4124b19..057f473 100755
--- a/server/src/com/cloud/network/NetworkManager.java
+++ b/server/src/com/cloud/network/NetworkManager.java
@@ -50,6 +50,7 @@ import com.cloud.network.rules.StaticNat;
import com.cloud.offering.NetworkOffering;
import com.cloud.offerings.NetworkOfferingVO;
import com.cloud.user.Account;
+import com.cloud.uservm.UserVm;
import com.cloud.utils.Pair;
import com.cloud.vm.Nic;
import com.cloud.vm.NicProfile;
@@ -189,6 +190,8 @@ public interface NetworkManager extends NetworkService {
UserDataServiceProvider getPasswordResetProvider(Network network);
+ UserDataServiceProvider getUserDataUpdateProvider(Network network);
+
boolean networkIsConfiguredForExternalNetworking(long zoneId, long networkId);
Map<Capability, String> getNetworkServiceCapabilities(long networkId, Service service);
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/4c86b154/server/src/com/cloud/network/NetworkManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/network/NetworkManagerImpl.java b/server/src/com/cloud/network/NetworkManagerImpl.java
index 5c40f52..ec0ca79 100755
--- a/server/src/com/cloud/network/NetworkManagerImpl.java
+++ b/server/src/com/cloud/network/NetworkManagerImpl.java
@@ -184,6 +184,7 @@ import com.cloud.user.User;
import com.cloud.user.UserContext;
import com.cloud.user.dao.AccountDao;
import com.cloud.user.dao.UserStatisticsDao;
+import com.cloud.uservm.UserVm;
import com.cloud.utils.AnnotationHelper;
import com.cloud.utils.NumbersUtil;
import com.cloud.utils.Pair;
@@ -4342,6 +4343,18 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
}
@Override
+ public UserDataServiceProvider getUserDataUpdateProvider(Network network) {
+ String userDataProvider = _ntwkSrvcDao.getProviderForServiceInNetwork(network.getId(), Service.UserData);
+
+ if (userDataProvider == null) {
+ s_logger.debug("Network " + network + " doesn't support service " + Service.UserData.getName());
+ return null;
+ }
+
+ return (UserDataServiceProvider)getElementImplementingProvider(userDataProvider);
+ }
+
+ @Override
public boolean networkIsConfiguredForExternalNetworking(long zoneId, long networkId) {
boolean netscalerInNetwork = isProviderForNetwork(Network.Provider.Netscaler, networkId);
boolean juniperInNetwork = isProviderForNetwork(Network.Provider.JuniperSRX, networkId);
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/4c86b154/server/src/com/cloud/network/element/CloudZonesNetworkElement.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/network/element/CloudZonesNetworkElement.java b/server/src/com/cloud/network/element/CloudZonesNetworkElement.java
index bb9ae81..ae8be0d 100644
--- a/server/src/com/cloud/network/element/CloudZonesNetworkElement.java
+++ b/server/src/com/cloud/network/element/CloudZonesNetworkElement.java
@@ -252,6 +252,12 @@ public class CloudZonesNetworkElement extends AdapterBase implements NetworkElem
}
@Override
+ public boolean saveUserData(Network network, NicProfile nic, VirtualMachineProfile<? extends VirtualMachine> vm) throws ResourceUnavailableException {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
public boolean verifyServicesCombination(Set<Service> services) {
return true;
}
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/4c86b154/server/src/com/cloud/network/element/VirtualRouterElement.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/network/element/VirtualRouterElement.java b/server/src/com/cloud/network/element/VirtualRouterElement.java
index 07b1823..4ff1082 100755
--- a/server/src/com/cloud/network/element/VirtualRouterElement.java
+++ b/server/src/com/cloud/network/element/VirtualRouterElement.java
@@ -662,6 +662,24 @@ public class VirtualRouterElement extends AdapterBase implements VirtualRouterEl
}
@Override
+ public boolean saveUserData(Network network, NicProfile nic, VirtualMachineProfile<? extends VirtualMachine> vm)
+ throws ResourceUnavailableException {
+ if (!canHandle(network, null)) {
+ return false;
+ }
+ List<DomainRouterVO> routers = _routerDao.listByNetworkAndRole(network.getId(), Role.VIRTUAL_ROUTER);
+ if (routers == null || routers.isEmpty()) {
+ s_logger.debug("Can't find virtual router element in network " + network.getId());
+ return true;
+ }
+
+ @SuppressWarnings("unchecked")
+ VirtualMachineProfile<UserVm> uservm = (VirtualMachineProfile<UserVm>) vm;
+
+ return _routerMgr.saveUserDataToRouter(network, nic, uservm, routers);
+ }
+
+ @Override
public String getPropertiesFile() {
return "virtualrouter_commands.properties";
}
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/4c86b154/server/src/com/cloud/network/router/VirtualNetworkApplianceManager.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/network/router/VirtualNetworkApplianceManager.java b/server/src/com/cloud/network/router/VirtualNetworkApplianceManager.java
index c57e472..2980871 100644
--- a/server/src/com/cloud/network/router/VirtualNetworkApplianceManager.java
+++ b/server/src/com/cloud/network/router/VirtualNetworkApplianceManager.java
@@ -62,7 +62,10 @@ public interface VirtualNetworkApplianceManager extends Manager, VirtualNetworkA
*/
boolean savePasswordToRouter(Network network, NicProfile nic, VirtualMachineProfile<UserVm> profile,
List<? extends VirtualRouter> routers) throws ResourceUnavailableException;
-
+
+ boolean saveUserDataToRouter(Network network, NicProfile nic, VirtualMachineProfile<UserVm> profile,
+ List<? extends VirtualRouter> routers) throws ResourceUnavailableException;
+
List<DomainRouterVO> deployVirtualRouterInGuestNetwork(Network guestNetwork, DeployDestination dest, Account owner,
Map<VirtualMachineProfile.Param, Object> params, boolean isRedundant) throws InsufficientCapacityException,
ResourceUnavailableException, ConcurrentOperationException;
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/4c86b154/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java
index 928ce0e..f5ec28c 100755
--- a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java
+++ b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java
@@ -464,6 +464,24 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian
});
}
+ @Override
+ public boolean saveUserDataToRouter(Network network, final NicProfile nic, VirtualMachineProfile<UserVm> profile, List<? extends VirtualRouter> routers) throws ResourceUnavailableException {
+ _userVmDao.loadDetails((UserVmVO) profile.getVirtualMachine());
+
+ final VirtualMachineProfile<UserVm> updatedProfile = profile;
+
+ return applyRules(network, routers, "save userdata entry", false, null, false, new RuleApplier() {
+ @Override
+ public boolean execute(Network network, VirtualRouter router) throws ResourceUnavailableException {
+ // 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);
+ return sendCommandsToRouter(router, cmds);
+ }
+ });
+ }
+
@Override @ActionEvent(eventType = EventTypes.EVENT_ROUTER_STOP, eventDescription = "stopping router Vm", async = true)
public VirtualRouter stopRouter(long routerId, boolean forced) throws ResourceUnavailableException, ConcurrentOperationException {
UserContext context = UserContext.current();
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/4c86b154/server/src/com/cloud/vm/UserVmManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java b/server/src/com/cloud/vm/UserVmManagerImpl.java
index 96f1a2d..1533416 100755
--- a/server/src/com/cloud/vm/UserVmManagerImpl.java
+++ b/server/src/com/cloud/vm/UserVmManagerImpl.java
@@ -1756,13 +1756,14 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
@Override
@ActionEvent(eventType = EventTypes.EVENT_VM_UPDATE, eventDescription = "updating Vm")
- public UserVm updateVirtualMachine(UpdateVMCmd cmd) {
+ public UserVm updateVirtualMachine(UpdateVMCmd cmd)
+ throws ResourceUnavailableException, InsufficientCapacityException {
String displayName = cmd.getDisplayName();
String group = cmd.getGroup();
Boolean ha = cmd.getHaEnable();
Long id = cmd.getId();
Long osTypeId = cmd.getOsTypeId();
- String userData = cmd.getUserData();
+ String userData = cmd.getUserData().replace("\\n", "");
// Input validation
UserVmVO vmInstance = null;
@@ -1799,9 +1800,11 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
throw new InvalidParameterValueException("Vm with id " + id + " is not in the right state");
}
+ boolean updateUserdata = false;
if (userData != null) {
validateUserData(userData);
// update userData on domain router.
+ updateUserdata = true;
} else {
userData = vmInstance.getUserData();
}
@@ -1833,9 +1836,43 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
_vmDao.updateVM(id, displayName, ha, osTypeId, userData);
+ if (updateUserdata) {
+ boolean result = updateUserDataInternal(_vmDao.findById(id));
+ if (result) {
+ s_logger.debug("User data successfully updated for vm id="+id);
+ } else {
+ throw new CloudRuntimeException("Failed to reset userdata for the virtual machine ");
+ }
+ }
+
return _vmDao.findById(id);
}
+ private boolean updateUserDataInternal(UserVm vm)
+ throws ResourceUnavailableException, InsufficientCapacityException {
+ VMTemplateVO template = _templateDao.findByIdIncludingRemoved(vm.getTemplateId());
+ Nic defaultNic = _networkMgr.getDefaultNic(vm.getId());
+ if (defaultNic == null) {
+ s_logger.error("Unable to update userdata for vm id=" + vm.getId() + " as the instance doesn't have default nic");
+ return false;
+ }
+
+ Network defaultNetwork = _networkDao.findById(defaultNic.getNetworkId());
+ NicProfile defaultNicProfile = new NicProfile(defaultNic, defaultNetwork, null, null, null,
+ _networkMgr.isSecurityGroupSupportedInNetwork(defaultNetwork),
+ _networkMgr.getNetworkTag(template.getHypervisorType(), defaultNetwork));
+
+ VirtualMachineProfile<VMInstanceVO> vmProfile = new VirtualMachineProfileImpl<VMInstanceVO>((VMInstanceVO)vm);
+
+ UserDataServiceProvider element = _networkMgr.getUserDataUpdateProvider(defaultNetwork);
+ if (element == null) {
+ throw new CloudRuntimeException("Can't find network element for " + Service.UserData.getName() + " provider needed for UserData update");
+ }
+ boolean result = element.saveUserData(defaultNetwork, defaultNicProfile, vmProfile);
+
+ return true;
+ }
+
@Override
@ActionEvent(eventType = EventTypes.EVENT_VM_START, eventDescription = "starting Vm", async = true)
public UserVm startVirtualMachine(StartVMCmd cmd) throws ExecutionException, ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException {
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/4c86b154/server/test/com/cloud/network/MockNetworkManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/test/com/cloud/network/MockNetworkManagerImpl.java b/server/test/com/cloud/network/MockNetworkManagerImpl.java
index 8c7b67f..a038e71 100755
--- a/server/test/com/cloud/network/MockNetworkManagerImpl.java
+++ b/server/test/com/cloud/network/MockNetworkManagerImpl.java
@@ -616,6 +616,12 @@ public class MockNetworkManagerImpl implements NetworkManager, Manager, NetworkS
}
@Override
+ public UserDataServiceProvider getUserDataUpdateProvider(Network network) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
public PhysicalNetworkServiceProvider updateNetworkServiceProvider(Long id, String state, List<String> enabledServices) {
// TODO Auto-generated method stub
return null;
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/4c86b154/server/test/com/cloud/vpc/MockNetworkManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/test/com/cloud/vpc/MockNetworkManagerImpl.java b/server/test/com/cloud/vpc/MockNetworkManagerImpl.java
index e1b6ad4..dc0e880 100644
--- a/server/test/com/cloud/vpc/MockNetworkManagerImpl.java
+++ b/server/test/com/cloud/vpc/MockNetworkManagerImpl.java
@@ -810,6 +810,12 @@ public class MockNetworkManagerImpl implements NetworkManager, Manager{
return null;
}
+ @Override
+ public UserDataServiceProvider getUserDataUpdateProvider(Network network) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
/* (non-Javadoc)
* @see com.cloud.network.NetworkManager#networkIsConfiguredForExternalNetworking(long, long)
*/