From df2131810f9cc4454f899bd91a6ec5caeadd2c8d Mon Sep 17 00:00:00 2001 From: Manoj Kumar Date: Fri, 13 Feb 2026 13:52:08 +0530 Subject: [PATCH] 1. Setup Dns zone schema 2. added relevant changes in dao and vo 3. worked on creatednszone, integration with mgr 4. powerdns create zone api call --- .../command/user/dns/CreateDnsZoneCmd.java | 22 ++--- .../api/response/DnsZoneResponse.java | 50 ++++++++-- .../apache/cloudstack/dns/DnsProvider.java | 3 +- .../cloudstack/dns/DnsProviderManager.java | 6 +- .../org/apache/cloudstack/dns/DnsZone.java | 7 +- .../META-INF/db/schema-42210to42300.sql | 15 ++- .../dns/powerdns/PowerDnsClient.java | 93 ++++++++++++++++--- .../dns/powerdns/PowerDnsProvider.java | 16 +++- .../dns/DnsProviderManagerImpl.java | 61 +++++++++++- .../apache/cloudstack/dns/dao/DnsZoneDao.java | 3 + .../cloudstack/dns/dao/DnsZoneDaoImpl.java | 30 ++++++ .../apache/cloudstack/dns/vo/DnsZoneVO.java | 41 +++++++- 12 files changed, 293 insertions(+), 54 deletions(-) diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/dns/CreateDnsZoneCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/dns/CreateDnsZoneCmd.java index 7c1e2f9c7f5..3e85946222c 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/dns/CreateDnsZoneCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/dns/CreateDnsZoneCmd.java @@ -23,7 +23,7 @@ import com.cloud.exception.ResourceAllocationException; requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateDnsZoneCmd extends BaseAsyncCreateCmd { - private static final String s_name = "creatednszoneresponse"; + private static final String COMMAND_RESPONSE_NAME = "creatednszoneresponse"; @Inject DnsProviderManager dnsProviderManager; @@ -48,8 +48,8 @@ public class CreateDnsZoneCmd extends BaseAsyncCreateCmd { description = "The type of zone (Public, Private). Defaults to Public.") private String type; - // Standard CloudStack ownership parameters (account/domain) are handled - // automatically by the BaseCmd parent if we access them via getEntityOwnerId() + @Parameter(name = ApiConstants.DESCRIPTION, type = CommandType.STRING, description = "Display text for the zone") + private String description; ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// @@ -71,16 +71,18 @@ public class CreateDnsZoneCmd extends BaseAsyncCreateCmd { return type; } + public String getDescription() { + return description; + } + ///////////////////////////////////////////////////// /////////////// Implementation ////////////////////// ///////////////////////////////////////////////////// @Override public void create() throws ResourceAllocationException { - // Phase 1: DB Persist - // The manager should create the DnsZoneVO in 'Allocating' state try { - DnsZone zone = dnsProviderManager.allocDnsZone(this); + DnsZone zone = dnsProviderManager.allocateDnsZone(this); if (zone != null) { setEntityId(zone.getId()); setEntityUuid(zone.getUuid()); @@ -94,12 +96,8 @@ public class CreateDnsZoneCmd extends BaseAsyncCreateCmd { @Override public void execute() { - // Phase 2: Action (Call Plugin) - // The manager should retrieve the zone by ID, call the plugin, and update state to 'Ready' try { - // Note: We use getEntityId() which was set in the create() phase DnsZone result = dnsProviderManager.provisionDnsZone(getEntityId()); - if (result != null) { DnsZoneResponse response = dnsProviderManager.createDnsZoneResponse(result); response.setResponseName(getCommandName()); @@ -114,7 +112,7 @@ public class CreateDnsZoneCmd extends BaseAsyncCreateCmd { @Override public String getCommandName() { - return s_name; + return COMMAND_RESPONSE_NAME; } @Override @@ -124,7 +122,7 @@ public class CreateDnsZoneCmd extends BaseAsyncCreateCmd { @Override public String getEventType() { - return EventTypes.EVENT_DNS_ZONE_CREATE; // You must add this constant to EventTypes.java + return EventTypes.EVENT_DNS_ZONE_CREATE; } @Override diff --git a/api/src/main/java/org/apache/cloudstack/api/response/DnsZoneResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/DnsZoneResponse.java index 9519555e2b7..f8ef89824c4 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/DnsZoneResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/DnsZoneResponse.java @@ -28,35 +28,67 @@ import com.google.gson.annotations.SerializedName; @EntityReference(value = DnsZone.class) public class DnsZoneResponse extends BaseResponse { @SerializedName(ApiConstants.ID) - @Param(description = "the ID of the DNS zone") + @Param(description = "ID of the DNS zone") private String id; @SerializedName(ApiConstants.NAME) - @Param(description = "the name of the DNS zone") + @Param(description = "Name of the DNS zone") private String name; @SerializedName("dnsserverid") - @Param(description = "the ID of the DNS server this zone belongs to") - private String dnsServerId; + @Param(description = "ID of the DNS server this zone belongs to") + private Long dnsServerId; @SerializedName("dnsservername") - @Param(description = "the name of the DNS server this zone belongs to") + @Param(description = "Name of the DNS server this zone belongs to") private String dnsServerName; @SerializedName(ApiConstants.NETWORK_ID) - @Param(description = "the ID of the network this zone is associated with") + @Param(description = "ID of the network this zone is associated with") private String networkId; @SerializedName(ApiConstants.NETWORK_NAME) - @Param(description = "the name of the network this zone is associated with") + @Param(description = "Name of the network this zone is associated with") private String networkName; @SerializedName(ApiConstants.TYPE) - @Param(description = "the type of the zone (Public/Private)") - private String type; + @Param(description = "The type of the zone (Public/Private)") + private DnsZone.ZoneType type; + + @SerializedName(ApiConstants.STATE) + @Param(description = "The state of the zone (Active/Inactive)") + private DnsZone.State state; public DnsZoneResponse() { super(); setObjectName("dnszone"); } + + public void setName(String name) { + this.name = name; + } + + public void setDnsServerId(Long dnsServerId) { + this.dnsServerId = dnsServerId; + } + + public void setDnsServerName(String dnsServerName) { + this.dnsServerName = dnsServerName; + } + + public void setNetworkId(String networkId) { + this.networkId = networkId; + } + + public void setNetworkName(String networkName) { + this.networkName = networkName; + } + + public void setType(DnsZone.ZoneType type) { + this.type = type; + } + + public void setState(DnsZone.State state) { + this.state = state; + } } diff --git a/api/src/main/java/org/apache/cloudstack/dns/DnsProvider.java b/api/src/main/java/org/apache/cloudstack/dns/DnsProvider.java index c0687571375..68ebd2a682d 100644 --- a/api/src/main/java/org/apache/cloudstack/dns/DnsProvider.java +++ b/api/src/main/java/org/apache/cloudstack/dns/DnsProvider.java @@ -28,10 +28,9 @@ public interface DnsProvider extends Adapter { boolean validate(DnsServer server) throws Exception; // Zone Operations - boolean createZone(DnsServer server, DnsZone zone); + boolean provisionZone(DnsServer server, DnsZone zone) throws Exception; boolean deleteZone(DnsServer server, DnsZone zone); - DnsRecord createRecord(DnsServer server, DnsZone zone, DnsRecord record); boolean updateRecord(DnsServer server, DnsZone zone, DnsRecord record); boolean deleteRecord(DnsServer server, DnsZone zone, DnsRecord record); diff --git a/api/src/main/java/org/apache/cloudstack/dns/DnsProviderManager.java b/api/src/main/java/org/apache/cloudstack/dns/DnsProviderManager.java index 138b32943dc..0421e8fffb6 100644 --- a/api/src/main/java/org/apache/cloudstack/dns/DnsProviderManager.java +++ b/api/src/main/java/org/apache/cloudstack/dns/DnsProviderManager.java @@ -60,10 +60,10 @@ public interface DnsProviderManager extends Manager, PluggableService { List listProviderNames(); - // Allocates the DB row (State: Allocating) - DnsZone allocDnsZone(CreateDnsZoneCmd cmd); + // Allocates the DB row (State: Inactive) + DnsZone allocateDnsZone(CreateDnsZoneCmd cmd); - // Calls the Plugin (State: Allocating -> Ready/Error) + // Calls the Plugin (State: Inactive -> Active) DnsZone provisionDnsZone(long zoneId); // Helper to create the response object diff --git a/api/src/main/java/org/apache/cloudstack/dns/DnsZone.java b/api/src/main/java/org/apache/cloudstack/dns/DnsZone.java index 1e8e8010689..193185a6b0c 100644 --- a/api/src/main/java/org/apache/cloudstack/dns/DnsZone.java +++ b/api/src/main/java/org/apache/cloudstack/dns/DnsZone.java @@ -19,10 +19,11 @@ package org.apache.cloudstack.dns; import java.util.List; +import org.apache.cloudstack.acl.ControlledEntity; import org.apache.cloudstack.api.Identity; import org.apache.cloudstack.api.InternalIdentity; -public interface DnsZone extends InternalIdentity, Identity { +public interface DnsZone extends InternalIdentity, Identity, ControlledEntity { enum ZoneType { Public, Private } @@ -38,5 +39,9 @@ public interface DnsZone extends InternalIdentity, Identity { ZoneType getType(); + String getDescription(); + List getAssociatedNetworks(); + + State getState(); } diff --git a/engine/schema/src/main/resources/META-INF/db/schema-42210to42300.sql b/engine/schema/src/main/resources/META-INF/db/schema-42210to42300.sql index d58dc3a56bb..7eb199c0205 100644 --- a/engine/schema/src/main/resources/META-INF/db/schema-42210to42300.sql +++ b/engine/schema/src/main/resources/META-INF/db/schema-42210to42300.sql @@ -58,7 +58,7 @@ CREATE TABLE IF NOT EXISTS `cloud`.`webhook_filter` ( -- 1. DNS Server Table (Stores DNS Server Configurations) CREATE TABLE `cloud`.`dns_server` ( `id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'id of the dns server', - `uuid` varchar(255) COMMENT 'uuid of the dns server', + `uuid` varchar(40) COMMENT 'uuid of the dns server', `name` varchar(255) NOT NULL COMMENT 'display name of the dns server', `provider_type` varchar(255) NOT NULL COMMENT 'Provider type such as PowerDns', `url` varchar(1024) NOT NULL COMMENT 'dns server url', @@ -79,16 +79,25 @@ CREATE TABLE `cloud`.`dns_server` ( -- 2. DNS Zone Table (Stores DNS Zone Metadata) CREATE TABLE `cloud`.`dns_zone` ( `id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'id of the dns zone', - `uuid` varchar(255) COMMENT 'uuid of the dns zone', + `uuid` varchar(40) COMMENT 'uuid of the dns zone', `name` varchar(255) NOT NULL COMMENT 'dns zone name (e.g. example.com)', `dns_server_id` bigint unsigned NOT NULL COMMENT 'fk to dns_server.id', `external_reference` VARCHAR(255) COMMENT 'id of external provider resource', + `domain_id` bigint unsigned COMMENT 'for domain-specific ownership', + `account_id` bigint unsigned COMMENT 'account id. foreign key to account table', + `description` varchar(1024) DEFAULT NULL, + `type` ENUM('Private', 'Public') NOT NULL DEFAULT 'Public', `state` ENUM('Active', 'Inactive') NOT NULL DEFAULT 'Inactive', `created` datetime NOT NULL COMMENT 'date created', `removed` datetime DEFAULT NULL COMMENT 'Date removed (soft delete)', PRIMARY KEY (`id`), + CONSTRAINT `uc_dns_zone__uuid` UNIQUE (`uuid`), + CONSTRAINT `uc_dns_zone__name_server_type` UNIQUE (`name`, `dns_server_id`, `type`), KEY `i_dns_zone__dns_server` (`dns_server_id`), - CONSTRAINT `fk_dns_zone__dns_server_id` FOREIGN KEY (`dns_server_id`) REFERENCES `dns_server` (`id`) ON DELETE CASCADE + KEY `i_dns_zone__account_id` (`account_id`), + CONSTRAINT `fk_dns_zone__dns_server_id` FOREIGN KEY (`dns_server_id`) REFERENCES `dns_server` (`id`) ON DELETE CASCADE, + CONSTRAINT `fk_dns_zone__account_id` FOREIGN KEY (`account_id`) REFERENCES `account` (`id`) ON DELETE CASCADE, + CONSTRAINT `fk_dns_zone__domain_id` FOREIGN KEY (`domain_id`) REFERENCES `domain` (`id`) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- 3. DNS Zone Network Map (One-to-Many Link) diff --git a/plugins/dns/powerdns/src/main/java/org/apache/cloudstack/dns/powerdns/PowerDnsClient.java b/plugins/dns/powerdns/src/main/java/org/apache/cloudstack/dns/powerdns/PowerDnsClient.java index 1377519202e..23b23e7e7e2 100644 --- a/plugins/dns/powerdns/src/main/java/org/apache/cloudstack/dns/powerdns/PowerDnsClient.java +++ b/plugins/dns/powerdns/src/main/java/org/apache/cloudstack/dns/powerdns/PowerDnsClient.java @@ -18,11 +18,14 @@ package org.apache.cloudstack.dns.powerdns; import java.io.IOException; +import java.util.List; import org.apache.http.HttpStatus; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.util.EntityUtils; @@ -32,6 +35,8 @@ import org.slf4j.LoggerFactory; import com.cloud.utils.exception.CloudRuntimeException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; public class PowerDnsClient implements AutoCloseable { public static final Logger logger = LoggerFactory.getLogger(PowerDnsClient.class); @@ -40,19 +45,7 @@ public class PowerDnsClient implements AutoCloseable { private final CloseableHttpClient httpClient; public void validate(String baseUrl, String apiKey) { - String normalizedUrl = baseUrl.trim(); - - if (!normalizedUrl.startsWith("http://") && !normalizedUrl.startsWith("https://")) { - normalizedUrl = "http://" + normalizedUrl; // default to HTTP - } - - if (normalizedUrl.endsWith("/")) { - normalizedUrl = normalizedUrl.substring(0, normalizedUrl.length() - 1); - } - - - String checkUrl = normalizedUrl + "/api/v1/servers"; - + String checkUrl = buildApiUrl(baseUrl, "/api/v1/servers"); HttpGet request = new HttpGet(checkUrl); request.addHeader("X-API-Key", apiKey); request.addHeader("Accept", "application/json"); @@ -94,6 +87,62 @@ public class PowerDnsClient implements AutoCloseable { } } + public void createZone(String baseUrl, String apiKey, String zoneName, List nameservers) { + String url = buildApiUrl(baseUrl, "/servers/localhost/zones"); + ObjectNode json = MAPPER.createObjectNode(); + json.put("name", zoneName.endsWith(".") ? zoneName : zoneName + "."); + json.put("kind", "Native"); + json.put("dnssec", false); + + if (nameservers != null && !nameservers.isEmpty()) { + ArrayNode nsArray = json.putArray("nameservers"); + for (String ns : nameservers) { + nsArray.add(ns.endsWith(".") ? ns : ns + "."); + } + } + + logger.debug("Creating PowerDNS zone: {} using URL: {}", zoneName, url); + + HttpPost request = new HttpPost(url); + request.addHeader("X-API-Key", apiKey); + request.addHeader("Content-Type", "application/json"); + request.addHeader("Accept", "application/json"); + + try { + request.setEntity(new StringEntity(json.toString())); + + try (CloseableHttpResponse response = httpClient.execute(request)) { + + int statusCode = response.getStatusLine().getStatusCode(); + String body = response.getEntity() != null + ? EntityUtils.toString(response.getEntity()) + : null; + + if (statusCode == HttpStatus.SC_CREATED) { + logger.debug("Zone {} created successfully", zoneName); + return; + } + + if (statusCode == HttpStatus.SC_CONFLICT) { + throw new CloudRuntimeException("Zone already exists: " + zoneName); + } + + if (statusCode == HttpStatus.SC_UNAUTHORIZED || + statusCode == HttpStatus.SC_FORBIDDEN) { + throw new CloudRuntimeException("Invalid PowerDNS API key"); + } + + logger.debug("Unexpected PowerDNS response: HTTP {} Body: {}", statusCode, body); + + throw new CloudRuntimeException(String.format("Failed to create zone %s (HTTP %d)", zoneName, statusCode)); + } + + } catch (IOException e) { + throw new CloudRuntimeException("Error while creating PowerDNS zone " + zoneName, e); + } + } + + public PowerDnsClient() { RequestConfig config = RequestConfig.custom() .setConnectTimeout(TIMEOUT_MS) @@ -107,6 +156,24 @@ public class PowerDnsClient implements AutoCloseable { .build(); } + private String normalizeBaseUrl(String baseUrl) { + if (baseUrl == null) { + throw new IllegalArgumentException("PowerDNS base URL cannot be null"); + } + String normalizedUrl = baseUrl.trim(); + if (!normalizedUrl.startsWith("http://") && !normalizedUrl.startsWith("https://")) { + normalizedUrl = "http://" + normalizedUrl; + } + if (normalizedUrl.endsWith("/")) { + normalizedUrl = normalizedUrl.substring(0, normalizedUrl.length() - 1); + } + return normalizedUrl; + } + + private String buildApiUrl(String baseUrl, String path) { + return normalizeBaseUrl(baseUrl) + "/api/v1" + path; + } + @Override public void close() { try { diff --git a/plugins/dns/powerdns/src/main/java/org/apache/cloudstack/dns/powerdns/PowerDnsProvider.java b/plugins/dns/powerdns/src/main/java/org/apache/cloudstack/dns/powerdns/PowerDnsProvider.java index ba774745d05..a5056b045f9 100644 --- a/plugins/dns/powerdns/src/main/java/org/apache/cloudstack/dns/powerdns/PowerDnsProvider.java +++ b/plugins/dns/powerdns/src/main/java/org/apache/cloudstack/dns/powerdns/PowerDnsProvider.java @@ -51,8 +51,20 @@ public class PowerDnsProvider extends AdapterBase implements DnsProvider { } @Override - public boolean createZone(DnsServer server, DnsZone zone) { - return false; + public boolean provisionZone(DnsServer server, DnsZone zone) throws Exception { + if (StringUtils.isBlank(zone.getName())) { + throw new IllegalArgumentException("Zone name cannot be empty"); + } + + if (StringUtils.isBlank(server.getUrl())) { + throw new IllegalArgumentException("PowerDNS API URL cannot be empty"); + } + + if (StringUtils.isBlank(server.getApiKey())) { + throw new IllegalArgumentException("PowerDNS API key cannot be empty"); + } + client.createZone(server.getUrl(), server.getApiKey(), zone.getName(), null); + return true; } @Override diff --git a/server/src/main/java/org/apache/cloudstack/dns/DnsProviderManagerImpl.java b/server/src/main/java/org/apache/cloudstack/dns/DnsProviderManagerImpl.java index 4d5c0e5d1ca..7192261087d 100644 --- a/server/src/main/java/org/apache/cloudstack/dns/DnsProviderManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/dns/DnsProviderManagerImpl.java @@ -39,7 +39,9 @@ import org.apache.cloudstack.api.response.DnsZoneResponse; import org.apache.cloudstack.api.response.ListResponse; import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.dns.dao.DnsServerDao; +import org.apache.cloudstack.dns.dao.DnsZoneDao; import org.apache.cloudstack.dns.vo.DnsServerVO; +import org.apache.cloudstack.dns.vo.DnsZoneVO; import org.springframework.stereotype.Component; import com.cloud.exception.InvalidParameterValueException; @@ -59,6 +61,8 @@ public class DnsProviderManagerImpl extends ManagerBase implements DnsProviderMa AccountManager accountMgr; @Inject DnsServerDao dnsServerDao; + @Inject + DnsZoneDao dnsZoneDao; private DnsProvider getProvider(DnsProviderType type) { if (type == null) { @@ -272,18 +276,67 @@ public class DnsProviderManagerImpl extends ManagerBase implements DnsProviderMa } @Override - public DnsZone allocDnsZone(CreateDnsZoneCmd cmd) { - return null; + public DnsZone allocateDnsZone(CreateDnsZoneCmd cmd) { + Account caller = CallContext.current().getCallingAccount(); + DnsServerVO server = dnsServerDao.findById(cmd.getDnsServerId()); + if (server == null) { + throw new InvalidParameterValueException("DNS Server not found"); + } + boolean isOwner = (server.getAccountId() == caller.getId()); + if (!server.isPublic() && !isOwner) { + throw new PermissionDeniedException("You do not have permission to use this DNS Server."); + } + DnsZone.ZoneType type = DnsZone.ZoneType.Public; + if (cmd.getType() != null) { + try { + type = DnsZone.ZoneType.valueOf(cmd.getType()); + } catch (IllegalArgumentException e) { + throw new InvalidParameterValueException("Invalid Zone Type"); + } + } + DnsZoneVO existing = dnsZoneDao.findByNameServerAndType(cmd.getName(), server.getId(), type); + if (existing != null) { + throw new InvalidParameterValueException("Zone already exists on this server."); + } + DnsZoneVO dnsZoneVO = new DnsZoneVO(cmd.getName(), type, server.getId(), caller.getId(), caller.getDomainId(), cmd.getDescription()); + return dnsZoneDao.persist(dnsZoneVO); } @Override public DnsZone provisionDnsZone(long zoneId) { - return null; + DnsZoneVO dnsZone = dnsZoneDao.findById(zoneId); + if (dnsZone == null) { + throw new CloudRuntimeException("DNS Zone not found during provisioning"); + } + DnsServerVO server = dnsServerDao.findById(dnsZone.getDnsServerId()); + + try { + DnsProvider provider = getProvider(server.getProviderType()); + logger.debug("Provision DNS zone: {} on DNS server: {}", dnsZone.getName(), server.getName()); + boolean success = provider.provisionZone(server, dnsZone); + if (success) { + dnsZone.setState(DnsZone.State.Active); + dnsZoneDao.update(dnsZone.getId(), dnsZone); + return dnsZone; + } else { + logger.error("DNS provider failed to provision zone: {}", dnsZone.getName()); + throw new CloudRuntimeException("DNS provider failed to provision zone"); + } + } catch (Exception ex) { + logger.error("Failed to provision zone: {} on server: {}", dnsZone.getName(), server.getName(), ex); + dnsZoneDao.remove(zoneId); + throw new CloudRuntimeException("Failed to provision zone: " + dnsZone.getName()); + } } @Override public DnsZoneResponse createDnsZoneResponse(DnsZone zone) { - return null; + DnsZoneResponse res = new DnsZoneResponse(); + res.setName(zone.getName()); + res.setDnsServerId(zone.getDnsServerId()); + res.setType(zone.getType()); + res.setState(zone.getState()); + return res; } @Override diff --git a/server/src/main/java/org/apache/cloudstack/dns/dao/DnsZoneDao.java b/server/src/main/java/org/apache/cloudstack/dns/dao/DnsZoneDao.java index 30d34102143..d618597757d 100644 --- a/server/src/main/java/org/apache/cloudstack/dns/dao/DnsZoneDao.java +++ b/server/src/main/java/org/apache/cloudstack/dns/dao/DnsZoneDao.java @@ -19,10 +19,13 @@ package org.apache.cloudstack.dns.dao; import java.util.List; +import org.apache.cloudstack.dns.DnsZone; import org.apache.cloudstack.dns.vo.DnsZoneVO; import com.cloud.utils.db.GenericDao; public interface DnsZoneDao extends GenericDao { List listByServerId(long serverId); + List listByAccount(long accountId); + DnsZoneVO findByNameServerAndType(String name, long dnsServerId, DnsZone.ZoneType type); } diff --git a/server/src/main/java/org/apache/cloudstack/dns/dao/DnsZoneDaoImpl.java b/server/src/main/java/org/apache/cloudstack/dns/dao/DnsZoneDaoImpl.java index 1a573e4132a..cb693338ef5 100644 --- a/server/src/main/java/org/apache/cloudstack/dns/dao/DnsZoneDaoImpl.java +++ b/server/src/main/java/org/apache/cloudstack/dns/dao/DnsZoneDaoImpl.java @@ -19,6 +19,8 @@ package org.apache.cloudstack.dns.dao; import java.util.List; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.dns.DnsZone; import org.apache.cloudstack.dns.vo.DnsZoneVO; import org.springframework.stereotype.Component; @@ -30,12 +32,24 @@ import com.cloud.utils.db.SearchCriteria; public class DnsZoneDaoImpl extends GenericDaoBase implements DnsZoneDao { static final String DNS_SERVER_ID = "dnsServerId"; SearchBuilder ServerSearch; + SearchBuilder AccountSearch; + SearchBuilder NameServerTypeSearch; public DnsZoneDaoImpl() { super(); ServerSearch = createSearchBuilder(); ServerSearch.and(DNS_SERVER_ID, ServerSearch.entity().getDnsServerId(), SearchCriteria.Op.EQ); ServerSearch.done(); + + AccountSearch = createSearchBuilder(); + AccountSearch.and(ApiConstants.ACCOUNT_ID, AccountSearch.entity().getAccountId(), SearchCriteria.Op.EQ); + AccountSearch.done(); + + NameServerTypeSearch = createSearchBuilder(); + NameServerTypeSearch.and(ApiConstants.NAME, NameServerTypeSearch.entity().getName(), SearchCriteria.Op.EQ); + NameServerTypeSearch.and(DNS_SERVER_ID, NameServerTypeSearch.entity().getDnsServerId(), SearchCriteria.Op.EQ); + NameServerTypeSearch.and(ApiConstants.TYPE, NameServerTypeSearch.entity().getType(), SearchCriteria.Op.EQ); + NameServerTypeSearch.done(); } @Override @@ -44,4 +58,20 @@ public class DnsZoneDaoImpl extends GenericDaoBase implements D sc.setParameters(DNS_SERVER_ID, serverId); return listBy(sc); } + + @Override + public List listByAccount(long accountId) { + SearchCriteria sc = AccountSearch.create(); + sc.setParameters(ApiConstants.ACCOUNT_ID, accountId); + return listBy(sc); + } + + @Override + public DnsZoneVO findByNameServerAndType(String name, long dnsServerId, DnsZone.ZoneType type) { + SearchCriteria sc = NameServerTypeSearch.create(); + sc.setParameters(ApiConstants.NAME, name); + sc.setParameters(DNS_SERVER_ID, dnsServerId); + sc.setParameters(ApiConstants.TYPE, type); + return findOneBy(sc); + } } diff --git a/server/src/main/java/org/apache/cloudstack/dns/vo/DnsZoneVO.java b/server/src/main/java/org/apache/cloudstack/dns/vo/DnsZoneVO.java index 4495081cd20..0d47c1abad0 100644 --- a/server/src/main/java/org/apache/cloudstack/dns/vo/DnsZoneVO.java +++ b/server/src/main/java/org/apache/cloudstack/dns/vo/DnsZoneVO.java @@ -53,6 +53,15 @@ public class DnsZoneVO implements DnsZone { @Column(name = "dns_server_id") private long dnsServerId; + @Column(name = "account_id") + private long accountId; + + @Column(name = "domain_id") + private long domainId; + + @Column(name = "description") + private String description; + @Column(name = "external_reference") private String externalReference; @@ -64,9 +73,6 @@ public class DnsZoneVO implements DnsZone { @Enumerated(EnumType.STRING) private State state; - @Column(name = "account_id") - private long accountId; - @Column(name = GenericDao.CREATED_COLUMN) @Temporal(value = TemporalType.TIMESTAMP) private Date created = null; @@ -78,14 +84,22 @@ public class DnsZoneVO implements DnsZone { public DnsZoneVO() { this.uuid = UUID.randomUUID().toString(); this.created = new Date(); + this.state = State.Inactive; } - public DnsZoneVO(String name, long dnsServerId, long accountId) { + public DnsZoneVO(String name, ZoneType type, long dnsServerId, long accountId, long domainId, String description) { this(); this.name = name; + this.type = (type != null) ? type : ZoneType.Public; this.dnsServerId = dnsServerId; this.accountId = accountId; - this.type = ZoneType.Public; + this.domainId = domainId; + this.description = description; + } + + @Override + public Class getEntityType() { + return DnsZone.class; } @Override @@ -108,11 +122,21 @@ public class DnsZoneVO implements DnsZone { return type; } + @Override + public String getDescription() { + return description; + } + @Override public List getAssociatedNetworks() { return List.of(); } + @Override + public State getState() { + return state; + } + @Override public String getUuid() { return uuid; @@ -122,4 +146,11 @@ public class DnsZoneVO implements DnsZone { public long getId() { return id; } + + @Override + public long getDomainId() { + return domainId; + } + + public void setState(State state) { this.state = state; } }