Sergey Gotliv has uploaded a new change for review. Change subject: engine, dao: Introduce ISCSI Bond entity, tables and dao ......................................................................
engine, dao: Introduce ISCSI Bond entity, tables and dao ISCSI Bond is the logical entity representing the group of networks and the group of iscsi targets which will be connected by using these networks. IscsiBond is used for configuring iscsi multipathing. Change-Id: I12313c02810a2f0e75016bdd78b44da43f2154d4 Bug-Url: https://bugzilla.redhat.com/753541 Signed-off-by: Sergey Gotliv <[email protected]> --- A backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/storage/GetConnectableStorageServerConnectionsByStoragePoolIdQuery.java A backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/storage/GetIscsiBondsByStoragePoolIdQuery.java A backend/manager/modules/bll/src/test/java/org/ovirt/engine/core/bll/storage/GetIscsiBondsByStoragePoolIdQueryTest.java A backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/IscsiBond.java M backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/queries/VdcQueryType.java M backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dal/dbbroker/DbFacade.java M backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/BaseDAODbFacade.java A backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/IscsiBondDao.java A backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/IscsiBondDaoDbFacadeImpl.java M backend/manager/modules/dal/src/main/jdbc-resources/engine-daos.properties M backend/manager/modules/dal/src/main/resources/bundles/AppErrors.properties M backend/manager/modules/dal/src/test/java/org/ovirt/engine/core/dao/FixturesTool.java A backend/manager/modules/dal/src/test/java/org/ovirt/engine/core/dao/IscsiBondDaoTest.java M backend/manager/modules/dal/src/test/resources/fixtures.xml M frontend/webadmin/modules/frontend/src/main/java/org/ovirt/engine/ui/frontend/AppErrors.java M frontend/webadmin/modules/userportal-gwtp/src/main/resources/org/ovirt/engine/ui/frontend/AppErrors.properties M frontend/webadmin/modules/webadmin/src/main/resources/org/ovirt/engine/ui/frontend/AppErrors.properties A packaging/dbscripts/iscsi_bonds_sp.sql A packaging/dbscripts/upgrade/03_04_0500_add_iscsi_bond.sql 19 files changed, 798 insertions(+), 0 deletions(-) git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/39/23539/1 diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/storage/GetConnectableStorageServerConnectionsByStoragePoolIdQuery.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/storage/GetConnectableStorageServerConnectionsByStoragePoolIdQuery.java new file mode 100644 index 0000000..3c1b923 --- /dev/null +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/storage/GetConnectableStorageServerConnectionsByStoragePoolIdQuery.java @@ -0,0 +1,18 @@ +package org.ovirt.engine.core.bll.storage; + +import org.ovirt.engine.core.bll.QueriesCommandBase; +import org.ovirt.engine.core.common.queries.IdQueryParameters; + +public class GetConnectableStorageServerConnectionsByStoragePoolIdQuery<P extends IdQueryParameters> extends QueriesCommandBase<P> { + + public GetConnectableStorageServerConnectionsByStoragePoolIdQuery(P parameters) { + super(parameters); + } + + @Override + protected void executeQueryCommand() { + getQueryReturnValue().setReturnValue( + getDbFacade().getStorageServerConnectionDao() + .getAllConnectableStorageSeverConnection(getParameters().getId())); + } +} diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/storage/GetIscsiBondsByStoragePoolIdQuery.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/storage/GetIscsiBondsByStoragePoolIdQuery.java new file mode 100644 index 0000000..25d270b --- /dev/null +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/storage/GetIscsiBondsByStoragePoolIdQuery.java @@ -0,0 +1,30 @@ +package org.ovirt.engine.core.bll.storage; + +import java.util.List; + +import org.ovirt.engine.core.bll.QueriesCommandBase; +import org.ovirt.engine.core.common.businessentities.IscsiBond; +import org.ovirt.engine.core.common.queries.IdQueryParameters; +import org.ovirt.engine.core.compat.Guid; + +public class GetIscsiBondsByStoragePoolIdQuery <P extends IdQueryParameters> extends QueriesCommandBase<P> { + + public GetIscsiBondsByStoragePoolIdQuery(P parameters) { + super(parameters); + } + + @Override + protected void executeQueryCommand() { + List<IscsiBond> iscsiBonds = getDbFacade().getIscsiBondDao().getAllByStoragePoolId(getParameters().getId()); + + for (IscsiBond iscsiBond : iscsiBonds) { + List<Guid> networkIds = getDbFacade().getIscsiBondDao().getNetworkIdsByIscsiBondId(iscsiBond.getId()); + iscsiBond.setNetworkIds(networkIds); + + List<String> connectionIds = getDbFacade().getIscsiBondDao().getStorageConnectionIdsByIscsiBondId(iscsiBond.getId()); + iscsiBond.setStorageConnectionIds(connectionIds); + } + + getQueryReturnValue().setReturnValue(iscsiBonds); + } +} diff --git a/backend/manager/modules/bll/src/test/java/org/ovirt/engine/core/bll/storage/GetIscsiBondsByStoragePoolIdQueryTest.java b/backend/manager/modules/bll/src/test/java/org/ovirt/engine/core/bll/storage/GetIscsiBondsByStoragePoolIdQueryTest.java new file mode 100644 index 0000000..0915037 --- /dev/null +++ b/backend/manager/modules/bll/src/test/java/org/ovirt/engine/core/bll/storage/GetIscsiBondsByStoragePoolIdQueryTest.java @@ -0,0 +1,54 @@ +package org.ovirt.engine.core.bll.storage; + +import static junit.framework.Assert.assertNotNull; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import static junit.framework.Assert.assertEquals; + +import java.util.Collections; +import java.util.List; + +import org.junit.Test; +import org.ovirt.engine.core.bll.AbstractQueryTest; +import org.ovirt.engine.core.common.businessentities.IscsiBond; +import org.ovirt.engine.core.common.queries.IdQueryParameters; +import org.ovirt.engine.core.compat.Guid; +import org.ovirt.engine.core.dao.IscsiBondDao; + +public class GetIscsiBondsByStoragePoolIdQueryTest extends + AbstractQueryTest<IdQueryParameters, GetIscsiBondsByStoragePoolIdQuery<IdQueryParameters>> { + + @Test + public void testExecuteQueryCommand() { + Guid storagePoolId = Guid.newGuid(); + Guid networkId = Guid.newGuid(); + String connectionId = Guid.newGuid().toString(); + + IscsiBond iscsiBond = new IscsiBond(); + iscsiBond.setId(Guid.newGuid()); + + IscsiBondDao iscsiBondDao = mock(IscsiBondDao.class); + + when(getQueryParameters().getId()).thenReturn(storagePoolId); + when(getDbFacadeMockInstance().getIscsiBondDao()).thenReturn(iscsiBondDao); + when(iscsiBondDao.getAllByStoragePoolId(storagePoolId)).thenReturn(Collections.singletonList(iscsiBond)); + when(iscsiBondDao.getNetworkIdsByIscsiBondId(iscsiBond.getId())).thenReturn(Collections.singletonList(networkId)); + when(iscsiBondDao.getStorageConnectionIdsByIscsiBondId(iscsiBond.getId())).thenReturn(Collections.singletonList(connectionId)); + + getQuery().executeQueryCommand(); + + List<IscsiBond> result = getQuery().getQueryReturnValue().getReturnValue(); + + assertNotNull(result); + assertEquals(1, result.size()); + assertEquals(iscsiBond, result.get(0)); + + assertNotNull(iscsiBond.getNetworkIds()); + assertEquals(1, iscsiBond.getNetworkIds().size()); + assertEquals(iscsiBond.getNetworkIds().get(0), networkId); + + assertNotNull(iscsiBond.getStorageConnectionIds()); + assertEquals(1, iscsiBond.getStorageConnectionIds().size()); + assertEquals(iscsiBond.getStorageConnectionIds().get(0), connectionId); + } +} diff --git a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/IscsiBond.java b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/IscsiBond.java new file mode 100644 index 0000000..3903c25 --- /dev/null +++ b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/IscsiBond.java @@ -0,0 +1,139 @@ +package org.ovirt.engine.core.common.businessentities; + +import java.util.LinkedList; +import java.util.List; + +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; + +import org.ovirt.engine.core.common.utils.ObjectUtils; +import org.ovirt.engine.core.common.validation.annotation.ValidDescription; +import org.ovirt.engine.core.common.validation.annotation.ValidI18NName; +import org.ovirt.engine.core.common.validation.group.CreateEntity; +import org.ovirt.engine.core.common.validation.group.UpdateEntity; +import org.ovirt.engine.core.compat.Guid; + +public class IscsiBond extends IVdcQueryable implements BusinessEntity<Guid>, Nameable { + + private static final long serialVersionUID = 6318808440502965971L; + + private Guid id; + private Guid storagePoolId; + + @NotNull(message = "VALIDATION_ISCSI_BOND_NAME_NOT_NULL", groups = { CreateEntity.class, UpdateEntity.class }) + @Size(min = 1, max = 50, message = "VALIDATION_ISCSI_BOND_NAME_MAX", + groups = { CreateEntity.class, UpdateEntity.class }) + @ValidI18NName(message = "VALIDATION_ISCSI_BOND_NAME_INVALID_CHARACTER", + groups = { CreateEntity.class, UpdateEntity.class }) + private String name; + + @Size(max = BusinessEntitiesDefinitions.GENERAL_MAX_SIZE, message = "VALIDATION_ISCSI_BOND_DESCRIPTION_MAX", + groups = { CreateEntity.class, UpdateEntity.class }) + @ValidDescription(message = "VALIDATION_ISCSI_BOND_DESCRIPTION_INVALID", + groups = { CreateEntity.class, UpdateEntity.class }) + private String description; + private List<Guid> networkIds; + private List<String> storageConnectionIds; + + public IscsiBond() { + networkIds = new LinkedList<Guid>(); + storageConnectionIds = new LinkedList<String>(); + } + + public IscsiBond(Guid id, Guid storagePoolId, String name, String description) { + this(); + this.id = id; + this.storagePoolId = storagePoolId; + this.name = name; + this.description = description; + } + + @Override + public Guid getId() { + return id; + } + + @Override + public void setId(Guid id) { + this.id = id; + } + + public Guid getStoragePoolId() { + return storagePoolId; + } + + public void setStoragePoolId(Guid storagePoolId) { + this.storagePoolId = storagePoolId; + } + + @Override + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public List<Guid> getNetworkIds() { + return networkIds; + } + + public void setNetworkIds(List<Guid> networkIds) { + this.networkIds = networkIds; + } + + public List<String> getStorageConnectionIds() { + return storageConnectionIds; + } + + public void setStorageConnectionIds(List<String> connectionIds) { + this.storageConnectionIds = connectionIds; + } + + @Override + public Object getQueryableId() { + return getId(); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((id == null) ? 0 : id.hashCode()); + result = prime * result + ((name == null) ? 0 : name.hashCode()); + result = prime * result + ((description == null) ? 0 : description.hashCode()); + result = prime * result + ((storagePoolId == null) ? 0 : storagePoolId.hashCode()); + result = prime * result + ((networkIds == null) ? 0 : networkIds.hashCode()); + result = prime * result + ((storageConnectionIds == null) ? 0 : storageConnectionIds.hashCode()); + + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj == null || !(obj instanceof IscsiBond)) { + return false; + } + + IscsiBond iscsiBond = (IscsiBond) obj; + return ObjectUtils.objectsEqual(id, iscsiBond.getId()) && + ObjectUtils.objectsEqual(name, iscsiBond.getName()) && + ObjectUtils.objectsEqual(description, iscsiBond.getDescription()) && + ObjectUtils.objectsEqual(storagePoolId, iscsiBond.getStoragePoolId()) && + ObjectUtils.objectsEqual(networkIds, iscsiBond.getNetworkIds()) && + ObjectUtils.objectsEqual(storageConnectionIds, iscsiBond.getStorageConnectionIds()); + } +} diff --git a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/queries/VdcQueryType.java b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/queries/VdcQueryType.java index a488a7b..3dc50bc 100644 --- a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/queries/VdcQueryType.java +++ b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/queries/VdcQueryType.java @@ -209,6 +209,7 @@ GetStorageServerConnectionsForDomain, GetStoragePoolById(VdcQueryAuthType.User), GetStorageDomainsByConnection, + GetConnectableStorageServerConnectionsByStoragePoolId, GetStorageDomainsByStoragePoolId(VdcQueryAuthType.User), GetStorageDomainsByImageId, GetVgList, @@ -226,6 +227,7 @@ GetStorageDomainListById, GetLunsByVgId, GetPermittedStorageDomainsByStoragePoolId(VdcQueryAuthType.User), + GetIscsiBondsByStoragePoolId, // Event Notification GetEventSubscribersBySubscriberIdGrouped, diff --git a/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dal/dbbroker/DbFacade.java b/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dal/dbbroker/DbFacade.java index a9da479..1949018 100644 --- a/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dal/dbbroker/DbFacade.java +++ b/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dal/dbbroker/DbFacade.java @@ -15,6 +15,7 @@ import org.ovirt.engine.core.common.businessentities.DiskImageDynamic; import org.ovirt.engine.core.common.businessentities.DwhHistoryTimekeeping; import org.ovirt.engine.core.common.businessentities.Image; +import org.ovirt.engine.core.common.businessentities.IscsiBond; import org.ovirt.engine.core.common.businessentities.Permissions; import org.ovirt.engine.core.common.businessentities.Provider; import org.ovirt.engine.core.common.businessentities.Role; @@ -64,6 +65,7 @@ import org.ovirt.engine.core.dao.GenericDao; import org.ovirt.engine.core.dao.ImageDao; import org.ovirt.engine.core.dao.ImageStorageDomainMapDao; +import org.ovirt.engine.core.dao.IscsiBondDao; import org.ovirt.engine.core.dao.JobDao; import org.ovirt.engine.core.dao.JobSubjectEntityDao; import org.ovirt.engine.core.dao.LunDAO; @@ -170,6 +172,7 @@ put(VnicProfile.class, VnicProfileDao.class); put(VnicProfileView.class, VnicProfileDao.class); put(DwhHistoryTimekeeping.class, DwhHistoryTimekeepingDao.class); + put(IscsiBond.class, IscsiBondDao.class); } }; @@ -979,4 +982,8 @@ } getCallsHandler().executeStoredProcAsBatch("insert_osinfo", executions); } + + public IscsiBondDao getIscsiBondDao() { + return getDao(IscsiBondDao.class); + } } diff --git a/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/BaseDAODbFacade.java b/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/BaseDAODbFacade.java index bf2a1ef..b17fc06 100644 --- a/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/BaseDAODbFacade.java +++ b/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/BaseDAODbFacade.java @@ -89,6 +89,17 @@ return integerRowMapper; } + private static RowMapper<String> stringRowMapper = new RowMapper<String>() { + @Override + public String mapRow(ResultSet rs, int rowNum) throws SQLException { + return rs.getString(1); + }; + }; + + protected RowMapper<String> getStringMapper() { + return stringRowMapper; + } + protected SimpleJdbcCallsHandler getCallsHandler() { return dbFacade.getCallsHandler(); } diff --git a/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/IscsiBondDao.java b/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/IscsiBondDao.java new file mode 100644 index 0000000..04f95dd --- /dev/null +++ b/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/IscsiBondDao.java @@ -0,0 +1,23 @@ +package org.ovirt.engine.core.dao; + +import java.util.List; + +import org.ovirt.engine.core.common.businessentities.IscsiBond; +import org.ovirt.engine.core.compat.Guid; + +public interface IscsiBondDao extends GenericDao<IscsiBond, Guid> { + + public List<IscsiBond> getAllByStoragePoolId(Guid storagePoolId); + + public List<Guid> getNetworkIdsByIscsiBondId(Guid iscsiBondId); + + public void addNetworkToIscsiBond(Guid iscsiBondId, Guid networkId); + + public void removeNetworkFromIscsiBond(Guid iscsiBondId, Guid networkId); + + public List<String> getStorageConnectionIdsByIscsiBondId(Guid iscsiBondId); + + public void addStorageConnectionToIscsiBond(Guid iscsiBondId, String storageConnectionId); + + public void removeStorageConnectionFromIscsiBond(Guid iscsiBondId, String storageConnectionId); +} diff --git a/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/IscsiBondDaoDbFacadeImpl.java b/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/IscsiBondDaoDbFacadeImpl.java new file mode 100644 index 0000000..bb3f925 --- /dev/null +++ b/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/IscsiBondDaoDbFacadeImpl.java @@ -0,0 +1,102 @@ +package org.ovirt.engine.core.dao; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.List; + +import org.ovirt.engine.core.common.businessentities.IscsiBond; +import org.ovirt.engine.core.compat.Guid; + +import org.springframework.jdbc.core.RowMapper; +import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; + +public class IscsiBondDaoDbFacadeImpl extends DefaultGenericDaoDbFacade<IscsiBond, Guid> implements IscsiBondDao { + + public IscsiBondDaoDbFacadeImpl() { + super("IscsiBond"); + } + + @Override + public List<IscsiBond> getAllByStoragePoolId(Guid storagePoolId) { + return getCallsHandler().executeReadList("GetIscsiBondsByStoragePoolId", + IscsiBondRowMapper.instance, + getCustomMapSqlParameterSource().addValue("storage_pool_id", storagePoolId)); + } + + @Override + public List<Guid> getNetworkIdsByIscsiBondId(Guid iscsiBondId) { + return getCallsHandler().executeReadList("GetNetworksByIscsiBondId", + createGuidMapper(), getCustomMapSqlParameterSource().addValue("iscsi_bond_id", iscsiBondId)); + } + + @Override + public void addNetworkToIscsiBond(Guid iscsiBondId, Guid networkId) { + getCallsHandler().executeModification("AddNetworkToIscsiBond", + getCustomMapSqlParameterSource() + .addValue("iscsi_bond_id", iscsiBondId) + .addValue("network_id", networkId)); + } + + @Override + public void removeNetworkFromIscsiBond(Guid iscsiBondId, Guid networkId) { + getCallsHandler().executeModification("RemoveNetworkFromIscsiBond", + getCustomMapSqlParameterSource() + .addValue("iscsi_bond_id", iscsiBondId) + .addValue("network_id", networkId)); + } + + @Override + public List<String> getStorageConnectionIdsByIscsiBondId(Guid iscsiBondId) { + return getCallsHandler().executeReadList("GetConnectionsByIscsiBondId", + getStringMapper(), getCustomMapSqlParameterSource().addValue("iscsi_bond_id", iscsiBondId)); + } + + @Override + public void addStorageConnectionToIscsiBond(Guid iscsiBondId, String connectionId) { + getCallsHandler().executeModification("AddConnectionToIscsiBond", + getCustomMapSqlParameterSource() + .addValue("iscsi_bond_id", iscsiBondId) + .addValue("connection_id", connectionId)); + } + + @Override + public void removeStorageConnectionFromIscsiBond(Guid iscsiBondId, String connectionId) { + getCallsHandler().executeModification("RemoveConnectionFromIscsiBond", + getCustomMapSqlParameterSource() + .addValue("iscsi_bond_id", iscsiBondId) + .addValue("connection_id", connectionId)); + } + + @Override + protected MapSqlParameterSource createIdParameterMapper(Guid id) { + return getCustomMapSqlParameterSource().addValue("id", id); + } + + @Override + protected MapSqlParameterSource createFullParametersMapper(IscsiBond iscsiBond) { + return createIdParameterMapper(iscsiBond.getId()) + .addValue("name", iscsiBond.getName()) + .addValue("description", iscsiBond.getDescription()) + .addValue("storage_pool_id", iscsiBond.getStoragePoolId()); + } + + @Override + protected RowMapper<IscsiBond> createEntityRowMapper() { + return IscsiBondRowMapper.instance; + } + + private static class IscsiBondRowMapper implements RowMapper<IscsiBond> { + public static final IscsiBondRowMapper instance = new IscsiBondRowMapper(); + + @Override + public IscsiBond mapRow(ResultSet rs, int rowNum) throws SQLException { + IscsiBond entity = new IscsiBond(); + + entity.setId(getGuid(rs, "id")); + entity.setDescription(rs.getString("description")); + entity.setName(rs.getString("name")); + entity.setStoragePoolId(getGuidDefaultNewGuid(rs, "storage_pool_id")); + return entity; + } + } +} diff --git a/backend/manager/modules/dal/src/main/jdbc-resources/engine-daos.properties b/backend/manager/modules/dal/src/main/jdbc-resources/engine-daos.properties index 906d13c..3c966ef 100644 --- a/backend/manager/modules/dal/src/main/jdbc-resources/engine-daos.properties +++ b/backend/manager/modules/dal/src/main/jdbc-resources/engine-daos.properties @@ -71,3 +71,4 @@ ClusterPolicyDao=org.ovirt.engine.core.dao.scheduling.ClusterPolicyDaoImpl DwhHistoryTimekeepingDao=org.ovirt.engine.core.dao.dwh.DwhHistoryTimekeepingDaoDbFacadeImpl AffinityGroupDao=org.ovirt.engine.core.dao.scheduling.AffinityGroupDaoImpl +IscsiBondDao=org.ovirt.engine.core.dao.IscsiBondDaoDbFacadeImpl diff --git a/backend/manager/modules/dal/src/main/resources/bundles/AppErrors.properties b/backend/manager/modules/dal/src/main/resources/bundles/AppErrors.properties index ede6ab1..8f34b2a 100644 --- a/backend/manager/modules/dal/src/main/resources/bundles/AppErrors.properties +++ b/backend/manager/modules/dal/src/main/resources/bundles/AppErrors.properties @@ -1124,3 +1124,10 @@ ACTION_TYPE_FAILED_POSITIVE_AFFINITY_GROUP=VM is associated with a positive Affinity Group and requires to run on the same Host as the other group VMs ACTION_TYPE_FAILED_NEGATIVE_AFFINITY_GROUP=VM is associated with a negative Affinity Group and requires to run on separate Host, which doesn't run other group VMs ACTION_TYPE_FAILED_MIX_POSITIVE_NEGATIVE_AFFINITY_GROUP=VM is associated with both positive and negative Affinity Groups, please reconfigure VM's affinity groups + +# Iscsi Bond +VALIDATION_ISCSI_BOND_NAME_MAX=iSCSI bond name must not exceed 50 characters +VALIDATION_ISCSI_BOND_NAME_NOT_NULL=iSCSI bond name is required +VALIDATION_ISCSI_BOND_DESCRIPTION_MAX=iSCSI bond description must not exceed 4000 characters +VALIDATION_ISCSI_BOND_NAME_INVALID_CHARACTER=iSCSI Bond name must be formed from alpha-numeric characters or "-_." +VALIDATION_SCSI_BOND_DESCRIPTION_INVALID=iSCSI Bond description must be formed only from alpha-numeric characters and special characters that conform to the standard ASCII character set. diff --git a/backend/manager/modules/dal/src/test/java/org/ovirt/engine/core/dao/FixturesTool.java b/backend/manager/modules/dal/src/test/java/org/ovirt/engine/core/dao/FixturesTool.java index 87c6cfc..9a96828 100644 --- a/backend/manager/modules/dal/src/test/java/org/ovirt/engine/core/dao/FixturesTool.java +++ b/backend/manager/modules/dal/src/test/java/org/ovirt/engine/core/dao/FixturesTool.java @@ -498,4 +498,26 @@ public static final String DATA_CENTER_NAME = "rhel6.iscsi"; public static final Guid EXISTING_AFFINITY_GROUP_ID = new Guid("6d849ebf-0ccc-4552-ad09-ccc90cda105d"); + + /** + * Id of predefined iscsi bond with the following properties: + * + * <ul> + * <li>name: IscsiBond1</li> + * <li>storage_pool_id_id: 6d849ebf-755f-4552-ad09-9a090cda105d</li> + * </ul> + */ + public static final Guid ISCSI_BOND_ID = new Guid("7368f2be-1263-41f8-b95e-70cdaf23b80d"); + + /** + * Id of predefined iscsi storage connection id with the following properties: + * + * <ul> + * <li>connection: 10.35.64.25</li> + * <li>iqn: iqn.2008-09.com.hateya:server.targeta</li> + * <li>port: 3260</li> + * <li>portal: 1</li> + * </ul> + */ + public static final String STORAGE_CONNECTION_ID = "0cc146e8-e5ed-482c-8814-270bc48c297e"; } diff --git a/backend/manager/modules/dal/src/test/java/org/ovirt/engine/core/dao/IscsiBondDaoTest.java b/backend/manager/modules/dal/src/test/java/org/ovirt/engine/core/dao/IscsiBondDaoTest.java new file mode 100644 index 0000000..bd6d1ab --- /dev/null +++ b/backend/manager/modules/dal/src/test/java/org/ovirt/engine/core/dao/IscsiBondDaoTest.java @@ -0,0 +1,143 @@ +package org.ovirt.engine.core.dao; + +import java.util.List; + +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertFalse; +import static junit.framework.Assert.assertNotNull; +import static junit.framework.Assert.assertNull; +import static junit.framework.Assert.assertTrue; + +import org.junit.Test; +import org.ovirt.engine.core.common.businessentities.IscsiBond; +import org.ovirt.engine.core.compat.Guid; + +public class IscsiBondDaoTest extends BaseDAOTestCase { + + private IscsiBondDao dao; + private Guid storagePoolId; + private IscsiBond newIscsiBond; + private Guid iscsiBondId; + private Guid networkId; + private String connectionId; + + @Override + public void setUp() throws Exception { + super.setUp(); + + dao = dbFacade.getIscsiBondDao(); + storagePoolId = FixturesTool.STORAGE_POOL_RHEL6_ISCSI_OTHER; + networkId = FixturesTool.NETWORK_ENGINE_2; + iscsiBondId = FixturesTool.ISCSI_BOND_ID; + connectionId = FixturesTool.STORAGE_CONNECTION_ID; + + newIscsiBond = new IscsiBond(); + newIscsiBond.setId(Guid.newGuid()); + newIscsiBond.setName("Multipath"); + newIscsiBond.setDescription("New iscsi bond for multipathing"); + newIscsiBond.setStoragePoolId(storagePoolId); + } + + @Test + public void testGetAllByStoragePoolId() { + List<IscsiBond> iscsiBonds = dao.getAllByStoragePoolId(storagePoolId); + assertEquals(1, iscsiBonds.size()); + } + + @Test + public void testGetAllByStoragePoolIdStoragePoolDoesNotExist() { + List<IscsiBond> iscsiBonds = dao.getAllByStoragePoolId(Guid.Empty); + assertTrue(iscsiBonds.isEmpty()); + } + + @Test + public void testGetNetworkIdsByIscsiBondId() { + List<Guid> networkIds = dao.getNetworkIdsByIscsiBondId(newIscsiBond.getId()); + assertTrue(networkIds.isEmpty()); + } + + @Test + public void testGetIscsiBondByIscsiBondId() { + IscsiBond iscsiBond = dao.get(iscsiBondId); + assertNotNull(iscsiBond); + } + + @Test + public void testAddNewIscsiBond() { + dao.save(newIscsiBond); + + IscsiBond iscsiBond = dao.get(newIscsiBond.getId()); + assertEquals(newIscsiBond, iscsiBond); + } + + @Test + public void testUpdateIscsiBond() { + final String newDescription = "10GB iscsi bond"; + + IscsiBond iscsiBond = dao.get(iscsiBondId); + assertFalse(newDescription.equals(iscsiBond.getDescription())); + + iscsiBond.setDescription(newDescription); + dao.update(iscsiBond); + + iscsiBond = dao.get(iscsiBondId); + assertEquals(newDescription, iscsiBond.getDescription()); + } + + @Test + public void testRemoveIscsiBond() { + IscsiBond iscsiBond = dao.get(iscsiBondId); + assertNotNull(iscsiBond); + + dao.remove(iscsiBondId); + + iscsiBond = dao.get(iscsiBondId); + List<Guid> networks = dao.getNetworkIdsByIscsiBondId(iscsiBondId); + List<String> connections = dao.getStorageConnectionIdsByIscsiBondId(iscsiBondId); + + assertNull(iscsiBond); + assertTrue(networks.isEmpty()); + assertTrue(connections.isEmpty()); + } + + @Test + public void testAddNetworkToIscsiBond() { + dao.addNetworkToIscsiBond(iscsiBondId, networkId); + + List<Guid> networks = dao.getNetworkIdsByIscsiBondId(iscsiBondId); + assertEquals(2, networks.size()); + assertTrue(networks.contains(networkId)); + } + + @Test + public void testRemoveNetworkFromIscsiBond() { + List<Guid> networks = dao.getNetworkIdsByIscsiBondId(iscsiBondId); + networkId = networks.get(0); + + dao.removeNetworkFromIscsiBond(iscsiBondId, networkId); + + networks = dao.getNetworkIdsByIscsiBondId(iscsiBondId); + assertTrue(networks.isEmpty()); + } + + @Test + public void testAddStorageConnectionToIscsiBond() { + dao.addStorageConnectionToIscsiBond(iscsiBondId, connectionId); + + List<String> connections = dao.getStorageConnectionIdsByIscsiBondId(iscsiBondId); + assertEquals(3, connections.size()); + assertTrue(connections.contains(connectionId)); + } + + @Test + public void testRemoveStorageConnectionFromIscsiBond() { + List<String> connections = dao.getStorageConnectionIdsByIscsiBondId(iscsiBondId); + connectionId = connections.get(0); + + dao.removeStorageConnectionFromIscsiBond(iscsiBondId, connectionId); + + connections = dao.getStorageConnectionIdsByIscsiBondId(iscsiBondId); + assertEquals(1, connections.size()); + assertFalse(connections.contains(connectionId)); + } +} diff --git a/backend/manager/modules/dal/src/test/resources/fixtures.xml b/backend/manager/modules/dal/src/test/resources/fixtures.xml index 5d62c7d..f0b0ea2 100644 --- a/backend/manager/modules/dal/src/test/resources/fixtures.xml +++ b/backend/manager/modules/dal/src/test/resources/fixtures.xml @@ -5677,4 +5677,50 @@ <value>77296e00-0cad-4e5a-9299-008a7b6f4355</value> </row> </table> + <table name="iscsi_bonds"> + <column>id</column> + <column>name</column> + <column>description</column> + <column>storage_pool_id</column> + <row> + <value>7368f2be-1263-41f8-b95e-70cdaf23b80d</value> + <value>IscsiBond1</value> + <null/> + <value>6d849ebf-755f-4552-ad09-9a090cda105d</value> + </row> + <row> + <value>3e1004c1-a683-4b9d-8f49-f65b584d78dc</value> + <value>IscsiBond2</value> + <value>10GB Ethernet Storage</value> + <value>386bffd1-e7ed-4b08-bce9-d7df10f8c9a0</value> + </row> + </table> + <table name="iscsi_bonds_networks_map"> + <column>iscsi_bond_id</column> + <column>network_id</column> + <row> + <value>7368f2be-1263-41f8-b95e-70cdaf23b80d</value> + <value>58d5c1c6-cb15-4832-b2a4-023770607188</value> + </row> + <row> + <value>3e1004c1-a683-4b9d-8f49-f65b584d78dc</value> + <value>58d5c1c6-cb15-4832-b2a4-023770607190</value> + </row> + </table> + <table name="iscsi_bonds_storage_connections_map"> + <column>iscsi_bond_id</column> + <column>connection_id</column> + <row> + <value>7368f2be-1263-41f8-b95e-70cdaf23b80d</value> + <value>0cc146e8-e5ed-482c-8814-270bc48c297b</value> + </row> + <row> + <value>7368f2be-1263-41f8-b95e-70cdaf23b80d</value> + <value>0cc146e8-e5ed-482c-8814-270bc48c297c</value> + </row> + <row> + <value>3e1004c1-a683-4b9d-8f49-f65b584d78dc</value> + <value>0cc146e8-e5ed-482c-8814-270bc48c297d</value> + </row> + </table> </dataset> diff --git a/frontend/webadmin/modules/frontend/src/main/java/org/ovirt/engine/ui/frontend/AppErrors.java b/frontend/webadmin/modules/frontend/src/main/java/org/ovirt/engine/ui/frontend/AppErrors.java index 7a22338..935d6d6 100644 --- a/frontend/webadmin/modules/frontend/src/main/java/org/ovirt/engine/ui/frontend/AppErrors.java +++ b/frontend/webadmin/modules/frontend/src/main/java/org/ovirt/engine/ui/frontend/AppErrors.java @@ -2995,4 +2995,19 @@ @DefaultStringValue("VM is associated with both positive and negative Affinity Groups, please reconfigure VM's affinity groups") String ACTION_TYPE_FAILED_MIX_POSITIVE_NEGATIVE_AFFINITY_GROUP(); + + @DefaultStringValue("iSCSI bond name must not exceed 50 characters") + String VALIDATION_ISCSI_BOND_NAME_MAX(); + + @DefaultStringValue("iSCSI bond name is required") + String VALIDATION_ISCSI_BOND_NAME_NOT_NULL(); + + @DefaultStringValue("iSCSI bond description must not exceed 4000 characters") + String VALIDATION_ISCSI_BOND_DESCRIPTION_MAX(); + + @DefaultStringValue("iSCSI Bond name must be formed from alpha-numeric characters or \"-_.\"") + String VALIDATION_ISCSI_BOND_NAME_INVALID_CHARACTER(); + + @DefaultStringValue("iSCSI Bond description must be formed only from alpha-numeric characters and special characters that conform to the standard ASCII character set.") + String VALIDATION_SCSI_BOND_DESCRIPTION_INVALID(); } diff --git a/frontend/webadmin/modules/userportal-gwtp/src/main/resources/org/ovirt/engine/ui/frontend/AppErrors.properties b/frontend/webadmin/modules/userportal-gwtp/src/main/resources/org/ovirt/engine/ui/frontend/AppErrors.properties index f35790a..c5bf41a 100644 --- a/frontend/webadmin/modules/userportal-gwtp/src/main/resources/org/ovirt/engine/ui/frontend/AppErrors.properties +++ b/frontend/webadmin/modules/userportal-gwtp/src/main/resources/org/ovirt/engine/ui/frontend/AppErrors.properties @@ -960,3 +960,10 @@ ACTION_TYPE_FAILED_POSITIVE_AFFINITY_GROUP=VM is associated with a positive Affinity Group (${affinityGroupName}) and require to run on the same Host (${hostName}) as the other group VMs ACTION_TYPE_FAILED_NEGATIVE_AFFINITY_GROUP=VM is associated with a negative Affinity Group and require to run on separate Host, which doesn't run other group VMs ACTION_TYPE_FAILED_MIX_POSITIVE_NEGATIVE_AFFINITY_GROUP=VM is associated with both positive and negative Affinity Groups, please contact your system administrator + +# Iscsi Bond +VALIDATION_ISCSI_BOND_NAME_MAX=iSCSI bond name must not exceed 50 characters +VALIDATION_ISCSI_BOND_NAME_NOT_NULL=iSCSI bond name is required +VALIDATION_ISCSI_BOND_DESCRIPTION_MAX=iSCSI bond description must not exceed 4000 characters +VALIDATION_ISCSI_BOND_NAME_INVALID_CHARACTER=iSCSI Bond name must be formed from alpha-numeric characters or "-_." +VALIDATION_SCSI_BOND_DESCRIPTION_INVALID=iSCSI Bond description must be formed only from alpha-numeric characters and special characters that conform to the standard ASCII character set. diff --git a/frontend/webadmin/modules/webadmin/src/main/resources/org/ovirt/engine/ui/frontend/AppErrors.properties b/frontend/webadmin/modules/webadmin/src/main/resources/org/ovirt/engine/ui/frontend/AppErrors.properties index fe488f2..5f628e0 100644 --- a/frontend/webadmin/modules/webadmin/src/main/resources/org/ovirt/engine/ui/frontend/AppErrors.properties +++ b/frontend/webadmin/modules/webadmin/src/main/resources/org/ovirt/engine/ui/frontend/AppErrors.properties @@ -1097,3 +1097,11 @@ ACTION_TYPE_FAILED_POSITIVE_AFFINITY_GROUP=VM is associated with a positive Affinity Group (${affinityGroupName}) and require to run on the same Host (${hostName}) as the other group VMs ACTION_TYPE_FAILED_NEGATIVE_AFFINITY_GROUP=VM is associated with a negative Affinity Group and require to run on separte Host, which doesn't run the other group VMs ACTION_TYPE_FAILED_MIX_POSITIVE_NEGATIVE_AFFINITY_GROUP=VM is associated with both positive and negative Affinity Groups, please reconfigure VM's affinity groups + +# Iscsi Bond +VALIDATION_ISCSI_BOND_NAME_MAX=iSCSI bond name must not exceed 50 characters +VALIDATION_ISCSI_BOND_NAME_NOT_NULL=iSCSI bond name is required +VALIDATION_ISCSI_BOND_DESCRIPTION_MAX=iSCSI bond description must not exceed 4000 characters +VALIDATION_ISCSI_BOND_NAME_INVALID_CHARACTER=iSCSI Bond name must be formed from alpha-numeric characters or "-_." +VALIDATION_SCSI_BOND_DESCRIPTION_INVALID=iSCSI Bond description must be formed only from alpha-numeric characters and special characters that conform to the standard ASCII character set. + diff --git a/packaging/dbscripts/iscsi_bonds_sp.sql b/packaging/dbscripts/iscsi_bonds_sp.sql new file mode 100644 index 0000000..5d34bd7 --- /dev/null +++ b/packaging/dbscripts/iscsi_bonds_sp.sql @@ -0,0 +1,129 @@ +---------------------------------------------------------------- +-- [iscsi_bonds] Table +-- + +Create or replace FUNCTION GetIscsiBondByIscsiBondId(v_id UUID) RETURNS SETOF iscsi_bonds STABLE + AS $procedure$ +BEGIN + RETURN QUERY SELECT iscsi_bonds.* + FROM iscsi_bonds + WHERE id = v_id; +END; $procedure$ +LANGUAGE plpgsql; + + +Create or replace FUNCTION GetAllFromIscsiBonds() RETURNS SETOF iscsi_bonds STABLE + AS $procedure$ +BEGIN + RETURN QUERY SELECT iscsi_bonds.* + FROM iscsi_bonds; +END; $procedure$ +LANGUAGE plpgsql; + + +Create or replace FUNCTION GetIscsiBondsByStoragePoolId(v_storage_pool_id UUID) RETURNS SETOF iscsi_bonds STABLE + AS $procedure$ +BEGIN + RETURN QUERY SELECT iscsi_bonds.* + FROM iscsi_bonds + WHERE storage_pool_id = v_storage_pool_id; +END; $procedure$ +LANGUAGE plpgsql; + + +Create or replace FUNCTION GetNetworksByIscsiBondId(v_iscsi_bond_id UUID) RETURNS SETOF UUID STABLE + AS $procedure$ +BEGIN + RETURN QUERY SELECT iscsi_bonds_networks_map.network_id + FROM iscsi_bonds_networks_map + WHERE iscsi_bond_id = v_iscsi_bond_id; +END; $procedure$ +LANGUAGE plpgsql; + + +Create or replace FUNCTION InsertIscsiBond(v_id UUID, + v_name VARCHAR(50), + v_description VARCHAR(4000), + v_storage_pool_id UUID) +RETURNS VOID + AS $procedure$ +BEGIN + INSERT INTO iscsi_bonds(id, name, description, storage_pool_id) + VALUES(v_id, v_name, v_description, v_storage_pool_id); +END; $procedure$ +LANGUAGE plpgsql; + + +Create or replace FUNCTION UpdateIscsiBond(v_id UUID, + v_name VARCHAR(50), + v_description VARCHAR(4000)) +RETURNS VOID + AS $procedure$ +BEGIN + UPDATE iscsi_bonds + SET name = v_name, description = v_description + WHERE id = v_id; +END; $procedure$ +LANGUAGE plpgsql; + + +Create or replace FUNCTION DeleteIscsiBond(v_id UUID) +RETURNS VOID + AS $procedure$ + DECLARE + v_val UUID; +BEGIN + DELETE FROM iscsi_bonds WHERE id = v_id; +END; $procedure$ +LANGUAGE plpgsql; + + +Create or replace FUNCTION AddNetworkToIscsiBond(v_iscsi_bond_id UUID, v_network_id UUID) +RETURNS VOID + AS $procedure$ +BEGIN + INSERT INTO iscsi_bonds_networks_map(iscsi_bond_id, network_id) + VALUES(v_iscsi_bond_id, v_network_id); +END; $procedure$ +LANGUAGE plpgsql; + + +Create or replace FUNCTION RemoveNetworkFromIscsiBond(v_iscsi_bond_id UUID, v_network_id UUID) +RETURNS VOID + AS $procedure$ +BEGIN + DELETE FROM iscsi_bonds_networks_map + WHERE iscsi_bond_id = v_iscsi_bond_id and network_id = v_network_id; +END; $procedure$ +LANGUAGE plpgsql; + + +Create or replace FUNCTION AddConnectionToIscsiBond(v_iscsi_bond_id UUID, v_connection_id VARCHAR(50)) +RETURNS VOID + AS $procedure$ +BEGIN + INSERT INTO iscsi_bonds_storage_connections_map(iscsi_bond_id, connection_id) + VALUES(v_iscsi_bond_id, v_connection_id); +END; $procedure$ +LANGUAGE plpgsql; + + +Create or replace FUNCTION RemoveConnectionFromIscsiBond(v_iscsi_bond_id UUID, v_connection_id VARCHAR(50)) +RETURNS VOID + AS $procedure$ +BEGIN + DELETE FROM iscsi_bonds_storage_connections_map + WHERE iscsi_bond_id = v_iscsi_bond_id and connection_id = v_connection_id; +END; $procedure$ +LANGUAGE plpgsql; + + +Create or replace FUNCTION GetConnectionsByIscsiBondId(v_iscsi_bond_id UUID) RETURNS SETOF VARCHAR(50) STABLE + AS $procedure$ +BEGIN + RETURN QUERY SELECT iscsi_bonds_storage_connections_map.connection_id + FROM iscsi_bonds_storage_connections_map + WHERE iscsi_bond_id = v_iscsi_bond_id; +END; $procedure$ +LANGUAGE plpgsql; + diff --git a/packaging/dbscripts/upgrade/03_04_0500_add_iscsi_bond.sql b/packaging/dbscripts/upgrade/03_04_0500_add_iscsi_bond.sql new file mode 100644 index 0000000..400d5b3 --- /dev/null +++ b/packaging/dbscripts/upgrade/03_04_0500_add_iscsi_bond.sql @@ -0,0 +1,34 @@ +CREATE TABLE iscsi_bonds +( + id UUID NOT NULL, + name varchar(50) NOT NULL, + description varchar(4000), + storage_pool_id UUID NOT NULL, + CONSTRAINT PK_iscsi_bonds PRIMARY KEY(id), + CONSTRAINT FK_iscsi_bonds_storage_pool FOREIGN KEY(storage_pool_id) + REFERENCES storage_pool(id) ON DELETE CASCADE +) WITH OIDS; + + +CREATE TABLE iscsi_bonds_networks_map +( + iscsi_bond_id UUID NOT NULL, + network_id UUID NOT NULL, + CONSTRAINT PK_iscsi_bonds_networks_map PRIMARY KEY(iscsi_bond_id,network_id), + CONSTRAINT FK_iscsi_bonds_networks_map_iscsi_bond_id FOREIGN KEY(iscsi_bond_id) + REFERENCES iscsi_bonds(id) ON DELETE CASCADE, + CONSTRAINT FK_iscsi_bonds_networks_map_network_id FOREIGN KEY(network_id) + REFERENCES network(id) ON DELETE CASCADE +) WITH OIDS; + + +CREATE TABLE iscsi_bonds_storage_connections_map +( + iscsi_bond_id UUID NOT NULL, + connection_id varchar(50) NOT NULL, + CONSTRAINT PK_iscsi_bonds_storage_connections_map PRIMARY KEY(iscsi_bond_id,connection_id), + CONSTRAINT FK_iscsi_bonds_storage_connections_map_iscsi_bond_id FOREIGN KEY(iscsi_bond_id) + REFERENCES iscsi_bonds(id) ON DELETE CASCADE, + CONSTRAINT FK_iscsi_bonds_storage_connections_map_connection_id FOREIGN KEY(connection_id) + REFERENCES storage_server_connections(id) ON DELETE CASCADE +) WITH OIDS; \ No newline at end of file -- To view, visit http://gerrit.ovirt.org/23539 To unsubscribe, visit http://gerrit.ovirt.org/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I12313c02810a2f0e75016bdd78b44da43f2154d4 Gerrit-PatchSet: 1 Gerrit-Project: ovirt-engine Gerrit-Branch: ovirt-engine-3.4 Gerrit-Owner: Sergey Gotliv <[email protected]> _______________________________________________ Engine-patches mailing list [email protected] http://lists.ovirt.org/mailman/listinfo/engine-patches
