Skip to content

Commit 0ca267f

Browse files
authored
Allow uploading of ISO for creating kubernetes supported versions (#9561)
1 parent 8464e46 commit 0ca267f

File tree

10 files changed

+414
-49
lines changed

10 files changed

+414
-49
lines changed

api/src/main/java/org/apache/cloudstack/api/AbstractGetUploadParamsCmd.java

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,34 @@ public Long getProjectId() {
8181
return projectId;
8282
}
8383

84+
public void setName(String name) {
85+
this.name = name;
86+
}
87+
88+
public void setFormat(String format) {
89+
this.format = format;
90+
}
91+
92+
public void setZoneId(Long zoneId) {
93+
this.zoneId = zoneId;
94+
}
95+
96+
public void setChecksum(String checksum) {
97+
this.checksum = checksum;
98+
}
99+
100+
public void setAccountName(String accountName) {
101+
this.accountName = accountName;
102+
}
103+
104+
public void setDomainId(Long domainId) {
105+
this.domainId = domainId;
106+
}
107+
108+
public void setProjectId(Long projectId) {
109+
this.projectId = projectId;
110+
}
111+
84112
public GetUploadParamsResponse createGetUploadParamsResponse(UUID id, URL postURL, String metadata, String timeout, String signature) {
85113
return new GetUploadParamsResponse(id, postURL, metadata, timeout, signature);
86114
}

api/src/main/java/org/apache/cloudstack/api/command/user/iso/GetUploadParamsForIsoCmd.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,29 @@ public Long getOsTypeId() {
104104
return osTypeId;
105105
}
106106

107+
public void setBootable(Boolean bootable) {
108+
this.bootable = bootable;
109+
}
110+
111+
public void setDisplayText(String displayText) {
112+
this.displayText = displayText;
113+
}
114+
115+
public void setFeatured(Boolean featured) {
116+
this.featured = featured;
117+
}
118+
119+
public void setPublicIso(Boolean publicIso) {
120+
this.publicIso = publicIso;
121+
}
122+
123+
public void setExtractable(Boolean extractable) {
124+
this.extractable = extractable;
125+
}
126+
127+
public void setOsTypeId(Long osTypeId) {
128+
this.osTypeId = osTypeId;
129+
}
107130

108131
/////////////////////////////////////////////////////
109132
/////////////// API Implementation///////////////////

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,10 @@ public GetUploadParamsResponse() {
6262
setObjectName("getuploadparams");
6363
}
6464

65+
public UUID getId() {
66+
return id;
67+
}
68+
6569
public void setId(UUID id) {
6670
this.id = id;
6771
}

plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/version/KubernetesVersionManagerImpl.java

Lines changed: 79 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
package com.cloud.kubernetes.version;
1919

20+
import java.net.MalformedURLException;
2021
import java.util.ArrayList;
2122
import java.util.List;
2223

@@ -26,10 +27,13 @@
2627
import org.apache.cloudstack.api.ApiConstants;
2728
import org.apache.cloudstack.api.command.admin.kubernetes.version.AddKubernetesSupportedVersionCmd;
2829
import org.apache.cloudstack.api.command.admin.kubernetes.version.DeleteKubernetesSupportedVersionCmd;
30+
import org.apache.cloudstack.api.command.admin.kubernetes.version.GetUploadParamsForKubernetesSupportedVersionCmd;
2931
import org.apache.cloudstack.api.command.admin.kubernetes.version.UpdateKubernetesSupportedVersionCmd;
3032
import org.apache.cloudstack.api.command.user.iso.DeleteIsoCmd;
33+
import org.apache.cloudstack.api.command.user.iso.GetUploadParamsForIsoCmd;
3134
import org.apache.cloudstack.api.command.user.iso.RegisterIsoCmd;
3235
import org.apache.cloudstack.api.command.user.kubernetes.version.ListKubernetesSupportedVersionsCmd;
36+
import org.apache.cloudstack.api.response.GetUploadParamsResponse;
3337
import org.apache.cloudstack.api.response.KubernetesSupportedVersionResponse;
3438
import org.apache.cloudstack.api.response.ListResponse;
3539
import org.apache.cloudstack.context.CallContext;
@@ -162,6 +166,33 @@ private List <KubernetesSupportedVersionVO> filterKubernetesSupportedVersions(Li
162166
return versions;
163167
}
164168

169+
private GetUploadParamsResponse registerKubernetesVersionIsoForUpload(final Long zoneId, final String versionName, final String isoChecksum) {
170+
CallContext.register(CallContext.current(), ApiCommandResourceType.Iso);
171+
String isoName = String.format("%s-Kubernetes-Binaries-ISO", versionName);
172+
GetUploadParamsForIsoCmd uploadIso = new GetUploadParamsForIsoCmd();
173+
uploadIso = ComponentContext.inject(uploadIso);
174+
uploadIso.setName(isoName);
175+
uploadIso.setPublicIso(true);
176+
if (zoneId != null) {
177+
uploadIso.setZoneId(zoneId);
178+
}
179+
uploadIso.setDisplayText(isoName);
180+
uploadIso.setBootable(false);
181+
if (StringUtils.isNotEmpty(isoChecksum)) {
182+
uploadIso.setChecksum(isoChecksum);
183+
}
184+
uploadIso.setAccountName(accountManager.getSystemAccount().getAccountName());
185+
uploadIso.setDomainId(accountManager.getSystemAccount().getDomainId());
186+
try {
187+
return templateService.registerIsoForPostUpload(uploadIso);
188+
} catch (MalformedURLException | ResourceAllocationException e) {
189+
logger.error(String.format("Unable to register binaries ISO for supported kubernetes version, %s", versionName), e);
190+
throw new CloudRuntimeException(String.format("Unable to register binaries ISO for supported kubernetes version, %s", versionName), e);
191+
} finally {
192+
CallContext.unregister();
193+
}
194+
}
195+
165196
private VirtualMachineTemplate registerKubernetesVersionIso(final Long zoneId, final String versionName, final String isoUrl, final String isoChecksum, final boolean directDownload, CPU.CPUArch arch) throws IllegalAccessException, NoSuchFieldException,
166197
IllegalArgumentException, ResourceAllocationException {
167198
CallContext.register(CallContext.current(), ApiCommandResourceType.Iso);
@@ -316,23 +347,8 @@ public ListResponse<KubernetesSupportedVersionResponse> listKubernetesSupportedV
316347
return createKubernetesSupportedVersionListResponse(versions, versionsAndCount.second());
317348
}
318349

319-
@Override
320-
@ActionEvent(eventType = KubernetesVersionEventTypes.EVENT_KUBERNETES_VERSION_ADD,
321-
eventDescription = "Adding Kubernetes supported version")
322-
public KubernetesSupportedVersionResponse addKubernetesSupportedVersion(final AddKubernetesSupportedVersionCmd cmd) {
323-
if (!KubernetesClusterService.KubernetesServiceEnabled.value()) {
324-
throw new CloudRuntimeException("Kubernetes Service plugin is disabled");
325-
}
326-
String name = cmd.getName();
327-
final String semanticVersion = cmd.getSemanticVersion();
328-
final Long zoneId = cmd.getZoneId();
329-
final String isoUrl = cmd.getUrl();
330-
final String isoChecksum = cmd.getChecksum();
331-
final Integer minimumCpu = cmd.getMinimumCpu();
332-
final Integer minimumRamSize = cmd.getMinimumRamSize();
333-
final boolean isDirectDownload = cmd.isDirectDownload();
334-
CPU.CPUArch arch = cmd.getArch();
335-
350+
private void validateKubernetesSupportedVersion(Long zoneId, String semanticVersion, Integer minimumCpu,
351+
Integer minimumRamSize, boolean isDirectDownload) {
336352
if (minimumCpu == null || minimumCpu < KubernetesClusterService.MIN_KUBERNETES_CLUSTER_NODE_CPU) {
337353
throw new InvalidParameterValueException(String.format("Invalid value for %s parameter. Minimum %d vCPUs required.", ApiConstants.MIN_CPU_NUMBER, KubernetesClusterService.MIN_KUBERNETES_CLUSTER_NODE_CPU));
338354
}
@@ -351,6 +367,27 @@ public KubernetesSupportedVersionResponse addKubernetesSupportedVersion(final Ad
351367
throw new InvalidParameterValueException(String.format("Zone: %s supports only direct download Kubernetes versions", zone.getName()));
352368
}
353369
}
370+
}
371+
372+
@Override
373+
@ActionEvent(eventType = KubernetesVersionEventTypes.EVENT_KUBERNETES_VERSION_ADD,
374+
eventDescription = "Adding Kubernetes supported version")
375+
public KubernetesSupportedVersionResponse addKubernetesSupportedVersion(final AddKubernetesSupportedVersionCmd cmd) {
376+
if (!KubernetesClusterService.KubernetesServiceEnabled.value()) {
377+
throw new CloudRuntimeException("Kubernetes Service plugin is disabled");
378+
}
379+
String name = cmd.getName();
380+
final String semanticVersion = cmd.getSemanticVersion();
381+
final Long zoneId = cmd.getZoneId();
382+
final String isoUrl = cmd.getUrl();
383+
final String isoChecksum = cmd.getChecksum();
384+
final Integer minimumCpu = cmd.getMinimumCpu();
385+
final Integer minimumRamSize = cmd.getMinimumRamSize();
386+
final boolean isDirectDownload = cmd.isDirectDownload();
387+
CPU.CPUArch arch = cmd.getArch();
388+
389+
validateKubernetesSupportedVersion(zoneId, semanticVersion, minimumCpu, minimumRamSize, isDirectDownload);
390+
354391
if (StringUtils.isEmpty(isoUrl)) {
355392
throw new InvalidParameterValueException(String.format("Invalid URL for ISO specified, %s", isoUrl));
356393
}
@@ -377,6 +414,30 @@ public KubernetesSupportedVersionResponse addKubernetesSupportedVersion(final Ad
377414
return createKubernetesSupportedVersionResponse(supportedVersionVO);
378415
}
379416

417+
@Override
418+
public GetUploadParamsResponse registerKubernetesSupportedVersionForPostUpload(GetUploadParamsForKubernetesSupportedVersionCmd cmd) {
419+
if (!KubernetesClusterService.KubernetesServiceEnabled.value()) {
420+
throw new CloudRuntimeException("Kubernetes Service plugin is disabled");
421+
}
422+
String name = cmd.getName();
423+
final String semanticVersion = cmd.getSemanticVersion();
424+
final Long zoneId = cmd.getZoneId();
425+
final String isoChecksum = cmd.getChecksum();
426+
final Integer minimumCpu = cmd.getMinimumCpu();
427+
final Integer minimumRamSize = cmd.getMinimumRamSize();
428+
429+
validateKubernetesSupportedVersion(zoneId, semanticVersion, minimumCpu, minimumRamSize, false);
430+
431+
GetUploadParamsResponse response = registerKubernetesVersionIsoForUpload(zoneId, name, isoChecksum);
432+
433+
VMTemplateVO template = templateDao.findByUuid(response.getId().toString());
434+
KubernetesSupportedVersionVO supportedVersionVO = new KubernetesSupportedVersionVO(name, semanticVersion, template.getId(), zoneId, minimumCpu, minimumRamSize);
435+
supportedVersionVO = kubernetesSupportedVersionDao.persist(supportedVersionVO);
436+
CallContext.current().putContextParameter(KubernetesSupportedVersion.class, supportedVersionVO.getUuid());
437+
438+
return response;
439+
}
440+
380441
@Override
381442
@ActionEvent(eventType = KubernetesVersionEventTypes.EVENT_KUBERNETES_VERSION_DELETE,
382443
eventDescription = "deleting Kubernetes supported version", async = true)
@@ -445,6 +506,7 @@ public List<Class<?>> getCommands() {
445506
return cmdList;
446507
}
447508
cmdList.add(AddKubernetesSupportedVersionCmd.class);
509+
cmdList.add(GetUploadParamsForKubernetesSupportedVersionCmd.class);
448510
cmdList.add(ListKubernetesSupportedVersionsCmd.class);
449511
cmdList.add(DeleteKubernetesSupportedVersionCmd.class);
450512
cmdList.add(UpdateKubernetesSupportedVersionCmd.class);

plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/version/KubernetesVersionService.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,10 @@
1919

2020
import org.apache.cloudstack.api.command.admin.kubernetes.version.AddKubernetesSupportedVersionCmd;
2121
import org.apache.cloudstack.api.command.admin.kubernetes.version.DeleteKubernetesSupportedVersionCmd;
22+
import org.apache.cloudstack.api.command.admin.kubernetes.version.GetUploadParamsForKubernetesSupportedVersionCmd;
2223
import org.apache.cloudstack.api.command.admin.kubernetes.version.UpdateKubernetesSupportedVersionCmd;
2324
import org.apache.cloudstack.api.command.user.kubernetes.version.ListKubernetesSupportedVersionsCmd;
25+
import org.apache.cloudstack.api.response.GetUploadParamsResponse;
2426
import org.apache.cloudstack.api.response.KubernetesSupportedVersionResponse;
2527
import org.apache.cloudstack.api.response.ListResponse;
2628

@@ -31,6 +33,7 @@ public interface KubernetesVersionService extends PluggableService {
3133
static final String MIN_KUBERNETES_VERSION = "1.11.0";
3234
ListResponse<KubernetesSupportedVersionResponse> listKubernetesSupportedVersions(ListKubernetesSupportedVersionsCmd cmd);
3335
KubernetesSupportedVersionResponse addKubernetesSupportedVersion(AddKubernetesSupportedVersionCmd cmd) throws CloudRuntimeException;
36+
GetUploadParamsResponse registerKubernetesSupportedVersionForPostUpload(GetUploadParamsForKubernetesSupportedVersionCmd cmd);
3437
boolean deleteKubernetesSupportedVersion(DeleteKubernetesSupportedVersionCmd cmd) throws CloudRuntimeException;
3538
KubernetesSupportedVersionResponse updateKubernetesSupportedVersion(UpdateKubernetesSupportedVersionCmd cmd) throws CloudRuntimeException;
3639
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
package org.apache.cloudstack.api.command.admin.kubernetes.version;
19+
20+
import com.cloud.exception.ConcurrentOperationException;
21+
import com.cloud.exception.InvalidParameterValueException;
22+
import com.cloud.kubernetes.version.KubernetesSupportedVersion;
23+
import com.cloud.kubernetes.version.KubernetesVersionService;
24+
import com.cloud.utils.exception.CloudRuntimeException;
25+
import org.apache.cloudstack.acl.RoleType;
26+
import org.apache.cloudstack.api.APICommand;
27+
import org.apache.cloudstack.api.AbstractGetUploadParamsCmd;
28+
import org.apache.cloudstack.api.ApiCommandResourceType;
29+
import org.apache.cloudstack.api.ApiConstants;
30+
import org.apache.cloudstack.api.ApiErrorCode;
31+
import org.apache.cloudstack.api.Parameter;
32+
import org.apache.cloudstack.api.ResponseObject;
33+
import org.apache.cloudstack.api.ServerApiException;
34+
import org.apache.cloudstack.api.command.admin.AdminCmd;
35+
import org.apache.cloudstack.api.response.GetUploadParamsResponse;
36+
import org.apache.cloudstack.api.response.KubernetesSupportedVersionResponse;
37+
import org.apache.cloudstack.context.CallContext;
38+
import org.apache.commons.lang3.StringUtils;
39+
40+
import javax.inject.Inject;
41+
42+
@APICommand(name = "getUploadParamsForKubernetesSupportedVersion",
43+
description = "Upload a supported Kubernetes version",
44+
responseObject = KubernetesSupportedVersionResponse.class,
45+
responseView = ResponseObject.ResponseView.Full,
46+
entityType = {KubernetesSupportedVersion.class},
47+
authorized = {RoleType.Admin})
48+
public class GetUploadParamsForKubernetesSupportedVersionCmd extends AbstractGetUploadParamsCmd implements AdminCmd {
49+
50+
@Inject
51+
private KubernetesVersionService kubernetesVersionService;
52+
53+
/////////////////////////////////////////////////////
54+
//////////////// API parameters /////////////////////
55+
/////////////////////////////////////////////////////
56+
@Parameter(name = ApiConstants.SEMANTIC_VERSION, type = CommandType.STRING, required = true,
57+
description = "the semantic version of the Kubernetes version. It needs to be specified in MAJOR.MINOR.PATCH format")
58+
private String semanticVersion;
59+
60+
@Parameter(name = ApiConstants.CHECKSUM, type = CommandType.STRING,
61+
description = "the checksum value of the binaries ISO. " + ApiConstants.CHECKSUM_PARAMETER_PREFIX_DESCRIPTION)
62+
private String checksum;
63+
64+
@Parameter(name = ApiConstants.MIN_CPU_NUMBER, type = CommandType.INTEGER, required = true,
65+
description = "the minimum number of CPUs to be set with the Kubernetes version")
66+
private Integer minimumCpu;
67+
68+
@Parameter(name = ApiConstants.MIN_MEMORY, type = CommandType.INTEGER, required = true,
69+
description = "the minimum RAM size in MB to be set with the Kubernetes version")
70+
private Integer minimumRamSize;
71+
72+
/////////////////////////////////////////////////////
73+
/////////////////// Accessors ///////////////////////
74+
/////////////////////////////////////////////////////
75+
76+
public String getSemanticVersion() {
77+
if(StringUtils.isEmpty(semanticVersion)) {
78+
throw new InvalidParameterValueException("Version can not be null");
79+
}
80+
if(!semanticVersion.matches("[0-9]+(\\.[0-9]+)*")) {
81+
throw new IllegalArgumentException("Invalid version format. Semantic version needed");
82+
}
83+
return semanticVersion;
84+
}
85+
86+
public String getChecksum() {
87+
return checksum;
88+
}
89+
90+
public Integer getMinimumCpu() {
91+
return minimumCpu;
92+
}
93+
94+
public Integer getMinimumRamSize() {
95+
return minimumRamSize;
96+
}
97+
98+
@Override
99+
public long getEntityOwnerId() {
100+
return CallContext.current().getCallingAccountId();
101+
}
102+
103+
@Override
104+
public ApiCommandResourceType getApiResourceType() {
105+
return ApiCommandResourceType.KubernetesSupportedVersion;
106+
}
107+
108+
/////////////////////////////////////////////////////
109+
/////////////// API Implementation///////////////////
110+
/////////////////////////////////////////////////////
111+
@Override
112+
public void execute() throws ServerApiException, ConcurrentOperationException {
113+
if (getZoneId() <= 0) {
114+
throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Invalid zoneid");
115+
}
116+
try {
117+
GetUploadParamsResponse response = kubernetesVersionService.registerKubernetesSupportedVersionForPostUpload(this);
118+
if (response == null) {
119+
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to add Kubernetes supported version");
120+
}
121+
response.setResponseName(getCommandName());
122+
setResponseObject(response);
123+
} catch (CloudRuntimeException ex) {
124+
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage());
125+
}
126+
}
127+
}

ui/public/locales/en.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1407,6 +1407,7 @@
14071407
"label.kubernetes.version.add": "Add Kubernetes version",
14081408
"label.kubernetes.version.delete": "Delete Kubernetes version",
14091409
"label.kubernetes.version.update": "Manage Kubernetes version",
1410+
"label.kubernetes.version.from.local": "Add Kubernetes version from local",
14101411
"label.kubernetesversionid": "Kubernetes version",
14111412
"label.kubernetesversionname": "Kubernetes version",
14121413
"label.kvm": "KVM",

ui/src/config/section/image.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,15 @@ export default {
395395
show: isZoneCreated,
396396
component: shallowRef(defineAsyncComponent(() => import('@/views/image/AddKubernetesSupportedVersion.vue')))
397397
},
398+
{
399+
api: 'getUploadParamsForKubernetesSupportedVersion',
400+
icon: 'cloud-upload-outlined',
401+
label: 'label.kubernetes.version.from.local',
402+
listView: true,
403+
popup: true,
404+
show: isZoneCreated,
405+
component: shallowRef(defineAsyncComponent(() => import('@/views/image/AddKubernetesSupportedVersion.vue')))
406+
},
398407
{
399408
api: 'updateKubernetesSupportedVersion',
400409
icon: 'edit-outlined',

0 commit comments

Comments
 (0)