CS-15217: Security: Malicious user is able to get the size of the cloud by enumerating IDs

Description:

	More changes to remove DB IDs from exception messages,
This commit is contained in:
Vijayendra Bhamidipati 2012-07-11 12:21:43 -07:00
parent 76b8407b69
commit f2c8a59983
6 changed files with 471 additions and 443 deletions

View File

@ -73,6 +73,7 @@ import com.cloud.user.SSHKeyPair;
import com.cloud.user.User;
import com.cloud.user.UserContext;
import com.cloud.uservm.UserVm;
import com.cloud.utils.IdentityProxy;
import com.cloud.utils.NumbersUtil;
import com.cloud.utils.Pair;
import com.cloud.utils.component.Adapters;
@ -100,61 +101,61 @@ import com.cloud.vm.VirtualMachineProfile.Param;
@Local(value={BareMetalVmManager.class, BareMetalVmService.class})
public class BareMetalVmManagerImpl extends UserVmManagerImpl implements BareMetalVmManager, BareMetalVmService, Manager,
StateListener<State, VirtualMachine.Event, VirtualMachine> {
private static final Logger s_logger = Logger.getLogger(BareMetalVmManagerImpl.class);
private ConfigurationDao _configDao;
@Inject PxeServerManager _pxeMgr;
@Inject ResourceManager _resourceMgr;
StateListener<State, VirtualMachine.Event, VirtualMachine> {
private static final Logger s_logger = Logger.getLogger(BareMetalVmManagerImpl.class);
private ConfigurationDao _configDao;
@Inject PxeServerManager _pxeMgr;
@Inject ResourceManager _resourceMgr;
@Inject (adapter=TemplateAdapter.class)
protected Adapters<TemplateAdapter> _adapters;
@Override
public boolean attachISOToVM(long vmId, long isoId, boolean attach) {
s_logger.warn("attachISOToVM is not supported by Bare Metal, just fake a true");
return true;
}
@Override
public Volume attachVolumeToVM(AttachVolumeCmd command) {
s_logger.warn("attachVolumeToVM is not supported by Bare Metal, return null");
return null;
}
@Override
public Volume detachVolumeFromVM(DetachVolumeCmd cmd) {
s_logger.warn("detachVolumeFromVM is not supported by Bare Metal, return null");
return null;
}
@Override
public UserVm upgradeVirtualMachine(UpgradeVMCmd cmd) {
s_logger.warn("upgradeVirtualMachine is not supported by Bare Metal, return null");
return null;
}
@Override
@Override
public boolean attachISOToVM(long vmId, long isoId, boolean attach) {
s_logger.warn("attachISOToVM is not supported by Bare Metal, just fake a true");
return true;
}
@Override
public Volume attachVolumeToVM(AttachVolumeCmd command) {
s_logger.warn("attachVolumeToVM is not supported by Bare Metal, return null");
return null;
}
@Override
public Volume detachVolumeFromVM(DetachVolumeCmd cmd) {
s_logger.warn("detachVolumeFromVM is not supported by Bare Metal, return null");
return null;
}
@Override
public UserVm upgradeVirtualMachine(UpgradeVMCmd cmd) {
s_logger.warn("upgradeVirtualMachine is not supported by Bare Metal, return null");
return null;
}
@Override
public VMTemplateVO createPrivateTemplateRecord(CreateTemplateCmd cmd, Account templateOwner) throws ResourceAllocationException {
/*Baremetal creates record after host rebooting for imaging, in createPrivateTemplate*/
return null;
}
@Override @DB
/*Baremetal creates record after host rebooting for imaging, in createPrivateTemplate*/
return null;
}
@Override @DB
public VMTemplateVO createPrivateTemplate(CreateTemplateCmd cmd) throws CloudRuntimeException {
Long vmId = cmd.getVmId();
if (vmId == null) {
throw new InvalidParameterValueException("VM ID is null");
}
UserVmVO vm = _vmDao.findById(vmId);
if (vm == null) {
throw new InvalidParameterValueException("Cannot find VM for ID " + vmId);
}
Long hostId = (vm.getHostId() == null ? vm.getLastHostId() : vm.getHostId());
Long vmId = cmd.getVmId();
if (vmId == null) {
throw new InvalidParameterValueException("VM ID is null", null);
}
UserVmVO vm = _vmDao.findById(vmId);
if (vm == null) {
throw new InvalidParameterValueException("Cannot find VM by ID", null);
}
Long hostId = (vm.getHostId() == null ? vm.getLastHostId() : vm.getHostId());
HostVO host = _hostDao.findById(hostId);
if (host == null) {
throw new InvalidParameterValueException("Cannot find host with id " + hostId);
throw new InvalidParameterValueException("Cannot find host by id", null);
}
List<HostVO> pxes = _resourceMgr.listAllUpAndEnabledHosts(Host.Type.PxeServer, null, host.getPodId(), host.getDataCenterId());
@ -163,7 +164,7 @@ public class BareMetalVmManagerImpl extends UserVmManagerImpl implements BareMet
}
if (pxes.size() > 1) {
CloudRuntimeException ex = new CloudRuntimeException("Multiple PXE servers found in Pod " + host.getPodId() + " in Zone with specified id");
CloudRuntimeException ex = new CloudRuntimeException("Multiple PXE servers found in Pod " + host.getPodId() + " in Zone with specified id");
ex.addProxyObject("data_center", host.getDataCenterId(), "zoneId");
throw ex;
}
@ -177,12 +178,12 @@ public class BareMetalVmManagerImpl extends UserVmManagerImpl implements BareMet
Long userId = UserContext.current().getCallerUserId();
userId = (userId == null ? User.UID_SYSTEM : userId);
AccountVO account = _accountDao.findById(vm.getAccountId());
try {
TemplateProfile tmplProfile;
tmplProfile = adapter.prepare(false, userId, cmd.getTemplateName(), cmd.getDisplayText(), cmd.getBits(), false, false, cmd.getUrl(), cmd.isPublic(), cmd.isFeatured(), false,
"BareMetal", cmd.getOsTypeId(), pxe.getDataCenterId(), HypervisorType.BareMetal, account.getAccountName(), account.getDomainId(), "0", true, cmd.getDetails());
if (!_pxeMgr.prepareCreateTemplate(_pxeMgr.getPxeServerType(pxe), pxe.getId(), vm, cmd.getUrl())) {
throw new Exception("Prepare PXE boot file for host " + hostId + " failed");
}
@ -206,117 +207,123 @@ public class BareMetalVmManagerImpl extends UserVmManagerImpl implements BareMet
s_logger.debug("Create baremetal tempalte for host " + hostId + " failed", e);
throw new CloudRuntimeException(e.getMessage());
}
}
}
@Override
public UserVm createVirtualMachine(DeployVMCmd cmd) throws InsufficientCapacityException, ResourceUnavailableException, ConcurrentOperationException,
StorageUnavailableException, ResourceAllocationException {
Account caller = UserContext.current().getCaller();
@Override
public UserVm createVirtualMachine(DeployVMCmd cmd) throws InsufficientCapacityException, ResourceUnavailableException, ConcurrentOperationException,
StorageUnavailableException, ResourceAllocationException {
Account caller = UserContext.current().getCaller();
String accountName = cmd.getAccountName();
Long domainId = cmd.getDomainId();
List<Long> networkList = cmd.getNetworkIds();
String group = cmd.getGroup();
String accountName = cmd.getAccountName();
Long domainId = cmd.getDomainId();
List<Long> networkList = cmd.getNetworkIds();
String group = cmd.getGroup();
Account owner = _accountDao.findActiveAccount(accountName, domainId);
if (owner == null) {
throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
}
_accountMgr.checkAccess(caller, null, true, owner);
long accountId = owner.getId();
DataCenterVO dc = _dcDao.findById(cmd.getZoneId());
if (dc == null) {
throw new InvalidParameterValueException("Unable to find zone: " + cmd.getZoneId());
}
if(Grouping.AllocationState.Disabled == dc.getAllocationState() && !_accountMgr.isRootAdmin(caller.getType())){
throw new PermissionDeniedException("Cannot perform this operation, Zone is currently disabled: "+ cmd.getZoneId() );
}
if (dc.getDomainId() != null) {
DomainVO domain = _domainDao.findById(dc.getDomainId());
if (domain == null) {
throw new CloudRuntimeException("Unable to find the domain " + dc.getDomainId() + " for the zone: " + dc);
}
_configMgr.checkZoneAccess(caller, dc);
_configMgr.checkZoneAccess(owner, dc);
}
// check if account/domain is with in resource limits to create a new vm
_resourceLimitMgr.checkResourceLimit(owner, ResourceType.user_vm);
ServiceOfferingVO offering = _serviceOfferingDao.findById(cmd.getServiceOfferingId());
if (offering == null || offering.getRemoved() != null) {
throw new InvalidParameterValueException("Unable to find service offering: " + cmd.getServiceOfferingId());
Account owner = _accountDao.findActiveAccount(accountName, domainId);
if (owner == null) {
List<IdentityProxy> idList = new ArrayList<IdentityProxy>();
idList.add(new IdentityProxy("domain", domainId, "domainId"));
throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain with specified id", idList);
}
VMTemplateVO template = _templateDao.findById(cmd.getTemplateId());
_accountMgr.checkAccess(caller, null, true, owner);
long accountId = owner.getId();
DataCenterVO dc = _dcDao.findById(cmd.getZoneId());
if (dc == null) {
throw new InvalidParameterValueException("Unable to find zone by id", null);
}
if(Grouping.AllocationState.Disabled == dc.getAllocationState() && !_accountMgr.isRootAdmin(caller.getType())){
throw new PermissionDeniedException("Cannot perform this operation, Zone is currently disabled: "+ cmd.getZoneId() );
}
if (dc.getDomainId() != null) {
DomainVO domain = _domainDao.findById(dc.getDomainId());
if (domain == null) {
throw new CloudRuntimeException("Unable to find the domain " + dc.getDomainId() + " for the zone: " + dc);
}
_configMgr.checkZoneAccess(caller, dc);
_configMgr.checkZoneAccess(owner, dc);
}
// check if account/domain is with in resource limits to create a new vm
_resourceLimitMgr.checkResourceLimit(owner, ResourceType.user_vm);
ServiceOfferingVO offering = _serviceOfferingDao.findById(cmd.getServiceOfferingId());
if (offering == null || offering.getRemoved() != null) {
throw new InvalidParameterValueException("Unable to find service offering by id", null);
}
VMTemplateVO template = _templateDao.findById(cmd.getTemplateId());
// Make sure a valid template ID was specified
if (template == null || template.getRemoved() != null) {
throw new InvalidParameterValueException("Unable to use template " + cmd.getTemplateId());
throw new InvalidParameterValueException("Unable to use template since it couldn't be found by id or has been marked as removed", null);
}
if (template.getTemplateType().equals(TemplateType.SYSTEM)) {
throw new InvalidParameterValueException("Unable to use system template " + cmd.getTemplateId()+" to deploy a user vm");
List<IdentityProxy> idList = new ArrayList<IdentityProxy>();
idList.add(new IdentityProxy(template, cmd.getTemplateId(), "templateId"));
throw new InvalidParameterValueException("Unable to use system template with specified id to deploy a user vm", idList);
}
if (template.getFormat() != Storage.ImageFormat.BAREMETAL) {
throw new InvalidParameterValueException("Unable to use non Bare Metal template" + cmd.getTemplateId() +" to deploy a bare metal vm");
List<IdentityProxy> idList = new ArrayList<IdentityProxy>();
idList.add(new IdentityProxy(template, cmd.getTemplateId(), "templateId"));
throw new InvalidParameterValueException("Unable to use non Bare Metal template with specified id to deploy a bare metal vm", idList);
}
String userData = cmd.getUserData();
byte [] decodedUserData = null;
if (userData != null) {
if (userData.length() >= 2 * MAX_USER_DATA_LENGTH_BYTES) {
throw new InvalidParameterValueException("User data is too long");
throw new InvalidParameterValueException("User data is too long", null);
}
decodedUserData = org.apache.commons.codec.binary.Base64.decodeBase64(userData.getBytes());
if (decodedUserData.length > MAX_USER_DATA_LENGTH_BYTES){
throw new InvalidParameterValueException("User data is too long");
throw new InvalidParameterValueException("User data is too long", null);
}
if (decodedUserData.length < 1) {
throw new InvalidParameterValueException("User data is too short");
throw new InvalidParameterValueException("User data is too short", null);
}
}
// Find an SSH public key corresponding to the key pair name, if one is given
String sshPublicKey = null;
if (cmd.getSSHKeyPairName() != null && !cmd.getSSHKeyPairName().equals("")) {
Account account = UserContext.current().getCaller();
SSHKeyPair pair = _sshKeyPairDao.findByName(account.getAccountId(), account.getDomainId(), cmd.getSSHKeyPairName());
if (pair == null) {
throw new InvalidParameterValueException("A key pair with name '" + cmd.getSSHKeyPairName() + "' was not found.");
SSHKeyPair pair = _sshKeyPairDao.findByName(account.getAccountId(), account.getDomainId(), cmd.getSSHKeyPairName());
if (pair == null) {
throw new InvalidParameterValueException("A key pair with name '" + cmd.getSSHKeyPairName() + "' was not found.", null);
}
sshPublicKey = pair.getPublicKey();
}
sshPublicKey = pair.getPublicKey();
}
_accountMgr.checkAccess(caller, null, true, template);
_accountMgr.checkAccess(caller, null, true, template);
DataCenterDeployment plan = new DataCenterDeployment(dc.getId());
DataCenterDeployment plan = new DataCenterDeployment(dc.getId());
s_logger.debug("Allocating in the DB for bare metal vm");
if (dc.getNetworkType() != NetworkType.Basic || networkList != null) {
s_logger.warn("Bare Metal only supports basical network mode now, switch to baisc network automatically");
}
Network defaultNetwork = _networkMgr.getExclusiveGuestNetwork(dc.getId());
if (defaultNetwork == null) {
throw new InvalidParameterValueException("Unable to find a default network to start a vm");
}
networkList = new ArrayList<Long>();
networkList.add(defaultNetwork.getId());
List<Pair<NetworkVO, NicProfile>> networks = new ArrayList<Pair<NetworkVO, NicProfile>>();
s_logger.debug("Allocating in the DB for bare metal vm");
if (dc.getNetworkType() != NetworkType.Basic || networkList != null) {
s_logger.warn("Bare Metal only supports basical network mode now, switch to baisc network automatically");
}
Network defaultNetwork = _networkMgr.getExclusiveGuestNetwork(dc.getId());
if (defaultNetwork == null) {
throw new InvalidParameterValueException("Unable to find a default network to start a vm", null);
}
networkList = new ArrayList<Long>();
networkList.add(defaultNetwork.getId());
List<Pair<NetworkVO, NicProfile>> networks = new ArrayList<Pair<NetworkVO, NicProfile>>();
for (Long networkId : networkList) {
NetworkVO network = _networkDao.findById(networkId);
if (network == null) {
throw new InvalidParameterValueException("Unable to find network by id " + networkId);
throw new InvalidParameterValueException("Unable to find network by id ", null);
} else {
if (network.getGuestType() != Network.GuestType.Shared) {
//Check account permissions
@ -328,9 +335,9 @@ public class BareMetalVmManagerImpl extends UserVmManagerImpl implements BareMet
networks.add(new Pair<NetworkVO, NicProfile>(network, null));
}
}
long id = _vmDao.getNextInSequence(Long.class, "id");
String hostName = cmd.getName();
String instanceName = VirtualMachineName.getVmName(id, owner.getId(), _instance);
if (hostName == null) {
@ -339,79 +346,81 @@ public class BareMetalVmManagerImpl extends UserVmManagerImpl implements BareMet
//verify hostName (hostname doesn't have to be unique)
if (!NetUtils.verifyDomainNameLabel(hostName, true)) {
throw new InvalidParameterValueException("Invalid name. Vm name can contain ASCII letters 'a' through 'z', the digits '0' through '9', " +
"and the hyphen ('-'), must be between 1 and 63 characters long, and can't start or end with \"-\" and can't start with digit");
"and the hyphen ('-'), must be between 1 and 63 characters long, and can't start or end with \"-\" and can't start with digit", null);
}
}
UserVmVO vm = new UserVmVO(id, instanceName, cmd.getDisplayName(), template.getId(), HypervisorType.BareMetal,
template.getGuestOSId(), offering.getOfferHA(), false, domainId, owner.getId(), offering.getId(), userData, hostName);
if (sshPublicKey != null) {
vm.setDetail("SSH.PublicKey", sshPublicKey);
}
if (_itMgr.allocate(vm, template, offering, null, null, networks, null, plan, cmd.getHypervisor(), owner) == null) {
return null;
}
if (_itMgr.allocate(vm, template, offering, null, null, networks, null, plan, cmd.getHypervisor(), owner) == null) {
return null;
}
if (s_logger.isDebugEnabled()) {
s_logger.debug("Successfully allocated DB entry for " + vm);
}
if (s_logger.isDebugEnabled()) {
s_logger.debug("Successfully allocated DB entry for " + vm);
}
UserContext.current().setEventDetails("Vm Id: " + vm.getId());
UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_VM_CREATE, accountId, cmd.getZoneId(), vm.getId(), vm.getHostName(), offering.getId(), template.getId(), HypervisorType.BareMetal.toString());
_usageEventDao.persist(usageEvent);
if (s_logger.isDebugEnabled()) {
s_logger.debug("Successfully allocated DB entry for " + vm);
}
_resourceLimitMgr.incrementResourceCount(accountId, ResourceType.user_vm);
if (s_logger.isDebugEnabled()) {
s_logger.debug("Successfully allocated DB entry for " + vm);
}
UserContext.current().setEventDetails("Vm Id: " + vm.getId());
UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_VM_CREATE, accountId, cmd.getZoneId(), vm.getId(), vm.getHostName(), offering.getId(), template.getId(), HypervisorType.BareMetal.toString());
_usageEventDao.persist(usageEvent);
// Assign instance to the group
try {
if (group != null) {
boolean addToGroup = addInstanceToGroup(Long.valueOf(id), group);
if (!addToGroup) {
throw new CloudRuntimeException("Unable to assign Vm to the group " + group);
}
}
} catch (Exception ex) {
throw new CloudRuntimeException("Unable to assign Vm to the group " + group);
}
_resourceLimitMgr.incrementResourceCount(accountId, ResourceType.user_vm);
return vm;
}
public UserVm startVirtualMachine(DeployVMCmd cmd) throws ResourceUnavailableException, InsufficientCapacityException, ConcurrentOperationException {
UserVmVO vm = _vmDao.findById(cmd.getInstanceId());
List<HostVO> servers = _resourceMgr.listAllUpAndEnabledHostsInOneZoneByType(Host.Type.PxeServer, vm.getDataCenterIdToDeployIn());
if (servers.size() == 0) {
throw new CloudRuntimeException("Cannot find PXE server, please make sure there is one PXE server per zone");
}
HostVO pxeServer = servers.get(0);
VMTemplateVO template = _templateDao.findById(vm.getTemplateId());
if (template == null || template.getFormat() != Storage.ImageFormat.BAREMETAL) {
throw new InvalidParameterValueException("Invalid template with id = " + vm.getTemplateId());
}
Map<VirtualMachineProfile.Param, Object> params = new HashMap<VirtualMachineProfile.Param, Object>();
params.put(Param.PxeSeverType, _pxeMgr.getPxeServerType(pxeServer));
// Assign instance to the group
try {
if (group != null) {
boolean addToGroup = addInstanceToGroup(Long.valueOf(id), group);
if (!addToGroup) {
throw new CloudRuntimeException("Unable to assign Vm to the group " + group);
}
}
} catch (Exception ex) {
throw new CloudRuntimeException("Unable to assign Vm to the group " + group);
}
return startVirtualMachine(cmd, params);
}
public UserVm startVirtualMachine(StartVMCmd cmd) throws ResourceUnavailableException, InsufficientCapacityException, ConcurrentOperationException {
return vm;
}
@Override
public UserVm startVirtualMachine(DeployVMCmd cmd) throws ResourceUnavailableException, InsufficientCapacityException, ConcurrentOperationException {
UserVmVO vm = _vmDao.findById(cmd.getInstanceId());
List<HostVO> servers = _resourceMgr.listAllUpAndEnabledHostsInOneZoneByType(Host.Type.PxeServer, vm.getDataCenterIdToDeployIn());
if (servers.size() == 0) {
throw new CloudRuntimeException("Cannot find PXE server, please make sure there is one PXE server per zone");
}
HostVO pxeServer = servers.get(0);
VMTemplateVO template = _templateDao.findById(vm.getTemplateId());
if (template == null || template.getFormat() != Storage.ImageFormat.BAREMETAL) {
throw new InvalidParameterValueException("Cannot locate template by id", null);
}
Map<VirtualMachineProfile.Param, Object> params = new HashMap<VirtualMachineProfile.Param, Object>();
params.put(Param.PxeSeverType, _pxeMgr.getPxeServerType(pxeServer));
return startVirtualMachine(cmd, params);
}
@Override
public UserVm startVirtualMachine(StartVMCmd cmd) throws ResourceUnavailableException, InsufficientCapacityException, ConcurrentOperationException {
UserVmVO vm = _vmDao.findById(cmd.getInstanceId());
VMTemplateVO template = _templateDao.findById(vm.getTemplateId());
if (template == null || template.getFormat() != Storage.ImageFormat.BAREMETAL) {
throw new InvalidParameterValueException("Invalid template with id = " + vm.getTemplateId());
throw new InvalidParameterValueException("Cannot locate template by id", null);
}
Map<VirtualMachineProfile.Param, Object> params = null;
if (vm.isUpdateParameters()) {
List<HostVO> servers = _resourceMgr.listAllUpAndEnabledHostsInOneZoneByType(Host.Type.PxeServer, vm.getDataCenterIdToDeployIn());
@ -422,140 +431,140 @@ public class BareMetalVmManagerImpl extends UserVmManagerImpl implements BareMet
params = new HashMap<VirtualMachineProfile.Param, Object>();
params.put(Param.PxeSeverType, _pxeMgr.getPxeServerType(pxeServer));
}
Pair<UserVmVO, Map<VirtualMachineProfile.Param, Object>> vmDetailsPair = super.startVirtualMachine(vm.getId(), cmd.getHostId(), params);
return vmDetailsPair.first();
}
@Override
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
_name = name;
@Override
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
_name = name;
ComponentLocator locator = ComponentLocator.getCurrentLocator();
_configDao = locator.getDao(ConfigurationDao.class);
if (_configDao == null) {
throw new ConfigurationException("Unable to get the configuration dao.");
}
ComponentLocator locator = ComponentLocator.getCurrentLocator();
_configDao = locator.getDao(ConfigurationDao.class);
if (_configDao == null) {
throw new ConfigurationException("Unable to get the configuration dao.");
}
Map<String, String> configs = _configDao.getConfiguration("AgentManager", params);
Map<String, String> configs = _configDao.getConfiguration("AgentManager", params);
_instance = configs.get("instance.name");
if (_instance == null) {
_instance = "DEFAULT";
}
_instance = configs.get("instance.name");
if (_instance == null) {
_instance = "DEFAULT";
}
String workers = configs.get("expunge.workers");
int wrks = NumbersUtil.parseInt(workers, 10);
String workers = configs.get("expunge.workers");
int wrks = NumbersUtil.parseInt(workers, 10);
String time = configs.get("expunge.interval");
_expungeInterval = NumbersUtil.parseInt(time, 86400);
String time = configs.get("expunge.interval");
_expungeInterval = NumbersUtil.parseInt(time, 86400);
time = configs.get("expunge.delay");
_expungeDelay = NumbersUtil.parseInt(time, _expungeInterval);
time = configs.get("expunge.delay");
_expungeDelay = NumbersUtil.parseInt(time, _expungeInterval);
_executor = Executors.newScheduledThreadPool(wrks, new NamedThreadFactory("UserVm-Scavenger"));
_executor = Executors.newScheduledThreadPool(wrks, new NamedThreadFactory("UserVm-Scavenger"));
_itMgr.registerGuru(Type.UserBareMetal, this);
VirtualMachine.State.getStateMachine().registerListener(this);
_itMgr.registerGuru(Type.UserBareMetal, this);
VirtualMachine.State.getStateMachine().registerListener(this);
s_logger.info("User VM Manager is configured.");
s_logger.info("User VM Manager is configured.");
return true;
}
@Override
public boolean finalizeVirtualMachineProfile(VirtualMachineProfile<UserVmVO> profile, DeployDestination dest, ReservationContext context) {
return true;
}
@Override
public boolean finalizeVirtualMachineProfile(VirtualMachineProfile<UserVmVO> profile, DeployDestination dest, ReservationContext context) {
UserVmVO vm = profile.getVirtualMachine();
Account owner = _accountDao.findById(vm.getAccountId());
if (owner == null || owner.getState() == Account.State.disabled) {
throw new PermissionDeniedException("The owner of " + vm + " either does not exist or is disabled: " + vm.getAccountId());
}
PxeServerType pxeType = (PxeServerType) profile.getParameter(Param.PxeSeverType);
if (pxeType == null) {
s_logger.debug("This is a normal IPMI start, skip prepartion of PXE server");
return true;
}
s_logger.debug("This is a PXE start, prepare PXE server first");
List<HostVO> servers = _resourceMgr.listAllUpAndEnabledHosts(Host.Type.PxeServer, null, dest.getPod().getId(), dest.getDataCenter().getId());
if (servers.size() == 0) {
throw new CloudRuntimeException("Cannot find PXE server, please make sure there is one PXE server per zone");
}
if (servers.size() > 1) {
throw new CloudRuntimeException("Find more than one PXE server, please make sure there is only one PXE server per zone in pod " + dest.getPod().getId() + " zone " + dest.getDataCenter().getId());
}
HostVO pxeServer = servers.get(0);
if (!_pxeMgr.prepare(pxeType, profile, dest, context, pxeServer.getId())) {
throw new CloudRuntimeException("Pepare PXE server failed");
}
profile.addBootArgs("PxeBoot");
return true;
}
@Override
public boolean finalizeDeployment(Commands cmds, VirtualMachineProfile<UserVmVO> profile, DeployDestination dest, ReservationContext context) {
UserVmVO userVm = profile.getVirtualMachine();
List<NicVO> nics = _nicDao.listByVmId(userVm.getId());
for (NicVO nic : nics) {
NetworkVO network = _networkDao.findById(nic.getNetworkId());
if (network.getTrafficType() == TrafficType.Guest) {
userVm.setPrivateIpAddress(nic.getIp4Address());
userVm.setPrivateMacAddress(nic.getMacAddress());
}
}
_vmDao.update(userVm.getId(), userVm);
return true;
}
Account owner = _accountDao.findById(vm.getAccountId());
@Override
public void finalizeStop(VirtualMachineProfile<UserVmVO> profile, StopAnswer answer) {
super.finalizeStop(profile, answer);
}
if (owner == null || owner.getState() == Account.State.disabled) {
throw new PermissionDeniedException("The owner of " + vm + " either does not exist or is disabled: " + vm.getAccountId());
}
@Override
public UserVm destroyVm(long vmId) throws ResourceUnavailableException, ConcurrentOperationException {
return super.destroyVm(vmId);
}
PxeServerType pxeType = (PxeServerType) profile.getParameter(Param.PxeSeverType);
if (pxeType == null) {
s_logger.debug("This is a normal IPMI start, skip prepartion of PXE server");
return true;
}
s_logger.debug("This is a PXE start, prepare PXE server first");
@Override
public boolean preStateTransitionEvent(State oldState, Event event, State newState, VirtualMachine vo, boolean status, Object opaque) {
return true;
}
List<HostVO> servers = _resourceMgr.listAllUpAndEnabledHosts(Host.Type.PxeServer, null, dest.getPod().getId(), dest.getDataCenter().getId());
if (servers.size() == 0) {
throw new CloudRuntimeException("Cannot find PXE server, please make sure there is one PXE server per zone");
}
if (servers.size() > 1) {
throw new CloudRuntimeException("Find more than one PXE server, please make sure there is only one PXE server per zone in pod " + dest.getPod().getId() + " zone " + dest.getDataCenter().getId());
}
HostVO pxeServer = servers.get(0);
@Override
public boolean postStateTransitionEvent(State oldState, Event event, State newState, VirtualMachine vo, boolean status, Object opaque) {
if (newState != State.Starting && newState != State.Error && newState != State.Expunging) {
return true;
}
if (vo.getHypervisorType() != HypervisorType.BareMetal) {
return true;
}
HostVO host = _hostDao.findById(vo.getHostId());
if (host == null) {
s_logger.debug("Skip oldState " + oldState + " to " + "newState " + newState + " transimtion");
return true;
}
_hostDao.loadDetails(host);
if (newState == State.Starting) {
host.setDetail("vmName", vo.getInstanceName());
s_logger.debug("Add vmName " + host.getDetail("vmName") + " to host " + host.getId() + " details");
} else {
if (host.getDetail("vmName") != null && host.getDetail("vmName").equalsIgnoreCase(vo.getInstanceName())) {
s_logger.debug("Remove vmName " + host.getDetail("vmName") + " from host " + host.getId() + " details");
host.getDetails().remove("vmName");
}
}
_hostDao.saveDetails(host);
return true;
}
if (!_pxeMgr.prepare(pxeType, profile, dest, context, pxeServer.getId())) {
throw new CloudRuntimeException("Pepare PXE server failed");
}
profile.addBootArgs("PxeBoot");
return true;
}
@Override
public boolean finalizeDeployment(Commands cmds, VirtualMachineProfile<UserVmVO> profile, DeployDestination dest, ReservationContext context) {
UserVmVO userVm = profile.getVirtualMachine();
List<NicVO> nics = _nicDao.listByVmId(userVm.getId());
for (NicVO nic : nics) {
NetworkVO network = _networkDao.findById(nic.getNetworkId());
if (network.getTrafficType() == TrafficType.Guest) {
userVm.setPrivateIpAddress(nic.getIp4Address());
userVm.setPrivateMacAddress(nic.getMacAddress());
}
}
_vmDao.update(userVm.getId(), userVm);
return true;
}
@Override
public void finalizeStop(VirtualMachineProfile<UserVmVO> profile, StopAnswer answer) {
super.finalizeStop(profile, answer);
}
@Override
public UserVm destroyVm(long vmId) throws ResourceUnavailableException, ConcurrentOperationException {
return super.destroyVm(vmId);
}
@Override
public boolean preStateTransitionEvent(State oldState, Event event, State newState, VirtualMachine vo, boolean status, Object opaque) {
return true;
}
@Override
public boolean postStateTransitionEvent(State oldState, Event event, State newState, VirtualMachine vo, boolean status, Object opaque) {
if (newState != State.Starting && newState != State.Error && newState != State.Expunging) {
return true;
}
if (vo.getHypervisorType() != HypervisorType.BareMetal) {
return true;
}
HostVO host = _hostDao.findById(vo.getHostId());
if (host == null) {
s_logger.debug("Skip oldState " + oldState + " to " + "newState " + newState + " transimtion");
return true;
}
_hostDao.loadDetails(host);
if (newState == State.Starting) {
host.setDetail("vmName", vo.getInstanceName());
s_logger.debug("Add vmName " + host.getDetail("vmName") + " to host " + host.getId() + " details");
} else {
if (host.getDetail("vmName") != null && host.getDetail("vmName").equalsIgnoreCase(vo.getInstanceName())) {
s_logger.debug("Remove vmName " + host.getDetail("vmName") + " from host " + host.getId() + " details");
host.getDetails().remove("vmName");
}
}
_hostDao.saveDetails(host);
return true;
}
}

View File

@ -66,6 +66,7 @@ import com.cloud.offerings.NetworkOfferingVO;
import com.cloud.offerings.dao.NetworkOfferingDao;
import com.cloud.user.AccountManager;
import com.cloud.uservm.UserVm;
import com.cloud.utils.IdentityProxy;
import com.cloud.utils.Pair;
import com.cloud.utils.component.AdapterBase;
import com.cloud.utils.component.Inject;
@ -86,8 +87,8 @@ import com.google.gson.Gson;
@Local(value = NetworkElement.class)
public class VirtualRouterElement extends AdapterBase implements VirtualRouterElementService, DhcpServiceProvider,
UserDataServiceProvider, SourceNatServiceProvider, StaticNatServiceProvider, FirewallServiceProvider,
LoadBalancingServiceProvider, PortForwardingServiceProvider, RemoteAccessVPNServiceProvider, IpDeployer {
UserDataServiceProvider, SourceNatServiceProvider, StaticNatServiceProvider, FirewallServiceProvider,
LoadBalancingServiceProvider, PortForwardingServiceProvider, RemoteAccessVPNServiceProvider, IpDeployer {
private static final Logger s_logger = Logger.getLogger(VirtualRouterElement.class);
protected static final Map<Service, Map<Capability, String>> capabilities = setCapabilities();
@ -128,7 +129,7 @@ public class VirtualRouterElement extends AdapterBase implements VirtualRouterEl
if (physicalNetworkId == null) {
return false;
}
if (network.getVpcId() != null) {
return false;
}
@ -157,7 +158,7 @@ public class VirtualRouterElement extends AdapterBase implements VirtualRouterEl
public boolean implement(Network network, NetworkOffering offering, DeployDestination dest, ReservationContext context)
throws ResourceUnavailableException, ConcurrentOperationException,
InsufficientCapacityException {
if (offering.isSystemOnly()) {
return false;
}
@ -172,14 +173,14 @@ public class VirtualRouterElement extends AdapterBase implements VirtualRouterEl
throw new ResourceUnavailableException("Can't find at least one running router!",
DataCenter.class, network.getDataCenterId());
}
return true;
}
@Override
public boolean prepare(Network network, NicProfile nic, VirtualMachineProfile<? extends VirtualMachine> vm,
DeployDestination dest, ReservationContext context)
throws ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException {
throws ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException {
if (vm.getType() != VirtualMachine.Type.User || vm.getHypervisorType() == HypervisorType.BareMetal) {
return false;
}
@ -205,7 +206,7 @@ public class VirtualRouterElement extends AdapterBase implements VirtualRouterEl
throw new ResourceUnavailableException("Can't find at least one running router!",
DataCenter.class, network.getDataCenterId());
}
return true;
}
@ -215,7 +216,7 @@ public class VirtualRouterElement extends AdapterBase implements VirtualRouterEl
List<DomainRouterVO> routers = _routerDao.listByNetworkAndRole(config.getId(), Role.VIRTUAL_ROUTER);
if (routers == null || routers.isEmpty()) {
s_logger.debug("Virtual router elemnt doesn't need to apply firewall rules on the backend; virtual " +
"router doesn't exist in the network " + config.getId());
"router doesn't exist in the network " + config.getId());
return true;
}
@ -243,7 +244,7 @@ public class VirtualRouterElement extends AdapterBase implements VirtualRouterEl
boolean matchedEndChar = false;
if (str.length() < 2)
return false; // atleast one numeric and one char. example:
// 3h
// 3h
char strEnd = str.toCharArray()[str.length() - 1];
for (char c : endChar.toCharArray()) {
if (strEnd == c) {
@ -285,12 +286,16 @@ public class VirtualRouterElement extends AdapterBase implements VirtualRouterEl
expire = value;
}
if ((expire != null) && !containsOnlyNumbers(expire, timeEndChar)) {
throw new InvalidParameterValueException("Failed LB in validation rule id: " + rule.getId() +
" Cause: expire is not in timeformat: " + expire);
List<IdentityProxy> idList = new ArrayList<IdentityProxy>();
idList.add(new IdentityProxy(rule, rule.getId(), "ruleId"));
throw new InvalidParameterValueException("Failed LB in validation rule with specified id." +
" Cause: expire is not in timeformat: " + expire, idList);
}
if ((tablesize != null) && !containsOnlyNumbers(tablesize, "kmg")) {
throw new InvalidParameterValueException("Failed LB in validation rule id: " + rule.getId() +
" Cause: tablesize is not in size format: " + tablesize);
List<IdentityProxy> idList = new ArrayList<IdentityProxy>();
idList.add(new IdentityProxy(rule, rule.getId(), "ruleId"));
throw new InvalidParameterValueException("Failed LB in validation rule with specified id." +
" Cause: tablesize is not in size format: " + tablesize, idList);
}
} else if (StickinessMethodType.AppCookieBased.getName().equalsIgnoreCase(stickinessPolicy.getMethodName())) {
@ -316,12 +321,16 @@ public class VirtualRouterElement extends AdapterBase implements VirtualRouterEl
}
if ((length != null) && (!containsOnlyNumbers(length, null))) {
throw new InvalidParameterValueException("Failed LB in validation rule id: " + rule.getId() +
" Cause: length is not a number: " + length);
List<IdentityProxy> idList = new ArrayList<IdentityProxy>();
idList.add(new IdentityProxy(rule, rule.getId(), "ruleId"));
throw new InvalidParameterValueException("Failed LB in validation rule with specified id." +
" Cause: length is not a number: " + length, idList);
}
if ((holdTime != null) && (!containsOnlyNumbers(holdTime, timeEndChar) && !containsOnlyNumbers(holdTime, null))) {
throw new InvalidParameterValueException("Failed LB in validation rule id: " + rule.getId() +
" Cause: holdtime is not in timeformat: " + holdTime);
List<IdentityProxy> idList = new ArrayList<IdentityProxy>();
idList.add(new IdentityProxy(rule, rule.getId(), "ruleId"));
throw new InvalidParameterValueException("Failed LB in validation rule with specified id." +
" Cause: holdtime is not in timeformat: " + holdTime, idList);
}
}
}
@ -346,7 +355,7 @@ public class VirtualRouterElement extends AdapterBase implements VirtualRouterEl
List<DomainRouterVO> routers = _routerDao.listByNetworkAndRole(network.getId(), Role.VIRTUAL_ROUTER);
if (routers == null || routers.isEmpty()) {
s_logger.debug("Virtual router elemnt doesn't need to apply firewall rules on the backend; virtual " +
"router doesn't exist in the network " + network.getId());
"router doesn't exist in the network " + network.getId());
return true;
}
@ -368,7 +377,7 @@ public class VirtualRouterElement extends AdapterBase implements VirtualRouterEl
List<DomainRouterVO> routers = _routerDao.listByNetworkAndRole(network.getId(), Role.VIRTUAL_ROUTER);
if (routers == null || routers.isEmpty()) {
s_logger.debug("Virtual router elemnt doesn't need to apply vpn users on the backend; virtual router" +
" doesn't exist in the network " + network.getId());
" doesn't exist in the network " + network.getId());
return null;
}
return _routerMgr.applyVpnUsers(network, users, routers);
@ -384,7 +393,7 @@ public class VirtualRouterElement extends AdapterBase implements VirtualRouterEl
List<DomainRouterVO> routers = _routerDao.listByNetworkAndRole(network.getId(), Role.VIRTUAL_ROUTER);
if (routers == null || routers.isEmpty()) {
s_logger.debug("Virtual router elemnt doesn't need stop vpn on the backend; virtual router doesn't" +
" exist in the network " + network.getId());
" exist in the network " + network.getId());
return true;
}
return _routerMgr.startRemoteAccessVpn(network, vpn, routers);
@ -400,7 +409,7 @@ public class VirtualRouterElement extends AdapterBase implements VirtualRouterEl
List<DomainRouterVO> routers = _routerDao.listByNetworkAndRole(network.getId(), Role.VIRTUAL_ROUTER);
if (routers == null || routers.isEmpty()) {
s_logger.debug("Virtual router elemnt doesn't need stop vpn on the backend; virtual router doesn't " +
"exist in the network " + network.getId());
"exist in the network " + network.getId());
return true;
}
return _routerMgr.deleteRemoteAccessVpn(network, vpn, routers);
@ -424,7 +433,7 @@ public class VirtualRouterElement extends AdapterBase implements VirtualRouterEl
List<DomainRouterVO> routers = _routerDao.listByNetworkAndRole(network.getId(), Role.VIRTUAL_ROUTER);
if (routers == null || routers.isEmpty()) {
s_logger.debug("Virtual router elemnt doesn't need to associate ip addresses on the backend; virtual " +
"router doesn't exist in the network " + network.getId());
"router doesn't exist in the network " + network.getId());
return true;
}
@ -452,61 +461,61 @@ public class VirtualRouterElement extends AdapterBase implements VirtualRouterEl
method.addParam("cookie-name", false, "Cookie name passed in http header by the LB to the client.", false);
method.addParam("mode", false,
"Valid values: insert, rewrite, prefix. Default value: insert. In the insert mode cookie will be created" +
" by the LB. In other modes, cookie will be created by the server and LB modifies it.", false);
" by the LB. In other modes, cookie will be created by the server and LB modifies it.", false);
method.addParam(
"nocache",
false,
"This option is recommended in conjunction with the insert mode when there is a cache between the client" +
" and HAProxy, as it ensures that a cacheable response will be tagged non-cacheable if a cookie needs " +
"to be inserted. This is important because if all persistence cookies are added on a cacheable home page" +
" for instance, then all customers will then fetch the page from an outer cache and will all share the " +
"same persistence cookie, leading to one server receiving much more traffic than others. See also the " +
"insert and postonly options. ",
true);
" and HAProxy, as it ensures that a cacheable response will be tagged non-cacheable if a cookie needs " +
"to be inserted. This is important because if all persistence cookies are added on a cacheable home page" +
" for instance, then all customers will then fetch the page from an outer cache and will all share the " +
"same persistence cookie, leading to one server receiving much more traffic than others. See also the " +
"insert and postonly options. ",
true);
method.addParam(
"indirect",
false,
"When this option is specified in insert mode, cookies will only be added when the server was not reached" +
" after a direct access, which means that only when a server is elected after applying a load-balancing algorithm," +
" or after a redispatch, then the cookie will be inserted. If the client has all the required information" +
" to connect to the same server next time, no further cookie will be inserted. In all cases, when the " +
"indirect option is used in insert mode, the cookie is always removed from the requests transmitted to " +
"the server. The persistence mechanism then becomes totally transparent from the application point of view.",
true);
" after a direct access, which means that only when a server is elected after applying a load-balancing algorithm," +
" or after a redispatch, then the cookie will be inserted. If the client has all the required information" +
" to connect to the same server next time, no further cookie will be inserted. In all cases, when the " +
"indirect option is used in insert mode, the cookie is always removed from the requests transmitted to " +
"the server. The persistence mechanism then becomes totally transparent from the application point of view.",
true);
method.addParam(
"postonly",
false,
"This option ensures that cookie insertion will only be performed on responses to POST requests. It is an" +
" alternative to the nocache option, because POST responses are not cacheable, so this ensures that the " +
"persistence cookie will never get cached.Since most sites do not need any sort of persistence before the" +
" first POST which generally is a login request, this is a very efficient method to optimize caching " +
"without risking to find a persistence cookie in the cache. See also the insert and nocache options.",
true);
" alternative to the nocache option, because POST responses are not cacheable, so this ensures that the " +
"persistence cookie will never get cached.Since most sites do not need any sort of persistence before the" +
" first POST which generally is a login request, this is a very efficient method to optimize caching " +
"without risking to find a persistence cookie in the cache. See also the insert and nocache options.",
true);
method.addParam(
"domain",
false,
"This option allows to specify the domain at which a cookie is inserted. It requires exactly one parameter:" +
" a valid domain name. If the domain begins with a dot, the browser is allowed to use it for any host " +
"ending with that name. It is also possible to specify several domain names by invoking this option multiple" +
" times. Some browsers might have small limits on the number of domains, so be careful when doing that. " +
"For the record, sending 10 domains to MSIE 6 or Firefox 2 works as expected.",
false);
" a valid domain name. If the domain begins with a dot, the browser is allowed to use it for any host " +
"ending with that name. It is also possible to specify several domain names by invoking this option multiple" +
" times. Some browsers might have small limits on the number of domains, so be careful when doing that. " +
"For the record, sending 10 domains to MSIE 6 or Firefox 2 works as expected.",
false);
methodList.add(method);
method = new LbStickinessMethod(StickinessMethodType.AppCookieBased,
"This is App session based sticky method. Define session stickiness on an existing application cookie. " +
"It can be used only for a specific http traffic");
method.addParam("cookie-name", false, "This is the name of the cookie used by the application and which LB will " +
"have to learn for each new session. Default value: Auto geneared based on ip", false);
"have to learn for each new session. Default value: Auto geneared based on ip", false);
method.addParam("length", false, "This is the max number of characters that will be memorized and checked in " +
"each cookie value. Default value:52", false);
"each cookie value. Default value:52", false);
method.addParam(
"holdtime",
false,
"This is the time after which the cookie will be removed from memory if unused. The value should be in " +
"the format Example : 20s or 30m or 4h or 5d . only seconds(s), minutes(m) hours(h) and days(d) are valid," +
" cannot use th combinations like 20h30m. Default value:3h ",
false);
"the format Example : 20s or 30m or 4h or 5d . only seconds(s), minutes(m) hours(h) and days(d) are valid," +
" cannot use th combinations like 20h30m. Default value:3h ",
false);
method.addParam(
"request-learn",
false,
@ -516,24 +525,24 @@ public class VirtualRouterElement extends AdapterBase implements VirtualRouterEl
"prefix",
false,
"When this option is specified, haproxy will match on the cookie prefix (or URL parameter prefix). " +
"The appsession value is the data following this prefix. Example : appsession ASPSESSIONID len 64 timeout 3h prefix This will match the cookie ASPSESSIONIDXXXX=XXXXX, the appsession value will be XXXX=XXXXX.",
true);
"The appsession value is the data following this prefix. Example : appsession ASPSESSIONID len 64 timeout 3h prefix This will match the cookie ASPSESSIONIDXXXX=XXXXX, the appsession value will be XXXX=XXXXX.",
true);
method.addParam(
"mode",
false,
"This option allows to change the URL parser mode. 2 modes are currently supported : - path-parameters " +
": The parser looks for the appsession in the path parameters part (each parameter is separated by a semi-colon), " +
"which is convenient for JSESSIONID for example.This is the default mode if the option is not set. - query-string :" +
" In this mode, the parser will look for the appsession in the query string.",
false);
": The parser looks for the appsession in the path parameters part (each parameter is separated by a semi-colon), " +
"which is convenient for JSESSIONID for example.This is the default mode if the option is not set. - query-string :" +
" In this mode, the parser will look for the appsession in the query string.",
false);
methodList.add(method);
method = new LbStickinessMethod(StickinessMethodType.SourceBased, "This is source based Stickiness method, " +
"it can be used for any type of protocol.");
"it can be used for any type of protocol.");
method.addParam("tablesize", false, "Size of table to store source ip addresses. example: tablesize=200k or 300m" +
" or 400g. Default value:200k", false);
" or 400g. Default value:200k", false);
method.addParam("expire", false, "Entry in source ip table will expire after expire duration. units can be s,m,h,d ." +
" example: expire=30m 20s 50h 4d. Default value:3h", false);
" example: expire=30m 20s 50h 4d. Default value:3h", false);
methodList.add(method);
Gson gson = new Gson();
@ -593,7 +602,7 @@ public class VirtualRouterElement extends AdapterBase implements VirtualRouterEl
List<DomainRouterVO> routers = _routerDao.listByNetworkAndRole(config.getId(), Role.VIRTUAL_ROUTER);
if (routers == null || routers.isEmpty()) {
s_logger.debug("Virtual router elemnt doesn't need to apply static nat on the backend; virtual " +
"router doesn't exist in the network " + config.getId());
"router doesn't exist in the network " + config.getId());
return true;
}
@ -694,7 +703,7 @@ public class VirtualRouterElement extends AdapterBase implements VirtualRouterEl
List<DomainRouterVO> routers = _routerDao.listByNetworkAndRole(network.getId(), Role.VIRTUAL_ROUTER);
if (routers == null || routers.isEmpty()) {
s_logger.debug("Virtual router elemnt doesn't need to apply firewall rules on the backend; virtual " +
"router doesn't exist in the network " + network.getId());
"router doesn't exist in the network " + network.getId());
return true;
}
@ -735,7 +744,7 @@ public class VirtualRouterElement extends AdapterBase implements VirtualRouterEl
result = result && (_routerMgr.destroyRouter(router.getId()) != null);
}
_vrProviderDao.remove(elementId);
return result;
}
@ -764,7 +773,7 @@ public class VirtualRouterElement extends AdapterBase implements VirtualRouterEl
@Override
public boolean addDhcpEntry(Network network, NicProfile nic, VirtualMachineProfile<? extends VirtualMachine> vm,
DeployDestination dest, ReservationContext context)
throws ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException {
throws ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException {
if (canHandle(network, Service.Dhcp)) {
if (vm.getType() != VirtualMachine.Type.User) {
return false;
@ -787,7 +796,7 @@ public class VirtualRouterElement extends AdapterBase implements VirtualRouterEl
@Override
public boolean addPasswordAndUserdata(Network network, NicProfile nic, VirtualMachineProfile<? extends VirtualMachine> vm,
DeployDestination dest, ReservationContext context)
throws ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException {
throws ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException {
if (canHandle(network, Service.UserData)) {
if (vm.getType() != VirtualMachine.Type.User) {
return false;

View File

@ -61,6 +61,7 @@ import com.cloud.user.Account;
import com.cloud.user.AccountManager;
import com.cloud.user.DomainManager;
import com.cloud.user.UserContext;
import com.cloud.utils.IdentityProxy;
import com.cloud.utils.Ternary;
import com.cloud.utils.component.Inject;
import com.cloud.utils.component.Manager;
@ -148,25 +149,25 @@ public class FirewallManagerImpl implements FirewallService, FirewallManager, Ma
public FirewallRule createFirewallRule(long ipAddrId, Account caller, String xId, Integer portStart,
Integer portEnd, String protocol, List<String> sourceCidrList, Integer icmpCode, Integer icmpType,
Long relatedRuleId, FirewallRule.FirewallRuleType type, long networkId) throws NetworkRuleConflictException {
IPAddressVO ipAddress = _ipAddressDao.findById(ipAddrId);
// Validate ip address
if (ipAddress == null && type == FirewallRule.FirewallRuleType.User) {
throw new InvalidParameterValueException("Unable to create firewall rule; ip id=" + ipAddrId +
" doesn't exist in the system");
throw new InvalidParameterValueException("Unable to create firewall rule; " +
"couldn't locate IP address by id in the system", null);
}
_networkMgr.checkIpForService(ipAddress, Service.Firewall);
validateFirewallRule(caller, ipAddress, portStart, portEnd, protocol, Purpose.Firewall, type);
// icmp code and icmp type can't be passed in for any other protocol rather than icmp
if (!protocol.equalsIgnoreCase(NetUtils.ICMP_PROTO) && (icmpCode != null || icmpType != null)) {
throw new InvalidParameterValueException("Can specify icmpCode and icmpType for ICMP protocol only");
throw new InvalidParameterValueException("Can specify icmpCode and icmpType for ICMP protocol only", null);
}
if (protocol.equalsIgnoreCase(NetUtils.ICMP_PROTO) && (portStart != null || portEnd != null)) {
throw new InvalidParameterValueException("Can't specify start/end port when protocol is ICMP");
throw new InvalidParameterValueException("Can't specify start/end port when protocol is ICMP", null);
}
Long accountId = null;
@ -209,8 +210,13 @@ public class FirewallManagerImpl implements FirewallService, FirewallManager, Ma
if (ipId != null) {
IPAddressVO ipAddressVO = _ipAddressDao.findById(ipId);
if (ipAddressVO == null || !ipAddressVO.readyToUse()) {
throw new InvalidParameterValueException("Ip address id=" + ipId + " not ready for firewall rules yet");
if (ipAddressVO == null) {
throw new InvalidParameterValueException("Couldn't locate Ip address by id", null);
}
if (!ipAddressVO.readyToUse()) {
List<IdentityProxy> idList = new ArrayList<IdentityProxy>();
idList.add(new IdentityProxy(ipAddressVO, ipId, "IpId"));
throw new InvalidParameterValueException("Ip address with specified id is not ready for firewall rules yet", idList);
}
_accountMgr.checkAccess(caller, null, true, ipAddressVO);
}
@ -228,19 +234,19 @@ public class FirewallManagerImpl implements FirewallService, FirewallManager, Ma
sb.and("id", sb.entity().getId(), Op.EQ);
sb.and("ip", sb.entity().getSourceIpAddressId(), Op.EQ);
sb.and("purpose", sb.entity().getPurpose(), Op.EQ);
if (tags != null && !tags.isEmpty()) {
SearchBuilder<ResourceTagVO> tagSearch = _resourceTagDao.createSearchBuilder();
for (int count=0; count < tags.size(); count++) {
tagSearch.or().op("key" + String.valueOf(count), tagSearch.entity().getKey(), SearchCriteria.Op.EQ);
tagSearch.and("value" + String.valueOf(count), tagSearch.entity().getValue(), SearchCriteria.Op.EQ);
tagSearch.cp();
SearchBuilder<ResourceTagVO> tagSearch = _resourceTagDao.createSearchBuilder();
for (int count=0; count < tags.size(); count++) {
tagSearch.or().op("key" + String.valueOf(count), tagSearch.entity().getKey(), SearchCriteria.Op.EQ);
tagSearch.and("value" + String.valueOf(count), tagSearch.entity().getValue(), SearchCriteria.Op.EQ);
tagSearch.cp();
}
tagSearch.and("resourceType", tagSearch.entity().getResourceType(), SearchCriteria.Op.EQ);
sb.groupBy(sb.entity().getId());
sb.join("tagSearch", tagSearch, sb.entity().getId(), tagSearch.entity().getResourceId(), JoinBuilder.JoinType.INNER);
}
tagSearch.and("resourceType", tagSearch.entity().getResourceType(), SearchCriteria.Op.EQ);
sb.groupBy(sb.entity().getId());
sb.join("tagSearch", tagSearch, sb.entity().getId(), tagSearch.entity().getResourceId(), JoinBuilder.JoinType.INNER);
}
SearchCriteria<FirewallRuleVO> sc = sb.create();
_accountMgr.buildACLSearchCriteria(sc, domainId, isRecursive, permittedAccounts, listProjectResourcesCriteria);
@ -248,7 +254,7 @@ public class FirewallManagerImpl implements FirewallService, FirewallManager, Ma
if (id != null) {
sc.setParameters("id", id);
}
if (tags != null && !tags.isEmpty()) {
int count = 0;
sc.setJoinParameters("tagSearch", "resourceType", TaggedResourceType.FirewallRule.toString());
@ -273,7 +279,7 @@ public class FirewallManagerImpl implements FirewallService, FirewallManager, Ma
List<FirewallRuleVO> rules = _firewallDao.listByIpAndPurposeAndNotRevoked(newRule.getSourceIpAddressId(), null);
assert (rules.size() >= 1) : "For network rules, we now always first persist the rule and then check for " +
"network conflicts so we should at least have one rule at this point.";
"network conflicts so we should at least have one rule at this point.";
for (FirewallRuleVO rule : rules) {
if (rule.getId() == newRule.getId()) {
@ -282,7 +288,7 @@ public class FirewallManagerImpl implements FirewallService, FirewallManager, Ma
boolean oneOfRulesIsFirewall = ((rule.getPurpose() == Purpose.Firewall || newRule.getPurpose() == Purpose.Firewall)
&& ((newRule.getPurpose() != rule.getPurpose()) || (!newRule.getProtocol()
.equalsIgnoreCase(rule.getProtocol()))));
.equalsIgnoreCase(rule.getProtocol()))));
// if both rules are firewall and their cidrs are different, we can skip port ranges verification
boolean bothRulesFirewall = (rule.getPurpose() == newRule.getPurpose() && rule.getPurpose() == Purpose.Firewall);
@ -323,7 +329,9 @@ public class FirewallManagerImpl implements FirewallService, FirewallManager, Ma
if (newRule.getIcmpCode().longValue() == rule.getIcmpCode().longValue()
&& newRule.getIcmpType().longValue() == rule.getIcmpType().longValue()
&& newRule.getProtocol().equalsIgnoreCase(rule.getProtocol()) && duplicatedCidrs) {
throw new InvalidParameterValueException("New rule conflicts with existing rule id=" + rule.getId());
List<IdentityProxy> idList = new ArrayList<IdentityProxy>();
idList.add(new IdentityProxy(rule, rule.getId(), "ruleId"));
throw new InvalidParameterValueException("New rule conflicts with existing rule with specified id", idList);
}
}
@ -334,12 +342,12 @@ public class FirewallManagerImpl implements FirewallService, FirewallManager, Ma
} else if (!oneOfRulesIsFirewall && !(bothRulesFirewall && !duplicatedCidrs)
&& ((rule.getSourcePortStart().intValue() <= newRule.getSourcePortStart().intValue()
&& rule.getSourcePortEnd().intValue() >= newRule.getSourcePortStart().intValue())
|| (rule.getSourcePortStart().intValue() <= newRule.getSourcePortEnd().intValue()
&& rule.getSourcePortEnd().intValue() >= newRule.getSourcePortEnd().intValue())
|| (newRule.getSourcePortStart().intValue() <= rule.getSourcePortStart().intValue()
&& newRule.getSourcePortEnd().intValue() >= rule.getSourcePortStart().intValue())
|| (newRule.getSourcePortStart().intValue() <= rule.getSourcePortEnd().intValue()
&& newRule.getSourcePortEnd().intValue() >= rule.getSourcePortEnd().intValue()))) {
|| (rule.getSourcePortStart().intValue() <= newRule.getSourcePortEnd().intValue()
&& rule.getSourcePortEnd().intValue() >= newRule.getSourcePortEnd().intValue())
|| (newRule.getSourcePortStart().intValue() <= rule.getSourcePortStart().intValue()
&& newRule.getSourcePortEnd().intValue() >= rule.getSourcePortStart().intValue())
|| (newRule.getSourcePortStart().intValue() <= rule.getSourcePortEnd().intValue()
&& newRule.getSourcePortEnd().intValue() >= rule.getSourcePortEnd().intValue()))) {
// we allow port forwarding rules with the same parameters but different protocols
boolean allowPf = (rule.getPurpose() == Purpose.PortForwarding && newRule.getPurpose() == Purpose.PortForwarding
@ -363,15 +371,15 @@ public class FirewallManagerImpl implements FirewallService, FirewallManager, Ma
public void validateFirewallRule(Account caller, IPAddressVO ipAddress, Integer portStart, Integer portEnd,
String proto, Purpose purpose, FirewallRuleType type) {
if (portStart != null && !NetUtils.isValidPort(portStart)) {
throw new InvalidParameterValueException("publicPort is an invalid value: " + portStart);
throw new InvalidParameterValueException("publicPort is an invalid value: " + portStart, null);
}
if (portEnd != null && !NetUtils.isValidPort(portEnd)) {
throw new InvalidParameterValueException("Public port range is an invalid value: " + portEnd);
throw new InvalidParameterValueException("Public port range is an invalid value: " + portEnd, null);
}
// start port can't be bigger than end port
if (portStart != null && portEnd != null && portStart > portEnd) {
throw new InvalidParameterValueException("Start port can't be bigger than end port");
throw new InvalidParameterValueException("Start port can't be bigger than end port", null);
}
if (ipAddress == null && type == FirewallRuleType.System) {
@ -384,8 +392,9 @@ public class FirewallManagerImpl implements FirewallService, FirewallManager, Ma
Long networkId = null;
if (ipAddress.getAssociatedWithNetworkId() == null) {
throw new InvalidParameterValueException("Unable to create firewall rule ; ip id=" +
ipAddress.getId() + " is not associated with any network");
List<IdentityProxy> idList = new ArrayList<IdentityProxy>();
idList.add(new IdentityProxy(ipAddress, ipAddress.getId(), "IpId"));
throw new InvalidParameterValueException("Unable to create firewall rule ; ip with specified id is not associated with any network", idList);
} else {
networkId = ipAddress.getAssociatedWithNetworkId();
}
@ -407,9 +416,11 @@ public class FirewallManagerImpl implements FirewallService, FirewallManager, Ma
if (caps != null) {
String supportedProtocols = caps.get(Capability.SupportedProtocols).toLowerCase();
if (!supportedProtocols.contains(proto.toLowerCase())) {
throw new InvalidParameterValueException("Protocol " + proto + " is not supported in zone " + network.getDataCenterId());
List<IdentityProxy> idList = new ArrayList<IdentityProxy>();
idList.add(new IdentityProxy(network, network.getDataCenterId(), "dcId"));
throw new InvalidParameterValueException("Protocol " + proto + " is not supported in zone with specified id", idList);
} else if (proto.equalsIgnoreCase(NetUtils.ICMP_PROTO) && purpose != Purpose.Firewall) {
throw new InvalidParameterValueException("Protocol " + proto + " is currently supported only for rules with purpose " + Purpose.Firewall);
throw new InvalidParameterValueException("Protocol " + proto + " is currently supported only for rules with purpose " + Purpose.Firewall, null);
}
}
}
@ -448,18 +459,18 @@ public class FirewallManagerImpl implements FirewallService, FirewallManager, Ma
@DB
@Override
public void removeRule(FirewallRule rule) {
Transaction txn = Transaction.currentTxn();
txn.start();
//remove the rule
_firewallDao.remove(rule.getId());
//if the rule is the last one for the ip address assigned to VPC, unassign it from the network
IpAddress ip = _ipAddressDao.findById(rule.getSourceIpAddressId());
if (ip != null && ip.getVpcId() != null && _firewallDao.listByIp(ip.getId()).isEmpty()) {
_networkMgr.unassignIPFromVpcNetwork(ip.getId());
}
txn.commit();
}
@ -504,11 +515,11 @@ public class FirewallManagerImpl implements FirewallService, FirewallManager, Ma
FirewallRuleVO rule = _firewallDao.findById(ruleId);
if (rule == null || rule.getPurpose() != Purpose.Firewall) {
throw new InvalidParameterValueException("Unable to find " + ruleId + " having purpose " + Purpose.Firewall);
throw new InvalidParameterValueException("Unable to find rule having purpose " + Purpose.Firewall, null);
}
if (rule.getType() == FirewallRuleType.System && caller.getType() != Account.ACCOUNT_TYPE_ADMIN) {
throw new InvalidParameterValueException("Only root admin can delete the system wide firewall rule");
throw new InvalidParameterValueException("Only root admin can delete the system wide firewall rule", null);
}
_accountMgr.checkAccess(caller, null, true, rule);
@ -602,7 +613,7 @@ public class FirewallManagerImpl implements FirewallService, FirewallManager, Ma
@Override
public FirewallRule createRuleForAllCidrs(long ipAddrId, Account caller,
Integer startPort, Integer endPort, String protocol, Integer icmpCode, Integer icmpType, Long relatedRuleId, long networkId)
throws NetworkRuleConflictException {
throws NetworkRuleConflictException {
// If firwallRule for this port range already exists, return it
List<FirewallRuleVO> rules = _firewallDao.listByIpPurposeAndProtocolAndNotRevoked(ipAddrId, startPort, endPort,

View File

@ -65,24 +65,24 @@ public class DirectNetworkGuru extends AdapterBase implements NetworkGuru {
IPAddressDao _ipAddressDao;
@Inject
NetworkOfferingDao _networkOfferingDao;
private static final TrafficType[] _trafficTypes = {TrafficType.Guest};
@Override
public boolean isMyTrafficType(TrafficType type) {
for (TrafficType t : _trafficTypes) {
if (t == type) {
return true;
}
}
return false;
for (TrafficType t : _trafficTypes) {
if (t == type) {
return true;
}
}
return false;
}
@Override
public TrafficType[] getSupportedTrafficType() {
return _trafficTypes;
return _trafficTypes;
}
protected boolean canHandle(NetworkOffering offering, DataCenter dc) {
// this guru handles only Guest networks in Advance zone with source nat service disabled
if (dc.getNetworkType() == NetworkType.Advanced && isMyTrafficType(offering.getTrafficType()) && offering.getGuestType() == GuestType.Shared) {
@ -110,7 +110,7 @@ public class DirectNetworkGuru extends AdapterBase implements NetworkGuru {
if (userSpecified != null) {
if ((userSpecified.getCidr() == null && userSpecified.getGateway() != null) || (userSpecified.getCidr() != null && userSpecified.getGateway() == null)) {
throw new InvalidParameterValueException("cidr and gateway must be specified together.");
throw new InvalidParameterValueException("cidr and gateway must be specified together.", null);
}
if (userSpecified.getCidr() != null) {
@ -152,7 +152,7 @@ public class DirectNetworkGuru extends AdapterBase implements NetworkGuru {
@Override
public NicProfile allocate(Network network, NicProfile nic, VirtualMachineProfile<? extends VirtualMachine> vm) throws InsufficientVirtualNetworkCapcityException,
InsufficientAddressCapacityException, ConcurrentOperationException {
InsufficientAddressCapacityException, ConcurrentOperationException {
DataCenter dc = _dcDao.findById(network.getDataCenterId());
@ -191,10 +191,10 @@ public class DirectNetworkGuru extends AdapterBase implements NetworkGuru {
@Override @DB
public void deallocate(Network network, NicProfile nic, VirtualMachineProfile<? extends VirtualMachine> vm) {
if (s_logger.isDebugEnabled()) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Deallocate network: networkId: " + nic.getNetworkId() + ", ip: " + nic.getIp4Address());
}
IPAddressVO ip = _ipAddressDao.findByIpAndSourceNetworkId(nic.getNetworkId(), nic.getIp4Address());
if (ip != null) {
Transaction txn = Transaction.currentTxn();

View File

@ -136,7 +136,7 @@ public class GuestNetworkGuru extends AdapterBase implements NetworkGuru {
if (userSpecified != null) {
if ((userSpecified.getCidr() == null && userSpecified.getGateway() != null) ||
(userSpecified.getCidr() != null && userSpecified.getGateway() == null)) {
throw new InvalidParameterValueException("cidr and gateway must be specified together.");
throw new InvalidParameterValueException("cidr and gateway must be specified together.", null);
}
if (userSpecified.getCidr() != null) {
@ -255,12 +255,12 @@ public class GuestNetworkGuru extends AdapterBase implements NetworkGuru {
}
protected void allocateVnet(Network network, NetworkVO implemented, long dcId,
long physicalNetworkId, String reservationId) throws InsufficientVirtualNetworkCapcityException {
long physicalNetworkId, String reservationId) throws InsufficientVirtualNetworkCapcityException {
if (network.getBroadcastUri() == null) {
String vnet = _dcDao.allocateVnet(dcId, physicalNetworkId, network.getAccountId(), reservationId);
if (vnet == null) {
throw new InsufficientVirtualNetworkCapcityException("Unable to allocate vnet as a " +
"part of network " + network + " implement ", DataCenter.class, dcId);
"part of network " + network + " implement ", DataCenter.class, dcId);
}
implemented.setBroadcastUri(BroadcastDomainType.Vlan.toUri(vnet));
EventUtils.saveEvent(UserContext.current().getCallerUserId(), network.getAccountId(),
@ -269,7 +269,7 @@ public class GuestNetworkGuru extends AdapterBase implements NetworkGuru {
implemented.setBroadcastUri(network.getBroadcastUri());
}
}
@Override
public Network implement(Network network, NetworkOffering offering, DeployDestination dest,
ReservationContext context) throws InsufficientVirtualNetworkCapcityException {
@ -299,10 +299,10 @@ public class GuestNetworkGuru extends AdapterBase implements NetworkGuru {
@Override
public NicProfile allocate(Network network, NicProfile nic, VirtualMachineProfile<? extends VirtualMachine> vm)
throws InsufficientVirtualNetworkCapcityException,
InsufficientAddressCapacityException {
InsufficientAddressCapacityException {
assert (network.getTrafficType() == TrafficType.Guest) : "Look at my name! Why are you calling" +
" me when the traffic type is : " + network.getTrafficType();
" me when the traffic type is : " + network.getTrafficType();
if (nic == null) {
nic = new NicProfile(ReservationStrategy.Start, null, null, null, null);
@ -363,7 +363,7 @@ public class GuestNetworkGuru extends AdapterBase implements NetworkGuru {
@Override
public void reserve(NicProfile nic, Network network, VirtualMachineProfile<? extends VirtualMachine> vm,
DeployDestination dest, ReservationContext context)
throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException {
throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException {
assert (nic.getReservationStrategy() == ReservationStrategy.Start) : "What can I do for nics that are not allocated at start? ";
nic.setBroadcastUri(network.getBroadcastUri());
@ -385,7 +385,7 @@ public class GuestNetworkGuru extends AdapterBase implements NetworkGuru {
profile.getPhysicalNetworkId(), profile.getAccountId(), profile.getReservationId());
EventUtils.saveEvent(UserContext.current().getCallerUserId(), profile.getAccountId(),
EventVO.LEVEL_INFO, EventTypes.EVENT_ZONE_VLAN_RELEASE, "Released Zone Vlan: "
+profile.getBroadcastUri().getHost()+" for Network: "+profile.getId(), 0);
+profile.getBroadcastUri().getHost()+" for Network: "+profile.getId(), 0);
profile.setBroadcastUri(null);
}
}

View File

@ -21,7 +21,6 @@ import com.cloud.dc.DataCenter;
import com.cloud.dc.DataCenter.NetworkType;
import com.cloud.deploy.DeployDestination;
import com.cloud.deploy.DeploymentPlan;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientAddressCapacityException;
import com.cloud.exception.InsufficientVirtualNetworkCapcityException;
import com.cloud.exception.InvalidParameterValueException;
@ -60,7 +59,7 @@ public class PrivateNetworkGuru extends AdapterBase implements NetworkGuru {
protected PrivateIpDao _privateIpDao;
@Inject
protected NetworkManager _networkMgr;
private static final TrafficType[] _trafficTypes = {TrafficType.Guest};
protected PrivateNetworkGuru() {
@ -106,14 +105,14 @@ public class PrivateNetworkGuru extends AdapterBase implements NetworkGuru {
if (userSpecified != null) {
if ((userSpecified.getCidr() == null && userSpecified.getGateway() != null) ||
(userSpecified.getCidr() != null && userSpecified.getGateway() == null)) {
throw new InvalidParameterValueException("cidr and gateway must be specified together.");
throw new InvalidParameterValueException("cidr and gateway must be specified together.", null);
}
if (userSpecified.getCidr() != null) {
network.setCidr(userSpecified.getCidr());
network.setGateway(userSpecified.getGateway());
} else {
throw new InvalidParameterValueException("Can't design network " + network + "; netmask/gateway must be passed in");
throw new InvalidParameterValueException("Can't design network " + network + "; netmask/gateway must be passed in", null);
}
if (offering.getSpecifyVlan()) {
@ -122,7 +121,7 @@ public class PrivateNetworkGuru extends AdapterBase implements NetworkGuru {
}
} else {
throw new CloudRuntimeException("Can't design network " + network + "; netmask/gateway must be passed in");
}
return network;
@ -133,19 +132,19 @@ public class PrivateNetworkGuru extends AdapterBase implements NetworkGuru {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Deallocate network: networkId: " + nic.getNetworkId() + ", ip: " + nic.getIp4Address());
}
PrivateIpVO ip = _privateIpDao.findByIpAndSourceNetworkId(nic.getNetworkId(), nic.getIp4Address());
if (ip != null) {
_privateIpDao.releaseIpAddress(nic.getIp4Address(), nic.getNetworkId());
}
nic.deallocate();
}
@Override
public Network implement(Network network, NetworkOffering offering, DeployDestination dest,
ReservationContext context) throws InsufficientVirtualNetworkCapcityException {
return network;
}
@ -157,11 +156,11 @@ public class PrivateNetworkGuru extends AdapterBase implements NetworkGuru {
if (!canHandle(offering, dc)) {
return null;
}
if (nic == null) {
nic = new NicProfile(ReservationStrategy.Create, null, null, null, null);
}
getIp(nic, dc, network);
if (nic.getIp4Address() == null) {
@ -172,8 +171,8 @@ public class PrivateNetworkGuru extends AdapterBase implements NetworkGuru {
return nic;
}
protected void getIp(NicProfile nic, DataCenter dc, Network network)
throws InsufficientVirtualNetworkCapcityException,InsufficientAddressCapacityException {
if (nic.getIp4Address() == null) {
@ -196,7 +195,7 @@ public class PrivateNetworkGuru extends AdapterBase implements NetworkGuru {
nic.setDns1(dc.getDns1());
nic.setDns2(dc.getDns2());
}
@Override
public void updateNicProfile(NicProfile profile, Network network) {
@ -210,7 +209,7 @@ public class PrivateNetworkGuru extends AdapterBase implements NetworkGuru {
@Override
public void reserve(NicProfile nic, Network network, VirtualMachineProfile<? extends VirtualMachine> vm,
DeployDestination dest, ReservationContext context)
throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException {
throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException {
if (nic.getIp4Address() == null) {
getIp(nic, _configMgr.getZone(network.getDataCenterId()), network);
nic.setStrategy(ReservationStrategy.Create);
@ -224,7 +223,7 @@ public class PrivateNetworkGuru extends AdapterBase implements NetworkGuru {
@Override
public void shutdown(NetworkProfile profile, NetworkOffering offering) {
}
@Override