Skip to content

Commit 7e030ee

Browse files
committed
volume upload: persisting the template metadata
on calling GetUploadParamsForTemplate, persisting the metadata to db validating the account limits and incrementing the appropriate limits encoded the metadata on management server using preshared key
1 parent b963bb1 commit 7e030ee

10 files changed

Lines changed: 297 additions & 34 deletions

File tree

api/src/com/cloud/template/TemplateApiService.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
// under the License.
1717
package com.cloud.template;
1818

19+
import java.net.MalformedURLException;
1920
import java.net.URISyntaxException;
2021
import java.util.List;
2122

@@ -29,6 +30,7 @@
2930
import org.apache.cloudstack.api.command.user.template.CreateTemplateCmd;
3031
import org.apache.cloudstack.api.command.user.template.DeleteTemplateCmd;
3132
import org.apache.cloudstack.api.command.user.template.ExtractTemplateCmd;
33+
import org.apache.cloudstack.api.command.user.template.GetUploadParamsForTemplate;
3234
import org.apache.cloudstack.api.command.user.template.RegisterTemplateCmd;
3335
import org.apache.cloudstack.api.command.user.template.UpdateTemplateCmd;
3436

@@ -37,11 +39,14 @@
3739
import com.cloud.exception.StorageUnavailableException;
3840
import com.cloud.user.Account;
3941
import com.cloud.utils.exception.CloudRuntimeException;
42+
import org.apache.cloudstack.api.response.GetUploadParamsResponse;
4043

4144
public interface TemplateApiService {
4245

4346
VirtualMachineTemplate registerTemplate(RegisterTemplateCmd cmd) throws URISyntaxException, ResourceAllocationException;
4447

48+
public GetUploadParamsResponse registerTemplateForPostUpload(GetUploadParamsForTemplate cmd) throws ResourceAllocationException, MalformedURLException;
49+
4550
VirtualMachineTemplate registerIso(RegisterIsoCmd cmd) throws IllegalArgumentException, ResourceAllocationException;
4651

4752
VirtualMachineTemplate copyTemplate(CopyTemplateCmd cmd) throws StorageUnavailableException, ResourceAllocationException;

api/src/org/apache/cloudstack/api/command/user/template/GetUploadParamsForTemplate.java

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,10 @@
1919
package org.apache.cloudstack.api.command.user.template;
2020

2121
import java.net.MalformedURLException;
22-
import java.net.URL;
2322
import java.util.Collection;
2423
import java.util.Map;
25-
import java.util.UUID;
2624

25+
import com.cloud.exception.ResourceAllocationException;
2726
import org.apache.cloudstack.api.APICommand;
2827
import org.apache.cloudstack.api.AbstractGetUploadParamsCommand;
2928
import org.apache.cloudstack.api.ApiConstants;
@@ -109,35 +108,35 @@ public Map getDetails() {
109108
return params;
110109
}
111110

112-
public Boolean getIsDynamicallyScalable() {
111+
public Boolean isDynamicallyScalable() {
113112
return isDynamicallyScalable;
114113
}
115114

116-
public Boolean getExtractable() {
115+
public Boolean isExtractable() {
117116
return extractable;
118117
}
119118

120-
public Boolean getFeatured() {
119+
public Boolean isFeatured() {
121120
return featured;
122121
}
123122

124-
public Boolean getPublicTemplate() {
123+
public Boolean isPublic() {
125124
return publicTemplate;
126125
}
127126

128-
public Boolean getIsRoutingType() {
127+
public Boolean isRoutingType() {
129128
return isRoutingType;
130129
}
131130

132-
public Boolean getPasswordEnabled() {
131+
public Boolean isPasswordEnabled() {
133132
return passwordEnabled;
134133
}
135134

136135
public Boolean getRequiresHvm() {
137136
return requiresHvm;
138137
}
139138

140-
public Boolean getSshKeyEnabled() {
139+
public Boolean isSshKeyEnabled() {
141140
return sshKeyEnabled;
142141
}
143142

@@ -147,17 +146,13 @@ public String getTemplateTag() {
147146

148147
@Override
149148
public void execute() throws ServerApiException {
150-
// TODO Auto-generated method stub
151149
try {
152-
GetUploadParamsResponse response = createGetUploadParamsResponse(
153-
UUID.fromString("C7D351D2-F167-4CC8-A9FF-3BECB0A625C4"),
154-
new URL("https://1-2-3-4.xyz.com/upload/C7D351D2-F167-4CC8-A9FF-3BECB0A625C4"),
155-
"TKPFeuz2nHmE/kcREEu24mnj1MrLdzOeJIHXR9HLIGgk56bkRJHaD0RRL2lds1rKKhrro4/PuleEh4YhRinhxaAmPpU4e55eprG8gTCX0ItyFAtlZViVdKXMew5Dfp4Qg8W9I1/IsDJd2Kas9/ftDQLiemAlPt0uS7Ou6asOCpifnBaKvhM4UGEjHSnni1KhBzjgEyDW3Y42HKJSSv58Sgmxl9LCewBX8vtn9tXKr+j4afj7Jlh7DFhyo9HOPC5ogR4hPBKqP7xF9tHxAyq6YqfBzsng3Xwe+Pb8TU1kFHg1l2DM4tY6ooW2h8lOhWUkrJu4hOAOeTeRtCjW3H452NKoeA1M8pKWuqMo5zRMti2u2hNZs0YY2yOy8oWMMG+lG0hvIlajqEU=",
156-
"2014-10-17T12:00:00+0530", "de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9");
150+
GetUploadParamsResponse response = _templateService.registerTemplateForPostUpload(this);
157151
response.setResponseName(getCommandName());
158152
setResponseObject(response);
159-
} catch (MalformedURLException e) {
160-
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "malformedurl exception: " + e.getMessage());
153+
} catch (ResourceAllocationException | MalformedURLException e) {
154+
s_logger.error("exception while registering template", e);
155+
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "exception while registering template: " + e.getMessage());
161156
}
162157
}
163158

api/src/org/apache/cloudstack/api/response/GetUploadParamsResponse.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ public GetUploadParamsResponse(UUID id, URL postURL, String metadata, String tim
5757
setObjectName("getuploadparams");
5858
}
5959

60+
public GetUploadParamsResponse() {
61+
}
62+
6063
public void setId(UUID id) {
6164
this.id = id;
6265
}

core/pom.xml

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -55,21 +55,7 @@
5555
<groupId>org.apache.maven.plugins</groupId>
5656
<artifactId>maven-pmd-plugin</artifactId>
5757
</plugin>
58-
<plugin>
59-
<groupId>com.mycila</groupId>
60-
<artifactId>license-maven-plugin</artifactId>
61-
<executions>
62-
<execution>
63-
<id>cloudstack-checklicence</id>
64-
<phase>process-classes</phase>
65-
<goals>
66-
<goal>check</goal>
67-
</goals>
68-
</execution>
69-
</executions>
70-
</plugin>
7158
</plugins>
72-
7359
</build>
7460

7561
</project>
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package org.apache.cloudstack.storage.command;
21+
22+
import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
23+
import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint;
24+
25+
public class TemplateOrVolumePostUploadCommand {
26+
DataObject dataObject;
27+
EndPoint endPoint;
28+
29+
public TemplateOrVolumePostUploadCommand(DataObject dataObject, EndPoint endPoint) {
30+
this.dataObject = dataObject;
31+
this.endPoint = endPoint;
32+
}
33+
34+
public DataObject getDataObject() {
35+
return dataObject;
36+
}
37+
38+
public void setDataObject(DataObject dataObject) {
39+
this.dataObject = dataObject;
40+
}
41+
42+
public EndPoint getEndPoint() {
43+
return endPoint;
44+
}
45+
46+
public void setEndPoint(EndPoint endPoint) {
47+
this.endPoint = endPoint;
48+
}
49+
50+
@Override
51+
public boolean equals(Object o) {
52+
if (this == o) {
53+
return true;
54+
}
55+
if (o == null || getClass() != o.getClass()) {
56+
return false;
57+
}
58+
59+
TemplateOrVolumePostUploadCommand that = (TemplateOrVolumePostUploadCommand) o;
60+
61+
return dataObject.equals(that.dataObject) && endPoint.equals(that.endPoint);
62+
63+
}
64+
65+
@Override
66+
public int hashCode() {
67+
int result = dataObject.hashCode();
68+
result = 31 * result + endPoint.hashCode();
69+
return result;
70+
}
71+
72+
@Override public String toString() {
73+
return "TemplateOrVolumePostUploadCommand{" +
74+
"dataObject=" + dataObject +
75+
", endPoint=" + endPoint +
76+
'}';
77+
}
78+
}

plugins/hypervisors/baremetal/src/com/cloud/baremetal/manager/BareMetalTemplateAdapter.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
import org.apache.cloudstack.api.command.user.iso.DeleteIsoCmd;
4242
import org.apache.cloudstack.api.command.user.iso.RegisterIsoCmd;
4343
import org.apache.cloudstack.api.command.user.template.RegisterTemplateCmd;
44+
import org.apache.cloudstack.storage.command.TemplateOrVolumePostUploadCommand;
4445
import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO;
4546
import org.apache.log4j.Logger;
4647

@@ -104,6 +105,12 @@ public VMTemplateVO create(TemplateProfile profile) {
104105
return template;
105106
}
106107

108+
@Override
109+
public List<TemplateOrVolumePostUploadCommand> createTemplateForPostUpload(TemplateProfile profile) {
110+
// TODO: support baremetal for postupload
111+
return null;
112+
}
113+
107114
@Override
108115
public TemplateProfile prepareDelete(DeleteIsoCmd cmd) {
109116
throw new CloudRuntimeException("Baremetal doesn't support ISO, how the delete get here???");

server/src/com/cloud/template/HypervisorTemplateAdapter.java

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,18 @@
1818

1919
import java.util.Collections;
2020
import java.util.HashSet;
21+
import java.util.LinkedList;
2122
import java.util.List;
2223
import java.util.Set;
2324
import java.util.concurrent.ExecutionException;
2425

2526
import javax.ejb.Local;
2627
import javax.inject.Inject;
2728

29+
import org.apache.cloudstack.api.command.user.template.GetUploadParamsForTemplate;
30+
import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
31+
import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint;
32+
import org.apache.cloudstack.storage.command.TemplateOrVolumePostUploadCommand;
2833
import org.apache.log4j.Logger;
2934

3035
import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao;
@@ -131,6 +136,15 @@ public TemplateProfile prepare(RegisterTemplateCmd cmd) throws ResourceAllocatio
131136
return profile;
132137
}
133138

139+
@Override
140+
public TemplateProfile prepare(GetUploadParamsForTemplate cmd) throws ResourceAllocationException {
141+
TemplateProfile profile = super.prepare(cmd);
142+
143+
// Check that the resource limit for secondary storage won't be exceeded
144+
_resourceLimitMgr.checkResourceLimit(_accountMgr.getAccount(cmd.getEntityOwnerId()), ResourceType.secondary_storage);
145+
return profile;
146+
}
147+
134148
@Override
135149
public VMTemplateVO create(TemplateProfile profile) {
136150
// persist entry in vm_template, vm_template_details and template_zone_ref tables, not that entry at template_store_ref is not created here, and created in createTemplateAsync.
@@ -185,6 +199,70 @@ public VMTemplateVO create(TemplateProfile profile) {
185199
return template;
186200
}
187201

202+
@Override
203+
public List<TemplateOrVolumePostUploadCommand> createTemplateForPostUpload(TemplateProfile profile) {
204+
// persist entry in vm_template, vm_template_details and template_zone_ref tables, not that entry at template_store_ref is not created here, and created in createTemplateAsync.
205+
VMTemplateVO template = persistTemplate(profile);
206+
207+
if (template == null) {
208+
throw new CloudRuntimeException("Unable to persist the template " + profile.getTemplate());
209+
}
210+
211+
// find all eligible image stores for this zone scope
212+
List<DataStore> imageStores = storeMgr.getImageStoresByScope(new ZoneScope(profile.getZoneId()));
213+
if (imageStores == null || imageStores.size() == 0) {
214+
throw new CloudRuntimeException("Unable to find image store to download template " + profile.getTemplate());
215+
}
216+
217+
List<TemplateOrVolumePostUploadCommand> payloads = new LinkedList<>();
218+
Set<Long> zoneSet = new HashSet<Long>();
219+
Collections.shuffle(imageStores); // For private templates choose a random store. TODO - Have a better algorithm based on size, no. of objects, load etc.
220+
for (DataStore imageStore : imageStores) {
221+
// skip data stores for a disabled zone
222+
Long zoneId = imageStore.getScope().getScopeId();
223+
if (zoneId != null) {
224+
DataCenterVO zone = _dcDao.findById(zoneId);
225+
if (zone == null) {
226+
s_logger.warn("Unable to find zone by id " + zoneId + ", so skip downloading template to its image store " + imageStore.getId());
227+
continue;
228+
}
229+
230+
// Check if zone is disabled
231+
if (Grouping.AllocationState.Disabled == zone.getAllocationState()) {
232+
s_logger.info("Zone " + zoneId + " is disabled, so skip downloading template to its image store " + imageStore.getId());
233+
continue;
234+
}
235+
236+
// We want to download private template to one of the image store in a zone
237+
if (isPrivateTemplate(template) && zoneSet.contains(zoneId)) {
238+
continue;
239+
} else {
240+
zoneSet.add(zoneId);
241+
}
242+
243+
}
244+
245+
TemplateInfo tmpl = imageFactory.getTemplate(template.getId(), imageStore);
246+
//imageService.createTemplateAsync(tmpl, imageStore, caller);
247+
248+
// persist template_store_ref entry
249+
DataObject templateOnStore = imageStore.create(tmpl);
250+
// update template_store_ref and template state
251+
252+
EndPoint ep = _epSelector.select(templateOnStore);
253+
if (ep == null) {
254+
String errMsg = "There is no secondary storage VM for downloading template to image store " + imageStore.getName();
255+
s_logger.warn(errMsg);
256+
throw new CloudRuntimeException(errMsg);
257+
}
258+
259+
TemplateOrVolumePostUploadCommand payload = new TemplateOrVolumePostUploadCommand(templateOnStore, ep);
260+
payloads.add(payload);
261+
}
262+
_resourceLimitMgr.incrementResourceCount(profile.getAccountId(), ResourceType.template);
263+
return payloads;
264+
}
265+
188266
private boolean isPrivateTemplate(VMTemplateVO template){
189267

190268
// if public OR featured OR system template

server/src/com/cloud/template/TemplateAdapter.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,14 @@
1616
// under the License.
1717
package com.cloud.template;
1818

19+
import java.util.List;
1920
import java.util.Map;
2021

2122
import org.apache.cloudstack.api.command.user.iso.DeleteIsoCmd;
2223
import org.apache.cloudstack.api.command.user.iso.RegisterIsoCmd;
2324
import org.apache.cloudstack.api.command.user.template.DeleteTemplateCmd;
2425
import org.apache.cloudstack.api.command.user.template.ExtractTemplateCmd;
26+
import org.apache.cloudstack.api.command.user.template.GetUploadParamsForTemplate;
2527
import org.apache.cloudstack.api.command.user.template.RegisterTemplateCmd;
2628

2729
import com.cloud.exception.ResourceAllocationException;
@@ -31,6 +33,7 @@
3133
import com.cloud.storage.VMTemplateVO;
3234
import com.cloud.user.Account;
3335
import com.cloud.utils.component.Adapter;
36+
import org.apache.cloudstack.storage.command.TemplateOrVolumePostUploadCommand;
3437

3538
public interface TemplateAdapter extends Adapter {
3639
public static class TemplateAdapterType {
@@ -50,10 +53,14 @@ public String getName() {
5053

5154
public TemplateProfile prepare(RegisterTemplateCmd cmd) throws ResourceAllocationException;
5255

56+
public TemplateProfile prepare(GetUploadParamsForTemplate cmd) throws ResourceAllocationException;
57+
5358
public TemplateProfile prepare(RegisterIsoCmd cmd) throws ResourceAllocationException;
5459

5560
public VMTemplateVO create(TemplateProfile profile);
5661

62+
public List<TemplateOrVolumePostUploadCommand> createTemplateForPostUpload(TemplateProfile profile);
63+
5764
public TemplateProfile prepareDelete(DeleteTemplateCmd cmd);
5865

5966
public TemplateProfile prepareDelete(DeleteIsoCmd cmd);

0 commit comments

Comments
 (0)