Пример #1
0
  private void handle(final ExpungeImageMsg msg) {
    final ExpungeImageReply reply = new ExpungeImageReply();
    final ImageBackupStorageRefVO ref =
        CollectionUtils.find(
            self.getBackupStorageRefs(),
            new Function<ImageBackupStorageRefVO, ImageBackupStorageRefVO>() {
              @Override
              public ImageBackupStorageRefVO call(ImageBackupStorageRefVO arg) {
                return arg.getBackupStorageUuid().equals(msg.getBackupStorageUuid()) ? arg : null;
              }
            });

    if (ref == null) {
      logger.debug(
          String.format(
              "cannot find reference for the image[uuid:%s] on the backup storage[uuid:%s], assume it's been deleted",
              self.getUuid(), msg.getBackupStorageUuid()));
      bus.reply(msg, reply);
      return;
    }

    DeleteBitsOnBackupStorageMsg dmsg = new DeleteBitsOnBackupStorageMsg();
    dmsg.setBackupStorageUuid(ref.getBackupStorageUuid());
    dmsg.setInstallPath(ref.getInstallPath());
    bus.makeTargetServiceIdByResourceUuid(
        dmsg, BackupStorageConstant.SERVICE_ID, dmsg.getBackupStorageUuid());
    bus.send(
        dmsg,
        new CloudBusCallBack(msg) {
          @Override
          public void run(MessageReply r) {
            if (!r.isSuccess()) {
              // TODO
              logger.warn(
                  String.format(
                      "failed to delete image[uuid:%s, name:%s] from backup storage[uuid:%s] because %s, need to garbage collect it",
                      self.getUuid(), self.getName(), r.getError(), ref.getBackupStorageUuid()));
              reply.setError(r.getError());
            } else {
              returnBackupStorageCapacity(ref.getBackupStorageUuid(), self.getSize());
              dbf.remove(ref);
              logger.debug(
                  String.format(
                      "successfully expunged the image[uuid: %s, name: %s] on the backup storage[uuid: %s]",
                      self.getUuid(), self.getName(), ref.getBackupStorageUuid()));
              self = dbf.findByUuid(self.getUuid(), ImageVO.class);
              if (self.getBackupStorageRefs().isEmpty()) {
                logger.debug(
                    String.format(
                        "the image[uuid:%s, name:%s] has been expunged on all backup storage, remove it from database",
                        self.getUuid(), self.getName()));
                dbf.remove(self);
              }
            }

            bus.reply(msg, reply);
          }
        });
  }
Пример #2
0
  private void handle(APIChangeImageStateMsg msg) {
    ImageStateEvent sevt = ImageStateEvent.valueOf(msg.getStateEvent());
    if (sevt == ImageStateEvent.disable) {
      self.setState(ImageState.Disabled);
    } else {
      self.setState(ImageState.Enabled);
    }
    self = dbf.updateAndRefresh(self);

    APIChangeImageStateEvent evt = new APIChangeImageStateEvent(msg.getId());
    evt.setInventory(ImageInventory.valueOf(self));
    bus.publish(evt);
  }
Пример #3
0
  private void handle(APIUpdateImageMsg msg) {
    boolean update = false;
    if (msg.getName() != null) {
      self.setName(msg.getName());
      update = true;
    }
    if (msg.getDescription() != null) {
      self.setDescription(msg.getDescription());
      update = true;
    }
    if (msg.getSystem() != null) {
      self.setSystem(msg.getSystem());
      update = true;
    }
    if (msg.getGuestOsType() != null) {
      self.setGuestOsType(msg.getGuestOsType());
      update = true;
    }
    if (msg.getMediaType() != null) {
      self.setMediaType(ImageMediaType.valueOf(msg.getMediaType()));
      update = true;
    }
    if (msg.getFormat() != null) {
      self.setFormat(msg.getFormat());
      update = true;
    }
    if (msg.getPlatform() != null) {
      self.setPlatform(ImagePlatform.valueOf(msg.getPlatform()));
      update = true;
    }
    if (update) {
      self = dbf.updateAndRefresh(self);
    }

    APIUpdateImageEvent evt = new APIUpdateImageEvent(msg.getId());
    evt.setInventory(getSelfInventory());
    bus.publish(evt);
  }
Пример #4
0
  private void handle(final APIExpungeImageMsg msg) {
    List<String> bsUuids = new ArrayList<String>();
    if (msg.getBackupStorageUuids() == null || msg.getBackupStorageUuids().isEmpty()) {
      bsUuids =
          CollectionUtils.transformToList(
              self.getBackupStorageRefs(),
              new Function<String, ImageBackupStorageRefVO>() {
                @Override
                public String call(ImageBackupStorageRefVO arg) {
                  return ImageStatus.Deleted == arg.getStatus() ? arg.getBackupStorageUuid() : null;
                }
              });

      if (bsUuids.isEmpty()) {
        throw new OperationFailureException(
            errf.stringToOperationError(
                String.format(
                    "the image[uuid:%s, name:%s] is not deleted on any backup storage",
                    self.getUuid(), self.getName())));
      }
    } else {
      for (final String bsUuid : msg.getBackupStorageUuids()) {
        ImageBackupStorageRefVO ref =
            CollectionUtils.find(
                self.getBackupStorageRefs(),
                new Function<ImageBackupStorageRefVO, ImageBackupStorageRefVO>() {
                  @Override
                  public ImageBackupStorageRefVO call(ImageBackupStorageRefVO arg) {
                    return arg.getBackupStorageUuid().equals(bsUuid) ? arg : null;
                  }
                });

        if (ref == null) {
          throw new OperationFailureException(
              errf.stringToInvalidArgumentError(
                  String.format(
                      "the image[uuid:%s, name:%s] is not on the backup storage[uuid:%s]",
                      self.getUuid(), self.getName(), bsUuid)));
        }

        if (ref.getStatus() != ImageStatus.Deleted) {
          throw new OperationFailureException(
              errf.stringToInvalidArgumentError(
                  String.format(
                      "the image[uuid:%s, name:%s] is not deleted on the backup storage[uuid:%s]",
                      self.getUuid(), self.getName(), bsUuid)));
        }

        bsUuids.add(bsUuid);
      }
    }

    List<ExpungeImageMsg> emsgs =
        CollectionUtils.transformToList(
            bsUuids,
            new Function<ExpungeImageMsg, String>() {
              @Override
              public ExpungeImageMsg call(String arg) {
                ExpungeImageMsg emsg = new ExpungeImageMsg();
                emsg.setBackupStorageUuid(arg);
                emsg.setImageUuid(self.getUuid());
                bus.makeTargetServiceIdByResourceUuid(
                    emsg, ImageConstant.SERVICE_ID, self.getUuid());
                return emsg;
              }
            });

    final List<String> finalBsUuids = bsUuids;
    final APIExpungeImageEvent evt = new APIExpungeImageEvent(msg.getId());
    bus.send(
        emsgs,
        new CloudBusListCallBack(msg) {
          @Override
          public void run(List<MessageReply> replies) {
            for (MessageReply r : replies) {
              if (!r.isSuccess()) {
                String bsUuid = finalBsUuids.get(replies.indexOf(r));
                // TODO
                logger.warn(
                    String.format(
                        "failed to expunge the image[uuid:%s, name:%s] on the backup storage[uuid:%s]"
                            + ", %s",
                        self.getUuid(), self.getName(), bsUuid, r.getError()));
              }
            }

            bus.publish(evt);
          }
        });
  }
Пример #5
0
  private void handle(APIRecoverImageMsg msg) {
    List<String> toRecoverBsUuids;
    if (msg.getBackupStorageUuids() == null || msg.getBackupStorageUuids().isEmpty()) {
      toRecoverBsUuids =
          CollectionUtils.transformToList(
              self.getBackupStorageRefs(),
              new Function<String, ImageBackupStorageRefVO>() {
                @Override
                public String call(ImageBackupStorageRefVO arg) {
                  return arg.getStatus() == ImageStatus.Deleted ? arg.getBackupStorageUuid() : null;
                }
              });

      if (toRecoverBsUuids.isEmpty()) {
        throw new OperationFailureException(
            errf.stringToOperationError(
                String.format(
                    "the image[uuid:%s, name:%s] is not deleted on any backup storage",
                    self.getUuid(), self.getName())));
      }
    } else {
      toRecoverBsUuids = new ArrayList<String>();
      for (final String bsUuid : msg.getBackupStorageUuids()) {
        ImageBackupStorageRefVO ref =
            CollectionUtils.find(
                self.getBackupStorageRefs(),
                new Function<ImageBackupStorageRefVO, ImageBackupStorageRefVO>() {
                  @Override
                  public ImageBackupStorageRefVO call(ImageBackupStorageRefVO arg) {
                    return bsUuid.equals(arg.getBackupStorageUuid()) ? arg : null;
                  }
                });

        if (ref == null) {
          throw new OperationFailureException(
              errf.stringToInvalidArgumentError(
                  String.format(
                      "the image[uuid:%s, name:%s] is not on the backup storage[uuid:%s]",
                      self.getUuid(), self.getName(), bsUuid)));
        }

        if (ref.getStatus() != ImageStatus.Deleted) {
          throw new OperationFailureException(
              errf.stringToInvalidArgumentError(
                  String.format(
                      "the image[uuid:%s, name:%s]'s status[%s] is not Deleted on the backup storage[uuid:%s]",
                      self.getUuid(), self.getName(), ref.getStatus(), bsUuid)));
        }

        toRecoverBsUuids.add(bsUuid);
      }
    }

    for (ImageBackupStorageRefVO ref : self.getBackupStorageRefs()) {
      if (toRecoverBsUuids.contains(ref.getBackupStorageUuid())) {
        ref.setStatus(ImageStatus.Ready);
        dbf.update(ref);
      }
    }

    self.setStatus(ImageStatus.Ready);
    self = dbf.updateAndRefresh(self);

    logger.debug(
        String.format(
            "successfully recovered the image[uuid:%s, name:%s] on the backup storage%s",
            self.getUuid(), self.getName(), toRecoverBsUuids));
    APIRecoverImageEvent evt = new APIRecoverImageEvent(msg.getId());
    evt.setInventory(getSelfInventory());
    bus.publish(evt);
  }
Пример #6
0
  private void handle(final ImageDeletionMsg msg) {
    final ImageDeletionReply reply = new ImageDeletionReply();
    if (self.getBackupStorageRefs().isEmpty()) {
      // the image is not on any backup storage; mostly likely the image is not in the status of
      // Ready, for example
      // it's still downloading
      // in this case, we directly delete it from the database
      dbf.remove(self);
      bus.reply(msg, reply);
      return;
    }

    final ImageDeletionPolicy deletionPolicy =
        msg.getDeletionPolicy() == null
            ? deletionPolicyMgr.getDeletionPolicy(self.getUuid())
            : ImageDeletionPolicy.valueOf(msg.getDeletionPolicy());
    FlowChain chain = FlowChainBuilder.newSimpleFlowChain();
    chain.setName(String.format("delete-image-%s", self.getUuid()));
    Collection<ImageBackupStorageRefVO> toDelete =
        msg.getBackupStorageUuids() == null
            ? self.getBackupStorageRefs()
            : CollectionUtils.transformToList(
                self.getBackupStorageRefs(),
                new Function<ImageBackupStorageRefVO, ImageBackupStorageRefVO>() {
                  @Override
                  public ImageBackupStorageRefVO call(ImageBackupStorageRefVO arg) {
                    return msg.getBackupStorageUuids().contains(arg.getBackupStorageUuid())
                        ? arg
                        : null;
                  }
                });

    for (final ImageBackupStorageRefVO ref : toDelete) {
      chain.then(
          new NoRollbackFlow() {
            String __name__ =
                String.format(
                    "delete-image-%s-from-backup-storage-%s",
                    self.getUuid(), ref.getBackupStorageUuid());

            @Override
            public void run(final FlowTrigger trigger, Map data) {
              if (deletionPolicy == ImageDeletionPolicy.Direct) {
                DeleteBitsOnBackupStorageMsg dmsg = new DeleteBitsOnBackupStorageMsg();
                dmsg.setBackupStorageUuid(ref.getBackupStorageUuid());
                dmsg.setInstallPath(ref.getInstallPath());
                bus.makeTargetServiceIdByResourceUuid(
                    dmsg, BackupStorageConstant.SERVICE_ID, dmsg.getBackupStorageUuid());
                bus.send(
                    dmsg,
                    new CloudBusCallBack(trigger) {
                      @Override
                      public void run(MessageReply reply) {
                        if (!reply.isSuccess()) {
                          // TODO
                          logger.warn(
                              String.format(
                                  "failed to delete image[uuid:%s, name:%s] from backup storage[uuid:%s] because %s, need to garbage collect it",
                                  self.getUuid(),
                                  self.getName(),
                                  reply.getError(),
                                  ref.getBackupStorageUuid()));
                        } else {
                          returnBackupStorageCapacity(ref.getBackupStorageUuid(), self.getSize());
                          dbf.remove(ref);
                        }
                        trigger.next();
                      }
                    });
              } else if (deletionPolicy == ImageDeletionPolicy.DeleteReference) {
                dbf.remove(ref);
                logger.debug(
                    String.format(
                        "delete the image[uuid: %s, name:%s]'s reference of the backup storage[uuid:%s]",
                        self.getUuid(), self.getName(), ref.getBackupStorageUuid()));
                trigger.next();
              } else {
                ref.setStatus(ImageStatus.Deleted);
                dbf.update(ref);
                trigger.next();
              }
            }
          });
    }

    chain
        .done(
            new FlowDoneHandler(msg) {
              @Override
              public void handle(Map data) {
                self = dbf.reload(self);
                if (self.getBackupStorageRefs().isEmpty()) {
                  dbf.remove(self);
                  if (deletionPolicy == ImageDeletionPolicy.DeleteReference) {
                    logger.debug(
                        String.format(
                            "successfully directly deleted the image[uuid:%s, name:%s] from the database,"
                                + " as the policy is DeleteReference, it's still on the physical backup storage",
                            self.getUuid(), self.getName()));
                  } else {
                    logger.debug(
                        String.format(
                            "successfully directly deleted the image[uuid:%s, name:%s]",
                            self.getUuid(), self.getName()));
                  }
                } else {
                  int deleteCount = 0;
                  for (ImageBackupStorageRefVO ref : self.getBackupStorageRefs()) {
                    if (ref.getStatus() == ImageStatus.Deleted) {
                      deleteCount++;
                    }
                  }
                  if (deleteCount == self.getBackupStorageRefs().size()) {
                    self.setStatus(ImageStatus.Deleted);
                    self = dbf.updateAndRefresh(self);
                    logger.debug(
                        String.format(
                            "successfully deleted the image[uuid:%s, name:%s] with deletion policy[%s]",
                            self.getUuid(), self.getName(), deletionPolicy));
                  }
                }

                bus.reply(msg, reply);
              }
            })
        .error(
            new FlowErrorHandler(msg) {
              @Override
              public void handle(ErrorCode errCode, Map data) {
                reply.setError(errCode);
                bus.reply(msg, reply);
              }
            })
        .start();
  }
Пример #7
0
  @Override
  protected void startVmFromNewCreate(
      final StartNewCreatedVmInstanceMsg msg, final SyncTaskChain taskChain) {
    boolean callNext = true;
    try {
      refreshVO();
      ErrorCode allowed = validateOperationByState(msg, self.getState(), null);
      if (allowed != null) {
        bus.replyErrorByMessageType(msg, allowed);
        return;
      }
      ErrorCode preCreated = extEmitter.preStartNewCreatedVm(msg.getVmInstanceInventory());
      if (preCreated != null) {
        bus.replyErrorByMessageType(msg, preCreated);
        return;
      }

      StartNewCreatedApplianceVmMsg smsg = (StartNewCreatedApplianceVmMsg) msg;
      ApplianceVmSpec aspec = smsg.getApplianceVmSpec();

      final VmInstanceSpec spec = new VmInstanceSpec();
      spec.setVmInventory(msg.getVmInstanceInventory());
      if (msg.getL3NetworkUuids() != null && !msg.getL3NetworkUuids().isEmpty()) {
        SimpleQuery<L3NetworkVO> nwquery = dbf.createQuery(L3NetworkVO.class);
        nwquery.add(L3NetworkVO_.uuid, SimpleQuery.Op.IN, msg.getL3NetworkUuids());
        List<L3NetworkVO> vos = nwquery.list();
        List<L3NetworkInventory> nws = L3NetworkInventory.valueOf(vos);
        spec.setL3Networks(nws);
      } else {
        spec.setL3Networks(new ArrayList<L3NetworkInventory>(0));
      }

      if (msg.getDataDiskOfferingUuids() != null && !msg.getDataDiskOfferingUuids().isEmpty()) {
        SimpleQuery<DiskOfferingVO> dquery = dbf.createQuery(DiskOfferingVO.class);
        dquery.add(DiskOfferingVO_.uuid, SimpleQuery.Op.IN, msg.getDataDiskOfferingUuids());
        List<DiskOfferingVO> vos = dquery.list();

        // allow create multiple data volume from the same disk offering
        List<DiskOfferingInventory> disks = new ArrayList<DiskOfferingInventory>();
        for (final String duuid : msg.getDataDiskOfferingUuids()) {
          DiskOfferingVO dvo =
              CollectionUtils.find(
                  vos,
                  new Function<DiskOfferingVO, DiskOfferingVO>() {
                    @Override
                    public DiskOfferingVO call(DiskOfferingVO arg) {
                      if (duuid.equals(arg.getUuid())) {
                        return arg;
                      }
                      return null;
                    }
                  });
          disks.add(DiskOfferingInventory.valueOf(dvo));
        }
        spec.setDataDiskOfferings(disks);
      } else {
        spec.setDataDiskOfferings(new ArrayList<DiskOfferingInventory>(0));
      }

      ImageVO imvo = dbf.findByUuid(spec.getVmInventory().getImageUuid(), ImageVO.class);
      spec.getImageSpec().setInventory(ImageInventory.valueOf(imvo));

      spec.putExtensionData(ApplianceVmConstant.Params.applianceVmSpec.toString(), aspec);
      spec.setCurrentVmOperation(VmInstanceConstant.VmOperation.NewCreate);
      spec.putExtensionData(
          ApplianceVmConstant.Params.applianceVmSubType.toString(), getSelf().getApplianceVmType());

      changeVmStateInDb(VmInstanceStateEvent.starting);

      extEmitter.beforeStartNewCreatedVm(VmInstanceInventory.valueOf(self));
      FlowChain chain = apvmf.getCreateApplianceVmWorkFlowBuilder().build();
      chain.setName(String.format("create-appliancevm-%s", msg.getVmInstanceUuid()));
      chain.getData().put(VmInstanceConstant.Params.VmInstanceSpec.toString(), spec);
      chain
          .getData()
          .put(
              ApplianceVmConstant.Params.applianceVmFirewallRules.toString(),
              aspec.getFirewallRules());

      addBootstrapFlows(
          chain, VolumeFormat.getMasterHypervisorTypeByVolumeFormat(imvo.getFormat()));

      List<Flow> subCreateFlows = getPostCreateFlows();
      if (subCreateFlows != null) {
        for (Flow f : subCreateFlows) {
          chain.then(f);
        }
      }

      chain.then(
          new NoRollbackFlow() {
            String __name__ = "change-appliancevm-status-to-connected";

            @Override
            public void run(FlowTrigger trigger, Map data) {
              // must reload here, otherwise it will override changes created by previous flows
              self = dbf.reload(self);
              getSelf().setStatus(ApplianceVmStatus.Connected);
              dbf.update(self);
              trigger.next();
            }
          });

      boolean noRollbackOnFailure = ApplianceVmGlobalProperty.NO_ROLLBACK_ON_POST_FAILURE;
      chain.noRollback(noRollbackOnFailure);
      chain
          .done(
              new FlowDoneHandler(msg, taskChain) {
                @Override
                public void handle(Map data) {
                  VmInstanceSpec spec =
                      (VmInstanceSpec)
                          data.get(VmInstanceConstant.Params.VmInstanceSpec.toString());
                  self = dbf.reload(self);
                  self.setLastHostUuid(spec.getDestHost().getUuid());
                  self.setHostUuid(spec.getDestHost().getUuid());
                  self.setClusterUuid(spec.getDestHost().getClusterUuid());
                  self.setZoneUuid(spec.getDestHost().getZoneUuid());
                  self.setHypervisorType(spec.getDestHost().getHypervisorType());
                  self.setRootVolumeUuid(spec.getDestRootVolume().getUuid());
                  changeVmStateInDb(VmInstanceStateEvent.running);
                  logger.debug(
                      String.format(
                          "appliance vm[uuid:%s, name: %s, type:%s] is running ..",
                          self.getUuid(), self.getName(), getSelf().getApplianceVmType()));
                  VmInstanceInventory inv = VmInstanceInventory.valueOf(self);
                  extEmitter.afterStartNewCreatedVm(inv);
                  StartNewCreatedVmInstanceReply reply = new StartNewCreatedVmInstanceReply();
                  reply.setVmInventory(inv);
                  bus.reply(msg, reply);
                  taskChain.next();
                }
              })
          .error(
              new FlowErrorHandler(msg, taskChain) {
                @Override
                public void handle(ErrorCode errCode, Map data) {
                  extEmitter.failedToStartNewCreatedVm(VmInstanceInventory.valueOf(self), errCode);
                  dbf.remove(self);
                  StartNewCreatedVmInstanceReply reply = new StartNewCreatedVmInstanceReply();
                  reply.setError(errCode);
                  reply.setSuccess(false);
                  bus.reply(msg, reply);
                  taskChain.next();
                }
              })
          .start();

      callNext = false;
    } finally {
      if (callNext) {
        taskChain.next();
      }
    }
  }