Skip to content

Commit 1708ffd

Browse files
authored
Merge pull request #621 from jeongda-young/License_UI
라이센스 UI에서 glue-api 호출 부분 수정
2 parents fff008d + 807738a commit 1708ffd

5 files changed

Lines changed: 155 additions & 28 deletions

File tree

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1305,6 +1305,7 @@ public class ApiConstants {
13051305
public static final String DISASTER_RECOVERY_CLUSTER_VM_LIST = "disasterrecoveryclustervmlist";
13061306
public static final String EXPIRY_DATE = "expirydate";
13071307
public static final String LICENSE_CHECK = "licensecheck";
1308+
public static final String HAS_LICENSE = "haslicense";
13081309

13091310
/**
13101311
* This enum specifies IO Drivers, each option controls specific policies on I/O.

api/src/main/java/org/apache/cloudstack/api/command/admin/outofbandmanagement/LicenseCheckCmd.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,6 @@ public long getEntityOwnerId() {
9393
@Override
9494
public void execute() throws ResourceUnavailableException, ServerApiException {
9595
try {
96-
logger.info("라이센스 체크1");
9796
LicenseCheckerResponse response = _mgr.checkLicense(this);
9897

9998
setResponseObject(response);

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ public class LicenseCheckerResponse extends BaseResponse {
3737
@Param(description = "license success")
3838
private String success;
3939

40+
@SerializedName(ApiConstants.HAS_LICENSE)
41+
@Param(description = "whether host has a valid license")
42+
private String hasLicense;
43+
4044
public Long getHostId() {
4145
return HostId;
4246
}
@@ -49,6 +53,10 @@ public String getSuccess() {
4953
return success;
5054
}
5155

56+
public String getHasLicense() {
57+
return hasLicense;
58+
}
59+
5260
public void setHostId(long hostId) {
5361
this.HostId = Long.valueOf(hostId);
5462
}
@@ -60,4 +68,8 @@ public void setExpiryDate(Date expiryDate) {
6068
public void setSuccess(boolean isValid) {
6169
this.success = Boolean.toString(isValid);
6270
}
71+
72+
public void setHasLicense(boolean hasLicense) {
73+
this.hasLicense = Boolean.toString(hasLicense);
74+
}
6375
}

server/src/main/java/com/cloud/server/ManagementServerImpl.java

Lines changed: 105 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,10 @@
2222
import java.io.InputStreamReader;
2323
import java.lang.reflect.Field;
2424
import java.net.SocketTimeoutException;
25-
// import java.net.HttpURLConnection;
2625
import java.net.URL;
2726
import java.security.SecureRandom;
2827
import java.security.cert.CertificateException;
28+
import java.text.SimpleDateFormat;
2929
import java.util.ArrayList;
3030
import java.util.Arrays;
3131
import java.util.Calendar;
@@ -5883,7 +5883,6 @@ public void setLockControllerListener(final LockControllerListener lockControlle
58835883

58845884
@Override
58855885
public LicenseCheckerResponse checkLicense(LicenseCheckCmd cmd) {
5886-
logger.info("License check started");
58875886
Long hostId = cmd.getHostId();
58885887
if (hostId == null) {
58895888
throw new InvalidParameterValueException("Host ID is required");
@@ -5894,22 +5893,112 @@ public LicenseCheckerResponse checkLicense(LicenseCheckCmd cmd) {
58945893
throw new InvalidParameterValueException("Host not found: " + hostId);
58955894
}
58965895

5897-
return checkLicensesForHosts(List.of(host)).getResponses().get(0);
5898-
}
5899-
private List<HostVO> getHostsToCheck(Long hostId) {
5900-
if (hostId != null) {
5901-
SearchBuilder<HostVO> sb = _hostDao.createSearchBuilder();
5902-
sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
5903-
SearchCriteria<HostVO> sc = sb.create();
5904-
sc.setParameters("id", hostId);
5905-
return _hostDao.search(sc, new Filter(HostVO.class, "id", true));
5896+
LicenseCheckerResponse response = new LicenseCheckerResponse();
5897+
response.setHostId(hostId);
5898+
response.setObjectName("licensecheck");
5899+
5900+
try {
5901+
String ipAddress = host.getPrivateIpAddress();
5902+
String licenseApiUrl = "https://" + ipAddress + ":8080/api/v1/license/isLicenseExpired";
5903+
5904+
HttpsURLConnection connection = null;
5905+
try {
5906+
// SSL 설정
5907+
final SSLContext sslContext = SSLUtils.getSSLContext();
5908+
sslContext.init(null, new TrustManager[]{new TrustAllManager()}, new SecureRandom());
5909+
5910+
URL url = new URL(licenseApiUrl);
5911+
connection = (HttpsURLConnection) url.openConnection();
5912+
connection.setSSLSocketFactory(sslContext.getSocketFactory());
5913+
connection.setHostnameVerifier((hostname, session) -> hostname.equals(ipAddress));
5914+
connection.setDoOutput(true);
5915+
connection.setRequestMethod("GET");
5916+
connection.setConnectTimeout(10000);
5917+
connection.setReadTimeout(180000);
5918+
connection.setRequestProperty("Accept", "application/json");
5919+
connection.setRequestProperty("Content-Type", "application/json");
5920+
5921+
int responseCode = connection.getResponseCode();
5922+
5923+
if (responseCode == 200) {
5924+
BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
5925+
StringBuilder responseData = new StringBuilder();
5926+
String line;
5927+
while ((line = in.readLine()) != null) {
5928+
responseData.append(line);
5929+
}
5930+
in.close();
5931+
5932+
// JSON 응답 파싱
5933+
ObjectMapper mapper = new ObjectMapper();
5934+
JsonNode jsonNode = mapper.readTree(responseData.toString());
5935+
5936+
// 라이선스 정보 설정
5937+
if (jsonNode.has("error")) {
5938+
String errorMessage = jsonNode.get("error").asText();
5939+
response.setHasLicense(false);
5940+
response.setSuccess(false);
5941+
response.setExpiryDate(null);
5942+
} else {
5943+
boolean isExpired = jsonNode.get("expired").asBoolean();
5944+
String expiryDateStr = jsonNode.get("expiry_date").asText();
5945+
5946+
response.setSuccess(!isExpired);
5947+
response.setHasLicense(true);
5948+
if (expiryDateStr != null && !expiryDateStr.isEmpty()) {
5949+
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
5950+
Date expiryDate = sdf.parse(expiryDateStr);
5951+
response.setExpiryDate(expiryDate);
5952+
}
5953+
}
5954+
} else {
5955+
response.setHasLicense(false);
5956+
response.setSuccess(false);
5957+
response.setExpiryDate(null);
5958+
}
5959+
} finally {
5960+
if (connection != null) {
5961+
connection.disconnect();
5962+
}
5963+
}
5964+
return response;
5965+
} catch (Exception e) {
5966+
throw new CloudRuntimeException("라이선스 체크 실패: " + e.getMessage());
59065967
}
5907-
return _hostDao.listAll();
59085968
}
5909-
public ListResponse<LicenseCheckerResponse> listLicenseChecks(final LicenseCheckCmd cmd) {
5910-
final Long hostId = cmd.getHostId();
5911-
List<HostVO> hosts = getHostsToCheck(hostId);
5912-
return checkLicensesForHosts(hosts);
5969+
5970+
private Date getLicenseExpiryDate(String apiUrl, String ipAddress) throws Exception {
5971+
HttpsURLConnection connection = null;
5972+
try {
5973+
final SSLContext sslContext = SSLUtils.getSSLContext();
5974+
sslContext.init(null, new TrustManager[]{new TrustAllManager()}, new SecureRandom());
5975+
5976+
URL url = new URL(apiUrl);
5977+
connection = (HttpsURLConnection) url.openConnection();
5978+
connection.setSSLSocketFactory(sslContext.getSocketFactory());
5979+
connection.setHostnameVerifier((hostname, session) -> hostname.equals(ipAddress));
5980+
connection.setDoOutput(true);
5981+
connection.setRequestMethod("GET");
5982+
connection.setConnectTimeout(10000);
5983+
connection.setReadTimeout(180000);
5984+
connection.setRequestProperty("Accept", "application/json");
5985+
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
5986+
5987+
if (connection.getResponseCode() == 200) {
5988+
try (BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()))) {
5989+
String dateStr = in.readLine();
5990+
if (dateStr != null && !dateStr.isEmpty()) {
5991+
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
5992+
return sdf.parse(dateStr);
5993+
}
5994+
}
5995+
}
5996+
} finally {
5997+
if (connection != null) {
5998+
connection.disconnect();
5999+
}
6000+
}
6001+
return null;
59136002
}
59146003

59156004
private ListResponse<LicenseCheckerResponse> checkLicensesForHosts(List<HostVO> hosts) {

ui/src/components/view/DetailsTab.vue

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -193,13 +193,23 @@
193193
<DedicateData :resource="dataResource" v-if="dedicatedSectionActive" />
194194
<VmwareData :resource="dataResource" v-if="$route.meta.name === 'zone' && 'listVmwareDcs' in $store.getters.apis" />
195195
</a-list>
196+
<div class="license-info">
197+
<a-descriptions-item label="라이센스 만료일">
198+
{{ dataResource.licenseExpiryDate || '정보 없음' }}
199+
</a-descriptions-item>
200+
<a-descriptions-item label="라이센스 상태">
201+
{{ dataResource.hasLicense ? '있음' : '없음' }}
202+
({{ dataResource.licenseValid ? '유효함' : '만료됨' }})
203+
</a-descriptions-item>
204+
</div>
196205
</template>
197206

198207
<script>
199208
import DedicateData from './DedicateData'
200209
import HostInfo from '@/views/infra/HostInfo'
201210
import VmwareData from './VmwareData'
202211
import { genericCompare } from '@/utils/sort'
212+
import { api } from '@/api'
203213
204214
export default {
205215
name: 'DetailsTab',
@@ -478,21 +488,37 @@ export default {
478488
return `${this.$t('message.alert.licenseexpired')} ${this.resource.licenseExpiryDate} ${this.isLicenseExpired(this.resource.licenseExpiryDate) ? this.$t('message.license.renewal.required') : '(' + this.calculateDday(this.resource.licenseExpiryDate) + this.$t('message.license.days.left') + ')'}`
479489
},
480490
async fetchLicenseInfo () {
481-
if (this.resource && this.resource.ipaddress) {
482-
try {
483-
const response = await fetch(`https://${this.resource.ipaddress}:8080/api/v1/license/isLicenseExpired`)
484-
const data = await response.json()
485-
if (data.error) {
486-
this.dataResource.licenseExpiryDate = ''
491+
if (!this.resource || !this.resource.id) {
492+
return
493+
}
494+
495+
const params = {
496+
hostid: this.resource.id
497+
}
498+
499+
api('licenseCheck', params).then(response => {
500+
const licenseData = response?.null?.licensecheck
501+
502+
if (licenseData) {
503+
if (licenseData.expirydate) {
504+
const expiryDate = new Date(licenseData.expirydate)
505+
this.dataResource.licenseExpiryDate = expiryDate.toLocaleDateString('ko-KR')
487506
} else {
488-
this.dataResource.licenseExpiryDate = data.expiry_date
507+
this.dataResource.licenseExpiryDate = '만료일 정보 없음'
489508
}
490-
} catch (error) {
491-
console.error('라이선스 정보를 가져오는데 실패했습니다:', error)
509+
510+
this.dataResource.hostId = licenseData.hostid
511+
this.dataResource.hasLicense = licenseData.haslicense === 'true'
512+
this.dataResource.licenseValid = licenseData.success === 'true'
492513
}
493-
}
514+
}).catch(error => {
515+
console.error('라이선스 정보를 가져오는데 실패했습니다:', error)
516+
this.dataResource.licenseExpiryDate = '조회 실패'
517+
this.dataResource.hasLicense = false
518+
this.dataResource.licenseValid = false
519+
this.$notifyError(error)
520+
})
494521
},
495-
496522
isLicenseExpired (expiryDate) {
497523
const today = new Date()
498524
const expiry = new Date(expiryDate)

0 commit comments

Comments
 (0)