@Override
  public @Nonnull String createDnsZone(
      @Nonnull String domainName, @Nonnull String name, @Nonnull String description)
      throws CloudException, InternalException {
    APITrace.begin(provider, "DNS.createDnsZone");
    try {
      ProviderContext ctx = provider.getContext();

      if (ctx == null) {
        logger.error("No context exists for this request");
        throw new InternalException("No context exists for this request");
      }
      NovaMethod method = new NovaMethod(provider);

      HashMap<String, Object> wrapper = new HashMap<String, Object>();
      ArrayList<Map<String, Object>> domains = new ArrayList<Map<String, Object>>();

      HashMap<String, Object> domain = new HashMap<String, Object>();

      domain.put("name", domainName);
      domain.put("comment", description);
      domain.put("emailAddress", "postmaster@" + domainName);

      domains.add(domain);

      wrapper.put("domains", domains);

      JSONObject response =
          method.postString(SERVICE, RESOURCE, null, new JSONObject(wrapper), false);

      try {
        if (response != null && response.has("jobId")) {
          response = waitForJob(response.getString("jobId"));
          if (response != null && response.has("domains")) {
            JSONArray list = response.getJSONArray("domains");

            for (int i = 0; i < list.length(); i++) {
              DNSZone zone = toZone(ctx, list.getJSONObject(i));

              if (zone != null) {
                return zone.getProviderDnsZoneId();
              }
            }
          }
        }
      } catch (JSONException e) {
        logger.error("createDnsZone(): JSON error parsing response: " + e.getMessage());
        e.printStackTrace();
        throw new CloudException(
            CloudErrorType.COMMUNICATION, 200, "invalidResponse", "JSON error parsing " + response);
      }
      logger.error("createDnsZone(): No zone was created, but no error specified");
      throw new CloudException("No zone was created, but no error specified");
    } finally {
      APITrace.end();
    }
  }
  private @Nullable DNSRecord toRecord(
      @SuppressWarnings("UnusedParameters") @Nonnull ProviderContext ctx,
      @Nonnull DNSZone zone,
      @Nullable JSONObject json)
      throws CloudException, InternalException {
    if (json == null) {
      return null;
    }
    try {
      String recordId = (json.has("id") ? json.getString("id") : null);

      if (recordId == null) {
        return null;
      }
      String name = (json.has("name") ? json.getString("name") : null);

      if (name == null) {
        return null;
      }
      if (name.endsWith(zone.getDomainName())) {
        name = name + ".";
      }
      DNSRecordType recordType = DNSRecordType.A;
      String type = (json.has("type") ? json.getString("type") : null);

      if (type != null) {
        recordType = DNSRecordType.valueOf(type.toUpperCase());
      }
      String data = (json.has("data") ? json.getString("data") : null);
      int ttl = (json.has("ttl") ? json.getInt("ttl") : 3600);

      DNSRecord record = new DNSRecord();

      record.setName(name);
      record.setProviderZoneId(zone.getProviderDnsZoneId());
      record.setTtl(ttl);
      record.setType(recordType);
      record.setValues(data == null ? new String[0] : new String[] {data});

      return record;
    } catch (JSONException e) {
      throw new CloudException(e);
    }
  }