public HttpResponse call() throws Exception { HttpResponse response = null; for (; ; ) { HttpRequest request = command.getCurrentRequest(); Q nativeRequest = null; try { for (HttpRequestFilter filter : request.getFilters()) { request = filter.filter(request); } checkRequestHasContentLengthOrChunkedEncoding( request, "After filtering, the request has neither chunked encoding nor content length: " + request); logger.debug("Sending request %s: %s", request.hashCode(), request.getRequestLine()); wirePayloadIfEnabled(wire, request); utils.logRequest(headerLog, request, ">>"); nativeRequest = convert(request); response = invoke(nativeRequest); logger.debug("Receiving response %s: %s", request.hashCode(), response.getStatusLine()); utils.logResponse(headerLog, response, "<<"); if (response.getPayload() != null && wire.enabled()) wire.input(response); int statusCode = response.getStatusCode(); if (statusCode >= 300) { if (shouldContinue(response)) continue; else break; } else { break; } } catch (Exception e) { IOException ioe = Throwables2.getFirstThrowableOfType(e, IOException.class); if (ioe != null) { if (ioe instanceof SSLException) { command.setException( new AuthorizationException( e.getMessage() + " connecting to " + command.getCurrentRequest().getRequestLine(), e)); break; } else if (ioRetryHandler.shouldRetryRequest(command, ioe)) { continue; } } command.setException( new HttpResponseException( e.getMessage() + " connecting to " + command.getCurrentRequest().getRequestLine(), command, null, e)); break; } finally { cleanup(nativeRequest); } } if (command.getException() != null) throw command.getException(); return response; }
/** * Exit if klass has the same type or sub-type as throwable or one of its causes. If exiting, emit * message. */ private static void exitIfThrowableMatches( Throwable throwable, Class klass, Errno errno, String message) { Throwable cause = Throwables2.getFirstThrowableOfType(throwable, klass); if (cause == null) { return; } System.err.format("%s: %s\n", message, cause.getMessage()); System.exit(errno.getErrno()); }
@Override public T get() { TimeoutException ex = null; for (int i = 0; i < 3; i++) { try { ex = null; return delegate.get(); } catch (Exception e) { if ((ex = Throwables2.getFirstThrowableOfType(e, TimeoutException.class)) != null) continue; propagate(e); assert false; return null; } } if (ex != null) propagate(ex); assert false; return null; }
protected <T, C extends Connection<T>> T acquire(C connection) { String errorMessage = String.format("(%s) error acquiring %s", toString(), connection); for (int i = 0; i < sshRetries; i++) { try { connection.clear(); logger.debug(">> (%s) acquiring %s", toString(), connection); T returnVal = connection.create(); logger.debug("<< (%s) acquired %s", toString(), returnVal); return returnVal; } catch (Exception from) { try { connection.clear(); } catch (Exception e1) { logger.warn(from, "<< (%s) error closing connection", toString()); } if (i + 1 == sshRetries) { logger.error(from, "<< " + errorMessage + ": out of retries %d", sshRetries); throw propagate(from, errorMessage); } else if (Throwables2.getFirstThrowableOfType(from, IllegalStateException.class) != null) { logger.warn(from, "<< " + errorMessage + ": " + from.getMessage()); disconnect(); backoffForAttempt(i + 1, errorMessage + ": " + from.getMessage()); connect(); continue; } else if (shouldRetry(from)) { logger.warn(from, "<< " + errorMessage + ": " + from.getMessage()); backoffForAttempt(i + 1, errorMessage + ": " + from.getMessage()); continue; } else { logger.error(from, "<< " + errorMessage + ": exception not retryable"); throw propagate(from, errorMessage); } } } assert false : "should not reach here"; return null; }
@Override public NodeMetadata apply(VirtualMachine from) { // convert the result object to a jclouds NodeMetadata NodeMetadataBuilder builder = new NodeMetadataBuilder(); builder.ids(from.getId() + ""); builder.name(from.getName()); // TODO: in cloudstack 2.2.12, when "name" was set fine on the backend, // but wrong API response was returned to the user // http://bugs.cloud.com/show_bug.cgi?id=11664 // // we set displayName to the same value as name, but this could be wrong // on hosts not started with jclouds builder.hostname(from.getDisplayName()); builder.location(findLocationForVirtualMachine.apply(from)); builder.group(parseGroupFromName(from.getDisplayName())); Image image = findImageForVirtualMachine.apply(from); if (image != null) { builder.imageId(image.getId()); builder.operatingSystem(image.getOperatingSystem()); } builder.hardware( new HardwareBuilder() .ids(from.getServiceOfferingId() + "") .name(from.getServiceOfferingName() + "") // .tags() TODO .processors(ImmutableList.of(new Processor(from.getCpuCount(), from.getCpuSpeed()))) .ram((int) from.getMemory()) // .hypervisor(from.getHypervisor()) // .build()); builder.state(vmStateToNodeState.get(from.getState())); Set<String> publicAddresses = newHashSet(), privateAddresses = newHashSet(); if (from.getIPAddress() != null) { boolean isPrivate = isPrivateIPAddress(from.getIPAddress()); if (isPrivate) { privateAddresses.add(from.getIPAddress()); } else { publicAddresses.add(from.getIPAddress()); } } for (NIC nic : from.getNICs()) { if (nic.getIPAddress() != null) { if (isPrivateIPAddress(nic.getIPAddress())) { privateAddresses.add(nic.getIPAddress()); } else { publicAddresses.add(nic.getIPAddress()); } } } try { /* Also add to the list of public IPs any public IP address that has a forwarding rule that links to this machine */ Iterables.addAll( publicAddresses, transform( filter( getIPForwardingRulesByVirtualMachine.getUnchecked(from.getId()), new Predicate<IPForwardingRule>() { @Override public boolean apply(@Nullable IPForwardingRule rule) { return !"Deleting".equals(rule.getState()); } }), new Function<IPForwardingRule, String>() { @Override public String apply(@Nullable IPForwardingRule rule) { return rule.getIPAddress(); } })); } catch (UncheckedExecutionException e) { if (Throwables2.getFirstThrowableOfType(e, ResourceNotFoundException.class) == null) { Throwables.propagateIfPossible(e.getCause()); throw e; } } return builder.privateAddresses(privateAddresses).publicAddresses(publicAddresses).build(); }
@Test( timeOut = 5 * 60 * 1000, dependsOnMethods = {"testCreateContainer", "testCreatePublicContainer"}) public void testObjectOperations() throws Exception { String data = "Here is my data"; // Test PUT with string data, ETag hash, and a piece of metadata AzureBlob object = getApi().newBlob(); object.getProperties().setName("object"); object.setPayload(data); Payloads.calculateMD5(object); object.getProperties().getContentMetadata().setContentType("text/plain"); object.getProperties().getMetadata().put("mykey", "metadata-value"); byte[] md5 = object.getProperties().getContentMetadata().getContentMD5(); String newEtag = getApi().putBlob(privateContainer, object); assertEquals( CryptoStreams.hex(md5), CryptoStreams.hex(object.getProperties().getContentMetadata().getContentMD5())); // Test HEAD of missing object assert getApi().getBlobProperties(privateContainer, "non-existent-object") == null; // Test HEAD of object BlobProperties metadata = getApi().getBlobProperties(privateContainer, object.getProperties().getName()); // TODO assertEquals(metadata.getName(), // object.getProperties().getName()); // we can't check this while hacking around lack of content-md5, as GET of // the first byte will // show incorrect length 1, the returned size, as opposed to the real // length. This is an ok // tradeoff, as a container list will contain the correct size of the // objects in an // inexpensive fashion // http://code.google.com/p/jclouds/issues/detail?id=92 // assertEquals(metadata.getSize(), data.length()); assertEquals(metadata.getContentMetadata().getContentType(), "text/plain"); // Azure doesn't return the Content-MD5 on head request.. assertEquals( CryptoStreams.hex(md5), CryptoStreams.hex(object.getProperties().getContentMetadata().getContentMD5())); assertEquals(metadata.getETag(), newEtag); assertEquals(metadata.getMetadata().entrySet().size(), 1); assertEquals(metadata.getMetadata().get("mykey"), "metadata-value"); // // Test POST to update object's metadata // Multimap<String, String> userMetadata = LinkedHashMultimap.create(); // userMetadata.put("New-Metadata-1", "value-1"); // userMetadata.put("New-Metadata-2", "value-2"); // assertTrue(getApi().setBlobProperties(privateContainer, // object.getProperties().getName(), // userMetadata)); // Test GET of missing object assert getApi().getBlob(privateContainer, "non-existent-object") == null; // Test GET of object (including updated metadata) AzureBlob getBlob = getApi().getBlob(privateContainer, object.getProperties().getName()); assertEquals(Strings2.toString(getBlob.getPayload()), data); // TODO assertEquals(getBlob.getName(), object.getProperties().getName()); assertEquals( getBlob.getPayload().getContentMetadata().getContentLength(), Long.valueOf(data.length())); assertEquals(getBlob.getProperties().getContentMetadata().getContentType(), "text/plain"); assertEquals( CryptoStreams.hex(md5), CryptoStreams.hex(getBlob.getProperties().getContentMetadata().getContentMD5())); assertEquals(newEtag, getBlob.getProperties().getETag()); // wait until we can update metadata // assertEquals(getBlob.getProperties().getMetadata().entries().size(), // 2); // assertEquals( // Iterables.getLast(getBlob.getProperties().getMetadata().get("New-Metadata-1")), // "value-1"); // assertEquals( // Iterables.getLast(getBlob.getProperties().getMetadata().get("New-Metadata-2")), // "value-2"); assertEquals(metadata.getMetadata().entrySet().size(), 1); assertEquals(metadata.getMetadata().get("mykey"), "metadata-value"); // test listing ListBlobsResponse response = getApi() .listBlobs( privateContainer, ListBlobsOptions.Builder.prefix( object .getProperties() .getName() .substring(0, object.getProperties().getName().length() - 1)) .maxResults(1) .includeMetadata()); assertEquals(response.size(), 1); assertEquals(Iterables.getOnlyElement(response).getName(), object.getProperties().getName()); assertEquals( Iterables.getOnlyElement(response).getMetadata(), ImmutableMap.of("mykey", "metadata-value")); // Test PUT with invalid ETag (as if object's data was corrupted in // transit) String correctEtag = newEtag; String incorrectEtag = "0" + correctEtag.substring(1); object.getProperties().setETag(incorrectEtag); try { getApi().putBlob(privateContainer, object); } catch (Throwable e) { assertEquals(e.getCause().getClass(), HttpResponseException.class); assertEquals(((HttpResponseException) e.getCause()).getResponse().getStatusCode(), 422); } ByteArrayInputStream bais = new ByteArrayInputStream(data.getBytes(Charsets.UTF_8)); object = getApi().newBlob(); object.getProperties().setName("chunked-object"); object.setPayload(bais); object.getPayload().getContentMetadata().setContentLength(Long.valueOf(data.getBytes().length)); newEtag = getApi().putBlob(privateContainer, object); assertEquals( CryptoStreams.hex(md5), CryptoStreams.hex(getBlob.getProperties().getContentMetadata().getContentMD5())); // Test GET with options // Non-matching ETag try { getApi() .getBlob( privateContainer, object.getProperties().getName(), GetOptions.Builder.ifETagDoesntMatch(newEtag)); } catch (Exception e) { HttpResponseException httpEx = Throwables2.getFirstThrowableOfType(e, HttpResponseException.class); assert (httpEx != null) : "expected http exception, not " + e; assertEquals(httpEx.getResponse().getStatusCode(), 304); } // Matching ETag TODO this shouldn't fail!!! try { getBlob = getApi() .getBlob( privateContainer, object.getProperties().getName(), GetOptions.Builder.ifETagMatches(newEtag)); assertEquals(getBlob.getProperties().getETag(), newEtag); } catch (HttpResponseException e) { assertEquals(e.getResponse().getStatusCode(), 412); } // Range // doesn't work per // http://social.msdn.microsoft.com/Forums/en-US/windowsazure/thread/479fa63f-51df-4b66-96b5-33ae362747b6 // getBlob = getApi() // .getBlob(privateContainer, object.getProperties().getName(), // GetOptions.Builder.startAt(8)).get(120, // TimeUnit.SECONDS); // assertEquals(Utils.toStringAndClose((InputStream) getBlob.getData()), // data.substring(8)); getApi().deleteBlob(privateContainer, "object"); getApi().deleteBlob(privateContainer, "chunked-object"); }