use of com.yahoo.pulsar.broker.web.RestException in project pulsar by yahoo.
the class ResourceQuotas method setNamespaceBundleResourceQuota.
@POST
@Path("/{property}/{cluster}/{namespace}/{bundle}")
@ApiOperation(value = "Set resource quota on a namespace.")
@ApiResponses(value = { @ApiResponse(code = 403, message = "Don't have admin permission"), @ApiResponse(code = 409, message = "Concurrent modification") })
public void setNamespaceBundleResourceQuota(@PathParam("property") String property, @PathParam("cluster") String cluster, @PathParam("namespace") String namespace, @PathParam("bundle") String bundleRange, ResourceQuota quota) {
validateSuperUserAccess();
validatePoliciesReadOnlyAccess();
Policies policies = getNamespacePolicies(property, cluster, namespace);
if (!cluster.equals(Namespaces.GLOBAL_CLUSTER)) {
validateClusterOwnership(cluster);
validateClusterForProperty(property, cluster);
}
NamespaceName fqnn = new NamespaceName(property, cluster, namespace);
NamespaceBundle nsBundle = validateNamespaceBundleRange(fqnn, policies.bundles, bundleRange);
try {
pulsar().getLocalZkCacheService().getResourceQuotaCache().setQuota(nsBundle, quota);
log.info("[{}] Successfully set resource quota for namespace bundle {}", clientAppId(), nsBundle.toString());
} catch (KeeperException.NoNodeException e) {
log.warn("[{}] Failed to set resource quota for namespace bundle {}: concurrent modification", clientAppId(), nsBundle.toString());
throw new RestException(Status.CONFLICT, "Cuncurrent modification on namespace bundle quota");
} catch (Exception e) {
log.error("[{}] Failed to set resource quota for namespace bundle {}", clientAppId(), nsBundle.toString());
throw new RestException(e);
}
}
use of com.yahoo.pulsar.broker.web.RestException in project pulsar by yahoo.
the class Namespaces method setNamespaceMessageTTL.
@POST
@Path("/{property}/{cluster}/{namespace}/messageTTL")
@ApiOperation(value = "Set message TTL in seconds for namespace")
@ApiResponses(value = { @ApiResponse(code = 403, message = "Don't have admin permission"), @ApiResponse(code = 404, message = "Property or cluster or namespace doesn't exist"), @ApiResponse(code = 412, message = "Invalid TTL") })
public void setNamespaceMessageTTL(@PathParam("property") String property, @PathParam("cluster") String cluster, @PathParam("namespace") String namespace, int messageTTL) {
validateAdminAccessOnProperty(property);
validatePoliciesReadOnlyAccess();
if (messageTTL < 0) {
throw new RestException(Status.PRECONDITION_FAILED, "Invalid value for message TTL");
}
NamespaceName nsName = new NamespaceName(property, cluster, namespace);
Entry<Policies, Stat> policiesNode = null;
try {
// Force to read the data s.t. the watch to the cache content is setup.
policiesNode = policiesCache().getWithStat(path("policies", property, cluster, namespace)).orElseThrow(() -> new RestException(Status.NOT_FOUND, "Namespace " + nsName + " does not exist"));
policiesNode.getKey().message_ttl_in_seconds = messageTTL;
// Write back the new policies into zookeeper
globalZk().setData(path("policies", property, cluster, namespace), jsonMapper().writeValueAsBytes(policiesNode.getKey()), policiesNode.getValue().getVersion());
policiesCache().invalidate(path("policies", property, cluster, namespace));
log.info("[{}] Successfully updated the message TTL on namespace {}/{}/{}", clientAppId(), property, cluster, namespace);
} catch (KeeperException.NoNodeException e) {
log.warn("[{}] Failed to update the message TTL for namespace {}/{}/{}: does not exist", clientAppId(), property, cluster, namespace);
throw new RestException(Status.NOT_FOUND, "Namespace does not exist");
} catch (KeeperException.BadVersionException e) {
log.warn("[{}] Failed to update the message TTL on namespace {}/{}/{} expected policy node version={} : concurrent modification", clientAppId(), property, cluster, namespace, policiesNode.getValue().getVersion());
throw new RestException(Status.CONFLICT, "Concurrent modification");
} catch (Exception e) {
log.error("[{}] Failed to update the message TTL on namespace {}/{}/{}", clientAppId(), property, cluster, namespace, e);
throw new RestException(e);
}
}
use of com.yahoo.pulsar.broker.web.RestException in project pulsar by yahoo.
the class Namespaces method validateBundlesData.
private BundlesData validateBundlesData(BundlesData initialBundles) {
SortedSet<String> partitions = new TreeSet<String>();
for (String partition : initialBundles.getBoundaries()) {
Long partBoundary = Long.decode(partition);
partitions.add(String.format("0x%08x", partBoundary));
}
if (partitions.size() != initialBundles.getBoundaries().size()) {
log.debug("Input bundles included repeated partition points. Ignored.");
}
try {
NamespaceBundleFactory.validateFullRange(partitions);
} catch (IllegalArgumentException iae) {
throw new RestException(Status.BAD_REQUEST, "Input bundles do not cover the whole hash range. first:" + partitions.first() + ", last:" + partitions.last());
}
List<String> bundles = Lists.newArrayList();
bundles.addAll(partitions);
return new BundlesData(bundles);
}
use of com.yahoo.pulsar.broker.web.RestException in project pulsar by yahoo.
the class Namespaces method createNamespace.
@PUT
@Path("/{property}/{cluster}/{namespace}")
@ApiOperation(value = "Creates a new empty namespace with no policies attached.")
@ApiResponses(value = { @ApiResponse(code = 403, message = "Don't have admin permission"), @ApiResponse(code = 404, message = "Property or cluster or namespace doesn't exist"), @ApiResponse(code = 409, message = "Namespace already exists"), @ApiResponse(code = 412, message = "Namespace name is not valid") })
public void createNamespace(@PathParam("property") String property, @PathParam("cluster") String cluster, @PathParam("namespace") String namespace, BundlesData initialBundles) {
validateAdminAccessOnProperty(property);
validatePoliciesReadOnlyAccess();
// check is made at the time of setting replication.
if (!cluster.equals(GLOBAL_CLUSTER)) {
validateClusterForProperty(property, cluster);
}
if (!clusters().contains(cluster)) {
log.warn("[{}] Failed to create namespace. Cluster {} does not exist", clientAppId(), cluster);
throw new RestException(Status.NOT_FOUND, "Cluster does not exist");
}
try {
checkNotNull(propertiesCache().get(path("policies", property)));
} catch (NoNodeException nne) {
log.warn("[{}] Failed to create namespace. Property {} does not exist", clientAppId(), property);
throw new RestException(Status.NOT_FOUND, "Property does not exist");
} catch (RestException e) {
throw e;
} catch (Exception e) {
throw new RestException(e);
}
try {
NamedEntity.checkName(namespace);
policiesCache().invalidate(path("policies", property, cluster, namespace));
Policies policies = new Policies();
if (initialBundles != null && initialBundles.getNumBundles() > 0) {
if (initialBundles.getBoundaries() == null || initialBundles.getBoundaries().size() == 0) {
policies.bundles = getBundles(initialBundles.getNumBundles());
} else {
policies.bundles = validateBundlesData(initialBundles);
}
}
zkCreateOptimistic(path("policies", property, cluster, namespace), jsonMapper().writeValueAsBytes(policies));
log.info("[{}] Created namespace {}/{}/{}", clientAppId(), property, cluster, namespace);
} catch (KeeperException.NodeExistsException e) {
log.warn("[{}] Failed to create namespace {}/{}/{} - already exists", clientAppId(), property, cluster, namespace);
throw new RestException(Status.CONFLICT, "Namespace already exists");
} catch (IllegalArgumentException e) {
log.warn("[{}] Failed to create namespace with invalid name {}", clientAppId(), property, e);
throw new RestException(Status.PRECONDITION_FAILED, "Namespace name is not valid");
} catch (Exception e) {
log.error("[{}] Failed to create namespace {}/{}/{}", clientAppId(), property, cluster, namespace, e);
throw new RestException(e);
}
}
use of com.yahoo.pulsar.broker.web.RestException in project pulsar by yahoo.
the class DestinationLookup method lookupDestinationAsync.
@GET
@Path("persistent/{property}/{cluster}/{namespace}/{dest}")
@Produces(MediaType.APPLICATION_JSON)
public void lookupDestinationAsync(@PathParam("property") String property, @PathParam("cluster") String cluster, @PathParam("namespace") String namespace, @PathParam("dest") @Encoded String dest, @QueryParam("authoritative") @DefaultValue("false") boolean authoritative, @Suspended AsyncResponse asyncResponse) {
dest = Codec.decode(dest);
DestinationName topic = DestinationName.get("persistent", property, cluster, namespace, dest);
if (!pulsar().getBrokerService().getLookupRequestSemaphore().tryAcquire()) {
log.warn("No broker was found available for topic {}", topic);
asyncResponse.resume(new WebApplicationException(Response.Status.SERVICE_UNAVAILABLE));
return;
}
try {
validateClusterOwnership(topic.getCluster());
checkConnect(topic);
validateReplicationSettingsOnNamespace(pulsar(), topic.getNamespaceObject());
} catch (WebApplicationException we) {
// Validation checks failed
log.error("Validation check failed: {}", we.getMessage());
completeLookupResponseExceptionally(asyncResponse, we);
return;
} catch (Throwable t) {
// Validation checks failed with unknown error
log.error("Validation check failed: {}", t.getMessage(), t);
completeLookupResponseExceptionally(asyncResponse, new RestException(t));
return;
}
CompletableFuture<LookupResult> lookupFuture = pulsar().getNamespaceService().getBrokerServiceUrlAsync(topic, authoritative);
lookupFuture.thenAccept(result -> {
if (result == null) {
log.warn("No broker was found available for topic {}", topic);
completeLookupResponseExceptionally(asyncResponse, new WebApplicationException(Response.Status.SERVICE_UNAVAILABLE));
return;
}
if (result.isRedirect()) {
boolean newAuthoritative = this.isLeaderBroker();
URI redirect;
try {
String redirectUrl = isRequestHttps() ? result.getLookupData().getHttpUrlTls() : result.getLookupData().getHttpUrl();
redirect = new URI(String.format("%s%s%s?authoritative=%s", redirectUrl, "/lookup/v2/destination/", topic.getLookupName(), newAuthoritative));
} catch (URISyntaxException e) {
log.error("Error in preparing redirect url for {}: {}", topic, e.getMessage(), e);
completeLookupResponseExceptionally(asyncResponse, e);
return;
}
if (log.isDebugEnabled()) {
log.debug("Redirect lookup for topic {} to {}", topic, redirect);
}
completeLookupResponseExceptionally(asyncResponse, new WebApplicationException(Response.temporaryRedirect(redirect).build()));
} else {
if (log.isDebugEnabled()) {
log.debug("Lookup succeeded for topic {} -- broker: {}", topic, result.getLookupData());
}
completeLookupResponseSuccessfully(asyncResponse, result.getLookupData());
}
}).exceptionally(exception -> {
log.warn("Failed to lookup broker for topic {}: {}", topic, exception.getMessage(), exception);
completeLookupResponseExceptionally(asyncResponse, exception);
return null;
});
}
Aggregations