Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id D3E10200BBB for ; Thu, 27 Oct 2016 08:20:01 +0200 (CEST) Received: by cust-asf.ponee.io (Postfix) id D25E0160AEE; Thu, 27 Oct 2016 06:20:01 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id D3A78160B04 for ; Thu, 27 Oct 2016 08:19:59 +0200 (CEST) Received: (qmail 62965 invoked by uid 500); 27 Oct 2016 06:19:58 -0000 Mailing-List: contact commits-help@cloudstack.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@cloudstack.apache.org Delivered-To: mailing list commits@cloudstack.apache.org Received: (qmail 62771 invoked by uid 99); 27 Oct 2016 06:19:58 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 27 Oct 2016 06:19:58 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 6EDE4E186F; Thu, 27 Oct 2016 06:19:58 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: rajani@apache.org To: commits@cloudstack.apache.org Date: Thu, 27 Oct 2016 06:19:58 -0000 Message-Id: <73c265835043482fa05f743fd7015f6f@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [1/2] git commit: updated refs/heads/master to c9e7ccf archived-at: Thu, 27 Oct 2016 06:20:02 -0000 Repository: cloudstack Updated Branches: refs/heads/master 33518257b -> c9e7ccf46 CLOUDSTACK-9438: Fix for CLOUDSTACK-9252 - Make NFS version changeable in UI Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/2e774966 Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/2e774966 Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/2e774966 Branch: refs/heads/master Commit: 2e77496601ab5420723ce8b955b3960faaba7d5c Parents: 3a82636 Author: nvazquez Authored: Tue Jul 12 11:41:52 2016 -0300 Committer: nvazquez Committed: Wed Sep 28 08:51:37 2016 -0700 ---------------------------------------------------------------------- .../api/command/admin/config/ListCfgsByCmd.java | 14 ++ .../api/command/admin/config/UpdateCfgCmd.java | 14 +- .../src/com/cloud/capacity/CapacityManager.java | 10 ++ .../spring-engine-schema-core-daos-context.xml | 4 +- .../storage/datastore/db/ImageStoreDaoImpl.java | 127 ++++++++++++++ .../datastore/db/ImageStoreDetailVO.java | 34 ++-- .../datastore/db/ImageStoreDetailsDao.java | 4 +- .../datastore/db/ImageStoreDetailsDaoImpl.java | 119 +++++++++++++ .../test/resource/fakeDriverTestContext.xml | 4 +- .../test/resources/storageContext.xml | 4 +- .../storage/image/NfsImageStoreDriverImpl.java | 11 +- .../image/datastore/ImageStoreHelper.java | 5 +- .../storage/image/db/ImageStoreDaoImpl.java | 129 -------------- .../image/db/ImageStoreDetailsDaoImpl.java | 94 ---------- .../cloudstack/framework/config/ConfigKey.java | 2 +- .../framework/config/impl/ConfigDepotImpl.java | 1 + .../IntegrationTestConfiguration.java | 2 +- .../com/cloud/capacity/CapacityManagerImpl.java | 2 +- .../configuration/ConfigurationManagerImpl.java | 21 +++ .../com/cloud/server/ManagementServerImpl.java | 6 + .../cloud/storage/ImageStoreDetailsUtil.java | 48 +++-- .../storage/ImageStoreDetailsUtilTest.java | 30 +++- .../networkoffering/ChildTestConfiguration.java | 4 +- setup/db/db/schema-481to490.sql | 3 + test/integration/smoke/test_ssvm.py | 174 ++++++++++++++++++- ui/scripts/system.js | 72 +++++--- 26 files changed, 631 insertions(+), 307 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2e774966/api/src/org/apache/cloudstack/api/command/admin/config/ListCfgsByCmd.java ---------------------------------------------------------------------- diff --git a/api/src/org/apache/cloudstack/api/command/admin/config/ListCfgsByCmd.java b/api/src/org/apache/cloudstack/api/command/admin/config/ListCfgsByCmd.java index a34bc3e..8f71f48 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/config/ListCfgsByCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/config/ListCfgsByCmd.java @@ -28,6 +28,7 @@ import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.response.AccountResponse; import org.apache.cloudstack.api.response.ClusterResponse; import org.apache.cloudstack.api.response.ConfigurationResponse; +import org.apache.cloudstack.api.response.ImageStoreResponse; import org.apache.cloudstack.api.response.ListResponse; import org.apache.cloudstack.api.response.StoragePoolResponse; import org.apache.cloudstack.api.response.ZoneResponse; @@ -76,6 +77,12 @@ public class ListCfgsByCmd extends BaseListCmd { description = "the ID of the Account to update the parameter value for corresponding account") private Long accountId; + @Parameter(name = ApiConstants.IMAGE_STORE_UUID, + type = CommandType.UUID, + entityType = ImageStoreResponse.class, + description = "the ID of the Image Store to update the parameter value for corresponding image store") + private Long imageStoreId; + // /////////////////////////////////////////////////// // ///////////////// Accessors /////////////////////// // /////////////////////////////////////////////////// @@ -104,6 +111,10 @@ public class ListCfgsByCmd extends BaseListCmd { return accountId; } + public Long getImageStoreId() { + return imageStoreId; + } + @Override public Long getPageSizeVal() { Long defaultPageSize = 500L; @@ -147,6 +158,9 @@ public class ListCfgsByCmd extends BaseListCmd { if (getAccountId() != null) { cfgResponse.setScope("account"); } + if (getImageStoreId() != null){ + cfgResponse.setScope("imagestore"); + } configResponses.add(cfgResponse); } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2e774966/api/src/org/apache/cloudstack/api/command/admin/config/UpdateCfgCmd.java ---------------------------------------------------------------------- diff --git a/api/src/org/apache/cloudstack/api/command/admin/config/UpdateCfgCmd.java b/api/src/org/apache/cloudstack/api/command/admin/config/UpdateCfgCmd.java index 45f790f..fa5e26e 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/config/UpdateCfgCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/config/UpdateCfgCmd.java @@ -19,8 +19,8 @@ package org.apache.cloudstack.api.command.admin.config; import com.google.common.base.Strings; import org.apache.cloudstack.acl.RoleService; import org.apache.log4j.Logger; - import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiArgValidator; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; import org.apache.cloudstack.api.BaseCmd; @@ -29,6 +29,7 @@ import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.response.AccountResponse; import org.apache.cloudstack.api.response.ClusterResponse; import org.apache.cloudstack.api.response.ConfigurationResponse; +import org.apache.cloudstack.api.response.ImageStoreResponse; import org.apache.cloudstack.api.response.StoragePoolResponse; import org.apache.cloudstack.api.response.ZoneResponse; import org.apache.cloudstack.config.Configuration; @@ -75,6 +76,13 @@ public class UpdateCfgCmd extends BaseCmd { description = "the ID of the Account to update the parameter value for corresponding account") private Long accountId; + @Parameter(name = ApiConstants.IMAGE_STORE_UUID, + type = CommandType.UUID, + entityType = ImageStoreResponse.class, + description = "the ID of the Image Store to update the parameter value for corresponding image store", + validations = ApiArgValidator.PositiveNumber) + private Long imageStoreId; + ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -107,6 +115,10 @@ public class UpdateCfgCmd extends BaseCmd { return accountId; } + public Long getImageStoreId() { + return imageStoreId; + } + ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2e774966/engine/components-api/src/com/cloud/capacity/CapacityManager.java ---------------------------------------------------------------------- diff --git a/engine/components-api/src/com/cloud/capacity/CapacityManager.java b/engine/components-api/src/com/cloud/capacity/CapacityManager.java index d190d78..98287bb 100644 --- a/engine/components-api/src/com/cloud/capacity/CapacityManager.java +++ b/engine/components-api/src/com/cloud/capacity/CapacityManager.java @@ -73,6 +73,16 @@ public interface CapacityManager { "If set to true, creates VMs as full clones on ESX hypervisor", true, ConfigKey.Scope.StoragePool); + static final ConfigKey ImageStoreNFSVersion = + new ConfigKey( + Integer.class, + "secstorage.nfs.version", + "Advanced", + null, + "Enforces specific NFS version when mounting Secondary Storage. If NULL default selection is performed", + true, + ConfigKey.Scope.ImageStore, + null); public boolean releaseVmCapacity(VirtualMachine vm, boolean moveFromReserved, boolean moveToReservered, Long hostId); http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2e774966/engine/schema/resources/META-INF/cloudstack/core/spring-engine-schema-core-daos-context.xml ---------------------------------------------------------------------- diff --git a/engine/schema/resources/META-INF/cloudstack/core/spring-engine-schema-core-daos-context.xml b/engine/schema/resources/META-INF/cloudstack/core/spring-engine-schema-core-daos-context.xml index 6916478..884bb30 100644 --- a/engine/schema/resources/META-INF/cloudstack/core/spring-engine-schema-core-daos-context.xml +++ b/engine/schema/resources/META-INF/cloudstack/core/spring-engine-schema-core-daos-context.xml @@ -176,8 +176,8 @@ - - + + http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2e774966/engine/schema/src/org/apache/cloudstack/storage/datastore/db/ImageStoreDaoImpl.java ---------------------------------------------------------------------- diff --git a/engine/schema/src/org/apache/cloudstack/storage/datastore/db/ImageStoreDaoImpl.java b/engine/schema/src/org/apache/cloudstack/storage/datastore/db/ImageStoreDaoImpl.java new file mode 100644 index 0000000..9d53262 --- /dev/null +++ b/engine/schema/src/org/apache/cloudstack/storage/datastore/db/ImageStoreDaoImpl.java @@ -0,0 +1,127 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cloudstack.storage.datastore.db; + +import java.util.List; +import java.util.Map; + +import javax.naming.ConfigurationException; + +import org.springframework.stereotype.Component; + +import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope; + +import com.cloud.storage.DataStoreRole; +import com.cloud.storage.ScopeType; +import com.cloud.utils.db.GenericDaoBase; +import com.cloud.utils.db.SearchBuilder; +import com.cloud.utils.db.SearchCriteria; + +@Component +public class ImageStoreDaoImpl extends GenericDaoBase implements ImageStoreDao { + private SearchBuilder nameSearch; + private SearchBuilder providerSearch; + private SearchBuilder regionSearch; + + @Override + public boolean configure(String name, Map params) throws ConfigurationException { + super.configure(name, params); + + nameSearch = createSearchBuilder(); + nameSearch.and("name", nameSearch.entity().getName(), SearchCriteria.Op.EQ); + nameSearch.and("role", nameSearch.entity().getRole(), SearchCriteria.Op.EQ); + nameSearch.done(); + + providerSearch = createSearchBuilder(); + providerSearch.and("providerName", providerSearch.entity().getProviderName(), SearchCriteria.Op.EQ); + providerSearch.and("role", providerSearch.entity().getRole(), SearchCriteria.Op.EQ); + providerSearch.done(); + + regionSearch = createSearchBuilder(); + regionSearch.and("scope", regionSearch.entity().getScope(), SearchCriteria.Op.EQ); + regionSearch.and("role", regionSearch.entity().getRole(), SearchCriteria.Op.EQ); + regionSearch.done(); + + return true; + } + + @Override + public ImageStoreVO findByName(String name) { + SearchCriteria sc = nameSearch.create(); + sc.setParameters("name", name); + return findOneBy(sc); + } + + @Override + public List findByProvider(String provider) { + SearchCriteria sc = providerSearch.create(); + sc.setParameters("providerName", provider); + sc.setParameters("role", DataStoreRole.Image); + return listBy(sc); + } + + @Override + public List findByScope(ZoneScope scope) { + SearchCriteria sc = createSearchCriteria(); + sc.addAnd("role", SearchCriteria.Op.EQ, DataStoreRole.Image); + if (scope.getScopeId() != null) { + SearchCriteria scc = createSearchCriteria(); + scc.addOr("scope", SearchCriteria.Op.EQ, ScopeType.REGION); + scc.addOr("dcId", SearchCriteria.Op.EQ, scope.getScopeId()); + sc.addAnd("scope", SearchCriteria.Op.SC, scc); + } + // we should return all image stores if cross-zone scope is passed + // (scopeId = null) + return listBy(sc); + } + + @Override + public List findRegionImageStores() { + SearchCriteria sc = regionSearch.create(); + sc.setParameters("scope", ScopeType.REGION); + sc.setParameters("role", DataStoreRole.Image); + return listBy(sc); + } + + @Override + public List findImageCacheByScope(ZoneScope scope) { + SearchCriteria sc = createSearchCriteria(); + sc.addAnd("role", SearchCriteria.Op.EQ, DataStoreRole.ImageCache); + if (scope.getScopeId() != null) { + sc.addAnd("scope", SearchCriteria.Op.EQ, ScopeType.ZONE); + sc.addAnd("dcId", SearchCriteria.Op.EQ, scope.getScopeId()); + } + return listBy(sc); + } + + @Override + public List listImageStores() { + SearchCriteria sc = createSearchCriteria(); + sc.addAnd("role", SearchCriteria.Op.EQ, DataStoreRole.Image); + return listBy(sc); + } + + @Override + public List listImageCacheStores() { + SearchCriteria sc = createSearchCriteria(); + sc.addAnd("role", SearchCriteria.Op.EQ, DataStoreRole.ImageCache); + return listBy(sc); + } + +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2e774966/engine/schema/src/org/apache/cloudstack/storage/datastore/db/ImageStoreDetailVO.java ---------------------------------------------------------------------- diff --git a/engine/schema/src/org/apache/cloudstack/storage/datastore/db/ImageStoreDetailVO.java b/engine/schema/src/org/apache/cloudstack/storage/datastore/db/ImageStoreDetailVO.java index 6601437..fdfb734 100644 --- a/engine/schema/src/org/apache/cloudstack/storage/datastore/db/ImageStoreDetailVO.java +++ b/engine/schema/src/org/apache/cloudstack/storage/datastore/db/ImageStoreDetailVO.java @@ -23,18 +23,18 @@ import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; -import org.apache.cloudstack.api.InternalIdentity; +import org.apache.cloudstack.api.ResourceDetail; @Entity @Table(name = "image_store_details") -public class ImageStoreDetailVO implements InternalIdentity { +public class ImageStoreDetailVO implements ResourceDetail { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id") long id; @Column(name = "store_id") - long storeId; + long resourceId; @Column(name = "name") String name; @@ -42,13 +42,17 @@ public class ImageStoreDetailVO implements InternalIdentity { @Column(name = "value") String value; + @Column(name = "display") + private boolean display = true; + public ImageStoreDetailVO() { } - public ImageStoreDetailVO(long storeId, String name, String value) { - this.storeId = storeId; + public ImageStoreDetailVO(long storeId, String name, String value, boolean display) { + this.resourceId = storeId; this.name = name; this.value = value; + this.display = display; } @Override @@ -56,28 +60,24 @@ public class ImageStoreDetailVO implements InternalIdentity { return id; } - public long getStoreId() { - return storeId; - } - - public void setStoreId(long storeId) { - this.storeId = storeId; + @Override + public long getResourceId() { + return resourceId; } + @Override public String getName() { return name; } - public void setName(String name) { - this.name = name; - } - + @Override public String getValue() { return value; } - public void setValue(String value) { - this.value = value; + @Override + public boolean isDisplay() { + return display; } } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2e774966/engine/schema/src/org/apache/cloudstack/storage/datastore/db/ImageStoreDetailsDao.java ---------------------------------------------------------------------- diff --git a/engine/schema/src/org/apache/cloudstack/storage/datastore/db/ImageStoreDetailsDao.java b/engine/schema/src/org/apache/cloudstack/storage/datastore/db/ImageStoreDetailsDao.java index 91fff28..04cd703 100644 --- a/engine/schema/src/org/apache/cloudstack/storage/datastore/db/ImageStoreDetailsDao.java +++ b/engine/schema/src/org/apache/cloudstack/storage/datastore/db/ImageStoreDetailsDao.java @@ -18,9 +18,11 @@ package org.apache.cloudstack.storage.datastore.db; import java.util.Map; +import org.apache.cloudstack.resourcedetail.ResourceDetailsDao; + import com.cloud.utils.db.GenericDao; -public interface ImageStoreDetailsDao extends GenericDao { +public interface ImageStoreDetailsDao extends GenericDao, ResourceDetailsDao { void update(long storeId, Map details); http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2e774966/engine/schema/src/org/apache/cloudstack/storage/datastore/db/ImageStoreDetailsDaoImpl.java ---------------------------------------------------------------------- diff --git a/engine/schema/src/org/apache/cloudstack/storage/datastore/db/ImageStoreDetailsDaoImpl.java b/engine/schema/src/org/apache/cloudstack/storage/datastore/db/ImageStoreDetailsDaoImpl.java new file mode 100644 index 0000000..8e5ce77 --- /dev/null +++ b/engine/schema/src/org/apache/cloudstack/storage/datastore/db/ImageStoreDetailsDaoImpl.java @@ -0,0 +1,119 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.storage.datastore.db; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.springframework.stereotype.Component; + +import com.cloud.utils.crypt.DBEncryptionUtil; +import com.cloud.utils.db.QueryBuilder; +import com.cloud.utils.db.SearchBuilder; +import com.cloud.utils.db.SearchCriteria; +import com.cloud.utils.db.SearchCriteria.Op; +import com.cloud.utils.db.TransactionLegacy; + +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.framework.config.ConfigKey; +import org.apache.cloudstack.framework.config.ConfigKey.Scope; +import org.apache.cloudstack.framework.config.ScopedConfigStorage; +import org.apache.cloudstack.resourcedetail.ResourceDetailsDaoBase; + +@Component +public class ImageStoreDetailsDaoImpl extends ResourceDetailsDaoBase implements ImageStoreDetailsDao, ScopedConfigStorage { + + protected final SearchBuilder storeSearch; + + public ImageStoreDetailsDaoImpl() { + super(); + storeSearch = createSearchBuilder(); + storeSearch.and("store", storeSearch.entity().getResourceId(), SearchCriteria.Op.EQ); + storeSearch.done(); + } + + @Override + public void update(long storeId, Map details) { + TransactionLegacy txn = TransactionLegacy.currentTxn(); + SearchCriteria sc = storeSearch.create(); + sc.setParameters("store", storeId); + + txn.start(); + expunge(sc); + for (Map.Entry entry : details.entrySet()) { + ImageStoreDetailVO detail = new ImageStoreDetailVO(storeId, entry.getKey(), entry.getValue(), true); + persist(detail); + } + txn.commit(); + } + + @Override + public Map getDetails(long storeId) { + SearchCriteria sc = storeSearch.create(); + sc.setParameters("store", storeId); + + List details = listBy(sc); + Map detailsMap = new HashMap(); + for (ImageStoreDetailVO detail : details) { + String name = detail.getName(); + String value = detail.getValue(); + if (name.equals(ApiConstants.KEY) || name.equals(ApiConstants.S3_SECRET_KEY)) { + value = DBEncryptionUtil.decrypt(value); + } + detailsMap.put(name, value); + } + + return detailsMap; + } + + @Override + public void deleteDetails(long storeId) { + SearchCriteria sc = storeSearch.create(); + sc.setParameters("store", storeId); + + List results = search(sc, null); + for (ImageStoreDetailVO result : results) { + remove(result.getId()); + } + } + + @Override + public Scope getScope() { + return ConfigKey.Scope.ImageStore; + } + + @Override + public ImageStoreDetailVO findDetail(long storeId, String name) { + QueryBuilder sc = QueryBuilder.create(ImageStoreDetailVO.class); + sc.and(sc.entity().getResourceId(), Op.EQ, storeId); + sc.and(sc.entity().getName(), Op.EQ, name); + return sc.find(); + } + + @Override + public String getConfigValue(long id, ConfigKey key) { + ImageStoreDetailVO vo = findDetail(id, key.key()); + return vo == null ? null : vo.getValue(); + } + + @Override + public void addDetail(long resourceId, String key, String value, boolean display) { + super.addDetail(new ImageStoreDetailVO(resourceId, key, value, display)); + } + +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2e774966/engine/storage/integration-test/test/resource/fakeDriverTestContext.xml ---------------------------------------------------------------------- diff --git a/engine/storage/integration-test/test/resource/fakeDriverTestContext.xml b/engine/storage/integration-test/test/resource/fakeDriverTestContext.xml index b7ef363..c785f53 100644 --- a/engine/storage/integration-test/test/resource/fakeDriverTestContext.xml +++ b/engine/storage/integration-test/test/resource/fakeDriverTestContext.xml @@ -35,8 +35,8 @@ - - + + http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2e774966/engine/storage/integration-test/test/resources/storageContext.xml ---------------------------------------------------------------------- diff --git a/engine/storage/integration-test/test/resources/storageContext.xml b/engine/storage/integration-test/test/resources/storageContext.xml index c984515..667328f 100644 --- a/engine/storage/integration-test/test/resources/storageContext.xml +++ b/engine/storage/integration-test/test/resources/storageContext.xml @@ -35,8 +35,8 @@ - - + + http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2e774966/engine/storage/src/org/apache/cloudstack/storage/image/NfsImageStoreDriverImpl.java ---------------------------------------------------------------------- diff --git a/engine/storage/src/org/apache/cloudstack/storage/image/NfsImageStoreDriverImpl.java b/engine/storage/src/org/apache/cloudstack/storage/image/NfsImageStoreDriverImpl.java index 28d9d46..c7aad89 100755 --- a/engine/storage/src/org/apache/cloudstack/storage/image/NfsImageStoreDriverImpl.java +++ b/engine/storage/src/org/apache/cloudstack/storage/image/NfsImageStoreDriverImpl.java @@ -24,22 +24,23 @@ import javax.inject.Inject; import org.apache.cloudstack.storage.datastore.db.ImageStoreDetailsDao; +import com.cloud.capacity.CapacityManager; + public abstract class NfsImageStoreDriverImpl extends BaseImageStoreDriverImpl { @Inject ImageStoreDetailsDao _imageStoreDetailsDao; - private static final String NFS_VERSION_DETAILS_KEY = "nfs.version"; - /** * Retrieve NFS version to be used for imgStoreId store, if provided in image_store_details table * @param imgStoreId store id - * @return "nfs.version" associated value for imgStoreId in image_store_details table if exists, null if not + * @return "secstorage.nfs.version" associated value for imgStoreId in image_store_details table if exists, null if not */ protected Integer getNfsVersion(long imgStoreId){ Map imgStoreDetails = _imageStoreDetailsDao.getDetails(imgStoreId); - if (imgStoreDetails != null && imgStoreDetails.containsKey(NFS_VERSION_DETAILS_KEY)){ - String nfsVersionParam = imgStoreDetails.get(NFS_VERSION_DETAILS_KEY); + String nfsVersionKey = CapacityManager.ImageStoreNFSVersion.key(); + if (imgStoreDetails != null && imgStoreDetails.containsKey(nfsVersionKey)){ + String nfsVersionParam = imgStoreDetails.get(nfsVersionKey); return (nfsVersionParam != null ? Integer.valueOf(nfsVersionParam) : null); } return null; http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2e774966/engine/storage/src/org/apache/cloudstack/storage/image/datastore/ImageStoreHelper.java ---------------------------------------------------------------------- diff --git a/engine/storage/src/org/apache/cloudstack/storage/image/datastore/ImageStoreHelper.java b/engine/storage/src/org/apache/cloudstack/storage/image/datastore/ImageStoreHelper.java index 5e29f71..dbb606b 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/image/datastore/ImageStoreHelper.java +++ b/engine/storage/src/org/apache/cloudstack/storage/image/datastore/ImageStoreHelper.java @@ -129,15 +129,12 @@ public class ImageStoreHelper { Iterator keyIter = details.keySet().iterator(); while (keyIter.hasNext()) { String key = keyIter.next().toString(); - ImageStoreDetailVO detail = new ImageStoreDetailVO(); - detail.setStoreId(store.getId()); - detail.setName(key); String value = details.get(key); // encrypt swift key or s3 secret key if (key.equals(ApiConstants.KEY) || key.equals(ApiConstants.S3_SECRET_KEY)) { value = DBEncryptionUtil.encrypt(value); } - detail.setValue(value); + ImageStoreDetailVO detail = new ImageStoreDetailVO(store.getId(), key, value, true); imageStoreDetailsDao.persist(detail); } } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2e774966/engine/storage/src/org/apache/cloudstack/storage/image/db/ImageStoreDaoImpl.java ---------------------------------------------------------------------- diff --git a/engine/storage/src/org/apache/cloudstack/storage/image/db/ImageStoreDaoImpl.java b/engine/storage/src/org/apache/cloudstack/storage/image/db/ImageStoreDaoImpl.java deleted file mode 100644 index 13a7f47..0000000 --- a/engine/storage/src/org/apache/cloudstack/storage/image/db/ImageStoreDaoImpl.java +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.cloudstack.storage.image.db; - -import java.util.List; -import java.util.Map; - -import javax.naming.ConfigurationException; - -import org.springframework.stereotype.Component; - -import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope; -import org.apache.cloudstack.storage.datastore.db.ImageStoreDao; -import org.apache.cloudstack.storage.datastore.db.ImageStoreVO; - -import com.cloud.storage.DataStoreRole; -import com.cloud.storage.ScopeType; -import com.cloud.utils.db.GenericDaoBase; -import com.cloud.utils.db.SearchBuilder; -import com.cloud.utils.db.SearchCriteria; - -@Component -public class ImageStoreDaoImpl extends GenericDaoBase implements ImageStoreDao { - private SearchBuilder nameSearch; - private SearchBuilder providerSearch; - private SearchBuilder regionSearch; - - @Override - public boolean configure(String name, Map params) throws ConfigurationException { - super.configure(name, params); - - nameSearch = createSearchBuilder(); - nameSearch.and("name", nameSearch.entity().getName(), SearchCriteria.Op.EQ); - nameSearch.and("role", nameSearch.entity().getRole(), SearchCriteria.Op.EQ); - nameSearch.done(); - - providerSearch = createSearchBuilder(); - providerSearch.and("providerName", providerSearch.entity().getProviderName(), SearchCriteria.Op.EQ); - providerSearch.and("role", providerSearch.entity().getRole(), SearchCriteria.Op.EQ); - providerSearch.done(); - - regionSearch = createSearchBuilder(); - regionSearch.and("scope", regionSearch.entity().getScope(), SearchCriteria.Op.EQ); - regionSearch.and("role", regionSearch.entity().getRole(), SearchCriteria.Op.EQ); - regionSearch.done(); - - return true; - } - - @Override - public ImageStoreVO findByName(String name) { - SearchCriteria sc = nameSearch.create(); - sc.setParameters("name", name); - return findOneBy(sc); - } - - @Override - public List findByProvider(String provider) { - SearchCriteria sc = providerSearch.create(); - sc.setParameters("providerName", provider); - sc.setParameters("role", DataStoreRole.Image); - return listBy(sc); - } - - @Override - public List findByScope(ZoneScope scope) { - SearchCriteria sc = createSearchCriteria(); - sc.addAnd("role", SearchCriteria.Op.EQ, DataStoreRole.Image); - if (scope.getScopeId() != null) { - SearchCriteria scc = createSearchCriteria(); - scc.addOr("scope", SearchCriteria.Op.EQ, ScopeType.REGION); - scc.addOr("dcId", SearchCriteria.Op.EQ, scope.getScopeId()); - sc.addAnd("scope", SearchCriteria.Op.SC, scc); - } - // we should return all image stores if cross-zone scope is passed - // (scopeId = null) - return listBy(sc); - } - - @Override - public List findRegionImageStores() { - SearchCriteria sc = regionSearch.create(); - sc.setParameters("scope", ScopeType.REGION); - sc.setParameters("role", DataStoreRole.Image); - return listBy(sc); - } - - @Override - public List findImageCacheByScope(ZoneScope scope) { - SearchCriteria sc = createSearchCriteria(); - sc.addAnd("role", SearchCriteria.Op.EQ, DataStoreRole.ImageCache); - if (scope.getScopeId() != null) { - sc.addAnd("scope", SearchCriteria.Op.EQ, ScopeType.ZONE); - sc.addAnd("dcId", SearchCriteria.Op.EQ, scope.getScopeId()); - } - return listBy(sc); - } - - @Override - public List listImageStores() { - SearchCriteria sc = createSearchCriteria(); - sc.addAnd("role", SearchCriteria.Op.EQ, DataStoreRole.Image); - return listBy(sc); - } - - @Override - public List listImageCacheStores() { - SearchCriteria sc = createSearchCriteria(); - sc.addAnd("role", SearchCriteria.Op.EQ, DataStoreRole.ImageCache); - return listBy(sc); - } - -} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2e774966/engine/storage/src/org/apache/cloudstack/storage/image/db/ImageStoreDetailsDaoImpl.java ---------------------------------------------------------------------- diff --git a/engine/storage/src/org/apache/cloudstack/storage/image/db/ImageStoreDetailsDaoImpl.java b/engine/storage/src/org/apache/cloudstack/storage/image/db/ImageStoreDetailsDaoImpl.java deleted file mode 100644 index 2bfc38e..0000000 --- a/engine/storage/src/org/apache/cloudstack/storage/image/db/ImageStoreDetailsDaoImpl.java +++ /dev/null @@ -1,94 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. -package org.apache.cloudstack.storage.image.db; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - - -import org.springframework.stereotype.Component; - -import org.apache.cloudstack.api.ApiConstants; -import org.apache.cloudstack.storage.datastore.db.ImageStoreDetailVO; -import org.apache.cloudstack.storage.datastore.db.ImageStoreDetailsDao; - -import com.cloud.utils.crypt.DBEncryptionUtil; -import com.cloud.utils.db.GenericDaoBase; -import com.cloud.utils.db.SearchBuilder; -import com.cloud.utils.db.SearchCriteria; -import com.cloud.utils.db.TransactionLegacy; - -@Component -public class ImageStoreDetailsDaoImpl extends GenericDaoBase implements ImageStoreDetailsDao { - - protected final SearchBuilder storeSearch; - - protected ImageStoreDetailsDaoImpl() { - super(); - storeSearch = createSearchBuilder(); - storeSearch.and("store", storeSearch.entity().getStoreId(), SearchCriteria.Op.EQ); - storeSearch.done(); - } - - @Override - public void update(long storeId, Map details) { - TransactionLegacy txn = TransactionLegacy.currentTxn(); - SearchCriteria sc = storeSearch.create(); - sc.setParameters("store", storeId); - - txn.start(); - expunge(sc); - for (Map.Entry entry : details.entrySet()) { - ImageStoreDetailVO detail = new ImageStoreDetailVO(storeId, entry.getKey(), entry.getValue()); - persist(detail); - } - txn.commit(); - } - - @Override - public Map getDetails(long storeId) { - SearchCriteria sc = storeSearch.create(); - sc.setParameters("store", storeId); - - List details = listBy(sc); - Map detailsMap = new HashMap(); - for (ImageStoreDetailVO detail : details) { - String name = detail.getName(); - String value = detail.getValue(); - if (name.equals(ApiConstants.KEY) || name.equals(ApiConstants.S3_SECRET_KEY)) { - value = DBEncryptionUtil.decrypt(value); - } - detailsMap.put(name, value); - } - - return detailsMap; - } - - @Override - public void deleteDetails(long storeId) { - SearchCriteria sc = storeSearch.create(); - sc.setParameters("store", storeId); - - List results = search(sc, null); - for (ImageStoreDetailVO result : results) { - remove(result.getId()); - } - - } - -} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2e774966/framework/config/src/org/apache/cloudstack/framework/config/ConfigKey.java ---------------------------------------------------------------------- diff --git a/framework/config/src/org/apache/cloudstack/framework/config/ConfigKey.java b/framework/config/src/org/apache/cloudstack/framework/config/ConfigKey.java index 09e143e..4a41306 100644 --- a/framework/config/src/org/apache/cloudstack/framework/config/ConfigKey.java +++ b/framework/config/src/org/apache/cloudstack/framework/config/ConfigKey.java @@ -31,7 +31,7 @@ import com.cloud.utils.exception.CloudRuntimeException; public class ConfigKey { public static enum Scope { - Global, Zone, Cluster, StoragePool, Account, ManagementServer + Global, Zone, Cluster, StoragePool, Account, ManagementServer, ImageStore } private final String _category; http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2e774966/framework/config/src/org/apache/cloudstack/framework/config/impl/ConfigDepotImpl.java ---------------------------------------------------------------------- diff --git a/framework/config/src/org/apache/cloudstack/framework/config/impl/ConfigDepotImpl.java b/framework/config/src/org/apache/cloudstack/framework/config/impl/ConfigDepotImpl.java index 4631bb9..e68fd3c 100644 --- a/framework/config/src/org/apache/cloudstack/framework/config/impl/ConfigDepotImpl.java +++ b/framework/config/src/org/apache/cloudstack/framework/config/impl/ConfigDepotImpl.java @@ -84,6 +84,7 @@ public class ConfigDepotImpl implements ConfigDepot, ConfigDepotAdmin { _scopeLevelConfigsMap.put(ConfigKey.Scope.Cluster, new HashSet>()); _scopeLevelConfigsMap.put(ConfigKey.Scope.StoragePool, new HashSet>()); _scopeLevelConfigsMap.put(ConfigKey.Scope.Account, new HashSet>()); + _scopeLevelConfigsMap.put(ConfigKey.Scope.ImageStore, new HashSet>()); } @Override http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2e774966/plugins/network-elements/juniper-contrail/test/org/apache/cloudstack/network/contrail/management/IntegrationTestConfiguration.java ---------------------------------------------------------------------- diff --git a/plugins/network-elements/juniper-contrail/test/org/apache/cloudstack/network/contrail/management/IntegrationTestConfiguration.java b/plugins/network-elements/juniper-contrail/test/org/apache/cloudstack/network/contrail/management/IntegrationTestConfiguration.java index 77abb65..7f1d5b8 100644 --- a/plugins/network-elements/juniper-contrail/test/org/apache/cloudstack/network/contrail/management/IntegrationTestConfiguration.java +++ b/plugins/network-elements/juniper-contrail/test/org/apache/cloudstack/network/contrail/management/IntegrationTestConfiguration.java @@ -80,8 +80,8 @@ import org.apache.cloudstack.region.dao.RegionDaoImpl; import org.apache.cloudstack.spring.lifecycle.registry.ExtensionRegistry; import org.apache.cloudstack.storage.datastore.PrimaryDataStoreProviderManager; import org.apache.cloudstack.storage.image.datastore.ImageStoreProviderManager; +import org.apache.cloudstack.storage.datastore.db.ImageStoreDaoImpl; import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDaoImpl; -import org.apache.cloudstack.storage.image.db.ImageStoreDaoImpl; import org.apache.cloudstack.storage.image.db.TemplateDataStoreDaoImpl; import org.apache.cloudstack.usage.UsageService; http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2e774966/server/src/com/cloud/capacity/CapacityManagerImpl.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/capacity/CapacityManagerImpl.java b/server/src/com/cloud/capacity/CapacityManagerImpl.java index a3d2c3f..caf91a9 100644 --- a/server/src/com/cloud/capacity/CapacityManagerImpl.java +++ b/server/src/com/cloud/capacity/CapacityManagerImpl.java @@ -1101,6 +1101,6 @@ public class CapacityManagerImpl extends ManagerBase implements CapacityManager, @Override public ConfigKey[] getConfigKeys() { return new ConfigKey[] {CpuOverprovisioningFactor, MemOverprovisioningFactor, StorageCapacityDisableThreshold, StorageOverprovisioningFactor, - StorageAllocatedCapacityDisableThreshold, StorageOperationsExcludeCluster, VmwareCreateCloneFull}; + StorageAllocatedCapacityDisableThreshold, StorageOperationsExcludeCluster, VmwareCreateCloneFull, ImageStoreNFSVersion}; } } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2e774966/server/src/com/cloud/configuration/ConfigurationManagerImpl.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java index 2dd590c..06d8726 100644 --- a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java +++ b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java @@ -81,6 +81,9 @@ import org.apache.cloudstack.region.PortableIpVO; import org.apache.cloudstack.region.Region; import org.apache.cloudstack.region.RegionVO; import org.apache.cloudstack.region.dao.RegionDao; +import org.apache.cloudstack.storage.datastore.db.ImageStoreDao; +import org.apache.cloudstack.storage.datastore.db.ImageStoreDetailsDao; +import org.apache.cloudstack.storage.datastore.db.ImageStoreVO; import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; import org.apache.cloudstack.storage.datastore.db.StoragePoolDetailsDao; import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; @@ -216,6 +219,7 @@ import com.cloud.vm.dao.NicIpAliasDao; import com.cloud.vm.dao.NicIpAliasVO; import com.cloud.vm.dao.NicSecondaryIpDao; import com.cloud.vm.dao.VMInstanceDao; +import com.google.common.base.Preconditions; public class ConfigurationManagerImpl extends ManagerBase implements ConfigurationManager, ConfigurationService, Configurable { public static final Logger s_logger = Logger.getLogger(ConfigurationManagerImpl.class); @@ -335,6 +339,10 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati AffinityGroupService _affinityGroupService; @Inject StorageManager _storageManager; + @Inject + ImageStoreDao _imageStoreDao; + @Inject + ImageStoreDetailsDao _imageStoreDetailsDao; // FIXME - why don't we have interface for DataCenterLinkLocalIpAddressDao? @Inject @@ -520,6 +528,13 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati _accountDetailsDao.update(accountDetailVO.getId(), accountDetailVO); } break; + + case ImageStore: + final ImageStoreVO imgStore = _imageStoreDao.findById(resourceId); + Preconditions.checkState(imgStore != null); + _imageStoreDetailsDao.addDetail(resourceId, name, value, true); + break; + default: throw new InvalidParameterValueException("Scope provided is invalid"); } @@ -626,6 +641,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati final Long clusterId = cmd.getClusterId(); final Long storagepoolId = cmd.getStoragepoolId(); final Long accountId = cmd.getAccountId(); + final Long imageStoreId = cmd.getImageStoreId(); CallContext.current().setEventDetails(" Name: " + name + " New Value: " + (name.toLowerCase().contains("password") ? "*****" : value == null ? "" : value)); // check if config value exists final ConfigurationVO config = _configDao.findByName(name); @@ -676,6 +692,11 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati id = storagepoolId; paramCountCheck++; } + if (imageStoreId != null) { + scope = ConfigKey.Scope.ImageStore.toString(); + id = imageStoreId; + paramCountCheck++; + } if (paramCountCheck > 1) { throw new InvalidParameterValueException("cannot handle multiple IDs, provide only one ID corresponding to the scope"); http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2e774966/server/src/com/cloud/server/ManagementServerImpl.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java index 82f8030..b6a2637 100644 --- a/server/src/com/cloud/server/ManagementServerImpl.java +++ b/server/src/com/cloud/server/ManagementServerImpl.java @@ -1672,6 +1672,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe final Long clusterId = cmd.getClusterId(); final Long storagepoolId = cmd.getStoragepoolId(); final Long accountId = cmd.getAccountId(); + final Long imageStoreId = cmd.getImageStoreId(); String scope = null; Long id = null; int paramCountCheck = 0; @@ -1696,6 +1697,11 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe id = storagepoolId; paramCountCheck++; } + if (imageStoreId != null) { + scope = ConfigKey.Scope.ImageStore.toString(); + id = imageStoreId; + paramCountCheck++; + } if (paramCountCheck > 1) { throw new InvalidParameterValueException("cannot handle multiple IDs, provide only one ID corresponding to the scope"); http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2e774966/server/src/com/cloud/storage/ImageStoreDetailsUtil.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/storage/ImageStoreDetailsUtil.java b/server/src/com/cloud/storage/ImageStoreDetailsUtil.java index 7107650..3e27ce6 100755 --- a/server/src/com/cloud/storage/ImageStoreDetailsUtil.java +++ b/server/src/com/cloud/storage/ImageStoreDetailsUtil.java @@ -20,48 +20,64 @@ import java.util.Map; import javax.inject.Inject; +import org.apache.cloudstack.framework.config.dao.ConfigurationDao; +import org.apache.cloudstack.framework.config.impl.ConfigurationVO; import org.apache.cloudstack.storage.datastore.db.ImageStoreDao; import org.apache.cloudstack.storage.datastore.db.ImageStoreDetailsDao; import org.apache.cloudstack.storage.datastore.db.ImageStoreVO; +import com.cloud.capacity.CapacityManager; +import com.google.common.base.Preconditions; + public class ImageStoreDetailsUtil { @Inject protected ImageStoreDao imageStoreDao; @Inject protected ImageStoreDetailsDao imageStoreDetailsDao; + @Inject + protected ConfigurationDao configurationDao; /** - * Obtain NFS protocol version (if provided) for a store id.
- * It can be set by adding an entry in {@code image_store_details} table, providing {@code name=nfs.version} and {@code value=X} (e.g. 3) + * Retrieve global secondary storage NFS version default value + * @return global default value + */ + protected Integer getGlobalDefaultNfsVersion(){ + ConfigurationVO globalNfsVersion = configurationDao.findByName(CapacityManager.ImageStoreNFSVersion.key()); + Preconditions.checkState(globalNfsVersion != null, "Unable to find global NFS version for version key " + CapacityManager.ImageStoreNFSVersion.key()); + String value = globalNfsVersion.getValue(); + return (value != null ? Integer.valueOf(value) : null); + } + /** + * Obtain NFS protocol version (if provided) for a store id, if not use default config value
* @param storeId image store id - * @return {@code null} if {@code nfs.version} is not found for storeId
- * {@code X} if {@code nfs.version} is found found for storeId + * @return {@code null} if {@code secstorage.nfs.version} is not found for storeId
+ * {@code X} if {@code secstorage.nfs.version} is found found for storeId */ public Integer getNfsVersion(long storeId) throws NumberFormatException { - String nfsVersion = null; - if (imageStoreDetailsDao.getDetails(storeId) != null){ - Map storeDetails = imageStoreDetailsDao.getDetails(storeId); - if (storeDetails != null && storeDetails.containsKey("nfs.version")){ - nfsVersion = storeDetails.get("nfs.version"); - } + + final Map storeDetails = imageStoreDetailsDao.getDetails(storeId); + if (storeDetails != null && storeDetails.containsKey(CapacityManager.ImageStoreNFSVersion.key())) { + final String version = storeDetails.get(CapacityManager.ImageStoreNFSVersion.key()); + return (version != null ? Integer.valueOf(version) : null); } - return (nfsVersion != null ? Integer.valueOf(nfsVersion) : null); + + return getGlobalDefaultNfsVersion(); + } /** * Obtain NFS protocol version (if provided) for a store uuid.
- * It can be set by adding an entry in {@code image_store_details} table, providing {@code name=nfs.version} and {@code value=X} (e.g. 3) - * @param storeId image store id - * @return {@code null} if {@code nfs.version} is not found for storeUuid
- * {@code X} if {@code nfs.version} is found found for storeUuid + * @param resourceId image store id + * @return {@code null} if {@code secstorage.nfs.version} is not found for storeUuid
+ * {@code X} if {@code secstorage.nfs.version} is found found for storeUuid */ public Integer getNfsVersionByUuid(String storeUuid){ ImageStoreVO imageStore = imageStoreDao.findByUuid(storeUuid); if (imageStore != null){ return getNfsVersion(imageStore.getId()); } - return null; + return getGlobalDefaultNfsVersion(); } } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2e774966/server/test/com/cloud/storage/ImageStoreDetailsUtilTest.java ---------------------------------------------------------------------- diff --git a/server/test/com/cloud/storage/ImageStoreDetailsUtilTest.java b/server/test/com/cloud/storage/ImageStoreDetailsUtilTest.java index 4b3ce40..7efbe08 100755 --- a/server/test/com/cloud/storage/ImageStoreDetailsUtilTest.java +++ b/server/test/com/cloud/storage/ImageStoreDetailsUtilTest.java @@ -17,42 +17,54 @@ package com.cloud.storage; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import java.util.HashMap; import java.util.Map; +import org.apache.cloudstack.framework.config.dao.ConfigurationDao; +import org.apache.cloudstack.framework.config.impl.ConfigurationVO; import org.apache.cloudstack.storage.datastore.db.ImageStoreDao; import org.apache.cloudstack.storage.datastore.db.ImageStoreDetailsDao; import org.apache.cloudstack.storage.datastore.db.ImageStoreVO; import org.junit.Before; import org.junit.Test; +import com.cloud.capacity.CapacityManager; + public class ImageStoreDetailsUtilTest { private final static long STORE_ID = 1l; private final static String STORE_UUID = "aaaa-aaaa-aaaa-aaaa"; private final static Integer NFS_VERSION = 3; + private final static Integer NFS_VERSION_DEFAULT = 2; ImageStoreDetailsUtil imageStoreDetailsUtil = new ImageStoreDetailsUtil(); ImageStoreDao imgStoreDao = mock(ImageStoreDao.class); ImageStoreDetailsDao imgStoreDetailsDao = mock(ImageStoreDetailsDao.class); + ConfigurationDao configurationDao = mock(ConfigurationDao.class); @Before public void setup() throws Exception { Map imgStoreDetails = new HashMap(); - imgStoreDetails.put("nfs.version", String.valueOf(NFS_VERSION)); + String nfsVersionKey = CapacityManager.ImageStoreNFSVersion.key(); + imgStoreDetails.put(nfsVersionKey, String.valueOf(NFS_VERSION)); when(imgStoreDetailsDao.getDetails(STORE_ID)).thenReturn(imgStoreDetails); ImageStoreVO imgStoreVO = mock(ImageStoreVO.class); when(imgStoreVO.getId()).thenReturn(Long.valueOf(STORE_ID)); when(imgStoreDao.findByUuid(STORE_UUID)).thenReturn(imgStoreVO); + ConfigurationVO confVO = mock(ConfigurationVO.class); + String defaultValue = (NFS_VERSION_DEFAULT == null ? null : String.valueOf(NFS_VERSION_DEFAULT)); + when(confVO.getValue()).thenReturn(defaultValue); + when(configurationDao.findByName(nfsVersionKey)).thenReturn(confVO); + imageStoreDetailsUtil.imageStoreDao = imgStoreDao; imageStoreDetailsUtil.imageStoreDetailsDao = imgStoreDetailsDao; + imageStoreDetailsUtil.configurationDao = configurationDao; } @Test @@ -68,7 +80,7 @@ public class ImageStoreDetailsUtilTest { when(imgStoreDetailsDao.getDetails(STORE_ID)).thenReturn(imgStoreDetails); Integer nfsVersion = imageStoreDetailsUtil.getNfsVersion(STORE_ID); - assertNull(nfsVersion); + assertEquals(NFS_VERSION_DEFAULT, nfsVersion); } @Test @@ -77,7 +89,7 @@ public class ImageStoreDetailsUtilTest { when(imgStoreDetailsDao.getDetails(STORE_ID)).thenReturn(imgStoreDetails); Integer nfsVersion = imageStoreDetailsUtil.getNfsVersion(STORE_ID); - assertNull(nfsVersion); + assertEquals(NFS_VERSION_DEFAULT, nfsVersion); } @Test @@ -90,6 +102,12 @@ public class ImageStoreDetailsUtilTest { public void testGetNfsVersionByUuidNoImgStore(){ when(imgStoreDao.findByUuid(STORE_UUID)).thenReturn(null); Integer nfsVersion = imageStoreDetailsUtil.getNfsVersionByUuid(STORE_UUID); - assertNull(nfsVersion); + assertEquals(NFS_VERSION_DEFAULT, nfsVersion); + } + + @Test + public void testGetGlobalDefaultNfsVersion(){ + Integer globalDefaultNfsVersion = imageStoreDetailsUtil.getGlobalDefaultNfsVersion(); + assertEquals(NFS_VERSION_DEFAULT, globalDefaultNfsVersion); } -} \ No newline at end of file +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2e774966/server/test/org/apache/cloudstack/networkoffering/ChildTestConfiguration.java ---------------------------------------------------------------------- diff --git a/server/test/org/apache/cloudstack/networkoffering/ChildTestConfiguration.java b/server/test/org/apache/cloudstack/networkoffering/ChildTestConfiguration.java index 343589c..0a38158 100644 --- a/server/test/org/apache/cloudstack/networkoffering/ChildTestConfiguration.java +++ b/server/test/org/apache/cloudstack/networkoffering/ChildTestConfiguration.java @@ -41,6 +41,8 @@ import org.apache.cloudstack.framework.config.dao.ConfigurationDao; import org.apache.cloudstack.region.PortableIpDaoImpl; import org.apache.cloudstack.region.PortableIpRangeDaoImpl; import org.apache.cloudstack.region.dao.RegionDaoImpl; +import org.apache.cloudstack.storage.datastore.db.ImageStoreDaoImpl; +import org.apache.cloudstack.storage.datastore.db.ImageStoreDetailsDaoImpl; import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDaoImpl; import org.apache.cloudstack.test.utils.SpringUtils; @@ -131,7 +133,7 @@ import com.cloud.vm.dao.VMInstanceDaoImpl; NetworkDomainDaoImpl.class, HostDetailsDaoImpl.class, HostTagsDaoImpl.class, ClusterDaoImpl.class, FirewallRulesDaoImpl.class, FirewallRulesCidrsDaoImpl.class, PhysicalNetworkDaoImpl.class, PhysicalNetworkTrafficTypeDaoImpl.class, PhysicalNetworkServiceProviderDaoImpl.class, LoadBalancerDaoImpl.class, NetworkServiceMapDaoImpl.class, PrimaryDataStoreDaoImpl.class, StoragePoolDetailsDaoImpl.class, - PortableIpRangeDaoImpl.class, RegionDaoImpl.class, PortableIpDaoImpl.class, AccountGuestVlanMapDaoImpl.class}, + PortableIpRangeDaoImpl.class, RegionDaoImpl.class, PortableIpDaoImpl.class, AccountGuestVlanMapDaoImpl.class, ImageStoreDaoImpl.class, ImageStoreDetailsDaoImpl.class}, includeFilters = {@Filter(value = ChildTestConfiguration.Library.class, type = FilterType.CUSTOM)}, useDefaultFilters = false) public class http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2e774966/setup/db/db/schema-481to490.sql ---------------------------------------------------------------------- diff --git a/setup/db/db/schema-481to490.sql b/setup/db/db/schema-481to490.sql index bd1dd82..0064d6f 100644 --- a/setup/db/db/schema-481to490.sql +++ b/setup/db/db/schema-481to490.sql @@ -545,3 +545,6 @@ INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervis INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(), 'VMware', '5.0', 'centos64Guest', 228, now(), 0); INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(), 'VMware', '5.1', 'centos64Guest', 228, now(), 0); INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(), 'VMware', '5.5', 'centos64Guest', 228, now(), 0); + +ALTER TABLE `cloud`.`image_store_details` CHANGE COLUMN `value` `value` VARCHAR(255) NULL DEFAULT NULL COMMENT 'value of the detail', ADD COLUMN `display` tinyint(1) NOT +NULL DEFAULT '1' COMMENT 'True if the detail can be displayed to the end user' AFTER `value`; http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2e774966/test/integration/smoke/test_ssvm.py ---------------------------------------------------------------------- diff --git a/test/integration/smoke/test_ssvm.py b/test/integration/smoke/test_ssvm.py index 81dba32..b14883c 100644 --- a/test/integration/smoke/test_ssvm.py +++ b/test/integration/smoke/test_ssvm.py @@ -20,12 +20,13 @@ from marvin.cloudstackTestCase import cloudstackTestCase from marvin.cloudstackAPI import (stopSystemVm, rebootSystemVm, - destroySystemVm) + destroySystemVm, updateConfiguration) from marvin.lib.utils import (cleanup_resources, get_process_status, - get_host_credentials) + get_host_credentials, + wait_until) from marvin.lib.base import (PhysicalNetwork, - NetScaler) + NetScaler, ImageStore) from marvin.lib.common import (get_zone, list_hosts, list_ssvms, @@ -33,6 +34,7 @@ from marvin.lib.common import (get_zone, list_vlan_ipranges) from nose.plugins.attrib import attr import telnetlib +import logging # Import System modules import time @@ -42,12 +44,19 @@ _multiprocess_shared_ = True class TestSSVMs(cloudstackTestCase): def setUp(self): + test_case = super(TestSSVMs, self) self.apiclient = self.testClient.getApiClient() self.hypervisor = self.testClient.getHypervisorInfo() self.cleanup = [] + self.config = test_case.getClsConfig() self.services = self.testClient.getParsedTestDataConfig() self.zone = get_zone(self.apiclient, self.testClient.getZoneForTests()) + self.logger = logging.getLogger('TestSSVMs') + self.stream_handler = logging.StreamHandler() + self.logger.setLevel(logging.DEBUG) + self.logger.addHandler(self.stream_handler) + # Default sleep is set to 90 seconds, which is too long if the SSVM takes up to 2min to start. # Second sleep in the loop will waste test time. self.services["sleep"] = 30 @@ -1197,3 +1206,162 @@ class TestSSVMs(cloudstackTestCase): # Call to verify cloud process is running self.test_04_cpvm_internals() return + + @attr( + tags=[ + "advanced", + "advancedns", + "smoke", + "basic", + "sg"], + required_hardware="true") + def test_11_ss_nfs_version_on_ssvm(self): + """Test NFS Version on Secondary Storage mounted properly on SSVM + """ + + # 1) List SSVM in zone + # 2) Get id and url from mounted nfs store + # 3) Update NFS version for previous image store + # 4) Stop SSVM + # 5) Check NFS version of mounted nfs store after SSVM starts + + nfs_version = self.config.nfsVersion + if nfs_version == None: + self.skipTest('No NFS version provided in test data') + + #List SSVM for zone id + list_ssvm_response = list_ssvms( + self.apiclient, + systemvmtype='secondarystoragevm', + state='Running', + zoneid=self.zone.id + ) + self.assertNotEqual( + list_ssvm_response, + None + ) + self.assertEqual( + isinstance(list_ssvm_response, list), + True, + "Check list response returns a valid list" + ) + self.assertEqual( + len(list_ssvm_response), + 1, + "Check list System VMs response" + ) + + ssvm = list_ssvm_response[0] + image_stores_response = ImageStore.list(self.apiclient,zoneid=self.zone.id) + + if self.hypervisor.lower() in ('vmware', 'hyperv'): + # SSH into SSVMs is done via management server for Vmware and Hyper-V + result = get_process_status( + self.apiclient.connection.mgtSvr, + 22, + self.apiclient.connection.user, + self.apiclient.connection.passwd, + ssvm.privateip, + "mount | grep 'type nfs'", + hypervisor=self.hypervisor) + + for res in result: + split_res = res.split("on") + mounted_img_store_url = split_res[0].strip() + for img_store in image_stores_response: + img_store_url = str(img_store.url) + if img_store_url.startswith("nfs://"): + img_store_url = img_store_url[6:] + #Add colon after ip address to match output from mount command + first_slash = img_store_url.find('/') + img_store_url = img_store_url[0:first_slash] + ':' + img_store_url[first_slash:] + if img_store_url == mounted_img_store_url: + img_store_id = img_store.id + break + + self.assertNotEqual( + img_store_id, + None, + "Check image store id mounted on SSVM" + ) + + #Update NFS version for image store mounted on SSVM + updateConfigurationCmd = updateConfiguration.updateConfigurationCmd() + updateConfigurationCmd.name = "secstorage.nfs.version" + updateConfigurationCmd.value = nfs_version + updateConfigurationCmd.imagestoreuuid = img_store_id + + updateConfigurationResponse = self.apiclient.updateConfiguration(updateConfigurationCmd) + self.logger.debug("updated the parameter %s with value %s"%(updateConfigurationResponse.name, updateConfigurationResponse.value)) + + #Stop SSVM + self.debug("Stopping SSVM: %s" % ssvm.id) + cmd = stopSystemVm.stopSystemVmCmd() + cmd.id = ssvm.id + self.apiclient.stopSystemVm(cmd) + + def checkForRunningSSVM(): + new_list_ssvm_response = list_ssvms( + self.apiclient, + id=ssvm.id + ) + if isinstance(new_list_ssvm_response, list): + return new_list_ssvm_response[0].state == 'Running', None + + res, _ = wait_until(self.services["sleep"], self.services["timeout"], checkForRunningSSVM) + if not res: + self.fail("List SSVM call failed!") + + new_list_ssvm_response = list_ssvms( + self.apiclient, + id=ssvm.id + ) + + self.assertNotEqual( + new_list_ssvm_response, + None + ) + self.assertEqual( + isinstance(new_list_ssvm_response, list), + True, + "Check list response returns a valid list" + ) + ssvm = new_list_ssvm_response[0] + self.debug("SSVM state after debug: %s" % ssvm.state) + self.assertEqual( + ssvm.state, + 'Running', + "Check whether SSVM is running or not" + ) + # Wait for the agent to be up + self.waitForSystemVMAgent(ssvm.name) + + #Check NFS version on mounted image store + result = get_process_status( + self.apiclient.connection.mgtSvr, + 22, + self.apiclient.connection.user, + self.apiclient.connection.passwd, + ssvm.privateip, + "mount | grep '%s'"%mounted_img_store_url, + hypervisor=self.hypervisor) + + self.assertNotEqual( + result, + None + ) + self.assertEqual( + len(result), + 1, + "Check result length" + ) + + res = result[0] + mounted_nfs_version = res.split("vers=")[1][0:1] + self.assertEqual( + int(mounted_nfs_version), + int(nfs_version), + "Check mounted NFS version to be the same as provided" + ) + + return http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2e774966/ui/scripts/system.js ---------------------------------------------------------------------- diff --git a/ui/scripts/system.js b/ui/scripts/system.js index 7ffacd0..0ff633c 100644 --- a/ui/scripts/system.js +++ b/ui/scripts/system.js @@ -19974,28 +19974,58 @@ } }); } - } - - // Granular settings for storage pool for secondary storage is not required - /* settings: { - title: 'label.menu.global.settings', - custom: cloudStack.uiCustom.granularSettings({ - dataProvider: function(args) { - args.response.success({ - data: [ - { name: 'config.param.1', value: 1 }, - { name: 'config.param.2', value: 2 } - ] - }); }, - actions: { - edit: function(args) { - // call updateStorageLevelParameters - args.response.success(); - } - } - }) - } */ + + // Granular settings for image store + settings: { + title: 'label.settings', + custom: cloudStack.uiCustom.granularSettings({ + dataProvider: function (args) { + + $.ajax({ + url: createURL('listConfigurations&imagestoreuuid=' + args.context.secondaryStorage[0].id), + data: listViewDataProvider(args, { + }, + { + searchBy: 'name' + }), + success: function (json) { + args.response.success({ + data: json.listconfigurationsresponse.configuration + }); + }, + + error: function (json) { + args.response.error(parseXMLHttpResponse(json)); + } + }); + }, + actions: { + edit: function (args) { + // call updateStorageLevelParameters + var data = { + name: args.data.jsonObj.name, + value: args.data.value + }; + + $.ajax({ + url: createURL('updateConfiguration&imagestoreuuid=' + args.context.secondaryStorage[0].id), + data: data, + success: function (json) { + var item = json.updateconfigurationresponse.configuration; + args.response.success({ + data: item + }); + }, + + error: function (json) { + args.response.error(parseXMLHttpResponse(json)); + } + }); + } + } + }) + } } } }