Skip to content

Commit a1a9fb8

Browse files
authored
KVM: Enhancements for direct download feature (#3374)
* Add revoke certificates API * Add background task to sync certificates * Fix marvin test and revoke certificate * Fix certificate sent to hypervisor was missing headers * Fix background task for uploading certificates to hosts
1 parent a1faf09 commit a1a9fb8

File tree

20 files changed

+933
-21
lines changed

20 files changed

+933
-21
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
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+
package org.apache.cloudstack.api.command.admin.direct.download;
20+
21+
import com.cloud.exception.ConcurrentOperationException;
22+
import com.cloud.exception.InsufficientCapacityException;
23+
import com.cloud.exception.NetworkRuleConflictException;
24+
import com.cloud.exception.ResourceAllocationException;
25+
import com.cloud.exception.ResourceUnavailableException;
26+
import org.apache.cloudstack.acl.RoleType;
27+
import org.apache.cloudstack.api.APICommand;
28+
import org.apache.cloudstack.api.ApiConstants;
29+
import org.apache.cloudstack.api.ApiErrorCode;
30+
import org.apache.cloudstack.api.BaseCmd;
31+
import org.apache.cloudstack.api.Parameter;
32+
import org.apache.cloudstack.api.ServerApiException;
33+
import org.apache.cloudstack.api.response.HostResponse;
34+
import org.apache.cloudstack.api.response.SuccessResponse;
35+
import org.apache.cloudstack.api.response.ZoneResponse;
36+
import org.apache.cloudstack.context.CallContext;
37+
import org.apache.cloudstack.direct.download.DirectDownloadManager;
38+
import org.apache.log4j.Logger;
39+
40+
import javax.inject.Inject;
41+
42+
@APICommand(name = RevokeTemplateDirectDownloadCertificateCmd.APINAME,
43+
description = "Revoke a certificate alias from a KVM host",
44+
responseObject = SuccessResponse.class,
45+
requestHasSensitiveInfo = true,
46+
responseHasSensitiveInfo = true,
47+
since = "4.13",
48+
authorized = {RoleType.Admin})
49+
public class RevokeTemplateDirectDownloadCertificateCmd extends BaseCmd {
50+
51+
@Inject
52+
DirectDownloadManager directDownloadManager;
53+
54+
private static final Logger LOG = Logger.getLogger(RevokeTemplateDirectDownloadCertificateCmd.class);
55+
public static final String APINAME = "revokeTemplateDirectDownloadCertificate";
56+
57+
@Parameter(name = ApiConstants.NAME, type = BaseCmd.CommandType.STRING, required = true,
58+
description = "alias of the SSL certificate")
59+
private String certificateAlias;
60+
61+
@Parameter(name = ApiConstants.HYPERVISOR, type = BaseCmd.CommandType.STRING, required = true,
62+
description = "hypervisor type")
63+
private String hypervisor;
64+
65+
@Parameter(name = ApiConstants.ZONE_ID, type = CommandType.UUID, entityType = ZoneResponse.class,
66+
description = "zone to revoke certificate", required = true)
67+
private Long zoneId;
68+
69+
@Parameter(name = ApiConstants.HOST_ID, type = CommandType.UUID, entityType = HostResponse.class,
70+
description = "(optional) the host ID to revoke certificate")
71+
private Long hostId;
72+
73+
@Override
74+
public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException {
75+
if (!hypervisor.equalsIgnoreCase("kvm")) {
76+
throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Currently supporting KVM hosts only");
77+
}
78+
SuccessResponse response = new SuccessResponse(getCommandName());
79+
try {
80+
LOG.debug("Revoking certificate " + certificateAlias + " from " + hypervisor + " hosts");
81+
boolean result = directDownloadManager.revokeCertificateAlias(certificateAlias, hypervisor, zoneId, hostId);
82+
response.setSuccess(result);
83+
setResponseObject(response);
84+
} catch (Exception e) {
85+
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, e.getMessage());
86+
}
87+
}
88+
89+
@Override
90+
public String getCommandName() {
91+
return APINAME.toLowerCase() + BaseCmd.RESPONSE_SUFFIX;
92+
}
93+
94+
@Override
95+
public long getEntityOwnerId() {
96+
return CallContext.current().getCallingAccount().getId();
97+
}
98+
}

api/src/main/java/org/apache/cloudstack/api/command/admin/direct/download/UploadTemplateDirectDownloadCertificateCmd.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,9 @@
2323
import org.apache.cloudstack.api.Parameter;
2424
import org.apache.cloudstack.api.ServerApiException;
2525
import org.apache.cloudstack.api.ApiErrorCode;
26+
import org.apache.cloudstack.api.response.HostResponse;
2627
import org.apache.cloudstack.api.response.SuccessResponse;
28+
import org.apache.cloudstack.api.response.ZoneResponse;
2729
import org.apache.cloudstack.context.CallContext;
2830
import org.apache.cloudstack.direct.download.DirectDownloadManager;
2931
import org.apache.log4j.Logger;
@@ -56,6 +58,14 @@ public class UploadTemplateDirectDownloadCertificateCmd extends BaseCmd {
5658
@Parameter(name = ApiConstants.HYPERVISOR, type = BaseCmd.CommandType.STRING, required = true, description = "Hypervisor type")
5759
private String hypervisor;
5860

61+
@Parameter(name = ApiConstants.ZONE_ID, type = CommandType.UUID, entityType = ZoneResponse.class,
62+
description = "Zone to upload certificate", required = true)
63+
private Long zoneId;
64+
65+
@Parameter(name = ApiConstants.HOST_ID, type = CommandType.UUID, entityType = HostResponse.class,
66+
description = "(optional) the host ID to revoke certificate")
67+
private Long hostId;
68+
5969
@Override
6070
public void execute() {
6171
if (!hypervisor.equalsIgnoreCase("kvm")) {
@@ -64,7 +74,7 @@ public void execute() {
6474

6575
try {
6676
LOG.debug("Uploading certificate " + name + " to agents for Direct Download");
67-
boolean result = directDownloadManager.uploadCertificateToHosts(certificate, name, hypervisor);
77+
boolean result = directDownloadManager.uploadCertificateToHosts(certificate, name, hypervisor, zoneId, hostId);
6878
SuccessResponse response = new SuccessResponse(getCommandName());
6979
response.setSuccess(result);
7080
setResponseObject(response);
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
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+
package org.apache.cloudstack.direct.download;
18+
19+
import com.cloud.hypervisor.Hypervisor;
20+
import org.apache.cloudstack.api.Identity;
21+
import org.apache.cloudstack.api.InternalIdentity;
22+
23+
public interface DirectDownloadCertificate extends InternalIdentity, Identity {
24+
25+
String getCertificate();
26+
String getAlias();
27+
Hypervisor.HypervisorType getHypervisorType();
28+
29+
}

api/src/main/java/org/apache/cloudstack/direct/download/DirectDownloadManager.java

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,21 @@
1919

2020
import com.cloud.utils.component.PluggableService;
2121
import org.apache.cloudstack.framework.agent.direct.download.DirectDownloadService;
22+
import org.apache.cloudstack.framework.config.ConfigKey;
23+
import org.apache.cloudstack.framework.config.Configurable;
2224

23-
public interface DirectDownloadManager extends DirectDownloadService, PluggableService {
25+
public interface DirectDownloadManager extends DirectDownloadService, PluggableService, Configurable {
2426

27+
ConfigKey<Long> DirectDownloadCertificateUploadInterval = new ConfigKey<>("Advanced", Long.class,
28+
"direct.download.certificate.background.task.interval",
29+
"0",
30+
"This interval (in hours) controls a background task to sync hosts within enabled zones " +
31+
"missing uploaded certificates for direct download." +
32+
"Only certificates which have not been revoked from hosts are uploaded",
33+
false);
34+
35+
/**
36+
* Revoke direct download certificate with alias 'alias' from hosts of hypervisor type 'hypervisor'
37+
*/
38+
boolean revokeCertificateAlias(String certificateAlias, String hypervisor, Long zoneId, Long hostId);
2539
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
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+
package org.apache.cloudstack.agent.directdownload;
20+
21+
import com.cloud.agent.api.Command;
22+
23+
public class RevokeDirectDownloadCertificateCommand extends Command {
24+
25+
private String certificateAlias;
26+
27+
public RevokeDirectDownloadCertificateCommand(final String alias) {
28+
this.certificateAlias = alias;
29+
}
30+
31+
public String getCertificateAlias() {
32+
return certificateAlias;
33+
}
34+
35+
@Override
36+
public boolean executeInSequence() {
37+
return false;
38+
}
39+
}

engine/schema/src/main/java/com/cloud/host/dao/HostDao.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,4 +107,6 @@ public interface HostDao extends GenericDao<HostVO, Long>, StateDao<Status, Stat
107107
* Side note: this method is currently only used in XenServerGuru; therefore, it was designed to meet XenServer deployment scenarios requirements.
108108
*/
109109
HostVO findHostInZoneToExecuteCommand(long zoneId, HypervisorType hypervisorType);
110+
111+
List<HostVO> listAllHostsUpByZoneAndHypervisor(long zoneId, HypervisorType hypervisorType);
110112
}

engine/schema/src/main/java/com/cloud/host/dao/HostDaoImpl.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import java.util.Map;
2727
import java.util.Objects;
2828
import java.util.TimeZone;
29+
import java.util.stream.Collectors;
2930

3031
import javax.annotation.PostConstruct;
3132
import javax.inject.Inject;
@@ -1190,6 +1191,15 @@ public HostVO findHostInZoneToExecuteCommand(long zoneId, HypervisorType hypervi
11901191
}
11911192
}
11921193

1194+
@Override
1195+
public List<HostVO> listAllHostsUpByZoneAndHypervisor(long zoneId, HypervisorType hypervisorType) {
1196+
return listByDataCenterIdAndHypervisorType(zoneId, hypervisorType)
1197+
.stream()
1198+
.filter(x -> x.getStatus().equals(Status.Up) &&
1199+
x.getType() == Host.Type.Routing)
1200+
.collect(Collectors.toList());
1201+
}
1202+
11931203
private ResultSet executeSqlGetResultsetForMethodFindHostInZoneToExecuteCommand(HypervisorType hypervisorType, long zoneId, TransactionLegacy tx, String sql) throws SQLException {
11941204
PreparedStatement pstmt = tx.prepareAutoCloseStatement(sql);
11951205
pstmt.setString(1, Objects.toString(hypervisorType));
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
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+
package org.apache.cloudstack.direct.download;
18+
19+
import com.cloud.hypervisor.Hypervisor;
20+
import com.cloud.utils.db.GenericDao;
21+
22+
import java.util.List;
23+
24+
public interface DirectDownloadCertificateDao extends GenericDao<DirectDownloadCertificateVO, Long> {
25+
DirectDownloadCertificateVO findByAlias(String alias, Hypervisor.HypervisorType hypervisorType, long zoneId);
26+
List<DirectDownloadCertificateVO> listByZone(long zoneId);
27+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
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+
package org.apache.cloudstack.direct.download;
18+
19+
import com.cloud.hypervisor.Hypervisor;
20+
import com.cloud.utils.db.GenericDaoBase;
21+
import com.cloud.utils.db.SearchBuilder;
22+
import com.cloud.utils.db.SearchCriteria;
23+
24+
import java.util.List;
25+
26+
public class DirectDownloadCertificateDaoImpl extends GenericDaoBase<DirectDownloadCertificateVO, Long> implements DirectDownloadCertificateDao {
27+
28+
private final SearchBuilder<DirectDownloadCertificateVO> certificateSearchBuilder;
29+
30+
public DirectDownloadCertificateDaoImpl() {
31+
certificateSearchBuilder = createSearchBuilder();
32+
certificateSearchBuilder.and("alias", certificateSearchBuilder.entity().getAlias(), SearchCriteria.Op.EQ);
33+
certificateSearchBuilder.and("hypervisor_type", certificateSearchBuilder.entity().getHypervisorType(), SearchCriteria.Op.EQ);
34+
certificateSearchBuilder.and("zone_id", certificateSearchBuilder.entity().getZoneId(), SearchCriteria.Op.EQ);
35+
certificateSearchBuilder.done();
36+
}
37+
38+
@Override
39+
public DirectDownloadCertificateVO findByAlias(String alias, Hypervisor.HypervisorType hypervisorType, long zoneId) {
40+
SearchCriteria<DirectDownloadCertificateVO> sc = certificateSearchBuilder.create();
41+
sc.setParameters("alias", alias);
42+
sc.setParameters("hypervisor_type", hypervisorType);
43+
sc.setParameters("zone_id", zoneId);
44+
return findOneBy(sc);
45+
}
46+
47+
@Override
48+
public List<DirectDownloadCertificateVO> listByZone(long zoneId) {
49+
SearchCriteria<DirectDownloadCertificateVO> sc = certificateSearchBuilder.create();
50+
sc.setParameters("zone_id", zoneId);
51+
return listBy(sc);
52+
}
53+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
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+
package org.apache.cloudstack.direct.download;
18+
19+
import com.cloud.utils.db.GenericDao;
20+
21+
import java.util.List;
22+
23+
public interface DirectDownloadCertificateHostMapDao extends GenericDao<DirectDownloadCertificateHostMapVO, Long> {
24+
DirectDownloadCertificateHostMapVO findByCertificateAndHost(long certificateId, long hostId);
25+
List<DirectDownloadCertificateHostMapVO> listByCertificateId(long certificateId);
26+
}

0 commit comments

Comments
 (0)