private void generateDownloadManifests(final String imageId) {
   // lookup all reservations that reference the newly available image id
   final List<VmInstance> pendingInstances =
       VmInstances.list(
           new Predicate<VmInstance>() {
             @Override
             public boolean apply(VmInstance arg0) {
               return imageId.equals(arg0.getBootRecord().getMachineImageId())
                   && VmState.PENDING.equals(arg0.getState());
             }
           });
   for (final VmInstance instance : pendingInstances) {
     final String reservationId = instance.getReservationId();
     final String partitionName = instance.getPartition();
     final Partition partition = Partitions.lookupByName(partitionName);
     final MachineImageInfo machineImage = LookupMachine.INSTANCE.apply(imageId);
     try {
       final String manifestLocation =
           DownloadManifestFactory.generateDownloadManifest(
               new ImageManifestFile(
                   machineImage.getRunManifestLocation(), BundleImageManifest.INSTANCE),
               partition.getNodeCertificate().getPublicKey(),
               reservationId);
       LOG.debug(
           String.format(
               "Generated download manifest for instance %s", instance.getDisplayName()));
     } catch (final Exception ex) {
       LOG.error(
           String.format(
               "Failed to generate download manifest for instance %s", instance.getDisplayName()),
           ex);
     }
   }
 }
예제 #2
0
 private List<Cluster> doPrivilegedLookup(String partitionName, String vmTypeName)
     throws NotEnoughResourcesException {
   if (Partition.DEFAULT_NAME.equals(partitionName)) {
     Iterable<Cluster> authorizedClusters =
         Iterables.filter(
             Clusters.getInstance().listValues(),
             RestrictedTypes.filterPrivilegedWithoutOwner());
     Multimap<VmTypeAvailability, Cluster> sorted = TreeMultimap.create();
     for (Cluster c : authorizedClusters) {
       sorted.put(c.getNodeState().getAvailability(vmTypeName), c);
     }
     if (sorted.isEmpty()) {
       throw new NotEnoughResourcesException(
           "Not enough resources: no availability zone is available in which you have permissions to run instances.");
     } else {
       return Lists.newArrayList(sorted.values());
     }
   } else {
     ServiceConfiguration ccConfig =
         Topology.lookup(ClusterController.class, Partitions.lookupByName(partitionName));
     Cluster cluster = Clusters.lookup(ccConfig);
     if (cluster == null) {
       throw new NotEnoughResourcesException("Can't find cluster " + partitionName);
     }
     if (!RestrictedTypes.filterPrivilegedWithoutOwner().apply(cluster)) {
       throw new NotEnoughResourcesException("Not authorized to use cluster " + partitionName);
     }
     return Lists.newArrayList(cluster);
   }
 }
예제 #3
0
  public CreateVolumeResponseType CreateVolume(final CreateVolumeType request)
      throws EucalyptusCloudException, AuthException {
    Context ctx = Contexts.lookup();
    Long volSize = request.getSize() != null ? Long.parseLong(request.getSize()) : null;
    final String snapId = request.getSnapshotId();
    String partition = request.getAvailabilityZone();

    if ((request.getSnapshotId() == null && request.getSize() == null)) {
      throw new EucalyptusCloudException("One of size or snapshotId is required as a parameter.");
    }

    if (snapId != null) {
      try {
        Transactions.find(Snapshot.named(null, snapId));
      } catch (ExecutionException ex) {
        throw new EucalyptusCloudException(
            "Failed to create volume because the referenced snapshot id is invalid: " + snapId);
      }
    }
    final Integer newSize = new Integer(request.getSize() != null ? request.getSize() : "-1");
    Exception lastEx = null;
    for (int i = 0; i < VOL_CREATE_RETRIES; i++) {
      try {
        final ServiceConfiguration sc =
            Topology.lookup(Storage.class, Partitions.lookupByName(partition));
        final UserFullName owner = ctx.getUserFullName();
        Function<Long, Volume> allocator =
            new Function<Long, Volume>() {

              @Override
              public Volume apply(Long size) {
                try {
                  return Volumes.createStorageVolume(
                      sc, owner, snapId, Ints.checkedCast(size), request);
                } catch (ExecutionException ex) {
                  throw Exceptions.toUndeclared(ex);
                }
              }
            };
        Volume newVol = RestrictedTypes.allocateMeasurableResource(newSize.longValue(), allocator);
        CreateVolumeResponseType reply = request.getReply();
        reply.setVolume(newVol.morph(new edu.ucsb.eucalyptus.msgs.Volume()));
        return reply;
      } catch (RuntimeException ex) {
        LOG.error(ex, ex);
        if (!(ex.getCause() instanceof ExecutionException)) {
          throw ex;
        } else {
          lastEx = ex;
        }
      }
    }
    throw new EucalyptusCloudException(
        "Failed to create volume after " + VOL_CREATE_RETRIES + " because of: " + lastEx, lastEx);
  }
예제 #4
0
 @Override
 public boolean apply(Allocation allocInfo) throws MetadataException {
   RunInstancesType request = allocInfo.getRequest();
   String zoneName = request.getAvailabilityZone();
   if (Clusters.getInstance().listValues().isEmpty()) {
     LOG.debug("enabled values: " + Joiner.on("\n").join(Clusters.getInstance().listValues()));
     LOG.debug("disabled values: " + Joiner.on("\n").join(Clusters.getInstance().listValues()));
     throw new VerificationException(
         "Not enough resources: no cluster controller is currently available to run instances.");
   } else if (Partitions.exists(zoneName)) {
     Partition partition = Partitions.lookupByName(zoneName);
     allocInfo.setPartition(partition);
   } else if (Partition.DEFAULT_NAME.equals(zoneName)) {
     Partition partition = Partition.DEFAULT;
     allocInfo.setPartition(partition);
   } else {
     throw new VerificationException(
         "Not enough resources: no cluster controller is currently available to run instances.");
   }
   return true;
 }
예제 #5
0
  public static Volume checkVolumeReady(final Volume vol) throws EucalyptusCloudException {
    if (vol.isReady()) {
      return vol;
    } else {
      // TODO:GRZE:REMOVE temporary workaround to update the volume state.
      final ServiceConfiguration sc =
          Topology.lookup(Storage.class, Partitions.lookupByName(vol.getPartition()));
      final DescribeStorageVolumesType descVols =
          new DescribeStorageVolumesType(Lists.newArrayList(vol.getDisplayName()));
      try {
        Transactions.one(
            Volume.named(null, vol.getDisplayName()),
            new Callback<Volume>() {

              @Override
              public void fire(final Volume t) {
                try {
                  final DescribeStorageVolumesResponseType volState =
                      AsyncRequests.sendSync(sc, descVols);
                  if (!volState.getVolumeSet().isEmpty()) {
                    final State newVolumeState =
                        Volumes.transformStorageState(
                            vol.getState(), volState.getVolumeSet().get(0).getStatus());
                    vol.setState(newVolumeState);
                  }
                } catch (final Exception ex) {
                  LOG.error(ex);
                  Logs.extreme().error(ex, ex);
                  throw Exceptions.toUndeclared(
                      "Failed to update the volume state "
                          + vol.getDisplayName()
                          + " not yet ready",
                      ex);
                }
              }
            });
      } catch (final ExecutionException ex) {
        throw new EucalyptusCloudException(ex.getCause());
      }
      if (!vol.isReady()) {
        throw new EucalyptusCloudException("Volume " + vol.getDisplayName() + " not yet ready");
      }
      return vol;
    }
  }
예제 #6
0
 static Map<String, StorageVolume> updateVolumesInPartition(final String partition) {
   final Map<String, StorageVolume> idStorageVolumeMap = Maps.newHashMap();
   final ServiceConfiguration scConfig =
       Topology.lookup(Storage.class, Partitions.lookupByName(partition));
   try {
     final DescribeStorageVolumesResponseType volState =
         AsyncRequests.sendSync(scConfig, new DescribeStorageVolumesType());
     for (final StorageVolume vol : volState.getVolumeSet()) {
       LOG.trace(
           "Volume states: "
               + vol.getVolumeId()
               + " "
               + vol.getStatus()
               + " "
               + vol.getActualDeviceName());
       idStorageVolumeMap.put(vol.getVolumeId(), vol);
     }
   } catch (final Exception ex) {
     LOG.error(ex);
     Logs.extreme().error(ex, ex);
   }
   return idStorageVolumeMap;
 }
예제 #7
0
  public AttachVolumeResponseType AttachVolume(AttachVolumeType request)
      throws EucalyptusCloudException {
    AttachVolumeResponseType reply = (AttachVolumeResponseType) request.getReply();
    final String deviceName = request.getDevice();
    final String volumeId = request.getVolumeId();
    final Context ctx = Contexts.lookup();

    if (request.getDevice() == null
        || request.getDevice().endsWith("sda")
        || request.getDevice().endsWith("sdb")) {
      throw new EucalyptusCloudException("Invalid device name specified: " + request.getDevice());
    }
    VmInstance vm = null;
    try {
      vm = RestrictedTypes.doPrivileged(request.getInstanceId(), VmInstance.class);
    } catch (NoSuchElementException ex) {
      LOG.debug(ex, ex);
      throw new EucalyptusCloudException("Instance does not exist: " + request.getInstanceId(), ex);
    } catch (Exception ex) {
      LOG.debug(ex, ex);
      throw new EucalyptusCloudException(ex.getMessage(), ex);
    }
    AccountFullName ownerFullName = ctx.getUserFullName().asAccountFullName();
    Volume volume = Volumes.lookup(ownerFullName, volumeId);
    if (!RestrictedTypes.filterPrivileged().apply(volume)) {
      throw new EucalyptusCloudException(
          "Not authorized to attach volume "
              + request.getVolumeId()
              + " by "
              + ctx.getUser().getName());
    }
    try {
      vm.lookupVolumeAttachmentByDevice(deviceName);
      throw new EucalyptusCloudException(
          "Already have a device attached to: " + request.getDevice());
    } catch (NoSuchElementException ex1) {
      /** no attachment * */
    }
    try {
      VmInstances.lookupVolumeAttachment(volumeId);
      throw new EucalyptusCloudException("Volume already attached: " + request.getVolumeId());
    } catch (NoSuchElementException ex1) {
      /** no attachment * */
    }

    Partition volPartition = Partitions.lookupByName(volume.getPartition());
    ServiceConfiguration sc = Topology.lookup(Storage.class, volPartition);
    ServiceConfiguration scVm = Topology.lookup(Storage.class, vm.lookupPartition());
    if (!sc.equals(scVm)) {
      throw new EucalyptusCloudException(
          "Can only attach volumes in the same zone: " + request.getVolumeId());
    }
    ServiceConfiguration ccConfig = Topology.lookup(ClusterController.class, vm.lookupPartition());
    AttachStorageVolumeResponseType scAttachResponse;
    try {
      AttachStorageVolumeType req =
          new AttachStorageVolumeType(Nodes.lookupIqn(vm), volume.getDisplayName());
      scAttachResponse = AsyncRequests.sendSync(sc, req);
    } catch (Exception e) {
      LOG.debug(e, e);
      throw new EucalyptusCloudException(e.getMessage(), e);
    }
    request.setRemoteDevice(scAttachResponse.getRemoteDeviceString());

    AttachedVolume attachVol =
        new AttachedVolume(
            volume.getDisplayName(),
            vm.getInstanceId(),
            request.getDevice(),
            request.getRemoteDevice());
    vm.addTransientVolume(deviceName, scAttachResponse.getRemoteDeviceString(), volume);
    AsyncRequests.newRequest(new VolumeAttachCallback(request)).dispatch(ccConfig);

    EventRecord.here(VolumeManager.class, EventClass.VOLUME, EventType.VOLUME_ATTACH)
        .withDetails(
            volume.getOwner().toString(), volume.getDisplayName(), "instance", vm.getInstanceId())
        .withDetails("partition", vm.getPartition().toString())
        .info();
    reply.setAttachedVolume(attachVol);
    return reply;
  }
예제 #8
0
 public Partition lookupPartition() {
   return Partitions.lookupByName(this.partitionName);
 }