You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by mc...@apache.org on 2013/04/06 02:35:24 UTC

[51/57] [abbrv] git commit: updated refs/heads/object_store to a872d6d

Create DB view for Image Data Store.


Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/7699485b
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/7699485b
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/7699485b

Branch: refs/heads/object_store
Commit: 7699485b4fb6a98d94a4fec194c54cf87db43880
Parents: 86a3840
Author: Min Chen <mi...@citrix.com>
Authored: Tue Apr 2 18:15:15 2013 -0700
Committer: Min Chen <mi...@citrix.com>
Committed: Fri Apr 5 11:18:33 2013 -0700

----------------------------------------------------------------------
 .../api/response/ObjectStoreDetailResponse.java    |   38 +++
 .../api/response/ObjectStoreResponse.java          |   48 +++--
 .../datastore/db/ImageDataStoreDetailVO.java       |   81 ++++++
 .../datastore/db/ImageDataStoreDetailsDao.java     |   28 ++
 server/src/com/cloud/api/ApiDBUtils.java           |   22 ++-
 server/src/com/cloud/api/ApiResponseHelper.java    |    9 +-
 .../com/cloud/api/query/ViewResponseHelper.java    |   20 ++
 .../cloud/api/query/dao/ImageDataStoreJoinDao.java |   36 +++
 .../api/query/dao/ImageDataStoreJoinDaoImpl.java   |  164 ++++++++++++
 .../cloud/api/query/vo/ImageDataStoreJoinVO.java   |  201 +++++++++++++++
 .../cloud/storage/dao/ImageDataStoreDaoImpl.java   |   75 ++++++
 setup/db/db/schema-410to420.sql                    |   28 ++-
 12 files changed, 729 insertions(+), 21 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/7699485b/api/src/org/apache/cloudstack/api/response/ObjectStoreDetailResponse.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/response/ObjectStoreDetailResponse.java b/api/src/org/apache/cloudstack/api/response/ObjectStoreDetailResponse.java
index b532c28..74a42f2 100644
--- a/api/src/org/apache/cloudstack/api/response/ObjectStoreDetailResponse.java
+++ b/api/src/org/apache/cloudstack/api/response/ObjectStoreDetailResponse.java
@@ -28,6 +28,16 @@ public class ObjectStoreDetailResponse extends BaseResponse {
     @SerializedName("value") @Param(description="detail property value of the object store")
     private String value;
 
+    public ObjectStoreDetailResponse(){
+        super();
+    }
+
+    public ObjectStoreDetailResponse(String name, String val){
+        super();
+        this.name = name;
+        this.value = val;
+    }
+
     public String getName() {
         return name;
     }
@@ -44,5 +54,33 @@ public class ObjectStoreDetailResponse extends BaseResponse {
         this.value = value;
     }
 
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        String oid = this.getName();
+        result = prime * result + ((oid== null) ? 0 : oid.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        ObjectStoreDetailResponse other = (ObjectStoreDetailResponse) obj;
+        String oid = this.getName();
+        if (oid == null) {
+            if (other.getName() != null)
+                return false;
+        } else if (!oid.equals(other.getName()))
+            return false;
+        else if ( this.getValue().equals(other.getValue()))
+            return false;
+        return true;
+    }
 
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/7699485b/api/src/org/apache/cloudstack/api/response/ObjectStoreResponse.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/response/ObjectStoreResponse.java b/api/src/org/apache/cloudstack/api/response/ObjectStoreResponse.java
index de3a26f..595ae97 100644
--- a/api/src/org/apache/cloudstack/api/response/ObjectStoreResponse.java
+++ b/api/src/org/apache/cloudstack/api/response/ObjectStoreResponse.java
@@ -16,9 +16,8 @@
 // under the License.
 package org.apache.cloudstack.api.response;
 
-import java.util.Date;
-
-import javax.persistence.Column;
+import java.util.LinkedHashSet;
+import java.util.Set;
 
 import org.apache.cloudstack.api.ApiConstants;
 import org.apache.cloudstack.api.BaseResponse;
@@ -27,8 +26,6 @@ import org.apache.cloudstack.api.EntityReference;
 import com.cloud.serializer.Param;
 import com.cloud.storage.ObjectStore;
 import com.cloud.storage.ScopeType;
-import com.cloud.storage.StoragePool;
-import com.cloud.storage.StoragePoolStatus;
 import com.google.gson.annotations.SerializedName;
 
 @EntityReference(value=ObjectStore.class)
@@ -43,7 +40,7 @@ public class ObjectStoreResponse extends BaseResponse {
     private String zoneName;
 
     @SerializedName("regionid") @Param(description="the Region ID of the object store")
-    private String regionId;
+    private Long regionId;
 
     @SerializedName("regionname") @Param(description="the Region name of the object store")
     private String regionName;
@@ -54,16 +51,22 @@ public class ObjectStoreResponse extends BaseResponse {
     @SerializedName("url") @Param(description="the url of the object store")
     private String url;
 
+    @SerializedName("protocol") @Param(description="the protocol of the object store")
+    private String protocol;
+
     @SerializedName("providername") @Param(description="the provider name of the object store")
     private String providerName;
 
     @SerializedName("scope") @Param(description="the scope of the object store")
-    private ScopeType type;
+    private ScopeType scope;
 
     @SerializedName("details") @Param(description="the details of the object store")
-    private String details;
+    private Set<ObjectStoreDetailResponse> details;
 
 
+    public ObjectStoreResponse(){
+        this.details = new LinkedHashSet<ObjectStoreDetailResponse>();
+    }
 
     @Override
     public String getObjectId() {
@@ -95,11 +98,11 @@ public class ObjectStoreResponse extends BaseResponse {
     }
 
 
-    public String getRegionId() {
+    public Long getRegionId() {
         return regionId;
     }
 
-    public void setRegionId(String regionId) {
+    public void setRegionId(Long regionId) {
         this.regionId = regionId;
     }
 
@@ -135,22 +138,35 @@ public class ObjectStoreResponse extends BaseResponse {
         this.providerName = providerName;
     }
 
-    public ScopeType getType() {
-        return type;
+    public ScopeType getScope() {
+        return scope;
+    }
+
+    public void setScope(ScopeType type) {
+        this.scope = type;
     }
 
-    public void setType(ScopeType type) {
-        this.type = type;
+
+    public String getProtocol() {
+        return protocol;
+    }
+
+    public void setProtocol(String protocol) {
+        this.protocol = protocol;
     }
 
-    public String getDetails() {
+    public Set<ObjectStoreDetailResponse> getDetails() {
         return details;
     }
 
-    public void setDetails(String details) {
+    public void setDetails(Set<ObjectStoreDetailResponse> details) {
         this.details = details;
     }
 
+    public void addDetail(ObjectStoreDetailResponse detail){
+        this.details.add(detail);
+    }
+
 
 
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/7699485b/engine/api/src/org/apache/cloudstack/storage/datastore/db/ImageDataStoreDetailVO.java
----------------------------------------------------------------------
diff --git a/engine/api/src/org/apache/cloudstack/storage/datastore/db/ImageDataStoreDetailVO.java b/engine/api/src/org/apache/cloudstack/storage/datastore/db/ImageDataStoreDetailVO.java
new file mode 100644
index 0000000..c980cf1
--- /dev/null
+++ b/engine/api/src/org/apache/cloudstack/storage/datastore/db/ImageDataStoreDetailVO.java
@@ -0,0 +1,81 @@
+// 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 org.apache.cloudstack.api.InternalIdentity;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+@Entity
+@Table(name="image_data_store_details")
+public class ImageDataStoreDetailVO implements InternalIdentity {
+    @Id
+    @GeneratedValue(strategy=GenerationType.IDENTITY)
+    @Column(name="id")
+    long id;
+
+    @Column(name="store_id")
+    long storeId;
+
+    @Column(name="name")
+    String name;
+
+    @Column(name="value")
+    String value;
+
+    public ImageDataStoreDetailVO(long storeId, String name, String value) {
+        this.storeId = storeId;
+        this.name = name;
+        this.value = value;
+    }
+
+    public long getId() {
+        return id;
+    }
+
+    public long getStoreId() {
+        return storeId;
+    }
+
+    public void setStoreId(long storeId) {
+        this.storeId = storeId;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getValue() {
+        return value;
+    }
+
+    public void setValue(String value) {
+        this.value = value;
+    }
+
+    protected ImageDataStoreDetailVO() {
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/7699485b/engine/api/src/org/apache/cloudstack/storage/datastore/db/ImageDataStoreDetailsDao.java
----------------------------------------------------------------------
diff --git a/engine/api/src/org/apache/cloudstack/storage/datastore/db/ImageDataStoreDetailsDao.java b/engine/api/src/org/apache/cloudstack/storage/datastore/db/ImageDataStoreDetailsDao.java
new file mode 100644
index 0000000..781efcf
--- /dev/null
+++ b/engine/api/src/org/apache/cloudstack/storage/datastore/db/ImageDataStoreDetailsDao.java
@@ -0,0 +1,28 @@
+// 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.Map;
+
+
+import com.cloud.utils.db.GenericDao;
+
+public interface ImageDataStoreDetailsDao extends GenericDao<ImageDataStoreDetailVO, Long> {
+
+    void update(long storeId, Map<String, String> details);
+    Map<String, String> getDetails(long storeId);
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/7699485b/server/src/com/cloud/api/ApiDBUtils.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/ApiDBUtils.java b/server/src/com/cloud/api/ApiDBUtils.java
index 7b44190..41f0759 100755
--- a/server/src/com/cloud/api/ApiDBUtils.java
+++ b/server/src/com/cloud/api/ApiDBUtils.java
@@ -34,6 +34,7 @@ import org.apache.cloudstack.api.response.DomainRouterResponse;
 import org.apache.cloudstack.api.response.EventResponse;
 import org.apache.cloudstack.api.response.HostResponse;
 import org.apache.cloudstack.api.response.InstanceGroupResponse;
+import org.apache.cloudstack.api.response.ObjectStoreResponse;
 import org.apache.cloudstack.api.response.ProjectAccountResponse;
 import org.apache.cloudstack.api.response.ProjectInvitationResponse;
 import org.apache.cloudstack.api.response.ProjectResponse;
@@ -55,6 +56,7 @@ import com.cloud.api.query.dao.DataCenterJoinDao;
 import com.cloud.api.query.dao.DiskOfferingJoinDao;
 import com.cloud.api.query.dao.DomainRouterJoinDao;
 import com.cloud.api.query.dao.HostJoinDao;
+import com.cloud.api.query.dao.ImageDataStoreJoinDao;
 import com.cloud.api.query.dao.InstanceGroupJoinDao;
 import com.cloud.api.query.dao.ProjectAccountJoinDao;
 import com.cloud.api.query.dao.ProjectInvitationJoinDao;
@@ -73,6 +75,7 @@ import com.cloud.api.query.vo.DiskOfferingJoinVO;
 import com.cloud.api.query.vo.DomainRouterJoinVO;
 import com.cloud.api.query.vo.EventJoinVO;
 import com.cloud.api.query.vo.HostJoinVO;
+import com.cloud.api.query.vo.ImageDataStoreJoinVO;
 import com.cloud.api.query.vo.InstanceGroupJoinVO;
 import com.cloud.api.query.vo.ProjectAccountJoinVO;
 import com.cloud.api.query.vo.ProjectInvitationJoinVO;
@@ -284,7 +287,7 @@ public class ApiDBUtils {
     static NetworkModel _networkModel;
     static NetworkManager _networkMgr;
     static TemplateManager _templateMgr;
-    
+
     static StatsCollector _statsCollector;
 
     static AccountDao _accountDao;
@@ -362,6 +365,7 @@ public class ApiDBUtils {
     static HostJoinDao _hostJoinDao;
     static VolumeJoinDao _volJoinDao;
     static StoragePoolJoinDao _poolJoinDao;
+    static ImageDataStoreJoinDao _imageStoreJoinDao;
     static AccountJoinDao _accountJoinDao;
     static AsyncJobJoinDao _jobJoinDao;
 
@@ -466,6 +470,7 @@ public class ApiDBUtils {
     @Inject private HostJoinDao hostJoinDao;
     @Inject private VolumeJoinDao volJoinDao;
     @Inject private StoragePoolJoinDao poolJoinDao;
+    @Inject private ImageDataStoreJoinDao imageStoreJoinDao;
     @Inject private AccountJoinDao accountJoinDao;
     @Inject private AsyncJobJoinDao jobJoinDao;
 
@@ -566,6 +571,7 @@ public class ApiDBUtils {
         _hostJoinDao = hostJoinDao;
         _volJoinDao = volJoinDao;
         _poolJoinDao = poolJoinDao;
+        _imageStoreJoinDao = imageStoreJoinDao;
         _accountJoinDao = accountJoinDao;
         _jobJoinDao = jobJoinDao;
 
@@ -1535,6 +1541,18 @@ public class ApiDBUtils {
         return _poolJoinDao.newStoragePoolView(vr);
     }
 
+    public static ObjectStoreResponse newImageStoreResponse(ImageDataStoreJoinVO vr) {
+        return _imageStoreJoinDao.newObjectStoreResponse(vr);
+    }
+
+    public static ObjectStoreResponse fillImageStoreDetails(ObjectStoreResponse vrData, ImageDataStoreJoinVO vr){
+        return _imageStoreJoinDao.setObjectStoreResponse(vrData, vr);
+    }
+
+    public static List<ImageDataStoreJoinVO> newImageStoreView(ObjectStore vr){
+        return _imageStoreJoinDao.newObjectStoreView(vr);
+    }
+
 
     public static AccountResponse newAccountResponse(AccountJoinVO ve) {
         return _accountJoinDao.newAccountResponse(ve);
@@ -1579,7 +1597,7 @@ public class ApiDBUtils {
    public static DataCenterJoinVO newDataCenterView(DataCenter dc){
        return _dcJoinDao.newDataCenterView(dc);
    }
-   
+
    public static Map<String, String> findHostDetailsById(long hostId){
 	   return _hostDetailsDao.findDetails(hostId);
    }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/7699485b/server/src/com/cloud/api/ApiResponseHelper.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/ApiResponseHelper.java b/server/src/com/cloud/api/ApiResponseHelper.java
index 9054331..03ed97d 100755
--- a/server/src/com/cloud/api/ApiResponseHelper.java
+++ b/server/src/com/cloud/api/ApiResponseHelper.java
@@ -142,6 +142,7 @@ import com.cloud.api.query.vo.DiskOfferingJoinVO;
 import com.cloud.api.query.vo.DomainRouterJoinVO;
 import com.cloud.api.query.vo.EventJoinVO;
 import com.cloud.api.query.vo.HostJoinVO;
+import com.cloud.api.query.vo.ImageDataStoreJoinVO;
 import com.cloud.api.query.vo.InstanceGroupJoinVO;
 import com.cloud.api.query.vo.ProjectAccountJoinVO;
 import com.cloud.api.query.vo.ProjectInvitationJoinVO;
@@ -892,8 +893,12 @@ public class ApiResponseHelper implements ResponseGenerator {
 
     @Override
     public ObjectStoreResponse createObjectStoreResponse(ObjectStore os) {
-        // TODO Auto-generated method stub
-        return null;
+        List<ImageDataStoreJoinVO> viewStores = ApiDBUtils.newImageStoreView(os);
+        List<ObjectStoreResponse> listStores = ViewResponseHelper.createObjectStoreResponse(viewStores.toArray(new ImageDataStoreJoinVO[viewStores.size()]));
+        assert listStores != null && listStores.size() == 1 : "There should be one image data store returned";
+        return listStores.get(0);
+
+
     }
 
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/7699485b/server/src/com/cloud/api/query/ViewResponseHelper.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/query/ViewResponseHelper.java b/server/src/com/cloud/api/query/ViewResponseHelper.java
index 9e612b0..a1d1bf8 100644
--- a/server/src/com/cloud/api/query/ViewResponseHelper.java
+++ b/server/src/com/cloud/api/query/ViewResponseHelper.java
@@ -30,6 +30,7 @@ import org.apache.cloudstack.api.response.DomainRouterResponse;
 import org.apache.cloudstack.api.response.EventResponse;
 import org.apache.cloudstack.api.response.HostResponse;
 import org.apache.cloudstack.api.response.InstanceGroupResponse;
+import org.apache.cloudstack.api.response.ObjectStoreResponse;
 import org.apache.cloudstack.api.response.ProjectAccountResponse;
 import org.apache.cloudstack.api.response.ProjectInvitationResponse;
 import org.apache.cloudstack.api.response.ProjectResponse;
@@ -51,6 +52,7 @@ import com.cloud.api.query.vo.DiskOfferingJoinVO;
 import com.cloud.api.query.vo.DomainRouterJoinVO;
 import com.cloud.api.query.vo.EventJoinVO;
 import com.cloud.api.query.vo.HostJoinVO;
+import com.cloud.api.query.vo.ImageDataStoreJoinVO;
 import com.cloud.api.query.vo.InstanceGroupJoinVO;
 import com.cloud.api.query.vo.ProjectAccountJoinVO;
 import com.cloud.api.query.vo.ProjectInvitationJoinVO;
@@ -263,6 +265,24 @@ public class ViewResponseHelper {
         return new ArrayList<StoragePoolResponse>(vrDataList.values());
     }
 
+    public static List<ObjectStoreResponse> createObjectStoreResponse(ImageDataStoreJoinVO... stores) {
+        Hashtable<Long, ObjectStoreResponse> vrDataList = new Hashtable<Long, ObjectStoreResponse>();
+        // Initialise the vrdatalist with the input data
+        for (ImageDataStoreJoinVO vr : stores) {
+            ObjectStoreResponse vrData = vrDataList.get(vr.getId());
+            if ( vrData == null ){
+                // first time encountering this vm
+                vrData = ApiDBUtils.newImageStoreResponse(vr);
+            }
+            else{
+                // update tags
+                vrData = ApiDBUtils.fillImageStoreDetails(vrData, vr);
+            }
+            vrDataList.put(vr.getId(), vrData);
+        }
+        return new ArrayList<ObjectStoreResponse>(vrDataList.values());
+    }
+
 
     public static List<AccountResponse> createAccountResponse(AccountJoinVO... accounts) {
         List<AccountResponse> respList = new ArrayList<AccountResponse>();

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/7699485b/server/src/com/cloud/api/query/dao/ImageDataStoreJoinDao.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/query/dao/ImageDataStoreJoinDao.java b/server/src/com/cloud/api/query/dao/ImageDataStoreJoinDao.java
new file mode 100644
index 0000000..b92fbe6
--- /dev/null
+++ b/server/src/com/cloud/api/query/dao/ImageDataStoreJoinDao.java
@@ -0,0 +1,36 @@
+// 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 com.cloud.api.query.dao;
+
+import java.util.List;
+
+import org.apache.cloudstack.api.response.ObjectStoreResponse;
+import com.cloud.api.query.vo.ImageDataStoreJoinVO;
+import com.cloud.storage.ObjectStore;
+import com.cloud.utils.db.GenericDao;
+
+public interface ImageDataStoreJoinDao extends GenericDao<ImageDataStoreJoinVO, Long> {
+
+    ObjectStoreResponse newObjectStoreResponse(ImageDataStoreJoinVO os);
+
+    ObjectStoreResponse setObjectStoreResponse(ObjectStoreResponse response, ImageDataStoreJoinVO os);
+
+    List<ImageDataStoreJoinVO> newObjectStoreView(ObjectStore os);
+
+    List<ImageDataStoreJoinVO> searchByIds(Long... spIds);
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/7699485b/server/src/com/cloud/api/query/dao/ImageDataStoreJoinDaoImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/query/dao/ImageDataStoreJoinDaoImpl.java b/server/src/com/cloud/api/query/dao/ImageDataStoreJoinDaoImpl.java
new file mode 100644
index 0000000..c58f954
--- /dev/null
+++ b/server/src/com/cloud/api/query/dao/ImageDataStoreJoinDaoImpl.java
@@ -0,0 +1,164 @@
+// 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 com.cloud.api.query.dao;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.ejb.Local;
+import javax.inject.Inject;
+
+import org.apache.cloudstack.api.response.ObjectStoreDetailResponse;
+import org.apache.cloudstack.api.response.ObjectStoreResponse;
+import org.apache.log4j.Logger;
+import org.springframework.stereotype.Component;
+
+import com.cloud.api.query.vo.ImageDataStoreJoinVO;
+import com.cloud.configuration.dao.ConfigurationDao;
+import com.cloud.storage.ObjectStore;
+import com.cloud.utils.db.GenericDaoBase;
+import com.cloud.utils.db.SearchBuilder;
+import com.cloud.utils.db.SearchCriteria;
+
+
+@Component
+@Local(value={ImageDataStoreJoinDao.class})
+public class ImageDataStoreJoinDaoImpl extends GenericDaoBase<ImageDataStoreJoinVO, Long> implements ImageDataStoreJoinDao {
+    public static final Logger s_logger = Logger.getLogger(ImageDataStoreJoinDaoImpl.class);
+
+    @Inject
+    private ConfigurationDao  _configDao;
+
+    private final SearchBuilder<ImageDataStoreJoinVO> dsSearch;
+
+    private final SearchBuilder<ImageDataStoreJoinVO> dsIdSearch;
+
+
+    protected ImageDataStoreJoinDaoImpl() {
+
+        dsSearch = createSearchBuilder();
+        dsSearch.and("idIN", dsSearch.entity().getId(), SearchCriteria.Op.IN);
+        dsSearch.done();
+
+        dsIdSearch = createSearchBuilder();
+        dsIdSearch.and("id", dsIdSearch.entity().getId(), SearchCriteria.Op.EQ);
+        dsIdSearch.done();
+
+        this._count = "select count(distinct id) from image_data_store_view WHERE ";
+    }
+
+
+
+
+
+    @Override
+    public ObjectStoreResponse newObjectStoreResponse(ImageDataStoreJoinVO ids) {
+        ObjectStoreResponse osResponse = new ObjectStoreResponse();
+        osResponse.setId(ids.getUuid());
+        osResponse.setName(ids.getName());
+        osResponse.setProviderName(ids.getProviderName());
+        osResponse.setProtocol(ids.getProtocol());
+        osResponse.setUrl(ids.getUrl());
+        osResponse.setScope(ids.getScope());
+        osResponse.setZoneId(ids.getZoneUuid());
+        osResponse.setZoneName(ids.getZoneName());
+        osResponse.setRegionId(ids.getRegionId());
+        osResponse.setRegionName(ids.getRegionName());
+
+        String detailName = ids.getDetailName();
+        if ( detailName != null && detailName.length() > 0 ){
+            ObjectStoreDetailResponse osdResponse = new ObjectStoreDetailResponse(detailName, ids.getDetailValue());
+            osResponse.addDetail(osdResponse);
+        }
+        osResponse.setObjectName("objectstore");
+        return osResponse;
+    }
+
+
+
+
+
+    @Override
+    public ObjectStoreResponse setObjectStoreResponse(ObjectStoreResponse response, ImageDataStoreJoinVO ids) {
+        String detailName = ids.getDetailName();
+        if ( detailName != null && detailName.length() > 0 ){
+            ObjectStoreDetailResponse osdResponse = new ObjectStoreDetailResponse(detailName, ids.getDetailValue());
+            response.addDetail(osdResponse);
+        }
+        return response;
+    }
+
+
+
+    @Override
+    public List<ImageDataStoreJoinVO> newObjectStoreView(ObjectStore os) {
+        SearchCriteria<ImageDataStoreJoinVO> sc = dsIdSearch.create();
+        sc.setParameters("id", os.getId());
+        return searchIncludingRemoved(sc, null, null, false);
+
+    }
+
+
+
+    @Override
+    public List<ImageDataStoreJoinVO> searchByIds(Long... spIds) {
+        // set detail batch query size
+        int DETAILS_BATCH_SIZE = 2000;
+        String batchCfg = _configDao.getValue("detail.batch.query.size");
+        if ( batchCfg != null ){
+            DETAILS_BATCH_SIZE = Integer.parseInt(batchCfg);
+        }
+        // query details by batches
+        List<ImageDataStoreJoinVO> uvList = new ArrayList<ImageDataStoreJoinVO>();
+        // query details by batches
+        int curr_index = 0;
+        if ( spIds.length > DETAILS_BATCH_SIZE ){
+            while ( (curr_index + DETAILS_BATCH_SIZE ) <= spIds.length ) {
+                Long[] ids = new Long[DETAILS_BATCH_SIZE];
+                for (int k = 0, j = curr_index; j < curr_index + DETAILS_BATCH_SIZE; j++, k++) {
+                    ids[k] = spIds[j];
+                }
+                SearchCriteria<ImageDataStoreJoinVO> sc = dsSearch.create();
+                sc.setParameters("idIN", ids);
+                List<ImageDataStoreJoinVO> vms = searchIncludingRemoved(sc, null, null, false);
+                if (vms != null) {
+                    uvList.addAll(vms);
+                }
+                curr_index += DETAILS_BATCH_SIZE;
+            }
+        }
+        if (curr_index < spIds.length) {
+            int batch_size = (spIds.length - curr_index);
+            // set the ids value
+            Long[] ids = new Long[batch_size];
+            for (int k = 0, j = curr_index; j < curr_index + batch_size; j++, k++) {
+                ids[k] = spIds[j];
+            }
+            SearchCriteria<ImageDataStoreJoinVO> sc = dsSearch.create();
+            sc.setParameters("idIN", ids);
+            List<ImageDataStoreJoinVO> vms = searchIncludingRemoved(sc, null, null, false);
+            if (vms != null) {
+                uvList.addAll(vms);
+            }
+        }
+        return uvList;
+    }
+
+
+
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/7699485b/server/src/com/cloud/api/query/vo/ImageDataStoreJoinVO.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/query/vo/ImageDataStoreJoinVO.java b/server/src/com/cloud/api/query/vo/ImageDataStoreJoinVO.java
new file mode 100644
index 0000000..5858dff
--- /dev/null
+++ b/server/src/com/cloud/api/query/vo/ImageDataStoreJoinVO.java
@@ -0,0 +1,201 @@
+// 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 com.cloud.api.query.vo;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import javax.persistence.Id;
+import javax.persistence.Table;
+import com.cloud.storage.ScopeType;
+import org.apache.cloudstack.api.Identity;
+import org.apache.cloudstack.api.InternalIdentity;
+
+/**
+ * Image Data Store DB view.
+ *
+ */
+@Entity
+@Table(name="image_data_store_view")
+public class ImageDataStoreJoinVO extends BaseViewVO implements InternalIdentity, Identity {
+
+    @Id
+    @Column(name="id")
+    private long id;
+
+    @Column(name="uuid")
+    private String uuid;
+
+    @Column(name="name")
+    private String name;
+
+    @Column(name="url")
+    private String url;
+
+    @Column(name = "protocol")
+    private String protocol;
+
+    @Column(name = "provider_name", nullable = false)
+    private String providerName;
+
+    @Column(name="scope")
+    @Enumerated(value = EnumType.STRING)
+    private ScopeType scope;
+
+    @Column(name="data_center_id")
+    private long zoneId;
+
+    @Column(name="data_center_uuid")
+    private String zoneUuid;
+
+    @Column(name="data_center_name")
+    private String zoneName;
+
+    @Column(name="region_id")
+    private long regionId;
+
+    @Column(name="region_name")
+    private String regionName;
+
+    @Column(name="detail_name")
+    private String detailName;
+
+    @Column(name="detail_value")
+    private String detailValue;
+
+
+    @Override
+    public long getId() {
+        return id;
+    }
+
+    @Override
+    public void setId(long id) {
+        this.id = id;
+    }
+
+    @Override
+    public String getUuid() {
+        return uuid;
+    }
+
+    public void setUuid(String uuid) {
+        this.uuid = uuid;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+
+
+    public long getZoneId() {
+        return zoneId;
+    }
+
+    public void setZoneId(long zoneId) {
+        this.zoneId = zoneId;
+    }
+
+    public String getZoneUuid() {
+        return zoneUuid;
+    }
+
+    public void setZoneUuid(String zoneUuid) {
+        this.zoneUuid = zoneUuid;
+    }
+
+    public String getZoneName() {
+        return zoneName;
+    }
+
+    public void setZoneName(String zoneName) {
+        this.zoneName = zoneName;
+    }
+
+    public String getUrl() {
+        return url;
+    }
+
+    public void setUrl(String url) {
+        this.url = url;
+    }
+
+    public String getProtocol() {
+        return protocol;
+    }
+
+    public void setProtocol(String protocol) {
+        this.protocol = protocol;
+    }
+
+    public String getProviderName() {
+        return providerName;
+    }
+
+    public void setProviderName(String providerName) {
+        this.providerName = providerName;
+    }
+
+    public ScopeType getScope() {
+        return scope;
+    }
+
+    public void setScope(ScopeType scope) {
+        this.scope = scope;
+    }
+
+    public long getRegionId() {
+        return regionId;
+    }
+
+    public void setRegionId(long regionId) {
+        this.regionId = regionId;
+    }
+
+    public String getRegionName() {
+        return regionName;
+    }
+
+    public void setRegionName(String regionName) {
+        this.regionName = regionName;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getDetailName() {
+        return detailName;
+    }
+
+    public void setDetailName(String detailName) {
+        this.detailName = detailName;
+    }
+
+    public String getDetailValue() {
+        return detailValue;
+    }
+
+    public void setDetailValue(String detailValue) {
+        this.detailValue = detailValue;
+    }
+
+
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/7699485b/server/src/com/cloud/storage/dao/ImageDataStoreDaoImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/storage/dao/ImageDataStoreDaoImpl.java b/server/src/com/cloud/storage/dao/ImageDataStoreDaoImpl.java
new file mode 100644
index 0000000..1b3fa46
--- /dev/null
+++ b/server/src/com/cloud/storage/dao/ImageDataStoreDaoImpl.java
@@ -0,0 +1,75 @@
+// 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 com.cloud.storage.dao;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.ejb.Local;
+
+import org.apache.cloudstack.storage.datastore.db.ImageDataStoreDetailVO;
+import org.apache.cloudstack.storage.datastore.db.ImageDataStoreDetailsDao;
+import org.springframework.stereotype.Component;
+
+import com.cloud.utils.db.GenericDaoBase;
+import com.cloud.utils.db.SearchBuilder;
+import com.cloud.utils.db.SearchCriteria;
+import com.cloud.utils.db.Transaction;
+
+@Component
+@Local(value=ImageDataStoreDetailsDao.class)
+public class ImageDataStoreDaoImpl extends GenericDaoBase<ImageDataStoreDetailVO, Long> implements ImageDataStoreDetailsDao {
+
+    protected final SearchBuilder<ImageDataStoreDetailVO> storeSearch;
+
+    protected ImageDataStoreDaoImpl() {
+        super();
+        storeSearch = createSearchBuilder();
+        storeSearch.and("store", storeSearch.entity().getStoreId(), SearchCriteria.Op.EQ);
+        storeSearch.done();
+    }
+
+    @Override
+    public void update(long storeId, Map<String, String> details) {
+        Transaction txn = Transaction.currentTxn();
+        SearchCriteria<ImageDataStoreDetailVO> sc = storeSearch.create();
+        sc.setParameters("store", storeId);
+
+        txn.start();
+        expunge(sc);
+        for (Map.Entry<String, String> entry : details.entrySet()) {
+            ImageDataStoreDetailVO detail = new ImageDataStoreDetailVO(storeId, entry.getKey(), entry.getValue());
+            persist(detail);
+        }
+        txn.commit();
+    }
+
+    @Override
+    public Map<String, String> getDetails(long storeId) {
+    	SearchCriteria<ImageDataStoreDetailVO> sc = storeSearch.create();
+    	sc.setParameters("store", storeId);
+
+    	List<ImageDataStoreDetailVO> details = listBy(sc);
+    	Map<String, String> detailsMap = new HashMap<String, String>();
+    	for (ImageDataStoreDetailVO detail : details) {
+    		detailsMap.put(detail.getName(), detail.getValue());
+    	}
+
+    	return detailsMap;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/7699485b/setup/db/db/schema-410to420.sql
----------------------------------------------------------------------
diff --git a/setup/db/db/schema-410to420.sql b/setup/db/db/schema-410to420.sql
index da5d5d5..ed95461 100644
--- a/setup/db/db/schema-410to420.sql
+++ b/setup/db/db/schema-410to420.sql
@@ -91,7 +91,33 @@ CREATE TABLE `cloud`.`image_data_store_details` (
   INDEX `i_image_data_store__name__value`(`name`(128), `value`(128))
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
 
-
+DROP VIEW IF EXISTS `cloud`.`image_data_store_view`;
+CREATE VIEW `cloud`.`image_data_store_view` AS
+    select 
+        image_data_store.id,
+        image_data_store.uuid,
+        image_data_store.name,
+        image_data_store.provider_name,
+        image_data_store.protocol,
+        image_data_store.url,
+        image_data_store.scope,
+        data_center.id data_center_id,
+        data_center.uuid data_center_uuid,
+        data_center.name data_center_name,
+        region.id region_id,
+        region.name region_name,
+        image_data_store_details.name detail_name,
+        image_data_store_details.value detail_value
+    from
+        `cloud`.`image_data_store`
+            left join
+        `cloud`.`data_center` ON image_data_store.data_center_id = data_center.id
+            left join
+        `cloud`.`region` ON image_data_store.region_id = region.id
+            left join
+        `cloud`.`image_data_store_details` ON image_data_store_details.store_id = image_data_store.id;
+            
+            
 CREATE TABLE  `cloud`.`template_store_ref` (
   `id` bigint unsigned NOT NULL auto_increment,
   `store_id` bigint unsigned NOT NULL,