Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,6 @@ public interface HypervisorHostListener {
boolean hostAboutToBeRemoved(long hostId);

boolean hostRemoved(long hostId, long clusterId);

boolean hostEnabled(long hostId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,8 @@ public interface StorageManager extends StorageService {

void disconnectHostFromSharedPool(long hostId, long poolId) throws StorageUnavailableException, StorageConflictException;

void enableHost(long hostId) throws StorageUnavailableException, StorageConflictException;

void createCapacityEntry(long poolId);

DataStore createLocalStorage(Host host, StoragePoolInfo poolInfo) throws ConnectionException;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import com.cloud.agent.api.CleanupPersistentNetworkResourceCommand;
import org.apache.cloudstack.agent.lb.SetupMSListCommand;
import org.apache.cloudstack.managed.context.ManagedContextRunnable;
import org.apache.log4j.Logger;
Expand Down Expand Up @@ -118,7 +119,8 @@ public int compare(final Object o1, final Object o2) {
StopCommand.class.toString(), CheckVirtualMachineCommand.class.toString(), PingTestCommand.class.toString(), CheckHealthCommand.class.toString(),
ReadyCommand.class.toString(), ShutdownCommand.class.toString(), SetupCommand.class.toString(),
CleanupNetworkRulesCmd.class.toString(), CheckNetworkCommand.class.toString(), PvlanSetupCommand.class.toString(), CheckOnHostCommand.class.toString(),
ModifyTargetsCommand.class.toString(), ModifySshKeysCommand.class.toString(), ModifyStoragePoolCommand.class.toString(), SetupMSListCommand.class.toString(), RollingMaintenanceCommand.class.toString()};
ModifyTargetsCommand.class.toString(), ModifySshKeysCommand.class.toString(), ModifyStoragePoolCommand.class.toString(), SetupMSListCommand.class.toString(), RollingMaintenanceCommand.class.toString(),
CleanupPersistentNetworkResourceCommand.class.toString()};
protected final static String[] s_commandsNotAllowedInConnectingMode = new String[] { StartCommand.class.toString(), CreateCommand.class.toString() };
static {
Arrays.sort(s_commandsAllowedInMaintenanceMode);
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -130,4 +130,6 @@ public interface NetworkDao extends GenericDao<NetworkVO, Long>, StateDao<State,
List<NetworkVO> listByPhysicalNetworkPvlan(long physicalNetworkId, String broadcastUri, Network.PVlanType pVlanType);

List<NetworkVO> listByPhysicalNetworkPvlan(long physicalNetworkId, String broadcastUri);

List<NetworkVO> getAllPersistentNetworksFromZone(long dataCenterId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,16 @@ public int getOtherPersistentNetworksCount(long id, String broadcastURI, boolean
return persistentNetworks.size();
}

@Override
public List<NetworkVO> getAllPersistentNetworksFromZone(long dataCenterId) {
Object[] guestTypes = {"Isolated", "L2"};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Pearl1594
cannot Isolated network be persistent ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

they can @weizhouapache hence Isolated & l2 are included in the search criteria

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Pearl1594
oh thanks... stupid me. I thought it contains Shared and L2 ...

why exclude Shared networks ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We dont have a concept of Persistent shared networks currently @weizhouapache

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

final SearchCriteria<NetworkVO> sc = PersistentNetworkSearch.create();
sc.setParameters("guestType", guestTypes);
sc.setParameters("dc", dataCenterId);
sc.setJoinParameters("persistent", "persistent", true);
return search(sc, null);
}

@Override
public String getNextAvailableMacAddress(final long networkConfigId, Integer zoneMacIdentifier) {
final SequenceFetcher fetch = SequenceFetcher.getInstance();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,21 @@

import com.cloud.agent.AgentManager;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.CleanupPersistentNetworkResourceCommand;
import com.cloud.agent.api.ModifyStoragePoolAnswer;
import com.cloud.agent.api.ModifyStoragePoolCommand;
import com.cloud.agent.api.SetupPersistentNetworkCommand;
import com.cloud.agent.api.to.NicTO;
import com.cloud.alert.AlertManager;
import com.cloud.configuration.ConfigurationManager;
import com.cloud.exception.StorageConflictException;
import com.cloud.host.HostVO;
import com.cloud.host.dao.HostDao;
import com.cloud.network.NetworkModel;
import com.cloud.network.dao.NetworkDao;
import com.cloud.network.dao.NetworkVO;
import com.cloud.offerings.NetworkOfferingVO;
import com.cloud.offerings.dao.NetworkOfferingDao;
import com.cloud.storage.DataStoreRole;
import com.cloud.storage.Storage;
import com.cloud.storage.StorageManager;
Expand Down Expand Up @@ -62,12 +73,50 @@ public class DefaultHostListener implements HypervisorHostListener {
StorageManager storageManager;
@Inject
StorageService storageService;
@Inject
NetworkOfferingDao networkOfferingDao;
@Inject
HostDao hostDao;
@Inject
NetworkModel networkModel;
@Inject
ConfigurationManager configManager;
@Inject
NetworkDao networkDao;


@Override
public boolean hostAdded(long hostId) {
return true;
}

private boolean createPersistentNetworkResourcesOnHost(long hostId) {
HostVO host = hostDao.findById(hostId);
if (host == null) {
s_logger.warn(String.format("Host with id %ld can't be found", hostId));
return false;
}
setupPersistentNetwork(host);
return true;
}

/**
* Creates a dummy NicTO object which is used by the respective hypervisors to setup network elements / resources
* - bridges(KVM), VLANs(Xen) and portgroups(VMWare) for L2 network
*/
private NicTO createNicTOFromNetworkAndOffering(NetworkVO networkVO, NetworkOfferingVO networkOfferingVO, HostVO hostVO) {
NicTO to = new NicTO();
to.setName(networkModel.getNetworkTag(hostVO.getHypervisorType(), networkVO));
to.setBroadcastType(networkVO.getBroadcastDomainType());
to.setType(networkVO.getTrafficType());
to.setBroadcastUri(networkVO.getBroadcastUri());
to.setIsolationuri(networkVO.getBroadcastUri());
to.setNetworkRateMbps(configManager.getNetworkOfferingNetworkRate(networkOfferingVO.getId(), networkVO.getDataCenterId()));
to.setSecurityGroupEnabled(networkModel.isSecurityGroupSupportedInNetwork(networkVO));
return to;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it is required @weizhouapache

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Pearl1594 ok to me.

}


@Override
public boolean hostConnect(long hostId, long poolId) throws StorageConflictException {
StoragePool pool = (StoragePool) this.dataStoreMgr.getDataStore(poolId, DataStoreRole.Primary);
Expand Down Expand Up @@ -109,7 +158,8 @@ public boolean hostConnect(long hostId, long poolId) throws StorageConflictExcep
storageService.updateStorageCapabilities(poolId, false);

s_logger.info("Connection established between storage pool " + pool + " and host " + hostId);
return true;

return createPersistentNetworkResourcesOnHost(hostId);
}

private void updateStoragePoolHostVOAndDetails(StoragePool pool, long hostId, ModifyStoragePoolAnswer mspAnswer) {
Expand All @@ -124,7 +174,7 @@ private void updateStoragePoolHostVOAndDetails(StoragePool pool, long hostId, Mo
StoragePoolVO poolVO = this.primaryStoreDao.findById(pool.getId());
poolVO.setUsedBytes(mspAnswer.getPoolInfo().getCapacityBytes() - mspAnswer.getPoolInfo().getAvailableBytes());
poolVO.setCapacityBytes(mspAnswer.getPoolInfo().getCapacityBytes());
if(StringUtils.isNotEmpty(mspAnswer.getPoolType())) {
if (StringUtils.isNotEmpty(mspAnswer.getPoolType())) {
StoragePoolDetailVO poolType = storagePoolDetailsDao.findDetail(pool.getId(), "pool_type");
if (poolType == null) {
StoragePoolDetailVO storagePoolDetailVO = new StoragePoolDetailVO(pool.getId(), "pool_type", mspAnswer.getPoolType(), false);
Expand All @@ -142,11 +192,62 @@ public boolean hostDisconnected(long hostId, long poolId) {

@Override
public boolean hostAboutToBeRemoved(long hostId) {
// send host the cleanup persistent network resources
HostVO host = hostDao.findById(hostId);
if (host == null) {
s_logger.warn("Host with id " + hostId + " can't be found");
return false;
}

List<NetworkVO> allPersistentNetworks = networkDao.getAllPersistentNetworksFromZone(host.getDataCenterId()); // find zoneId of host
for (NetworkVO persistentNetworkVO : allPersistentNetworks) {
NetworkOfferingVO networkOfferingVO = networkOfferingDao.findById(persistentNetworkVO.getNetworkOfferingId());
CleanupPersistentNetworkResourceCommand cleanupCmd =
new CleanupPersistentNetworkResourceCommand(createNicTOFromNetworkAndOffering(persistentNetworkVO, networkOfferingVO, host));
Answer answer = agentMgr.easySend(hostId, cleanupCmd);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @Pearl1594 - @NuxRo found there is an issue when the host is on maintenance, the command cannot be sent and the resources are not removed, can you please check?

2022-03-18 16:26:36,292 WARN  [c.c.a.m.AgentManagerImpl] (qtp1747352992-22:ctx-86e6bd15 ctx-c42a5840) (logid:3ca85a2b) Resource [Host:5] is unreachable: Host 5: Unable to send class c
om.cloud.agent.api.CleanupPersistentNetworkResourceCommand because agent ref-trl-2736-k-M7-nicolas-vazquez-kvm2 is in maintenance mode
2022-03-18 16:26:36,292 ERROR [o.a.c.s.d.p.DefaultHostListener] (qtp1747352992-22:ctx-86e6bd15 ctx-c42a5840) (logid:3ca85a2b) Unable to get answer to the cleanup persistent network command 205
2022-03-18 16:26:36,295 DEBUG [c.c.n.NetworkModelImpl] (qtp1747352992-22:ctx-86e6bd15 ctx-c42a5840) (logid:3ca85a2b) Service SecurityGroup is not supported in the network id=205
2022-03-18 16:26:36,296 WARN  [c.c.a.m.AgentManagerImpl] (qtp1747352992-22:ctx-86e6bd15 ctx-c42a5840) (logid:3ca85a2b) Resource [Host:5] is unreachable: Host 5: Unable to send class com.cloud.agent.api.CleanupPersistentNetworkResourceCommand because agent ref-trl-2736-k-M7-nicolas-vazquez-kvm2 is in maintenance mode
2022-03-18 16:26:36,296 ERROR [o.a.c.s.d.p.DefaultHostListener] (qtp1747352992-22:ctx-86e6bd15 ctx-c42a5840) (logid:3ca85a2b) Unable to get answer to the cleanup persistent network command 205

Could verify it works using the deleteHost API passing forced=true

if (answer == null) {
s_logger.error("Unable to get answer to the cleanup persistent network command " + persistentNetworkVO.getId());
continue;
}
if (!answer.getResult()) {
String msg = String.format("Unable to cleanup persistent network resources from network %d on the host %d", persistentNetworkVO.getId(), hostId);
s_logger.error(msg);
}
}
return true;
}

@Override
public boolean hostRemoved(long hostId, long clusterId) {
return true;
}

@Override
public boolean hostEnabled(long hostId) {
HostVO host = hostDao.findById(hostId);
if (host == null) {
s_logger.warn(String.format("Host with id %d can't be found", hostId));
return false;
}
setupPersistentNetwork(host);
return true;
}

private void setupPersistentNetwork(HostVO host) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if it is neccesary to create bridges, vlans on kvm hosts, although it is not harmful.
from my understanding, persist L2/Isolated network means the vlan id will be not released even if there is no vm running.
for vmware/xenserver, it might be useful.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Pearl1594
can you explain a bit what's the benifit of this feature ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, we had persistent networks in ACS - and by definition, these networks are meant to be setup at the time of network created across all hosts. However, while the definition in the docs said that, it didn't actually behave that way. So when a new host is added no bridge/vlan/port-group of the existing persistent network is present. So the idea of this enhancement, is to setup network on the new hosts or when disable hosts are enabled to stay true to the definition of Persistent networks as per docs.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Pearl1594
I just read the cloudstack document http://docs.cloudstack.apache.org/en/latest/adminguide/networking/persistent_networks.html
which was updated by apache/cloudstack-documentation#183

The only thing different from what I understand is

-  Creation of an L2 Persistent network setups up the network devices namely,
   bridges, VLANs or port-groups across all hosts in a zone.

I do not see the benifit to have permanent linux bridges but without any vm on kvm hosts.
I have no idea it is useful for vmware or xenserver.

in my understanding, persistent network means the network will not be shutdown even if no vm running. therefore vlan will be released/re-allocated, virtual router will not be stopped, which are useful for network administrators and users.

List<NetworkVO> allPersistentNetworks = networkDao.getAllPersistentNetworksFromZone(host.getDataCenterId());
for (NetworkVO networkVO : allPersistentNetworks) {
NetworkOfferingVO networkOfferingVO = networkOfferingDao.findById(networkVO.getNetworkOfferingId());

SetupPersistentNetworkCommand persistentNetworkCommand =
new SetupPersistentNetworkCommand(createNicTOFromNetworkAndOffering(networkVO, networkOfferingVO, host));
Answer answer = agentMgr.easySend(host.getId(), persistentNetworkCommand);
if (answer == null) {
throw new CloudRuntimeException("Unable to get answer to the setup persistent network command " + networkVO.getId());
}
if (!answer.getResult()) {
String msg = String.format("Unable to create persistent network resources for network %d on the host %d in zone %d", networkVO.getId(), host.getId(), networkVO.getDataCenterId());
s_logger.error(msg);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -140,4 +140,9 @@ public boolean hostAboutToBeRemoved(long hostId) {
public boolean hostRemoved(long hostId, long clusterId) {
return true;
}

@Override
public boolean hostEnabled(long hostId) {
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,11 @@ public boolean hostRemoved(long hostId, long clusterId) {
return true;
}

@Override
public boolean hostEnabled(long hostId) {
return true;
}

private void handleXenServer(long clusterId, long hostId, long storagePoolId) {
List<String> storagePaths = getStoragePaths(clusterId, storagePoolId);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,9 @@ public boolean hostRemoved(long hostId, long clusterId) {

return true;
}

@Override
public boolean hostEnabled(long hostId) {
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -138,4 +138,9 @@ public boolean hostAboutToBeRemoved(long hostId) {
public boolean hostRemoved(long hostId, long clusterId) {
return true;
}

@Override
public boolean hostEnabled(long hostId) {
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,11 @@ public boolean hostRemoved(long hostId, long clusterId) {
return true;
}

@Override
public boolean hostEnabled(long hostId) {
return true;
}

private void handleXenServer(long clusterId, long hostId, long storagePoolId) {
List<String> storagePaths = getStoragePaths(clusterId, storagePoolId);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,11 @@ public boolean hostRemoved(long hostId, long clusterId) {
return true;
}

@Override
public boolean hostEnabled(long hostId) {
return true;
}

private void handleVMware(HostVO host, boolean add, ModifyTargetsCommand.TargetTypeToRemove targetTypeToRemove) {
if (HypervisorType.VMware.equals(host.getHypervisorType())) {
List<StoragePoolVO> storagePools = storagePoolDao.findPoolsByProvider(SolidFireUtil.SHARED_PROVIDER_NAME);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@
import javax.inject.Inject;
import javax.naming.ConfigurationException;

import com.cloud.exception.StorageConflictException;
import com.cloud.exception.StorageUnavailableException;
import org.apache.cloudstack.annotation.AnnotationService;
import org.apache.cloudstack.annotation.dao.AnnotationDao;
import org.apache.cloudstack.api.ApiConstants;
Expand Down Expand Up @@ -1836,6 +1838,11 @@ public Host updateHost(final UpdateHostCmd cmd) throws NoTransitionException {
if (url != null) {
_storageMgr.updateSecondaryStorage(cmd.getId(), cmd.getUrl());
}
try {
_storageMgr.enableHost(hostId);
} catch (StorageUnavailableException | StorageConflictException e) {
s_logger.error(String.format("Failed to setup host %s when enabled", host));
}

final HostVO updatedHost = _hostDao.findById(hostId);
return updatedHost;
Expand Down
21 changes: 21 additions & 0 deletions server/src/main/java/com/cloud/storage/StorageManagerImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@
import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreDriver;
import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreInfo;
import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreLifeCycle;
import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreProvider;
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotDataFactory;
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotService;
Expand Down Expand Up @@ -1119,6 +1120,26 @@ public void disconnectHostFromSharedPool(long hostId, long poolId) throws Storag
listener.hostDisconnected(hostId, pool.getId());
}

@Override
public void enableHost(long hostId) {
List<DataStoreProvider> providers = _dataStoreProviderMgr.getProviders();
if (providers != null) {
for (DataStoreProvider provider : providers) {
if (provider instanceof PrimaryDataStoreProvider) {
try {
HypervisorHostListener hypervisorHostListener = provider.getHostListener();
if (hypervisorHostListener != null) {
hypervisorHostListener.hostEnabled(hostId);
}
}
catch (Exception ex) {
s_logger.error("hostEnabled(long) failed for storage provider " + provider.getName(), ex);
}
}
}
}
}

@Override
public BigDecimal getStorageOverProvisioningFactor(Long poolId) {
return new BigDecimal(CapacityManager.StorageOverprovisioningFactor.valueIn(poolId));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -260,4 +260,9 @@ public List<NetworkVO> listByPhysicalNetworkPvlan(long physicalNetworkId, String
public List<NetworkVO> listByPhysicalNetworkPvlan(long physicalNetworkId, String broadcastUri) {
return null;
}

@Override
public List<NetworkVO> getAllPersistentNetworksFromZone(long dataCenterId) {
return null;
}
}
Loading