From c6033baa78c373f7b067c5cd7fbd6daa02e74c64 Mon Sep 17 00:00:00 2001 From: Alex Huang Date: Mon, 8 Nov 2010 15:03:43 -0800 Subject: [PATCH] system vm start and stop added --- client/tomcatconf/commands.properties.in | 16 +-- server/src/com/cloud/api/ApiServer.java | 11 +- .../cloud/api/commands/StartSystemVm2Cmd.java | 109 ++++++++++++++++++ .../cloud/api/commands/StopSystemVm2Cmd.java | 105 +++++++++++++++++ .../consoleproxy/ConsoleProxyManagerImpl.java | 8 +- .../router/DomainRouterManagerImpl.java | 10 +- .../com/cloud/server/ManagementServer.java | 6 + .../cloud/server/ManagementServerImpl.java | 72 ++++++++++++ 8 files changed, 320 insertions(+), 17 deletions(-) create mode 100644 server/src/com/cloud/api/commands/StartSystemVm2Cmd.java create mode 100644 server/src/com/cloud/api/commands/StopSystemVm2Cmd.java diff --git a/client/tomcatconf/commands.properties.in b/client/tomcatconf/commands.properties.in index f2eb4b68d13..bb98211053a 100755 --- a/client/tomcatconf/commands.properties.in +++ b/client/tomcatconf/commands.properties.in @@ -33,11 +33,11 @@ updateResourceLimit=com.cloud.api.commands.UpdateResourceLimitCmd;3 listResourceLimits=com.cloud.api.commands.ListResourceLimitsCmd;15 #### VM commands -deployVirtualMachine=com.cloud.api.commands.DeployVMCmd;11 -destroyVirtualMachine=com.cloud.api.commands.DestroyVMCmd;15 +deployVirtualMachine=com.cloud.api.commands.DeployVm2Cmd;11 +destroyVirtualMachine=com.cloud.api.commands.DestroyVm2Cmd;15 rebootVirtualMachine=com.cloud.api.commands.RebootVMCmd;15 -startVirtualMachine=com.cloud.api.commands.StartVMCmd;15 -stopVirtualMachine=com.cloud.api.commands.StopVMCmd;15 +startVirtualMachine=com.cloud.api.commands.StartVm2Cmd;15 +stopVirtualMachine=com.cloud.api.commands.StopVm2Cmd;15 resetPasswordForVirtualMachine=com.cloud.api.commands.ResetVMPasswordCmd;15 changeServiceForVirtualMachine=com.cloud.api.commands.UpgradeVMCmd;15 updateVirtualMachine=com.cloud.api.commands.UpdateVMCmd;15 @@ -117,16 +117,16 @@ listLoadBalancerRules=com.cloud.api.commands.ListLoadBalancerRulesCmd;15 listLoadBalancerRuleInstances=com.cloud.api.commands.ListLoadBalancerRuleInstancesCmd;15 #### router commands -startRouter=com.cloud.api.commands.StartRouterCmd;3 +startRouter=com.cloud.api.commands.StartRouter2Cmd;3 rebootRouter=com.cloud.api.commands.RebootRouterCmd;3 -stopRouter=com.cloud.api.commands.StopRouterCmd;3 +stopRouter=com.cloud.api.commands.StopRouter2Cmd;3 changeServiceForRouter=com.cloud.api.commands.UpgradeRouterCmd;3 listRouters=com.cloud.api.commands.ListRoutersCmd;7 #### system vm commands -startSystemVm=com.cloud.api.commands.StartSystemVMCmd;1 +startSystemVm=com.cloud.api.commands.StartSystemVm2Cmd;1 rebootSystemVm=com.cloud.api.commands.RebootSystemVmCmd;1 -stopSystemVm=com.cloud.api.commands.StopSystemVmCmd;1 +stopSystemVm=com.cloud.api.commands.StopSystemVm2Cmd;1 listSystemVms=com.cloud.api.commands.ListSystemVMsCmd;1 #### configuration commands diff --git a/server/src/com/cloud/api/ApiServer.java b/server/src/com/cloud/api/ApiServer.java index 583567af40a..2978b8f4ce5 100755 --- a/server/src/com/cloud/api/ApiServer.java +++ b/server/src/com/cloud/api/ApiServer.java @@ -90,6 +90,7 @@ import com.cloud.exception.CloudAuthenticationException; import com.cloud.maid.StackMaid; import com.cloud.server.ManagementServer; import com.cloud.user.Account; +import com.cloud.user.AccountManager; import com.cloud.user.User; import com.cloud.user.UserAccount; import com.cloud.user.UserContext; @@ -113,6 +114,9 @@ public class ApiServer implements HttpRequestHandler { //private AsyncJobManager _asyncMgr; private ApiDispatcher _dispatcher; private ManagementServer _ms = null; + private AccountManager _accountMgr = null; + private Account _systemAccount = null; + private User _systemUser = null; private static int _workerCount = 0; @@ -187,6 +191,9 @@ public class ApiServer implements HttpRequestHandler { _ms = (ManagementServer)ComponentLocator.getComponent(ManagementServer.Name); ComponentLocator locator = ComponentLocator.getLocator(ManagementServer.Name); + _accountMgr = locator.getManager(AccountManager.class); + _systemAccount = _accountMgr.getSystemAccount(); + _systemUser = _accountMgr.getSystemUser(); //_asyncMgr = locator.getManager(AsyncJobManager.class); _dispatcher = ApiDispatcher.getInstance(); @@ -247,7 +254,7 @@ public class ApiServer implements HttpRequestHandler { } try { // always trust commands from API port, user context will always be UID_SYSTEM/ACCOUNT_ID_SYSTEM - UserContext.registerContext(User.UID_SYSTEM, null, null, Account.ACCOUNT_ID_SYSTEM, null, null, true); + UserContext.registerContext(_systemUser.getId(), _systemAccount, _systemAccount.getAccountName(), _systemAccount.getId(), null, null, true); sb.insert(0,"(userId="+User.UID_SYSTEM+ " accountId="+Account.ACCOUNT_ID_SYSTEM+ " sessionId="+null+ ") " ); String responseText = handleRequest(parameterMap, true, responseType, sb); sb.append(" 200 " + ((responseText == null) ? 0 : responseText.length())); @@ -362,7 +369,7 @@ public class ApiServer implements HttpRequestHandler { UserContext ctx = UserContext.current(); Long userId = ctx.getUserId(); - Account account = (Account)ctx.getAccount(); + Account account = ctx.getAccount(); if (userId != null) { params.put("ctxUserId", userId.toString()); } diff --git a/server/src/com/cloud/api/commands/StartSystemVm2Cmd.java b/server/src/com/cloud/api/commands/StartSystemVm2Cmd.java new file mode 100644 index 00000000000..86fc5dc2049 --- /dev/null +++ b/server/src/com/cloud/api/commands/StartSystemVm2Cmd.java @@ -0,0 +1,109 @@ +/** + * Copyright (C) 2010 Cloud.com, Inc. All rights reserved. + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package com.cloud.api.commands; + +import org.apache.log4j.Logger; + +import com.cloud.api.ApiConstants; +import com.cloud.api.ApiResponseHelper; +import com.cloud.api.BaseAsyncCmd; +import com.cloud.api.Implementation; +import com.cloud.api.Parameter; +import com.cloud.api.ServerApiException; +import com.cloud.api.response.SystemVmResponse; +import com.cloud.event.EventTypes; +import com.cloud.exception.ConcurrentOperationException; +import com.cloud.exception.InsufficientAddressCapacityException; +import com.cloud.exception.InsufficientCapacityException; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.exception.PermissionDeniedException; +import com.cloud.server.ManagementServer; +import com.cloud.user.Account; +import com.cloud.user.UserContext; +import com.cloud.vm.VMInstanceVO; +import com.cloud.vm.VirtualMachine; + +@Implementation(method="startSystemVM", manager=ManagementServer.class, description="Starts a system virtual machine.") +public class StartSystemVm2Cmd extends BaseAsyncCmd { + public static final Logger s_logger = Logger.getLogger(StartSystemVm2Cmd.class.getName()); + + private static final String s_name = "startsystemvmresponse"; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name=ApiConstants.ID, type=CommandType.LONG, required=true, description="The ID of the system virtual machine") + private Long id; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public Long getId() { + return id; + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public String getName() { + return s_name; + } + + public static String getResultObjectName() { + return "systemvm"; + } + + @Override + public long getAccountId() { + Account account = UserContext.current().getAccount(); + if (account != null) { + return account.getId(); + } + + return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this command to SYSTEM so ERROR events are tracked + } + + @Override + public String getEventType() { + return EventTypes.EVENT_SSVM_START; + } + + @Override + public String getEventDescription() { + return "starting system vm: " + getId(); + } + + @Override @SuppressWarnings("unchecked") + public SystemVmResponse getResponse() { + VMInstanceVO instance = (VMInstanceVO)getResponseObject(); + SystemVmResponse response = ApiResponseHelper.createSystemVmResponse(instance); + response.setResponseName(getName()); + return response; + } + + @Override + public Object execute() throws ServerApiException, InvalidParameterValueException, PermissionDeniedException, InsufficientAddressCapacityException, InsufficientCapacityException, ConcurrentOperationException{ + VirtualMachine result = _mgr.startSystemVm(this); + return result; + } +} diff --git a/server/src/com/cloud/api/commands/StopSystemVm2Cmd.java b/server/src/com/cloud/api/commands/StopSystemVm2Cmd.java new file mode 100644 index 00000000000..e869d9ea88d --- /dev/null +++ b/server/src/com/cloud/api/commands/StopSystemVm2Cmd.java @@ -0,0 +1,105 @@ +/** + * Copyright (C) 2010 Cloud.com, Inc. All rights reserved. + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package com.cloud.api.commands; + +import org.apache.log4j.Logger; + +import com.cloud.api.ApiConstants; +import com.cloud.api.ApiResponseHelper; +import com.cloud.api.BaseAsyncCmd; +import com.cloud.api.Implementation; +import com.cloud.api.Parameter; +import com.cloud.api.ServerApiException; +import com.cloud.api.response.SystemVmResponse; +import com.cloud.event.EventTypes; +import com.cloud.exception.ConcurrentOperationException; +import com.cloud.exception.InsufficientAddressCapacityException; +import com.cloud.exception.InsufficientCapacityException; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.exception.PermissionDeniedException; +import com.cloud.server.ManagementServer; +import com.cloud.user.Account; +import com.cloud.user.UserContext; +import com.cloud.vm.VMInstanceVO; +import com.cloud.vm.VirtualMachine; + +@Implementation(method="stopSystemVM", manager=ManagementServer.class, description="Stops a system VM.") +public class StopSystemVm2Cmd extends BaseAsyncCmd { + public static final Logger s_logger = Logger.getLogger(StopSystemVm2Cmd.class.getName()); + + private static final String s_name = "stopsystemvmresponse"; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name=ApiConstants.ID, type=CommandType.LONG, required=true, description="The ID of the system virtual machine") + private Long id; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public Long getId() { + return id; + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public String getName() { + return s_name; + } + + @Override + public long getAccountId() { + Account account = UserContext.current().getAccount(); + if (account != null) { + return account.getId(); + } + + return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this command to SYSTEM so ERROR events are tracked + } + + @Override + public String getEventType() { + return EventTypes.EVENT_SSVM_STOP; + } + + @Override + public String getEventDescription() { + return "stopping system vm: " + getId(); + } + + @Override @SuppressWarnings("unchecked") + public SystemVmResponse getResponse() { + VMInstanceVO instance = (VMInstanceVO)getResponseObject(); + SystemVmResponse response = ApiResponseHelper.createSystemVmResponse(instance); + response.setResponseName(getName()); + return response; + } + + @Override + public Object execute() throws ServerApiException, InvalidParameterValueException, PermissionDeniedException, InsufficientAddressCapacityException, InsufficientCapacityException, ConcurrentOperationException{ + VirtualMachine result = _mgr.stopSystemVm(this); + return result; + } +} diff --git a/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java b/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java index 369de47ef6b..e6ef7b5e576 100644 --- a/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java +++ b/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java @@ -531,7 +531,7 @@ public class ConsoleProxyManagerImpl implements ConsoleProxyManager, VirtualMach @Override public ConsoleProxyVO startProxy(long proxyVmId, long startEventId) { try { - return start(proxyVmId, startEventId); + return start2(proxyVmId, startEventId); } catch (StorageUnavailableException e) { s_logger.warn("Exception while trying to start console proxy", e); return null; @@ -887,7 +887,7 @@ public class ConsoleProxyManagerImpl implements ConsoleProxyManager, VirtualMach if (s_logger.isDebugEnabled()) s_logger.debug("Assign console proxy from a newly started instance for request from data center : " + dataCenterId); - Map context = createProxyInstance(dataCenterId); + Map context = createProxyInstance2(dataCenterId); long proxyVmId = (Long) context.get("proxyVmId"); if (proxyVmId == 0) { @@ -927,7 +927,7 @@ public class ConsoleProxyManagerImpl implements ConsoleProxyManager, VirtualMach if (s_logger.isDebugEnabled()) s_logger.debug("Assign console proxy from a newly started instance for request from data center : " + dataCenterId); - Map context = createProxyInstance(dataCenterId); + Map context = createProxyInstance2(dataCenterId); long proxyVmId = (Long) context.get("proxyVmId"); if (proxyVmId == 0) { @@ -1468,7 +1468,7 @@ public class ConsoleProxyManagerImpl implements ConsoleProxyManager, VirtualMach try { if (proxyLock.lock(ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_SYNC)) { try { - readyProxy = start(readyProxy.getId(), 0); + readyProxy = start2(readyProxy.getId(), 0); } finally { proxyLock.unlock(); } diff --git a/server/src/com/cloud/network/router/DomainRouterManagerImpl.java b/server/src/com/cloud/network/router/DomainRouterManagerImpl.java index 8adea84dcc0..6ab7e36212b 100644 --- a/server/src/com/cloud/network/router/DomainRouterManagerImpl.java +++ b/server/src/com/cloud/network/router/DomainRouterManagerImpl.java @@ -2371,7 +2371,11 @@ public class DomainRouterManagerImpl implements DomainRouterManager, DomainRoute @Override public DomainRouter stopRouter(StopRouter2Cmd cmd) throws ResourceUnavailableException, ConcurrentOperationException { Long routerId = cmd.getId(); - Account account = UserContext.current().getAccount(); + UserContext context = UserContext.current(); + Account account = context.getAccount(); + long accountId = context.getAccountId(); + long userId = context.getUserId(); + // verify parameters DomainRouterVO router = _routerDao.findById(routerId); @@ -2381,9 +2385,9 @@ public class DomainRouterManagerImpl implements DomainRouterManager, DomainRoute _accountMgr.checkAccess(account, router); - long eventId = EventUtils.saveScheduledEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, EventTypes.EVENT_ROUTER_STOP, "stopping Router with Id: "+routerId); + long eventId = EventUtils.saveScheduledEvent(userId, accountId, EventTypes.EVENT_ROUTER_STOP, "stopping Router with Id: "+routerId); - UserVO user = _userDao.findById(UserContext.current().getUserId()); + UserVO user = _userDao.findById(context.getUserId()); try { if (!_itMgr.stop(router, user, account)) { diff --git a/server/src/com/cloud/server/ManagementServer.java b/server/src/com/cloud/server/ManagementServer.java index e86dc14b6c8..651b135d4e5 100755 --- a/server/src/com/cloud/server/ManagementServer.java +++ b/server/src/com/cloud/server/ManagementServer.java @@ -71,6 +71,8 @@ import com.cloud.api.commands.RebootSystemVmCmd; import com.cloud.api.commands.RegisterCmd; import com.cloud.api.commands.RegisterPreallocatedLunCmd; import com.cloud.api.commands.StartSystemVMCmd; +import com.cloud.api.commands.StartSystemVm2Cmd; +import com.cloud.api.commands.StopSystemVm2Cmd; import com.cloud.api.commands.StopSystemVmCmd; import com.cloud.api.commands.UpdateDomainCmd; import com.cloud.api.commands.UpdateIPForwardingRuleCmd; @@ -144,6 +146,7 @@ import com.cloud.vm.VirtualMachine; */ public interface ManagementServer { static final String Name = "management-server"; + List listClusterByPodId(long podId); @@ -679,6 +682,9 @@ public interface ManagementServer { VMInstanceVO stopSystemVM(StopSystemVmCmd cmd); VMInstanceVO startSystemVM(StartSystemVMCmd cmd); VMInstanceVO rebootSystemVM(RebootSystemVmCmd cmd); + + VirtualMachine startSystemVm(StartSystemVm2Cmd cmd); + VirtualMachine stopSystemVm(StopSystemVm2Cmd cmd); /** * Returns a configuration value with the specified name diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java index 1a42309ecb0..6f3cbfe163c 100755 --- a/server/src/com/cloud/server/ManagementServerImpl.java +++ b/server/src/com/cloud/server/ManagementServerImpl.java @@ -121,6 +121,8 @@ import com.cloud.api.commands.RebootSystemVmCmd; import com.cloud.api.commands.RegisterCmd; import com.cloud.api.commands.RegisterPreallocatedLunCmd; import com.cloud.api.commands.StartSystemVMCmd; +import com.cloud.api.commands.StartSystemVm2Cmd; +import com.cloud.api.commands.StopSystemVm2Cmd; import com.cloud.api.commands.StopSystemVmCmd; import com.cloud.api.commands.UpdateDomainCmd; import com.cloud.api.commands.UpdateIPForwardingRuleCmd; @@ -4796,6 +4798,76 @@ public class ManagementServerImpl implements ManagementServer { } } + @Override + public VirtualMachine startSystemVm(StartSystemVm2Cmd cmd) { + UserContext context = UserContext.current(); + long callerId = context.getUserId(); + long callerAccountId = context.getAccountId(); + + //verify input + Long id = cmd.getId(); + + VMInstanceVO systemVm = _vmInstanceDao.findByIdTypes(id, VirtualMachine.Type.ConsoleProxy, VirtualMachine.Type.SecondaryStorageVm); + if (systemVm == null) { + throw new InvalidParameterValueException("unable to find a system vm with id " + id); + } + + if (systemVm.getType() == VirtualMachine.Type.ConsoleProxy) { + long eventId = EventUtils.saveScheduledEvent(callerId, callerAccountId, EventTypes.EVENT_PROXY_START, "Starting console proxy with Id: "+id); + try { + checkIfStoragePoolAvailable(id); + } catch (StorageUnavailableException e) { + s_logger.warn(e.getMessage()); + return null; + } catch (Exception e){ + //unforseen exceptions + s_logger.warn(e.getMessage()); + return null; + } + return startConsoleProxy(id, eventId); + } else if (systemVm.getType() == VirtualMachine.Type.SecondaryStorageVm) { + long eventId = EventUtils.saveScheduledEvent(callerId, callerAccountId, EventTypes.EVENT_SSVM_START, "Starting secondary storage Vm Id: "+id); + try { + checkIfStoragePoolAvailable(id); + } catch (StorageUnavailableException e) { + s_logger.warn(e.getMessage()); + return null; + } catch (Exception e){ + //unforseen exceptions + s_logger.warn(e.getMessage()); + return null; + } + return startSecondaryStorageVm(id, eventId); + } else { + throw new InvalidParameterValueException("Unable to find a system vm: " + id); + } + } + + @Override + public VirtualMachine stopSystemVm(StopSystemVm2Cmd cmd) { + UserContext context = UserContext.current(); + + long callerId = context.getUserId(); + long callerAccountId = context.getAccountId(); + + Long id = cmd.getId(); + + // verify parameters + VMInstanceVO systemVm = _vmInstanceDao.findByIdTypes(id, VirtualMachine.Type.ConsoleProxy, VirtualMachine.Type.SecondaryStorageVm); + if (systemVm == null) { + throw new ServerApiException (BaseCmd.PARAM_ERROR, "unable to find a system vm with id " + id); + } + + // FIXME: We need to return the system VM from this method, so what do we do with the boolean response from stopConsoleProxy and stopSecondaryStorageVm? + if (systemVm.getType().equals(VirtualMachine.Type.ConsoleProxy)){ + long eventId = EventUtils.saveScheduledEvent(callerId, callerAccountId, EventTypes.EVENT_PROXY_STOP, "stopping console proxy with Id: "+id); + return stopConsoleProxy(id, eventId); + } else { + long eventId = EventUtils.saveScheduledEvent(callerId, callerAccountId, EventTypes.EVENT_SSVM_STOP, "stopping secondary storage Vm Id: "+id); + return stopSecondaryStorageVm(id, eventId); + } + } + private void checkIfStoragePoolAvailable(Long id) throws StorageUnavailableException { //check if the sp is up before starting List rootVolList = _volumeDao.findByInstanceAndType(id, VolumeType.ROOT);