http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/1b2b369e/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java ---------------------------------------------------------------------- diff --cc server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java index b9c3b98,132dbaa..a787079 --- a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java +++ b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java @@@ -39,12 -39,10 +39,12 @@@ import java.util.concurrent.ScheduledEx import java.util.concurrent.TimeUnit; import javax.ejb.Local; +import javax.inject.Inject; import javax.naming.ConfigurationException; - import org.apache.cloudstack.api.command.admin.router.UpgradeRouterCmd; + import com.cloud.agent.api.to.*; import org.apache.log4j.Logger; +import org.springframework.stereotype.Component; import com.cloud.agent.AgentManager; import com.cloud.agent.AgentManager.OnError; @@@ -2253,17 -2271,17 +2287,17 @@@ public class VirtualNetworkApplianceMan } } } - + - //Re-apply static nats + // Re-apply static nats s_logger.debug("Found " + staticNats.size() + " static nat(s) to apply as a part of domR " + router + " start."); if (!staticNats.isEmpty()) { createApplyStaticNatCommands(staticNats, router, cmds, guestNetworkId); } - + - //Re-apply firewall rules - s_logger.debug("Found " + staticNats.size() + " firewall rule(s) to apply as a part of domR " + router + " start."); - if (!firewallRules.isEmpty()) { - createFirewallRulesCommands(firewallRules, router, cmds, guestNetworkId); + // Re-apply firewall Ingress rules + s_logger.debug("Found " + firewallRulesIngress.size() + " firewall Ingress rule(s) to apply as a part of domR " + router + " start."); + if (!firewallRulesIngress.isEmpty()) { + createFirewallRulesCommands(firewallRulesIngress, router, cmds, guestNetworkId); } // Re-apply port forwarding rules @@@ -3248,13 -3266,18 +3282,18 @@@ if (rules != null) { rulesTO = new ArrayList<FirewallRuleTO>(); for (FirewallRule rule : rules) { + FirewallRule.TrafficType traffictype = rule.getTrafficType(); + if(traffictype == FirewallRule.TrafficType.Ingress){ - IpAddress sourceIp = _networkModel.getIp(rule.getSourceIpAddressId()); + IpAddress sourceIp = _networkModel.getIp(rule.getSourceIpAddressId()); - if (rule.getSourceCidrList() == null && (rule.getPurpose() == Purpose.Firewall || rule.getPurpose() == Purpose.NetworkACL)) { - _rulesDao.loadSourceCidrs((FirewallRuleVO)rule); - } - FirewallRuleTO ruleTO = new FirewallRuleTO(rule, null, sourceIp.getAddress().addr()); + FirewallRuleTO ruleTO = new FirewallRuleTO(rule, null, sourceIp.getAddress().addr(),Purpose.Firewall,traffictype); - rulesTO.add(ruleTO); - } + rulesTO.add(ruleTO); + } + else if (rule.getTrafficType() == FirewallRule.TrafficType.Egress){ + assert (rule.getSourceIpAddressId()==null) : "ipAddressId should be null for egress firewall rule. "; + FirewallRuleTO ruleTO = new FirewallRuleTO(rule, null,"",Purpose.Firewall,traffictype); + rulesTO.add(ruleTO); + } + } } SetFirewallRulesCommand cmd = new SetFirewallRulesCommand(rulesTO);
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/1b2b369e/server/src/com/cloud/network/rules/FirewallManager.java ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/1b2b369e/server/src/com/cloud/network/rules/FirewallRuleVO.java ---------------------------------------------------------------------- diff --cc server/src/com/cloud/network/rules/FirewallRuleVO.java index 83057e0,e493673..a761520 --- a/server/src/com/cloud/network/rules/FirewallRuleVO.java +++ b/server/src/com/cloud/network/rules/FirewallRuleVO.java @@@ -84,8 -87,8 +84,8 @@@ public class FirewallRuleVO implements Date created; @Column(name="network_id") - long networkId; + Long networkId; - + @Column(name="icmp_code") Integer icmpCode; http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/1b2b369e/server/src/com/cloud/network/rules/RulesManagerImpl.java ---------------------------------------------------------------------- diff --cc server/src/com/cloud/network/rules/RulesManagerImpl.java index 0062b26,fe86a8e..c65f2d9 --- a/server/src/com/cloud/network/rules/RulesManagerImpl.java +++ b/server/src/com/cloud/network/rules/RulesManagerImpl.java @@@ -214,10 -201,10 +214,10 @@@ public class RulesManagerImpl extends M if (ipAddress.getAssociatedWithNetworkId() == null) { throw new InvalidParameterValueException("Ip address " + ipAddress + " is not assigned to the network " + network); } - + try { _firewallMgr.validateFirewallRule(caller, ipAddress, rule.getSourcePortStart(), rule.getSourcePortEnd(), - rule.getProtocol(), Purpose.PortForwarding, FirewallRuleType.User); + rule.getProtocol(), Purpose.PortForwarding, FirewallRuleType.User, networkId, rule.getTrafficType()); Long accountId = ipAddress.getAllocatedToAccountId(); Long domainId = ipAddress.getAllocatedInDomainId(); http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/1b2b369e/server/src/com/cloud/network/vpn/RemoteAccessVpnManagerImpl.java ---------------------------------------------------------------------- diff --cc server/src/com/cloud/network/vpn/RemoteAccessVpnManagerImpl.java index a99e332,e360bca..d4b2424 --- a/server/src/com/cloud/network/vpn/RemoteAccessVpnManagerImpl.java +++ b/server/src/com/cloud/network/vpn/RemoteAccessVpnManagerImpl.java @@@ -261,16 -262,16 +261,16 @@@ public class RemoteAccessVpnManagerImp _firewallMgr.revokeRelatedFirewallRule(vpnFwRule.getId(), false); fwRules.add(_rulesDao.findByRelatedId(vpnFwRule.getId())); } - + s_logger.debug("Marked " + fwRules.size() + " firewall rules as Revoked as a part of disable remote access vpn"); - + txn.commit(); - + //now apply vpn rules on the backend s_logger.debug("Reapplying firewall rules for ip id=" + ipId + " as a part of disable remote access vpn"); - success = _firewallMgr.applyFirewallRules(ipId, caller); + success = _firewallMgr.applyIngressFirewallRules(ipId, caller); } - + if (success) { try { txn.start(); @@@ -382,9 -383,9 +382,9 @@@ try { boolean firewallOpened = true; if (openFirewall) { - firewallOpened = _firewallMgr.applyFirewallRules(vpn.getServerAddressId(), caller); + firewallOpened = _firewallMgr.applyIngressFirewallRules(vpn.getServerAddressId(), caller); } - + if (firewallOpened) { for (RemoteAccessVPNServiceProvider element : _vpnServiceProviders) { if (element.startVpn(network, vpn)) { http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/1b2b369e/server/src/com/cloud/server/ManagementServerImpl.java ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/1b2b369e/server/src/com/cloud/user/DomainManagerImpl.java ---------------------------------------------------------------------- diff --cc server/src/com/cloud/user/DomainManagerImpl.java index 5d39360,791f581..e80da9f --- a/server/src/com/cloud/user/DomainManagerImpl.java +++ b/server/src/com/cloud/user/DomainManagerImpl.java @@@ -348,7 -368,9 +348,9 @@@ public class DomainManagerImpl extends } _accountMgr.checkAccess(caller, domain); } else { + if (caller.getType() != Account.ACCOUNT_TYPE_ADMIN) { - domainId = caller.getDomainId(); + domainId = caller.getDomainId(); + } if (listAll) { isRecursive = true; } http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/1b2b369e/server/src/com/cloud/vm/UserVmManagerImpl.java ---------------------------------------------------------------------- diff --cc server/src/com/cloud/vm/UserVmManagerImpl.java index 8dd83c6,3737450..dd60da7 --- a/server/src/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/com/cloud/vm/UserVmManagerImpl.java @@@ -16,61 -16,9 +16,67 @@@ // under the License. package com.cloud.vm; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +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.cloudstack.acl.ControlledEntity.ACLType; +import org.apache.cloudstack.acl.SecurityChecker.AccessType; +import org.apache.cloudstack.api.BaseCmd; +import org.apache.cloudstack.api.command.admin.vm.AssignVMCmd; +import org.apache.cloudstack.api.command.admin.vm.RecoverVMCmd; +import org.apache.cloudstack.api.command.user.template.CreateTemplateCmd; ++import org.apache.cloudstack.api.command.user.vm.AddNicToVMCmd; +import org.apache.cloudstack.api.command.user.vm.DeployVMCmd; +import org.apache.cloudstack.api.command.user.vm.DestroyVMCmd; +import org.apache.cloudstack.api.command.user.vm.RebootVMCmd; ++import org.apache.cloudstack.api.command.user.vm.RemoveNicFromVMCmd; +import org.apache.cloudstack.api.command.user.vm.ResetVMPasswordCmd; ++import org.apache.cloudstack.api.command.user.vm.ResetVMSSHKeyCmd; +import org.apache.cloudstack.api.command.user.vm.RestoreVMCmd; +import org.apache.cloudstack.api.command.user.vm.StartVMCmd; ++import org.apache.cloudstack.api.command.user.vm.UpdateDefaultNicForVMCmd; +import org.apache.cloudstack.api.command.user.vm.UpdateVMCmd; +import org.apache.cloudstack.api.command.user.vm.UpgradeVMCmd; +import org.apache.cloudstack.api.command.user.vmgroup.CreateVMGroupCmd; +import org.apache.cloudstack.api.command.user.vmgroup.DeleteVMGroupCmd; +import org.apache.cloudstack.api.command.user.volume.AttachVolumeCmd; +import org.apache.cloudstack.api.command.user.volume.DetachVolumeCmd; + +import org.apache.cloudstack.engine.cloud.entity.api.VirtualMachineEntity; +import org.apache.cloudstack.engine.service.api.OrchestrationService; +import org.apache.commons.codec.binary.Base64; +import org.apache.log4j.Logger; + import com.cloud.agent.AgentManager; +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.AttachIsoCommand; +import com.cloud.agent.api.AttachVolumeAnswer; +import com.cloud.agent.api.AttachVolumeCommand; +import com.cloud.agent.api.ComputeChecksumCommand; +import com.cloud.agent.api.CreatePrivateTemplateFromSnapshotCommand; +import com.cloud.agent.api.CreatePrivateTemplateFromVolumeCommand; +import com.cloud.agent.api.GetVmStatsAnswer; +import com.cloud.agent.api.GetVmStatsCommand; +import com.cloud.agent.api.SnapshotCommand; +import com.cloud.agent.api.StartAnswer; +import com.cloud.agent.api.StopAnswer; +import com.cloud.agent.api.UpgradeSnapshotCommand; +import com.cloud.agent.api.VmStatsEntry; + import com.cloud.agent.AgentManager.OnError; + import com.cloud.agent.api.*; import com.cloud.agent.api.storage.CreatePrivateTemplateAnswer; import com.cloud.agent.api.to.NicTO; import com.cloud.agent.api.to.VirtualMachineTO; @@@ -105,17 -56,7 +115,18 @@@ import com.cloud.event.ActionEvent import com.cloud.event.EventTypes; import com.cloud.event.UsageEventVO; import com.cloud.event.dao.UsageEventDao; -import com.cloud.exception.*; ++import com.cloud.exception.AgentUnavailableException; +import com.cloud.exception.CloudException; +import com.cloud.exception.ConcurrentOperationException; +import com.cloud.exception.InsufficientCapacityException; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.exception.ManagementServerException; +import com.cloud.exception.OperationTimedoutException; +import com.cloud.exception.PermissionDeniedException; +import com.cloud.exception.ResourceAllocationException; +import com.cloud.exception.ResourceUnavailableException; +import com.cloud.exception.StorageUnavailableException; +import com.cloud.exception.VirtualMachineMigrationException; import com.cloud.ha.HighAvailabilityManager; import com.cloud.host.Host; import com.cloud.host.HostVO; @@@ -201,15 -106,7 +212,16 @@@ import com.cloud.storage.snapshot.Snaps import com.cloud.tags.dao.ResourceTagDao; import com.cloud.template.VirtualMachineTemplate; import com.cloud.template.VirtualMachineTemplate.BootloaderType; -import com.cloud.user.*; +import com.cloud.user.Account; +import com.cloud.user.AccountManager; +import com.cloud.user.AccountService; +import com.cloud.user.AccountVO; +import com.cloud.user.ResourceLimitService; +import com.cloud.user.SSHKeyPair; ++import com.cloud.user.SSHKeyPairVO; +import com.cloud.user.User; +import com.cloud.user.UserContext; +import com.cloud.user.UserVO; import com.cloud.user.dao.AccountDao; import com.cloud.user.dao.SSHKeyPairDao; import com.cloud.user.dao.UserDao; @@@ -1182,8 -1032,239 +1304,240 @@@ public class UserVmManagerImpl extends } @Override + public UserVm addNicToVirtualMachine(AddNicToVMCmd cmd) throws InvalidParameterValueException, PermissionDeniedException, CloudRuntimeException { + Long vmId = cmd.getVmId(); + Long networkId = cmd.getNetworkId(); + String ipAddress = cmd.getIpAddress(); + Account caller = UserContext.current().getCaller(); + + UserVmVO vmInstance = _vmDao.findById(vmId); + if(vmInstance == null) { + throw new InvalidParameterValueException("unable to find a virtual machine with id " + vmId); + } + NetworkVO network = _networkDao.findById(networkId); + if(network == null) { + throw new InvalidParameterValueException("unable to find a network with id " + networkId); + } + NicProfile profile = new NicProfile(null); + if(ipAddress != null) { + profile = new NicProfile(ipAddress); + } + + // Perform permission check on VM + _accountMgr.checkAccess(caller, null, true, vmInstance); + + // Verify that zone is not Basic - DataCenterVO dc = _dcDao.findById(vmInstance.getDataCenterIdToDeployIn()); ++ DataCenterVO dc = _dcDao.findById(vmInstance.getDataCenterId()); + if (dc.getNetworkType() == DataCenter.NetworkType.Basic) { - throw new CloudRuntimeException("Zone " + vmInstance.getDataCenterIdToDeployIn() + ", has a NetworkType of Basic. Can't add a new NIC to a VM on a Basic Network"); ++ throw new CloudRuntimeException("Zone " + vmInstance.getDataCenterId() + ", has a NetworkType of Basic. Can't add a new NIC to a VM on a Basic Network"); + } + + // Perform account permission check on network + if (network.getGuestType() != Network.GuestType.Shared) { + // Check account permissions + List<NetworkVO> networkMap = _networkDao.listBy(caller.getId(), network.getId()); + if ((networkMap == null || networkMap.isEmpty() ) && caller.getType() != Account.ACCOUNT_TYPE_ADMIN) { + throw new PermissionDeniedException("Unable to modify a vm using network with id " + network.getId() + ", permission denied"); + } + } + + //ensure network belongs in zone - if (network.getDataCenterId() != vmInstance.getDataCenterIdToDeployIn()) { - throw new CloudRuntimeException(vmInstance + " is in zone:" + vmInstance.getDataCenterIdToDeployIn() + " but " + network + " is in zone:" + network.getDataCenterId()); ++ if (network.getDataCenterId() != vmInstance.getDataCenterId()) { ++ throw new CloudRuntimeException(vmInstance + " is in zone:" + vmInstance.getDataCenterId() + " but " + network + " is in zone:" + network.getDataCenterId()); + } + + if(_networkModel.getNicInNetwork(vmInstance.getId(),network.getId()) != null){ + s_logger.debug(vmInstance + " already in " + network + " going to add another NIC"); + } else { + //* get all vms hostNames in the network + List<String> hostNames = _vmInstanceDao.listDistinctHostNames(network.getId()); + //* verify that there are no duplicates + if (hostNames.contains(vmInstance.getHostName())) { + throw new CloudRuntimeException(network + " already has a vm with host name: '" + vmInstance.getHostName()); + } + } + + NicProfile guestNic = null; + + try { + guestNic = _itMgr.addVmToNetwork(vmInstance, network, profile); + } catch (ResourceUnavailableException e) { + throw new CloudRuntimeException("Unable to add NIC to " + vmInstance + ": " + e); + } catch (InsufficientCapacityException e) { + throw new CloudRuntimeException("Insufficient capacity when adding NIC to " + vmInstance + ": " + e); + } catch (ConcurrentOperationException e) { + throw new CloudRuntimeException("Concurrent operations on adding NIC to " + vmInstance + ": " +e); + } + if (guestNic == null) { + throw new CloudRuntimeException("Unable to add NIC to " + vmInstance); + } + + s_logger.debug("Successful addition of " + network + " from " + vmInstance); + return _vmDao.findById(vmInstance.getId()); + } + + @Override + public UserVm removeNicFromVirtualMachine(RemoveNicFromVMCmd cmd) throws InvalidParameterValueException, PermissionDeniedException, CloudRuntimeException { + Long vmId = cmd.getVmId(); + Long nicId = cmd.getNicId(); + Account caller = UserContext.current().getCaller(); + + UserVmVO vmInstance = _vmDao.findById(vmId); + if(vmInstance == null) { + throw new InvalidParameterValueException("unable to find a virtual machine with id " + vmId); + } + NicVO nic = _nicDao.findById(nicId); + if (nic == null){ + throw new InvalidParameterValueException("unable to find a nic with id " + nicId); + } + NetworkVO network = _networkDao.findById(nic.getNetworkId()); + if(network == null) { + throw new InvalidParameterValueException("unable to find a network with id " + nic.getNetworkId()); + } + + // Perform permission check on VM + _accountMgr.checkAccess(caller, null, true, vmInstance); + + // Verify that zone is not Basic - DataCenterVO dc = _dcDao.findById(vmInstance.getDataCenterIdToDeployIn()); ++ DataCenterVO dc = _dcDao.findById(vmInstance.getDataCenterId()); + if (dc.getNetworkType() == DataCenter.NetworkType.Basic) { - throw new CloudRuntimeException("Zone " + vmInstance.getDataCenterIdToDeployIn() + ", has a NetworkType of Basic. Can't remove a NIC from a VM on a Basic Network"); ++ throw new CloudRuntimeException("Zone " + vmInstance.getDataCenterId() + ", has a NetworkType of Basic. Can't remove a NIC from a VM on a Basic Network"); + } + + //check to see if nic is attached to VM + if (nic.getInstanceId() != vmId) { + throw new InvalidParameterValueException(nic + " is not a nic on " + vmInstance); + } + + // Perform account permission check on network + if (network.getGuestType() != Network.GuestType.Shared) { + // Check account permissions + List<NetworkVO> networkMap = _networkDao.listBy(caller.getId(), network.getId()); + if ((networkMap == null || networkMap.isEmpty() ) && caller.getType() != Account.ACCOUNT_TYPE_ADMIN) { + throw new PermissionDeniedException("Unable to modify a vm using network with id " + network.getId() + ", permission denied"); + } + } + + boolean nicremoved = false; + + try { + nicremoved = _itMgr.removeNicFromVm(vmInstance, nic); + } catch (ResourceUnavailableException e) { + throw new CloudRuntimeException("Unable to remove " + network + " from " + vmInstance +": " + e); + + } catch (ConcurrentOperationException e) { + throw new CloudRuntimeException("Concurrent operations on removing " + network + " from " + vmInstance + ": " + e); + } + + if (!nicremoved) { + throw new CloudRuntimeException("Unable to remove " + network + " from " + vmInstance ); + } + + s_logger.debug("Successful removal of " + network + " from " + vmInstance); + return _vmDao.findById(vmInstance.getId()); + + + } + + @Override + public UserVm updateDefaultNicForVirtualMachine(UpdateDefaultNicForVMCmd cmd) throws InvalidParameterValueException, CloudRuntimeException { + Long vmId = cmd.getVmId(); + Long nicId = cmd.getNicId(); + Account caller = UserContext.current().getCaller(); + + UserVmVO vmInstance = _vmDao.findById(vmId); + if (vmInstance == null){ + throw new InvalidParameterValueException("unable to find a virtual machine with id " + vmId); + } + NicVO nic = _nicDao.findById(nicId); + if (nic == null){ + throw new InvalidParameterValueException("unable to find a nic with id " + nicId); + } + NetworkVO network = _networkDao.findById(nic.getNetworkId()); + if (network == null){ + throw new InvalidParameterValueException("unable to find a network with id " + nic.getNetworkId()); + } + + // Perform permission check on VM + _accountMgr.checkAccess(caller, null, true, vmInstance); + + // Verify that zone is not Basic - DataCenterVO dc = _dcDao.findById(vmInstance.getDataCenterIdToDeployIn()); ++ DataCenterVO dc = _dcDao.findById(vmInstance.getDataCenterId()); + if (dc.getNetworkType() == DataCenter.NetworkType.Basic) { - throw new CloudRuntimeException("Zone " + vmInstance.getDataCenterIdToDeployIn() + ", has a NetworkType of Basic. Can't change default NIC on a Basic Network"); ++ throw new CloudRuntimeException("Zone " + vmInstance.getDataCenterId() + ", has a NetworkType of Basic. Can't change default NIC on a Basic Network"); + } + + // no need to check permissions for network, we'll enumerate the ones they already have access to + Network existingdefaultnet = _networkModel.getDefaultNetworkForVm(vmId); + + //check to see if nic is attached to VM + if (nic.getInstanceId() != vmId) { + throw new InvalidParameterValueException(nic + " is not a nic on " + vmInstance); + } + // if current default equals chosen new default, Throw an exception + if (nic.isDefaultNic()){ + throw new CloudRuntimeException("refusing to set default nic because chosen nic is already the default"); + } + + //make sure the VM is Running or Stopped + if ((vmInstance.getState() != State.Running) && (vmInstance.getState() != State.Stopped)) { + throw new CloudRuntimeException("refusing to set default " + vmInstance + " is not Running or Stopped"); + } + + NicProfile existing = null; + List<NicProfile> nicProfiles = _networkMgr.getNicProfiles(vmInstance); + for (NicProfile nicProfile : nicProfiles) { + if(nicProfile.isDefaultNic() && nicProfile.getNetworkId() == existingdefaultnet.getId()){ + existing = nicProfile; + continue; + } + } + + if (existing == null){ + s_logger.warn("Failed to update default nic, no nic profile found for existing default network"); + throw new CloudRuntimeException("Failed to find a nic profile for the existing default network. This is bad and probably means some sort of configuration corruption"); + } + + NicVO existingVO = _nicDao.findById(existing.id); + Integer chosenID = nic.getDeviceId(); + Integer existingID = existing.getDeviceId(); + + nic.setDefaultNic(true); + nic.setDeviceId(existingID); + existingVO.setDefaultNic(false); + existingVO.setDeviceId(chosenID); + + nic = _nicDao.persist(nic); + existingVO = _nicDao.persist(existingVO); + + Network newdefault = null; + newdefault = _networkModel.getDefaultNetworkForVm(vmId); + + if (newdefault == null){ + nic.setDefaultNic(false); + nic.setDeviceId(chosenID); + existingVO.setDefaultNic(true); + existingVO.setDeviceId(existingID); + + nic = _nicDao.persist(nic); + existingVO = _nicDao.persist(existingVO); + + newdefault = _networkModel.getDefaultNetworkForVm(vmId); + if (newdefault.getId() == existingdefaultnet.getId()) { + throw new CloudRuntimeException("Setting a default nic failed, and we had no default nic, but we were able to set it back to the original"); + } + throw new CloudRuntimeException("Failed to change default nic to " + nic + " and now we have no default"); + } else if (newdefault.getId() == nic.getNetworkId()) { + s_logger.debug("successfully set default network to " + network + " for " + vmInstance); + return _vmDao.findById(vmInstance.getId()); + } + + throw new CloudRuntimeException("something strange happened, new default network(" + newdefault.getId() + ") is not null, and is not equal to the network(" + nic.getNetworkId() + ") of the chosen nic"); + } + + @Override - public HashMap<Long, VmStatsEntry> getVirtualMachineStatistics(long hostId, String hostName, List<Long> vmIds) throws CloudRuntimeException { + public HashMap<Long, VmStatsEntry> getVirtualMachineStatistics(long hostId, + String hostName, List<Long> vmIds) throws CloudRuntimeException { HashMap<Long, VmStatsEntry> vmStatsById = new HashMap<Long, VmStatsEntry>(); if (vmIds.isEmpty()) { @@@ -1364,16 -1415,11 +1718,10 @@@ String time = configs.get("expunge.interval"); _expungeInterval = NumbersUtil.parseInt(time, 86400); - if (_expungeInterval < 600) { - _expungeInterval = 600; - } - time = configs.get("expunge.delay"); _expungeDelay = NumbersUtil.parseInt(time, _expungeInterval); - if (_expungeDelay < 600) { - _expungeDelay = 600; - } - _executor = Executors.newScheduledThreadPool(wrks, - new NamedThreadFactory("UserVm-Scavenger")); + + _executor = Executors.newScheduledThreadPool(wrks, new NamedThreadFactory("UserVm-Scavenger")); _itMgr.registerGuru(VirtualMachine.Type.User, this); @@@ -2014,13 -1939,12 +2362,12 @@@ UserVmVO vm = _vmDao.findById(vmId); - if (vm != null) { if (vm.getState().equals(State.Stopped)) { - s_logger.debug("Destroying vm " + vm - + " as it failed to create"); + s_logger.debug("Destroying vm " + vm + " as it failed to create on Host with Id:" + hostId); try { - _itMgr.stateTransitTo(vm, VirtualMachine.Event.OperationFailedToError, null); + _itMgr.stateTransitTo(vm, + VirtualMachine.Event.OperationFailedToError, null); } catch (NoTransitionException e1) { s_logger.warn(e1.getMessage()); } @@@ -2034,18 -1957,13 +2381,16 @@@ _storageMgr.destroyVolume(volume); } } catch (ConcurrentOperationException e) { - s_logger.warn("Unable to delete volume:" + volume.getId() + " for vm:" + vmId + " whilst transitioning to error state"); + s_logger.warn("Unable to delete volume:" + + volume.getId() + " for vm:" + vmId + + " whilst transitioning to error state"); } } - String msg = "Failed to deploy Vm with Id: " + vmId; - _alertMgr.sendAlert(AlertManager.ALERT_TYPE_USERVM, - vm.getDataCenterId(), - vm.getPodIdToDeployIn(), msg, msg); + String msg = "Failed to deploy Vm with Id: " + vmId + ", on Host with Id: " + hostId; - _alertMgr.sendAlert(AlertManager.ALERT_TYPE_USERVM, vm.getDataCenterIdToDeployIn(), vm.getPodIdToDeployIn(), msg, msg); ++ _alertMgr.sendAlert(AlertManager.ALERT_TYPE_USERVM, vm.getDataCenterId(), vm.getPodIdToDeployIn(), msg, msg); - _resourceLimitMgr.decrementResourceCount(vm.getAccountId(), ResourceType.user_vm); + _resourceLimitMgr.decrementResourceCount(vm.getAccountId(), + ResourceType.user_vm); } } } @@@ -4501,21 -4011,60 +4845,60 @@@ @Override public boolean plugNic(Network network, NicTO nic, VirtualMachineTO vm, - ReservationContext context, DeployDestination dest) throws ConcurrentOperationException, ResourceUnavailableException, - InsufficientCapacityException { + ReservationContext context, DeployDestination dest) + throws ConcurrentOperationException, ResourceUnavailableException, + InsufficientCapacityException { - // not supported - throw new UnsupportedOperationException( - "Plug nic is not supported for vm of type " + vm.getType()); + UserVmVO vmVO = _vmDao.findById(vm.getId()); + if (vmVO.getState() == State.Running) { + try { + PlugNicCommand plugNicCmd = new PlugNicCommand(nic,vm.getName()); + Commands cmds = new Commands(OnError.Stop); + cmds.addCommand("plugnic",plugNicCmd); + _agentMgr.send(dest.getHost().getId(),cmds); + PlugNicAnswer plugNicAnswer = cmds.getAnswer(PlugNicAnswer.class); + if (!(plugNicAnswer != null && plugNicAnswer.getResult())) { + s_logger.warn("Unable to plug nic for " + vmVO); + return false; + } + } catch (OperationTimedoutException e) { + throw new AgentUnavailableException("Unable to plug nic for " + vmVO + " in network " + network, dest.getHost().getId(), e); + } + } else if (vmVO.getState() == State.Stopped || vmVO.getState() == State.Stopping) { + s_logger.warn(vmVO + " is Stopped, not sending PlugNicCommand. Currently " + vmVO.getState()); + } else { + s_logger.warn("Unable to plug nic, " + vmVO + " is not in the right state " + vmVO.getState()); + throw new ResourceUnavailableException("Unable to plug nic on the backend," + - vmVO + " is not in the right state", DataCenter.class, vmVO.getDataCenterIdToDeployIn()); ++ vmVO + " is not in the right state", DataCenter.class, vmVO.getDataCenterId()); + } + return true; } - @Override public boolean unplugNic(Network network, NicTO nic, VirtualMachineTO vm, - ReservationContext context, DeployDestination dest) - throws ConcurrentOperationException, ResourceUnavailableException { - // not supported - throw new UnsupportedOperationException( - "Unplug nic is not supported for vm of type " + vm.getType()); + ReservationContext context, DeployDestination dest) throws ConcurrentOperationException, ResourceUnavailableException { + UserVmVO vmVO = _vmDao.findById(vm.getId()); + if (vmVO.getState() == State.Running) { + try { + UnPlugNicCommand unplugNicCmd = new UnPlugNicCommand(nic,vm.getName()); + Commands cmds = new Commands(OnError.Stop); + cmds.addCommand("unplugnic",unplugNicCmd); + _agentMgr.send(dest.getHost().getId(),cmds); + UnPlugNicAnswer unplugNicAnswer = cmds.getAnswer(UnPlugNicAnswer.class); + if (!(unplugNicAnswer != null && unplugNicAnswer.getResult())) { + s_logger.warn("Unable to unplug nic for " + vmVO); + return false; + } + } catch (OperationTimedoutException e) { + throw new AgentUnavailableException("Unable to unplug nic for " + vmVO + " in network " + network, dest.getHost().getId(), e); + } + } else if (vmVO.getState() == State.Stopped || vmVO.getState() == State.Stopping) { + s_logger.warn(vmVO + " is Stopped, not sending UnPlugNicCommand. Currently " + vmVO.getState()); + } else { + s_logger.warn("Unable to unplug nic, " + vmVO + " is not in the right state " + vmVO.getState()); + throw new ResourceUnavailableException("Unable to unplug nic on the backend," + - vmVO + " is not in the right state", DataCenter.class, vmVO.getDataCenterIdToDeployIn()); ++ vmVO + " is not in the right state", DataCenter.class, vmVO.getDataCenterId()); + } + return true; } @Override http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/1b2b369e/server/src/com/cloud/vm/VirtualMachineManager.java ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/1b2b369e/server/src/com/cloud/vm/VirtualMachineManagerImpl.java ---------------------------------------------------------------------- diff --cc server/src/com/cloud/vm/VirtualMachineManagerImpl.java index 9b00d7a,19756ad..1838ed2 --- a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java +++ b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java @@@ -2448,19 -2456,24 +2448,24 @@@ public class VirtualMachineManagerImpl vmForUpdate.setServiceOfferingId(newSvcOff.getId()); return _vmDao.update(vmId, vmForUpdate); } - + @Override public NicProfile addVmToNetwork(VirtualMachine vm, Network network, NicProfile requested) throws ConcurrentOperationException, - ResourceUnavailableException, InsufficientCapacityException { - + ResourceUnavailableException, InsufficientCapacityException { + s_logger.debug("Adding vm " + vm + " to network " + network + "; requested nic profile " + requested); - VMInstanceVO vmVO = _vmDao.findById(vm.getId()); + VMInstanceVO vmVO; + if (vm.getType() == VirtualMachine.Type.User) { + vmVO = _userVmDao.findById(vm.getId()); + } else { + vmVO = _vmDao.findById(vm.getId()); + } ReservationContext context = new ReservationContextImpl(null, null, _accountMgr.getActiveUser(User.UID_SYSTEM), _accountMgr.getAccount(Account.ACCOUNT_ID_SYSTEM)); - + VirtualMachineProfileImpl<VMInstanceVO> vmProfile = new VirtualMachineProfileImpl<VMInstanceVO>(vmVO, null, null, null, null); - + DataCenter dc = _configMgr.getZone(network.getDataCenterId()); Host host = _hostDao.findById(vm.getHostId()); DeployDestination dest = new DeployDestination(dc, null, null, host); @@@ -2506,8 -2518,63 +2510,63 @@@ NicTO nicTO = hvGuru.toNicTO(nic); return nicTO; } - + @Override + public boolean removeNicFromVm(VirtualMachine vm, NicVO nic) throws ConcurrentOperationException, ResourceUnavailableException { + VMInstanceVO vmVO = _vmDao.findById(vm.getId()); + NetworkVO network = _networkDao.findById(nic.getNetworkId()); + ReservationContext context = new ReservationContextImpl(null, null, _accountMgr.getActiveUser(User.UID_SYSTEM), + _accountMgr.getAccount(Account.ACCOUNT_ID_SYSTEM)); + + VirtualMachineProfileImpl<VMInstanceVO> vmProfile = new VirtualMachineProfileImpl<VMInstanceVO>(vmVO, null, + null, null, null); + + DataCenter dc = _configMgr.getZone(network.getDataCenterId()); + Host host = _hostDao.findById(vm.getHostId()); + DeployDestination dest = new DeployDestination(dc, null, null, host); + VirtualMachineGuru<VMInstanceVO> vmGuru = getVmGuru(vmVO); + HypervisorGuru hvGuru = _hvGuruMgr.getGuru(vmProfile.getVirtualMachine().getHypervisorType()); + VirtualMachineTO vmTO = hvGuru.implement(vmProfile); + + // don't delete default NIC on a user VM + if (nic.isDefaultNic() && vm.getType() == VirtualMachine.Type.User ) { + s_logger.warn("Failed to remove nic from " + vm + " in " + network + ", nic is default."); + throw new CloudRuntimeException("Failed to remove nic from " + vm + " in " + network + ", nic is default."); + } + + NicProfile nicProfile = new NicProfile(nic, network, nic.getBroadcastUri(), nic.getIsolationUri(), + _networkModel.getNetworkRate(network.getId(), vm.getId()), + _networkModel.isSecurityGroupSupportedInNetwork(network), + _networkModel.getNetworkTag(vmProfile.getVirtualMachine().getHypervisorType(), network)); + + //1) Unplug the nic + if (vm.getState() == State.Running) { + NicTO nicTO = toNicTO(nicProfile, vmProfile.getVirtualMachine().getHypervisorType()); + s_logger.debug("Un-plugging nic " + nic + " for vm " + vm + " from network " + network); + boolean result = vmGuru.unplugNic(network, nicTO, vmTO, context, dest); + if (result) { + s_logger.debug("Nic is unplugged successfully for vm " + vm + " in network " + network ); + } else { + s_logger.warn("Failed to unplug nic for the vm " + vm + " from network " + network); + return false; + } + } else if (vm.getState() != State.Stopped) { + s_logger.warn("Unable to remove vm " + vm + " from network " + network); + throw new ResourceUnavailableException("Unable to remove vm " + vm + " from network, is not in the right state", - DataCenter.class, vm.getDataCenterIdToDeployIn()); ++ DataCenter.class, vm.getDataCenterId()); + } + + //2) Release the nic + _networkMgr.releaseNic(vmProfile, nic); + s_logger.debug("Successfully released nic " + nic + "for vm " + vm); + + //3) Remove the nic + _networkMgr.removeNic(vmProfile, nic); + _nicsDao.expunge(nic.getId()); + return true; + } + + @Override public boolean removeVmFromNetwork(VirtualMachine vm, Network network, URI broadcastUri) throws ConcurrentOperationException, ResourceUnavailableException { VMInstanceVO vmVO = _vmDao.findById(vm.getId()); ReservationContext context = new ReservationContextImpl(null, null, _accountMgr.getActiveUser(User.UID_SYSTEM), @@@ -2535,25 -2613,31 +2605,31 @@@ _networkModel.getNetworkRate(network.getId(), vm.getId()), _networkModel.isSecurityGroupSupportedInNetwork(network), _networkModel.getNetworkTag(vmProfile.getVirtualMachine().getHypervisorType(), network)); - + //1) Unplug the nic + if (vm.getState() == State.Running) { - NicTO nicTO = toNicTO(nicProfile, vmProfile.getVirtualMachine().getHypervisorType()); - s_logger.debug("Un-plugging nic for vm " + vm + " from network " + network); - boolean result = vmGuru.unplugNic(network, nicTO, vmTO, context, dest); - if (result) { - s_logger.debug("Nic is unplugged successfully for vm " + vm + " in network " + network ); - } else { - s_logger.warn("Failed to unplug nic for the vm " + vm + " from network " + network); - return false; - } + NicTO nicTO = toNicTO(nicProfile, vmProfile.getVirtualMachine().getHypervisorType()); + s_logger.debug("Un-plugging nic for vm " + vm + " from network " + network); + boolean result = vmGuru.unplugNic(network, nicTO, vmTO, context, dest); + if (result) { + s_logger.debug("Nic is unplugged successfully for vm " + vm + " in network " + network ); + } else { + s_logger.warn("Failed to unplug nic for the vm " + vm + " from network " + network); + return false; + } + } else if (vm.getState() != State.Stopped) { + s_logger.warn("Unable to remove vm " + vm + " from network " + network); + throw new ResourceUnavailableException("Unable to remove vm " + vm + " from network, is not in the right state", - DataCenter.class, vm.getDataCenterIdToDeployIn()); ++ DataCenter.class, vm.getDataCenterId()); + } - + //2) Release the nic _networkMgr.releaseNic(vmProfile, nic); s_logger.debug("Successfully released nic " + nic + "for vm " + vm); - + //3) Remove the nic _networkMgr.removeNic(vmProfile, nic); - return result; + return true; } - + } http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/1b2b369e/server/test/com/cloud/network/MockFirewallManagerImpl.java ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/1b2b369e/server/test/com/cloud/network/MockNetworkManagerImpl.java ---------------------------------------------------------------------- diff --cc server/test/com/cloud/network/MockNetworkManagerImpl.java index 6621d1d,e628033..fbd3e27 --- a/server/test/com/cloud/network/MockNetworkManagerImpl.java +++ b/server/test/com/cloud/network/MockNetworkManagerImpl.java @@@ -738,9 -734,9 +739,9 @@@ public class MockNetworkManagerImpl ext */ @Override public NicProfile createNicForVm(Network network, NicProfile requested, ReservationContext context, - VirtualMachineProfileImpl<VMInstanceVO> vmProfile, boolean prepare) + VirtualMachineProfile<? extends VMInstanceVO> vmProfile, boolean prepare) - throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException, - ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException { + throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException, + ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException { // TODO Auto-generated method stub return null; } http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/1b2b369e/server/test/com/cloud/vm/MockUserVmManagerImpl.java ---------------------------------------------------------------------- diff --cc server/test/com/cloud/vm/MockUserVmManagerImpl.java index 0b17d6e,684040c..86f9d54 --- a/server/test/com/cloud/vm/MockUserVmManagerImpl.java +++ b/server/test/com/cloud/vm/MockUserVmManagerImpl.java @@@ -23,29 -23,29 +23,33 @@@ import java.util.Map import javax.ejb.Local; import javax.naming.ConfigurationException; -import com.cloud.agent.api.StopAnswer; -import com.cloud.agent.api.VmStatsEntry; -import com.cloud.agent.api.to.NicTO; -import com.cloud.agent.api.to.VirtualMachineTO; -import com.cloud.agent.manager.Commands; -import com.cloud.api.query.vo.UserVmJoinVO; - import org.apache.cloudstack.api.command.admin.vm.AssignVMCmd; import org.apache.cloudstack.api.command.admin.vm.RecoverVMCmd; -import org.apache.cloudstack.api.command.user.vm.*; -import org.apache.cloudstack.api.command.user.vmgroup.DeleteVMGroupCmd; -import org.apache.cloudstack.api.command.user.volume.AttachVolumeCmd; -import org.apache.cloudstack.api.command.user.volume.DetachVolumeCmd; import org.apache.cloudstack.api.command.user.template.CreateTemplateCmd; -import org.apache.cloudstack.api.command.user.vmgroup.CreateVMGroupCmd; ++import org.apache.cloudstack.api.command.user.vm.AddNicToVMCmd; +import org.apache.cloudstack.api.command.user.vm.DeployVMCmd; import org.apache.cloudstack.api.command.user.vm.DestroyVMCmd; -import org.apache.cloudstack.api.command.user.vm.ListVMsCmd; import org.apache.cloudstack.api.command.user.vm.RebootVMCmd; ++import org.apache.cloudstack.api.command.user.vm.RemoveNicFromVMCmd; import org.apache.cloudstack.api.command.user.vm.ResetVMPasswordCmd; ++import org.apache.cloudstack.api.command.user.vm.ResetVMSSHKeyCmd; import org.apache.cloudstack.api.command.user.vm.RestoreVMCmd; import org.apache.cloudstack.api.command.user.vm.StartVMCmd; ++import org.apache.cloudstack.api.command.user.vm.UpdateDefaultNicForVMCmd; import org.apache.cloudstack.api.command.user.vm.UpdateVMCmd; import org.apache.cloudstack.api.command.user.vm.UpgradeVMCmd; +import org.apache.cloudstack.api.command.user.vmgroup.CreateVMGroupCmd; +import org.apache.cloudstack.api.command.user.vmgroup.DeleteVMGroupCmd; +import org.apache.cloudstack.api.command.user.volume.AttachVolumeCmd; +import org.apache.cloudstack.api.command.user.volume.DetachVolumeCmd; +import org.springframework.stereotype.Component; + +import com.cloud.agent.api.StopAnswer; +import com.cloud.agent.api.VmStatsEntry; +import com.cloud.agent.api.to.NicTO; +import com.cloud.agent.api.to.VirtualMachineTO; +import com.cloud.agent.manager.Commands; +import com.cloud.api.query.vo.UserVmJoinVO; import com.cloud.dc.DataCenter; import com.cloud.deploy.DeployDestination; import com.cloud.exception.ConcurrentOperationException; @@@ -68,12 -70,11 +74,13 @@@ import com.cloud.user.Account import com.cloud.uservm.UserVm; import com.cloud.utils.Pair; import com.cloud.utils.component.Manager; +import com.cloud.utils.component.ManagerBase; import com.cloud.utils.exception.ExecutionException; + import com.cloud.utils.exception.CloudRuntimeException; +@Component @Local(value = { UserVmManager.class, UserVmService.class }) -public class MockUserVmManagerImpl implements UserVmManager, UserVmService, Manager { +public class MockUserVmManagerImpl extends ManagerBase implements UserVmManager, UserVmService { @Override public UserVmVO findByName(String name) { http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/1b2b369e/server/test/com/cloud/vm/MockVirtualMachineManagerImpl.java ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/1b2b369e/server/test/com/cloud/vpc/MockNetworkManagerImpl.java ---------------------------------------------------------------------- diff --cc server/test/com/cloud/vpc/MockNetworkManagerImpl.java index c1aacff,a0f9d00..7c8226a --- a/server/test/com/cloud/vpc/MockNetworkManagerImpl.java +++ b/server/test/com/cloud/vpc/MockNetworkManagerImpl.java @@@ -1130,9 -1126,9 +1129,9 @@@ public class MockNetworkManagerImpl ext */ @Override public NicProfile createNicForVm(Network network, NicProfile requested, ReservationContext context, - VirtualMachineProfileImpl<VMInstanceVO> vmProfile, boolean prepare) + VirtualMachineProfile<? extends VMInstanceVO> vmProfile, boolean prepare) - throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException, - ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException { + throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException, + ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException { // TODO Auto-generated method stub return null; } http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/1b2b369e/server/test/com/cloud/vpc/MockVpcVirtualNetworkApplianceManager.java ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/1b2b369e/tools/cli/cloudmonkey/cloudmonkey.py ---------------------------------------------------------------------- diff --cc tools/cli/cloudmonkey/cloudmonkey.py index 6487724,646ad40..909d3c3 --- a/tools/cli/cloudmonkey/cloudmonkey.py +++ b/tools/cli/cloudmonkey/cloudmonkey.py @@@ -81,26 -86,31 +86,31 @@@ class CloudMonkeyShell(cmd.Cmd, object) if os.path.exists(self.config_file): config = self.read_config() else: - for key in self.config_fields.keys(): - setattr(self, key, self.config_fields[key]) - config = self.write_config() - print "Welcome! Using `set` configure the necessary settings:" - print " ".join(sorted(self.config_fields.keys())) - print "Config file:", self.config_file - print "For debugging, tail -f", self.log_file, "\n" + first_time = True + config = self.write_config(first_time) - for key in self.config_fields.keys(): + for section in config_fields.keys(): + for key in config_fields[section].keys(): - try: + try: - setattr(self, key, config.get('CLI', key)) - self.config_fields[key] = config.get('CLI', key) + self.config_options.append(key) + setattr(self, key, config.get(section, key)) - except Exception: + except Exception: - print "Please fix `%s` config in %s" % (key, self.config_file) + print "Please fix `%s` in %s" % (key, self.config_file) - sys.exit() + sys.exit() + if first_time: + print "Welcome! Using `set` configure the necessary settings:" + print " ".join(sorted(self.config_options)) + print "Config file:", self.config_file + print "For debugging, tail -f", self.log_file, "\n" + self.prompt = self.prompt.strip() + " " # Cosmetic fix for prompt + logging.basicConfig(filename=self.log_file, level=logging.DEBUG, format=log_fmt) - logger.debug("Loaded config fields:\n%s" % self.config_fields) + logger.debug("Loaded config fields:\n%s" % map(lambda x: "%s=%s" % + (x, getattr(self, x)), + self.config_options)) cmd.Cmd.__init__(self) if not os.path.exists(self.config_file): @@@ -149,30 -165,13 +165,13 @@@ arg = str(arg) if isinstance(type(args), types.NoneType): continue + output += arg - if self.color == 'true': + if self.color == 'true': - if str(arg).count(self.ruler) == len(str(arg)): - print colored.green(arg), - elif 'Error' in arg: - print colored.red(arg), - elif ":\n=" in arg: - print colored.red(arg), - elif ':' in arg: - print colored.blue(arg), - elif 'type' in arg: - print colored.green(arg), - elif 'state' in arg or 'count' in arg: - print colored.magenta(arg), - elif 'id =' in arg: - print colored.yellow(arg), - elif 'name =' in arg: - print colored.cyan(arg), - else: - print arg, + monkeyprint(output) - else: + else: - print arg, - print + print output except Exception, e: - print colored.red("Error: "), e + self.print_shell("Error: " + e) def print_result(self, result, result_filter=None): if result is None or len(result) == 0:
