mirror of https://github.com/apache/cloudstack.git
Merge 64560e3581 into b7d4df0a11
This commit is contained in:
commit
7f90d1e0cc
|
|
@ -38,11 +38,14 @@ import org.apache.cloudstack.api.command.admin.offering.CloneDiskOfferingCmd;
|
|||
import org.apache.cloudstack.api.command.admin.offering.CloneServiceOfferingCmd;
|
||||
import org.apache.cloudstack.api.command.admin.offering.CreateDiskOfferingCmd;
|
||||
import org.apache.cloudstack.api.command.admin.offering.CreateServiceOfferingCmd;
|
||||
import org.apache.cloudstack.api.command.admin.offering.CreateServiceOfferingCategoryCmd;
|
||||
import org.apache.cloudstack.api.command.admin.offering.DeleteDiskOfferingCmd;
|
||||
import org.apache.cloudstack.api.command.admin.offering.DeleteServiceOfferingCmd;
|
||||
import org.apache.cloudstack.api.command.admin.offering.DeleteServiceOfferingCategoryCmd;
|
||||
import org.apache.cloudstack.api.command.admin.offering.IsAccountAllowedToCreateOfferingsWithTagsCmd;
|
||||
import org.apache.cloudstack.api.command.admin.offering.UpdateDiskOfferingCmd;
|
||||
import org.apache.cloudstack.api.command.admin.offering.UpdateServiceOfferingCmd;
|
||||
import org.apache.cloudstack.api.command.admin.offering.UpdateServiceOfferingCategoryCmd;
|
||||
import org.apache.cloudstack.api.command.admin.pod.DeletePodCmd;
|
||||
import org.apache.cloudstack.api.command.admin.pod.UpdatePodCmd;
|
||||
import org.apache.cloudstack.api.command.admin.region.CreatePortableIpRangeCmd;
|
||||
|
|
@ -75,6 +78,7 @@ import com.cloud.network.Networks.TrafficType;
|
|||
import com.cloud.offering.DiskOffering;
|
||||
import com.cloud.offering.NetworkOffering;
|
||||
import com.cloud.offering.ServiceOffering;
|
||||
import com.cloud.offering.ServiceOfferingCategory;
|
||||
import com.cloud.user.Account;
|
||||
import com.cloud.utils.Pair;
|
||||
|
||||
|
|
@ -157,6 +161,30 @@ public interface ConfigurationService {
|
|||
*/
|
||||
List<Long> getServiceOfferingZones(Long serviceOfferingId);
|
||||
|
||||
/**
|
||||
* Creates a service offering category
|
||||
*
|
||||
* @param cmd - the command specifying name and sort key
|
||||
* @return the newly created service offering category
|
||||
*/
|
||||
ServiceOfferingCategory createServiceOfferingCategory(CreateServiceOfferingCategoryCmd cmd);
|
||||
|
||||
/**
|
||||
* Deletes a service offering category
|
||||
*
|
||||
* @param cmd - the command specifying category id
|
||||
* @return true if successful, false otherwise
|
||||
*/
|
||||
boolean deleteServiceOfferingCategory(DeleteServiceOfferingCategoryCmd cmd);
|
||||
|
||||
/**
|
||||
* Updates a service offering category
|
||||
*
|
||||
* @param cmd - the command specifying category id, name, and/or sort key
|
||||
* @return updated service offering category
|
||||
*/
|
||||
ServiceOfferingCategory updateServiceOfferingCategory(UpdateServiceOfferingCategoryCmd cmd);
|
||||
|
||||
/**
|
||||
* Updates a disk offering
|
||||
*
|
||||
|
|
|
|||
|
|
@ -85,6 +85,7 @@ import com.cloud.network.vpc.VpcOffering;
|
|||
import com.cloud.offering.DiskOffering;
|
||||
import com.cloud.offering.NetworkOffering;
|
||||
import com.cloud.offering.ServiceOffering;
|
||||
import com.cloud.offering.ServiceOfferingCategory;
|
||||
import com.cloud.projects.Project;
|
||||
import com.cloud.server.ResourceTag;
|
||||
import com.cloud.storage.GuestOS;
|
||||
|
|
@ -396,6 +397,11 @@ public class EventTypes {
|
|||
public static final String EVENT_SERVICE_OFFERING_EDIT = "SERVICE.OFFERING.EDIT";
|
||||
public static final String EVENT_SERVICE_OFFERING_DELETE = "SERVICE.OFFERING.DELETE";
|
||||
|
||||
// Service Offering Categories
|
||||
public static final String EVENT_SERVICE_OFFERING_CATEGORY_CREATE = "SERVICE.OFFERING.CATEGORY.CREATE";
|
||||
public static final String EVENT_SERVICE_OFFERING_CATEGORY_EDIT = "SERVICE.OFFERING.CATEGORY.EDIT";
|
||||
public static final String EVENT_SERVICE_OFFERING_CATEGORY_DELETE = "SERVICE.OFFERING.CATEGORY.DELETE";
|
||||
|
||||
// Disk Offerings
|
||||
public static final String EVENT_DISK_OFFERING_CREATE = "DISK.OFFERING.CREATE";
|
||||
public static final String EVENT_DISK_OFFERING_CLONE = "DISK.OFFERING.CLONE";
|
||||
|
|
@ -1089,6 +1095,9 @@ public class EventTypes {
|
|||
entityEventDetails.put(EVENT_SERVICE_OFFERING_CLONE, ServiceOffering.class);
|
||||
entityEventDetails.put(EVENT_SERVICE_OFFERING_EDIT, ServiceOffering.class);
|
||||
entityEventDetails.put(EVENT_SERVICE_OFFERING_DELETE, ServiceOffering.class);
|
||||
entityEventDetails.put(EVENT_SERVICE_OFFERING_CATEGORY_CREATE, ServiceOfferingCategory.class);
|
||||
entityEventDetails.put(EVENT_SERVICE_OFFERING_CATEGORY_EDIT, ServiceOfferingCategory.class);
|
||||
entityEventDetails.put(EVENT_SERVICE_OFFERING_CATEGORY_DELETE, ServiceOfferingCategory.class);
|
||||
|
||||
// Disk Offerings
|
||||
entityEventDetails.put(EVENT_DISK_OFFERING_CREATE, DiskOffering.class);
|
||||
|
|
|
|||
|
|
@ -146,4 +146,6 @@ public interface ServiceOffering extends InfrastructureEntity, InternalIdentity,
|
|||
Long getVgpuProfileId();
|
||||
|
||||
Integer getGpuCount();
|
||||
|
||||
long getCategoryId();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,31 @@
|
|||
// 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.offering;
|
||||
|
||||
import org.apache.cloudstack.api.Identity;
|
||||
import org.apache.cloudstack.api.InternalIdentity;
|
||||
|
||||
public interface ServiceOfferingCategory extends Identity, InternalIdentity {
|
||||
|
||||
String getName();
|
||||
|
||||
void setName(String name);
|
||||
|
||||
int getSortKey();
|
||||
|
||||
void setSortKey(int sortKey);
|
||||
}
|
||||
|
|
@ -546,6 +546,8 @@ public class ApiConstants {
|
|||
public static final String SENT_BYTES = "sentbytes";
|
||||
public static final String SERIAL = "serial";
|
||||
public static final String SERVICE_IP = "serviceip";
|
||||
public static final String SERVICE_OFFERING_CATEGORY_ID = "categoryid";
|
||||
public static final String SERVICE_OFFERING_CATEGORY_NAME = "categoryname";
|
||||
public static final String SERVICE_OFFERING_ID = "serviceofferingid";
|
||||
public static final String SERVICE_OFFERING_NAME = "serviceofferingname";
|
||||
public static final String SESSIONKEY = "sessionkey";
|
||||
|
|
|
|||
|
|
@ -116,6 +116,7 @@ import org.apache.cloudstack.api.response.SSHKeyPairResponse;
|
|||
import org.apache.cloudstack.api.response.SecondaryStorageHeuristicsResponse;
|
||||
import org.apache.cloudstack.api.response.SecurityGroupResponse;
|
||||
import org.apache.cloudstack.api.response.ServiceOfferingResponse;
|
||||
import org.apache.cloudstack.api.response.ServiceOfferingCategoryResponse;
|
||||
import org.apache.cloudstack.api.response.ServiceResponse;
|
||||
import org.apache.cloudstack.api.response.SharedFSResponse;
|
||||
import org.apache.cloudstack.api.response.Site2SiteCustomerGatewayResponse;
|
||||
|
|
@ -224,6 +225,7 @@ import com.cloud.network.vpc.VpcOffering;
|
|||
import com.cloud.offering.DiskOffering;
|
||||
import com.cloud.offering.NetworkOffering;
|
||||
import com.cloud.offering.ServiceOffering;
|
||||
import com.cloud.offering.ServiceOfferingCategory;
|
||||
import com.cloud.org.Cluster;
|
||||
import com.cloud.projects.Project;
|
||||
import com.cloud.projects.ProjectAccount;
|
||||
|
|
@ -271,6 +273,8 @@ public interface ResponseGenerator {
|
|||
|
||||
ServiceOfferingResponse createServiceOfferingResponse(ServiceOffering offering);
|
||||
|
||||
ServiceOfferingCategoryResponse createServiceOfferingCategoryResponse(ServiceOfferingCategory category);
|
||||
|
||||
ConfigurationResponse createConfigurationResponse(Configuration cfg);
|
||||
|
||||
ConfigurationGroupResponse createConfigurationGroupResponse(ConfigurationGroup cfgGroup);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,85 @@
|
|||
// 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.api.command.admin.offering;
|
||||
|
||||
import org.apache.cloudstack.api.APICommand;
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.ApiErrorCode;
|
||||
import org.apache.cloudstack.api.BaseCmd;
|
||||
import org.apache.cloudstack.api.Parameter;
|
||||
import org.apache.cloudstack.api.ServerApiException;
|
||||
import org.apache.cloudstack.api.response.ServiceOfferingCategoryResponse;
|
||||
|
||||
import com.cloud.offering.ServiceOfferingCategory;
|
||||
import com.cloud.user.Account;
|
||||
|
||||
@APICommand(name = "createServiceOfferingCategory",
|
||||
description = "Creates a service offering category.",
|
||||
responseObject = ServiceOfferingCategoryResponse.class,
|
||||
since = "4.23.0",
|
||||
requestHasSensitiveInfo = false,
|
||||
responseHasSensitiveInfo = false)
|
||||
public class CreateServiceOfferingCategoryCmd extends BaseCmd {
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
//////////////// API parameters /////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
@Parameter(name = ApiConstants.NAME,
|
||||
type = CommandType.STRING,
|
||||
required = true,
|
||||
description = "the name of the service offering category")
|
||||
private String name;
|
||||
|
||||
@Parameter(name = ApiConstants.SORT_KEY,
|
||||
type = CommandType.INTEGER,
|
||||
description = "sort key of the service offering category, default is 0")
|
||||
private Integer sortKey;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////////// Accessors ///////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public Integer getSortKey() {
|
||||
return sortKey;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////// API Implementation///////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
ServiceOfferingCategory result = _configService.createServiceOfferingCategory(this);
|
||||
if (result != null) {
|
||||
ServiceOfferingCategoryResponse response = _responseGenerator.createServiceOfferingCategoryResponse(result);
|
||||
response.setResponseName(getCommandName());
|
||||
setResponseObject(response);
|
||||
} else {
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to create service offering category");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getEntityOwnerId() {
|
||||
return Account.ACCOUNT_ID_SYSTEM;
|
||||
}
|
||||
}
|
||||
|
|
@ -32,6 +32,7 @@ import org.apache.cloudstack.api.ServerApiException;
|
|||
import org.apache.cloudstack.api.response.DiskOfferingResponse;
|
||||
import org.apache.cloudstack.api.response.DomainResponse;
|
||||
import org.apache.cloudstack.api.response.ServiceOfferingResponse;
|
||||
import org.apache.cloudstack.api.response.ServiceOfferingCategoryResponse;
|
||||
import org.apache.cloudstack.api.response.VgpuProfileResponse;
|
||||
import org.apache.cloudstack.api.response.VsphereStoragePoliciesResponse;
|
||||
import org.apache.cloudstack.api.response.ZoneResponse;
|
||||
|
|
@ -288,6 +289,14 @@ public class CreateServiceOfferingCmd extends BaseCmd {
|
|||
since = "4.21.0")
|
||||
private Map externalDetails;
|
||||
|
||||
@Parameter(name = ApiConstants.SERVICE_OFFERING_CATEGORY_ID,
|
||||
type = CommandType.UUID,
|
||||
entityType = ServiceOfferingCategoryResponse.class,
|
||||
required = false,
|
||||
description = "the ID of the service offering category to associate with this offering",
|
||||
since = "4.23.0")
|
||||
private Long categoryId;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////////// Accessors ///////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
|
@ -560,6 +569,10 @@ public class CreateServiceOfferingCmd extends BaseCmd {
|
|||
return Boolean.TRUE.equals(gpuDisplay);
|
||||
}
|
||||
|
||||
public Long getCategoryId() {
|
||||
return categoryId;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////// API Implementation///////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -0,0 +1,76 @@
|
|||
// 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.api.command.admin.offering;
|
||||
|
||||
import org.apache.cloudstack.api.APICommand;
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.ApiErrorCode;
|
||||
import org.apache.cloudstack.api.BaseCmd;
|
||||
import org.apache.cloudstack.api.Parameter;
|
||||
import org.apache.cloudstack.api.ServerApiException;
|
||||
import org.apache.cloudstack.api.response.ServiceOfferingCategoryResponse;
|
||||
import org.apache.cloudstack.api.response.SuccessResponse;
|
||||
|
||||
import com.cloud.user.Account;
|
||||
|
||||
@APICommand(name = "deleteServiceOfferingCategory",
|
||||
description = "Deletes a service offering category.",
|
||||
responseObject = SuccessResponse.class,
|
||||
since = "4.23.0",
|
||||
requestHasSensitiveInfo = false,
|
||||
responseHasSensitiveInfo = false)
|
||||
public class DeleteServiceOfferingCategoryCmd extends BaseCmd {
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
//////////////// API parameters /////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
@Parameter(name = ApiConstants.ID,
|
||||
type = CommandType.UUID,
|
||||
entityType = ServiceOfferingCategoryResponse.class,
|
||||
required = true,
|
||||
description = "the ID of the service offering category")
|
||||
private Long id;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////////// Accessors ///////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////// API Implementation///////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
boolean result = _configService.deleteServiceOfferingCategory(this);
|
||||
if (result) {
|
||||
SuccessResponse response = new SuccessResponse(getCommandName());
|
||||
setResponseObject(response);
|
||||
} else {
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to delete service offering category");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getEntityOwnerId() {
|
||||
return Account.ACCOUNT_ID_SYSTEM;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
// 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.api.command.admin.offering;
|
||||
|
||||
import org.apache.cloudstack.api.APICommand;
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.BaseListCmd;
|
||||
import org.apache.cloudstack.api.Parameter;
|
||||
import org.apache.cloudstack.api.response.ListResponse;
|
||||
import org.apache.cloudstack.api.response.ServiceOfferingCategoryResponse;
|
||||
|
||||
@APICommand(name = "listServiceOfferingCategories",
|
||||
description = "Lists service offering categories.",
|
||||
responseObject = ServiceOfferingCategoryResponse.class,
|
||||
since = "4.23.0",
|
||||
requestHasSensitiveInfo = false,
|
||||
responseHasSensitiveInfo = false)
|
||||
public class ListServiceOfferingCategoriesCmd extends BaseListCmd {
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
//////////////// API parameters /////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
@Parameter(name = ApiConstants.ID,
|
||||
type = CommandType.UUID,
|
||||
entityType = ServiceOfferingCategoryResponse.class,
|
||||
description = "ID of the service offering category")
|
||||
private Long id;
|
||||
|
||||
@Parameter(name = ApiConstants.NAME,
|
||||
type = CommandType.STRING,
|
||||
description = "name of the service offering category")
|
||||
private String name;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////////// Accessors ///////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////// API Implementation///////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
ListResponse<ServiceOfferingCategoryResponse> response = _queryService.listServiceOfferingCategories(this);
|
||||
response.setResponseName(getCommandName());
|
||||
setResponseObject(response);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,95 @@
|
|||
// 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.api.command.admin.offering;
|
||||
|
||||
import org.apache.cloudstack.api.APICommand;
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.ApiErrorCode;
|
||||
import org.apache.cloudstack.api.BaseCmd;
|
||||
import org.apache.cloudstack.api.Parameter;
|
||||
import org.apache.cloudstack.api.ServerApiException;
|
||||
import org.apache.cloudstack.api.response.ServiceOfferingCategoryResponse;
|
||||
|
||||
import com.cloud.offering.ServiceOfferingCategory;
|
||||
import com.cloud.user.Account;
|
||||
|
||||
@APICommand(name = "updateServiceOfferingCategory",
|
||||
description = "Updates a service offering category",
|
||||
responseObject = ServiceOfferingCategoryResponse.class,
|
||||
since = "4.23.0",
|
||||
requestHasSensitiveInfo = false,
|
||||
responseHasSensitiveInfo = false)
|
||||
public class UpdateServiceOfferingCategoryCmd extends BaseCmd {
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
//////////////// API parameters /////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
@Parameter(name = ApiConstants.ID,
|
||||
type = CommandType.UUID,
|
||||
entityType = ServiceOfferingCategoryResponse.class,
|
||||
required = true,
|
||||
description = "the ID of the service offering category")
|
||||
private Long id;
|
||||
|
||||
@Parameter(name = ApiConstants.NAME,
|
||||
type = CommandType.STRING,
|
||||
description = "the name of the service offering category")
|
||||
private String name;
|
||||
|
||||
@Parameter(name = ApiConstants.SORT_KEY,
|
||||
type = CommandType.INTEGER,
|
||||
description = "sort key of the service offering category")
|
||||
private Integer sortKey;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////////// Accessors ///////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public Integer getSortKey() {
|
||||
return sortKey;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////// API Implementation///////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public long getEntityOwnerId() {
|
||||
return Account.ACCOUNT_ID_SYSTEM;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
ServiceOfferingCategory result = _configService.updateServiceOfferingCategory(this);
|
||||
if (result != null) {
|
||||
ServiceOfferingCategoryResponse response = _responseGenerator.createServiceOfferingCategoryResponse(result);
|
||||
response.setResponseName(getCommandName());
|
||||
setResponseObject(response);
|
||||
} else {
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to update service offering category");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -29,6 +29,7 @@ import org.apache.cloudstack.api.Parameter;
|
|||
import org.apache.cloudstack.api.ServerApiException;
|
||||
import org.apache.cloudstack.api.command.offering.DomainAndZoneIdResolver;
|
||||
import org.apache.cloudstack.api.response.ServiceOfferingResponse;
|
||||
import org.apache.cloudstack.api.response.ServiceOfferingCategoryResponse;
|
||||
import org.apache.commons.lang3.EnumUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
|
|
@ -108,6 +109,14 @@ public class UpdateServiceOfferingCmd extends BaseCmd implements DomainAndZoneId
|
|||
since = "4.22.0")
|
||||
protected Boolean cleanupExternalDetails;
|
||||
|
||||
@Parameter(name = ApiConstants.SERVICE_OFFERING_CATEGORY_ID,
|
||||
type = CommandType.UUID,
|
||||
entityType = ServiceOfferingCategoryResponse.class,
|
||||
required = false,
|
||||
description = "the ID of the service offering category to associate",
|
||||
since = "4.23.0")
|
||||
private Long categoryId;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////////// Accessors ///////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
|
@ -164,6 +173,8 @@ public class UpdateServiceOfferingCmd extends BaseCmd implements DomainAndZoneId
|
|||
return Boolean.TRUE.equals(cleanupExternalDetails);
|
||||
}
|
||||
|
||||
public Long getCategoryId() { return categoryId; }
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////// API Implementation///////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import org.apache.cloudstack.api.ApiConstants;
|
|||
import org.apache.cloudstack.api.BaseListProjectAndAccountResourcesCmd;
|
||||
import org.apache.cloudstack.api.Parameter;
|
||||
import org.apache.cloudstack.api.response.ListResponse;
|
||||
import org.apache.cloudstack.api.response.ServiceOfferingCategoryResponse;
|
||||
import org.apache.cloudstack.api.response.ServiceOfferingResponse;
|
||||
import org.apache.cloudstack.api.response.TemplateResponse;
|
||||
import org.apache.cloudstack.api.response.UserVmResponse;
|
||||
|
|
@ -124,6 +125,13 @@ public class ListServiceOfferingsCmd extends BaseListProjectAndAccountResourcesC
|
|||
since = "4.21.0")
|
||||
private Boolean gpuEnabled;
|
||||
|
||||
@Parameter(name = ApiConstants.SERVICE_OFFERING_CATEGORY_ID,
|
||||
type = CommandType.UUID,
|
||||
entityType = ServiceOfferingCategoryResponse.class,
|
||||
description = "the ID of the service offering category",
|
||||
since = "4.23.0")
|
||||
private Long categoryId;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////////// Accessors ///////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
|
@ -193,6 +201,10 @@ public class ListServiceOfferingsCmd extends BaseListProjectAndAccountResourcesC
|
|||
return gpuEnabled;
|
||||
}
|
||||
|
||||
public Long getCategoryId() {
|
||||
return categoryId;
|
||||
}
|
||||
|
||||
public void setZoneId(Long zoneId) {
|
||||
this.zoneId = zoneId;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,65 @@
|
|||
// 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.api.response;
|
||||
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.BaseResponse;
|
||||
import org.apache.cloudstack.api.EntityReference;
|
||||
|
||||
import com.cloud.offering.ServiceOfferingCategory;
|
||||
import com.cloud.serializer.Param;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
@EntityReference(value = ServiceOfferingCategory.class)
|
||||
public class ServiceOfferingCategoryResponse extends BaseResponse {
|
||||
|
||||
@SerializedName(ApiConstants.ID)
|
||||
@Param(description = "the ID of the service offering category")
|
||||
private String id;
|
||||
|
||||
@SerializedName(ApiConstants.NAME)
|
||||
@Param(description = "the name of the service offering category")
|
||||
private String name;
|
||||
|
||||
@SerializedName(ApiConstants.SORT_KEY)
|
||||
@Param(description = "sort key of the service offering category")
|
||||
private Integer sortKey;
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Integer getSortKey() {
|
||||
return sortKey;
|
||||
}
|
||||
|
||||
public void setSortKey(Integer sortKey) {
|
||||
this.sortKey = sortKey;
|
||||
}
|
||||
}
|
||||
|
|
@ -286,6 +286,14 @@ public class ServiceOfferingResponse extends BaseResponseWithAnnotations {
|
|||
@Param(description = "Action to be taken once lease is over", since = "4.21.0")
|
||||
private String leaseExpiryAction;
|
||||
|
||||
@SerializedName("categoryid")
|
||||
@Param(description = "the ID of the service offering category", since = "4.23.0")
|
||||
private String categoryId;
|
||||
|
||||
@SerializedName("category")
|
||||
@Param(description = "the name of the service offering category", since = "4.23.0")
|
||||
private String categoryName;
|
||||
|
||||
public ServiceOfferingResponse() {
|
||||
}
|
||||
|
||||
|
|
@ -707,4 +715,9 @@ public class ServiceOfferingResponse extends BaseResponseWithAnnotations {
|
|||
public void setPurgeResources(Boolean purgeResources) {
|
||||
this.purgeResources = purgeResources;
|
||||
}
|
||||
|
||||
public String getCategoryId() { return categoryId; }
|
||||
public void setCategoryId(String categoryId) { this.categoryId = categoryId; }
|
||||
public String getCategoryName() { return categoryName; }
|
||||
public void setCategoryName(String categoryName) { this.categoryName = categoryName; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ import org.apache.cloudstack.api.command.admin.storage.ListStorageAccessGroupsCm
|
|||
import org.apache.cloudstack.api.command.admin.storage.ListStoragePoolsCmd;
|
||||
import org.apache.cloudstack.api.command.admin.storage.ListStorageTagsCmd;
|
||||
import org.apache.cloudstack.api.command.admin.storage.heuristics.ListSecondaryStorageSelectorsCmd;
|
||||
import org.apache.cloudstack.api.command.admin.offering.ListServiceOfferingCategoriesCmd;
|
||||
import org.apache.cloudstack.api.command.admin.user.ListUsersCmd;
|
||||
import org.apache.cloudstack.api.command.user.account.ListAccountsCmd;
|
||||
import org.apache.cloudstack.api.command.user.account.ListProjectAccountsCmd;
|
||||
|
|
@ -87,6 +88,7 @@ import org.apache.cloudstack.api.response.RouterHealthCheckResultResponse;
|
|||
import org.apache.cloudstack.api.response.SecondaryStorageHeuristicsResponse;
|
||||
import org.apache.cloudstack.api.response.SecurityGroupResponse;
|
||||
import org.apache.cloudstack.api.response.ServiceOfferingResponse;
|
||||
import org.apache.cloudstack.api.response.ServiceOfferingCategoryResponse;
|
||||
import org.apache.cloudstack.api.response.SnapshotResponse;
|
||||
import org.apache.cloudstack.api.response.StorageAccessGroupResponse;
|
||||
import org.apache.cloudstack.api.response.StoragePoolResponse;
|
||||
|
|
@ -187,6 +189,8 @@ public interface QueryService {
|
|||
|
||||
ListResponse<ServiceOfferingResponse> searchForServiceOfferings(ListServiceOfferingsCmd cmd);
|
||||
|
||||
ListResponse<ServiceOfferingCategoryResponse> listServiceOfferingCategories(ListServiceOfferingCategoriesCmd cmd);
|
||||
|
||||
ListResponse<ZoneResponse> listDataCenters(ListZonesCmd cmd);
|
||||
|
||||
ListResponse<TemplateResponse> listTemplates(ListTemplatesCmd cmd);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,100 @@
|
|||
// 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.service;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import com.cloud.offering.ServiceOfferingCategory;
|
||||
|
||||
@Entity
|
||||
@Table(name = "service_offering_category")
|
||||
public class ServiceOfferingCategoryVO implements ServiceOfferingCategory {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@Column(name = "id")
|
||||
private long id;
|
||||
|
||||
@Column(name = "name")
|
||||
private String name;
|
||||
|
||||
@Column(name = "uuid")
|
||||
private String uuid;
|
||||
|
||||
@Column(name = "sort_key")
|
||||
private int sortKey;
|
||||
|
||||
public ServiceOfferingCategoryVO() {
|
||||
this.uuid = UUID.randomUUID().toString();
|
||||
}
|
||||
|
||||
public ServiceOfferingCategoryVO(String name) {
|
||||
this.name = name;
|
||||
this.uuid = UUID.randomUUID().toString();
|
||||
}
|
||||
|
||||
public ServiceOfferingCategoryVO(String name, int sortKey) {
|
||||
this.name = name;
|
||||
this.sortKey = sortKey;
|
||||
this.uuid = UUID.randomUUID().toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUuid() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
public void setUuid(String uuid) {
|
||||
this.uuid = uuid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSortKey() {
|
||||
return sortKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSortKey(int sortKey) {
|
||||
this.sortKey = sortKey;
|
||||
}
|
||||
}
|
||||
|
|
@ -133,6 +133,9 @@ public class ServiceOfferingVO implements ServiceOffering {
|
|||
@Column(name = "gpu_display")
|
||||
private Boolean gpuDisplay;
|
||||
|
||||
@Column(name = "category_id")
|
||||
private long categoryId = 1L; // Default category
|
||||
|
||||
// This is a delayed load value. If the value is null,
|
||||
// then this field has not been loaded yet.
|
||||
// Call service offering dao to load it.
|
||||
|
|
@ -482,4 +485,13 @@ public class ServiceOfferingVO implements ServiceOffering {
|
|||
public void setGpuDisplay(Boolean gpuDisplay) {
|
||||
this.gpuDisplay = gpuDisplay;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getCategoryId() {
|
||||
return categoryId;
|
||||
}
|
||||
|
||||
public void setCategoryId(long categoryId) {
|
||||
this.categoryId = categoryId;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,29 @@
|
|||
// 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.service.dao;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.cloud.service.ServiceOfferingCategoryVO;
|
||||
import com.cloud.utils.db.GenericDao;
|
||||
|
||||
public interface ServiceOfferingCategoryDao extends GenericDao<ServiceOfferingCategoryVO, Long> {
|
||||
|
||||
ServiceOfferingCategoryVO findByName(String name);
|
||||
|
||||
List<ServiceOfferingCategoryVO> listAll();
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
// 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.service.dao;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.cloud.service.ServiceOfferingCategoryVO;
|
||||
import com.cloud.utils.db.GenericDaoBase;
|
||||
import com.cloud.utils.db.SearchBuilder;
|
||||
import com.cloud.utils.db.SearchCriteria;
|
||||
import com.cloud.utils.db.DB;
|
||||
|
||||
@Component
|
||||
@DB()
|
||||
public class ServiceOfferingCategoryDaoImpl extends GenericDaoBase<ServiceOfferingCategoryVO, Long> implements ServiceOfferingCategoryDao {
|
||||
|
||||
protected final SearchBuilder<ServiceOfferingCategoryVO> NameSearch;
|
||||
|
||||
protected ServiceOfferingCategoryDaoImpl() {
|
||||
NameSearch = createSearchBuilder();
|
||||
NameSearch.and("name", NameSearch.entity().getName(), SearchCriteria.Op.EQ);
|
||||
NameSearch.done();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServiceOfferingCategoryVO findByName(String name) {
|
||||
SearchCriteria<ServiceOfferingCategoryVO> sc = NameSearch.create();
|
||||
sc.setParameters("name", name);
|
||||
return findOneBy(sc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ServiceOfferingCategoryVO> listAll() {
|
||||
return listAll(null);
|
||||
}
|
||||
}
|
||||
|
|
@ -59,5 +59,7 @@ public interface ServiceOfferingDao extends GenericDao<ServiceOfferingVO, Long>
|
|||
|
||||
List<Long> listIdsByHostTag(String tag);
|
||||
|
||||
List<ServiceOfferingVO> listByCategoryId(Long categoryId);
|
||||
|
||||
void addCheckForGpuEnabled(SearchBuilder<ServiceOfferingVO> serviceOfferingSearch, Boolean gpuEnabled);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ public class ServiceOfferingDaoImpl extends GenericDaoBase<ServiceOfferingVO, Lo
|
|||
protected final SearchBuilder<ServiceOfferingVO> ServiceOfferingsByKeywordSearch;
|
||||
protected final SearchBuilder<ServiceOfferingVO> PublicCpuRamSearch;
|
||||
protected final SearchBuilder<ServiceOfferingVO> SearchComputeOfferingByComputeOnlyDiskOffering;
|
||||
protected final SearchBuilder<ServiceOfferingVO> CategoryIdSearch;
|
||||
|
||||
public ServiceOfferingDaoImpl() {
|
||||
super();
|
||||
|
|
@ -79,6 +80,17 @@ public class ServiceOfferingDaoImpl extends GenericDaoBase<ServiceOfferingVO, Lo
|
|||
SearchComputeOfferingByComputeOnlyDiskOffering = createSearchBuilder();
|
||||
SearchComputeOfferingByComputeOnlyDiskOffering.and("disk_offering_id", SearchComputeOfferingByComputeOnlyDiskOffering.entity().getDiskOfferingId(), SearchCriteria.Op.EQ);
|
||||
SearchComputeOfferingByComputeOnlyDiskOffering.done();
|
||||
|
||||
CategoryIdSearch = createSearchBuilder();
|
||||
CategoryIdSearch.and("category_id", CategoryIdSearch.entity().getCategoryId(), SearchCriteria.Op.EQ);
|
||||
CategoryIdSearch.done();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ServiceOfferingVO> listByCategoryId(Long categoryId) {
|
||||
SearchCriteria<ServiceOfferingVO> sc = CategoryIdSearch.create();
|
||||
sc.setParameters("category_id", categoryId);
|
||||
return listBy(sc);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@
|
|||
<bean id="roleDaoImpl" class="org.apache.cloudstack.acl.dao.RoleDaoImpl" />
|
||||
<bean id="serviceOfferingDaoImpl" class="com.cloud.service.dao.ServiceOfferingDaoImpl" />
|
||||
<bean id="serviceOfferingDetailsDaoImpl" class="com.cloud.service.dao.ServiceOfferingDetailsDaoImpl"/>
|
||||
<bean id="serviceOfferingCategoryDaoImpl" class="com.cloud.service.dao.ServiceOfferingCategoryDaoImpl" />
|
||||
<bean id="snapshotDaoImpl" class="com.cloud.storage.dao.SnapshotDaoImpl" />
|
||||
<bean id="snapshotZoneDaoImpl" class="com.cloud.storage.dao.SnapshotZoneDaoImpl" />
|
||||
<bean id="snapshotDataStoreDaoImpl" class="org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreDaoImpl" />
|
||||
|
|
|
|||
|
|
@ -19,6 +19,21 @@
|
|||
-- Schema upgrade from 4.22.1.0 to 4.23.0.0
|
||||
--;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `cloud`.`service_offering_category` (
|
||||
`id` bigint unsigned NOT NULL auto_increment,
|
||||
`name` varchar(255) NOT NULL,
|
||||
`uuid` varchar(40),
|
||||
`sort_key` int NOT NULL DEFAULT 0,
|
||||
PRIMARY KEY (`id`),
|
||||
CONSTRAINT `uc_service_offering_category__uuid` UNIQUE (`uuid`),
|
||||
CONSTRAINT `uc_service_offering_category__name` UNIQUE (`name`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
|
||||
|
||||
INSERT INTO `cloud`.`service_offering_category` (id, name, uuid) VALUES (1, 'Default', UUID());
|
||||
|
||||
ALTER TABLE `cloud`.`service_offering` ADD COLUMN `category_id` bigint unsigned NOT NULL DEFAULT 1;
|
||||
ALTER TABLE `cloud`.`service_offering` ADD CONSTRAINT `fk_service_offering__category_id` FOREIGN KEY (`category_id`) REFERENCES `cloud`.`service_offering_category` (`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
CREATE TABLE `cloud`.`backup_offering_details` (
|
||||
`id` bigint unsigned NOT NULL auto_increment,
|
||||
`backup_offering_id` bigint unsigned NOT NULL COMMENT 'Backup offering id',
|
||||
|
|
|
|||
|
|
@ -85,6 +85,9 @@ SELECT
|
|||
`vgpu_profile`.`max_resolution_y` AS `vgpu_profile_max_resolution_y`,
|
||||
`service_offering`.`gpu_count` AS `gpu_count`,
|
||||
`service_offering`.`gpu_display` AS `gpu_display`,
|
||||
`service_offering`.`category_id` AS `category_id`,
|
||||
`service_offering_category`.`uuid` AS `category_uuid`,
|
||||
`service_offering_category`.`name` AS `category_name`,
|
||||
GROUP_CONCAT(DISTINCT(domain.id)) AS domain_id,
|
||||
GROUP_CONCAT(DISTINCT(domain.uuid)) AS domain_uuid,
|
||||
GROUP_CONCAT(DISTINCT(domain.name)) AS domain_name,
|
||||
|
|
@ -105,6 +108,8 @@ FROM
|
|||
LEFT JOIN
|
||||
`cloud`.`gpu_card` ON vgpu_profile.card_id = gpu_card.id
|
||||
LEFT JOIN
|
||||
`cloud`.`service_offering_category` ON service_offering.category_id = service_offering_category.id
|
||||
LEFT JOIN
|
||||
`cloud`.`service_offering_details` AS `domain_details` ON `domain_details`.`service_offering_id` = `service_offering`.`id` AND `domain_details`.`name`='domainid'
|
||||
LEFT JOIN
|
||||
`cloud`.`domain` AS `domain` ON FIND_IN_SET(`domain`.`id`, `domain_details`.`value`)
|
||||
|
|
|
|||
|
|
@ -162,6 +162,7 @@ import org.apache.cloudstack.api.response.SecondaryStorageHeuristicsResponse;
|
|||
import org.apache.cloudstack.api.response.SecurityGroupResponse;
|
||||
import org.apache.cloudstack.api.response.SecurityGroupRuleResponse;
|
||||
import org.apache.cloudstack.api.response.ServiceOfferingResponse;
|
||||
import org.apache.cloudstack.api.response.ServiceOfferingCategoryResponse;
|
||||
import org.apache.cloudstack.api.response.ServiceResponse;
|
||||
import org.apache.cloudstack.api.response.SharedFSResponse;
|
||||
import org.apache.cloudstack.api.response.Site2SiteCustomerGatewayResponse;
|
||||
|
|
@ -384,6 +385,7 @@ import com.cloud.offering.DiskOffering;
|
|||
import com.cloud.offering.NetworkOffering;
|
||||
import com.cloud.offering.NetworkOffering.Detail;
|
||||
import com.cloud.offering.ServiceOffering;
|
||||
import com.cloud.offering.ServiceOfferingCategory;
|
||||
import com.cloud.offerings.NetworkOfferingVO;
|
||||
import com.cloud.offerings.dao.NetworkOfferingDao;
|
||||
import com.cloud.org.Cluster;
|
||||
|
|
@ -674,6 +676,16 @@ public class ApiResponseHelper implements ResponseGenerator, ResourceIdSupport {
|
|||
return ApiDBUtils.newServiceOfferingResponse(vOffering);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServiceOfferingCategoryResponse createServiceOfferingCategoryResponse(ServiceOfferingCategory category) {
|
||||
ServiceOfferingCategoryResponse response = new ServiceOfferingCategoryResponse();
|
||||
response.setId(category.getUuid());
|
||||
response.setName(category.getName());
|
||||
response.setSortKey(category.getSortKey());
|
||||
response.setObjectName("serviceofferingcategory");
|
||||
return response;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConfigurationResponse createConfigurationResponse(Configuration cfg) {
|
||||
ConfigurationResponse cfgResponse = new ConfigurationResponse();
|
||||
|
|
|
|||
|
|
@ -76,6 +76,7 @@ import org.apache.cloudstack.api.command.admin.host.ListHostsCmd;
|
|||
import org.apache.cloudstack.api.command.admin.internallb.ListInternalLBVMsCmd;
|
||||
import org.apache.cloudstack.api.command.admin.iso.ListIsosCmdByAdmin;
|
||||
import org.apache.cloudstack.api.command.admin.management.ListMgmtsCmd;
|
||||
import org.apache.cloudstack.api.command.admin.offering.ListServiceOfferingCategoriesCmd;
|
||||
import org.apache.cloudstack.api.command.admin.pod.ListPodsByCmd;
|
||||
import org.apache.cloudstack.api.command.admin.resource.icon.ListResourceIconCmd;
|
||||
import org.apache.cloudstack.api.command.admin.router.GetRouterHealthCheckResultsCmd;
|
||||
|
|
@ -145,6 +146,7 @@ import org.apache.cloudstack.api.response.RouterHealthCheckResultResponse;
|
|||
import org.apache.cloudstack.api.response.SecondaryStorageHeuristicsResponse;
|
||||
import org.apache.cloudstack.api.response.SecurityGroupResponse;
|
||||
import org.apache.cloudstack.api.response.ServiceOfferingResponse;
|
||||
import org.apache.cloudstack.api.response.ServiceOfferingCategoryResponse;
|
||||
import org.apache.cloudstack.api.response.SnapshotResponse;
|
||||
import org.apache.cloudstack.api.response.StorageAccessGroupResponse;
|
||||
import org.apache.cloudstack.api.response.StoragePoolResponse;
|
||||
|
|
@ -301,8 +303,10 @@ import com.cloud.server.ResourceManagerUtil;
|
|||
import com.cloud.server.ResourceMetaDataService;
|
||||
import com.cloud.server.ResourceTag;
|
||||
import com.cloud.server.ResourceTag.ResourceObjectType;
|
||||
import com.cloud.service.ServiceOfferingCategoryVO;
|
||||
import com.cloud.service.ServiceOfferingDetailsVO;
|
||||
import com.cloud.service.ServiceOfferingVO;
|
||||
import com.cloud.service.dao.ServiceOfferingCategoryDao;
|
||||
import com.cloud.service.dao.ServiceOfferingDao;
|
||||
import com.cloud.service.dao.ServiceOfferingDetailsDao;
|
||||
import com.cloud.storage.BucketVO;
|
||||
|
|
@ -484,6 +488,9 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
|
|||
@Inject
|
||||
ServiceOfferingDetailsDao _srvOfferingDetailsDao;
|
||||
|
||||
@Inject
|
||||
ServiceOfferingCategoryDao _serviceOfferingCategoryDao;
|
||||
|
||||
@Inject
|
||||
DiskOfferingDao _diskOfferingDao;
|
||||
|
||||
|
|
@ -4095,6 +4102,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
|
|||
ServiceOffering.State state = cmd.getState();
|
||||
final Long vgpuProfileId = cmd.getVgpuProfileId();
|
||||
final Boolean gpuEnabled = cmd.getGpuEnabled();
|
||||
Long categoryId = cmd.getCategoryId();
|
||||
|
||||
final Account owner = accountMgr.finalizeOwner(caller, accountName, domainId, projectId);
|
||||
|
||||
|
|
@ -4142,6 +4150,10 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
|
|||
_srvOfferingDao.addCheckForGpuEnabled(serviceOfferingSearch, gpuEnabled);
|
||||
}
|
||||
|
||||
if (categoryId != null) {
|
||||
serviceOfferingSearch.and("categoryId", serviceOfferingSearch.entity().getCategoryId(), Op.EQ);
|
||||
}
|
||||
|
||||
if (vmId != null) {
|
||||
currentVmOffering = _srvOfferingDao.findByIdIncludingRemoved(vmInstance.getId(), vmInstance.getServiceOfferingId());
|
||||
diskOffering = _diskOfferingDao.findByIdIncludingRemoved(currentVmOffering.getDiskOfferingId());
|
||||
|
|
@ -4435,6 +4447,10 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
|
|||
sc.setParameters("vgpuProfileId", vgpuProfileId);
|
||||
}
|
||||
|
||||
if (categoryId != null) {
|
||||
sc.setParameters("categoryId", categoryId);
|
||||
}
|
||||
|
||||
if (vmId != null) {
|
||||
if (!currentVmOffering.isDynamic()) {
|
||||
sc.setParameters("idNEQ", currentVmOffering.getId());
|
||||
|
|
@ -6354,6 +6370,46 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
|
|||
return bucketDao.searchByIds(bktIds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListResponse<ServiceOfferingCategoryResponse> listServiceOfferingCategories(ListServiceOfferingCategoriesCmd cmd) {
|
||||
Long id = cmd.getId();
|
||||
String name = cmd.getName();
|
||||
|
||||
Filter searchFilter = new Filter(ServiceOfferingCategoryVO.class, "sortKey", true, cmd.getStartIndex(), cmd.getPageSizeVal());
|
||||
SearchBuilder<ServiceOfferingCategoryVO> sb = _serviceOfferingCategoryDao.createSearchBuilder();
|
||||
|
||||
if (id != null) {
|
||||
sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
|
||||
}
|
||||
|
||||
if (name != null) {
|
||||
sb.and("name", sb.entity().getName(), SearchCriteria.Op.EQ);
|
||||
}
|
||||
|
||||
sb.done();
|
||||
SearchCriteria<ServiceOfferingCategoryVO> sc = sb.create();
|
||||
|
||||
if (id != null) {
|
||||
sc.setParameters("id", id);
|
||||
}
|
||||
|
||||
if (name != null) {
|
||||
sc.setParameters("name", name);
|
||||
}
|
||||
|
||||
Pair<List<ServiceOfferingCategoryVO>, Integer> result = _serviceOfferingCategoryDao.searchAndCount(sc, searchFilter);
|
||||
ListResponse<ServiceOfferingCategoryResponse> response = new ListResponse<>();
|
||||
List<ServiceOfferingCategoryResponse> responses = new ArrayList<>();
|
||||
|
||||
for (ServiceOfferingCategoryVO category : result.first()) {
|
||||
ServiceOfferingCategoryResponse categoryResponse = responseGenerator.createServiceOfferingCategoryResponse(category);
|
||||
responses.add(categoryResponse);
|
||||
}
|
||||
|
||||
response.setResponses(responses, result.second());
|
||||
return response;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getConfigComponentName() {
|
||||
return QueryService.class.getSimpleName();
|
||||
|
|
|
|||
|
|
@ -147,6 +147,13 @@ public class ServiceOfferingJoinDaoImpl extends GenericDaoBase<ServiceOfferingJo
|
|||
offeringResponse.setMaxResolutionY(offering.getMaxResolutionY());
|
||||
offeringResponse.setGpuCount(offering.getGpuCount());
|
||||
offeringResponse.setGpuDisplay(offering.getGpuDisplay());
|
||||
|
||||
// Set category information if available (joined via service_offering_view)
|
||||
if (offering.getCategoryUuid() != null) {
|
||||
offeringResponse.setCategoryId(offering.getCategoryUuid());
|
||||
offeringResponse.setCategoryName(offering.getCategoryName());
|
||||
}
|
||||
|
||||
offeringResponse.setNetworkRate(offering.getRateMbps());
|
||||
offeringResponse.setHostTag(offering.getHostTag());
|
||||
offeringResponse.setDeploymentPlanner(offering.getDeploymentPlanner());
|
||||
|
|
|
|||
|
|
@ -263,6 +263,15 @@ public class ServiceOfferingJoinVO extends BaseViewVO implements InternalIdentit
|
|||
@Column(name = "gpu_display")
|
||||
private Boolean gpuDisplay;
|
||||
|
||||
@Column(name = "category_id")
|
||||
private Long categoryId;
|
||||
|
||||
@Column(name = "category_uuid")
|
||||
private String categoryUuid;
|
||||
|
||||
@Column(name = "category_name")
|
||||
private String categoryName;
|
||||
|
||||
public ServiceOfferingJoinVO() {
|
||||
}
|
||||
|
||||
|
|
@ -557,4 +566,10 @@ public class ServiceOfferingJoinVO extends BaseViewVO implements InternalIdentit
|
|||
public Boolean getGpuDisplay() {
|
||||
return gpuDisplay;
|
||||
}
|
||||
|
||||
public Long getCategoryId() { return categoryId; }
|
||||
|
||||
public String getCategoryUuid() { return categoryUuid; }
|
||||
|
||||
public String getCategoryName() { return categoryName; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -82,11 +82,14 @@ import org.apache.cloudstack.api.command.admin.offering.CloneDiskOfferingCmd;
|
|||
import org.apache.cloudstack.api.command.admin.offering.CloneServiceOfferingCmd;
|
||||
import org.apache.cloudstack.api.command.admin.offering.CreateDiskOfferingCmd;
|
||||
import org.apache.cloudstack.api.command.admin.offering.CreateServiceOfferingCmd;
|
||||
import org.apache.cloudstack.api.command.admin.offering.CreateServiceOfferingCategoryCmd;
|
||||
import org.apache.cloudstack.api.command.admin.offering.DeleteDiskOfferingCmd;
|
||||
import org.apache.cloudstack.api.command.admin.offering.DeleteServiceOfferingCmd;
|
||||
import org.apache.cloudstack.api.command.admin.offering.DeleteServiceOfferingCategoryCmd;
|
||||
import org.apache.cloudstack.api.command.admin.offering.IsAccountAllowedToCreateOfferingsWithTagsCmd;
|
||||
import org.apache.cloudstack.api.command.admin.offering.UpdateDiskOfferingCmd;
|
||||
import org.apache.cloudstack.api.command.admin.offering.UpdateServiceOfferingCmd;
|
||||
import org.apache.cloudstack.api.command.admin.offering.UpdateServiceOfferingCategoryCmd;
|
||||
import org.apache.cloudstack.api.command.admin.pod.DeletePodCmd;
|
||||
import org.apache.cloudstack.api.command.admin.pod.UpdatePodCmd;
|
||||
import org.apache.cloudstack.api.command.admin.region.CreatePortableIpRangeCmd;
|
||||
|
|
@ -266,6 +269,7 @@ import com.cloud.offering.NetworkOffering;
|
|||
import com.cloud.offering.NetworkOffering.Availability;
|
||||
import com.cloud.offering.NetworkOffering.Detail;
|
||||
import com.cloud.offering.ServiceOffering;
|
||||
import com.cloud.offering.ServiceOfferingCategory;
|
||||
import com.cloud.offerings.NetworkOfferingDetailsVO;
|
||||
import com.cloud.offerings.NetworkOfferingServiceMapVO;
|
||||
import com.cloud.offerings.NetworkOfferingVO;
|
||||
|
|
@ -280,6 +284,8 @@ import com.cloud.resourcelimit.CheckedReservation;
|
|||
import com.cloud.server.ManagementService;
|
||||
import com.cloud.service.ServiceOfferingDetailsVO;
|
||||
import com.cloud.service.ServiceOfferingVO;
|
||||
import com.cloud.service.ServiceOfferingCategoryVO;
|
||||
import com.cloud.service.dao.ServiceOfferingCategoryDao;
|
||||
import com.cloud.service.dao.ServiceOfferingDao;
|
||||
import com.cloud.service.dao.ServiceOfferingDetailsDao;
|
||||
import com.cloud.storage.DiskOfferingVO;
|
||||
|
|
@ -376,6 +382,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
|||
@Inject
|
||||
ServiceOfferingDetailsDao _serviceOfferingDetailsDao;
|
||||
@Inject
|
||||
ServiceOfferingCategoryDao _serviceOfferingCategoryDao;
|
||||
@Inject
|
||||
DiskOfferingDao _diskOfferingDao;
|
||||
@Inject
|
||||
DiskOfferingDetailsDao diskOfferingDetailsDao;
|
||||
|
|
@ -3529,6 +3537,12 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
|||
}
|
||||
}
|
||||
|
||||
// validate optional category id
|
||||
final Long serviceOfferingCategoryId = cmd.getCategoryId();
|
||||
if (serviceOfferingCategoryId != null && _serviceOfferingCategoryDao.findById(serviceOfferingCategoryId) == null) {
|
||||
throw new InvalidParameterValueException("Please specify a valid service offering category id");
|
||||
}
|
||||
|
||||
// validate lease properties and set leaseExpiryAction
|
||||
Integer leaseDuration = cmd.getLeaseDuration();
|
||||
VMLeaseManager.ExpiryAction leaseExpiryAction = validateAndGetLeaseExpiryAction(leaseDuration, cmd.getLeaseExpiryAction());
|
||||
|
|
@ -3544,7 +3558,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
|||
cmd.getIopsReadRate(), cmd.getIopsReadRateMax(), cmd.getIopsReadRateMaxLength(),
|
||||
cmd.getIopsWriteRate(), cmd.getIopsWriteRateMax(), cmd.getIopsWriteRateMaxLength(),
|
||||
cmd.getHypervisorSnapshotReserve(), cmd.getCacheMode(), storagePolicyId, cmd.getDynamicScalingEnabled(), diskOfferingId,
|
||||
cmd.getDiskOfferingStrictness(), cmd.isCustomized(), cmd.getEncryptRoot(), vgpuProfileId, gpuCount, cmd.getGpuDisplay(), cmd.isPurgeResources(), leaseDuration, leaseExpiryAction);
|
||||
cmd.getDiskOfferingStrictness(), cmd.isCustomized(), cmd.getEncryptRoot(), vgpuProfileId, gpuCount, cmd.getGpuDisplay(), cmd.isPurgeResources(), leaseDuration, leaseExpiryAction, serviceOfferingCategoryId);
|
||||
}
|
||||
|
||||
private Integer validateVgpuProfileAndGetGpuCount(final Long vgpuProfileId, Integer gpuCount) {
|
||||
|
|
@ -3574,7 +3588,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
|||
Long iopsWriteRate, Long iopsWriteRateMax, Long iopsWriteRateMaxLength,
|
||||
final Integer hypervisorSnapshotReserve, String cacheMode, final Long storagePolicyID,
|
||||
final boolean dynamicScalingEnabled, final Long diskOfferingId, final boolean diskOfferingStrictness,
|
||||
final boolean isCustomized, final boolean encryptRoot, Long vgpuProfileId, Integer gpuCount, Boolean gpuDisplay, final boolean purgeResources, Integer leaseDuration, VMLeaseManager.ExpiryAction leaseExpiryAction) {
|
||||
final boolean isCustomized, final boolean encryptRoot, Long vgpuProfileId, Integer gpuCount, Boolean gpuDisplay, final boolean purgeResources, Integer leaseDuration, VMLeaseManager.ExpiryAction leaseExpiryAction, final Long categoryId) {
|
||||
|
||||
// Filter child domains when both parent and child domains are present
|
||||
List<Long> filteredDomainIds = domainHelper.filterChildSubDomains(domainIds);
|
||||
|
|
@ -3659,6 +3673,10 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
|||
serviceOffering.setVgpuProfileId(vgpuProfileId);
|
||||
serviceOffering.setGpuCount(gpuCount);
|
||||
serviceOffering.setGpuDisplay(gpuDisplay);
|
||||
// Set category if provided (categoryId was validated in caller)
|
||||
if (categoryId != null) {
|
||||
serviceOffering.setCategoryId(categoryId);
|
||||
}
|
||||
|
||||
DiskOfferingVO diskOffering = null;
|
||||
if (diskOfferingId == null) {
|
||||
|
|
@ -3969,7 +3987,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
|||
diskParams.iopsWriteRate, diskParams.iopsWriteRateMax, diskParams.iopsWriteRateMaxLength,
|
||||
diskParams.hypervisorSnapshotReserve, diskParams.cacheMode, customParams.storagePolicy, dynamicScalingEnabled,
|
||||
diskOfferingId, diskOfferingStrictness, isCustomized, encryptRoot,
|
||||
vgpuProfileId, finalGpuCount, gpuDisplay, purgeResources, leaseParams.leaseDuration, leaseParams.leaseExpiryAction);
|
||||
vgpuProfileId, finalGpuCount, gpuDisplay, purgeResources, leaseParams.leaseDuration, leaseParams.leaseExpiryAction, sourceOffering.getCategoryId());
|
||||
}
|
||||
|
||||
private ServiceOfferingVO getAndValidateSourceOffering(Long sourceOfferingId) {
|
||||
|
|
@ -4371,11 +4389,17 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
|||
boolean purgeResources = cmd.isPurgeResources();
|
||||
final Map<String, String> externalDetails = cmd.getExternalDetails();
|
||||
final boolean cleanupExternalDetails = cmd.isCleanupExternalDetails();
|
||||
final Long categoryId = cmd.getCategoryId();
|
||||
|
||||
if (userId == null) {
|
||||
userId = Long.valueOf(User.UID_SYSTEM);
|
||||
}
|
||||
|
||||
// Validate category if provided
|
||||
if (categoryId != null && _serviceOfferingCategoryDao.findById(categoryId) == null) {
|
||||
throw new InvalidParameterValueException("Please specify a valid service offering category id");
|
||||
}
|
||||
|
||||
// Verify input parameters
|
||||
final ServiceOffering offeringHandle = _entityMgr.findById(ServiceOffering.class, id);
|
||||
if (offeringHandle == null) {
|
||||
|
|
@ -4468,7 +4492,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
|||
throw new InvalidParameterValueException(String.format("Unable to update service offering: %s by id user: %s because it is not root-admin or domain-admin", offeringHandle, user));
|
||||
}
|
||||
|
||||
final boolean updateNeeded = name != null || displayText != null || sortKey != null || storageTags != null || hostTags != null || state != null;
|
||||
final boolean updateNeeded = name != null || displayText != null || sortKey != null || storageTags != null || hostTags != null || state != null || categoryId != null;
|
||||
final boolean serviceOfferingExternalDetailsNeedUpdate =
|
||||
serviceOfferingExternalDetailsNeedUpdate(offeringDetails, externalDetails, cleanupExternalDetails);
|
||||
final boolean detailsUpdateNeeded = !filteredDomainIds.equals(existingDomainIds) ||
|
||||
|
|
@ -4496,6 +4520,10 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
|||
offering.setState(state);
|
||||
}
|
||||
|
||||
if (categoryId != null) {
|
||||
offering.setCategoryId(categoryId);
|
||||
}
|
||||
|
||||
DiskOfferingVO diskOffering = _diskOfferingDao.findById(offeringHandle.getDiskOfferingId());
|
||||
updateOfferingTagsIfIsNotNull(storageTags, diskOffering);
|
||||
|
||||
|
|
@ -9552,4 +9580,97 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
|||
this.scope = scope;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ActionEvent(eventType = EventTypes.EVENT_SERVICE_OFFERING_CATEGORY_CREATE, eventDescription = "creating service offering category")
|
||||
public ServiceOfferingCategory createServiceOfferingCategory(CreateServiceOfferingCategoryCmd cmd) {
|
||||
String name = cmd.getName();
|
||||
Integer sortKey = cmd.getSortKey();
|
||||
|
||||
// Check if category with same name already exists
|
||||
ServiceOfferingCategoryVO existingCategory = _serviceOfferingCategoryDao.findByName(name);
|
||||
if (existingCategory != null) {
|
||||
throw new InvalidParameterValueException("Service offering category with name " + name + " already exists");
|
||||
}
|
||||
|
||||
ServiceOfferingCategoryVO category = new ServiceOfferingCategoryVO(name);
|
||||
if (sortKey != null) {
|
||||
category.setSortKey(sortKey);
|
||||
}
|
||||
|
||||
category = _serviceOfferingCategoryDao.persist(category);
|
||||
CallContext.current().setEventDetails("Service offering category id=" + category.getId());
|
||||
return category;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ActionEvent(eventType = EventTypes.EVENT_SERVICE_OFFERING_CATEGORY_DELETE, eventDescription = "deleting service offering category")
|
||||
public boolean deleteServiceOfferingCategory(DeleteServiceOfferingCategoryCmd cmd) {
|
||||
Long categoryId = cmd.getId();
|
||||
|
||||
ServiceOfferingCategoryVO category = _serviceOfferingCategoryDao.findById(categoryId);
|
||||
if (category == null) {
|
||||
throw new InvalidParameterValueException("Unable to find service offering category with id " + categoryId);
|
||||
}
|
||||
|
||||
// Check if any service offering is using this category
|
||||
// For now we'll just check if it's the default category (id=1)
|
||||
if (categoryId == 1L) {
|
||||
throw new InvalidParameterValueException("Cannot delete the default service offering category");
|
||||
}
|
||||
|
||||
// Check if any service offering is using this category
|
||||
List<ServiceOfferingVO> offeringsUsingCategory = _serviceOfferingDao.listByCategoryId(categoryId);
|
||||
if (offeringsUsingCategory != null && !offeringsUsingCategory.isEmpty()) {
|
||||
throw new InvalidParameterValueException("Cannot delete service offering category with id " + categoryId +
|
||||
" because it is in use by one or more service offerings.");
|
||||
}
|
||||
boolean result = _serviceOfferingCategoryDao.remove(categoryId);
|
||||
if (result) {
|
||||
CallContext.current().setEventDetails("Service offering category id=" + categoryId);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ActionEvent(eventType = EventTypes.EVENT_SERVICE_OFFERING_CATEGORY_EDIT, eventDescription = "updating service offering category")
|
||||
public ServiceOfferingCategory updateServiceOfferingCategory(UpdateServiceOfferingCategoryCmd cmd) {
|
||||
Long categoryId = cmd.getId();
|
||||
String name = cmd.getName();
|
||||
Integer sortKey = cmd.getSortKey();
|
||||
|
||||
// Validate category exists
|
||||
ServiceOfferingCategoryVO category = _serviceOfferingCategoryDao.findById(categoryId);
|
||||
if (category == null) {
|
||||
throw new InvalidParameterValueException("Unable to find service offering category with id " + categoryId);
|
||||
}
|
||||
|
||||
// Check if at least one parameter is being updated
|
||||
if (name == null && sortKey == null) {
|
||||
throw new InvalidParameterValueException("Please specify at least one parameter to update (name or sortKey)");
|
||||
}
|
||||
|
||||
// If name is being updated, check for duplicates
|
||||
if (name != null && !name.equals(category.getName())) {
|
||||
ServiceOfferingCategoryVO existingCategory = _serviceOfferingCategoryDao.findByName(name);
|
||||
if (existingCategory != null) {
|
||||
throw new InvalidParameterValueException("A service offering category with name '" + name + "' already exists");
|
||||
}
|
||||
category.setName(name);
|
||||
}
|
||||
|
||||
// Update sort key if provided
|
||||
if (sortKey != null) {
|
||||
category.setSortKey(sortKey);
|
||||
}
|
||||
|
||||
// Persist changes
|
||||
boolean updated = _serviceOfferingCategoryDao.update(categoryId, category);
|
||||
if (!updated) {
|
||||
throw new CloudRuntimeException("Failed to update service offering category");
|
||||
}
|
||||
|
||||
CallContext.current().setEventDetails("Service offering category id=" + categoryId);
|
||||
return _serviceOfferingCategoryDao.findById(categoryId);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -168,11 +168,15 @@ import org.apache.cloudstack.api.command.admin.offering.CloneDiskOfferingCmd;
|
|||
import org.apache.cloudstack.api.command.admin.offering.CloneServiceOfferingCmd;
|
||||
import org.apache.cloudstack.api.command.admin.offering.CreateDiskOfferingCmd;
|
||||
import org.apache.cloudstack.api.command.admin.offering.CreateServiceOfferingCmd;
|
||||
import org.apache.cloudstack.api.command.admin.offering.CreateServiceOfferingCategoryCmd;
|
||||
import org.apache.cloudstack.api.command.admin.offering.DeleteDiskOfferingCmd;
|
||||
import org.apache.cloudstack.api.command.admin.offering.DeleteServiceOfferingCmd;
|
||||
import org.apache.cloudstack.api.command.admin.offering.DeleteServiceOfferingCategoryCmd;
|
||||
import org.apache.cloudstack.api.command.admin.offering.IsAccountAllowedToCreateOfferingsWithTagsCmd;
|
||||
import org.apache.cloudstack.api.command.admin.offering.ListServiceOfferingCategoriesCmd;
|
||||
import org.apache.cloudstack.api.command.admin.offering.UpdateDiskOfferingCmd;
|
||||
import org.apache.cloudstack.api.command.admin.offering.UpdateServiceOfferingCmd;
|
||||
import org.apache.cloudstack.api.command.admin.offering.UpdateServiceOfferingCategoryCmd;
|
||||
import org.apache.cloudstack.api.command.admin.outofbandmanagement.ChangeOutOfBandManagementPasswordCmd;
|
||||
import org.apache.cloudstack.api.command.admin.outofbandmanagement.ConfigureOutOfBandManagementCmd;
|
||||
import org.apache.cloudstack.api.command.admin.outofbandmanagement.DisableOutOfBandManagementForClusterCmd;
|
||||
|
|
@ -3904,6 +3908,10 @@ public class ManagementServerImpl extends MutualExclusiveIdsManagerBase implemen
|
|||
cmdList.add(IsAccountAllowedToCreateOfferingsWithTagsCmd.class);
|
||||
cmdList.add(UpdateDiskOfferingCmd.class);
|
||||
cmdList.add(UpdateServiceOfferingCmd.class);
|
||||
cmdList.add(CreateServiceOfferingCategoryCmd.class);
|
||||
cmdList.add(ListServiceOfferingCategoriesCmd.class);
|
||||
cmdList.add(UpdateServiceOfferingCategoryCmd.class);
|
||||
cmdList.add(DeleteServiceOfferingCategoryCmd.class);
|
||||
cmdList.add(CreatePodCmd.class);
|
||||
cmdList.add(DeletePodCmd.class);
|
||||
cmdList.add(ListPodsByCmd.class);
|
||||
|
|
|
|||
|
|
@ -251,7 +251,7 @@ public class ConfigurationManagerCloneIntegrationTest {
|
|||
anyString(), anyMap(), anyLong(), any(Boolean.class),
|
||||
anyLong(), anyLong(), anyLong(), anyLong(), anyLong(), anyLong(), anyLong(), anyLong(), anyLong(), anyLong(), anyLong(), anyLong(), anyLong(), anyLong(),
|
||||
any(Integer.class), anyString(), anyLong(), anyBoolean(), anyLong(), anyBoolean(), anyBoolean(), anyBoolean(),
|
||||
anyLong(), any(Integer.class), any(Boolean.class), anyBoolean(), any(Integer.class), any(VMLeaseManager.ExpiryAction.class)
|
||||
anyLong(), any(Integer.class), any(Boolean.class), anyBoolean(), any(Integer.class), any(VMLeaseManager.ExpiryAction.class), anyLong()
|
||||
);
|
||||
|
||||
ServiceOffering result = configurationManager.cloneServiceOffering(cmd);
|
||||
|
|
@ -328,7 +328,7 @@ public class ConfigurationManagerCloneIntegrationTest {
|
|||
anyLong(), anyLong(), anyLong(), anyLong(), anyLong(), anyLong(), anyLong(),
|
||||
anyLong(), anyLong(), anyInt(), anyString(), anyLong(), anyBoolean(), anyLong(),
|
||||
anyBoolean(), anyBoolean(), anyBoolean(), anyLong(), anyInt(), anyBoolean(),
|
||||
anyBoolean(), anyInt(), any());
|
||||
anyBoolean(), anyInt(), any(), anyLong());
|
||||
|
||||
ServiceOffering result = configurationManager.cloneServiceOffering(cmd);
|
||||
|
||||
|
|
@ -553,7 +553,7 @@ public class ConfigurationManagerCloneIntegrationTest {
|
|||
anyLong(), anyLong(), anyLong(), anyLong(), anyLong(), anyLong(), anyLong(),
|
||||
anyLong(), anyLong(), anyInt(), anyString(), anyLong(), anyBoolean(), anyLong(),
|
||||
anyBoolean(), anyBoolean(), anyBoolean(), anyLong(), anyInt(), anyBoolean(),
|
||||
anyBoolean(), anyInt(), any());
|
||||
anyBoolean(), anyInt(), any(), anyLong());
|
||||
|
||||
ServiceOffering result = configurationManager.cloneServiceOffering(cmd);
|
||||
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ import com.cloud.offering.DiskOffering;
|
|||
import com.cloud.offering.NetworkOffering;
|
||||
import com.cloud.offering.NetworkOffering.Availability;
|
||||
import com.cloud.offering.ServiceOffering;
|
||||
import com.cloud.offering.ServiceOfferingCategory;
|
||||
import com.cloud.offerings.NetworkOfferingVO;
|
||||
import com.cloud.offerings.dao.NetworkOfferingDaoImpl;
|
||||
import com.cloud.org.Grouping.AllocationState;
|
||||
|
|
@ -65,11 +66,14 @@ import org.apache.cloudstack.api.command.admin.offering.CloneDiskOfferingCmd;
|
|||
import org.apache.cloudstack.api.command.admin.offering.CloneServiceOfferingCmd;
|
||||
import org.apache.cloudstack.api.command.admin.offering.CreateDiskOfferingCmd;
|
||||
import org.apache.cloudstack.api.command.admin.offering.CreateServiceOfferingCmd;
|
||||
import org.apache.cloudstack.api.command.admin.offering.CreateServiceOfferingCategoryCmd;
|
||||
import org.apache.cloudstack.api.command.admin.offering.DeleteDiskOfferingCmd;
|
||||
import org.apache.cloudstack.api.command.admin.offering.DeleteServiceOfferingCmd;
|
||||
import org.apache.cloudstack.api.command.admin.offering.DeleteServiceOfferingCategoryCmd;
|
||||
import org.apache.cloudstack.api.command.admin.offering.IsAccountAllowedToCreateOfferingsWithTagsCmd;
|
||||
import org.apache.cloudstack.api.command.admin.offering.UpdateDiskOfferingCmd;
|
||||
import org.apache.cloudstack.api.command.admin.offering.UpdateServiceOfferingCmd;
|
||||
import org.apache.cloudstack.api.command.admin.offering.UpdateServiceOfferingCategoryCmd;
|
||||
import org.apache.cloudstack.api.command.admin.pod.DeletePodCmd;
|
||||
import org.apache.cloudstack.api.command.admin.pod.UpdatePodCmd;
|
||||
import org.apache.cloudstack.api.command.admin.region.CreatePortableIpRangeCmd;
|
||||
|
|
@ -168,6 +172,24 @@ public class MockConfigurationManagerImpl extends ManagerBase implements Configu
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServiceOfferingCategory createServiceOfferingCategory(CreateServiceOfferingCategoryCmd cmd) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteServiceOfferingCategory(DeleteServiceOfferingCategoryCmd cmd) {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServiceOfferingCategory updateServiceOfferingCategory(UpdateServiceOfferingCategoryCmd cmd) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.cloud.configuration.ConfigurationService#updateDiskOffering(org.apache.cloudstack.api.commands.UpdateDiskOfferingCmd)
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -535,6 +535,8 @@
|
|||
"label.capacitybytes": "Capacity bytes",
|
||||
"label.capacityiops": "IOPS total",
|
||||
"label.category": "Category",
|
||||
"label.categoryid": "Category",
|
||||
"label.categoryname": "Category name",
|
||||
"label.certchain": "Chain",
|
||||
"label.certificate": "Certificate",
|
||||
"label.certificate.chain": "Certificate chain",
|
||||
|
|
@ -1222,6 +1224,10 @@
|
|||
"label.guest.os.category": "Guest OS Category",
|
||||
"label.guest.os.categories": "Guest OS Categories",
|
||||
"label.guest.os.hypervisor.mappings": "Guest OS mappings",
|
||||
"label.service.offering.categories": "Service Offering Categories",
|
||||
"label.add.service.offering.category": "Add Service Offering Category",
|
||||
"label.action.delete.service.offering.category": "Delete Service Offering Category",
|
||||
"message.action.delete.service.offering.category": "Please confirm that you want to delete this service offering category",
|
||||
"label.guest.start.ip": "Guest start IP",
|
||||
"label.guest.traffic": "Guest traffic",
|
||||
"label.guestcidraddress": "Guest CIDR",
|
||||
|
|
|
|||
|
|
@ -39,6 +39,25 @@
|
|||
v-model:value="form.displaytext"
|
||||
:placeholder="$t('label.displaytext')"/>
|
||||
</a-form-item>
|
||||
<a-form-item name="categoryid" ref="categoryid" v-if="!isSystem">
|
||||
<template #label>
|
||||
<tooltip-label :title="$t('label.category')" :tooltip="apiParams.categoryid ? apiParams.categoryid.description : $t('label.category')"/>
|
||||
</template>
|
||||
<a-select
|
||||
:getPopupContainer="(trigger) => trigger.parentNode"
|
||||
v-model:value="form.categoryid"
|
||||
showSearch
|
||||
optionFilterProp="label"
|
||||
:filterOption="(input, option) => {
|
||||
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
|
||||
}"
|
||||
:loading="categoryLoading"
|
||||
:placeholder="$t('label.category')">
|
||||
<a-select-option v-for="category in categories" :key="category.id" :label="category.name">
|
||||
{{ category.name }}
|
||||
</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item name="systemvmtype" ref="systemvmtype" v-if="isSystem">
|
||||
<template #label>
|
||||
<tooltip-label :title="$t('label.systemvmtype')" :tooltip="apiParams.systemvmtype.description"/>
|
||||
|
|
@ -667,7 +686,9 @@ export default {
|
|||
leaseexpiryaction: undefined,
|
||||
vgpuProfiles: [],
|
||||
vgpuProfileLoading: false,
|
||||
externalDetailsEnabled: false
|
||||
externalDetailsEnabled: false,
|
||||
categories: [],
|
||||
categoryLoading: false
|
||||
}
|
||||
},
|
||||
created () {
|
||||
|
|
@ -688,6 +709,7 @@ export default {
|
|||
this.fetchDomainData()
|
||||
this.fetchZoneData()
|
||||
this.fetchGPUCards()
|
||||
this.fetchCategories()
|
||||
if (isAdmin()) {
|
||||
this.fetchStorageTagData()
|
||||
this.fetchDeploymentPlannerData()
|
||||
|
|
@ -709,6 +731,14 @@ export default {
|
|||
this.gpuCardLoading = false
|
||||
})
|
||||
},
|
||||
fetchCategories () {
|
||||
this.categoryLoading = true
|
||||
getAPI('listServiceOfferingCategories', {}).then(json => {
|
||||
this.categories = json.listserviceofferingcategoriesresponse.serviceofferingcategory || []
|
||||
}).finally(() => {
|
||||
this.categoryLoading = false
|
||||
})
|
||||
},
|
||||
addDiskOffering () { this.showDiskOfferingModal = true },
|
||||
fetchDiskOfferings () {
|
||||
this.diskOfferingLoading = true
|
||||
|
|
|
|||
|
|
@ -1053,6 +1053,9 @@
|
|||
<template v-if="column.key === 'vgpuActions'">
|
||||
<slot name="actionButtons" :record="record" :actions="actions"></slot>
|
||||
</template>
|
||||
<template v-if="column.key === 'category' && $route.path.split('/')[1] === 'computeoffering'">
|
||||
<router-link :to="{ path: '/serviceofferingcategory/' + record.categoryid }">{{ text }}</router-link>
|
||||
</template>
|
||||
</template>
|
||||
<template #footer>
|
||||
<span v-if="hasSelected">
|
||||
|
|
@ -1330,6 +1333,9 @@ export default {
|
|||
case 'guestoscategory':
|
||||
apiCommand = 'updateOsCategory'
|
||||
break
|
||||
case 'serviceofferingcategory':
|
||||
apiCommand = 'updateServiceOfferingCategory'
|
||||
break
|
||||
}
|
||||
return apiCommand
|
||||
},
|
||||
|
|
|
|||
|
|
@ -202,6 +202,40 @@ export default {
|
|||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'serviceofferingcategory',
|
||||
title: 'label.service.offering.categories',
|
||||
icon: 'shopping-outlined',
|
||||
permission: ['listServiceOfferingCategories'],
|
||||
columns: ['name', 'order'],
|
||||
details: ['name', 'id'],
|
||||
actions: [
|
||||
{
|
||||
api: 'createServiceOfferingCategory',
|
||||
icon: 'plus-outlined',
|
||||
label: 'label.add.service.offering.category',
|
||||
listView: true,
|
||||
dataView: false,
|
||||
args: ['name']
|
||||
},
|
||||
{
|
||||
api: 'updateServiceOfferingCategory',
|
||||
icon: 'edit-outlined',
|
||||
label: 'label.edit',
|
||||
dataView: true,
|
||||
popup: true,
|
||||
args: ['name']
|
||||
},
|
||||
{
|
||||
api: 'deleteServiceOfferingCategory',
|
||||
icon: 'delete-outlined',
|
||||
label: 'label.action.delete.service.offering.category',
|
||||
message: 'message.action.delete.service.offering.category',
|
||||
dataView: true,
|
||||
popup: true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'guestos',
|
||||
title: 'label.guest.os',
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ export default {
|
|||
docHelp: 'adminguide/service_offerings.html#compute-and-disk-service-offerings',
|
||||
icon: 'cloud-outlined',
|
||||
permission: ['listServiceOfferings'],
|
||||
searchFilters: ['name', 'gpuenabled', 'zoneid', 'domainid', 'cpunumber', 'cpuspeed', 'memory'],
|
||||
searchFilters: ['name', 'gpuenabled', 'zoneid', 'domainid', 'cpunumber', 'cpuspeed', 'memory', 'categoryid'],
|
||||
params: () => {
|
||||
var params = {}
|
||||
if (['Admin', 'DomainAdmin'].includes(store.getters.userInfo.roletype)) {
|
||||
|
|
@ -39,9 +39,9 @@ export default {
|
|||
return params
|
||||
},
|
||||
filters: ['active', 'inactive'],
|
||||
columns: ['name', 'displaytext', 'state', 'cpunumber', 'cpuspeed', 'memory', 'gpu', 'domain', 'zone', 'order'],
|
||||
columns: ['name', 'displaytext', 'state', 'cpunumber', 'cpuspeed', 'memory', 'gpu', 'category', 'domain', 'zone', 'order'],
|
||||
details: () => {
|
||||
var fields = ['name', 'id', 'displaytext', 'offerha', 'provisioningtype', 'storagetype', 'iscustomized', 'iscustomizediops', 'limitcpuuse', 'cpunumber', 'cpuspeed', 'memory', 'hosttags', 'tags', 'storageaccessgroups', 'storagetags', 'domain', 'zone', 'created', 'dynamicscalingenabled', 'diskofferingstrictness', 'encryptroot', 'purgeresources', 'leaseduration', 'gpucardid', 'gpucardname', 'vgpuprofileid', 'vgpuprofilename', 'gpucount', 'gpudisplay', 'leaseexpiryaction', 'externaldetails']
|
||||
var fields = ['name', 'id', 'displaytext', 'offerha', 'provisioningtype', 'storagetype', 'iscustomized', 'iscustomizediops', 'limitcpuuse', 'cpunumber', 'cpuspeed', 'memory', 'hosttags', 'tags', 'storageaccessgroups', 'storagetags', 'domain', 'zone', 'created', 'dynamicscalingenabled', 'diskofferingstrictness', 'encryptroot', 'purgeresources', 'leaseduration', 'gpucardid', 'gpucardname', 'vgpuprofileid', 'vgpuprofilename', 'gpucount', 'gpudisplay', 'leaseexpiryaction', 'externaldetails', 'category']
|
||||
if (store.getters.apis.createServiceOffering &&
|
||||
store.getters.apis.createServiceOffering.params.filter(x => x.name === 'storagepolicy').length > 0) {
|
||||
fields.splice(6, 0, 'vspherestoragepolicy')
|
||||
|
|
@ -96,8 +96,11 @@ export default {
|
|||
label: 'label.edit',
|
||||
docHelp: 'adminguide/service_offerings.html#modifying-or-deleting-a-service-offering',
|
||||
dataView: true,
|
||||
args: ['name', 'displaytext', 'storagetags', 'hosttags', 'externaldetails'],
|
||||
args: ['name', 'displaytext', 'categoryid', 'storagetags', 'hosttags', 'externaldetails'],
|
||||
mapping: {
|
||||
categoryid: {
|
||||
api: 'listServiceOfferingCategories'
|
||||
},
|
||||
externaldetails: {
|
||||
transformedvalue: (record) => { return getFilteredExternalDetails(record.serviceofferingdetails) }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -261,8 +261,11 @@
|
|||
:minimum-cpunumber="templateConfigurationExists && selectedTemplateConfiguration && selectedTemplateConfiguration.cpunumber ? selectedTemplateConfiguration.cpunumber : 0"
|
||||
:minimum-cpuspeed="templateConfigurationExists && selectedTemplateConfiguration && selectedTemplateConfiguration.cpuspeed ? selectedTemplateConfiguration.cpuspeed : 0"
|
||||
:minimum-memory="templateConfigurationExists && selectedTemplateConfiguration && selectedTemplateConfiguration.memory ? selectedTemplateConfiguration.memory : 0"
|
||||
:service-offering-categories="options.serviceOfferingCategories"
|
||||
:selected-service-offering-category-id="selectedServiceOfferingCategoryId"
|
||||
@select-compute-item="($event) => updateComputeOffering($event)"
|
||||
@handle-search-filter="($event) => handleSearchFilter('serviceOfferings', $event)"
|
||||
@service-offering-category-change="($event) => handleServiceOfferingCategoryChange($event)"
|
||||
></compute-offering-selection>
|
||||
<compute-selection
|
||||
v-if="serviceOffering && (serviceOffering.iscustomized || serviceOffering.iscustomizediops)"
|
||||
|
|
@ -2333,6 +2336,46 @@ export default {
|
|||
console.error('Error fetching guestOsCategories:', e)
|
||||
})
|
||||
},
|
||||
fetchServiceOfferingCategories () {
|
||||
this.loading.serviceOfferingCategories = true
|
||||
return new Promise((resolve, reject) => {
|
||||
getAPI('listServiceOfferingCategories').then(json => {
|
||||
const categories = json.listserviceofferingcategoriesresponse.serviceofferingcategory || []
|
||||
this.options.serviceOfferingCategories = [
|
||||
{
|
||||
id: '-1',
|
||||
name: this.$t('label.all')
|
||||
},
|
||||
...categories
|
||||
]
|
||||
resolve()
|
||||
}).catch(error => {
|
||||
console.error('Error fetching service offering categories:', error)
|
||||
this.options.serviceOfferingCategories = [
|
||||
{
|
||||
id: '-1',
|
||||
name: this.$t('label.all')
|
||||
}
|
||||
]
|
||||
reject(error)
|
||||
}).finally(() => {
|
||||
this.loading.serviceOfferingCategories = false
|
||||
})
|
||||
})
|
||||
},
|
||||
handleServiceOfferingCategoryChange (categoryId) {
|
||||
this.selectedServiceOfferingCategoryId = categoryId
|
||||
const params = {
|
||||
page: 1,
|
||||
pageSize: 10
|
||||
}
|
||||
if (categoryId && categoryId !== '-1') {
|
||||
params.categoryid = categoryId
|
||||
} else {
|
||||
this.deleteFrom(this.params.serviceOfferings.options, ['categoryid'])
|
||||
}
|
||||
this.handleSearchFilter('serviceOfferings', params)
|
||||
},
|
||||
changeArchitecture (arch) {
|
||||
this.selectedArchitecture = arch
|
||||
this.updateImages()
|
||||
|
|
@ -3112,6 +3155,8 @@ export default {
|
|||
if (this.isModernImageSelection && guestOsFetch) {
|
||||
await guestOsFetch
|
||||
}
|
||||
// Load service offering categories
|
||||
this.fetchServiceOfferingCategories()
|
||||
this.fetchImages()
|
||||
this.updateTemplateKey()
|
||||
this.formModel = toRaw(this.form)
|
||||
|
|
|
|||
|
|
@ -167,8 +167,11 @@
|
|||
:minimum-cpunumber="templateConfigurationExists && selectedTemplateConfiguration && selectedTemplateConfiguration.cpunumber ? selectedTemplateConfiguration.cpunumber : 0"
|
||||
:minimum-cpuspeed="templateConfigurationExists && selectedTemplateConfiguration && selectedTemplateConfiguration.cpuspeed ? selectedTemplateConfiguration.cpuspeed : 0"
|
||||
:minimum-memory="templateConfigurationExists && selectedTemplateConfiguration && selectedTemplateConfiguration.memory ? selectedTemplateConfiguration.memory : 0"
|
||||
:service-offering-categories="options.serviceOfferingCategories"
|
||||
:selected-service-offering-category-id="selectedServiceOfferingCategoryId"
|
||||
@select-compute-item="($event) => updateComputeOffering($event)"
|
||||
@handle-search-filter="($event) => handleSearchFilter('serviceOfferings', $event)"
|
||||
@service-offering-category-change="($event) => handleServiceOfferingCategoryChange($event)"
|
||||
></compute-offering-selection>
|
||||
<compute-selection
|
||||
v-if="serviceOffering && (serviceOffering.iscustomized || serviceOffering.iscustomizediops)"
|
||||
|
|
@ -935,8 +938,10 @@ export default {
|
|||
rootdisksize: null,
|
||||
disksize: null
|
||||
},
|
||||
selectedServiceOfferingCategoryId: '-1',
|
||||
options: {
|
||||
guestOsCategories: [],
|
||||
serviceOfferingCategories: [],
|
||||
templates: {},
|
||||
isos: {},
|
||||
hypervisors: [],
|
||||
|
|
@ -960,6 +965,7 @@ export default {
|
|||
loading: {
|
||||
deploy: false,
|
||||
guestOsCategories: false,
|
||||
serviceOfferingCategories: false,
|
||||
templates: false,
|
||||
isos: false,
|
||||
hypervisors: false,
|
||||
|
|
@ -2639,6 +2645,8 @@ export default {
|
|||
if (this.isModernImageSelection && guestOsFetch) {
|
||||
await guestOsFetch
|
||||
}
|
||||
// Load service offering categories
|
||||
this.fetchServiceOfferingCategories()
|
||||
this.fetchAllTemplates()
|
||||
this.updateTemplateKey()
|
||||
this.formModel = toRaw(this.form)
|
||||
|
|
@ -2700,6 +2708,46 @@ export default {
|
|||
this.params[name].options = { ...this.params[name].options, ...options }
|
||||
this.fetchOptions(this.params[name], name)
|
||||
},
|
||||
fetchServiceOfferingCategories () {
|
||||
this.loading.serviceOfferingCategories = true
|
||||
return new Promise((resolve, reject) => {
|
||||
getAPI('listServiceOfferingCategories').then(json => {
|
||||
const categories = json.listserviceofferingcategoriesresponse.serviceofferingcategory || []
|
||||
this.options.serviceOfferingCategories = [
|
||||
{
|
||||
id: '-1',
|
||||
name: this.$t('label.all')
|
||||
},
|
||||
...categories
|
||||
]
|
||||
resolve()
|
||||
}).catch(error => {
|
||||
console.error('Error fetching service offering categories:', error)
|
||||
this.options.serviceOfferingCategories = [
|
||||
{
|
||||
id: '-1',
|
||||
name: this.$t('label.all')
|
||||
}
|
||||
]
|
||||
reject(error)
|
||||
}).finally(() => {
|
||||
this.loading.serviceOfferingCategories = false
|
||||
})
|
||||
})
|
||||
},
|
||||
handleServiceOfferingCategoryChange (categoryId) {
|
||||
this.selectedServiceOfferingCategoryId = categoryId
|
||||
const params = {
|
||||
page: 1,
|
||||
pageSize: 10
|
||||
}
|
||||
if (categoryId && categoryId !== '-1') {
|
||||
params.categoryid = categoryId
|
||||
} else {
|
||||
this.deleteFrom(this.params.serviceOfferings.options, ['categoryid'])
|
||||
}
|
||||
this.handleSearchFilter('serviceOfferings', params)
|
||||
},
|
||||
onTabChange (key, type) {
|
||||
this[type] = key
|
||||
},
|
||||
|
|
|
|||
|
|
@ -17,6 +17,25 @@
|
|||
|
||||
<template>
|
||||
<div>
|
||||
<a-form-item
|
||||
:label="$t('label.category')"
|
||||
name="serviceofferingcategoryid"
|
||||
ref="serviceofferingcategoryid"
|
||||
v-if="serviceOfferingCategories && serviceOfferingCategories.length > 0"
|
||||
style="margin-bottom: 16px;">
|
||||
<block-radio-group-select
|
||||
:maxBlocks="16"
|
||||
:items="serviceOfferingCategories"
|
||||
:selectedValue="selectedServiceOfferingCategoryId"
|
||||
:horizontalGutter="6"
|
||||
:verticalGutter="6"
|
||||
blockSize="medium"
|
||||
@change="handleServiceOfferingCategoryChange">
|
||||
<template #radio-option="{ item }">
|
||||
{{ item.name }}
|
||||
</template>
|
||||
</block-radio-group-select>
|
||||
</a-form-item>
|
||||
<div style="margin-bottom: 16px; display: flex; justify-content: right; align-items: center;">
|
||||
<div v-if="showGpuFilter" style="display: flex; align-items: center; margin-right: 16px;">
|
||||
<span>{{ $t('label.show.only.gpu.enabled.offerings') }}</span>
|
||||
|
|
@ -96,8 +115,13 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import BlockRadioGroupSelect from '@/components/widgets/BlockRadioGroupSelect.vue'
|
||||
|
||||
export default {
|
||||
name: 'ComputeOfferingSelection',
|
||||
components: {
|
||||
BlockRadioGroupSelect
|
||||
},
|
||||
props: {
|
||||
computeItems: {
|
||||
type: Array,
|
||||
|
|
@ -152,6 +176,14 @@ export default {
|
|||
type: Boolean,
|
||||
required: false,
|
||||
default: false
|
||||
},
|
||||
serviceOfferingCategories: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
selectedServiceOfferingCategoryId: {
|
||||
type: String,
|
||||
default: '-1'
|
||||
}
|
||||
},
|
||||
data () {
|
||||
|
|
@ -335,6 +367,9 @@ export default {
|
|||
}
|
||||
},
|
||||
methods: {
|
||||
handleServiceOfferingCategoryChange (categoryId) {
|
||||
this.$emit('service-offering-category-change', categoryId)
|
||||
},
|
||||
onSelectRow (value) {
|
||||
this.selectedRowKeys = value
|
||||
this.$emit('select-compute-item', value[0])
|
||||
|
|
@ -402,4 +437,26 @@ export default {
|
|||
:deep(.ant-table-tbody) > tr > td {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.radio-option {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
.radio-option__icon {
|
||||
font-size: 2rem;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.ellipsis {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -359,6 +359,11 @@ export default {
|
|||
params.diskofferingid = values.diskofferingid
|
||||
}
|
||||
|
||||
if (values.categoryid) {
|
||||
params.categoryid = values.categoryid
|
||||
}
|
||||
|
||||
// Add GPU parameters
|
||||
if (values.vgpuprofile) {
|
||||
params.vgpuprofileid = values.vgpuprofile
|
||||
}
|
||||
|
|
|
|||
|
|
@ -502,6 +502,10 @@ export default {
|
|||
params.diskofferingid = values.diskofferingid
|
||||
}
|
||||
|
||||
if (values.categoryid) {
|
||||
params.categoryid = values.categoryid
|
||||
}
|
||||
|
||||
if (values.vgpuprofile) {
|
||||
params.vgpuprofileid = values.vgpuprofile
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue