@SuppressWarnings({"unchecked", "rawtypes"})
  @Override
  public NodeMetadata apply(ServerInfo from) {
    NodeMetadataBuilder builder = new NodeMetadataBuilder();
    builder.ids(from.getUuid());
    builder.name(from.getName());
    builder.location(locationSupplier.get());
    builder.group(parseGroupFromName(from.getName()));

    String imageId = getImageIdFromServer.apply(from);
    if (imageId != null) {
      Image image = findImageForId.apply(imageId);
      if (image != null) {
        builder.operatingSystem(image.getOperatingSystem());
        builder.adminPassword(image.getAdminPassword());
      }
    }
    builder.hardware(
        new HardwareBuilder()
            .ids(from.getUuid())
            .processors(ImmutableList.of(new Processor(1, from.getCpu())))
            .ram(from.getMem())
            .volumes(
                (List)
                    ImmutableList.of(
                        Iterables.transform(from.getDevices().values(), deviceToVolume)))
            .build());
    builder.state(serverStatusToNodeState.get(from.getStatus()));
    builder.publicAddresses(ImmutableSet.<String>of(from.getVnc().getIp()));
    builder.privateAddresses(ImmutableSet.<String>of());
    builder.credentials(credentialStore.get("node#" + from.getUuid()));
    return builder.build();
  }
 @Override
 public void destroyNode(String id) {
   ServerInfo server = getNode(id);
   if (server != null) {
     client.stopServer(id);
     client.destroyServer(id);
     for (Device dev : server.getDevices().values()) client.destroyDrive(dev.getDriveUuid());
   }
 }
  @Override
  public NodeAndInitialCredentials<ServerInfo> createNodeWithGroupEncodedIntoName(
      String tag, String name, Template template) {
    long bootSize =
        (long) (template.getHardware().getVolumes().get(0).getSize() * 1024 * 1024 * 1024l);
    AffinityType affinityType = AffinityType.HDD;
    if (template.getOptions() instanceof CloudSigmaTemplateOptions) {
      CloudSigmaTemplateOptions options =
          CloudSigmaTemplateOptions.class.cast(template.getOptions());
      affinityType = options.getDiskDriveAffinity();
    }
    logger.debug(
        ">> imaging boot drive source(%s) bytes(%d) affinityType(%s)",
        template.getImage().getId(), bootSize, affinityType);
    DriveInfo drive =
        client.cloneDrive(
            template.getImage().getId(),
            template.getImage().getId(),
            new CloneDriveOptions().size(bootSize).affinity(affinityType));
    boolean success = driveNotClaimed.apply(drive);
    logger.debug("<< image(%s) complete(%s)", drive.getUuid(), success);
    if (!success) {
      client.destroyDrive(drive.getUuid());
      throw new IllegalStateException("could not image drive in time!");
    }

    Server toCreate =
        Servers.small(name, drive.getUuid(), defaultVncPassword)
            .mem(template.getHardware().getRam())
            .cpu((int) (template.getHardware().getProcessors().get(0).getSpeed()))
            .build();

    logger.debug(">> creating server");
    ServerInfo from = client.createServer(toCreate);
    logger.debug("<< created server(%s)", from.getUuid());
    logger.debug(">> starting server(%s)", from.getUuid());
    client.startServer(from.getUuid());
    return new NodeAndInitialCredentials<ServerInfo>(
        from,
        from.getUuid(),
        LoginCredentials.builder().password(defaultVncPassword).authenticateSudo(true).build());
  }