mirror of https://github.com/apache/cloudstack.git
Merge 4385101eb7 into 5893ba5a8c
This commit is contained in:
commit
edc9f2334a
|
|
@ -30,6 +30,9 @@ import org.apache.cloudstack.api.response.ZoneResponse;
|
|||
import org.apache.cloudstack.backup.BackupRepositoryService;
|
||||
import org.apache.cloudstack.config.Configuration;
|
||||
import org.apache.cloudstack.datacenter.DataCenterIpv4GuestSubnet;
|
||||
import org.apache.cloudstack.dns.DnsRecord;
|
||||
import org.apache.cloudstack.dns.DnsServer;
|
||||
import org.apache.cloudstack.dns.DnsZone;
|
||||
import org.apache.cloudstack.extension.Extension;
|
||||
import org.apache.cloudstack.extension.ExtensionCustomAction;
|
||||
import org.apache.cloudstack.gpu.GpuCard;
|
||||
|
|
@ -865,6 +868,17 @@ public class EventTypes {
|
|||
public static final String EVENT_BACKUP_REPOSITORY_ADD = "BACKUP.REPOSITORY.ADD";
|
||||
public static final String EVENT_BACKUP_REPOSITORY_UPDATE = "BACKUP.REPOSITORY.UPDATE";
|
||||
|
||||
// DNS Framework Events
|
||||
public static final String EVENT_DNS_SERVER_ADD = "DNS.SERVER.ADD";
|
||||
public static final String EVENT_DNS_SERVER_UPDATE = "DNS.SERVER.UPDATE";
|
||||
public static final String EVENT_DNS_SERVER_DELETE = "DNS.SERVER.DELETE";
|
||||
public static final String EVENT_DNS_ZONE_CREATE = "DNS.ZONE.CREATE";
|
||||
public static final String EVENT_DNS_ZONE_UPDATE = "DNS.ZONE.UPDATE";
|
||||
public static final String EVENT_DNS_ZONE_DELETE = "DNS.ZONE.DELETE";
|
||||
public static final String EVENT_DNS_RECORD_CREATE = "DNS.RECORD.CREATE";
|
||||
public static final String EVENT_DNS_RECORD_DELETE = "DNS.RECORD.DELETE";
|
||||
public static final String EVENT_DNS_NAME_COLLISION = "DNS.NAME.COLLISION";
|
||||
|
||||
static {
|
||||
|
||||
// TODO: need a way to force author adding event types to declare the entity details as well, with out braking
|
||||
|
|
@ -1406,6 +1420,17 @@ public class EventTypes {
|
|||
// Backup Repository
|
||||
entityEventDetails.put(EVENT_BACKUP_REPOSITORY_ADD, BackupRepositoryService.class);
|
||||
entityEventDetails.put(EVENT_BACKUP_REPOSITORY_UPDATE, BackupRepositoryService.class);
|
||||
|
||||
// DNS Framework Events
|
||||
entityEventDetails.put(EVENT_DNS_SERVER_ADD, DnsServer.class);
|
||||
entityEventDetails.put(EVENT_DNS_SERVER_UPDATE, DnsServer.class);
|
||||
entityEventDetails.put(EVENT_DNS_SERVER_DELETE, DnsServer.class);
|
||||
entityEventDetails.put(EVENT_DNS_ZONE_CREATE, DnsZone.class);
|
||||
entityEventDetails.put(EVENT_DNS_ZONE_UPDATE, DnsZone.class);
|
||||
entityEventDetails.put(EVENT_DNS_ZONE_DELETE, DnsZone.class);
|
||||
entityEventDetails.put(EVENT_DNS_RECORD_CREATE, DnsRecord.class);
|
||||
entityEventDetails.put(EVENT_DNS_RECORD_DELETE, DnsRecord.class);
|
||||
|
||||
}
|
||||
|
||||
public static boolean isNetworkEvent(String eventType) {
|
||||
|
|
|
|||
|
|
@ -33,6 +33,11 @@ import com.cloud.utils.fsm.StateMachine;
|
|||
* Nic represents one nic on the VM.
|
||||
*/
|
||||
public interface Nic extends Identity, InternalIdentity {
|
||||
|
||||
interface Topics {
|
||||
String NIC_LIFECYCLE = "nic.lifecycle";
|
||||
}
|
||||
|
||||
enum Event {
|
||||
ReservationRequested, ReleaseRequested, CancelRequested, OperationCompleted, OperationFailed,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1363,6 +1363,38 @@ public class ApiConstants {
|
|||
" a VR, CloudStack will use the same MAC address for the public NIC of all VRs. Otherwise, if \"false\", new public NICs will always have " +
|
||||
" a new MAC address.";
|
||||
|
||||
// DNS provider related
|
||||
public static final String NAME_SERVERS = "nameservers";
|
||||
public static final String DNS_USER_NAME = "dnsusername";
|
||||
public static final String DNS_API_KEY = "dnsapikey";
|
||||
public static final String DNS_ZONE_ID = "dnszoneid";
|
||||
public static final String DNS_ZONE = "dnszone";
|
||||
public static final String DNS_RECORD = "dnsrecord";
|
||||
public static final String DNS_SUB_DOMAIN = "dnssubdomain";
|
||||
public static final String DNS_SERVER_ID = "dnsserverid";
|
||||
public static final String CONTENT = "content";
|
||||
public static final String CONTENTS = "contents";
|
||||
public static final String PUBLIC_DOMAIN_SUFFIX = "publicdomainsuffix";
|
||||
public static final String AUTHORITATIVE = "authoritative";
|
||||
public static final String KIND = "kind";
|
||||
public static final String DNS_SEC = "dnssec";
|
||||
public static final String TTL = "ttl";
|
||||
public static final String CHANGE_TYPE = "changetype";
|
||||
public static final String RECORDS = "records";
|
||||
public static final String RR_SETS = "rrsets";
|
||||
public static final String X_API_KEY = "X-API-Key";
|
||||
public static final String DISABLED = "disabled";
|
||||
public static final String CONTENT_TYPE = "Content-Type";
|
||||
public static final String NATIVE_ZONE = "Native";
|
||||
public static final String NIC_DNS_NAME = "nicdnsname";
|
||||
public static final String TIME_STAMP = "timestamp";
|
||||
public static final String INSTANCE_ID = "instanceId";
|
||||
public static final String OLD_STATE = "oldState";
|
||||
public static final String NEW_STATE = "newState";
|
||||
public static final String OLD_HOST_NAME = "oldHostName";
|
||||
public static final String EXISTING = "existing";
|
||||
public static final String UNMANAGE = "unmanage";
|
||||
|
||||
public static final String PARAMETER_DESCRIPTION_ACTIVATION_RULE = "Quota tariff's activation rule. It can receive a JS script that results in either " +
|
||||
"a boolean or a numeric value: if it results in a boolean value, the tariff value will be applied according to the result; if it results in a numeric value, the " +
|
||||
"numeric value will be applied; if the result is neither a boolean nor a numeric value, the tariff will not be applied. If the rule is not informed, the tariff " +
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ import org.apache.cloudstack.affinity.AffinityGroupService;
|
|||
import org.apache.cloudstack.alert.AlertService;
|
||||
import org.apache.cloudstack.annotation.AnnotationService;
|
||||
import org.apache.cloudstack.context.CallContext;
|
||||
import org.apache.cloudstack.dns.DnsProviderManager;
|
||||
import org.apache.cloudstack.gpu.GpuService;
|
||||
import org.apache.cloudstack.network.RoutedIpv4Manager;
|
||||
import org.apache.cloudstack.network.lb.ApplicationLoadBalancerService;
|
||||
|
|
@ -232,6 +233,9 @@ public abstract class BaseCmd {
|
|||
@Inject
|
||||
public RoutedIpv4Manager routedIpv4Manager;
|
||||
|
||||
@Inject
|
||||
public DnsProviderManager dnsProviderManager;
|
||||
|
||||
public abstract void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException,
|
||||
ResourceAllocationException, NetworkRuleConflictException;
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,169 @@
|
|||
// 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.user.dns;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.cloudstack.acl.RoleType;
|
||||
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.DnsServerResponse;
|
||||
import org.apache.cloudstack.context.CallContext;
|
||||
import org.apache.cloudstack.dns.DnsProviderType;
|
||||
import org.apache.cloudstack.dns.DnsServer;
|
||||
import org.apache.commons.collections.MapUtils;
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
|
||||
import com.cloud.exception.InvalidParameterValueException;
|
||||
import com.cloud.utils.EnumUtils;
|
||||
|
||||
@APICommand(name = "addDnsServer",
|
||||
description = "Adds a new external DNS server",
|
||||
responseObject = DnsServerResponse.class,
|
||||
entityType = {DnsServer.class},
|
||||
requestHasSensitiveInfo = false,
|
||||
responseHasSensitiveInfo = false,
|
||||
since = "4.23.0",
|
||||
authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User})
|
||||
public class AddDnsServerCmd extends BaseCmd {
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
//////////////// API parameters /////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
///
|
||||
@Parameter(name = ApiConstants.NAME, type = CommandType.STRING, required = true, description = "Name of the DNS server")
|
||||
private String name;
|
||||
|
||||
@Parameter(name = ApiConstants.URL, type = CommandType.STRING, required = true, description = "API URL of the provider")
|
||||
private String url;
|
||||
|
||||
@Parameter(name = ApiConstants.PROVIDER, type = CommandType.STRING, required = true, description = "Provider type (e.g., PowerDNS)")
|
||||
private String provider;
|
||||
|
||||
@Parameter(name = ApiConstants.DNS_USER_NAME, type = CommandType.STRING,
|
||||
description = "Username or email associated with the DNS provider account (used for authentication)")
|
||||
private String dnsUserName;
|
||||
|
||||
@Parameter(name = ApiConstants.DNS_API_KEY, required = true, type = CommandType.STRING, description = "API key or token for the DNS provider")
|
||||
private String dnsApiKey;
|
||||
|
||||
@Parameter(name = ApiConstants.PORT, type = CommandType.INTEGER, description = "Port number of the external DNS server")
|
||||
private Integer port;
|
||||
|
||||
@Parameter(name = ApiConstants.IS_PUBLIC, type = CommandType.BOOLEAN,
|
||||
description = "Whether this DNS server can be used by accounts other than the owner to create and manage DNS zones")
|
||||
private Boolean isPublic;
|
||||
|
||||
@Parameter(name = ApiConstants.PUBLIC_DOMAIN_SUFFIX, type = CommandType.STRING,
|
||||
description = "Domain suffix that restricts DNS zones created by non-owner accounts to subdomains of this " +
|
||||
"suffix (for example, sub.example.com under example.com)")
|
||||
private String publicDomainSuffix;
|
||||
|
||||
@Parameter(name = ApiConstants.NAME_SERVERS, type = CommandType.LIST, collectionType = CommandType.STRING,
|
||||
required = true,
|
||||
description = "Comma separated list of name servers; used to create NS records for the DNS Zone (for example, ns1.example.com, ns2.example.com)")
|
||||
private List<String> nameServers;
|
||||
|
||||
@Parameter(name = ApiConstants.DETAILS, type = CommandType.MAP, description = "Details in key/value pairs using " +
|
||||
"format details[i].keyname=keyvalue. Example: details[0].pdnsServerId=localhost")
|
||||
protected Map details;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////////// Accessors ///////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
public String getName() { return name; }
|
||||
|
||||
public String getUrl() { return url; }
|
||||
|
||||
public String getDnsApiKey() {
|
||||
return dnsApiKey;
|
||||
}
|
||||
|
||||
public Integer getPort() {
|
||||
return port;
|
||||
}
|
||||
|
||||
public Boolean isPublic() {
|
||||
return BooleanUtils.isTrue(isPublic);
|
||||
}
|
||||
|
||||
public String getPublicDomainSuffix() {
|
||||
return publicDomainSuffix;
|
||||
}
|
||||
|
||||
public List<String> getNameServers() {
|
||||
return nameServers;
|
||||
}
|
||||
|
||||
public DnsProviderType getProvider() {
|
||||
DnsProviderType dnsProviderType = EnumUtils.getEnumIgnoreCase(DnsProviderType.class, provider, DnsProviderType.PowerDNS);
|
||||
if (dnsProviderType == null) {
|
||||
throw new InvalidParameterValueException(String.format("Invalid value passed for provider type, valid values are: %s",
|
||||
EnumUtils.listValues(DnsProviderType.values())));
|
||||
}
|
||||
return dnsProviderType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getEntityOwnerId() {
|
||||
return CallContext.current().getCallingAccount().getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
try {
|
||||
DnsServer server = dnsProviderManager.addDnsServer(this);
|
||||
if (server != null) {
|
||||
DnsServerResponse response = dnsProviderManager.createDnsServerResponse(server);
|
||||
response.setResponseName(getCommandName());
|
||||
setResponseObject(response);
|
||||
} else {
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to add DNS server");
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
logger.error("Failed to add DNS server", ex);
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public String getDnsUserName() {
|
||||
return dnsUserName;
|
||||
}
|
||||
|
||||
public Map<String, String> getDetails() {
|
||||
Map<String, String> detailsMap = new HashMap<>();
|
||||
if (MapUtils.isNotEmpty(details)) {
|
||||
Collection<?> props = details.values();
|
||||
for (Object prop : props) {
|
||||
HashMap<String, String> detail = (HashMap<String, String>) prop;
|
||||
for (Map.Entry<String, String> entry: detail.entrySet()) {
|
||||
detailsMap.put(entry.getKey(),entry.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
return detailsMap;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,94 @@
|
|||
// 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.user.dns;
|
||||
|
||||
import org.apache.cloudstack.acl.RoleType;
|
||||
import org.apache.cloudstack.acl.SecurityChecker;
|
||||
import org.apache.cloudstack.api.ACL;
|
||||
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.DnsZoneNetworkMapResponse;
|
||||
import org.apache.cloudstack.api.response.DnsZoneResponse;
|
||||
import org.apache.cloudstack.api.response.NetworkResponse;
|
||||
|
||||
import com.cloud.exception.ConcurrentOperationException;
|
||||
import com.cloud.exception.InsufficientCapacityException;
|
||||
import com.cloud.exception.NetworkRuleConflictException;
|
||||
import com.cloud.exception.ResourceAllocationException;
|
||||
import com.cloud.exception.ResourceUnavailableException;
|
||||
import com.cloud.network.Network;
|
||||
import com.cloud.user.Account;
|
||||
|
||||
@APICommand(name = "associateDnsZoneToNetwork",
|
||||
description = "Associates a DNS Zone with a Network for VM auto-registration",
|
||||
responseObject = DnsZoneNetworkMapResponse.class,
|
||||
requestHasSensitiveInfo = false,
|
||||
responseHasSensitiveInfo = false,
|
||||
since = "4.23.0",
|
||||
authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User})
|
||||
public class AssociateDnsZoneToNetworkCmd extends BaseCmd {
|
||||
|
||||
@Parameter(name = ApiConstants.DNS_ZONE_ID, type = CommandType.UUID, entityType = DnsZoneResponse.class,
|
||||
required = true, description = "The ID of the DNS zone")
|
||||
private Long dnsZoneId;
|
||||
|
||||
@ACL(accessType = SecurityChecker.AccessType.OperateEntry)
|
||||
@Parameter(name = ApiConstants.NETWORK_ID, type = CommandType.UUID, entityType = NetworkResponse.class,
|
||||
required = true, description = "The ID of the network")
|
||||
private Long networkId;
|
||||
|
||||
@Parameter(name = "subdomain", type = CommandType.STRING,
|
||||
description = "Optional subdomain to append (e.g., 'dev' creates vm1.dev.example.com)")
|
||||
private String subDomain;
|
||||
|
||||
@Override
|
||||
public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException {
|
||||
try {
|
||||
DnsZoneNetworkMapResponse response = dnsProviderManager.associateZoneToNetwork(this);
|
||||
response.setResponseName(getCommandName());
|
||||
setResponseObject(response);
|
||||
} catch (Exception e) {
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getEntityOwnerId() {
|
||||
Network network = _entityMgr.findById(Network.class, networkId);
|
||||
if (network != null) {
|
||||
return network.getAccountId();
|
||||
}
|
||||
return Account.ACCOUNT_ID_SYSTEM;
|
||||
}
|
||||
|
||||
public Long getDnsZoneId() {
|
||||
return dnsZoneId;
|
||||
}
|
||||
|
||||
public Long getNetworkId() {
|
||||
return networkId;
|
||||
}
|
||||
|
||||
public String getSubDomain() {
|
||||
return subDomain;
|
||||
}
|
||||
}
|
||||
|
|
@ -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 org.apache.cloudstack.api.command.user.dns;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.cloudstack.acl.RoleType;
|
||||
import org.apache.cloudstack.api.ACL;
|
||||
import org.apache.cloudstack.api.APICommand;
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.ApiErrorCode;
|
||||
import org.apache.cloudstack.api.BaseAsyncCmd;
|
||||
import org.apache.cloudstack.api.Parameter;
|
||||
import org.apache.cloudstack.api.ServerApiException;
|
||||
import org.apache.cloudstack.api.response.DnsRecordResponse;
|
||||
import org.apache.cloudstack.api.response.DnsZoneResponse;
|
||||
import org.apache.cloudstack.context.CallContext;
|
||||
import org.apache.cloudstack.dns.DnsRecord;
|
||||
|
||||
import com.cloud.event.EventTypes;
|
||||
import com.cloud.exception.InvalidParameterValueException;
|
||||
import com.cloud.utils.EnumUtils;
|
||||
|
||||
@APICommand(name = "createDnsRecord",
|
||||
description = "Creates a DNS record directly on the provider",
|
||||
responseObject = DnsRecordResponse.class,
|
||||
entityType = {DnsRecord.class},
|
||||
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false,
|
||||
since = "4.23.0",
|
||||
authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User})
|
||||
public class CreateDnsRecordCmd extends BaseAsyncCmd {
|
||||
|
||||
@ACL
|
||||
@Parameter(name = ApiConstants.DNS_ZONE_ID, type = CommandType.UUID, entityType = DnsZoneResponse.class, required = true,
|
||||
description = "ID of the DNS zone")
|
||||
private Long dnsZoneId;
|
||||
|
||||
@Parameter(name = ApiConstants.NAME, type = CommandType.STRING, required = true, description = "DNS record name")
|
||||
private String name;
|
||||
|
||||
@Parameter(name = ApiConstants.TYPE, type = CommandType.STRING, required = true, description = "DNS record type (e.g., A, AAAA, CNAME, MX, TXT, etc.)")
|
||||
private String type;
|
||||
|
||||
@Parameter(name = ApiConstants.CONTENTS, type = CommandType.LIST, collectionType = CommandType.STRING, required = true,
|
||||
description = "The content of the record (IP address for A/AAAA, FQDN for CNAME/NS, quoted string for TXT, etc.)")
|
||||
private List<String> contents;
|
||||
|
||||
@Parameter(name = "ttl", type = CommandType.INTEGER, description = "Time to live")
|
||||
private Integer ttl;
|
||||
|
||||
// Getters
|
||||
public Long getDnsZoneId() { return dnsZoneId; }
|
||||
public String getName() { return name; }
|
||||
|
||||
public List<String> getContents() { return contents; }
|
||||
public Integer getTtl() { return (ttl == null) ? 3600 : ttl; }
|
||||
|
||||
public DnsRecord.RecordType getType() {
|
||||
DnsRecord.RecordType dnsRecordType = EnumUtils.getEnumIgnoreCase(DnsRecord.RecordType.class, type);
|
||||
if (dnsRecordType == null) {
|
||||
throw new InvalidParameterValueException("Invalid value passed for record type, valid values are: " + EnumUtils.listValues(DnsRecord.RecordType.values()));
|
||||
}
|
||||
return dnsRecordType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
try {
|
||||
DnsRecordResponse response = dnsProviderManager.createDnsRecord(this);
|
||||
response.setResponseName(getCommandName());
|
||||
setResponseObject(response);
|
||||
} catch (Exception e) {
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to create DNS Record: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getEntityOwnerId() { return CallContext.current().getCallingAccount().getId(); }
|
||||
|
||||
@Override
|
||||
public String getEventType() { return EventTypes.EVENT_DNS_RECORD_CREATE; }
|
||||
|
||||
@Override
|
||||
public String getEventDescription() { return "Creating DNS Record: " + getName(); }
|
||||
}
|
||||
|
|
@ -0,0 +1,154 @@
|
|||
// 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.user.dns;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.apache.cloudstack.acl.RoleType;
|
||||
import org.apache.cloudstack.api.ACL;
|
||||
import org.apache.cloudstack.api.APICommand;
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.ApiErrorCode;
|
||||
import org.apache.cloudstack.api.BaseAsyncCreateCmd;
|
||||
import org.apache.cloudstack.api.Parameter;
|
||||
import org.apache.cloudstack.api.ServerApiException;
|
||||
import org.apache.cloudstack.api.response.DnsServerResponse;
|
||||
import org.apache.cloudstack.api.response.DnsZoneResponse;
|
||||
import org.apache.cloudstack.context.CallContext;
|
||||
import org.apache.cloudstack.dns.DnsZone;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import com.cloud.event.EventTypes;
|
||||
import com.cloud.exception.ResourceAllocationException;
|
||||
import com.cloud.utils.EnumUtils;
|
||||
|
||||
@APICommand(name = "createDnsZone",
|
||||
description = "Creates a new DNS Zone on a specific server",
|
||||
responseObject = DnsZoneResponse.class,
|
||||
entityType = {DnsZone.class},
|
||||
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false,
|
||||
since = "4.23.0",
|
||||
authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User})
|
||||
public class CreateDnsZoneCmd extends BaseAsyncCreateCmd {
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
//////////////// API Parameters /////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
@Parameter(name = ApiConstants.NAME, type = CommandType.STRING, required = true,
|
||||
description = "The name of the DNS zone (e.g. example.com)")
|
||||
private String name;
|
||||
|
||||
@ACL
|
||||
@Parameter(name = ApiConstants.DNS_SERVER_ID, type = CommandType.UUID, entityType = DnsServerResponse.class,
|
||||
required = true, description = "The ID of the DNS server to host this zone")
|
||||
private Long dnsServerId;
|
||||
|
||||
@Parameter(name = ApiConstants.TYPE, type = CommandType.STRING,
|
||||
description = "The type of zone (Public, Private). Defaults to Public.")
|
||||
private String type;
|
||||
|
||||
@Parameter(name = ApiConstants.DESCRIPTION, type = CommandType.STRING, description = "The description of the DNS zone")
|
||||
private String description;
|
||||
|
||||
@Parameter(name = ApiConstants.EXISTING, type = CommandType.BOOLEAN, entityType = DnsZoneResponse.class,
|
||||
description = "If true, imports an existing DNS zone from the DNS provider into CloudStack. " +
|
||||
"If false, creates the zone in the DNS provider and registers it in CloudStack. Default is false")
|
||||
private Boolean existing = false;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////////// Accessors ///////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public Long getDnsServerId() {
|
||||
return dnsServerId;
|
||||
}
|
||||
|
||||
public DnsZone.ZoneType getType() {
|
||||
if (StringUtils.isBlank(type)) {
|
||||
return DnsZone.ZoneType.Public;
|
||||
}
|
||||
DnsZone.ZoneType zoneType = EnumUtils.getEnumIgnoreCase(DnsZone.ZoneType.class, type);
|
||||
if (zoneType == null) {
|
||||
throw new IllegalArgumentException("Invalid type value, supported values are: " + Arrays.toString(DnsZone.ZoneType.values()));
|
||||
}
|
||||
return zoneType;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////// Implementation //////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public void create() throws ResourceAllocationException {
|
||||
try {
|
||||
DnsZone zone = dnsProviderManager.allocateDnsZone(this);
|
||||
if (zone != null) {
|
||||
setEntityId(zone.getId());
|
||||
setEntityUuid(zone.getUuid());
|
||||
} else {
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to create DNS Zone entity");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to allocate DNS Zone: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
try {
|
||||
DnsZone result = dnsProviderManager.provisionDnsZone(getEntityId(), isExistingZone());
|
||||
if (result != null) {
|
||||
DnsZoneResponse response = dnsProviderManager.createDnsZoneResponse(result);
|
||||
response.setResponseName(getCommandName());
|
||||
setResponseObject(response);
|
||||
} else {
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to provision DNS Zone on external provider");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to provision DNS Zone: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getEntityOwnerId() {
|
||||
return CallContext.current().getCallingAccount().getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType() {
|
||||
return EventTypes.EVENT_DNS_ZONE_CREATE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventDescription() {
|
||||
return "creating DNS zone: " + getName();
|
||||
}
|
||||
|
||||
public Boolean isExistingZone() {
|
||||
return Boolean.TRUE.equals(existing);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,92 @@
|
|||
// 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.user.dns;
|
||||
|
||||
import org.apache.cloudstack.acl.RoleType;
|
||||
import org.apache.cloudstack.acl.SecurityChecker;
|
||||
import org.apache.cloudstack.api.ACL;
|
||||
import org.apache.cloudstack.api.APICommand;
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.ApiErrorCode;
|
||||
import org.apache.cloudstack.api.BaseAsyncCmd;
|
||||
import org.apache.cloudstack.api.Parameter;
|
||||
import org.apache.cloudstack.api.ServerApiException;
|
||||
import org.apache.cloudstack.api.response.DnsZoneResponse;
|
||||
import org.apache.cloudstack.api.response.SuccessResponse;
|
||||
import org.apache.cloudstack.context.CallContext;
|
||||
import org.apache.cloudstack.dns.DnsRecord;
|
||||
|
||||
import com.cloud.event.EventTypes;
|
||||
import com.cloud.exception.InvalidParameterValueException;
|
||||
import com.cloud.utils.EnumUtils;
|
||||
|
||||
@APICommand(name = "deleteDnsRecord",
|
||||
description = "Deletes a DNS record from the external provider",
|
||||
responseObject = SuccessResponse.class,
|
||||
entityType = {DnsRecord.class},
|
||||
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false,
|
||||
since = "4.23.0",
|
||||
authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User})
|
||||
public class DeleteDnsRecordCmd extends BaseAsyncCmd {
|
||||
|
||||
@ACL(accessType = SecurityChecker.AccessType.OperateEntry)
|
||||
@Parameter(name = ApiConstants.DNS_ZONE_ID, type = CommandType.UUID, entityType = DnsZoneResponse.class,
|
||||
required = true, description = "The ID of the DNS zone")
|
||||
private Long dnsZoneId;
|
||||
|
||||
@Parameter(name = ApiConstants.NAME, type = CommandType.STRING, required = true)
|
||||
private String name;
|
||||
|
||||
@Parameter(name = ApiConstants.TYPE, type = CommandType.STRING, required = true)
|
||||
private String type;
|
||||
|
||||
// Getters
|
||||
public DnsRecord.RecordType getType() {
|
||||
DnsRecord.RecordType dnsRecordType = EnumUtils.getEnumIgnoreCase(DnsRecord.RecordType.class, type);
|
||||
if (dnsRecordType == null) {
|
||||
throw new InvalidParameterValueException("Invalid value passed for record type, valid values are: " + EnumUtils.listValues(DnsRecord.RecordType.values()));
|
||||
}
|
||||
return dnsRecordType;
|
||||
}
|
||||
public Long getDnsZoneId() { return dnsZoneId; }
|
||||
public String getName() { return name; }
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
try {
|
||||
boolean result = dnsProviderManager.deleteDnsRecord(this);
|
||||
if (result) {
|
||||
SuccessResponse response = new SuccessResponse(getCommandName());
|
||||
setResponseObject(response);
|
||||
} else {
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to delete DNS Record");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Error deleting DNS Record: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getEntityOwnerId() { return CallContext.current().getCallingAccount().getId(); }
|
||||
|
||||
@Override
|
||||
public String getEventType() { return EventTypes.EVENT_DNS_RECORD_DELETE; }
|
||||
|
||||
@Override
|
||||
public String getEventDescription() { return "Deleting DNS Record: " + getName(); }
|
||||
}
|
||||
|
|
@ -0,0 +1,115 @@
|
|||
// 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.user.dns;
|
||||
|
||||
import org.apache.cloudstack.acl.RoleType;
|
||||
import org.apache.cloudstack.acl.SecurityChecker;
|
||||
import org.apache.cloudstack.api.ACL;
|
||||
import org.apache.cloudstack.api.APICommand;
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.ApiErrorCode;
|
||||
import org.apache.cloudstack.api.BaseAsyncCmd;
|
||||
import org.apache.cloudstack.api.Parameter;
|
||||
import org.apache.cloudstack.api.ServerApiException;
|
||||
import org.apache.cloudstack.api.response.DnsServerResponse;
|
||||
import org.apache.cloudstack.api.response.DnsZoneResponse;
|
||||
import org.apache.cloudstack.api.response.SuccessResponse;
|
||||
import org.apache.cloudstack.dns.DnsServer;
|
||||
|
||||
import com.cloud.event.EventTypes;
|
||||
import com.cloud.user.Account;
|
||||
|
||||
@APICommand(name = "deleteDnsServer",
|
||||
description = "Removes a DNS server integration",
|
||||
responseObject = SuccessResponse.class,
|
||||
entityType = {DnsServer.class},
|
||||
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false,
|
||||
since = "4.23.0",
|
||||
authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User})
|
||||
public class DeleteDnsServerCmd extends BaseAsyncCmd {
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
//////////////// API Parameters /////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
@ACL(accessType = SecurityChecker.AccessType.OperateEntry)
|
||||
@Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = DnsServerResponse.class,
|
||||
required = true, description = "the ID of the DNS server")
|
||||
private Long id;
|
||||
|
||||
@Parameter(name = ApiConstants.CLEANUP, type = CommandType.BOOLEAN,
|
||||
entityType = DnsZoneResponse.class, description = "If true, all associated DNS zones will be cleaned up " +
|
||||
"when the server is removed. Default: true")
|
||||
private Boolean cleanup = true;
|
||||
|
||||
@Parameter(name = ApiConstants.UNMANAGE, type = CommandType.BOOLEAN, entityType = DnsZoneResponse.class,
|
||||
description = "If true, the DNS zone is only removed from CloudStack (unmanaged); if false, it is removed " +
|
||||
"from both CloudStack and the DNS provider. Default: false")
|
||||
private Boolean unmanage = false;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////////// Accessors ///////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////// Implementation //////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
try {
|
||||
boolean result = dnsProviderManager.deleteDnsServer(this);
|
||||
if (result) {
|
||||
SuccessResponse response = new SuccessResponse(getCommandName());
|
||||
setResponseObject(response);
|
||||
} else {
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to delete DNS server");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to delete DNS server: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getEntityOwnerId() {
|
||||
DnsServer server = _entityMgr.findById(DnsServer.class, id);
|
||||
if (server != null) {
|
||||
return server.getAccountId();
|
||||
}
|
||||
// If server not found, return System to fail safely (or let manager handle 404)
|
||||
return Account.ACCOUNT_ID_SYSTEM;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType() { return EventTypes.EVENT_DNS_SERVER_DELETE; }
|
||||
|
||||
@Override
|
||||
public String getEventDescription() { return "Deleting DNS server ID: " + getId(); }
|
||||
|
||||
public Boolean getCleanup() {
|
||||
return Boolean.TRUE.equals(cleanup);
|
||||
}
|
||||
|
||||
public Boolean isUnmanage() {
|
||||
return Boolean.TRUE.equals(unmanage);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,109 @@
|
|||
// 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.user.dns;
|
||||
|
||||
import org.apache.cloudstack.acl.RoleType;
|
||||
import org.apache.cloudstack.acl.SecurityChecker;
|
||||
import org.apache.cloudstack.api.ACL;
|
||||
import org.apache.cloudstack.api.APICommand;
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.ApiErrorCode;
|
||||
import org.apache.cloudstack.api.BaseAsyncCmd;
|
||||
import org.apache.cloudstack.api.Parameter;
|
||||
import org.apache.cloudstack.api.ServerApiException;
|
||||
import org.apache.cloudstack.api.response.DnsZoneResponse;
|
||||
import org.apache.cloudstack.api.response.SuccessResponse;
|
||||
import org.apache.cloudstack.dns.DnsZone;
|
||||
|
||||
import com.cloud.event.EventTypes;
|
||||
import com.cloud.user.Account;
|
||||
|
||||
@APICommand(name = "deleteDnsZone",
|
||||
description = "Removes a DNS Zone from CloudStack and the external provider",
|
||||
responseObject = SuccessResponse.class,
|
||||
entityType = {DnsZone.class},
|
||||
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false,
|
||||
since = "4.23.0",
|
||||
authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User})
|
||||
public class DeleteDnsZoneCmd extends BaseAsyncCmd {
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
//////////////// API Parameters /////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
@ACL(accessType = SecurityChecker.AccessType.OperateEntry)
|
||||
@Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = DnsZoneResponse.class, required = true,
|
||||
description = "The ID of the DNS zone")
|
||||
private Long id;
|
||||
|
||||
@Parameter(name = ApiConstants.UNMANAGE, type = CommandType.BOOLEAN, entityType = DnsZoneResponse.class,
|
||||
description = "If true, removes the DNS zone only from CloudStack; if false, removes it from " +
|
||||
"both CloudStack and the DNS provider. Default: false")
|
||||
private Boolean unmanage = false;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////////// Accessors ///////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////// API Implementation //////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
try {
|
||||
boolean result = dnsProviderManager.deleteDnsZone(getId(), isUnmanage());
|
||||
if (result) {
|
||||
SuccessResponse response = new SuccessResponse(getCommandName());
|
||||
setResponseObject(response);
|
||||
} else {
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to delete DNS Zone");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getEntityOwnerId() {
|
||||
DnsZone zone = _entityMgr.findById(DnsZone.class, id);
|
||||
if (zone != null) {
|
||||
return zone.getAccountId();
|
||||
}
|
||||
// Fallback or System if not found (likely to fail in execute() anyway)
|
||||
return Account.ACCOUNT_ID_SYSTEM;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType() {
|
||||
return EventTypes.EVENT_DNS_ZONE_DELETE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventDescription() {
|
||||
return "Deleting DNS Zone ID: " + getId();
|
||||
}
|
||||
|
||||
public Boolean isUnmanage() {
|
||||
return Boolean.TRUE.equals(unmanage);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
// 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.user.dns;
|
||||
|
||||
import org.apache.cloudstack.acl.RoleType;
|
||||
import org.apache.cloudstack.acl.SecurityChecker;
|
||||
import org.apache.cloudstack.api.ACL;
|
||||
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.NetworkResponse;
|
||||
import org.apache.cloudstack.api.response.SuccessResponse;
|
||||
|
||||
import com.cloud.exception.ConcurrentOperationException;
|
||||
import com.cloud.exception.InsufficientCapacityException;
|
||||
import com.cloud.exception.NetworkRuleConflictException;
|
||||
import com.cloud.exception.ResourceAllocationException;
|
||||
import com.cloud.exception.ResourceUnavailableException;
|
||||
import com.cloud.network.Network;
|
||||
import com.cloud.user.Account;
|
||||
|
||||
@APICommand(name = "disassociateDnsZoneFromNetwork",
|
||||
description = "Removes the association between a DNS Zone and a Network",
|
||||
responseObject = SuccessResponse.class,
|
||||
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false,
|
||||
since = "4.23.0",
|
||||
authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User})
|
||||
public class DisassociateDnsZoneFromNetworkCmd extends BaseCmd {
|
||||
|
||||
@ACL(accessType = SecurityChecker.AccessType.OperateEntry)
|
||||
@Parameter(name = ApiConstants.NETWORK_ID, type = CommandType.UUID, entityType = NetworkResponse.class,
|
||||
required = true, description = "The ID of the Network")
|
||||
private Long networkId;
|
||||
|
||||
@Override
|
||||
public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException {
|
||||
try {
|
||||
boolean result = dnsProviderManager.disassociateZoneFromNetwork(this);
|
||||
if (result) {
|
||||
SuccessResponse response = new SuccessResponse(getCommandName());
|
||||
setResponseObject(response);
|
||||
} else {
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to disassociate DNS zone from network.");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getEntityOwnerId() {
|
||||
Network network = _entityMgr.findById(Network.class, networkId);
|
||||
if (network != null) {
|
||||
return network.getAccountId();
|
||||
}
|
||||
return Account.ACCOUNT_ID_SYSTEM;
|
||||
}
|
||||
|
||||
public Long getNetworkId() {
|
||||
return networkId;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
// 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.user.dns;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.cloudstack.acl.RoleType;
|
||||
import org.apache.cloudstack.api.APICommand;
|
||||
import org.apache.cloudstack.api.BaseListCmd;
|
||||
import org.apache.cloudstack.api.response.DnsProviderResponse;
|
||||
import org.apache.cloudstack.api.response.ListResponse;
|
||||
import org.apache.cloudstack.dns.DnsProvider;
|
||||
|
||||
@APICommand(name = "listDnsProviders",
|
||||
description = "Lists available DNS plugin providers",
|
||||
responseObject = DnsProviderResponse.class,
|
||||
entityType = {DnsProvider.class},
|
||||
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false,
|
||||
since = "4.23.0",
|
||||
authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User})
|
||||
public class ListDnsProvidersCmd extends BaseListCmd {
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
List<String> providers = dnsProviderManager.listProviderNames();
|
||||
ListResponse<DnsProviderResponse> response = new ListResponse<>();
|
||||
List<DnsProviderResponse> responses = new ArrayList<>();
|
||||
for (String name : providers) {
|
||||
DnsProviderResponse resp = new DnsProviderResponse(name);
|
||||
resp.setName(name);
|
||||
responses.add(resp);
|
||||
}
|
||||
response.setResponses(responses);
|
||||
response.setResponseName(getCommandName());
|
||||
setResponseObject(response);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
// 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.user.dns;
|
||||
|
||||
import org.apache.cloudstack.acl.RoleType;
|
||||
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.DnsRecordResponse;
|
||||
import org.apache.cloudstack.api.response.DnsZoneResponse;
|
||||
import org.apache.cloudstack.api.response.ListResponse;
|
||||
import org.apache.cloudstack.dns.DnsRecord;
|
||||
|
||||
@APICommand(name = "listDnsRecords",
|
||||
description = "Lists DNS records from the external provider",
|
||||
responseObject = DnsRecordResponse.class,
|
||||
entityType = {DnsRecord.class},
|
||||
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false,
|
||||
since = "4.23.0",
|
||||
authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User})
|
||||
public class ListDnsRecordsCmd extends BaseListCmd {
|
||||
|
||||
@Parameter(name = ApiConstants.DNS_ZONE_ID, type = CommandType.UUID, entityType = DnsZoneResponse.class, required = true,
|
||||
description = "ID of the DNS zone to list records from")
|
||||
private Long dnsZoneId;
|
||||
|
||||
public Long getDnsZoneId() {
|
||||
return dnsZoneId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
// The manager will fetch live data from the plugin
|
||||
ListResponse<DnsRecordResponse> response = dnsProviderManager.listDnsRecords(this);
|
||||
response.setResponseName(getCommandName());
|
||||
setResponseObject(response);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
// 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.user.dns;
|
||||
|
||||
import org.apache.cloudstack.acl.RoleType;
|
||||
import org.apache.cloudstack.api.APICommand;
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.BaseListAccountResourcesCmd;
|
||||
import org.apache.cloudstack.api.Parameter;
|
||||
import org.apache.cloudstack.api.response.DnsServerResponse;
|
||||
import org.apache.cloudstack.api.response.ListResponse;
|
||||
import org.apache.cloudstack.dns.DnsProviderType;
|
||||
import org.apache.cloudstack.dns.DnsServer;
|
||||
|
||||
import com.cloud.exception.InvalidParameterValueException;
|
||||
import com.cloud.utils.EnumUtils;
|
||||
|
||||
@APICommand(name = "listDnsServers",
|
||||
description = "Lists DNS servers owned by the account.",
|
||||
responseObject = DnsServerResponse.class,
|
||||
entityType = {DnsServer.class},
|
||||
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false,
|
||||
since = "4.23.0",
|
||||
authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User})
|
||||
public class ListDnsServersCmd extends BaseListAccountResourcesCmd {
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
//////////////// API Parameters /////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
@Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = DnsServerResponse.class,
|
||||
description = "the ID of the DNS server")
|
||||
private Long id;
|
||||
|
||||
@Parameter(name = ApiConstants.PROVIDER_TYPE, type = CommandType.STRING,
|
||||
description = "filter by provider type (e.g. PowerDNS, Cloudflare)")
|
||||
private String providerType;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////////// Accessors ///////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public DnsProviderType getProviderType() {
|
||||
DnsProviderType dnsProviderType = EnumUtils.getEnumIgnoreCase(DnsProviderType.class, providerType, DnsProviderType.PowerDNS);
|
||||
if (dnsProviderType == null) {
|
||||
throw new InvalidParameterValueException(String.format("Invalid value passed for provider type, valid values are: %s",
|
||||
EnumUtils.listValues(DnsProviderType.values())));
|
||||
}
|
||||
return dnsProviderType;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////// Implementation //////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
ListResponse<DnsServerResponse> response = dnsProviderManager.listDnsServers(this);
|
||||
response.setResponseName(getCommandName());
|
||||
response.setObjectName("dnsserver");
|
||||
setResponseObject(response);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
// 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.user.dns;
|
||||
|
||||
import org.apache.cloudstack.acl.RoleType;
|
||||
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.DnsServerResponse;
|
||||
import org.apache.cloudstack.api.response.DnsZoneResponse;
|
||||
import org.apache.cloudstack.api.response.ListResponse;
|
||||
import org.apache.cloudstack.dns.DnsZone;
|
||||
|
||||
@APICommand(name = "listDnsZones",
|
||||
description = "Lists DNS zones.", responseObject = DnsZoneResponse.class,
|
||||
entityType = {DnsZone.class},
|
||||
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false,
|
||||
since = "4.23.0",
|
||||
authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User})
|
||||
public class ListDnsZonesCmd extends BaseListCmd {
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
//////////////// API parameters /////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
@Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = DnsZoneResponse.class,
|
||||
description = "List DNS zone by ID")
|
||||
private Long id;
|
||||
|
||||
@Parameter(name = "dnsserverid", type = CommandType.UUID, entityType = DnsServerResponse.class,
|
||||
description = "List DNS zones belonging to a specific DNS server")
|
||||
private Long dnsServerId;
|
||||
|
||||
@Parameter(name = ApiConstants.NAME, type = CommandType.STRING, description = "List by zone name")
|
||||
private String name;
|
||||
|
||||
public Long getId() { return id; }
|
||||
public Long getDnsServerId() { return dnsServerId; }
|
||||
public String getName() { return name; }
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
ListResponse<DnsZoneResponse> response = dnsProviderManager.listDnsZones(this);
|
||||
response.setResponseName(getCommandName());
|
||||
setResponseObject(response);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,151 @@
|
|||
// 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.user.dns;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.cloudstack.acl.RoleType;
|
||||
import org.apache.cloudstack.acl.SecurityChecker;
|
||||
import org.apache.cloudstack.api.ACL;
|
||||
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.DnsServerResponse;
|
||||
import org.apache.cloudstack.dns.DnsServer;
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import com.cloud.user.Account;
|
||||
import com.cloud.utils.EnumUtils;
|
||||
|
||||
@APICommand(name = "updateDnsServer",
|
||||
description = "Update DNS server",
|
||||
responseObject = DnsServerResponse.class,
|
||||
entityType = {DnsServer.class},
|
||||
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false,
|
||||
since = "4.23.0",
|
||||
authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User})
|
||||
public class UpdateDnsServerCmd extends BaseCmd {
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
//////////////// API parameters /////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
@ACL(accessType = SecurityChecker.AccessType.OperateEntry)
|
||||
@Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = DnsServerResponse.class,
|
||||
required = true, description = "The ID of the DNS server to update")
|
||||
private Long id;
|
||||
|
||||
@Parameter(name = ApiConstants.NAME, type = CommandType.STRING, description = "Name of the DNS server")
|
||||
private String name;
|
||||
|
||||
@Parameter(name = ApiConstants.URL, type = CommandType.STRING, description = "API URL of the provider")
|
||||
private String url;
|
||||
|
||||
@Parameter(name = ApiConstants.DNS_API_KEY, type = CommandType.STRING, description = "API Key or Credentials for the external provider")
|
||||
private String dnsApiKey;
|
||||
|
||||
@Parameter(name = ApiConstants.PORT, type = CommandType.INTEGER, description = "Port number of the external DNS server")
|
||||
private Integer port;
|
||||
|
||||
@Parameter(name = ApiConstants.IS_PUBLIC, type = CommandType.BOOLEAN,
|
||||
description = "Whether this DNS server can be used by accounts other than the owner to create and manage DNS zones")
|
||||
private Boolean isPublic;
|
||||
|
||||
@Parameter(name = ApiConstants.PUBLIC_DOMAIN_SUFFIX, type = CommandType.STRING,
|
||||
description = "Domain suffix that restricts DNS zones created by non-owner accounts to subdomains of this " +
|
||||
"suffix (for example, sub.example.com under example.com)")
|
||||
private String publicDomainSuffix;
|
||||
|
||||
@Parameter(name = ApiConstants.NAME_SERVERS, type = CommandType.LIST, collectionType = CommandType.STRING,
|
||||
description = "Comma separated list of name servers; used to create NS records for the DNS Zone (for example, ns1.example.com, ns2.example.com)")
|
||||
private List<String> nameServers;
|
||||
|
||||
@Parameter(name = ApiConstants.STATE, type = CommandType.STRING, description = "Update state for the DNS server (Enabled, Disabled)")
|
||||
private String state;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////////// Accessors ///////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
public Long getId() { return id; }
|
||||
public String getName() { return name; }
|
||||
public String getUrl() { return url; }
|
||||
public String getDnsApiKey() {
|
||||
return dnsApiKey;
|
||||
}
|
||||
public Integer getPort() {
|
||||
return port;
|
||||
}
|
||||
public Boolean isPublic() {
|
||||
return BooleanUtils.isTrue(isPublic);
|
||||
}
|
||||
public String getPublicDomainSuffix() {
|
||||
return publicDomainSuffix;
|
||||
}
|
||||
public String getNameServers() {
|
||||
if (nameServers == null) {
|
||||
return null;
|
||||
}
|
||||
return StringUtils.join(nameServers.stream()
|
||||
.filter(StringUtils::isNotBlank)
|
||||
.map(StringUtils::trim)
|
||||
.toArray(String[]::new), ",");
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getEntityOwnerId() {
|
||||
DnsServer server = _entityMgr.findById(DnsServer.class, id);
|
||||
if (server != null) {
|
||||
return server.getAccountId();
|
||||
}
|
||||
// If server not found, return System to fail safely (or let manager handle 404)
|
||||
return Account.ACCOUNT_ID_SYSTEM;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
try {
|
||||
DnsServer server = dnsProviderManager.updateDnsServer(this);
|
||||
if (server != null) {
|
||||
DnsServerResponse response = dnsProviderManager.createDnsServerResponse(server);
|
||||
response.setResponseName(getCommandName());
|
||||
setResponseObject(response);
|
||||
} else {
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to update DNS server");
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
logger.error("Failed to add update server", ex);
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public DnsServer.State getState() {
|
||||
if (StringUtils.isBlank(state)) {
|
||||
return null;
|
||||
}
|
||||
DnsServer.State dnsState = EnumUtils.getEnumIgnoreCase(DnsServer.State.class, state);
|
||||
if (dnsState == null) {
|
||||
throw new IllegalArgumentException("Invalid state value: " + state);
|
||||
}
|
||||
return dnsState;
|
||||
}
|
||||
}
|
||||
|
|
@ -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.user.dns;
|
||||
|
||||
import org.apache.cloudstack.acl.RoleType;
|
||||
import org.apache.cloudstack.acl.SecurityChecker;
|
||||
import org.apache.cloudstack.api.ACL;
|
||||
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.DnsZoneResponse;
|
||||
import org.apache.cloudstack.dns.DnsZone;
|
||||
|
||||
import com.cloud.user.Account;
|
||||
|
||||
@APICommand(name = "updateDnsZone",
|
||||
description = "Updates a DNS Zone's metadata",
|
||||
responseObject = DnsZoneResponse.class,
|
||||
entityType = {DnsZone.class},
|
||||
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false,
|
||||
since = "4.23.0",
|
||||
authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User})
|
||||
public class UpdateDnsZoneCmd extends BaseCmd {
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
//////////////// API Parameters /////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
@ACL(accessType = SecurityChecker.AccessType.OperateEntry)
|
||||
@Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = DnsZoneResponse.class,
|
||||
required = true, description = "The ID of the DNS zone")
|
||||
private Long id;
|
||||
|
||||
@Parameter(name = ApiConstants.DESCRIPTION, type = CommandType.STRING, description = "The description of the DNS zone to be updated")
|
||||
private String description;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////////// Accessors ///////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////// Implementation //////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
try {
|
||||
DnsZone result = dnsProviderManager.updateDnsZone(this);
|
||||
if (result != null) {
|
||||
DnsZoneResponse response = dnsProviderManager.createDnsZoneResponse(result);
|
||||
response.setResponseName(getCommandName());
|
||||
setResponseObject(response);
|
||||
} else {
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to update DNS Zone on external provider");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to update DNS Zone: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getEntityOwnerId() {
|
||||
DnsZone dnsZone = _entityMgr.findById(DnsZone.class, id);
|
||||
if (dnsZone != null) {
|
||||
return dnsZone.getAccountId();
|
||||
}
|
||||
return Account.ACCOUNT_ID_SYSTEM;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
// 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 com.cloud.serializer.Param;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
public class DnsProviderResponse extends BaseResponse {
|
||||
|
||||
@SerializedName(ApiConstants.NAME)
|
||||
@Param(description = "The name of the DNS provider (e.g. PowerDNS, Cloudflare)")
|
||||
private String name;
|
||||
|
||||
public DnsProviderResponse(String name) {
|
||||
this.name = name;
|
||||
setObjectName("dnsprovider"); // Sets the JSON wrapper name
|
||||
}
|
||||
|
||||
// Accessors
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
// 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 java.util.List;
|
||||
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.BaseResponse;
|
||||
import org.apache.cloudstack.dns.DnsRecord;
|
||||
|
||||
import com.cloud.serializer.Param;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
public class DnsRecordResponse extends BaseResponse {
|
||||
|
||||
@SerializedName(ApiConstants.NAME)
|
||||
@Param(description = "The record name (e.g., www.example.com.)")
|
||||
private String name;
|
||||
|
||||
@SerializedName(ApiConstants.TYPE)
|
||||
@Param(description = "The record type (e.g., A, CNAME, TXT)")
|
||||
private DnsRecord.RecordType type;
|
||||
|
||||
@SerializedName("contents")
|
||||
@Param(description = "The contents of the record (IP address or target)")
|
||||
private List<String> contents;
|
||||
|
||||
@SerializedName("ttl")
|
||||
@Param(description = "Time to live (TTL) in seconds")
|
||||
private Integer ttl;
|
||||
|
||||
public DnsRecordResponse() {
|
||||
super();
|
||||
setObjectName("dnsrecord");
|
||||
}
|
||||
|
||||
// Setters
|
||||
public void setName(String name) { this.name = name; }
|
||||
public void setType(DnsRecord.RecordType type) { this.type = type; }
|
||||
public void setContent(List<String> contents) { this.contents = contents; }
|
||||
public void setTtl(Integer ttl) { this.ttl = ttl; }
|
||||
}
|
||||
|
|
@ -0,0 +1,133 @@
|
|||
// 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 java.util.List;
|
||||
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.BaseResponse;
|
||||
import org.apache.cloudstack.api.EntityReference;
|
||||
import org.apache.cloudstack.dns.DnsServer;
|
||||
|
||||
import com.cloud.serializer.Param;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
@EntityReference(value = DnsServer.class)
|
||||
public class DnsServerResponse extends BaseResponse {
|
||||
|
||||
@SerializedName(ApiConstants.ID)
|
||||
@Param(description = "ID of the DNS server")
|
||||
private String id;
|
||||
|
||||
@SerializedName(ApiConstants.NAME)
|
||||
@Param(description = "Name of the DNS server")
|
||||
private String name;
|
||||
|
||||
@SerializedName(ApiConstants.URL)
|
||||
@Param(description = "URL of the DNS server API")
|
||||
private String url;
|
||||
|
||||
@SerializedName(ApiConstants.PORT)
|
||||
@Param(description = "The port of the DNS server")
|
||||
private Integer port;
|
||||
|
||||
@SerializedName(ApiConstants.PROVIDER)
|
||||
@Param(description = "The provider type of the DNS server")
|
||||
private String provider;
|
||||
|
||||
@SerializedName(ApiConstants.IS_PUBLIC)
|
||||
@Param(description = "Is the DNS server publicly available")
|
||||
private Boolean isPublic;
|
||||
|
||||
@SerializedName(ApiConstants.PUBLIC_DOMAIN_SUFFIX)
|
||||
@Param(description = "The public domain suffix for the DNS server")
|
||||
private String publicDomainSuffix;
|
||||
|
||||
@SerializedName(ApiConstants.NAME_SERVERS)
|
||||
@Param(description = "Name servers entries associated to DNS server")
|
||||
private List<String> nameServers;
|
||||
|
||||
@SerializedName(ApiConstants.ACCOUNT)
|
||||
@Param(description = "the account associated with the DNS server")
|
||||
private String accountName;
|
||||
|
||||
@SerializedName(ApiConstants.DOMAIN_ID)
|
||||
@Param(description = "the ID of the domain associated with the DNS server")
|
||||
private String domainId;
|
||||
|
||||
@SerializedName(ApiConstants.DOMAIN)
|
||||
@Param(description = "the name of the domain associated with the DNS server")
|
||||
private String domainName;
|
||||
|
||||
@SerializedName(ApiConstants.STATE)
|
||||
@Param(description = "The state of the account")
|
||||
private String state;
|
||||
|
||||
public DnsServerResponse() {
|
||||
super();
|
||||
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public void setUrl(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
public void setProvider(String provider) {
|
||||
this.provider = provider;
|
||||
}
|
||||
|
||||
public void setPublic(Boolean value) {
|
||||
isPublic = value;
|
||||
}
|
||||
|
||||
public void setPort(Integer port) {
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public void setPublicDomainSuffix(String publicDomainSuffix) {
|
||||
this.publicDomainSuffix = publicDomainSuffix;
|
||||
}
|
||||
|
||||
public void setNameServers(List<String> nameServers) {
|
||||
this.nameServers = nameServers;
|
||||
}
|
||||
|
||||
public void setAccountName(String accountName) {
|
||||
this.accountName = accountName;
|
||||
}
|
||||
|
||||
public void setDomainId(String domainId) {
|
||||
this.domainId = domainId;
|
||||
}
|
||||
|
||||
public void setDomainName(String domainName) {
|
||||
this.domainName = domainName;
|
||||
}
|
||||
|
||||
public void setState(String state) {
|
||||
this.state = state;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
// 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 com.cloud.serializer.Param;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
public class DnsZoneNetworkMapResponse extends BaseResponse {
|
||||
@SerializedName(ApiConstants.ID)
|
||||
@Param(description = "The ID of the mapping")
|
||||
private String id;
|
||||
|
||||
@SerializedName(ApiConstants.DNS_ZONE_ID)
|
||||
@Param(description = "The ID of the DNS zone")
|
||||
private String dnsZoneId;
|
||||
|
||||
@SerializedName(ApiConstants.NETWORK_ID)
|
||||
@Param(description = "The ID of the Network")
|
||||
private String networkId;
|
||||
|
||||
@SerializedName("subdomain")
|
||||
@Param(description = "The sub domain name of the auto-registered DNS record")
|
||||
private String subDomain;
|
||||
|
||||
public DnsZoneNetworkMapResponse() {
|
||||
super();
|
||||
setObjectName("dnszonenetwork");
|
||||
}
|
||||
|
||||
// Setters
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public void setDnsZoneId(String dnsZoneId) {
|
||||
this.dnsZoneId = dnsZoneId;
|
||||
}
|
||||
|
||||
public void setNetworkId(String networkId) {
|
||||
this.networkId = networkId;
|
||||
}
|
||||
|
||||
public void setSubDomain(String subDomain) {
|
||||
this.subDomain = subDomain;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,139 @@
|
|||
// 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 org.apache.cloudstack.dns.DnsZone;
|
||||
|
||||
import com.cloud.serializer.Param;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
@EntityReference(value = DnsZone.class)
|
||||
public class DnsZoneResponse extends BaseResponse {
|
||||
@SerializedName(ApiConstants.ID)
|
||||
@Param(description = "ID of the DNS zone")
|
||||
private String id;
|
||||
|
||||
@SerializedName(ApiConstants.NAME)
|
||||
@Param(description = "Name of the DNS zone")
|
||||
private String name;
|
||||
|
||||
@SerializedName("dnsserverid")
|
||||
@Param(description = "ID of the DNS server this zone belongs to")
|
||||
private String dnsServerId;
|
||||
|
||||
@SerializedName("dnsservername")
|
||||
@Param(description = "the name of the DNS server hosting this zone")
|
||||
private String dnsServerName;
|
||||
|
||||
@SerializedName("dnsserveraccount")
|
||||
@Param(description = "the account name of the DNS server owner")
|
||||
private String dnsServerAccountName;
|
||||
|
||||
@SerializedName(ApiConstants.ACCOUNT)
|
||||
@Param(description = "the account associated with the DNS zone")
|
||||
private String accountName;
|
||||
|
||||
@SerializedName(ApiConstants.DOMAIN)
|
||||
@Param(description = "the name of the domain associated with the DNS zone")
|
||||
private String domainName;
|
||||
|
||||
@SerializedName(ApiConstants.DOMAIN_ID)
|
||||
@Param(description = "the ID of the domain associated with the DNS server")
|
||||
private String domainId;
|
||||
|
||||
@SerializedName(ApiConstants.NETWORK_ID)
|
||||
@Param(description = "ID of the network this zone is associated with")
|
||||
private String networkId;
|
||||
|
||||
@SerializedName(ApiConstants.NETWORK_NAME)
|
||||
@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 DnsZone.ZoneType type;
|
||||
|
||||
@SerializedName(ApiConstants.STATE)
|
||||
@Param(description = "The state of the zone (Active/Inactive)")
|
||||
private DnsZone.State state;
|
||||
|
||||
@SerializedName(ApiConstants.DESCRIPTION)
|
||||
@Param(description = "Description for the DNS zone")
|
||||
private String description;
|
||||
|
||||
public DnsZoneResponse() {
|
||||
super();
|
||||
setObjectName("dnszone");
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public void setDnsServerId(String dnsServerId) {
|
||||
this.dnsServerId = dnsServerId;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public void setDnsServerName(String dnsServerName) {
|
||||
this.dnsServerName = dnsServerName;
|
||||
}
|
||||
|
||||
public void setDnsServerAccountName(String dnsServerAccountName) {
|
||||
this.dnsServerAccountName = dnsServerAccountName;
|
||||
}
|
||||
|
||||
public void setAccountName(String accountName) {
|
||||
this.accountName = accountName;
|
||||
}
|
||||
|
||||
public void setDomainName(String domainName) {
|
||||
this.domainName = domainName;
|
||||
}
|
||||
|
||||
public void setDomainId(String domainId) {
|
||||
this.domainId = domainId;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -335,6 +335,14 @@ public class NetworkResponse extends BaseResponseWithAssociatedNetwork implement
|
|||
@Param(description = ApiConstants.PARAMETER_DESCRIPTION_KEEP_MAC_ADDRESS_ON_PUBLIC_NIC, since = "4.23.0")
|
||||
private Boolean keepMacAddressOnPublicNic;
|
||||
|
||||
@SerializedName(ApiConstants.DNS_ZONE)
|
||||
@Param(description = "DNS zone associated to the network", since = "4.23.0")
|
||||
private String dnsZone;
|
||||
|
||||
@SerializedName(ApiConstants.DNS_SUB_DOMAIN)
|
||||
@Param(description = "DNS subdomain associated to the network", since = "4.23.0")
|
||||
private String dnsSubdomain;
|
||||
|
||||
public NetworkResponse() {}
|
||||
|
||||
public Boolean getDisplayNetwork() {
|
||||
|
|
@ -710,4 +718,12 @@ public class NetworkResponse extends BaseResponseWithAssociatedNetwork implement
|
|||
public void setKeepMacAddressOnPublicNic(Boolean keepMacAddressOnPublicNic) {
|
||||
this.keepMacAddressOnPublicNic = keepMacAddressOnPublicNic;
|
||||
}
|
||||
|
||||
public void setDnsZone(String dnsZone) {
|
||||
this.dnsZone = dnsZone;
|
||||
}
|
||||
|
||||
public void setDnsSubdomain(String dnsSubdomain) {
|
||||
this.dnsSubdomain = dnsSubdomain;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -150,6 +150,10 @@ public class NicResponse extends BaseResponse {
|
|||
@Param(description = "whether the NIC is enabled or not")
|
||||
private Boolean isEnabled;
|
||||
|
||||
@SerializedName(ApiConstants.NIC_DNS_NAME)
|
||||
@Param(description = "DNS name associated with this NIC's IP address")
|
||||
private String nicDnsName;
|
||||
|
||||
public void setVmId(String vmId) {
|
||||
this.vmId = vmId;
|
||||
}
|
||||
|
|
@ -428,4 +432,8 @@ public class NicResponse extends BaseResponse {
|
|||
public void setEnabled(Boolean enabled) {
|
||||
isEnabled = enabled;
|
||||
}
|
||||
|
||||
public void setNicDnsName(String nicDnsName) {
|
||||
this.nicDnsName = nicDnsName;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,45 @@
|
|||
// 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.dns;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.cloudstack.dns.exception.DnsProviderException;
|
||||
|
||||
import com.cloud.utils.component.Adapter;
|
||||
|
||||
public interface DnsProvider extends Adapter {
|
||||
DnsProviderType getProviderType();
|
||||
|
||||
// Validates connectivity to the server
|
||||
void validate(DnsServer server) throws Exception;
|
||||
|
||||
String validateAndResolveServer(DnsServer server) throws Exception;
|
||||
|
||||
// Zone Operations
|
||||
String provisionZone(DnsServer server, DnsZone zone) throws DnsProviderException;
|
||||
void deleteZone(DnsServer server, DnsZone zone) throws DnsProviderException;
|
||||
void updateZone(DnsServer server, DnsZone zone) throws DnsProviderException;
|
||||
|
||||
String addRecord(DnsServer server, DnsZone zone, DnsRecord record) throws DnsProviderException;
|
||||
List<DnsRecord> listRecords(DnsServer server, DnsZone zone) throws DnsProviderException;
|
||||
String updateRecord(DnsServer server, DnsZone zone, DnsRecord record) throws DnsProviderException;
|
||||
String deleteRecord(DnsServer server, DnsZone zone, DnsRecord record) throws DnsProviderException;
|
||||
boolean dnsRecordExists(DnsServer server, DnsZone zone, String recordName, String recordType) throws DnsProviderException;
|
||||
boolean dnsZoneExists(DnsServer server, DnsZone zone);
|
||||
}
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
// 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.dns;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.cloudstack.api.command.user.dns.AddDnsServerCmd;
|
||||
import org.apache.cloudstack.api.command.user.dns.AssociateDnsZoneToNetworkCmd;
|
||||
import org.apache.cloudstack.api.command.user.dns.CreateDnsRecordCmd;
|
||||
import org.apache.cloudstack.api.command.user.dns.CreateDnsZoneCmd;
|
||||
import org.apache.cloudstack.api.command.user.dns.DeleteDnsRecordCmd;
|
||||
import org.apache.cloudstack.api.command.user.dns.DeleteDnsServerCmd;
|
||||
import org.apache.cloudstack.api.command.user.dns.DisassociateDnsZoneFromNetworkCmd;
|
||||
import org.apache.cloudstack.api.command.user.dns.ListDnsRecordsCmd;
|
||||
import org.apache.cloudstack.api.command.user.dns.ListDnsServersCmd;
|
||||
import org.apache.cloudstack.api.command.user.dns.ListDnsZonesCmd;
|
||||
import org.apache.cloudstack.api.command.user.dns.UpdateDnsServerCmd;
|
||||
import org.apache.cloudstack.api.command.user.dns.UpdateDnsZoneCmd;
|
||||
import org.apache.cloudstack.api.response.DnsRecordResponse;
|
||||
import org.apache.cloudstack.api.response.DnsServerResponse;
|
||||
import org.apache.cloudstack.api.response.DnsZoneNetworkMapResponse;
|
||||
import org.apache.cloudstack.api.response.DnsZoneResponse;
|
||||
import org.apache.cloudstack.api.response.ListResponse;
|
||||
|
||||
import com.cloud.user.Account;
|
||||
import com.cloud.utils.component.Manager;
|
||||
import com.cloud.utils.component.PluggableService;
|
||||
|
||||
public interface DnsProviderManager extends Manager, PluggableService {
|
||||
|
||||
DnsServer addDnsServer(AddDnsServerCmd cmd);
|
||||
ListResponse<DnsServerResponse> listDnsServers(ListDnsServersCmd cmd);
|
||||
DnsServer updateDnsServer(UpdateDnsServerCmd cmd);
|
||||
boolean deleteDnsServer(DeleteDnsServerCmd cmd);
|
||||
DnsServerResponse createDnsServerResponse(DnsServer server);
|
||||
|
||||
// Allocates the DB row (State: Inactive)
|
||||
DnsZone allocateDnsZone(CreateDnsZoneCmd cmd);
|
||||
// Calls the Plugin (State: Inactive -> Active)
|
||||
DnsZone provisionDnsZone(long zoneId, boolean isImport);
|
||||
|
||||
DnsZone updateDnsZone(UpdateDnsZoneCmd cmd);
|
||||
boolean deleteDnsZone(Long id, boolean isUnmanage);
|
||||
ListResponse<DnsZoneResponse> listDnsZones(ListDnsZonesCmd cmd);
|
||||
|
||||
DnsRecordResponse createDnsRecord(CreateDnsRecordCmd cmd);
|
||||
boolean deleteDnsRecord(DeleteDnsRecordCmd cmd);
|
||||
ListResponse<DnsRecordResponse> listDnsRecords(ListDnsRecordsCmd cmd);
|
||||
|
||||
List<String> listProviderNames();
|
||||
|
||||
// Helper to create the response object
|
||||
DnsZoneResponse createDnsZoneResponse(DnsZone zone);
|
||||
DnsRecordResponse createDnsRecordResponse(DnsRecord record);
|
||||
|
||||
DnsZoneNetworkMapResponse associateZoneToNetwork(AssociateDnsZoneToNetworkCmd cmd);
|
||||
|
||||
boolean disassociateZoneFromNetwork(DisassociateDnsZoneFromNetworkCmd cmd);
|
||||
|
||||
void checkDnsServerPermission(Account caller, DnsServer dnsServer);
|
||||
|
||||
void checkDnsZonePermission(Account caller, DnsZone dnsZone);
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
// 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.dns;
|
||||
|
||||
public enum DnsProviderType {
|
||||
PowerDNS;
|
||||
// Cloudflare
|
||||
}
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
// 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.dns;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
|
||||
public class DnsRecord {
|
||||
|
||||
public enum RecordType {
|
||||
A, AAAA, CNAME, MX, TXT, SRV, PTR, NS;
|
||||
|
||||
public static RecordType fromString(String type) {
|
||||
if (type == null) return null;
|
||||
try {
|
||||
return RecordType.valueOf(type.toUpperCase());
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new CloudRuntimeException("Invalid DNS Record Type: " + type +
|
||||
". Supported: " + java.util.Arrays.toString(values()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String name;
|
||||
private RecordType type;
|
||||
private List<String> contents;
|
||||
private int ttl;
|
||||
|
||||
public DnsRecord() {}
|
||||
|
||||
public DnsRecord(String name, RecordType type, List<String> contents, int ttl) {
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
this.contents = contents;
|
||||
this.ttl = ttl;
|
||||
}
|
||||
|
||||
// Getters and Setters
|
||||
public String getName() { return name; }
|
||||
public void setName(String name) { this.name = name; }
|
||||
|
||||
public RecordType getType() { return type; }
|
||||
public void setType(RecordType type) { this.type = type; }
|
||||
|
||||
public List<String> getContents() { return contents; }
|
||||
public void setContents(List<String> contents) { this.contents = contents; }
|
||||
|
||||
public int getTtl() { return ttl; }
|
||||
public void setTtl(int ttl) { this.ttl = ttl; }
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
// 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.dns;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.cloudstack.acl.ControlledEntity;
|
||||
import org.apache.cloudstack.api.Identity;
|
||||
import org.apache.cloudstack.api.InternalIdentity;
|
||||
|
||||
public interface DnsServer extends InternalIdentity, Identity, ControlledEntity {
|
||||
enum State {
|
||||
Enabled, Disabled
|
||||
};
|
||||
|
||||
String getName();
|
||||
|
||||
String getUrl();
|
||||
|
||||
DnsProviderType getProviderType();
|
||||
|
||||
List<String> getNameServers();
|
||||
|
||||
String getDnsApiKey();
|
||||
|
||||
long getAccountId();
|
||||
|
||||
boolean getPublicServer();
|
||||
|
||||
Date getCreated();
|
||||
|
||||
Date getRemoved();
|
||||
|
||||
String getPublicDomainSuffix();
|
||||
|
||||
Integer getPort();
|
||||
|
||||
Map<String, String> getDetails();
|
||||
|
||||
String getDetail(String name);
|
||||
|
||||
void setDetails(Map<String, String> details);
|
||||
|
||||
void appendDetails(String name, String value);
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
// 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.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, ControlledEntity {
|
||||
enum ZoneType {
|
||||
Public, Private
|
||||
}
|
||||
enum State {
|
||||
Active, Inactive
|
||||
}
|
||||
|
||||
String getName();
|
||||
|
||||
long getDnsServerId();
|
||||
|
||||
long getAccountId();
|
||||
|
||||
ZoneType getType();
|
||||
|
||||
String getDescription();
|
||||
|
||||
List<Long> getAssociatedNetworks();
|
||||
|
||||
State getState();
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
// 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.dns.exception;
|
||||
|
||||
/**
|
||||
* Thrown when authentication to the DNS provider fails.
|
||||
*/
|
||||
public class DnsAuthenticationException extends DnsProviderException {
|
||||
public DnsAuthenticationException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
// 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.dns.exception;
|
||||
|
||||
/**
|
||||
* Thrown when attempting to create a zone or record that already exists.
|
||||
*/
|
||||
public class DnsConflictException extends DnsProviderException {
|
||||
public DnsConflictException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
// 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.dns.exception;
|
||||
|
||||
/**
|
||||
* Thrown when the requested zone or record does not exist.
|
||||
*/
|
||||
public class DnsNotFoundException extends DnsProviderException {
|
||||
public DnsNotFoundException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
// 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.dns.exception;
|
||||
|
||||
/**
|
||||
* Thrown for unexpected or unknown errors returned by the DNS provider.
|
||||
*/
|
||||
public class DnsOperationException extends DnsProviderException {
|
||||
public DnsOperationException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
// 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.dns.exception;
|
||||
|
||||
public class DnsProviderException extends Exception {
|
||||
public DnsProviderException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public DnsProviderException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
// 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.dns.exception;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Thrown when HTTP or network errors occur communicating with the DNS provider.
|
||||
*/
|
||||
public class DnsTransportException extends DnsProviderException {
|
||||
|
||||
public DnsTransportException(String message, IOException cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,134 @@
|
|||
// 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.user.dns;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.apache.cloudstack.api.ServerApiException;
|
||||
import org.apache.cloudstack.api.response.DnsServerResponse;
|
||||
import org.apache.cloudstack.dns.DnsProviderType;
|
||||
import org.apache.cloudstack.dns.DnsServer;
|
||||
import org.junit.Test;
|
||||
|
||||
public class AddDnsServerCmdTest extends BaseDnsCmdTest {
|
||||
|
||||
private AddDnsServerCmd createCmd() throws Exception {
|
||||
AddDnsServerCmd cmd = new AddDnsServerCmd();
|
||||
setField(cmd, "dnsProviderManager", dnsProviderManager);
|
||||
setField(cmd, "name", "test-dns");
|
||||
setField(cmd, "url", "http://dns.example.com");
|
||||
setField(cmd, "provider", "PowerDNS");
|
||||
setField(cmd, "dnsApiKey", "api-key-123");
|
||||
setField(cmd, "port", 8081);
|
||||
setField(cmd, "isPublic", true);
|
||||
setField(cmd, "publicDomainSuffix", "public.example.com");
|
||||
setField(cmd, "nameServers", Arrays.asList("ns1.example.com", "ns2.example.com"));
|
||||
setField(cmd, "dnsUserName", "admin@example.com");
|
||||
return cmd;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAccessors() throws Exception {
|
||||
AddDnsServerCmd cmd = createCmd();
|
||||
|
||||
assertEquals("test-dns", cmd.getName());
|
||||
assertEquals("http://dns.example.com", cmd.getUrl());
|
||||
assertEquals("api-key-123", cmd.getDnsApiKey());
|
||||
assertEquals(Integer.valueOf(8081), cmd.getPort());
|
||||
assertTrue(cmd.isPublic());
|
||||
assertEquals("public.example.com", cmd.getPublicDomainSuffix());
|
||||
assertEquals(Arrays.asList("ns1.example.com", "ns2.example.com"), cmd.getNameServers());
|
||||
assertEquals(DnsProviderType.PowerDNS, cmd.getProvider());
|
||||
assertEquals("admin@example.com", cmd.getDnsUserName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsPublicFalse() throws Exception {
|
||||
AddDnsServerCmd cmd = createCmd();
|
||||
setField(cmd, "isPublic", false);
|
||||
assertFalse(cmd.isPublic());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsPublicNull() throws Exception {
|
||||
AddDnsServerCmd cmd = createCmd();
|
||||
setField(cmd, "isPublic", null);
|
||||
assertFalse(cmd.isPublic());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetEntityOwnerId() throws Exception {
|
||||
AddDnsServerCmd cmd = createCmd();
|
||||
assertEquals(ACCOUNT_ID, cmd.getEntityOwnerId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetProviderDefault() throws Exception {
|
||||
AddDnsServerCmd cmd = createCmd();
|
||||
setField(cmd, "provider", null);
|
||||
assertEquals(DnsProviderType.PowerDNS, cmd.getProvider());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetProviderCaseInsensitive() throws Exception {
|
||||
AddDnsServerCmd cmd = createCmd();
|
||||
setField(cmd, "provider", "powerdns");
|
||||
assertEquals(DnsProviderType.PowerDNS, cmd.getProvider());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExecuteSuccess() throws Exception {
|
||||
AddDnsServerCmd cmd = createCmd();
|
||||
|
||||
DnsServer mockServer = mock(DnsServer.class);
|
||||
DnsServerResponse mockResponse = new DnsServerResponse();
|
||||
mockResponse.setName("test-dns");
|
||||
|
||||
when(dnsProviderManager.addDnsServer(cmd)).thenReturn(mockServer);
|
||||
when(dnsProviderManager.createDnsServerResponse(mockServer)).thenReturn(mockResponse);
|
||||
|
||||
cmd.execute();
|
||||
|
||||
DnsServerResponse response = (DnsServerResponse) cmd.getResponseObject();
|
||||
assertNotNull(response);
|
||||
assertEquals("adddnsserverresponse", response.getResponseName());
|
||||
verify(dnsProviderManager).addDnsServer(cmd);
|
||||
verify(dnsProviderManager).createDnsServerResponse(mockServer);
|
||||
}
|
||||
|
||||
@Test(expected = ServerApiException.class)
|
||||
public void testExecuteReturnsNull() throws Exception {
|
||||
AddDnsServerCmd cmd = createCmd();
|
||||
when(dnsProviderManager.addDnsServer(cmd)).thenReturn(null);
|
||||
cmd.execute();
|
||||
}
|
||||
|
||||
@Test(expected = ServerApiException.class)
|
||||
public void testExecuteThrowsException() throws Exception {
|
||||
AddDnsServerCmd cmd = createCmd();
|
||||
when(dnsProviderManager.addDnsServer(cmd)).thenThrow(new RuntimeException("Connection refused"));
|
||||
cmd.execute();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
// 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.user.dns;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import org.apache.cloudstack.api.ServerApiException;
|
||||
import org.apache.cloudstack.api.response.DnsZoneNetworkMapResponse;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.cloud.network.Network;
|
||||
import com.cloud.user.Account;
|
||||
|
||||
public class AssociateDnsZoneToNetworkCmdTest extends BaseDnsCmdTest {
|
||||
|
||||
private static final long NETWORK_ID = 200L;
|
||||
|
||||
private AssociateDnsZoneToNetworkCmd createCmd() throws Exception {
|
||||
AssociateDnsZoneToNetworkCmd cmd = new AssociateDnsZoneToNetworkCmd();
|
||||
setField(cmd, "dnsProviderManager", dnsProviderManager);
|
||||
setField(cmd, "_entityMgr", entityManager);
|
||||
setField(cmd, "dnsZoneId", ENTITY_ID);
|
||||
setField(cmd, "networkId", NETWORK_ID);
|
||||
setField(cmd, "subDomain", "dev");
|
||||
return cmd;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAccessors() throws Exception {
|
||||
AssociateDnsZoneToNetworkCmd cmd = createCmd();
|
||||
assertEquals(Long.valueOf(ENTITY_ID), cmd.getDnsZoneId());
|
||||
assertEquals(Long.valueOf(NETWORK_ID), cmd.getNetworkId());
|
||||
assertEquals("dev", cmd.getSubDomain());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetEntityOwnerIdWithNetwork() throws Exception {
|
||||
AssociateDnsZoneToNetworkCmd cmd = createCmd();
|
||||
Network mockNetwork = mock(Network.class);
|
||||
when(mockNetwork.getAccountId()).thenReturn(ACCOUNT_ID);
|
||||
when(entityManager.findById(Network.class, NETWORK_ID))
|
||||
.thenReturn(mockNetwork);
|
||||
|
||||
assertEquals(ACCOUNT_ID, cmd.getEntityOwnerId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetEntityOwnerIdNetworkNotFound() throws Exception {
|
||||
AssociateDnsZoneToNetworkCmd cmd = createCmd();
|
||||
when(entityManager.findById(Network.class, NETWORK_ID))
|
||||
.thenReturn(null);
|
||||
|
||||
assertEquals(Account.ACCOUNT_ID_SYSTEM, cmd.getEntityOwnerId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExecuteSuccess() throws Exception {
|
||||
AssociateDnsZoneToNetworkCmd cmd = createCmd();
|
||||
DnsZoneNetworkMapResponse mockResponse =
|
||||
new DnsZoneNetworkMapResponse();
|
||||
when(dnsProviderManager.associateZoneToNetwork(cmd))
|
||||
.thenReturn(mockResponse);
|
||||
|
||||
cmd.execute();
|
||||
|
||||
DnsZoneNetworkMapResponse response =
|
||||
(DnsZoneNetworkMapResponse) cmd.getResponseObject();
|
||||
assertNotNull(response);
|
||||
assertEquals("associatednszonetonetworkresponse",
|
||||
response.getResponseName());
|
||||
}
|
||||
|
||||
@Test(expected = ServerApiException.class)
|
||||
public void testExecuteThrowsException() throws Exception {
|
||||
AssociateDnsZoneToNetworkCmd cmd = createCmd();
|
||||
when(dnsProviderManager.associateZoneToNetwork(cmd))
|
||||
.thenThrow(new RuntimeException("Error"));
|
||||
cmd.execute();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
// 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.user.dns;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import org.apache.cloudstack.context.CallContext;
|
||||
import org.apache.cloudstack.dns.DnsProviderManager;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.mockito.MockedStatic;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import com.cloud.user.Account;
|
||||
import com.cloud.utils.db.EntityManager;
|
||||
|
||||
/**
|
||||
* Shared setup for all DNS command unit tests.
|
||||
*/
|
||||
public abstract class BaseDnsCmdTest {
|
||||
|
||||
protected static final long ACCOUNT_ID = 42L;
|
||||
protected static final long ENTITY_ID = 100L;
|
||||
|
||||
protected DnsProviderManager dnsProviderManager;
|
||||
protected EntityManager entityManager;
|
||||
protected Account callingAccount;
|
||||
|
||||
private MockedStatic<CallContext> callContextMock;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
dnsProviderManager = mock(DnsProviderManager.class);
|
||||
entityManager = mock(EntityManager.class);
|
||||
|
||||
callingAccount = mock(Account.class);
|
||||
when(callingAccount.getId()).thenReturn(ACCOUNT_ID);
|
||||
|
||||
CallContext callContext = mock(CallContext.class);
|
||||
when(callContext.getCallingAccount()).thenReturn(callingAccount);
|
||||
|
||||
callContextMock = Mockito.mockStatic(CallContext.class);
|
||||
callContextMock.when(CallContext::current).thenReturn(callContext);
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
callContextMock.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a private/inherited field value via reflection.
|
||||
*/
|
||||
protected void setField(Object target, String fieldName, Object value) throws Exception {
|
||||
Field field = null;
|
||||
Class<?> clazz = target.getClass();
|
||||
while (clazz != null) {
|
||||
try {
|
||||
field = clazz.getDeclaredField(fieldName);
|
||||
break;
|
||||
} catch (NoSuchFieldException e) {
|
||||
clazz = clazz.getSuperclass();
|
||||
}
|
||||
}
|
||||
if (field == null) {
|
||||
throw new NoSuchFieldException(fieldName + " not found in hierarchy of " + target.getClass().getName());
|
||||
}
|
||||
field.setAccessible(true);
|
||||
field.set(target, value);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,117 @@
|
|||
// 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.user.dns;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.apache.cloudstack.api.ServerApiException;
|
||||
import org.apache.cloudstack.api.response.DnsRecordResponse;
|
||||
import org.apache.cloudstack.dns.DnsRecord;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.cloud.event.EventTypes;
|
||||
import com.cloud.exception.InvalidParameterValueException;
|
||||
|
||||
public class CreateDnsRecordCmdTest extends BaseDnsCmdTest {
|
||||
|
||||
private CreateDnsRecordCmd createCmd() throws Exception {
|
||||
CreateDnsRecordCmd cmd = new CreateDnsRecordCmd();
|
||||
setField(cmd, "dnsProviderManager", dnsProviderManager);
|
||||
setField(cmd, "dnsZoneId", ENTITY_ID);
|
||||
setField(cmd, "name", "www");
|
||||
setField(cmd, "type", "A");
|
||||
setField(cmd, "contents", Arrays.asList("192.168.1.1"));
|
||||
setField(cmd, "ttl", 7200);
|
||||
return cmd;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAccessors() throws Exception {
|
||||
CreateDnsRecordCmd cmd = createCmd();
|
||||
|
||||
assertEquals(Long.valueOf(ENTITY_ID), cmd.getDnsZoneId());
|
||||
assertEquals("www", cmd.getName());
|
||||
assertEquals(DnsRecord.RecordType.A, cmd.getType());
|
||||
assertEquals(Arrays.asList("192.168.1.1"), cmd.getContents());
|
||||
assertEquals(Integer.valueOf(7200), cmd.getTtl());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetTtlDefault() throws Exception {
|
||||
CreateDnsRecordCmd cmd = createCmd();
|
||||
setField(cmd, "ttl", null);
|
||||
assertEquals(Integer.valueOf(3600), cmd.getTtl());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetTypeCname() throws Exception {
|
||||
CreateDnsRecordCmd cmd = createCmd();
|
||||
setField(cmd, "type", "CNAME");
|
||||
assertEquals(DnsRecord.RecordType.CNAME, cmd.getType());
|
||||
}
|
||||
|
||||
@Test(expected = InvalidParameterValueException.class)
|
||||
public void testGetTypeInvalid() throws Exception {
|
||||
CreateDnsRecordCmd cmd = createCmd();
|
||||
setField(cmd, "type", "INVALID");
|
||||
cmd.getType();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetEntityOwnerId() throws Exception {
|
||||
CreateDnsRecordCmd cmd = createCmd();
|
||||
assertEquals(ACCOUNT_ID, cmd.getEntityOwnerId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEventType() throws Exception {
|
||||
CreateDnsRecordCmd cmd = createCmd();
|
||||
assertEquals(EventTypes.EVENT_DNS_RECORD_CREATE, cmd.getEventType());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEventDescription() throws Exception {
|
||||
CreateDnsRecordCmd cmd = createCmd();
|
||||
assertEquals("Creating DNS Record: www", cmd.getEventDescription());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExecuteSuccess() throws Exception {
|
||||
CreateDnsRecordCmd cmd = createCmd();
|
||||
|
||||
DnsRecordResponse mockResponse = new DnsRecordResponse();
|
||||
mockResponse.setName("www");
|
||||
when(dnsProviderManager.createDnsRecord(cmd)).thenReturn(mockResponse);
|
||||
|
||||
cmd.execute();
|
||||
|
||||
DnsRecordResponse response = (DnsRecordResponse) cmd.getResponseObject();
|
||||
assertNotNull(response);
|
||||
assertEquals("creatednsrecordresponse", response.getResponseName());
|
||||
}
|
||||
|
||||
@Test(expected = ServerApiException.class)
|
||||
public void testExecuteThrowsException() throws Exception {
|
||||
CreateDnsRecordCmd cmd = createCmd();
|
||||
when(dnsProviderManager.createDnsRecord(cmd)).thenThrow(new RuntimeException("Provider error"));
|
||||
cmd.execute();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,157 @@
|
|||
// 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.user.dns;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import org.apache.cloudstack.api.ServerApiException;
|
||||
import org.apache.cloudstack.api.response.DnsZoneResponse;
|
||||
import org.apache.cloudstack.dns.DnsZone;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.cloud.event.EventTypes;
|
||||
|
||||
public class CreateDnsZoneCmdTest extends BaseDnsCmdTest {
|
||||
|
||||
private CreateDnsZoneCmd createCmd() throws Exception {
|
||||
CreateDnsZoneCmd cmd = new CreateDnsZoneCmd();
|
||||
setField(cmd, "dnsProviderManager", dnsProviderManager);
|
||||
setField(cmd, "name", "example.com");
|
||||
setField(cmd, "dnsServerId", ENTITY_ID);
|
||||
setField(cmd, "type", "Public");
|
||||
setField(cmd, "description", "Test zone");
|
||||
return cmd;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAccessors() throws Exception {
|
||||
CreateDnsZoneCmd cmd = createCmd();
|
||||
|
||||
assertEquals("example.com", cmd.getName());
|
||||
assertEquals(Long.valueOf(ENTITY_ID), cmd.getDnsServerId());
|
||||
assertEquals(DnsZone.ZoneType.Public, cmd.getType());
|
||||
assertEquals("Test zone", cmd.getDescription());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetTypePrivate() throws Exception {
|
||||
CreateDnsZoneCmd cmd = createCmd();
|
||||
setField(cmd, "type", "Private");
|
||||
assertEquals(DnsZone.ZoneType.Private, cmd.getType());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetTypeDefaultsToPublicWhenNull() throws Exception {
|
||||
CreateDnsZoneCmd cmd = createCmd();
|
||||
setField(cmd, "type", null);
|
||||
assertEquals(DnsZone.ZoneType.Public, cmd.getType());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetTypeDefaultsToPublicWhenBlank() throws Exception {
|
||||
CreateDnsZoneCmd cmd = createCmd();
|
||||
setField(cmd, "type", "");
|
||||
assertEquals(DnsZone.ZoneType.Public, cmd.getType());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetEntityOwnerId() throws Exception {
|
||||
CreateDnsZoneCmd cmd = createCmd();
|
||||
assertEquals(ACCOUNT_ID, cmd.getEntityOwnerId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEventType() throws Exception {
|
||||
CreateDnsZoneCmd cmd = createCmd();
|
||||
assertEquals(EventTypes.EVENT_DNS_ZONE_CREATE, cmd.getEventType());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEventDescription() throws Exception {
|
||||
CreateDnsZoneCmd cmd = createCmd();
|
||||
assertEquals("creating DNS zone: example.com", cmd.getEventDescription());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateSuccess() throws Exception {
|
||||
CreateDnsZoneCmd cmd = createCmd();
|
||||
|
||||
DnsZone mockZone = mock(DnsZone.class);
|
||||
when(mockZone.getId()).thenReturn(ENTITY_ID);
|
||||
when(mockZone.getUuid()).thenReturn("uuid-123");
|
||||
when(dnsProviderManager.allocateDnsZone(cmd)).thenReturn(mockZone);
|
||||
|
||||
cmd.create();
|
||||
|
||||
assertEquals(Long.valueOf(ENTITY_ID), cmd.getEntityId());
|
||||
assertEquals("uuid-123", cmd.getEntityUuid());
|
||||
}
|
||||
|
||||
@Test(expected = ServerApiException.class)
|
||||
public void testCreateReturnsNull() throws Exception {
|
||||
CreateDnsZoneCmd cmd = createCmd();
|
||||
when(dnsProviderManager.allocateDnsZone(cmd)).thenReturn(null);
|
||||
cmd.create();
|
||||
}
|
||||
|
||||
@Test(expected = ServerApiException.class)
|
||||
public void testCreateThrowsException() throws Exception {
|
||||
CreateDnsZoneCmd cmd = createCmd();
|
||||
when(dnsProviderManager.allocateDnsZone(cmd)).thenThrow(new RuntimeException("DB error"));
|
||||
cmd.create();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExecuteSuccess() throws Exception {
|
||||
CreateDnsZoneCmd cmd = createCmd();
|
||||
cmd.setEntityId(ENTITY_ID);
|
||||
|
||||
DnsZone mockZone = mock(DnsZone.class);
|
||||
DnsZoneResponse mockResponse = new DnsZoneResponse();
|
||||
mockResponse.setName("example.com");
|
||||
|
||||
when(dnsProviderManager.provisionDnsZone(ENTITY_ID, false)).thenReturn(mockZone);
|
||||
when(dnsProviderManager.createDnsZoneResponse(mockZone)).thenReturn(mockResponse);
|
||||
|
||||
cmd.execute();
|
||||
|
||||
DnsZoneResponse response = (DnsZoneResponse) cmd.getResponseObject();
|
||||
assertNotNull(response);
|
||||
assertEquals("creatednszoneresponse", response.getResponseName());
|
||||
}
|
||||
|
||||
@Test(expected = ServerApiException.class)
|
||||
public void testExecuteReturnsNull() throws Exception {
|
||||
CreateDnsZoneCmd cmd = createCmd();
|
||||
cmd.setEntityId(ENTITY_ID);
|
||||
|
||||
when(dnsProviderManager.provisionDnsZone(ENTITY_ID, false)).thenReturn(null);
|
||||
cmd.execute();
|
||||
}
|
||||
|
||||
@Test(expected = ServerApiException.class)
|
||||
public void testExecuteThrowsException() throws Exception {
|
||||
CreateDnsZoneCmd cmd = createCmd();
|
||||
cmd.setEntityId(ENTITY_ID);
|
||||
|
||||
when(dnsProviderManager.provisionDnsZone(ENTITY_ID, false)).thenThrow(new RuntimeException("Provider error"));
|
||||
cmd.execute();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,102 @@
|
|||
// 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.user.dns;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import org.apache.cloudstack.api.ServerApiException;
|
||||
import org.apache.cloudstack.api.response.SuccessResponse;
|
||||
import org.apache.cloudstack.dns.DnsRecord;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.cloud.event.EventTypes;
|
||||
import com.cloud.exception.InvalidParameterValueException;
|
||||
|
||||
public class DeleteDnsRecordCmdTest extends BaseDnsCmdTest {
|
||||
|
||||
private DeleteDnsRecordCmd createCmd() throws Exception {
|
||||
DeleteDnsRecordCmd cmd = new DeleteDnsRecordCmd();
|
||||
setField(cmd, "dnsProviderManager", dnsProviderManager);
|
||||
setField(cmd, "dnsZoneId", ENTITY_ID);
|
||||
setField(cmd, "name", "www");
|
||||
setField(cmd, "type", "A");
|
||||
return cmd;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAccessors() throws Exception {
|
||||
DeleteDnsRecordCmd cmd = createCmd();
|
||||
|
||||
assertEquals(Long.valueOf(ENTITY_ID), cmd.getDnsZoneId());
|
||||
assertEquals("www", cmd.getName());
|
||||
assertEquals(DnsRecord.RecordType.A, cmd.getType());
|
||||
}
|
||||
|
||||
@Test(expected = InvalidParameterValueException.class)
|
||||
public void testGetTypeInvalid() throws Exception {
|
||||
DeleteDnsRecordCmd cmd = createCmd();
|
||||
setField(cmd, "type", "BOGUS");
|
||||
cmd.getType();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetEntityOwnerId() throws Exception {
|
||||
DeleteDnsRecordCmd cmd = createCmd();
|
||||
assertEquals(ACCOUNT_ID, cmd.getEntityOwnerId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEventType() throws Exception {
|
||||
DeleteDnsRecordCmd cmd = createCmd();
|
||||
assertEquals(EventTypes.EVENT_DNS_RECORD_DELETE, cmd.getEventType());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEventDescription() throws Exception {
|
||||
DeleteDnsRecordCmd cmd = createCmd();
|
||||
assertEquals("Deleting DNS Record: www", cmd.getEventDescription());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExecuteSuccess() throws Exception {
|
||||
DeleteDnsRecordCmd cmd = createCmd();
|
||||
when(dnsProviderManager.deleteDnsRecord(cmd)).thenReturn(true);
|
||||
|
||||
cmd.execute();
|
||||
|
||||
SuccessResponse response = (SuccessResponse) cmd.getResponseObject();
|
||||
assertNotNull(response);
|
||||
verify(dnsProviderManager).deleteDnsRecord(cmd);
|
||||
}
|
||||
|
||||
@Test(expected = ServerApiException.class)
|
||||
public void testExecuteReturnsFalse() throws Exception {
|
||||
DeleteDnsRecordCmd cmd = createCmd();
|
||||
when(dnsProviderManager.deleteDnsRecord(cmd)).thenReturn(false);
|
||||
cmd.execute();
|
||||
}
|
||||
|
||||
@Test(expected = ServerApiException.class)
|
||||
public void testExecuteThrowsException() throws Exception {
|
||||
DeleteDnsRecordCmd cmd = createCmd();
|
||||
when(dnsProviderManager.deleteDnsRecord(cmd)).thenThrow(new RuntimeException("Error"));
|
||||
cmd.execute();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,119 @@
|
|||
// 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.user.dns;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import org.apache.cloudstack.api.ServerApiException;
|
||||
import org.apache.cloudstack.api.response.SuccessResponse;
|
||||
import org.apache.cloudstack.dns.DnsServer;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.cloud.event.EventTypes;
|
||||
import com.cloud.user.Account;
|
||||
|
||||
public class DeleteDnsServerCmdTest extends BaseDnsCmdTest {
|
||||
|
||||
private DeleteDnsServerCmd createCmd() throws Exception {
|
||||
DeleteDnsServerCmd cmd = new DeleteDnsServerCmd();
|
||||
setField(cmd, "dnsProviderManager", dnsProviderManager);
|
||||
setField(cmd, "_entityMgr", entityManager);
|
||||
setField(cmd, "id", ENTITY_ID);
|
||||
return cmd;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetId() throws Exception {
|
||||
DeleteDnsServerCmd cmd = createCmd();
|
||||
assertEquals(Long.valueOf(ENTITY_ID), cmd.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetCleanupDefault() throws Exception {
|
||||
DeleteDnsServerCmd cmd = createCmd();
|
||||
assertTrue(cmd.getCleanup());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetCleanupFalse() throws Exception {
|
||||
DeleteDnsServerCmd cmd = createCmd();
|
||||
setField(cmd, "cleanup", false);
|
||||
assertFalse(cmd.getCleanup());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetEntityOwnerIdWithServer() throws Exception {
|
||||
DeleteDnsServerCmd cmd = createCmd();
|
||||
DnsServer mockServer = mock(DnsServer.class);
|
||||
when(mockServer.getAccountId()).thenReturn(ACCOUNT_ID);
|
||||
when(entityManager.findById(DnsServer.class, ENTITY_ID)).thenReturn(mockServer);
|
||||
|
||||
assertEquals(ACCOUNT_ID, cmd.getEntityOwnerId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetEntityOwnerIdServerNotFound() throws Exception {
|
||||
DeleteDnsServerCmd cmd = createCmd();
|
||||
when(entityManager.findById(DnsServer.class, ENTITY_ID)).thenReturn(null);
|
||||
|
||||
assertEquals(Account.ACCOUNT_ID_SYSTEM, cmd.getEntityOwnerId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEventType() throws Exception {
|
||||
DeleteDnsServerCmd cmd = createCmd();
|
||||
assertEquals(EventTypes.EVENT_DNS_SERVER_DELETE, cmd.getEventType());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEventDescription() throws Exception {
|
||||
DeleteDnsServerCmd cmd = createCmd();
|
||||
assertEquals("Deleting DNS server ID: " + ENTITY_ID, cmd.getEventDescription());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExecuteSuccess() throws Exception {
|
||||
DeleteDnsServerCmd cmd = createCmd();
|
||||
when(dnsProviderManager.deleteDnsServer(cmd)).thenReturn(true);
|
||||
|
||||
cmd.execute();
|
||||
|
||||
SuccessResponse response = (SuccessResponse) cmd.getResponseObject();
|
||||
assertNotNull(response);
|
||||
verify(dnsProviderManager).deleteDnsServer(cmd);
|
||||
}
|
||||
|
||||
@Test(expected = ServerApiException.class)
|
||||
public void testExecuteReturnsFalse() throws Exception {
|
||||
DeleteDnsServerCmd cmd = createCmd();
|
||||
when(dnsProviderManager.deleteDnsServer(cmd)).thenReturn(false);
|
||||
cmd.execute();
|
||||
}
|
||||
|
||||
@Test(expected = ServerApiException.class)
|
||||
public void testExecuteThrowsException() throws Exception {
|
||||
DeleteDnsServerCmd cmd = createCmd();
|
||||
when(dnsProviderManager.deleteDnsServer(cmd)).thenThrow(new RuntimeException("Error"));
|
||||
cmd.execute();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,104 @@
|
|||
// 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.user.dns;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import org.apache.cloudstack.api.ServerApiException;
|
||||
import org.apache.cloudstack.api.response.SuccessResponse;
|
||||
import org.apache.cloudstack.dns.DnsZone;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.cloud.event.EventTypes;
|
||||
import com.cloud.user.Account;
|
||||
|
||||
public class DeleteDnsZoneCmdTest extends BaseDnsCmdTest {
|
||||
|
||||
private DeleteDnsZoneCmd createCmd() throws Exception {
|
||||
DeleteDnsZoneCmd cmd = new DeleteDnsZoneCmd();
|
||||
setField(cmd, "dnsProviderManager", dnsProviderManager);
|
||||
setField(cmd, "_entityMgr", entityManager);
|
||||
setField(cmd, "id", ENTITY_ID);
|
||||
return cmd;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetId() throws Exception {
|
||||
DeleteDnsZoneCmd cmd = createCmd();
|
||||
assertEquals(Long.valueOf(ENTITY_ID), cmd.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetEntityOwnerIdWithZone() throws Exception {
|
||||
DeleteDnsZoneCmd cmd = createCmd();
|
||||
DnsZone mockZone = mock(DnsZone.class);
|
||||
when(mockZone.getAccountId()).thenReturn(ACCOUNT_ID);
|
||||
when(entityManager.findById(DnsZone.class, ENTITY_ID)).thenReturn(mockZone);
|
||||
|
||||
assertEquals(ACCOUNT_ID, cmd.getEntityOwnerId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetEntityOwnerIdZoneNotFound() throws Exception {
|
||||
DeleteDnsZoneCmd cmd = createCmd();
|
||||
when(entityManager.findById(DnsZone.class, ENTITY_ID)).thenReturn(null);
|
||||
|
||||
assertEquals(Account.ACCOUNT_ID_SYSTEM, cmd.getEntityOwnerId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEventType() throws Exception {
|
||||
DeleteDnsZoneCmd cmd = createCmd();
|
||||
assertEquals(EventTypes.EVENT_DNS_ZONE_DELETE, cmd.getEventType());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEventDescription() throws Exception {
|
||||
DeleteDnsZoneCmd cmd = createCmd();
|
||||
assertEquals("Deleting DNS Zone ID: " + ENTITY_ID, cmd.getEventDescription());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExecuteSuccess() throws Exception {
|
||||
DeleteDnsZoneCmd cmd = createCmd();
|
||||
when(dnsProviderManager.deleteDnsZone(ENTITY_ID, false)).thenReturn(true);
|
||||
|
||||
cmd.execute();
|
||||
|
||||
SuccessResponse response = (SuccessResponse) cmd.getResponseObject();
|
||||
assertNotNull(response);
|
||||
verify(dnsProviderManager).deleteDnsZone(ENTITY_ID, false);
|
||||
}
|
||||
|
||||
@Test(expected = ServerApiException.class)
|
||||
public void testExecuteReturnsFalse() throws Exception {
|
||||
DeleteDnsZoneCmd cmd = createCmd();
|
||||
when(dnsProviderManager.deleteDnsZone(ENTITY_ID, false)).thenReturn(false);
|
||||
cmd.execute();
|
||||
}
|
||||
|
||||
@Test(expected = ServerApiException.class)
|
||||
public void testExecuteThrowsException() throws Exception {
|
||||
DeleteDnsZoneCmd cmd = createCmd();
|
||||
when(dnsProviderManager.deleteDnsZone(ENTITY_ID, false)).thenThrow(new RuntimeException("Error"));
|
||||
cmd.execute();
|
||||
}
|
||||
}
|
||||
|
|
@ -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 org.apache.cloudstack.api.command.user.dns;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import org.apache.cloudstack.api.ServerApiException;
|
||||
import org.apache.cloudstack.api.response.SuccessResponse;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.cloud.network.Network;
|
||||
import com.cloud.user.Account;
|
||||
|
||||
public class DisassociateDnsZoneFromNetworkCmdTest extends BaseDnsCmdTest {
|
||||
|
||||
private static final long NETWORK_ID = 200L;
|
||||
|
||||
private DisassociateDnsZoneFromNetworkCmd createCmd() throws Exception {
|
||||
DisassociateDnsZoneFromNetworkCmd cmd =
|
||||
new DisassociateDnsZoneFromNetworkCmd();
|
||||
setField(cmd, "dnsProviderManager", dnsProviderManager);
|
||||
setField(cmd, "_entityMgr", entityManager);
|
||||
setField(cmd, "networkId", NETWORK_ID);
|
||||
return cmd;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetNetworkId() throws Exception {
|
||||
DisassociateDnsZoneFromNetworkCmd cmd = createCmd();
|
||||
assertEquals(Long.valueOf(NETWORK_ID), cmd.getNetworkId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetEntityOwnerIdWithNetwork() throws Exception {
|
||||
DisassociateDnsZoneFromNetworkCmd cmd = createCmd();
|
||||
Network mockNetwork = mock(Network.class);
|
||||
when(mockNetwork.getAccountId()).thenReturn(ACCOUNT_ID);
|
||||
when(entityManager.findById(Network.class, NETWORK_ID))
|
||||
.thenReturn(mockNetwork);
|
||||
|
||||
assertEquals(ACCOUNT_ID, cmd.getEntityOwnerId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetEntityOwnerIdNetworkNotFound() throws Exception {
|
||||
DisassociateDnsZoneFromNetworkCmd cmd = createCmd();
|
||||
when(entityManager.findById(Network.class, NETWORK_ID))
|
||||
.thenReturn(null);
|
||||
|
||||
assertEquals(Account.ACCOUNT_ID_SYSTEM, cmd.getEntityOwnerId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExecuteSuccess() throws Exception {
|
||||
DisassociateDnsZoneFromNetworkCmd cmd = createCmd();
|
||||
when(dnsProviderManager.disassociateZoneFromNetwork(cmd))
|
||||
.thenReturn(true);
|
||||
|
||||
cmd.execute();
|
||||
|
||||
SuccessResponse response =
|
||||
(SuccessResponse) cmd.getResponseObject();
|
||||
assertNotNull(response);
|
||||
verify(dnsProviderManager).disassociateZoneFromNetwork(cmd);
|
||||
}
|
||||
|
||||
@Test(expected = ServerApiException.class)
|
||||
public void testExecuteReturnsFalse() throws Exception {
|
||||
DisassociateDnsZoneFromNetworkCmd cmd = createCmd();
|
||||
when(dnsProviderManager.disassociateZoneFromNetwork(cmd))
|
||||
.thenReturn(false);
|
||||
cmd.execute();
|
||||
}
|
||||
|
||||
@Test(expected = ServerApiException.class)
|
||||
public void testExecuteThrowsException() throws Exception {
|
||||
DisassociateDnsZoneFromNetworkCmd cmd = createCmd();
|
||||
when(dnsProviderManager.disassociateZoneFromNetwork(cmd))
|
||||
.thenThrow(new RuntimeException("Error"));
|
||||
cmd.execute();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
// 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.user.dns;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.apache.cloudstack.api.response.DnsProviderResponse;
|
||||
import org.apache.cloudstack.api.response.ListResponse;
|
||||
import org.junit.Test;
|
||||
|
||||
public class ListDnsProvidersCmdTest extends BaseDnsCmdTest {
|
||||
|
||||
private ListDnsProvidersCmd createCmd() throws Exception {
|
||||
ListDnsProvidersCmd cmd = new ListDnsProvidersCmd();
|
||||
setField(cmd, "dnsProviderManager", dnsProviderManager);
|
||||
return cmd;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExecute() throws Exception {
|
||||
ListDnsProvidersCmd cmd = createCmd();
|
||||
when(dnsProviderManager.listProviderNames()).thenReturn(Arrays.asList("PowerDNS"));
|
||||
|
||||
cmd.execute();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
ListResponse<DnsProviderResponse> response =
|
||||
(ListResponse<DnsProviderResponse>) cmd.getResponseObject();
|
||||
assertNotNull(response);
|
||||
assertEquals("listdnsprovidersresponse", response.getResponseName());
|
||||
assertNotNull(response.getResponses());
|
||||
assertEquals(1, response.getResponses().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExecuteMultipleProviders() throws Exception {
|
||||
ListDnsProvidersCmd cmd = createCmd();
|
||||
when(dnsProviderManager.listProviderNames())
|
||||
.thenReturn(Arrays.asList("PowerDNS", "Cloudflare"));
|
||||
|
||||
cmd.execute();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
ListResponse<DnsProviderResponse> response =
|
||||
(ListResponse<DnsProviderResponse>) cmd.getResponseObject();
|
||||
assertNotNull(response);
|
||||
assertEquals(2, response.getResponses().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExecuteEmptyList() throws Exception {
|
||||
ListDnsProvidersCmd cmd = createCmd();
|
||||
when(dnsProviderManager.listProviderNames())
|
||||
.thenReturn(Collections.emptyList());
|
||||
|
||||
cmd.execute();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
ListResponse<DnsProviderResponse> response =
|
||||
(ListResponse<DnsProviderResponse>) cmd.getResponseObject();
|
||||
assertNotNull(response);
|
||||
assertEquals(0, response.getResponses().size());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
// 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.user.dns;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import org.apache.cloudstack.api.response.DnsRecordResponse;
|
||||
import org.apache.cloudstack.api.response.ListResponse;
|
||||
import org.junit.Test;
|
||||
|
||||
public class ListDnsRecordsCmdTest extends BaseDnsCmdTest {
|
||||
|
||||
private ListDnsRecordsCmd createCmd() throws Exception {
|
||||
ListDnsRecordsCmd cmd = new ListDnsRecordsCmd();
|
||||
setField(cmd, "dnsProviderManager", dnsProviderManager);
|
||||
setField(cmd, "dnsZoneId", ENTITY_ID);
|
||||
return cmd;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetDnsZoneId() throws Exception {
|
||||
ListDnsRecordsCmd cmd = createCmd();
|
||||
assertEquals(Long.valueOf(ENTITY_ID), cmd.getDnsZoneId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExecute() throws Exception {
|
||||
ListDnsRecordsCmd cmd = createCmd();
|
||||
|
||||
ListResponse<DnsRecordResponse> mockListResponse = new ListResponse<>();
|
||||
when(dnsProviderManager.listDnsRecords(cmd)).thenReturn(mockListResponse);
|
||||
|
||||
cmd.execute();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
ListResponse<DnsRecordResponse> response = (ListResponse<DnsRecordResponse>) cmd.getResponseObject();
|
||||
assertNotNull(response);
|
||||
assertEquals("listdnsrecordsresponse", response.getResponseName());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
// 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.user.dns;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import org.apache.cloudstack.api.response.DnsServerResponse;
|
||||
import org.apache.cloudstack.api.response.ListResponse;
|
||||
import org.apache.cloudstack.dns.DnsProviderType;
|
||||
import org.junit.Test;
|
||||
|
||||
public class ListDnsServersCmdTest extends BaseDnsCmdTest {
|
||||
|
||||
private ListDnsServersCmd createCmd() throws Exception {
|
||||
ListDnsServersCmd cmd = new ListDnsServersCmd();
|
||||
setField(cmd, "dnsProviderManager", dnsProviderManager);
|
||||
setField(cmd, "id", ENTITY_ID);
|
||||
setField(cmd, "providerType", "PowerDNS");
|
||||
return cmd;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAccessors() throws Exception {
|
||||
ListDnsServersCmd cmd = createCmd();
|
||||
assertEquals(Long.valueOf(ENTITY_ID), cmd.getId());
|
||||
assertEquals(DnsProviderType.PowerDNS, cmd.getProviderType());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetProviderTypeNull() throws Exception {
|
||||
ListDnsServersCmd cmd = createCmd();
|
||||
setField(cmd, "providerType", null);
|
||||
assertEquals(DnsProviderType.PowerDNS, cmd.getProviderType());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExecute() throws Exception {
|
||||
ListDnsServersCmd cmd = createCmd();
|
||||
|
||||
ListResponse<DnsServerResponse> mockListResponse = new ListResponse<>();
|
||||
when(dnsProviderManager.listDnsServers(cmd)).thenReturn(mockListResponse);
|
||||
|
||||
cmd.execute();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
ListResponse<DnsServerResponse> response = (ListResponse<DnsServerResponse>) cmd.getResponseObject();
|
||||
assertNotNull(response);
|
||||
assertEquals("listdnsserversresponse", response.getResponseName());
|
||||
assertEquals("dnsserver", response.getObjectName());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
// 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.user.dns;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import org.apache.cloudstack.api.response.DnsZoneResponse;
|
||||
import org.apache.cloudstack.api.response.ListResponse;
|
||||
import org.junit.Test;
|
||||
|
||||
public class ListDnsZonesCmdTest extends BaseDnsCmdTest {
|
||||
|
||||
private ListDnsZonesCmd createCmd() throws Exception {
|
||||
ListDnsZonesCmd cmd = new ListDnsZonesCmd();
|
||||
setField(cmd, "dnsProviderManager", dnsProviderManager);
|
||||
setField(cmd, "id", ENTITY_ID);
|
||||
setField(cmd, "dnsServerId", 200L);
|
||||
setField(cmd, "name", "example.com");
|
||||
return cmd;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAccessors() throws Exception {
|
||||
ListDnsZonesCmd cmd = createCmd();
|
||||
assertEquals(Long.valueOf(ENTITY_ID), cmd.getId());
|
||||
assertEquals(Long.valueOf(200L), cmd.getDnsServerId());
|
||||
assertEquals("example.com", cmd.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExecute() throws Exception {
|
||||
ListDnsZonesCmd cmd = createCmd();
|
||||
|
||||
ListResponse<DnsZoneResponse> mockListResponse = new ListResponse<>();
|
||||
when(dnsProviderManager.listDnsZones(cmd)).thenReturn(mockListResponse);
|
||||
|
||||
cmd.execute();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
ListResponse<DnsZoneResponse> response = (ListResponse<DnsZoneResponse>) cmd.getResponseObject();
|
||||
assertNotNull(response);
|
||||
assertEquals("listdnszonesresponse", response.getResponseName());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,145 @@
|
|||
// 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.user.dns;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.apache.cloudstack.api.ServerApiException;
|
||||
import org.apache.cloudstack.api.response.DnsServerResponse;
|
||||
import org.apache.cloudstack.dns.DnsServer;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.cloud.user.Account;
|
||||
|
||||
public class UpdateDnsServerCmdTest extends BaseDnsCmdTest {
|
||||
|
||||
private UpdateDnsServerCmd createCmd() throws Exception {
|
||||
UpdateDnsServerCmd cmd = new UpdateDnsServerCmd();
|
||||
setField(cmd, "dnsProviderManager", dnsProviderManager);
|
||||
setField(cmd, "_entityMgr", entityManager);
|
||||
setField(cmd, "id", ENTITY_ID);
|
||||
setField(cmd, "name", "updated-dns");
|
||||
setField(cmd, "url", "http://updated.dns.com");
|
||||
setField(cmd, "dnsApiKey", "new-api-key");
|
||||
setField(cmd, "port", 9090);
|
||||
setField(cmd, "isPublic", true);
|
||||
setField(cmd, "publicDomainSuffix", "updated.example.com");
|
||||
setField(cmd, "nameServers", Arrays.asList("ns1.updated.com", "ns2.updated.com"));
|
||||
setField(cmd, "state", "Enabled");
|
||||
return cmd;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAccessors() throws Exception {
|
||||
UpdateDnsServerCmd cmd = createCmd();
|
||||
|
||||
assertEquals(Long.valueOf(ENTITY_ID), cmd.getId());
|
||||
assertEquals("updated-dns", cmd.getName());
|
||||
assertEquals("http://updated.dns.com", cmd.getUrl());
|
||||
assertEquals("new-api-key", cmd.getDnsApiKey());
|
||||
assertEquals(Integer.valueOf(9090), cmd.getPort());
|
||||
assertTrue(cmd.isPublic());
|
||||
assertEquals("updated.example.com", cmd.getPublicDomainSuffix());
|
||||
assertEquals("ns1.updated.com,ns2.updated.com", cmd.getNameServers());
|
||||
assertEquals(DnsServer.State.Enabled, cmd.getState());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetStateDisabled() throws Exception {
|
||||
UpdateDnsServerCmd cmd = createCmd();
|
||||
setField(cmd, "state", "Disabled");
|
||||
assertEquals(DnsServer.State.Disabled, cmd.getState());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetStateNull() throws Exception {
|
||||
UpdateDnsServerCmd cmd = createCmd();
|
||||
setField(cmd, "state", null);
|
||||
assertNull(cmd.getState());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetStateBlank() throws Exception {
|
||||
UpdateDnsServerCmd cmd = createCmd();
|
||||
setField(cmd, "state", "");
|
||||
assertNull(cmd.getState());
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testGetStateInvalid() throws Exception {
|
||||
UpdateDnsServerCmd cmd = createCmd();
|
||||
setField(cmd, "state", "InvalidState");
|
||||
cmd.getState();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetEntityOwnerIdWithServer() throws Exception {
|
||||
UpdateDnsServerCmd cmd = createCmd();
|
||||
DnsServer mockServer = mock(DnsServer.class);
|
||||
when(mockServer.getAccountId()).thenReturn(ACCOUNT_ID);
|
||||
when(entityManager.findById(DnsServer.class, ENTITY_ID)).thenReturn(mockServer);
|
||||
|
||||
assertEquals(ACCOUNT_ID, cmd.getEntityOwnerId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetEntityOwnerIdServerNotFound() throws Exception {
|
||||
UpdateDnsServerCmd cmd = createCmd();
|
||||
when(entityManager.findById(DnsServer.class, ENTITY_ID)).thenReturn(null);
|
||||
|
||||
assertEquals(Account.ACCOUNT_ID_SYSTEM, cmd.getEntityOwnerId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExecuteSuccess() throws Exception {
|
||||
UpdateDnsServerCmd cmd = createCmd();
|
||||
|
||||
DnsServer mockServer = mock(DnsServer.class);
|
||||
DnsServerResponse mockResponse = new DnsServerResponse();
|
||||
mockResponse.setName("updated-dns");
|
||||
|
||||
when(dnsProviderManager.updateDnsServer(cmd)).thenReturn(mockServer);
|
||||
when(dnsProviderManager.createDnsServerResponse(mockServer)).thenReturn(mockResponse);
|
||||
|
||||
cmd.execute();
|
||||
|
||||
DnsServerResponse response = (DnsServerResponse) cmd.getResponseObject();
|
||||
assertNotNull(response);
|
||||
assertEquals("updatednsserverresponse", response.getResponseName());
|
||||
}
|
||||
|
||||
@Test(expected = ServerApiException.class)
|
||||
public void testExecuteReturnsNull() throws Exception {
|
||||
UpdateDnsServerCmd cmd = createCmd();
|
||||
when(dnsProviderManager.updateDnsServer(cmd)).thenReturn(null);
|
||||
cmd.execute();
|
||||
}
|
||||
|
||||
@Test(expected = ServerApiException.class)
|
||||
public void testExecuteThrowsException() throws Exception {
|
||||
UpdateDnsServerCmd cmd = createCmd();
|
||||
when(dnsProviderManager.updateDnsServer(cmd)).thenThrow(new RuntimeException("Update failed"));
|
||||
cmd.execute();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,96 @@
|
|||
// 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.user.dns;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import org.apache.cloudstack.api.ServerApiException;
|
||||
import org.apache.cloudstack.api.response.DnsZoneResponse;
|
||||
import org.apache.cloudstack.dns.DnsZone;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.cloud.user.Account;
|
||||
|
||||
public class UpdateDnsZoneCmdTest extends BaseDnsCmdTest {
|
||||
|
||||
private UpdateDnsZoneCmd createCmd() throws Exception {
|
||||
UpdateDnsZoneCmd cmd = new UpdateDnsZoneCmd();
|
||||
setField(cmd, "dnsProviderManager", dnsProviderManager);
|
||||
setField(cmd, "_entityMgr", entityManager);
|
||||
setField(cmd, "id", ENTITY_ID);
|
||||
setField(cmd, "description", "Updated description");
|
||||
return cmd;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAccessors() throws Exception {
|
||||
UpdateDnsZoneCmd cmd = createCmd();
|
||||
assertEquals(Long.valueOf(ENTITY_ID), cmd.getId());
|
||||
assertEquals("Updated description", cmd.getDescription());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetEntityOwnerIdWhenZoneExists() throws Exception {
|
||||
UpdateDnsZoneCmd cmd = createCmd();
|
||||
DnsZone mockZone = mock(DnsZone.class);
|
||||
when(mockZone.getAccountId()).thenReturn(ACCOUNT_ID);
|
||||
when(entityManager.findById(DnsZone.class, ENTITY_ID)).thenReturn(mockZone);
|
||||
assertEquals(ACCOUNT_ID, cmd.getEntityOwnerId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetEntityOwnerIdWhenZoneNotFound() throws Exception {
|
||||
UpdateDnsZoneCmd cmd = createCmd();
|
||||
when(entityManager.findById(DnsZone.class, ENTITY_ID)).thenReturn(null);
|
||||
assertEquals(Account.ACCOUNT_ID_SYSTEM, cmd.getEntityOwnerId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExecuteSuccess() throws Exception {
|
||||
UpdateDnsZoneCmd cmd = createCmd();
|
||||
|
||||
DnsZone mockZone = mock(DnsZone.class);
|
||||
DnsZoneResponse mockResponse = new DnsZoneResponse();
|
||||
mockResponse.setName("example.com");
|
||||
|
||||
when(dnsProviderManager.updateDnsZone(cmd)).thenReturn(mockZone);
|
||||
when(dnsProviderManager.createDnsZoneResponse(mockZone)).thenReturn(mockResponse);
|
||||
|
||||
cmd.execute();
|
||||
|
||||
DnsZoneResponse response = (DnsZoneResponse) cmd.getResponseObject();
|
||||
assertNotNull(response);
|
||||
assertEquals("updatednszoneresponse", response.getResponseName());
|
||||
}
|
||||
|
||||
@Test(expected = ServerApiException.class)
|
||||
public void testExecuteReturnsNull() throws Exception {
|
||||
UpdateDnsZoneCmd cmd = createCmd();
|
||||
when(dnsProviderManager.updateDnsZone(cmd)).thenReturn(null);
|
||||
cmd.execute();
|
||||
}
|
||||
|
||||
@Test(expected = ServerApiException.class)
|
||||
public void testExecuteThrowsException() throws Exception {
|
||||
UpdateDnsZoneCmd cmd = createCmd();
|
||||
when(dnsProviderManager.updateDnsZone(cmd)).thenThrow(new RuntimeException("Update failed"));
|
||||
cmd.execute();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,105 @@
|
|||
// 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.dns;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
|
||||
public class DnsRecordTest {
|
||||
|
||||
@Test
|
||||
public void testDefaultConstructor() {
|
||||
DnsRecord record = new DnsRecord();
|
||||
assertNull(record.getName());
|
||||
assertNull(record.getType());
|
||||
assertNull(record.getContents());
|
||||
assertEquals(0, record.getTtl());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParameterizedConstructor() {
|
||||
List<String> contents = Arrays.asList("192.168.1.1");
|
||||
DnsRecord record = new DnsRecord("www", DnsRecord.RecordType.A, contents, 3600);
|
||||
|
||||
assertEquals("www", record.getName());
|
||||
assertEquals(DnsRecord.RecordType.A, record.getType());
|
||||
assertEquals(contents, record.getContents());
|
||||
assertEquals(3600, record.getTtl());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSettersAndGetters() {
|
||||
DnsRecord record = new DnsRecord();
|
||||
List<String> contents = Arrays.asList("10.0.0.1", "10.0.0.2");
|
||||
|
||||
record.setName("mail");
|
||||
record.setType(DnsRecord.RecordType.AAAA);
|
||||
record.setContents(contents);
|
||||
record.setTtl(7200);
|
||||
|
||||
assertEquals("mail", record.getName());
|
||||
assertEquals(DnsRecord.RecordType.AAAA, record.getType());
|
||||
assertEquals(contents, record.getContents());
|
||||
assertEquals(7200, record.getTtl());
|
||||
}
|
||||
|
||||
// RecordType.fromString tests
|
||||
|
||||
@Test
|
||||
public void testFromStringValid() {
|
||||
assertEquals(DnsRecord.RecordType.A, DnsRecord.RecordType.fromString("A"));
|
||||
assertEquals(DnsRecord.RecordType.AAAA, DnsRecord.RecordType.fromString("AAAA"));
|
||||
assertEquals(DnsRecord.RecordType.CNAME, DnsRecord.RecordType.fromString("CNAME"));
|
||||
assertEquals(DnsRecord.RecordType.MX, DnsRecord.RecordType.fromString("MX"));
|
||||
assertEquals(DnsRecord.RecordType.TXT, DnsRecord.RecordType.fromString("TXT"));
|
||||
assertEquals(DnsRecord.RecordType.SRV, DnsRecord.RecordType.fromString("SRV"));
|
||||
assertEquals(DnsRecord.RecordType.PTR, DnsRecord.RecordType.fromString("PTR"));
|
||||
assertEquals(DnsRecord.RecordType.NS, DnsRecord.RecordType.fromString("NS"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFromStringCaseInsensitive() {
|
||||
assertEquals(DnsRecord.RecordType.A, DnsRecord.RecordType.fromString("a"));
|
||||
assertEquals(DnsRecord.RecordType.CNAME, DnsRecord.RecordType.fromString("cname"));
|
||||
assertEquals(DnsRecord.RecordType.MX, DnsRecord.RecordType.fromString("mx"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFromStringNull() {
|
||||
assertNull(DnsRecord.RecordType.fromString(null));
|
||||
}
|
||||
|
||||
@Test(expected = CloudRuntimeException.class)
|
||||
public void testFromStringInvalid() {
|
||||
DnsRecord.RecordType.fromString("INVALID");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRecordTypeValues() {
|
||||
DnsRecord.RecordType[] values = DnsRecord.RecordType.values();
|
||||
assertNotNull(values);
|
||||
assertEquals(8, values.length);
|
||||
}
|
||||
}
|
||||
|
|
@ -662,6 +662,12 @@
|
|||
<artifactId>cloud-utils</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.cloudstack</groupId>
|
||||
<artifactId>cloud-plugin-dns-powerdns</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
|
|
|
|||
|
|
@ -366,4 +366,6 @@
|
|||
|
||||
<bean id="sharedFSProvidersRegistry" class="org.apache.cloudstack.spring.lifecycle.registry.ExtensionRegistry">
|
||||
</bean>
|
||||
|
||||
<bean id="dnsProvidersRegistry" class="org.apache.cloudstack.spring.lifecycle.registry.ExtensionRegistry" />
|
||||
</beans>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,21 @@
|
|||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
name=dns
|
||||
parent=core
|
||||
|
|
@ -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.
|
||||
|
||||
-->
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"
|
||||
>
|
||||
<bean class="org.apache.cloudstack.spring.lifecycle.registry.RegistryLifecycle">
|
||||
<property name="registry" ref="dnsProvidersRegistry" />
|
||||
<property name="typeClass" value="org.apache.cloudstack.dns.DnsProvider" />
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
|
|
@ -112,6 +112,8 @@ public interface VirtualMachineManager extends Manager {
|
|||
|
||||
interface Topics {
|
||||
String VM_POWER_STATE = "vm.powerstate";
|
||||
String VM_LIFECYCLE_STATE = "vm.lifecycle.state";
|
||||
String VM_ACTION = "vm.action";
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -16,10 +16,14 @@
|
|||
// under the License.
|
||||
package com.cloud.vm.dao;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.cloudstack.resourcedetail.ResourceDetailsDao;
|
||||
|
||||
import com.cloud.utils.db.GenericDao;
|
||||
import com.cloud.vm.NicDetailVO;
|
||||
|
||||
public interface NicDetailsDao extends GenericDao<NicDetailVO, Long>, ResourceDetailsDao<NicDetailVO> {
|
||||
|
||||
void removeDetailsForNicIds(String resourceName, Set<Long> nicIds);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,17 +17,43 @@
|
|||
package com.cloud.vm.dao;
|
||||
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.resourcedetail.ResourceDetailsDaoBase;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import org.apache.cloudstack.resourcedetail.ResourceDetailsDaoBase;
|
||||
|
||||
import com.cloud.utils.db.SearchBuilder;
|
||||
import com.cloud.utils.db.SearchCriteria;
|
||||
import com.cloud.vm.NicDetailVO;
|
||||
|
||||
@Component
|
||||
public class NicDetailsDaoImpl extends ResourceDetailsDaoBase<NicDetailVO> implements NicDetailsDao {
|
||||
private final SearchBuilder<NicDetailVO> ResourceIdNameSearch;
|
||||
|
||||
public NicDetailsDaoImpl() {
|
||||
super();
|
||||
ResourceIdNameSearch = createSearchBuilder();
|
||||
ResourceIdNameSearch.and(ApiConstants.NAME, ResourceIdNameSearch.entity().getName(), SearchCriteria.Op.EQ);
|
||||
ResourceIdNameSearch.and(ApiConstants.RESOURCE_ID, ResourceIdNameSearch.entity().getResourceId(), SearchCriteria.Op.IN);
|
||||
ResourceIdNameSearch.done();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void addDetail(long resourceId, String key, String value, boolean display) {
|
||||
super.addDetail(new NicDetailVO(resourceId, key, value, display));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeDetailsForNicIds(String resourceName, Set<Long> nicIds) {
|
||||
if (CollectionUtils.isEmpty(nicIds)) {
|
||||
return;
|
||||
}
|
||||
SearchCriteria<NicDetailVO> sc = ResourceIdNameSearch.create();
|
||||
sc.setParameters(ApiConstants.NAME, resourceName);
|
||||
sc.setParameters(ApiConstants.RESOURCE_ID, nicIds.toArray());
|
||||
remove(sc);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -310,4 +310,12 @@
|
|||
<bean id="importVMTaskDaoImpl" class="com.cloud.vm.dao.ImportVMTaskDaoImpl" />
|
||||
<bean id="apiKeyPairDaoImpl" class="org.apache.cloudstack.acl.dao.ApiKeyPairDaoImpl" />
|
||||
<bean id="apiKeyPairPermissionsDaoImpl" class="org.apache.cloudstack.acl.dao.ApiKeyPairPermissionsDaoImpl" />
|
||||
<bean id="dnsServerDao" class="org.apache.cloudstack.dns.dao.DnsServerDaoImpl" />
|
||||
<bean id="dnsZoneDao" class="org.apache.cloudstack.dns.dao.DnsZoneDaoImpl" />
|
||||
<bean id="dnsZoneNetworkMapDao" class="org.apache.cloudstack.dns.dao.DnsZoneNetworkMapDaoImpl" />
|
||||
<bean id="dnsServerJoinDao" class="org.apache.cloudstack.dns.dao.DnsServerJoinDaoImpl" />
|
||||
<bean id="dnsZoneJoinDao" class="org.apache.cloudstack.dns.dao.DnsZoneJoinDaoImpl" />
|
||||
<bean id="dnsNicJoinDao" class="org.apache.cloudstack.dns.dao.NicDnsJoinDaoImpl" />
|
||||
<bean id="dnsServerDetailsDao" class="org.apache.cloudstack.dns.dao.DnsServerDetailsDaoImpl" />
|
||||
|
||||
</beans>
|
||||
|
|
|
|||
|
|
@ -131,3 +131,81 @@ CREATE TABLE IF NOT EXISTS `cloud_usage`.`quota_tariff_usage` (
|
|||
-- Add the 'keep_mac_address_on_public_nic' column to the 'cloud.networks' and 'cloud.vpc' tables
|
||||
CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.networks', 'keep_mac_address_on_public_nic', 'TINYINT(1) NOT NULL DEFAULT 1');
|
||||
CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.vpc', 'keep_mac_address_on_public_nic', 'TINYINT(1) NOT NULL DEFAULT 1');
|
||||
|
||||
-- ======================================================================
|
||||
-- DNS Framework Schema
|
||||
-- ======================================================================
|
||||
|
||||
-- DNS Server Table (Stores DNS Server Configurations)
|
||||
CREATE TABLE IF NOT EXISTS `cloud`.`dns_server` (
|
||||
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'id 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',
|
||||
`dns_username` varchar(255) COMMENT 'username or email for dns server credentials',
|
||||
`dns_api_key` varchar(255) NOT NULL COMMENT 'api key or token for the dns server ',
|
||||
`port` int(11) DEFAULT NULL COMMENT 'optional dns server port',
|
||||
`name_servers` varchar(1024) DEFAULT NULL COMMENT 'Comma separated list of name servers',
|
||||
`is_public` tinyint(1) NOT NULL DEFAULT '0',
|
||||
`public_domain_suffix` VARCHAR(255),
|
||||
`state` ENUM('Enabled', 'Disabled') NOT NULL DEFAULT 'Disabled',
|
||||
`domain_id` bigint unsigned COMMENT 'for domain-specific ownership',
|
||||
`account_id` bigint(20) unsigned NOT NULL,
|
||||
`created` datetime NOT NULL COMMENT 'date created',
|
||||
`removed` datetime DEFAULT NULL COMMENT 'Date removed (soft delete)',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `i_dns_server__account_id` (`account_id`),
|
||||
CONSTRAINT `fk_dns_server__account_id` FOREIGN KEY (`account_id`) REFERENCES `account` (`id`) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
-- DNS Server Details Table
|
||||
CREATE TABLE IF NOT EXISTS `cloud`.`dns_server_details` (
|
||||
`id` bigint unsigned UNIQUE NOT NULL AUTO_INCREMENT COMMENT 'id',
|
||||
`dns_server_id` bigint unsigned NOT NULL COMMENT 'dns_server the detail is related to',
|
||||
`name` varchar(255) NOT NULL COMMENT 'name of the detail',
|
||||
`value` varchar(255) NOT NULL COMMENT 'value of the detail',
|
||||
`display` tinyint(1) NOT NULL DEFAULT 1 COMMENT 'Should detail be displayed to the end user',
|
||||
PRIMARY KEY (`id`),
|
||||
CONSTRAINT `fk_dns_server_details__dns_server_id` FOREIGN KEY (`dns_server_id`) REFERENCES `dns_server`(`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
-- DNS Zone Table (Stores DNS Zone Metadata)
|
||||
CREATE TABLE IF NOT EXISTS `cloud`.`dns_zone` (
|
||||
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'id 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`),
|
||||
KEY `i_dns_zone__dns_server` (`dns_server_id`),
|
||||
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;
|
||||
|
||||
-- DNS Zone Network Map (One-to-Many Link)
|
||||
CREATE TABLE IF NOT EXISTS `cloud`.`dns_zone_network_map` (
|
||||
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'id of the dns zone to network mapping',
|
||||
`uuid` varchar(40),
|
||||
`dns_zone_id` bigint(20) unsigned NOT NULL,
|
||||
`network_id` bigint(20) unsigned NOT NULL COMMENT 'network to which dns zone is associated to',
|
||||
`sub_domain` varchar(255) DEFAULT NULL COMMENT 'Subdomain for auto-registration',
|
||||
`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`),
|
||||
KEY `fk_dns_map__zone_id` (`dns_zone_id`),
|
||||
KEY `fk_dns_map__network_id` (`network_id`),
|
||||
CONSTRAINT `fk_dns_map__zone_id` FOREIGN KEY (`dns_zone_id`) REFERENCES `dns_zone` (`id`) ON DELETE CASCADE,
|
||||
CONSTRAINT `fk_dns_map__network_id` FOREIGN KEY (`network_id`) REFERENCES `networks` (`id`) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,44 @@
|
|||
-- 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.
|
||||
|
||||
-- VIEW `cloud`.`dns_server_view`;
|
||||
|
||||
DROP VIEW IF EXISTS `cloud`.`dns_server_view`;
|
||||
CREATE VIEW `cloud`.`dns_server_view` AS
|
||||
SELECT
|
||||
dns.id,
|
||||
dns.uuid,
|
||||
dns.name,
|
||||
dns.provider_type,
|
||||
dns.url,
|
||||
dns.port,
|
||||
dns.name_servers,
|
||||
dns.is_public,
|
||||
dns.public_domain_suffix,
|
||||
dns.state,
|
||||
dns.created,
|
||||
dns.removed,
|
||||
account.account_name account_name,
|
||||
domain.name domain_name,
|
||||
domain.uuid domain_uuid,
|
||||
domain.path domain_path
|
||||
FROM
|
||||
`cloud`.`dns_server` dns
|
||||
INNER JOIN
|
||||
`cloud`.`account` account ON dns.account_id = account.id
|
||||
INNER JOIN
|
||||
`cloud`.`domain` domain ON dns.domain_id = domain.id;
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
-- 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.
|
||||
|
||||
-- VIEW `cloud`.`dns_zone_view`;
|
||||
|
||||
DROP VIEW IF EXISTS `cloud`.`dns_zone_view`;
|
||||
CREATE VIEW `cloud`.`dns_zone_view` AS
|
||||
SELECT
|
||||
zone.id,
|
||||
zone.uuid,
|
||||
zone.name,
|
||||
zone.dns_server_id,
|
||||
zone.state,
|
||||
zone.description,
|
||||
server.uuid dns_server_uuid,
|
||||
server.name dns_server_name,
|
||||
server_account.account_name dns_server_account_name,
|
||||
account.account_name account_name,
|
||||
domain.name domain_name,
|
||||
domain.uuid domain_uuid,
|
||||
domain.path domain_path
|
||||
FROM
|
||||
`cloud`.`dns_zone` zone
|
||||
INNER JOIN
|
||||
`cloud`.`dns_server` server ON zone.dns_server_id = server.id
|
||||
INNER JOIN
|
||||
`cloud`.`account` server_account ON server.account_id = server_account.id
|
||||
INNER JOIN
|
||||
`cloud`.`account` account ON zone.account_id = account.id
|
||||
INNER JOIN
|
||||
`cloud`.`domain` domain ON zone.domain_id = domain.id;
|
||||
|
|
@ -143,6 +143,7 @@ SELECT
|
|||
`nics`.`broadcast_uri` AS `broadcast_uri`,
|
||||
`nics`.`isolation_uri` AS `isolation_uri`,
|
||||
`nics`.`enabled` AS `is_nic_enabled`,
|
||||
`nic_details`.`value` AS `nic_dns_name`,
|
||||
`vpc`.`id` AS `vpc_id`,
|
||||
`vpc`.`uuid` AS `vpc_uuid`,
|
||||
`networks`.`uuid` AS `network_uuid`,
|
||||
|
|
@ -187,7 +188,7 @@ SELECT
|
|||
`lease_expiry_action`.`value` AS `lease_expiry_action`,
|
||||
`lease_action_execution`.`value` AS `lease_action_execution`
|
||||
FROM
|
||||
(((((((((((((((((((((((((((((((((((((`user_vm`
|
||||
((((((((((((((((((((((((((((((((((((((`user_vm`
|
||||
JOIN `vm_instance` ON (((`vm_instance`.`id` = `user_vm`.`id`)
|
||||
AND ISNULL(`vm_instance`.`removed`))))
|
||||
JOIN `account` ON ((`vm_instance`.`account_id` = `account`.`id`)))
|
||||
|
|
@ -214,6 +215,7 @@ FROM
|
|||
LEFT JOIN `user_data` ON ((`user_data`.`id` = `user_vm`.`user_data_id`)))
|
||||
LEFT JOIN `nics` ON (((`vm_instance`.`id` = `nics`.`instance_id`)
|
||||
AND ISNULL(`nics`.`removed`))))
|
||||
LEFT JOIN `nic_details` ON ((`nic_details`.`nic_id` = `nics`.`id`) AND (`nic_details`.`name` = 'nicdnsname')))
|
||||
LEFT JOIN `networks` ON ((`nics`.`network_id` = `networks`.`id`)))
|
||||
LEFT JOIN `vpc` ON (((`networks`.`vpc_id` = `vpc`.`id`)
|
||||
AND ISNULL(`vpc`.`removed`))))
|
||||
|
|
|
|||
|
|
@ -0,0 +1,40 @@
|
|||
-- 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.
|
||||
|
||||
-- VIEW `cloud`.`nic_dns_view`;
|
||||
|
||||
DROP VIEW IF EXISTS `cloud`.`nic_dns_view`;
|
||||
CREATE VIEW `cloud`.`nic_dns_view` AS
|
||||
SELECT
|
||||
n.id AS id,
|
||||
n.uuid AS uuid,
|
||||
n.instance_id AS instance_id,
|
||||
n.network_id AS network_id,
|
||||
n.ip4_address AS ip4_address,
|
||||
n.ip6_address AS ip6_address,
|
||||
n.removed AS removed,
|
||||
nd.value AS nic_dns_name,
|
||||
map.dns_zone_id AS dns_zone_id,
|
||||
map.sub_domain AS sub_domain
|
||||
FROM
|
||||
`cloud`.`nics` n
|
||||
INNER JOIN
|
||||
`cloud`.`dns_zone_network_map` map ON n.network_id = map.network_id
|
||||
LEFT JOIN
|
||||
`cloud`.`nic_details` nd ON n.id = nd.nic_id AND nd.name = 'nicdnsname'
|
||||
WHERE
|
||||
n.instance_id IS NOT NULL AND map.removed IS NULL;
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
<!--
|
||||
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.
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>cloud-plugin-dns-powerdns</artifactId>
|
||||
<name>Apache CloudStack Plugin - PowerDNS</name>
|
||||
<parent>
|
||||
<groupId>org.apache.cloudstack</groupId>
|
||||
<artifactId>cloudstack-plugins</artifactId>
|
||||
<version>4.23.0.0-SNAPSHOT</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
</project>
|
||||
|
|
@ -0,0 +1,390 @@
|
|||
// 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.dns.powerdns;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.dns.exception.DnsAuthenticationException;
|
||||
import org.apache.cloudstack.dns.exception.DnsConflictException;
|
||||
import org.apache.cloudstack.dns.exception.DnsNotFoundException;
|
||||
import org.apache.cloudstack.dns.exception.DnsOperationException;
|
||||
import org.apache.cloudstack.dns.exception.DnsProviderException;
|
||||
import org.apache.cloudstack.dns.exception.DnsTransportException;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.http.client.config.RequestConfig;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.client.methods.HttpDelete;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.client.methods.HttpPatch;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.client.methods.HttpPut;
|
||||
import org.apache.http.client.methods.HttpUriRequest;
|
||||
import org.apache.http.entity.StringEntity;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
||||
import org.apache.http.util.EntityUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.cloud.utils.StringUtils;
|
||||
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);
|
||||
private static final ObjectMapper MAPPER = new ObjectMapper();
|
||||
|
||||
private static final int CONNECT_TIMEOUT_MS = 5_000;
|
||||
private static final int SOCKET_TIMEOUT_MS = 10_000;
|
||||
private static final int MAX_CONNECTIONS_TOTAL = 50;
|
||||
private static final int MAX_CONNECTIONS_PER_ROUTE = 10;
|
||||
private static final String API_PREFIX = "/api/v1";
|
||||
public static final String DEFAULT_SERVER_NAME = "localhost";
|
||||
|
||||
private final CloseableHttpClient httpClient;
|
||||
|
||||
public PowerDnsClient() {
|
||||
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
|
||||
connectionManager.setMaxTotal(MAX_CONNECTIONS_TOTAL);
|
||||
connectionManager.setDefaultMaxPerRoute(MAX_CONNECTIONS_PER_ROUTE);
|
||||
|
||||
RequestConfig requestConfig = RequestConfig.custom()
|
||||
.setConnectTimeout(CONNECT_TIMEOUT_MS)
|
||||
.setConnectionRequestTimeout(CONNECT_TIMEOUT_MS)
|
||||
.setSocketTimeout(SOCKET_TIMEOUT_MS)
|
||||
.build();
|
||||
|
||||
this.httpClient = HttpClientBuilder.create()
|
||||
.setConnectionManager(connectionManager)
|
||||
.setDefaultRequestConfig(requestConfig)
|
||||
.evictIdleConnections(30, TimeUnit.SECONDS)
|
||||
.disableCookieManagement()
|
||||
.build();
|
||||
}
|
||||
|
||||
public String resolveServerId(String baseUrl, Integer port, String apiKey, String externalServerId) throws DnsProviderException {
|
||||
if (StringUtils.isNotBlank(externalServerId)) {
|
||||
return validateServerId(baseUrl, port, apiKey, externalServerId);
|
||||
}
|
||||
return discoverAuthoritativeServerId(baseUrl, port, apiKey);
|
||||
}
|
||||
|
||||
public String validateServerId(String baseUrl, Integer port, String apiKey, String externalServerId) throws DnsProviderException {
|
||||
String encodedServer = URLEncoder.encode(externalServerId, StandardCharsets.UTF_8);
|
||||
HttpGet request = new HttpGet(buildUrl(baseUrl, port, "/servers/" + encodedServer));
|
||||
JsonNode server = execute(request, apiKey, 200);
|
||||
if (!ApiConstants.AUTHORITATIVE.equalsIgnoreCase(server.path("daemon_type").asText(null))) {
|
||||
throw new DnsOperationException(String.format("Server %s is not authoritative type=%s", externalServerId,
|
||||
server.path("daemon_type").asText(null)));
|
||||
}
|
||||
return externalServerId;
|
||||
}
|
||||
|
||||
public String discoverAuthoritativeServerId(String baseUrl, Integer port, String apiKey) throws DnsProviderException {
|
||||
String url = buildUrl(baseUrl, port , "/servers");
|
||||
HttpGet request = new HttpGet(url);
|
||||
JsonNode servers = execute(request, apiKey, 200);
|
||||
if (servers == null || !servers.isArray() || servers.isEmpty()) {
|
||||
throw new DnsOperationException("No servers returned by PowerDNS API");
|
||||
}
|
||||
String fallbackId = null;
|
||||
for (JsonNode server : servers) {
|
||||
String daemonType = server.path("daemon_type").asText(null);
|
||||
if (!ApiConstants.AUTHORITATIVE.equalsIgnoreCase(daemonType)) {
|
||||
continue;
|
||||
}
|
||||
String serverId = server.path(ApiConstants.ID).asText(null);
|
||||
if (StringUtils.isBlank(serverId)) {
|
||||
continue;
|
||||
}
|
||||
// Prefer localhost if present
|
||||
if (DEFAULT_SERVER_NAME.equals(serverId)) {
|
||||
return serverId;
|
||||
}
|
||||
if (fallbackId == null) {
|
||||
fallbackId = serverId;
|
||||
}
|
||||
}
|
||||
if (fallbackId != null) {
|
||||
return fallbackId;
|
||||
}
|
||||
throw new DnsOperationException("No authoritative PowerDNS server found");
|
||||
}
|
||||
|
||||
public String createZone(String baseUrl, Integer port, String apiKey, String externalServerId, String zoneName,
|
||||
String zoneKind, boolean dnsSecFlag, List<String> nameServers) throws DnsProviderException {
|
||||
|
||||
validateServerId(baseUrl, port, apiKey, externalServerId);
|
||||
String normalizedZone = normalizeZone(zoneName);
|
||||
ObjectNode json = MAPPER.createObjectNode();
|
||||
json.put(ApiConstants.NAME, normalizedZone);
|
||||
json.put(ApiConstants.KIND, zoneKind);
|
||||
json.put(ApiConstants.DNS_SEC, dnsSecFlag);
|
||||
if (!CollectionUtils.isEmpty(nameServers)) {
|
||||
ArrayNode nsArray = json.putArray(ApiConstants.NAME_SERVERS);
|
||||
for (String ns : nameServers) {
|
||||
nsArray.add(ns.endsWith(".") ? ns : ns + ".");
|
||||
}
|
||||
}
|
||||
HttpPost request = new HttpPost(buildUrl(baseUrl, port, "/servers/" + externalServerId + "/zones"));
|
||||
request.setEntity(new StringEntity(json.toString(), StandardCharsets.UTF_8));
|
||||
JsonNode response = execute(request, apiKey, 201);
|
||||
if (response == null) {
|
||||
throw new DnsOperationException("Empty response from DNS server");
|
||||
}
|
||||
String zoneId = response.path(ApiConstants.ID).asText();
|
||||
if (StringUtils.isBlank(zoneId)) {
|
||||
throw new DnsOperationException("PowerDNS returned empty zone id");
|
||||
}
|
||||
return zoneId;
|
||||
}
|
||||
|
||||
public void updateZone(String baseUrl, Integer port, String apiKey, String externalServerId, String zoneName,
|
||||
String zoneKind, Boolean dnsSecFlag, List<String> nameServers) throws DnsProviderException {
|
||||
|
||||
validateServerId(baseUrl, port, apiKey, externalServerId);
|
||||
String normalizedZone = normalizeZone(zoneName);
|
||||
String encodedZone = URLEncoder.encode(normalizedZone, StandardCharsets.UTF_8);
|
||||
String url = buildUrl(baseUrl, port,"/servers/" + externalServerId + "/zones/" + encodedZone);
|
||||
|
||||
ObjectNode json = MAPPER.createObjectNode();
|
||||
if (dnsSecFlag != null) {
|
||||
json.put(ApiConstants.DNS_SEC, dnsSecFlag);
|
||||
}
|
||||
if (StringUtils.isNotBlank(zoneKind)) {
|
||||
json.put(ApiConstants.KIND, zoneKind);
|
||||
}
|
||||
if (!CollectionUtils.isEmpty(nameServers)) {
|
||||
ArrayNode nsArray = json.putArray(ApiConstants.NAME_SERVERS);
|
||||
for (String ns : nameServers) {
|
||||
nsArray.add(ns.endsWith(".") ? ns : ns + ".");
|
||||
}
|
||||
}
|
||||
HttpPut request = new HttpPut(url);
|
||||
request.setEntity(new StringEntity(json.toString(), StandardCharsets.UTF_8));
|
||||
execute(request, apiKey, 204);
|
||||
}
|
||||
|
||||
public void deleteZone(String baseUrl, Integer port, String apiKey, String externalServerId, String zoneName) throws DnsProviderException {
|
||||
validateServerId(baseUrl, port, apiKey, externalServerId);
|
||||
String normalizedZone = normalizeZone(zoneName);
|
||||
String encodedZone = URLEncoder.encode(normalizedZone, StandardCharsets.UTF_8);
|
||||
HttpDelete request = new HttpDelete(buildUrl(baseUrl, port, "/servers/" + externalServerId + "/zones/" + encodedZone));
|
||||
execute(request, apiKey, 204, 404);
|
||||
}
|
||||
|
||||
public String modifyRecord(String baseUrl, Integer port, String apiKey, String externalServerId, String zoneName,
|
||||
String recordName, String type, long ttl, List<String> contents, String changeType) throws DnsProviderException {
|
||||
|
||||
validateServerId(baseUrl, port, apiKey, externalServerId);
|
||||
String normalizedZone = normalizeZone(zoneName);
|
||||
String normalizedRecord = normalizeRecordName(recordName, normalizedZone);
|
||||
ObjectNode root = MAPPER.createObjectNode();
|
||||
ArrayNode rrsets = root.putArray(ApiConstants.RR_SETS);
|
||||
ObjectNode rrset = rrsets.addObject();
|
||||
rrset.put(ApiConstants.NAME, normalizedRecord);
|
||||
rrset.put(ApiConstants.TYPE, type.toUpperCase());
|
||||
rrset.put(ApiConstants.TTL, ttl);
|
||||
rrset.put(ApiConstants.CHANGE_TYPE, changeType);
|
||||
ArrayNode records = rrset.putArray(ApiConstants.RECORDS);
|
||||
if (!CollectionUtils.isEmpty(contents)) {
|
||||
for (String content : contents) {
|
||||
ObjectNode record = records.addObject();
|
||||
record.put(ApiConstants.CONTENT, content);
|
||||
record.put(ApiConstants.DISABLED, false);
|
||||
}
|
||||
}
|
||||
String encodedZone = URLEncoder.encode(normalizedZone, StandardCharsets.UTF_8);
|
||||
HttpPatch request = new HttpPatch(buildUrl(baseUrl, port, "/servers/" + externalServerId + "/zones/" + encodedZone));
|
||||
request.setEntity(new StringEntity(root.toString(), StandardCharsets.UTF_8));
|
||||
execute(request, apiKey, 204);
|
||||
return normalizedRecord.endsWith(".") ? normalizedRecord.substring(0, normalizedRecord.length() - 1) : normalizedRecord;
|
||||
}
|
||||
|
||||
public Iterable<JsonNode> listRecords(String baseUrl, Integer port, String apiKey, String externalServerId, String zoneName) throws DnsProviderException {
|
||||
validateServerId(baseUrl, port, apiKey, externalServerId);
|
||||
String normalizedZone = normalizeZone(zoneName);
|
||||
String encodedZone = URLEncoder.encode(normalizedZone, StandardCharsets.UTF_8);
|
||||
HttpGet request = new HttpGet(buildUrl(baseUrl, port, "/servers/" + externalServerId + "/zones/" + encodedZone));
|
||||
JsonNode zoneNode = execute(request, apiKey, 200);
|
||||
if (zoneNode == null || !zoneNode.has(ApiConstants.RR_SETS)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
JsonNode rrsets = zoneNode.path(ApiConstants.RR_SETS);
|
||||
return rrsets.isArray() ? rrsets : Collections.emptyList();
|
||||
}
|
||||
|
||||
public boolean zoneExists(String baseUrl, Integer port, String apiKey, String externalServerId, String zoneName) {
|
||||
try {
|
||||
validateServerId(baseUrl, port, apiKey, externalServerId);
|
||||
String normalizedZone = normalizeZone(zoneName);
|
||||
String encodedZone = URLEncoder.encode(normalizedZone, StandardCharsets.UTF_8);
|
||||
HttpGet request = new HttpGet(buildUrl(baseUrl, port, "/servers/" + externalServerId + "/zones/" + encodedZone));
|
||||
execute(request, apiKey, 200);
|
||||
return true;
|
||||
} catch (DnsProviderException | IllegalArgumentException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean recordExists(String baseUrl, Integer port, String apiKey,
|
||||
String externalServerId, String zoneName,
|
||||
String recordName, String type) throws DnsProviderException {
|
||||
|
||||
validateServerId(baseUrl, port, apiKey, externalServerId);
|
||||
String normalizedZone = normalizeZone(zoneName);
|
||||
String normalizedRecord = normalizeRecordName(recordName, normalizedZone);
|
||||
String encodedZone = URLEncoder.encode(normalizedZone, StandardCharsets.UTF_8);
|
||||
String urlPath = "/servers/" + externalServerId + "/zones/" + encodedZone +
|
||||
"?rrset_name=" + URLEncoder.encode(normalizedRecord, StandardCharsets.UTF_8) +
|
||||
"&rrset_type=" + type.toUpperCase();
|
||||
HttpGet request = new HttpGet(buildUrl(baseUrl, port, urlPath));
|
||||
JsonNode zoneNode = execute(request, apiKey, 200);
|
||||
if (zoneNode == null || !zoneNode.has(ApiConstants.RR_SETS)) {
|
||||
return false;
|
||||
}
|
||||
JsonNode rrsets = zoneNode.path(ApiConstants.RR_SETS);
|
||||
return rrsets.isArray() && !rrsets.isEmpty();
|
||||
}
|
||||
|
||||
private JsonNode execute(HttpUriRequest request, String apiKey, int... expectedStatus) throws DnsProviderException {
|
||||
request.addHeader(ApiConstants.X_API_KEY, apiKey);
|
||||
request.addHeader("Accept", "application/json");
|
||||
request.addHeader(ApiConstants.CONTENT_TYPE, "application/json");
|
||||
|
||||
try (CloseableHttpResponse response = httpClient.execute(request)) {
|
||||
int status = response.getStatusLine().getStatusCode();
|
||||
String body = response.getEntity() != null ? EntityUtils.toString(response.getEntity()) : null;
|
||||
|
||||
for (int expected : expectedStatus) {
|
||||
if (status == expected) {
|
||||
if (body != null && !body.isEmpty()) {
|
||||
return MAPPER.readTree(body);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (status == 404) {
|
||||
throw new DnsNotFoundException("Resource not found: " + body);
|
||||
} else if (status == 401 || status == 403) {
|
||||
throw new DnsAuthenticationException("Invalid API key");
|
||||
} else if (status == 409) {
|
||||
throw new DnsConflictException("Conflict: " + body);
|
||||
}
|
||||
throw new DnsOperationException("Unexpected PowerDNS response: HTTP " + status + " Body: " + body);
|
||||
} catch (IOException ex) {
|
||||
throw new DnsTransportException("Error communicating with PowerDNS", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private String buildUrl(String baseUrl, Integer port, String path) {
|
||||
String fullUrl = normalizeBaseUrl(baseUrl);
|
||||
if (port != null && port > 0) {
|
||||
try {
|
||||
URI uri = new URI(fullUrl);
|
||||
if (uri.getPort() == -1) {
|
||||
fullUrl = fullUrl + ":" + port;
|
||||
}
|
||||
} catch (URISyntaxException e) {
|
||||
fullUrl = fullUrl + ":" + port;
|
||||
}
|
||||
}
|
||||
if (!path.startsWith("/")) {
|
||||
path = "/" + path;
|
||||
}
|
||||
return fullUrl + API_PREFIX + path;
|
||||
}
|
||||
|
||||
private String normalizeBaseUrl(String baseUrl) {
|
||||
if (baseUrl == null) {
|
||||
throw new IllegalArgumentException("Base URL cannot be null");
|
||||
}
|
||||
String url = baseUrl.trim();
|
||||
if (!url.startsWith("http://") && !url.startsWith("https://")) {
|
||||
url = "http://" + url;
|
||||
}
|
||||
if (url.endsWith("/")) {
|
||||
url = url.substring(0, url.length() - 1);
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
||||
private String normalizeZone(String zoneName) {
|
||||
if (StringUtils.isBlank(zoneName)) {
|
||||
throw new IllegalArgumentException("Zone name must not be null or empty");
|
||||
}
|
||||
String zone = zoneName.trim().toLowerCase();
|
||||
if (!zone.endsWith(".")) {
|
||||
zone = zone + ".";
|
||||
}
|
||||
if (zone.length() < 2) {
|
||||
throw new IllegalArgumentException("Zone name is too short");
|
||||
}
|
||||
return zone;
|
||||
}
|
||||
|
||||
String normalizeRecordName(String recordName, String zoneName) {
|
||||
if (recordName == null) {
|
||||
throw new IllegalArgumentException("Record name must not be null");
|
||||
}
|
||||
String normalizedZone = normalizeZone(zoneName);
|
||||
String name = recordName.trim().toLowerCase();
|
||||
// Apex of the zone
|
||||
if (name.equals("@") || name.isEmpty()) {
|
||||
return normalizedZone;
|
||||
}
|
||||
|
||||
String zoneWithoutDot = normalizedZone.substring(0, normalizedZone.length() - 1);
|
||||
// Already absolute (ends with dot)
|
||||
if (name.endsWith(".")) {
|
||||
// Check if the record belongs to the zone
|
||||
if (!name.equals(normalizedZone) && !name.endsWith("." + zoneWithoutDot + ".")) {
|
||||
throw new IllegalArgumentException(
|
||||
String.format("Record '%s' does not belong to zone '%s'", recordName, zoneName)
|
||||
);
|
||||
}
|
||||
return name;
|
||||
}
|
||||
if (name.contains(".")) {
|
||||
return name + ".";
|
||||
}
|
||||
// Relative name → append zone
|
||||
return name + "." + normalizedZone;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
try {
|
||||
httpClient.close();
|
||||
} catch (IOException e) {
|
||||
logger.warn("Failed to close PowerDNS HTTP client", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,202 @@
|
|||
// 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.dns.powerdns;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.dns.DnsProvider;
|
||||
import org.apache.cloudstack.dns.DnsProviderType;
|
||||
import org.apache.cloudstack.dns.DnsRecord;
|
||||
import org.apache.cloudstack.dns.DnsServer;
|
||||
import org.apache.cloudstack.dns.DnsZone;
|
||||
import org.apache.cloudstack.dns.exception.DnsProviderException;
|
||||
import org.apache.logging.log4j.util.Strings;
|
||||
|
||||
import com.cloud.utils.StringUtils;
|
||||
import com.cloud.utils.component.AdapterBase;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
|
||||
public class PowerDnsProvider extends AdapterBase implements DnsProvider {
|
||||
private PowerDnsClient client;
|
||||
static String PDNS_SERVER_ID = "pdnsServerId";
|
||||
|
||||
@Override
|
||||
public DnsProviderType getProviderType() {
|
||||
return DnsProviderType.PowerDNS;
|
||||
}
|
||||
|
||||
public void validate(DnsServer server) throws DnsProviderException {
|
||||
validateRequiredServerFields(server);
|
||||
client.validateServerId(server.getUrl(), server.getPort(), server.getDnsApiKey(), server.getDetail(PDNS_SERVER_ID));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String validateAndResolveServer(DnsServer server) throws Exception {
|
||||
validateRequiredServerFields(server);
|
||||
String resolvedDnsServerId = client.resolveServerId(server.getUrl(), server.getPort(), server.getDnsApiKey(), server.getDetail(PDNS_SERVER_ID));
|
||||
if (Strings.isNotBlank(resolvedDnsServerId)) {
|
||||
server.appendDetails(PDNS_SERVER_ID, resolvedDnsServerId);
|
||||
}
|
||||
return resolvedDnsServerId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String provisionZone(DnsServer server, DnsZone zone) throws DnsProviderException {
|
||||
validateRequiredServerAndZoneFields(server, zone);
|
||||
return client.createZone(
|
||||
server.getUrl(),
|
||||
server.getPort(),
|
||||
server.getDnsApiKey(),
|
||||
server.getDetail(PDNS_SERVER_ID),
|
||||
zone.getName(),
|
||||
ApiConstants.NATIVE_ZONE, false, server.getNameServers()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteZone(DnsServer server, DnsZone zone) throws DnsProviderException {
|
||||
validateRequiredServerAndZoneFields(server, zone);
|
||||
client.deleteZone(server.getUrl(), server.getPort(), server.getDnsApiKey(), server.getDetail(PDNS_SERVER_ID), zone.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateZone(DnsServer server, DnsZone zone) throws DnsProviderException {
|
||||
validateRequiredServerAndZoneFields(server, zone);
|
||||
client.updateZone(
|
||||
server.getUrl(),
|
||||
server.getPort(),
|
||||
server.getDnsApiKey(),
|
||||
server.getDetail(PDNS_SERVER_ID),
|
||||
zone.getName(), ApiConstants.NATIVE_ZONE, false, server.getNameServers());
|
||||
}
|
||||
|
||||
public enum ChangeType {
|
||||
REPLACE, DELETE
|
||||
}
|
||||
|
||||
@Override
|
||||
public String addRecord(DnsServer server, DnsZone zone, DnsRecord record) throws DnsProviderException {
|
||||
validateRequiredServerAndZoneFields(server, zone);
|
||||
return applyRecord(
|
||||
server.getUrl(),
|
||||
server.getPort(),
|
||||
server.getDnsApiKey(),
|
||||
server.getDetail(PDNS_SERVER_ID),
|
||||
zone.getName(), record, ChangeType.REPLACE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String updateRecord(DnsServer server, DnsZone zone, DnsRecord record) throws DnsProviderException {
|
||||
validateRequiredServerAndZoneFields(server, zone);
|
||||
return addRecord(server, zone, record);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String deleteRecord(DnsServer server, DnsZone zone, DnsRecord record) throws DnsProviderException {
|
||||
validateRequiredServerAndZoneFields(server, zone);
|
||||
return applyRecord(server.getUrl(),
|
||||
server.getPort(),
|
||||
server.getDnsApiKey(),
|
||||
server.getDetail(PDNS_SERVER_ID),
|
||||
zone.getName(), record, ChangeType.DELETE);
|
||||
}
|
||||
|
||||
public String applyRecord(String serverUrl, Integer port, String apiKey, String externalServerId, String zoneName,
|
||||
DnsRecord record, ChangeType changeType) throws DnsProviderException {
|
||||
|
||||
return client.modifyRecord(serverUrl, port, apiKey, externalServerId, zoneName, record.getName(),
|
||||
record.getType().name(), record.getTtl(), record.getContents(), changeType.name());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DnsRecord> listRecords(DnsServer server, DnsZone zone) throws DnsProviderException {
|
||||
validateRequiredServerAndZoneFields(server, zone);
|
||||
List<DnsRecord> records = new ArrayList<>();
|
||||
Iterable<JsonNode> rrsetNodes = client.listRecords(server.getUrl(), server.getPort(), server.getDnsApiKey(),
|
||||
server.getDetail(PDNS_SERVER_ID), zone.getName());
|
||||
|
||||
for (JsonNode rrset : rrsetNodes) {
|
||||
String name = rrset.path(ApiConstants.NAME).asText();
|
||||
String typeStr = rrset.path(ApiConstants.TYPE).asText();
|
||||
int ttl = rrset.path(ApiConstants.TTL).asInt(0);
|
||||
if (!"SOA".equalsIgnoreCase(typeStr)) {
|
||||
try {
|
||||
List<String> contents = new ArrayList<>();
|
||||
JsonNode recordsNode = rrset.path(ApiConstants.RECORDS);
|
||||
if (recordsNode.isArray()) {
|
||||
for (JsonNode rec : recordsNode) {
|
||||
String content = rec.path(ApiConstants.CONTENT).asText();
|
||||
if (!content.isEmpty()) {
|
||||
contents.add(content);
|
||||
}
|
||||
}
|
||||
}
|
||||
records.add(new DnsRecord(name, DnsRecord.RecordType.valueOf(typeStr), contents, ttl));
|
||||
} catch (Exception ignored) {
|
||||
// Skip unsupported record types
|
||||
}
|
||||
}
|
||||
}
|
||||
return records;
|
||||
}
|
||||
|
||||
public boolean dnsRecordExists(DnsServer server, DnsZone zone, String recordName, String recordType) throws DnsProviderException {
|
||||
return client.recordExists(server.getUrl(), server.getPort(), server.getDnsApiKey(),
|
||||
server.getDetail(PDNS_SERVER_ID), zone.getName(), recordName, recordType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean dnsZoneExists(DnsServer server, DnsZone zone) {
|
||||
return client.zoneExists(server.getUrl(), server.getPort(), server.getDnsApiKey(), server.getDetail(PDNS_SERVER_ID), zone.getName());
|
||||
}
|
||||
|
||||
void validateRequiredServerAndZoneFields(DnsServer server, DnsZone zone) {
|
||||
validateRequiredServerFields(server);
|
||||
if (StringUtils.isBlank(zone.getName())) {
|
||||
throw new IllegalArgumentException("Zone name cannot be empty");
|
||||
}
|
||||
}
|
||||
|
||||
void validateRequiredServerFields(DnsServer server) {
|
||||
if (StringUtils.isBlank(server.getUrl())) {
|
||||
throw new IllegalArgumentException("PowerDNS API URL cannot be empty");
|
||||
}
|
||||
if (StringUtils.isBlank(server.getDnsApiKey())) {
|
||||
throw new IllegalArgumentException("PowerDNS API key cannot be empty");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean configure(String name, Map<String, Object> params) {
|
||||
if (client == null) {
|
||||
client = new PowerDnsClient();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean stop() {
|
||||
if (client != null) {
|
||||
client.close();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
# 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.
|
||||
name=powerdns
|
||||
parent=dns
|
||||
|
|
@ -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.
|
||||
-->
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xmlns:aop="http://www.springframework.org/schema/aop"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
|
||||
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
|
||||
http://www.springframework.org/schema/context
|
||||
http://www.springframework.org/schema/context/spring-context-3.0.xsd"
|
||||
>
|
||||
|
||||
<bean id="powerDnsProvider" class="org.apache.cloudstack.dns.powerdns.PowerDnsProvider" />
|
||||
</beans>
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
// 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.dns;
|
||||
|
||||
import static org.apache.cloudstack.dns.DnsProviderUtil.appendPublicSuffixToZone;
|
||||
import static org.apache.cloudstack.dns.DnsProviderUtil.normalizeDomainForDb;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.apache.logging.log4j.util.Strings;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
|
||||
@RunWith(Parameterized.class)
|
||||
public class DnsProviderUtilTest {
|
||||
private final String userZoneName;
|
||||
private final String publicSuffix;
|
||||
private final String expectedResult;
|
||||
private final boolean expectException;
|
||||
|
||||
public DnsProviderUtilTest(String userZoneName,
|
||||
String publicSuffix,
|
||||
String expectedResult,
|
||||
boolean expectException) {
|
||||
this.userZoneName = userZoneName;
|
||||
this.publicSuffix = publicSuffix;
|
||||
this.expectedResult = expectedResult;
|
||||
this.expectException = expectException;
|
||||
}
|
||||
|
||||
@Parameterized.Parameters
|
||||
public static Collection<Object[]> data() {
|
||||
return Arrays.asList(new Object[][]{
|
||||
{"tenant1.com", "example.com", "tenant1.example.com", false},
|
||||
{"dev.tenant2.com", "example.com", "dev.tenant2.example.com", false},
|
||||
{"tenant3.example.com", "example.com", "tenant3.example.com", false},
|
||||
{"Tenant1.CoM", "ExAmple.CoM", "tenant1.example.com", false},
|
||||
{"tenant1.com.", "example.com.", "tenant1.example.com", false},
|
||||
{"tenant1.com", "", "tenant1.com", false},
|
||||
{"tenant1.com", null, "tenant1.com", false},
|
||||
{"test.abc.com", "abc.com", "test.abc.com", false},
|
||||
{"sub.test.abc.com", "abc.com", "sub.test.abc.com", false},
|
||||
{"test.ai.abc.com", "abc.com", "test.ai.abc.com", false},
|
||||
{"deep.sub.abc.com", "abc.com", "deep.sub.abc.com", false},
|
||||
{"abc.com", "xyz.com", "abc.xyz.com", false},
|
||||
{"test.xyz.com", "xyz.com", "test.xyz.com", false},
|
||||
{"test.com.xyz.com", "xyz.com", "test.com.xyz.com", false},
|
||||
{"tenant", "example.com", null, true}, // single label
|
||||
{"test", "abc.com", null, true},
|
||||
{"example.com.", "example.com", null, true},
|
||||
{"example.com", "example.com", null, true}, // root level forbidden
|
||||
{"abc.com", "abc.com", null, true}, // root level forbidden
|
||||
{"tenant1.org", "example.com", null, true}, // TLD mismatch
|
||||
{"test.ai", "abc.com", null, true}, // TLD mismatch
|
||||
{null, "example.com", null, true},
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAppendPublicSuffix() {
|
||||
if (expectException) {
|
||||
try {
|
||||
executeAppendSuffixTest(userZoneName, publicSuffix);
|
||||
fail("Expected IllegalArgumentException");
|
||||
} catch (IllegalArgumentException ignored) {
|
||||
// noop
|
||||
}
|
||||
} else {
|
||||
String result;
|
||||
if (Strings.isNotBlank(publicSuffix)) {
|
||||
result = executeAppendSuffixTest(userZoneName, publicSuffix);
|
||||
} else {
|
||||
result = appendPublicSuffixToZone(normalizeDomainForDb(userZoneName), publicSuffix);
|
||||
}
|
||||
assertEquals(expectedResult, result);
|
||||
}
|
||||
}
|
||||
|
||||
String executeAppendSuffixTest(String zoneName, String domainSuffix) {
|
||||
return appendPublicSuffixToZone(normalizeDomainForDb(zoneName), domainSuffix);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,197 @@
|
|||
// 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.dns;
|
||||
|
||||
import static org.apache.cloudstack.dns.DnsRecord.RecordType.A;
|
||||
import static org.apache.cloudstack.dns.DnsRecord.RecordType.AAAA;
|
||||
import static org.apache.cloudstack.dns.DnsRecord.RecordType.CNAME;
|
||||
import static org.apache.cloudstack.dns.DnsRecord.RecordType.MX;
|
||||
import static org.apache.cloudstack.dns.DnsRecord.RecordType.NS;
|
||||
import static org.apache.cloudstack.dns.DnsRecord.RecordType.PTR;
|
||||
import static org.apache.cloudstack.dns.DnsRecord.RecordType.SRV;
|
||||
import static org.apache.cloudstack.dns.DnsRecord.RecordType.TXT;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
|
||||
@RunWith(Parameterized.class)
|
||||
public class NormalizeDnsRecordValueTest {
|
||||
|
||||
private final String description;
|
||||
private final String input;
|
||||
private final DnsRecord.RecordType recordType;
|
||||
private final String expected;
|
||||
private final boolean expectException;
|
||||
|
||||
public NormalizeDnsRecordValueTest(String description, String input,
|
||||
DnsRecord.RecordType recordType,
|
||||
String expected, boolean expectException) {
|
||||
this.description = description;
|
||||
this.input = input;
|
||||
this.recordType = recordType;
|
||||
this.expected = expected;
|
||||
this.expectException = expectException;
|
||||
}
|
||||
|
||||
@Parameterized.Parameters(name = "{0}")
|
||||
public static Collection<Object[]> data() {
|
||||
return Arrays.asList(new Object[][] {
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// Guard: blank/null value — all record types should throw
|
||||
// ----------------------------------------------------------------
|
||||
{"null value, A record", null, A, null, true},
|
||||
{"empty value, A record", "", A, null, true},
|
||||
{"blank value, A record", " ", A, null, true},
|
||||
|
||||
{"null value, AAAA record", null, AAAA, null, true},
|
||||
{"null value, CNAME record", null, CNAME, null, true},
|
||||
{"null value, MX record", null, MX, null, true},
|
||||
{"null value, TXT record", null, TXT, null, true},
|
||||
{"null value, SRV record", null, SRV, null, true},
|
||||
{"null value, NS record", null, NS, null, true},
|
||||
{"null value, PTR record", null, PTR, null, true},
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// A record
|
||||
// ----------------------------------------------------------------
|
||||
{"A: valid IPv4", "93.184.216.34", A, "93.184.216.34", false},
|
||||
{"A: valid IPv4 with whitespace", " 93.184.216.34 ", A, "93.184.216.34", false},
|
||||
{"A: loopback", "127.0.0.1", A, "127.0.0.1", false},
|
||||
{"A: all-zeros", "0.0.0.0", A, "0.0.0.0", false},
|
||||
{"A: broadcast", "255.255.255.255", A, "255.255.255.255", false},
|
||||
{"A: private 10.x", "10.0.0.1", A, "10.0.0.1", false},
|
||||
{"A: private 192.168.x", "192.168.1.1", A, "192.168.1.1", false},
|
||||
|
||||
{"A: IPv6 rejected", "2001:db8::1", A, null, true},
|
||||
{"A: domain rejected", "example.com", A, null, true},
|
||||
{"A: partial IP rejected", "192.168.1", A, null, true},
|
||||
{"A: trailing dot rejected", "93.184.216.34.", A, null, true},
|
||||
{"A: octet out of range rejected", "256.0.0.1", A, null, true},
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// AAAA record
|
||||
// ----------------------------------------------------------------
|
||||
{"AAAA: full IPv6", "2001:0db8:0000:0000:0000:0000:0000:0001", AAAA,
|
||||
"2001:0db8:0000:0000:0000:0000:0000:0001", false},
|
||||
|
||||
{"AAAA: compressed IPv6", "2001:db8::1", AAAA, "2001:db8::1", false},
|
||||
{"AAAA: loopback", "::1", AAAA, "::1", false},
|
||||
{"AAAA: all zeros", "::", AAAA, "::", false},
|
||||
{"AAAA: whitespace", " 2001:db8::1 ", AAAA, "2001:db8::1", false},
|
||||
|
||||
{"AAAA: IPv4 rejected", "93.184.216.34", AAAA, null, true},
|
||||
{"AAAA: domain rejected", "example.com", AAAA, null, true},
|
||||
{"AAAA: invalid hex rejected", "2001:db8::xyz", AAAA, null, true},
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// CNAME record
|
||||
// ----------------------------------------------------------------
|
||||
{"CNAME: basic", "target.example.com", CNAME, "target.example.com.", false},
|
||||
{"CNAME: uppercase", "TARGET.EXAMPLE.COM", CNAME, "target.example.com.", false},
|
||||
{"CNAME: trailing dot", "target.example.com.", CNAME, "target.example.com.", false},
|
||||
{"CNAME: whitespace", " target.example.com ", CNAME, "target.example.com.", false},
|
||||
{"CNAME: subdomain", "sub.target.example.com", CNAME, "sub.target.example.com.", false},
|
||||
|
||||
{"CNAME: IP rejected", "192.168.1.1", CNAME, null, true},
|
||||
{"CNAME: invalid label", "-bad.example.com", CNAME, null, true},
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// NS record
|
||||
// ----------------------------------------------------------------
|
||||
{"NS: basic", "ns1.example.com", NS, "ns1.example.com.", false},
|
||||
{"NS: uppercase", "NS1.EXAMPLE.COM", NS, "ns1.example.com.", false},
|
||||
{"NS: trailing dot", "ns1.example.com.", NS, "ns1.example.com.", false},
|
||||
{"NS: subdomain", "ns1.sub.example.com", NS, "ns1.sub.example.com.", false},
|
||||
|
||||
{"NS: IP rejected", "8.8.8.8", NS, null, true},
|
||||
{"NS: invalid label", "ns1-.example.com", NS, null, true},
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// PTR record
|
||||
// ----------------------------------------------------------------
|
||||
{"PTR: basic", "host.example.com", PTR, "host.example.com.", false},
|
||||
{"PTR: in-addr.arpa", "1.168.192.in-addr.arpa", PTR, "1.168.192.in-addr.arpa.", false},
|
||||
{"PTR: uppercase", "HOST.EXAMPLE.COM", PTR, "host.example.com.", false},
|
||||
{"PTR: trailing dot", "host.example.com.", PTR, "host.example.com.", false},
|
||||
|
||||
{"PTR: IP rejected", "192.168.1.1", PTR, null, true},
|
||||
{"PTR: invalid label", "-host.example.com", PTR, null, true},
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// MX record
|
||||
// ----------------------------------------------------------------
|
||||
{"MX: standard", "10 mail.example.com", MX, "10 mail.example.com.", false},
|
||||
{"MX: zero priority", "0 mail.example.com", MX, "0 mail.example.com.", false},
|
||||
{"MX: max priority", "65535 mail.example.com", MX, "65535 mail.example.com.", false},
|
||||
{"MX: uppercase", "10 MAIL.EXAMPLE.COM", MX, "10 mail.example.com.", false},
|
||||
{"MX: trailing dot", "10 mail.example.com.", MX, "10 mail.example.com.", false},
|
||||
{"MX: extra whitespace", "10 mail.example.com", MX, "10 mail.example.com.", false},
|
||||
|
||||
{"MX: missing domain", "10", MX, null, true},
|
||||
{"MX: priority out of range", "65536 mail.example.com", MX, null, true},
|
||||
{"MX: non-numeric priority", "abc mail.example.com", MX, null, true},
|
||||
{"MX: IP rejected", "10 192.168.1.1", MX, null, true},
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// SRV record
|
||||
// ----------------------------------------------------------------
|
||||
{"SRV: standard", "10 20 443 target.example.com", SRV, "10 20 443 target.example.com.", false},
|
||||
{"SRV: zeros", "0 0 1 target.example.com", SRV, "0 0 1 target.example.com.", false},
|
||||
{"SRV: max values", "65535 65535 65535 target.example.com", SRV, "65535 65535 65535 target.example.com.", false},
|
||||
{"SRV: uppercase", "10 20 443 TARGET.EXAMPLE.COM", SRV, "10 20 443 target.example.com.", false},
|
||||
{"SRV: trailing dot", "10 20 443 target.example.com.", SRV, "10 20 443 target.example.com.", false},
|
||||
|
||||
{"SRV: missing target", "10 20 443", SRV, null, true},
|
||||
{"SRV: port 0", "10 20 0 target.example.com", SRV, null, true},
|
||||
{"SRV: priority out of range", "65536 20 443 target.example.com", SRV, null, true},
|
||||
{"SRV: IP rejected", "10 20 443 192.168.1.1", SRV, null, true},
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// TXT record
|
||||
// ----------------------------------------------------------------
|
||||
{"TXT: trim", " hello world ", TXT, "hello world", false},
|
||||
{"TXT: already clean", "v=spf1 include:example.com ~all", TXT, "v=spf1 include:example.com ~all", false},
|
||||
{"TXT: special chars", "v=DKIM1; k=rsa; p=MIGf", TXT, "v=DKIM1; k=rsa; p=MIGf", false},
|
||||
{"TXT: unicode", "héllo wörld", TXT, "héllo wörld", false},
|
||||
{"TXT: multiple spaces", "key=value with spaces", TXT, "key=value with spaces", false},
|
||||
{"TXT: quoted", "\"quoted value\"", TXT, "\"quoted value\"", false},
|
||||
{"TXT: blank", " ", TXT, null, true},
|
||||
{"TXT: newline", "\n", TXT, null, true},
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNormalizeDnsRecordValue() {
|
||||
if (expectException) {
|
||||
try {
|
||||
DnsProviderUtil.normalizeDnsRecordValue(input, recordType);
|
||||
fail("Expected IllegalArgumentException for [" + description + "] input='" + input + "'");
|
||||
} catch (IllegalArgumentException ignored) {}
|
||||
} else {
|
||||
String result = DnsProviderUtil.normalizeDnsRecordValue(input, recordType);
|
||||
assertEquals(description, expected, result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,432 @@
|
|||
// 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.dns.powerdns;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.apache.cloudstack.dns.exception.DnsOperationException;
|
||||
import org.apache.cloudstack.dns.exception.DnsAuthenticationException;
|
||||
import org.apache.cloudstack.dns.exception.DnsConflictException;
|
||||
import org.apache.cloudstack.dns.exception.DnsNotFoundException;
|
||||
import org.apache.http.StatusLine;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.client.methods.HttpUriRequest;
|
||||
import org.apache.http.entity.StringEntity;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.invocation.InvocationOnMock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import org.mockito.stubbing.Answer;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class PowerDnsClientTest {
|
||||
|
||||
PowerDnsClient client;
|
||||
CloseableHttpClient httpClientMock;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
client = new PowerDnsClient();
|
||||
httpClientMock = mock(CloseableHttpClient.class);
|
||||
ReflectionTestUtils.setField(client, "httpClient", httpClientMock);
|
||||
}
|
||||
|
||||
private CloseableHttpResponse createResponse(int statusCode, String jsonBody) {
|
||||
CloseableHttpResponse responseMock = mock(CloseableHttpResponse.class);
|
||||
StatusLine statusLineMock = mock(StatusLine.class);
|
||||
when(responseMock.getStatusLine()).thenReturn(statusLineMock);
|
||||
when(statusLineMock.getStatusCode()).thenReturn(statusCode);
|
||||
|
||||
if (jsonBody != null) {
|
||||
when(responseMock.getEntity()).thenReturn(new StringEntity(jsonBody, StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
return responseMock;
|
||||
}
|
||||
|
||||
private void mockHttpResponse(int statusCode, String jsonBody) throws IOException {
|
||||
CloseableHttpResponse response = createResponse(statusCode, jsonBody);
|
||||
when(httpClientMock.execute(any(HttpUriRequest.class))).thenReturn(response);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNormalizeApexRecord() {
|
||||
String result = client.normalizeRecordName("@", "example.com");
|
||||
assertEquals("example.com.", result);
|
||||
|
||||
result = client.normalizeRecordName("", "example.com");
|
||||
assertEquals("example.com.", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNormalizeRelativeRecord() {
|
||||
String result = client.normalizeRecordName("www", "example.com");
|
||||
assertEquals("www.example.com.", result);
|
||||
|
||||
result = client.normalizeRecordName("WWW", "example.com"); // test case-insensitive
|
||||
assertEquals("www.example.com.", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNormalizeAbsoluteRecordWithinZone() {
|
||||
String result = client.normalizeRecordName("www.example.com.", "example.com");
|
||||
assertEquals("www.example.com.", result);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testNormalizeAbsoluteRecordOutsideZoneThrows() {
|
||||
client.normalizeRecordName("other.com.", "example.com");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNormalizeDottedNameWithoutTrailingDot() {
|
||||
String result = client.normalizeRecordName("api.test.com", "example.com");
|
||||
assertEquals("api.test.com.", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNormalizeRelativeSubdomain() {
|
||||
String result = client.normalizeRecordName("mail", "example.com");
|
||||
assertEquals("mail.example.com.", result);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testNormalizeNullRecordNameThrows() {
|
||||
client.normalizeRecordName(null, "example.com");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNormalizeZoneNormalization() {
|
||||
String result = client.normalizeRecordName("www", "Example.Com");
|
||||
assertEquals("www.example.com.", result);
|
||||
|
||||
result = client.normalizeRecordName("www", "example.com.");
|
||||
assertEquals("www.example.com.", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDiscoverAuthoritativeServerIdSuccess() throws Exception {
|
||||
mockHttpResponse(200, "[{\"id\":\"localhost\", \"daemon_type\":\"authoritative\"}]");
|
||||
String result = client.discoverAuthoritativeServerId("http://pdns:8081", null, "apikey");
|
||||
assertEquals("localhost", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDiscoverAuthoritativeServerIdFallback() throws Exception {
|
||||
mockHttpResponse(200, "[{\"id\":\"server1\", \"daemon_type\":\"recursor\"}, {\"id\":\"server2\", \"daemon_type\":\"authoritative\"}]");
|
||||
String result = client.discoverAuthoritativeServerId("http://pdns", 8081, "apikey");
|
||||
assertEquals("server2", result);
|
||||
}
|
||||
|
||||
@Test(expected = DnsOperationException.class)
|
||||
public void testDiscoverAuthoritativeServerIdEmpty() throws Exception {
|
||||
mockHttpResponse(200, "[]");
|
||||
client.discoverAuthoritativeServerId("http://pdns", 8081, "apikey");
|
||||
}
|
||||
|
||||
@Test(expected = DnsOperationException.class)
|
||||
public void testDiscoverAuthoritativeServerIdNoAuthoritative() throws Exception {
|
||||
mockHttpResponse(200, "[{\"id\":\"server1\", \"daemon_type\":\"recursor\"}]");
|
||||
client.discoverAuthoritativeServerId("http://pdns", 8081, "apikey");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateServerIdSuccess() throws Exception {
|
||||
mockHttpResponse(200, "{\"id\":\"abc\", \"daemon_type\":\"authoritative\"}");
|
||||
String result = client.validateServerId("http://pdns", 8081, "apikey", "abc");
|
||||
assertEquals("abc", result);
|
||||
}
|
||||
|
||||
@Test(expected = DnsOperationException.class)
|
||||
public void testValidateServerIdNotAuthoritative() throws Exception {
|
||||
mockHttpResponse(200, "{\"id\":\"abc\", \"daemon_type\":\"recursor\"}");
|
||||
client.validateServerId("http://pdns", 8081, "apikey", "abc");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolveServerIdWithExternalId() throws Exception {
|
||||
mockHttpResponse(200, "{\"id\":\"abc\", \"daemon_type\":\"authoritative\"}");
|
||||
String result = client.resolveServerId("http://pdns", 8081, "apikey", "abc");
|
||||
assertEquals("abc", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolveServerIdWithoutExternalId() throws Exception {
|
||||
mockHttpResponse(200, "[{\"id\":\"localhost\", \"daemon_type\":\"authoritative\"}]");
|
||||
String result = client.resolveServerId("http://pdns", 8081, "apikey", null);
|
||||
assertEquals("localhost", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateZone() throws Exception {
|
||||
when(httpClientMock.execute(any(HttpUriRequest.class))).thenAnswer(new Answer<CloseableHttpResponse>() {
|
||||
@Override
|
||||
public CloseableHttpResponse answer(InvocationOnMock invocation) {
|
||||
HttpUriRequest request = invocation.getArgument(0);
|
||||
if (request.getMethod().equals("GET")) {
|
||||
return createResponse(200, "{\"id\":\"abc\", \"daemon_type\":\"authoritative\"}");
|
||||
}
|
||||
if (request.getMethod().equals("POST")) {
|
||||
return createResponse(201, "{\"id\":\"example.com.\"}");
|
||||
}
|
||||
return createResponse(500, null);
|
||||
}
|
||||
});
|
||||
|
||||
String result = client.createZone("http://pdns", 8081, "apikey", "abc", "example.com", "Native", false, Arrays.asList("ns1.com"));
|
||||
assertEquals("example.com.", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateZone() throws Exception {
|
||||
when(httpClientMock.execute(any(HttpUriRequest.class))).thenAnswer(new Answer<CloseableHttpResponse>() {
|
||||
@Override
|
||||
public CloseableHttpResponse answer(InvocationOnMock invocation) {
|
||||
HttpUriRequest request = invocation.getArgument(0);
|
||||
if (request.getMethod().equals("GET")) {
|
||||
return createResponse(200, "{\"id\":\"abc\", \"daemon_type\":\"authoritative\"}");
|
||||
}
|
||||
if (request.getMethod().equals("PUT")) {
|
||||
return createResponse(204, null);
|
||||
}
|
||||
return createResponse(500, null);
|
||||
}
|
||||
});
|
||||
|
||||
client.updateZone("http://pdns", 8081, "apikey", "abc", "example.com", "Native", true, Arrays.asList("ns1.com"));
|
||||
// No exception means success
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteZone() throws Exception {
|
||||
when(httpClientMock.execute(any(HttpUriRequest.class))).thenAnswer(new Answer<CloseableHttpResponse>() {
|
||||
@Override
|
||||
public CloseableHttpResponse answer(InvocationOnMock invocation) {
|
||||
HttpUriRequest request = invocation.getArgument(0);
|
||||
if (request.getMethod().equals("GET")) {
|
||||
return createResponse(200, "{\"id\":\"abc\", \"daemon_type\":\"authoritative\"}");
|
||||
}
|
||||
if (request.getMethod().equals("DELETE")) {
|
||||
return createResponse(204, null);
|
||||
}
|
||||
return createResponse(500, null);
|
||||
}
|
||||
});
|
||||
|
||||
client.deleteZone("http://pdns", 8081, "apikey", "abc", "example.com");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testModifyRecord() throws Exception {
|
||||
when(httpClientMock.execute(any(HttpUriRequest.class))).thenAnswer(new Answer<CloseableHttpResponse>() {
|
||||
@Override
|
||||
public CloseableHttpResponse answer(InvocationOnMock invocation) {
|
||||
HttpUriRequest request = invocation.getArgument(0);
|
||||
if (request.getMethod().equals("GET")) {
|
||||
return createResponse(200, "{\"id\":\"abc\", \"daemon_type\":\"authoritative\"}");
|
||||
}
|
||||
if (request.getMethod().equals("PATCH")) {
|
||||
return createResponse(204, null);
|
||||
}
|
||||
return createResponse(500, null);
|
||||
}
|
||||
});
|
||||
|
||||
String result = client.modifyRecord("http://pdns", 8081, "apikey", "abc", "example.com", "www", "A", 300, Arrays.asList("1.2.3.4"), "REPLACE");
|
||||
assertEquals("www.example.com", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testModifyRecordApex() throws Exception {
|
||||
when(httpClientMock.execute(any(HttpUriRequest.class))).thenAnswer(new Answer<CloseableHttpResponse>() {
|
||||
@Override
|
||||
public CloseableHttpResponse answer(InvocationOnMock invocation) {
|
||||
HttpUriRequest request = invocation.getArgument(0);
|
||||
if (request.getMethod().equals("GET")) {
|
||||
return createResponse(200, "{\"id\":\"abc\", \"daemon_type\":\"authoritative\"}");
|
||||
}
|
||||
if (request.getMethod().equals("PATCH")) {
|
||||
return createResponse(204, null);
|
||||
}
|
||||
return createResponse(500, null);
|
||||
}
|
||||
});
|
||||
|
||||
String result = client.modifyRecord("http://pdns", 8081, "apikey", "abc", "example.com", "@", "A", 300, Arrays.asList("1.2.3.4"), "REPLACE");
|
||||
assertEquals("example.com", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testListRecords() throws Exception {
|
||||
when(httpClientMock.execute(any(HttpUriRequest.class))).thenAnswer(new Answer<CloseableHttpResponse>() {
|
||||
@Override
|
||||
public CloseableHttpResponse answer(InvocationOnMock invocation) {
|
||||
HttpUriRequest request = invocation.getArgument(0);
|
||||
// validateServerId uses /servers/abc
|
||||
// listRecords uses /servers/abc/zones/example.com.
|
||||
if (request.getURI().getPath().endsWith("abc")) {
|
||||
return createResponse(200, "{\"id\":\"abc\", \"daemon_type\":\"authoritative\"}");
|
||||
}
|
||||
if (request.getURI().getPath().endsWith("example.com.")) {
|
||||
return createResponse(200, "{\"rrsets\":[{\"name\":\"www.example.com.\",\"type\":\"A\"}]}");
|
||||
}
|
||||
return createResponse(500, null);
|
||||
}
|
||||
});
|
||||
|
||||
Iterable<JsonNode> records = client.listRecords("http://pdns", 8081, "apikey", "abc", "example.com");
|
||||
assertNotNull(records);
|
||||
assertTrue(records.iterator().hasNext());
|
||||
assertEquals("www.example.com.", records.iterator().next().path("name").asText());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testListRecordsEmpty() throws Exception {
|
||||
when(httpClientMock.execute(any(HttpUriRequest.class))).thenAnswer(new Answer<CloseableHttpResponse>() {
|
||||
@Override
|
||||
public CloseableHttpResponse answer(InvocationOnMock invocation) {
|
||||
HttpUriRequest request = invocation.getArgument(0);
|
||||
if (request.getURI().getPath().endsWith("abc")) {
|
||||
return createResponse(200, "{\"id\":\"abc\", \"daemon_type\":\"authoritative\"}");
|
||||
}
|
||||
if (request.getURI().getPath().endsWith("example.com.")) {
|
||||
return createResponse(200, "{}");
|
||||
}
|
||||
return createResponse(500, null);
|
||||
}
|
||||
});
|
||||
|
||||
Iterable<JsonNode> records = client.listRecords("http://pdns", 8081, "apikey", "abc", "example.com");
|
||||
assertNotNull(records);
|
||||
assertTrue(!records.iterator().hasNext());
|
||||
}
|
||||
|
||||
@Test(expected = DnsNotFoundException.class)
|
||||
public void testExecuteThrowsNotFound() throws Exception {
|
||||
mockHttpResponse(404, "Not Found");
|
||||
client.validateServerId("http://pdns", 8081, "apikey", "abc");
|
||||
}
|
||||
|
||||
@Test(expected = DnsAuthenticationException.class)
|
||||
public void testExecuteThrowsAuthError() throws Exception {
|
||||
mockHttpResponse(401, "Unauthorized");
|
||||
client.validateServerId("http://pdns", 8081, "apikey", "abc");
|
||||
}
|
||||
|
||||
@Test(expected = DnsConflictException.class)
|
||||
public void testExecuteThrowsConflictError() throws Exception {
|
||||
mockHttpResponse(409, "Conflict");
|
||||
client.validateServerId("http://pdns", 8081, "apikey", "abc");
|
||||
}
|
||||
|
||||
@Test(expected = DnsOperationException.class)
|
||||
public void testExecuteThrowsUnexpectedStatus() throws Exception {
|
||||
mockHttpResponse(500, "Server Error");
|
||||
client.validateServerId("http://pdns", 8081, "apikey", "abc");
|
||||
}
|
||||
// Route helper: GET /servers/abc → validate; GET /zones/... → zone response
|
||||
private void mockRecordExists(String zoneJson) throws IOException {
|
||||
when(httpClientMock.execute(any(HttpUriRequest.class))).thenAnswer(new Answer<CloseableHttpResponse>() {
|
||||
@Override
|
||||
public CloseableHttpResponse answer(InvocationOnMock invocation) {
|
||||
HttpUriRequest request = invocation.getArgument(0);
|
||||
String path = request.getURI().getPath();
|
||||
if (path.endsWith("/abc")) {
|
||||
return createResponse(200, "{\"id\":\"abc\", \"daemon_type\":\"authoritative\"}");
|
||||
}
|
||||
// zone query (contains /zones/)
|
||||
if (zoneJson == null) {
|
||||
return createResponse(200, null); // empty body → execute() returns null
|
||||
}
|
||||
return createResponse(200, zoneJson);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRecordExistsZoneNodeNull() throws Exception {
|
||||
// execute() returns null → zoneNode == null → false
|
||||
mockRecordExists(null);
|
||||
boolean result = client.recordExists("http://pdns", 8081, "apikey", "abc", "example.com", "www", "A");
|
||||
assertEquals(false, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRecordExistsMissingRrSetsField() throws Exception {
|
||||
// response has no "rrsets" key → !zoneNode.has(RR_SETS) → false
|
||||
mockRecordExists("{}");
|
||||
boolean result = client.recordExists("http://pdns", 8081, "apikey", "abc", "example.com", "www", "A");
|
||||
assertEquals(false, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRecordExistsRrSetsNotArray() throws Exception {
|
||||
// rrsets is a scalar string, not an ArrayNode → isArray() == false → false
|
||||
mockRecordExists("{\"rrsets\":\"not-an-array\"}");
|
||||
boolean result = client.recordExists("http://pdns", 8081, "apikey", "abc", "example.com", "www", "A");
|
||||
assertEquals(false, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRecordExistsEmptyRrSetsArray() throws Exception {
|
||||
// rrsets is an empty array → isArray() == true && isEmpty() == true → false
|
||||
mockRecordExists("{\"rrsets\":[]}");
|
||||
boolean result = client.recordExists("http://pdns", 8081, "apikey", "abc", "example.com", "www", "A");
|
||||
assertEquals(false, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRecordExistsNonEmptyRrSetsArray() throws Exception {
|
||||
// rrsets is a non-empty array → isArray() == true && !isEmpty() → true
|
||||
mockRecordExists("{\"rrsets\":[{\"name\":\"www.example.com.\",\"type\":\"A\"}]}");
|
||||
boolean result = client.recordExists("http://pdns", 8081, "apikey", "abc", "example.com", "www", "A");
|
||||
assertEquals(true, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCloseSucceeds() throws Exception {
|
||||
// httpClient.close() completes normally → no exception propagated
|
||||
CloseableHttpClient mockClient = mock(CloseableHttpClient.class);
|
||||
ReflectionTestUtils.setField(client, "httpClient", mockClient);
|
||||
client.close();
|
||||
org.mockito.Mockito.verify(mockClient).close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCloseSwallowsIOException() throws Exception {
|
||||
// httpClient.close() throws IOException → caught and logged (warn), no rethrow
|
||||
CloseableHttpClient mockClient = mock(CloseableHttpClient.class);
|
||||
org.mockito.Mockito.doThrow(new IOException("connection reset")).when(mockClient).close();
|
||||
ReflectionTestUtils.setField(client, "httpClient", mockClient);
|
||||
client.close(); // must NOT throw
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,391 @@
|
|||
// 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.dns.powerdns;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.anyList;
|
||||
import static org.mockito.ArgumentMatchers.anyLong;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.cloudstack.dns.DnsRecord;
|
||||
import org.apache.cloudstack.dns.DnsRecord.RecordType;
|
||||
import org.apache.cloudstack.dns.DnsServer;
|
||||
import org.apache.cloudstack.dns.DnsZone;
|
||||
import org.apache.cloudstack.dns.DnsProviderType;
|
||||
import org.apache.cloudstack.dns.exception.DnsProviderException;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.node.ArrayNode;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class PowerDnsProviderTest {
|
||||
|
||||
private static final ObjectMapper MAPPER = new ObjectMapper();
|
||||
|
||||
private PowerDnsProvider provider;
|
||||
private PowerDnsClient clientMock;
|
||||
private DnsServer serverMock;
|
||||
private DnsZone zoneMock;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
provider = new PowerDnsProvider();
|
||||
clientMock = mock(PowerDnsClient.class);
|
||||
serverMock = mock(DnsServer.class);
|
||||
zoneMock = mock(DnsZone.class);
|
||||
ReflectionTestUtils.setField(provider, "client", clientMock);
|
||||
|
||||
when(serverMock.getUrl()).thenReturn("http://pdns:8081");
|
||||
when(serverMock.getDnsApiKey()).thenReturn("secret");
|
||||
when(serverMock.getPort()).thenReturn(8081);
|
||||
when(serverMock.getDetail(PowerDnsProvider.PDNS_SERVER_ID)).thenReturn("localhost");
|
||||
when(serverMock.getNameServers()).thenReturn(Arrays.asList("ns1.example.com"));
|
||||
|
||||
when(zoneMock.getName()).thenReturn("example.com");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetProviderType() {
|
||||
assertEquals(DnsProviderType.PowerDNS, provider.getProviderType());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConfigureCreatesClientWhenNull() {
|
||||
PowerDnsProvider freshProvider = new PowerDnsProvider();
|
||||
boolean result = freshProvider.configure("test", new HashMap<>());
|
||||
assertTrue(result);
|
||||
assertNotNull(ReflectionTestUtils.getField(freshProvider, "client"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConfigureDoesNotReplaceExistingClient() {
|
||||
PowerDnsClient existingClient = mock(PowerDnsClient.class);
|
||||
ReflectionTestUtils.setField(provider, "client", existingClient);
|
||||
|
||||
boolean result = provider.configure("test", new HashMap<>());
|
||||
|
||||
assertTrue(result);
|
||||
assertEquals(existingClient, ReflectionTestUtils.getField(provider, "client"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStopClosesClient() {
|
||||
boolean result = provider.stop();
|
||||
assertTrue(result);
|
||||
verify(clientMock, times(1)).close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStopWithNullClientSucceeds() {
|
||||
ReflectionTestUtils.setField(provider, "client", null);
|
||||
boolean result = provider.stop();
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testValidateServerFieldsNullUrl() {
|
||||
when(serverMock.getUrl()).thenReturn(null);
|
||||
provider.validateRequiredServerFields(serverMock);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testValidateServerFieldsBlankUrl() {
|
||||
when(serverMock.getUrl()).thenReturn(" ");
|
||||
provider.validateRequiredServerFields(serverMock);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testValidateServerFieldsNullApiKey() {
|
||||
when(serverMock.getDnsApiKey()).thenReturn(null);
|
||||
provider.validateRequiredServerFields(serverMock);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testValidateServerFieldsBlankApiKey() {
|
||||
when(serverMock.getDnsApiKey()).thenReturn("");
|
||||
provider.validateRequiredServerFields(serverMock);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testValidateServerAndZoneFieldsBlankZoneName() {
|
||||
when(zoneMock.getName()).thenReturn(" ");
|
||||
provider.validateRequiredServerAndZoneFields(serverMock, zoneMock);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testValidateServerAndZoneFieldsNullZoneName() {
|
||||
when(zoneMock.getName()).thenReturn(null);
|
||||
provider.validateRequiredServerAndZoneFields(serverMock, zoneMock);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateDelegatesToClient() throws DnsProviderException {
|
||||
when(clientMock.validateServerId(anyString(), anyInt(), anyString(), anyString())).thenReturn("localhost");
|
||||
provider.validate(serverMock);
|
||||
verify(clientMock).validateServerId("http://pdns:8081", 8081, "secret", "localhost");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testValidateThrowsWhenServerUrlBlank() throws DnsProviderException {
|
||||
when(serverMock.getUrl()).thenReturn("");
|
||||
provider.validate(serverMock);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateAndResolveServer() throws Exception {
|
||||
when(clientMock.resolveServerId(anyString(), anyInt(), anyString(), anyString())).thenReturn("localhost");
|
||||
String result = provider.validateAndResolveServer(serverMock);
|
||||
assertEquals("localhost", result);
|
||||
verify(clientMock).resolveServerId("http://pdns:8081", 8081, "secret", "localhost");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testValidateAndResolveServerThrowsWhenUrlBlank() throws Exception {
|
||||
when(serverMock.getUrl()).thenReturn(null);
|
||||
provider.validateAndResolveServer(serverMock);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProvisionZoneDelegatesToClient() throws DnsProviderException {
|
||||
when(clientMock.createZone(anyString(), anyInt(), anyString(), anyString(), anyString(), anyString(), eq(false), anyList())).thenReturn("example.com.");
|
||||
String zoneId = provider.provisionZone(serverMock, zoneMock);
|
||||
assertEquals("example.com.", zoneId);
|
||||
verify(clientMock).createZone("http://pdns:8081", 8081, "secret", "localhost", "example.com",
|
||||
"Native", false, Arrays.asList("ns1.example.com"));
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testProvisionZoneThrowsWhenZoneNameBlank() throws DnsProviderException {
|
||||
when(zoneMock.getName()).thenReturn(null);
|
||||
provider.provisionZone(serverMock, zoneMock);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteZoneDelegatesToClient() throws DnsProviderException {
|
||||
provider.deleteZone(serverMock, zoneMock);
|
||||
verify(clientMock).deleteZone("http://pdns:8081", 8081, "secret", "localhost", "example.com");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testDeleteZoneThrowsWhenZoneNameBlank() throws DnsProviderException {
|
||||
when(zoneMock.getName()).thenReturn("");
|
||||
provider.deleteZone(serverMock, zoneMock);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateZoneDelegatesToClient() throws DnsProviderException {
|
||||
provider.updateZone(serverMock, zoneMock);
|
||||
verify(clientMock).updateZone("http://pdns:8081", 8081, "secret", "localhost", "example.com",
|
||||
"Native", false, Arrays.asList("ns1.example.com"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddRecordDelegatesToClient() throws DnsProviderException {
|
||||
DnsRecord record = new DnsRecord("www", RecordType.A, Arrays.asList("1.2.3.4"), 300);
|
||||
when(clientMock.modifyRecord(anyString(), anyInt(), anyString(), anyString(), anyString(),
|
||||
anyString(), anyString(), anyLong(), anyList(), anyString())).thenReturn("www.example.com");
|
||||
|
||||
String result = provider.addRecord(serverMock, zoneMock, record);
|
||||
|
||||
assertEquals("www.example.com", result);
|
||||
verify(clientMock).modifyRecord("http://pdns:8081", 8081, "secret", "localhost", "example.com",
|
||||
"www", "A", 300L, Arrays.asList("1.2.3.4"), "REPLACE");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testAddRecordThrowsWhenServerUrlBlank() throws DnsProviderException {
|
||||
when(serverMock.getUrl()).thenReturn("");
|
||||
DnsRecord record = new DnsRecord("www", RecordType.A, Arrays.asList("1.2.3.4"), 300);
|
||||
provider.addRecord(serverMock, zoneMock, record);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateRecordDelegatesToAddRecord() throws DnsProviderException {
|
||||
DnsRecord record = new DnsRecord("mail", RecordType.MX, Arrays.asList("10 mail.example.com"), 300);
|
||||
when(clientMock.modifyRecord(anyString(), anyInt(), anyString(), anyString(), anyString(),
|
||||
anyString(), anyString(), anyLong(), anyList(), anyString())).thenReturn("mail.example.com");
|
||||
|
||||
String result = provider.updateRecord(serverMock, zoneMock, record);
|
||||
|
||||
assertEquals("mail.example.com", result);
|
||||
verify(clientMock).modifyRecord(anyString(), anyInt(), anyString(), anyString(), anyString(),
|
||||
eq("mail"), eq("MX"), eq(300L), eq(Arrays.asList("10 mail.example.com")), eq("REPLACE"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteRecordDelegatesToClientWithDeleteChangeType() throws DnsProviderException {
|
||||
DnsRecord record = new DnsRecord("old", RecordType.CNAME, Arrays.asList("target.com"), 600);
|
||||
when(clientMock.modifyRecord(anyString(), anyInt(), anyString(), anyString(), anyString(),
|
||||
anyString(), anyString(), anyLong(), anyList(), anyString())).thenReturn("old.example.com");
|
||||
|
||||
String result = provider.deleteRecord(serverMock, zoneMock, record);
|
||||
|
||||
assertEquals("old.example.com", result);
|
||||
verify(clientMock).modifyRecord(anyString(), anyInt(), anyString(), anyString(), anyString(),
|
||||
eq("old"), eq("CNAME"), eq(600L), eq(Arrays.asList("target.com")), eq("DELETE"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testApplyRecordPassesChangeTypeToClient() throws DnsProviderException {
|
||||
DnsRecord record = new DnsRecord("txt", RecordType.TXT, Arrays.asList("v=spf1 include:example.com ~all"), 3600);
|
||||
when(clientMock.modifyRecord(anyString(), anyInt(), anyString(), anyString(), anyString(),
|
||||
anyString(), anyString(), anyLong(), anyList(), anyString())).thenReturn("txt.example.com");
|
||||
|
||||
provider.applyRecord("http://pdns:8081", 8081, "secret", "localhost", "example.com",
|
||||
record, PowerDnsProvider.ChangeType.REPLACE);
|
||||
|
||||
verify(clientMock).modifyRecord("http://pdns:8081", 8081, "secret", "localhost", "example.com",
|
||||
"txt", "TXT", 3600L, Arrays.asList("v=spf1 include:example.com ~all"), "REPLACE");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testListRecordsParsesRrsets() throws DnsProviderException {
|
||||
ObjectNode aRecord = MAPPER.createObjectNode();
|
||||
aRecord.put("name", "www.example.com.");
|
||||
aRecord.put("type", "A");
|
||||
aRecord.put("ttl", 300);
|
||||
ArrayNode records = aRecord.putArray("records");
|
||||
records.addObject().put("content", "1.2.3.4");
|
||||
|
||||
ObjectNode mxRecord = MAPPER.createObjectNode();
|
||||
mxRecord.put("name", "example.com.");
|
||||
mxRecord.put("type", "MX");
|
||||
mxRecord.put("ttl", 600);
|
||||
ArrayNode mxRecords = mxRecord.putArray("records");
|
||||
mxRecords.addObject().put("content", "10 mail.example.com");
|
||||
|
||||
when(clientMock.listRecords(anyString(), anyInt(), anyString(), anyString(), anyString()))
|
||||
.thenReturn(Arrays.asList(aRecord, mxRecord));
|
||||
|
||||
List<DnsRecord> result = provider.listRecords(serverMock, zoneMock);
|
||||
|
||||
assertEquals(2, result.size());
|
||||
|
||||
DnsRecord first = result.get(0);
|
||||
assertEquals("www.example.com.", first.getName());
|
||||
assertEquals(RecordType.A, first.getType());
|
||||
assertEquals(300, first.getTtl());
|
||||
assertEquals(Arrays.asList("1.2.3.4"), first.getContents());
|
||||
|
||||
DnsRecord second = result.get(1);
|
||||
assertEquals("example.com.", second.getName());
|
||||
assertEquals(RecordType.MX, second.getType());
|
||||
assertEquals(600, second.getTtl());
|
||||
assertEquals(Arrays.asList("10 mail.example.com"), second.getContents());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testListRecordsSkipsSoaRecords() throws DnsProviderException {
|
||||
ObjectNode soaRecord = MAPPER.createObjectNode();
|
||||
soaRecord.put("name", "example.com.");
|
||||
soaRecord.put("type", "SOA");
|
||||
soaRecord.put("ttl", 3600);
|
||||
soaRecord.putArray("records").addObject().put("content", "ns1.example.com. admin.example.com. ...");
|
||||
|
||||
when(clientMock.listRecords(anyString(), anyInt(), anyString(), anyString(), anyString()))
|
||||
.thenReturn(Collections.singletonList(soaRecord));
|
||||
|
||||
List<DnsRecord> result = provider.listRecords(serverMock, zoneMock);
|
||||
assertTrue(result.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testListRecordsSkipsUnknownRecordTypes() throws DnsProviderException {
|
||||
ObjectNode unknownRecord = MAPPER.createObjectNode();
|
||||
unknownRecord.put("name", "test.example.com.");
|
||||
unknownRecord.put("type", "UNKNOWNTYPE");
|
||||
unknownRecord.put("ttl", 300);
|
||||
unknownRecord.putArray("records").addObject().put("content", "some-data");
|
||||
|
||||
when(clientMock.listRecords(anyString(), anyInt(), anyString(), anyString(), anyString()))
|
||||
.thenReturn(Collections.singletonList(unknownRecord));
|
||||
|
||||
List<DnsRecord> result = provider.listRecords(serverMock, zoneMock);
|
||||
assertTrue(result.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testListRecordsIgnoresEmptyContentEntries() throws DnsProviderException {
|
||||
ObjectNode aRecord = MAPPER.createObjectNode();
|
||||
aRecord.put("name", "host.example.com.");
|
||||
aRecord.put("type", "A");
|
||||
aRecord.put("ttl", 300);
|
||||
ArrayNode records = aRecord.putArray("records");
|
||||
records.addObject().put("content", "");
|
||||
records.addObject().put("content", "5.6.7.8");
|
||||
|
||||
when(clientMock.listRecords(anyString(), anyInt(), anyString(), anyString(), anyString()))
|
||||
.thenReturn(Collections.singletonList(aRecord));
|
||||
|
||||
List<DnsRecord> result = provider.listRecords(serverMock, zoneMock);
|
||||
assertEquals(1, result.size());
|
||||
assertEquals(Collections.singletonList("5.6.7.8"), result.get(0).getContents());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testListRecordsReturnsEmptyListWhenClientReturnsEmpty() throws DnsProviderException {
|
||||
when(clientMock.listRecords(anyString(), anyInt(), anyString(), anyString(), anyString()))
|
||||
.thenReturn(Collections.emptyList());
|
||||
|
||||
List<DnsRecord> result = provider.listRecords(serverMock, zoneMock);
|
||||
assertNotNull(result);
|
||||
assertTrue(result.isEmpty());
|
||||
}
|
||||
|
||||
@Test(expected = DnsProviderException.class)
|
||||
public void testListRecordsPropagatesClientException() throws DnsProviderException {
|
||||
when(clientMock.listRecords(anyString(), anyInt(), anyString(), anyString(), anyString()))
|
||||
.thenThrow(mock(DnsProviderException.class));
|
||||
|
||||
provider.listRecords(serverMock, zoneMock);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testListRecordsThrowsWhenZoneNameBlank() throws DnsProviderException {
|
||||
when(zoneMock.getName()).thenReturn("");
|
||||
provider.listRecords(serverMock, zoneMock);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testChangeTypeValues() {
|
||||
assertEquals("REPLACE", PowerDnsProvider.ChangeType.REPLACE.name());
|
||||
assertEquals("DELETE", PowerDnsProvider.ChangeType.DELETE.name());
|
||||
}
|
||||
}
|
||||
|
|
@ -153,6 +153,7 @@
|
|||
|
||||
<module>user-two-factor-authenticators/totp</module>
|
||||
<module>user-two-factor-authenticators/static-pin</module>
|
||||
<module>dns/powerdns</module>
|
||||
|
||||
</modules>
|
||||
<dependencies>
|
||||
|
|
|
|||
|
|
@ -28,6 +28,9 @@ import org.apache.cloudstack.acl.RolePermissionEntity;
|
|||
import org.apache.cloudstack.acl.SecurityChecker;
|
||||
import org.apache.cloudstack.affinity.AffinityGroup;
|
||||
import org.apache.cloudstack.context.CallContext;
|
||||
import org.apache.cloudstack.dns.DnsProviderManager;
|
||||
import org.apache.cloudstack.dns.DnsServer;
|
||||
import org.apache.cloudstack.dns.DnsZone;
|
||||
import org.apache.cloudstack.query.QueryService;
|
||||
import org.apache.cloudstack.resourcedetail.dao.DiskOfferingDetailsDao;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
|
@ -101,6 +104,8 @@ public class DomainChecker extends AdapterBase implements SecurityChecker {
|
|||
private ProjectDao projectDao;
|
||||
@Inject
|
||||
private AccountService accountService;
|
||||
@Inject
|
||||
private DnsProviderManager dnsProviderManager;
|
||||
|
||||
protected DomainChecker() {
|
||||
super();
|
||||
|
|
@ -216,7 +221,11 @@ public class DomainChecker extends AdapterBase implements SecurityChecker {
|
|||
_networkMgr.checkRouterPermissions(caller, (VirtualRouter)entity);
|
||||
} else if (entity instanceof AffinityGroup) {
|
||||
return false;
|
||||
} else {
|
||||
} else if (entity instanceof DnsServer) {
|
||||
dnsProviderManager.checkDnsServerPermission(caller, (DnsServer) entity);
|
||||
} else if (entity instanceof DnsZone) {
|
||||
dnsProviderManager.checkDnsZonePermission(caller, (DnsZone) entity);
|
||||
} else {
|
||||
validateCallerHasAccessToEntityOwner(caller, entity, accessType);
|
||||
}
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -80,6 +80,10 @@ import org.apache.cloudstack.backup.dao.BackupOfferingDao;
|
|||
import org.apache.cloudstack.backup.dao.BackupRepositoryDao;
|
||||
import org.apache.cloudstack.backup.dao.BackupScheduleDao;
|
||||
import org.apache.cloudstack.context.CallContext;
|
||||
import org.apache.cloudstack.dns.dao.DnsZoneDao;
|
||||
import org.apache.cloudstack.dns.dao.DnsZoneNetworkMapDao;
|
||||
import org.apache.cloudstack.dns.vo.DnsZoneNetworkMapVO;
|
||||
import org.apache.cloudstack.dns.vo.DnsZoneVO;
|
||||
import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
|
||||
import org.apache.cloudstack.engine.orchestration.service.VolumeOrchestrationService;
|
||||
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
|
||||
|
|
@ -363,6 +367,7 @@ import org.apache.cloudstack.acl.dao.ApiKeyPairDao;
|
|||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.logging.log4j.util.Strings;
|
||||
|
||||
public class ApiDBUtils {
|
||||
private static final Logger log = LogManager.getLogger(ApiDBUtils.class);
|
||||
|
|
@ -504,6 +509,8 @@ public class ApiDBUtils {
|
|||
static SharedFSJoinDao s_sharedFSJoinDao;
|
||||
|
||||
static BucketDao s_bucketDao;
|
||||
static DnsZoneDao s_dnsZoneDao;
|
||||
static DnsZoneNetworkMapDao s_dnsZoneNetworkMapDao;
|
||||
static VirtualMachineManager s_virtualMachineManager;
|
||||
|
||||
@Inject
|
||||
|
|
@ -776,6 +783,10 @@ public class ApiDBUtils {
|
|||
private VirtualMachineManager virtualMachineManager;
|
||||
@Inject
|
||||
private SharedFSJoinDao sharedFSJoinDao;
|
||||
@Inject
|
||||
private DnsZoneDao dnsZoneDao;
|
||||
@Inject
|
||||
private DnsZoneNetworkMapDao dnsZoneNetworkMapDao;
|
||||
|
||||
@PostConstruct
|
||||
void init() {
|
||||
|
|
@ -914,6 +925,8 @@ public class ApiDBUtils {
|
|||
s_bucketDao = bucketDao;
|
||||
s_virtualMachineManager = virtualMachineManager;
|
||||
s_sharedFSJoinDao = sharedFSJoinDao;
|
||||
s_dnsZoneDao = dnsZoneDao;
|
||||
s_dnsZoneNetworkMapDao = dnsZoneNetworkMapDao;
|
||||
}
|
||||
|
||||
// ///////////////////////////////////////////////////////////
|
||||
|
|
@ -2296,6 +2309,17 @@ public class ApiDBUtils {
|
|||
return details.isEmpty() ? null : details;
|
||||
}
|
||||
|
||||
public static Pair<String, String> findDnsZoneByNetworkId(long networkId) {
|
||||
DnsZoneNetworkMapVO dnsNetworkMapVO = s_dnsZoneNetworkMapDao.findByNetworkId(networkId);
|
||||
if (dnsNetworkMapVO != null) {
|
||||
DnsZoneVO dnsZoneVO = s_dnsZoneDao.findById(dnsNetworkMapVO.getDnsZoneId());
|
||||
if (Strings.isNotBlank(dnsZoneVO.getName())) {
|
||||
return new Pair<> (dnsZoneVO.getName(), dnsNetworkMapVO.getSubDomain());
|
||||
}
|
||||
}
|
||||
return new Pair<>(null, null);
|
||||
}
|
||||
|
||||
public static boolean isAdmin(Account account) {
|
||||
return s_accountService.isAdmin(account.getId());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -549,6 +549,7 @@ public class ApiResponseHelper implements ResponseGenerator, ResourceIdSupport {
|
|||
@Inject
|
||||
AsyncJobDao asyncJobDao;
|
||||
|
||||
|
||||
public static String getPrettyDomainPath(String path) {
|
||||
if (path == null) {
|
||||
return null;
|
||||
|
|
@ -2657,6 +2658,14 @@ public class ApiResponseHelper implements ResponseGenerator, ResourceIdSupport {
|
|||
response.setDetails(details);
|
||||
}
|
||||
|
||||
Pair<String, String> dnsZoneAndSubDomain = ApiDBUtils.findDnsZoneByNetworkId(network.getId());
|
||||
if (StringUtils.isNotBlank(dnsZoneAndSubDomain.first())) {
|
||||
response.setDnsZone(dnsZoneAndSubDomain.first());
|
||||
}
|
||||
if (StringUtils.isNotBlank(dnsZoneAndSubDomain.second())) {
|
||||
response.setDnsSubdomain(dnsZoneAndSubDomain.second());
|
||||
}
|
||||
|
||||
DataCenter zone = ApiDBUtils.findZoneById(network.getDataCenterId());
|
||||
if (zone != null) {
|
||||
response.setZoneId(zone.getUuid());
|
||||
|
|
|
|||
|
|
@ -360,6 +360,7 @@ public class UserVmJoinDaoImpl extends GenericDaoBaseWithTagInformation<UserVmJo
|
|||
nicResponse.setIp6Gateway(userVm.getIp6Gateway());
|
||||
nicResponse.setIp6Cidr(userVm.getIp6Cidr());
|
||||
nicResponse.setEnabled(userVm.isNicEnabled());
|
||||
nicResponse.setNicDnsName(userVm.getNicDnsName());
|
||||
if (userVm.getBroadcastUri() != null) {
|
||||
nicResponse.setBroadcastUri(userVm.getBroadcastUri().toString());
|
||||
}
|
||||
|
|
@ -621,6 +622,9 @@ public class UserVmJoinDaoImpl extends GenericDaoBaseWithTagInformation<UserVmJo
|
|||
nicResponse.setIp6Gateway(uvo.getIp6Gateway());
|
||||
/*13: IPv6Cidr*/
|
||||
nicResponse.setIp6Cidr(uvo.getIp6Cidr());
|
||||
/* dnsRecordUrl */
|
||||
nicResponse.setNicDnsName(uvo.getNicDnsName());
|
||||
|
||||
/*14: deviceId*/
|
||||
// where do we find nicResponse.setDeviceId(
|
||||
// this is probably not String.valueOf(uvo.getNicId())); as this is a db-id
|
||||
|
|
|
|||
|
|
@ -32,21 +32,22 @@ import javax.persistence.Temporal;
|
|||
import javax.persistence.TemporalType;
|
||||
import javax.persistence.Transient;
|
||||
|
||||
import org.apache.cloudstack.util.HypervisorTypeConverter;
|
||||
|
||||
import com.cloud.host.Status;
|
||||
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||
import com.cloud.network.Network.GuestType;
|
||||
import com.cloud.network.Networks.TrafficType;
|
||||
import com.cloud.resource.ResourceState;
|
||||
import com.cloud.storage.Storage;
|
||||
import com.cloud.storage.Storage.TemplateType;
|
||||
import com.cloud.storage.Storage.StoragePoolType;
|
||||
import com.cloud.storage.Storage.TemplateType;
|
||||
import com.cloud.storage.Volume;
|
||||
import com.cloud.user.Account;
|
||||
import com.cloud.util.StoragePoolTypeConverter;
|
||||
import com.cloud.utils.db.GenericDao;
|
||||
import com.cloud.vm.VirtualMachine;
|
||||
import com.cloud.vm.VirtualMachine.State;
|
||||
import org.apache.cloudstack.util.HypervisorTypeConverter;
|
||||
|
||||
@Entity
|
||||
@Table(name = "user_vm_view")
|
||||
|
|
@ -404,6 +405,9 @@ public class UserVmJoinVO extends BaseViewWithTagInformationVO implements Contro
|
|||
@Column(name = "public_ip_address")
|
||||
private String publicIpAddress;
|
||||
|
||||
@Column(name = "nic_dns_name")
|
||||
private String nicDnsName;
|
||||
|
||||
@Column(name = "user_data", updatable = true, nullable = true, length = 2048)
|
||||
private String userData;
|
||||
|
||||
|
|
@ -1103,4 +1107,8 @@ public class UserVmJoinVO extends BaseViewWithTagInformationVO implements Contro
|
|||
public boolean isNicEnabled() {
|
||||
return isNicEnabled;
|
||||
}
|
||||
|
||||
public String getNicDnsName() {
|
||||
return nicDnsName;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -315,7 +315,7 @@ public class FirewallManagerImpl extends ManagerBase implements FirewallService,
|
|||
|
||||
sb.and("id", sb.entity().getId(), Op.EQ);
|
||||
sb.and("trafficType", sb.entity().getTrafficType(), Op.EQ);
|
||||
sb.and("networkId", sb.entity().getNetworkId(), Op.EQ);
|
||||
sb.and("networkId", sb.entity().getNetworkId(), Op.EQ);
|
||||
sb.and("ip", sb.entity().getSourceIpAddressId(), Op.EQ);
|
||||
sb.and("purpose", sb.entity().getPurpose(), Op.EQ);
|
||||
sb.and("display", sb.entity().isDisplay(), Op.EQ);
|
||||
|
|
|
|||
|
|
@ -96,6 +96,8 @@ import org.apache.cloudstack.auth.UserTwoFactorAuthenticator;
|
|||
import org.apache.cloudstack.backup.BackupOffering;
|
||||
import org.apache.cloudstack.config.ApiServiceConfiguration;
|
||||
import org.apache.cloudstack.context.CallContext;
|
||||
import org.apache.cloudstack.dns.DnsServer;
|
||||
import org.apache.cloudstack.dns.DnsZone;
|
||||
import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
|
||||
import org.apache.cloudstack.framework.config.ConfigKey;
|
||||
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
|
||||
|
|
@ -775,7 +777,8 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
|
|||
}
|
||||
if (entity.getAccountId() != -1 && domainId != -1 && !(entity instanceof VirtualMachineTemplate)
|
||||
&& !(entity instanceof Network && (accessType == AccessType.UseEntry || accessType == AccessType.OperateEntry))
|
||||
&& !(entity instanceof AffinityGroup) && !(entity instanceof VirtualRouter)) {
|
||||
&& !(entity instanceof AffinityGroup) && !(entity instanceof VirtualRouter)
|
||||
&& !(entity instanceof DnsServer) && !(entity instanceof DnsZone)) {
|
||||
List<ControlledEntity> toBeChecked = domains.get(entity.getDomainId());
|
||||
// for templates, we don't have to do cross domains check
|
||||
if (toBeChecked == null) {
|
||||
|
|
|
|||
|
|
@ -16,9 +16,15 @@
|
|||
// under the License.
|
||||
package com.cloud.vm;
|
||||
|
||||
import static com.cloud.event.EventTypes.EVENT_NIC_CREATE;
|
||||
import static com.cloud.event.EventTypes.EVENT_NIC_DELETE;
|
||||
import static com.cloud.event.EventTypes.EVENT_NIC_UPDATE;
|
||||
import static com.cloud.event.EventTypes.EVENT_VM_UPDATE;
|
||||
import static com.cloud.hypervisor.Hypervisor.HypervisorType.Functionality;
|
||||
import static com.cloud.storage.Volume.IOPS_LIMIT;
|
||||
import static com.cloud.utils.NumbersUtil.toHumanReadableSize;
|
||||
import static com.cloud.vm.VirtualMachineManager.Topics.VM_ACTION;
|
||||
import static com.cloud.vm.VirtualMachineManager.Topics.VM_LIFECYCLE_STATE;
|
||||
import static org.apache.cloudstack.api.ApiConstants.MAX_IOPS;
|
||||
import static org.apache.cloudstack.api.ApiConstants.MIN_IOPS;
|
||||
|
||||
|
|
@ -159,6 +165,7 @@ import org.apache.commons.lang3.ObjectUtils;
|
|||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
import org.apache.logging.log4j.util.Strings;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
|
|
@ -1447,7 +1454,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
}
|
||||
|
||||
@Override
|
||||
@ActionEvent(eventType = EventTypes.EVENT_NIC_CREATE, eventDescription = "Creating NIC", async = true)
|
||||
@ActionEvent(eventType = EVENT_NIC_CREATE, eventDescription = "Creating NIC", async = true)
|
||||
public UserVm addNicToVirtualMachine(AddNicToVMCmd cmd) throws InvalidParameterValueException, PermissionDeniedException, CloudRuntimeException {
|
||||
Long vmId = cmd.getVmId();
|
||||
Long networkId = cmd.getNetworkId();
|
||||
|
|
@ -1549,9 +1556,59 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
}
|
||||
CallContext.current().putContextParameter(Nic.class, guestNic.getUuid());
|
||||
logger.debug(String.format("Successful addition of %s from %s through %s", network, vmInstance, guestNic));
|
||||
publishNicEventMessageBus(vmInstance.getId(), vmInstance.getAccountId(), guestNic.getId(), EVENT_NIC_CREATE);
|
||||
return _vmDao.findById(vmInstance.getId());
|
||||
}
|
||||
|
||||
private void publishVmLifecycleMessageBus(UserVm instance, @Nullable VirtualMachine.State oldState, VirtualMachine.State newState) {
|
||||
try {
|
||||
Map<String, Object> event = new HashMap<>();
|
||||
event.put(ApiConstants.EVENT_ID, UUID.randomUUID().toString());
|
||||
event.put(ApiConstants.INSTANCE_ID, instance.getId());
|
||||
event.put(ApiConstants.ACCOUNT_ID, instance.getAccountId());
|
||||
event.put(ApiConstants.OLD_STATE, oldState != null ? oldState : State.Unknown);
|
||||
event.put(ApiConstants.NEW_STATE, newState);
|
||||
event.put(ApiConstants.TIME_STAMP, System.currentTimeMillis());
|
||||
messageBus.publish(_name, VM_LIFECYCLE_STATE, PublishScope.GLOBAL, event);
|
||||
} catch (Exception ex) {
|
||||
logger.warn("Failed to publish lifecycle event for Instance: {}", instance.getUuid(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void publishNicEventMessageBus(Long instanceId, Long accountId, Long nicId, String eventType) {
|
||||
try {
|
||||
Map<String, Object> event = new HashMap<>();
|
||||
event.put(ApiConstants.EVENT_ID, UUID.randomUUID().toString());
|
||||
event.put(ApiConstants.INSTANCE_ID, instanceId);
|
||||
event.put(ApiConstants.ACCOUNT_ID, accountId);
|
||||
event.put(ApiConstants.NIC_ID, nicId);
|
||||
event.put(ApiConstants.EVENT_TYPE, eventType); // NIC.CREATE, NIC.DELETE or NIC.UPDATE
|
||||
event.put(ApiConstants.TIME_STAMP, System.currentTimeMillis());
|
||||
|
||||
messageBus.publish(_name, Nic.Topics.NIC_LIFECYCLE, PublishScope.GLOBAL, event);
|
||||
} catch (Exception ex) {
|
||||
logger.error("Failed to publish lifecycle event for NIC with ID: {}", nicId, ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void publishVmHostNameUpdateMessageBus(long instanceId, String oldHostName, String hostName) {
|
||||
if (Strings.isBlank(hostName) || oldHostName.equalsIgnoreCase(hostName)) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
Map<String, Object> event = new HashMap<>();
|
||||
event.put(ApiConstants.EVENT_ID, UUID.randomUUID().toString());
|
||||
event.put(ApiConstants.INSTANCE_ID, instanceId);
|
||||
event.put(ApiConstants.OLD_HOST_NAME, oldHostName);
|
||||
event.put(ApiConstants.HOST_NAME, hostName);
|
||||
event.put(ApiConstants.EVENT_TYPE, EVENT_VM_UPDATE);
|
||||
event.put(ApiConstants.TIME_STAMP, System.currentTimeMillis());
|
||||
messageBus.publish(_name, VM_ACTION, PublishScope.GLOBAL, event);
|
||||
} catch (Exception ex) {
|
||||
logger.error("Failed to publish Instance action event for ID: {}", instanceId, ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set NIC as default if VM has no default NIC
|
||||
* @param vmInstance VM instance to be checked
|
||||
|
|
@ -1666,6 +1723,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
}
|
||||
|
||||
logger.debug("Successful removal of " + network + " from " + vmInstance);
|
||||
publishNicEventMessageBus(vmInstance.getId(), vmInstance.getAccountId(), nic.getId(), EVENT_NIC_DELETE);
|
||||
return _vmDao.findById(vmInstance.getId());
|
||||
}
|
||||
|
||||
|
|
@ -1907,7 +1965,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
logger.debug("Updating IPv4 address of NIC " + nicVO + " to " + ipaddr + "/" + nicVO.getIPv4Netmask() + " with gateway " + nicVO.getIPv4Gateway());
|
||||
nicVO.setIPv4Address(ipaddr);
|
||||
_nicDao.persist(nicVO);
|
||||
|
||||
publishNicEventMessageBus(vm.getId(), vm.getAccountId(), nicVO.getId(), EVENT_NIC_UPDATE);
|
||||
return vm;
|
||||
}
|
||||
|
||||
|
|
@ -2929,7 +2987,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
}
|
||||
|
||||
@Override
|
||||
@ActionEvent(eventType = EventTypes.EVENT_VM_UPDATE, eventDescription = "updating Vm")
|
||||
@ActionEvent(eventType = EVENT_VM_UPDATE, eventDescription = "updating Vm")
|
||||
public UserVm updateVirtualMachine(UpdateVMCmd cmd) throws ResourceUnavailableException, InsufficientCapacityException {
|
||||
validateInputsAndPermissionForUpdateVirtualMachineCommand(cmd);
|
||||
|
||||
|
|
@ -3310,6 +3368,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
}
|
||||
|
||||
if (State.Running == vm.getState()) {
|
||||
publishVmHostNameUpdateMessageBus(vm.getId(), vm.getHostName(), hostName);
|
||||
updateDns(vm, hostName);
|
||||
}
|
||||
|
||||
|
|
@ -3650,7 +3709,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
logger.warn("Tried to destroy ROOT volume for VM [{}], but couldn't retrieve it.", vm);
|
||||
}
|
||||
}
|
||||
|
||||
publishVmLifecycleMessageBus(destroyedVm, vm.getState(), VirtualMachine.State.Destroyed);
|
||||
return destroyedVm;
|
||||
}
|
||||
|
||||
|
|
@ -5341,7 +5400,9 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
additionalParams.put(VirtualMachineProfile.Param.VmPassword, cmd.getPassword());
|
||||
}
|
||||
|
||||
return startVirtualMachine(vmId, podId, clusterId, hostId, diskOfferingMap, additionalParams, cmd.getDeploymentPlanner());
|
||||
UserVm userVm = startVirtualMachine(vmId, podId, clusterId, hostId, diskOfferingMap, additionalParams, cmd.getDeploymentPlanner());
|
||||
publishVmLifecycleMessageBus(userVm, null, VirtualMachine.State.Running);
|
||||
return userVm;
|
||||
}
|
||||
|
||||
private UserVm startVirtualMachine(long vmId, Long podId, Long clusterId, Long hostId, Map<Long, DiskOffering> diskOfferingMap
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,249 @@
|
|||
// 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.dns;
|
||||
|
||||
import java.net.Inet4Address;
|
||||
import java.net.Inet6Address;
|
||||
|
||||
import org.apache.commons.validator.routines.DomainValidator;
|
||||
|
||||
import com.cloud.utils.StringUtils;
|
||||
import com.google.common.net.InetAddresses;
|
||||
|
||||
public class DnsProviderUtil {
|
||||
static DomainValidator validator = DomainValidator.getInstance(true);
|
||||
|
||||
public static String appendPublicSuffixToZone(String zoneName, String suffixDomain) {
|
||||
if (StringUtils.isBlank(suffixDomain)) {
|
||||
return zoneName;
|
||||
}
|
||||
suffixDomain = DnsProviderUtil.normalizeDomainForDb(suffixDomain);
|
||||
// Already suffixed → return as-is
|
||||
if (zoneName.toLowerCase().endsWith("." + suffixDomain)) {
|
||||
return zoneName;
|
||||
}
|
||||
|
||||
if (zoneName.equals(suffixDomain)) {
|
||||
throw new IllegalArgumentException("Cannot create DNS zone at root-level: " + suffixDomain);
|
||||
}
|
||||
// Check TLD matches
|
||||
String tldUser = getTld(zoneName);
|
||||
String tldSuffix = getTld(suffixDomain);
|
||||
|
||||
if (!tldUser.equalsIgnoreCase(tldSuffix)) {
|
||||
throw new IllegalArgumentException("TLD mismatch between user zone and domain suffix");
|
||||
}
|
||||
// Remove TLD from userZone
|
||||
int lastDot = zoneName.lastIndexOf('.');
|
||||
String zonePrefix = zoneName.substring(0, lastDot);
|
||||
return zonePrefix + "." + suffixDomain;
|
||||
}
|
||||
|
||||
private static String getTld(String domain) {
|
||||
String[] labels = domain.split("\\.");
|
||||
return labels[labels.length - 1];
|
||||
}
|
||||
|
||||
// lowercase, no trailing dot (used for DB storage, comparisons)
|
||||
public static String normalizeDomainForDb(String domain) {
|
||||
if (StringUtils.isBlank(domain)) {
|
||||
throw new IllegalArgumentException("Domain cannot be empty");
|
||||
}
|
||||
|
||||
String normalized = domain.trim().toLowerCase();
|
||||
if (normalized.endsWith(".")) {
|
||||
normalized = normalized.substring(0, normalized.length() - 1);
|
||||
}
|
||||
// Validate domain, allow local/private TLDs
|
||||
boolean valid = isValidInternalDnsZoneName(normalized) || validator.isValid(normalized);
|
||||
if (!valid) {
|
||||
throw new IllegalArgumentException("Invalid domain name: " + domain);
|
||||
}
|
||||
return normalized;
|
||||
}
|
||||
|
||||
static boolean isValidInternalDnsZoneName(String domain) {
|
||||
// Total length limit (DNS standard)
|
||||
if (domain.length() > 253) {
|
||||
return false;
|
||||
}
|
||||
|
||||
String[] labels = domain.split("\\.");
|
||||
// Must have at least 2 labels (zone + suffix like internal/test/etc.)
|
||||
if (labels.length < 2) {
|
||||
return false;
|
||||
}
|
||||
for (String label : labels) {
|
||||
if (label.isEmpty() || label.length() > 63) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Must start and end with alphanumeric (even if underscores exist inside)
|
||||
if (!label.matches("^[a-z0-9](?:[a-z0-9_-]{0,61}[a-z0-9])?$")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Prevent obviously invalid cases like "__" only labels
|
||||
if (label.equals("_")) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// DNS wire form: lowercase, validated, WITH trailing dot (used in record values)
|
||||
public static String normalizeDnsRecordValue(String value, DnsRecord.RecordType recordType) {
|
||||
if (StringUtils.isBlank(value)) {
|
||||
throw new IllegalArgumentException("DNS record value cannot be empty");
|
||||
}
|
||||
String trimmedValue = value.trim();
|
||||
switch (recordType) {
|
||||
case A:
|
||||
if (!(InetAddresses.forString(trimmedValue) instanceof Inet4Address)) {
|
||||
throw new IllegalArgumentException(
|
||||
String.format("Invalid IP address for %s record: %s", recordType, value));
|
||||
}
|
||||
return trimmedValue;
|
||||
case AAAA:
|
||||
if (!(InetAddresses.forString(trimmedValue) instanceof Inet6Address)) {
|
||||
throw new IllegalArgumentException(
|
||||
String.format("Invalid IP address for %s record: %s", recordType, value));
|
||||
}
|
||||
return trimmedValue;
|
||||
case CNAME:
|
||||
case NS:
|
||||
case PTR:
|
||||
return normalizeDomainForDnsRecord(trimmedValue);
|
||||
case SRV:
|
||||
return normalizeSrvRecord(trimmedValue);
|
||||
case MX:
|
||||
return normalizeMxRecord(trimmedValue);
|
||||
case TXT:
|
||||
// Free text: preserve exactly
|
||||
return trimmedValue;
|
||||
default:
|
||||
throw new IllegalArgumentException("Unsupported DNS record type: " + recordType);
|
||||
}
|
||||
}
|
||||
|
||||
static String normalizeDomainForDnsRecord(String domain) {
|
||||
if (StringUtils.isBlank(domain)) {
|
||||
throw new IllegalArgumentException("Domain name cannot be empty");
|
||||
}
|
||||
String normalized = domain.trim().toLowerCase();
|
||||
// Strip trailing dot first (normalize input)
|
||||
if (normalized.endsWith(".")) {
|
||||
normalized = normalized.substring(0, normalized.length() - 1);
|
||||
}
|
||||
|
||||
// Reject IP addresses
|
||||
if (InetAddresses.isInetAddress(normalized)) {
|
||||
throw new IllegalArgumentException("Domain cannot be an IP address: " + normalized);
|
||||
}
|
||||
|
||||
// Validate total length (max 253 chars, excluding trailing dot)
|
||||
if (normalized.length() > 253) {
|
||||
throw new IllegalArgumentException(
|
||||
"Domain name exceeds maximum length: " + normalized);
|
||||
}
|
||||
|
||||
// Validate labels
|
||||
String[] labels = normalized.split("\\.", -1);
|
||||
for (String label : labels) {
|
||||
if (label.isEmpty()) {
|
||||
throw new IllegalArgumentException(
|
||||
"Domain contains empty label: " + normalized);
|
||||
}
|
||||
if (label.length() > 63) {
|
||||
throw new IllegalArgumentException(
|
||||
"Domain label too long: " + label);
|
||||
}
|
||||
if (!label.matches("[a-z0-9]([a-z0-9-]*[a-z0-9])?")) {
|
||||
throw new IllegalArgumentException(
|
||||
"Invalid domain label: " + label);
|
||||
}
|
||||
}
|
||||
return normalized + ".";
|
||||
}
|
||||
|
||||
private static String normalizeSrvRecord(String value) {
|
||||
String trimmed = value.trim();
|
||||
String[] parts = trimmed.split("\\s+", 4);
|
||||
if (parts.length != 4) {
|
||||
throw new IllegalArgumentException(
|
||||
"Invalid SRV record value (expected '<priority> <weight> <port> <target>'): " + trimmed);
|
||||
}
|
||||
|
||||
int priority;
|
||||
int weight;
|
||||
int port;
|
||||
|
||||
try {
|
||||
priority = Integer.parseInt(parts[0]);
|
||||
weight = Integer.parseInt(parts[1]);
|
||||
port = Integer.parseInt(parts[2]);
|
||||
} catch (NumberFormatException e) {
|
||||
throw new IllegalArgumentException(
|
||||
"SRV priority/weight/port must be numeric: " + trimmed);
|
||||
}
|
||||
|
||||
if (priority < 0 || priority > 65535) {
|
||||
throw new IllegalArgumentException("SRV priority out of range (0–65535): " + parts[0]);
|
||||
}
|
||||
|
||||
if (weight < 0 || weight > 65535) {
|
||||
throw new IllegalArgumentException("SRV weight out of range (0–65535): " + parts[1]);
|
||||
}
|
||||
|
||||
if (port < 1 || port > 65535) {
|
||||
throw new IllegalArgumentException("SRV port out of range (1–65535): " + parts[2]);
|
||||
}
|
||||
|
||||
String target = normalizeDomainForDnsRecord(parts[3]);
|
||||
|
||||
return priority + " " + weight + " " + port + " " + target;
|
||||
}
|
||||
|
||||
private static String normalizeMxRecord(String value) {
|
||||
String trimmed = value.trim();
|
||||
String[] parts = trimmed.split("\\s+", 2);
|
||||
|
||||
if (parts.length != 2) {
|
||||
throw new IllegalArgumentException(
|
||||
"Invalid MX record value (expected '<priority> <mail-exchanger>'): " + trimmed);
|
||||
}
|
||||
|
||||
int priority;
|
||||
|
||||
try {
|
||||
priority = Integer.parseInt(parts[0]);
|
||||
} catch (NumberFormatException e) {
|
||||
throw new IllegalArgumentException(
|
||||
"MX priority must be numeric: " + parts[0]);
|
||||
}
|
||||
|
||||
if (priority < 0 || priority > 65535) {
|
||||
throw new IllegalArgumentException(
|
||||
"MX priority out of range (0–65535): " + parts[0]);
|
||||
}
|
||||
|
||||
String mailExchanger = normalizeDomainForDnsRecord(parts[1]);
|
||||
|
||||
return priority + " " + mailExchanger;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
// 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.dns.dao;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.cloudstack.dns.DnsProviderType;
|
||||
import org.apache.cloudstack.dns.DnsServer;
|
||||
import org.apache.cloudstack.dns.vo.DnsServerVO;
|
||||
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.utils.db.Filter;
|
||||
import com.cloud.utils.db.GenericDao;
|
||||
|
||||
public interface DnsServerDao extends GenericDao<DnsServerVO, Long> {
|
||||
|
||||
DnsServerVO findById(Long dnsServerId);
|
||||
|
||||
DnsServer findByUrlAndAccount(String url, long accountId);
|
||||
|
||||
List<Long> listDnsServerIdsByAccountId(Long accountId);
|
||||
|
||||
Pair<List<DnsServerVO>, Integer> searchDnsServer(Long dnsServerId, Long accountId, Set<Long> domainIds, DnsProviderType providerType, String keyword, Filter filter);
|
||||
|
||||
void loadDetails(DnsServer dnsServer);
|
||||
|
||||
void saveDetails(DnsServer dnsServer);
|
||||
}
|
||||
|
|
@ -0,0 +1,196 @@
|
|||
// 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.dns.dao;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.dns.DnsProviderType;
|
||||
import org.apache.cloudstack.dns.DnsServer;
|
||||
import org.apache.cloudstack.dns.vo.DnsServerDetailVO;
|
||||
import org.apache.cloudstack.dns.vo.DnsServerVO;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.utils.db.Filter;
|
||||
import com.cloud.utils.db.GenericDaoBase;
|
||||
import com.cloud.utils.db.GenericSearchBuilder;
|
||||
import com.cloud.utils.db.SearchBuilder;
|
||||
import com.cloud.utils.db.SearchCriteria;
|
||||
import com.cloud.utils.db.Transaction;
|
||||
import com.cloud.utils.db.TransactionCallback;
|
||||
|
||||
@Component
|
||||
public class DnsServerDaoImpl extends GenericDaoBase<DnsServerVO, Long> implements DnsServerDao {
|
||||
@Inject
|
||||
DnsServerDetailsDao dnsServerDetailsDao;
|
||||
|
||||
SearchBuilder<DnsServerVO> AllFieldsSearch;
|
||||
SearchBuilder<DnsServerVO> AccountUrlSearch;
|
||||
GenericSearchBuilder<DnsServerVO, Long> DnsServerIdsByAccountSearch;
|
||||
|
||||
|
||||
public DnsServerDaoImpl() {
|
||||
super();
|
||||
|
||||
AccountUrlSearch = createSearchBuilder();
|
||||
AccountUrlSearch.and(ApiConstants.URL, AccountUrlSearch.entity().getUrl(), SearchCriteria.Op.EQ);
|
||||
AccountUrlSearch.and(ApiConstants.ACCOUNT_ID, AccountUrlSearch.entity().getAccountId(), SearchCriteria.Op.EQ);
|
||||
AccountUrlSearch.done();
|
||||
|
||||
AllFieldsSearch = createSearchBuilder();
|
||||
AllFieldsSearch.and(ApiConstants.ID, AllFieldsSearch.entity().getId(), SearchCriteria.Op.EQ);
|
||||
AllFieldsSearch.and(ApiConstants.NAME, AllFieldsSearch.entity().getName(), SearchCriteria.Op.LIKE);
|
||||
AllFieldsSearch.and(ApiConstants.PROVIDER_TYPE, AllFieldsSearch.entity().getProviderType(), SearchCriteria.Op.EQ);
|
||||
AllFieldsSearch.and(ApiConstants.ACCOUNT_ID, AllFieldsSearch.entity().getAccountId(), SearchCriteria.Op.EQ);
|
||||
AllFieldsSearch.done();
|
||||
|
||||
DnsServerIdsByAccountSearch = createSearchBuilder(Long.class);
|
||||
DnsServerIdsByAccountSearch.selectFields(DnsServerIdsByAccountSearch.entity().getId());
|
||||
DnsServerIdsByAccountSearch.and(ApiConstants.ACCOUNT_ID, DnsServerIdsByAccountSearch.entity().getAccountId(), SearchCriteria.Op.EQ);
|
||||
DnsServerIdsByAccountSearch.and(ApiConstants.STATE, DnsServerIdsByAccountSearch.entity().getState(), SearchCriteria.Op.EQ);
|
||||
DnsServerIdsByAccountSearch.done();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public DnsServerVO findById(Long dnsServerId) {
|
||||
DnsServerVO dnsServer = super.findById(dnsServerId);
|
||||
loadDetails(dnsServer);
|
||||
return dnsServer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DnsServer findByUrlAndAccount(String url, long accountId) {
|
||||
SearchCriteria<DnsServerVO> sc = AccountUrlSearch.create();
|
||||
sc.setParameters(ApiConstants.URL, url);
|
||||
sc.setParameters(ApiConstants.ACCOUNT_ID, accountId);
|
||||
return findOneBy(sc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Long> listDnsServerIdsByAccountId(Long accountId) {
|
||||
SearchCriteria<Long> sc = DnsServerIdsByAccountSearch.create();
|
||||
if (accountId != null) {
|
||||
sc.setParameters(ApiConstants.ACCOUNT_ID, accountId);
|
||||
}
|
||||
sc.setParameters(ApiConstants.STATE, DnsServer.State.Enabled);
|
||||
return customSearch(sc, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pair<List<DnsServerVO>, Integer> searchDnsServer(Long dnsServerId, Long accountId, Set<Long> domainIds, DnsProviderType providerType,
|
||||
String keyword, Filter filter) {
|
||||
|
||||
SearchBuilder<DnsServerVO> sb = createSearchBuilder();
|
||||
sb.and(ApiConstants.ID, sb.entity().getId(), SearchCriteria.Op.EQ);
|
||||
sb.and(ApiConstants.NAME, sb.entity().getName(), SearchCriteria.Op.LIKE);
|
||||
|
||||
sb.and().op(ApiConstants.ACCOUNT_ID, sb.entity().getAccountId(), SearchCriteria.Op.EQ);
|
||||
if (!CollectionUtils.isEmpty(domainIds)) {
|
||||
sb.or().op(ApiConstants.IS_PUBLIC, sb.entity().getPublicServer(), SearchCriteria.Op.EQ);
|
||||
sb.and(ApiConstants.DOMAIN_IDS, sb.entity().getDomainId(), SearchCriteria.Op.IN);
|
||||
sb.cp();
|
||||
}
|
||||
sb.cp();
|
||||
sb.and(ApiConstants.PROVIDER_TYPE, sb.entity().getProviderType(), SearchCriteria.Op.EQ);
|
||||
sb.and(ApiConstants.STATE, sb.entity().getState(), SearchCriteria.Op.EQ);
|
||||
sb.done();
|
||||
|
||||
SearchCriteria<DnsServerVO> sc = sb.create();
|
||||
if (dnsServerId != null) {
|
||||
sc.setParameters(ApiConstants.ID, dnsServerId);
|
||||
}
|
||||
if (accountId != null) {
|
||||
sc.setParameters(ApiConstants.ACCOUNT_ID, accountId);
|
||||
}
|
||||
if (!CollectionUtils.isEmpty(domainIds)) {
|
||||
sc.setParameters(ApiConstants.IS_PUBLIC, true);
|
||||
sc.setParameters(ApiConstants.DOMAIN_IDS, domainIds.toArray());
|
||||
}
|
||||
if (providerType != null) {
|
||||
sc.setParameters(ApiConstants.PROVIDER_TYPE, providerType);
|
||||
}
|
||||
if (keyword != null) {
|
||||
sc.setParameters(ApiConstants.NAME, "%" + keyword + "%");
|
||||
}
|
||||
sc.setParameters(ApiConstants.STATE, DnsServer.State.Enabled);
|
||||
return searchAndCount(sc, filter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DnsServerVO persist(DnsServerVO dnsServer) {
|
||||
return Transaction.execute((TransactionCallback<DnsServerVO>) status -> {
|
||||
DnsServerVO dnsServerDb = super.persist(dnsServer);
|
||||
saveDetails(dnsServer);
|
||||
loadDetails(dnsServerDb);
|
||||
return dnsServerDb;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean update(Long id, DnsServerVO dnsServer) {
|
||||
return Transaction.execute((TransactionCallback<Boolean>) status -> {
|
||||
boolean result = super.update(id, dnsServer);
|
||||
if (result) {
|
||||
saveDetails(dnsServer);
|
||||
}
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(Long dnsServerId) {
|
||||
return Transaction.execute((TransactionCallback<Boolean>) status -> {
|
||||
boolean result = super.remove(dnsServerId);
|
||||
if (result) {
|
||||
dnsServerDetailsDao.removeDetails(dnsServerId);
|
||||
}
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadDetails(DnsServer dnsServer) {
|
||||
if (dnsServer == null) {
|
||||
return;
|
||||
}
|
||||
Map<String, String> details = dnsServerDetailsDao.listDetailsKeyPairs(dnsServer.getId());
|
||||
dnsServer.setDetails(details);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveDetails(DnsServer dnsServer) {
|
||||
Map<String, String> detailsStr = dnsServer.getDetails();
|
||||
if (detailsStr == null) {
|
||||
return;
|
||||
}
|
||||
List<DnsServerDetailVO> details = new ArrayList<>();
|
||||
for (String key : detailsStr.keySet()) {
|
||||
DnsServerDetailVO detail = new DnsServerDetailVO(dnsServer.getId(), key, detailsStr.get(key), true);
|
||||
details.add(detail);
|
||||
}
|
||||
dnsServerDetailsDao.saveDetails(details);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
// 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.dns.dao;
|
||||
|
||||
import org.apache.cloudstack.dns.vo.DnsServerDetailVO;
|
||||
import org.apache.cloudstack.resourcedetail.ResourceDetailsDao;
|
||||
|
||||
import com.cloud.utils.db.GenericDao;
|
||||
|
||||
public interface DnsServerDetailsDao extends GenericDao<DnsServerDetailVO, Long>, ResourceDetailsDao<DnsServerDetailVO> {
|
||||
}
|
||||
|
|
@ -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 org.apache.cloudstack.dns.dao;
|
||||
|
||||
import org.apache.cloudstack.dns.vo.DnsServerDetailVO;
|
||||
import org.apache.cloudstack.resourcedetail.ResourceDetailsDaoBase;
|
||||
|
||||
|
||||
public class DnsServerDetailsDaoImpl extends ResourceDetailsDaoBase<DnsServerDetailVO> implements DnsServerDetailsDao {
|
||||
@Override
|
||||
public void addDetail(long resourceId, String key, String value, boolean display) {
|
||||
super.addDetail(new DnsServerDetailVO(resourceId, key, value, display));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
// 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.dns.dao;
|
||||
|
||||
import org.apache.cloudstack.dns.vo.DnsServerJoinVO;
|
||||
|
||||
import com.cloud.utils.db.GenericDao;
|
||||
|
||||
public interface DnsServerJoinDao extends GenericDao<DnsServerJoinVO, Long> {
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
// 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.dns.dao;
|
||||
|
||||
import org.apache.cloudstack.dns.vo.DnsServerJoinVO;
|
||||
|
||||
import com.cloud.utils.db.GenericDaoBase;
|
||||
|
||||
public class DnsServerJoinDaoImpl extends GenericDaoBase<DnsServerJoinVO, Long> implements DnsServerJoinDao {
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
// 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.dns.dao;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.cloudstack.dns.DnsZone;
|
||||
import org.apache.cloudstack.dns.vo.DnsZoneVO;
|
||||
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.utils.db.Filter;
|
||||
import com.cloud.utils.db.GenericDao;
|
||||
|
||||
public interface DnsZoneDao extends GenericDao<DnsZoneVO, Long> {
|
||||
List<DnsZoneVO> listByAccount(long accountId);
|
||||
DnsZoneVO findByNameServerAndType(String name, long dnsServerId, DnsZone.ZoneType type);
|
||||
|
||||
Pair<List<DnsZoneVO>, Integer> searchZones(Long id, Long accountId, List<Long> ownDnsServerIds, Long targetDnsServerId,
|
||||
String keyword, Filter filter);
|
||||
|
||||
List<DnsZoneVO> findDnsZonesByServerId(long dnsServerId);
|
||||
}
|
||||
|
|
@ -0,0 +1,122 @@
|
|||
// 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.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.apache.commons.collections.CollectionUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.utils.db.Filter;
|
||||
import com.cloud.utils.db.GenericDaoBase;
|
||||
import com.cloud.utils.db.SearchBuilder;
|
||||
import com.cloud.utils.db.SearchCriteria;
|
||||
|
||||
@Component
|
||||
public class DnsZoneDaoImpl extends GenericDaoBase<DnsZoneVO, Long> implements DnsZoneDao {
|
||||
SearchBuilder<DnsZoneVO> DnsServerSearch;
|
||||
SearchBuilder<DnsZoneVO> AccountSearch;
|
||||
SearchBuilder<DnsZoneVO> NameServerTypeSearch;
|
||||
|
||||
public DnsZoneDaoImpl() {
|
||||
super();
|
||||
|
||||
DnsServerSearch = createSearchBuilder();
|
||||
DnsServerSearch.selectFields(DnsServerSearch.entity().getId());
|
||||
DnsServerSearch.and(ApiConstants.DNS_SERVER_ID, DnsServerSearch.entity().getDnsServerId(), SearchCriteria.Op.EQ);
|
||||
DnsServerSearch.done();
|
||||
|
||||
AccountSearch = createSearchBuilder();
|
||||
AccountSearch.and(ApiConstants.ACCOUNT_ID, AccountSearch.entity().getAccountId(), SearchCriteria.Op.EQ);
|
||||
AccountSearch.and(ApiConstants.STATE, AccountSearch.entity().getState(), SearchCriteria.Op.EQ);
|
||||
AccountSearch.done();
|
||||
|
||||
NameServerTypeSearch = createSearchBuilder();
|
||||
NameServerTypeSearch.and(ApiConstants.NAME, NameServerTypeSearch.entity().getName(), SearchCriteria.Op.EQ);
|
||||
NameServerTypeSearch.and(ApiConstants.DNS_SERVER_ID, NameServerTypeSearch.entity().getDnsServerId(), SearchCriteria.Op.EQ);
|
||||
NameServerTypeSearch.and(ApiConstants.TYPE, NameServerTypeSearch.entity().getType(), SearchCriteria.Op.EQ);
|
||||
NameServerTypeSearch.and(ApiConstants.STATE, NameServerTypeSearch.entity().getState(), SearchCriteria.Op.EQ);
|
||||
NameServerTypeSearch.done();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DnsZoneVO> listByAccount(long accountId) {
|
||||
SearchCriteria<DnsZoneVO> sc = AccountSearch.create();
|
||||
sc.setParameters(ApiConstants.ACCOUNT_ID, accountId);
|
||||
sc.setParameters(ApiConstants.STATE, DnsZone.State.Active);
|
||||
return listBy(sc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DnsZoneVO findByNameServerAndType(String name, long dnsServerId, DnsZone.ZoneType type) {
|
||||
SearchCriteria<DnsZoneVO> sc = NameServerTypeSearch.create();
|
||||
sc.setParameters(ApiConstants.NAME, name);
|
||||
sc.setParameters(ApiConstants.DNS_SERVER_ID, dnsServerId);
|
||||
sc.setParameters(ApiConstants.TYPE, type);
|
||||
sc.setParameters(ApiConstants.STATE, DnsZone.State.Active);
|
||||
return findOneBy(sc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pair<List<DnsZoneVO>, Integer> searchZones(Long id, Long accountId, List<Long> ownDnsServerIds, Long targetDnsServerId,
|
||||
String keyword, Filter filter) {
|
||||
|
||||
SearchBuilder<DnsZoneVO> sb = createSearchBuilder();
|
||||
sb.and(ApiConstants.STATE, sb.entity().getState(), SearchCriteria.Op.EQ);
|
||||
sb.and(ApiConstants.ID, sb.entity().getId(), SearchCriteria.Op.EQ);
|
||||
sb.and(ApiConstants.NAME, sb.entity().getName(), SearchCriteria.Op.LIKE);
|
||||
sb.and(ApiConstants.TARGET_ID, sb.entity().getDnsServerId(), SearchCriteria.Op.EQ);
|
||||
if (!CollectionUtils.isEmpty(ownDnsServerIds)) {
|
||||
sb.and().op(ApiConstants.DNS_SERVER_ID, sb.entity().getDnsServerId(), SearchCriteria.Op.IN);
|
||||
sb.or(ApiConstants.ACCOUNT_ID, sb.entity().getAccountId(), SearchCriteria.Op.EQ);
|
||||
sb.cp();
|
||||
} else {
|
||||
sb.and(ApiConstants.ACCOUNT_ID, sb.entity().getAccountId(), SearchCriteria.Op.EQ);
|
||||
}
|
||||
sb.done();
|
||||
|
||||
SearchCriteria<DnsZoneVO> sc = sb.create();
|
||||
if (id != null) {
|
||||
sc.setParameters(ApiConstants.ID, id);
|
||||
}
|
||||
if (!CollectionUtils.isEmpty(ownDnsServerIds)) {
|
||||
sc.setParameters(ApiConstants.DNS_SERVER_ID, ownDnsServerIds.toArray());
|
||||
}
|
||||
if (keyword != null) {
|
||||
sc.setParameters(ApiConstants.NAME, "%" + keyword + "%");
|
||||
}
|
||||
if (accountId != null) {
|
||||
sc.setParameters(ApiConstants.ACCOUNT_ID, accountId);
|
||||
}
|
||||
if (targetDnsServerId != null) {
|
||||
sc.setParameters(ApiConstants.TARGET_ID, targetDnsServerId);
|
||||
}
|
||||
sc.setParameters(ApiConstants.STATE, DnsZone.State.Active);
|
||||
return searchAndCount(sc, filter);
|
||||
}
|
||||
|
||||
public List<DnsZoneVO> findDnsZonesByServerId(long dnsServerId) {
|
||||
SearchCriteria<DnsZoneVO> sc = DnsServerSearch.create();
|
||||
sc.setParameters(ApiConstants.DNS_SERVER_ID, dnsServerId);
|
||||
return listBy(sc);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
// 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.dns.dao;
|
||||
|
||||
import org.apache.cloudstack.dns.vo.DnsZoneJoinVO;
|
||||
|
||||
import com.cloud.utils.db.GenericDao;
|
||||
|
||||
public interface DnsZoneJoinDao extends GenericDao<DnsZoneJoinVO, Long> {
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
// 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.dns.dao;
|
||||
|
||||
import org.apache.cloudstack.dns.vo.DnsZoneJoinVO;
|
||||
|
||||
import com.cloud.utils.db.GenericDaoBase;
|
||||
|
||||
public class DnsZoneJoinDaoImpl extends GenericDaoBase<DnsZoneJoinVO, Long> implements DnsZoneJoinDao {
|
||||
}
|
||||
|
|
@ -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 org.apache.cloudstack.dns.dao;
|
||||
|
||||
import org.apache.cloudstack.dns.vo.DnsZoneNetworkMapVO;
|
||||
|
||||
import com.cloud.utils.db.GenericDao;
|
||||
|
||||
public interface DnsZoneNetworkMapDao extends GenericDao<DnsZoneNetworkMapVO, Long> {
|
||||
void removeNetworkMappingByZoneId(long dnsZoneId);
|
||||
DnsZoneNetworkMapVO findByNetworkId(long networkId);
|
||||
|
||||
DnsZoneNetworkMapVO findByZoneId(long networkId);
|
||||
}
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
// 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.dns.dao;
|
||||
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.dns.vo.DnsZoneNetworkMapVO;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.cloud.utils.db.GenericDaoBase;
|
||||
import com.cloud.utils.db.SearchBuilder;
|
||||
import com.cloud.utils.db.SearchCriteria;
|
||||
|
||||
@Component
|
||||
public class DnsZoneNetworkMapDaoImpl extends GenericDaoBase<DnsZoneNetworkMapVO, Long> implements DnsZoneNetworkMapDao {
|
||||
private final SearchBuilder<DnsZoneNetworkMapVO> ZoneNetworkSearch;
|
||||
private final SearchBuilder<DnsZoneNetworkMapVO> NetworkSearch;
|
||||
|
||||
public DnsZoneNetworkMapDaoImpl() {
|
||||
super();
|
||||
ZoneNetworkSearch = createSearchBuilder();
|
||||
ZoneNetworkSearch.and(ApiConstants.DNS_ZONE_ID, ZoneNetworkSearch.entity().getDnsZoneId(), SearchCriteria.Op.EQ);
|
||||
ZoneNetworkSearch.done();
|
||||
|
||||
NetworkSearch = createSearchBuilder();
|
||||
NetworkSearch.and(ApiConstants.NETWORK_ID, NetworkSearch.entity().getNetworkId(), SearchCriteria.Op.EQ);
|
||||
NetworkSearch.done();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeNetworkMappingByZoneId(long dnsZoneId) {
|
||||
SearchCriteria<DnsZoneNetworkMapVO> sc = ZoneNetworkSearch.create();
|
||||
sc.setParameters(ApiConstants.DNS_ZONE_ID, dnsZoneId);
|
||||
remove(sc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DnsZoneNetworkMapVO findByNetworkId(long networkId) {
|
||||
SearchCriteria<DnsZoneNetworkMapVO> sc = NetworkSearch.create();
|
||||
sc.setParameters(ApiConstants.NETWORK_ID, networkId);
|
||||
return findOneBy(sc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DnsZoneNetworkMapVO findByZoneId(long dnsZoneId) {
|
||||
SearchCriteria<DnsZoneNetworkMapVO> sc = ZoneNetworkSearch.create();
|
||||
sc.setParameters(ApiConstants.DNS_ZONE_ID, dnsZoneId);
|
||||
return findOneBy(sc);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
// 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.dns.dao;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.cloudstack.dns.vo.NicDnsJoinVO;
|
||||
|
||||
import com.cloud.utils.db.GenericDao;
|
||||
|
||||
public interface NicDnsJoinDao extends GenericDao<NicDnsJoinVO, Long> {
|
||||
|
||||
/**
|
||||
* Used for Collision Checks.
|
||||
*
|
||||
* @param dnsZoneId
|
||||
* @param nicDnsName
|
||||
* @return active records to see who currently owns the dnsRecordUrl.
|
||||
*/
|
||||
NicDnsJoinVO findActiveByDnsRecordAndZone(long dnsZoneId, String nicDnsName);
|
||||
|
||||
/**
|
||||
* Used to sync DNS record url based on available ips for vmId in the dnsZone
|
||||
*
|
||||
* @param vmId
|
||||
* @param dnsZoneId
|
||||
* @param nicDnsName
|
||||
* @return list of active nics using the dnsRecordUrl, supports null vmId for dnsZone wide query
|
||||
*/
|
||||
List<NicDnsJoinVO> listActiveByVmIdZoneAndDnsRecord(Long vmId, long dnsZoneId, String nicDnsName);
|
||||
|
||||
/**
|
||||
* Used for VM Start/Running
|
||||
* @param vmId
|
||||
* @return records associated to vmId
|
||||
*/
|
||||
List<NicDnsJoinVO> listActiveByVmId(long vmId);
|
||||
|
||||
/**
|
||||
* Used by Instance Destroy/Stop or NIC delete
|
||||
* @param vmId
|
||||
* @return records with soft-delete
|
||||
*/
|
||||
List<NicDnsJoinVO> listIncludingRemovedByVmId(long vmId);
|
||||
|
||||
/**
|
||||
* Find all records for dnsZoneId with valid nicDnsName
|
||||
* @param dnsZoneId
|
||||
* @return
|
||||
*/
|
||||
List<NicDnsJoinVO> listByZoneId(long dnsZoneId);
|
||||
}
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
// 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.dns.dao;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.dns.vo.NicDnsJoinVO;
|
||||
|
||||
import com.cloud.utils.db.GenericDaoBase;
|
||||
import com.cloud.utils.db.SearchBuilder;
|
||||
import com.cloud.utils.db.SearchCriteria;
|
||||
|
||||
public class NicDnsJoinDaoImpl extends GenericDaoBase<NicDnsJoinVO, Long> implements NicDnsJoinDao {
|
||||
private final SearchBuilder<NicDnsJoinVO> activeDnsRecordZoneSearch;
|
||||
private final SearchBuilder<NicDnsJoinVO> activeVmZoneDnsRecordSearch; // Route for null vmId
|
||||
private final SearchBuilder<NicDnsJoinVO> activeVmSearch;
|
||||
private final SearchBuilder<NicDnsJoinVO> activeDnsRecordsByZoneIdSearch;
|
||||
|
||||
public NicDnsJoinDaoImpl() {
|
||||
|
||||
activeDnsRecordZoneSearch = createSearchBuilder();
|
||||
activeDnsRecordZoneSearch.and(ApiConstants.NIC_DNS_NAME, activeDnsRecordZoneSearch.entity().getNicDnsName(), SearchCriteria.Op.EQ);
|
||||
activeDnsRecordZoneSearch.and(ApiConstants.DNS_ZONE_ID, activeDnsRecordZoneSearch.entity().getDnsZoneId(), SearchCriteria.Op.EQ);
|
||||
activeDnsRecordZoneSearch.and(ApiConstants.REMOVED, activeDnsRecordZoneSearch.entity().getRemoved(), SearchCriteria.Op.NULL);
|
||||
activeDnsRecordZoneSearch.done();
|
||||
|
||||
activeVmZoneDnsRecordSearch = createSearchBuilder();
|
||||
activeVmZoneDnsRecordSearch.and(ApiConstants.INSTANCE_ID, activeVmZoneDnsRecordSearch.entity().getInstanceId(), SearchCriteria.Op.EQ);
|
||||
activeVmZoneDnsRecordSearch.and(ApiConstants.NIC_DNS_NAME, activeVmZoneDnsRecordSearch.entity().getNicDnsName(), SearchCriteria.Op.EQ);
|
||||
activeVmZoneDnsRecordSearch.and(ApiConstants.DNS_ZONE_ID, activeVmZoneDnsRecordSearch.entity().getDnsZoneId(), SearchCriteria.Op.EQ);
|
||||
activeVmZoneDnsRecordSearch.and(ApiConstants.REMOVED, activeVmZoneDnsRecordSearch.entity().getRemoved(), SearchCriteria.Op.NULL);
|
||||
activeVmZoneDnsRecordSearch.done();
|
||||
|
||||
activeVmSearch = createSearchBuilder();
|
||||
activeVmSearch.and(ApiConstants.INSTANCE_ID, activeVmSearch.entity().getInstanceId(), SearchCriteria.Op.EQ);
|
||||
activeVmSearch.done();
|
||||
|
||||
activeDnsRecordsByZoneIdSearch = createSearchBuilder();
|
||||
activeDnsRecordsByZoneIdSearch.selectFields(activeDnsRecordsByZoneIdSearch.entity().getId());
|
||||
activeDnsRecordsByZoneIdSearch.and(ApiConstants.DNS_ZONE_ID, activeDnsRecordsByZoneIdSearch.entity().getDnsZoneId(), SearchCriteria.Op.EQ);
|
||||
activeDnsRecordsByZoneIdSearch.and(ApiConstants.NIC_DNS_NAME, activeDnsRecordsByZoneIdSearch.entity().getNicDnsName(), SearchCriteria.Op.NNULL);
|
||||
activeDnsRecordsByZoneIdSearch.and(ApiConstants.REMOVED, activeDnsRecordsByZoneIdSearch.entity().getRemoved(), SearchCriteria.Op.NULL);
|
||||
activeDnsRecordsByZoneIdSearch.done();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public NicDnsJoinVO findActiveByDnsRecordAndZone(long dnsZoneId, String nicDnsName) {
|
||||
SearchCriteria<NicDnsJoinVO> sc = activeDnsRecordZoneSearch.create();
|
||||
sc.setParameters(ApiConstants.NIC_DNS_NAME, nicDnsName);
|
||||
sc.setParameters(ApiConstants.DNS_ZONE_ID, dnsZoneId);
|
||||
return findOneBy(sc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<NicDnsJoinVO> listActiveByVmIdZoneAndDnsRecord(Long vmId, long dnsZoneId, String nicDnsName) {
|
||||
if (vmId != null) {
|
||||
SearchCriteria<NicDnsJoinVO> sc = activeVmZoneDnsRecordSearch.create();
|
||||
sc.setParameters(ApiConstants.INSTANCE_ID, vmId);
|
||||
sc.setParameters(ApiConstants.DNS_ZONE_ID, dnsZoneId);
|
||||
sc.setParameters(ApiConstants.NIC_DNS_NAME, nicDnsName);
|
||||
return listBy(sc);
|
||||
} else {
|
||||
SearchCriteria<NicDnsJoinVO> sc = activeDnsRecordZoneSearch.create();
|
||||
sc.setParameters(ApiConstants.DNS_ZONE_ID, dnsZoneId);
|
||||
sc.setParameters(ApiConstants.NIC_DNS_NAME, nicDnsName);
|
||||
return listBy(sc);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<NicDnsJoinVO> listActiveByVmId(long vmId) {
|
||||
SearchCriteria<NicDnsJoinVO> sc = activeVmSearch.create();
|
||||
sc.setParameters(ApiConstants.INSTANCE_ID, vmId);
|
||||
return listBy(sc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<NicDnsJoinVO> listIncludingRemovedByVmId(long vmId) {
|
||||
SearchCriteria<NicDnsJoinVO> sc = activeVmSearch.create();
|
||||
sc.setParameters(ApiConstants.INSTANCE_ID, vmId);
|
||||
return listIncludingRemovedBy(sc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<NicDnsJoinVO> listByZoneId(long dnsZoneId) {
|
||||
SearchCriteria<NicDnsJoinVO> sc = activeDnsRecordsByZoneIdSearch.create();
|
||||
sc.setParameters(ApiConstants.DNS_ZONE_ID, dnsZoneId);
|
||||
return listBy(sc);
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue