/**
   * {@inheritDoc}
   *
   * @throws EntityNotFoundException
   */
  @UseCase(traceTo = "UC_001.4", status = "implemented")
  @Override
  public ProductInstance upgrade(ProductInstance productInstance, ProductRelease productRelease)
      throws NotTransitableException, NodeExecutionException, FSMViolationException,
          InstallatorException, EntityNotFoundException {
    Status previousStatus = productInstance.getStatus();
    try {
      validator.validateUpdate(productInstance, productRelease);
      // update the status
      productInstance.setStatus(Status.UPGRADING);
      productInstance = productInstanceDao.update(productInstance);
      productInstance.setProductRelease(productRelease);

      VM vm = productInstance.getVm();
      Product product = productDao.load(productInstance.getName());

      if (INSTALATOR_PUPPET.equals(product.getMapMetadata().get("installator"))) {
        throw new InstallatorException("Product not upgradeable in Puppet");
      } else {
        chefInstallator.upgrade(productInstance, vm);
      }

      productInstance.setStatus(Status.INSTALLED);
      return productInstanceDao.update(productInstance);

    } catch (RuntimeException e) { // by runtime restore the previous state
      // restore the status
      restoreInstance(previousStatus, productInstance);
      throw new SdcRuntimeException(e);
    }
  }
  /**
   * {@inheritDoc}
   *
   * @throws InstallatorException
   */
  @Override
  public ProductInstance configure(ProductInstance productInstance, List<Attribute> configuration)
      throws NodeExecutionException, FSMViolationException, InstallatorException {
    System.out.println(
        "Configuring product instance " + productInstance.getName() + " " + configuration);
    Status previousStatus = productInstance.getStatus();
    try {
      validator.validateConfigure(productInstance);
      productInstance.setStatus(Status.CONFIGURING);
      productInstance = productInstanceDao.update(productInstance);

      System.out.println("Get VM");
      VM vm = productInstance.getVm();

      System.out.println(
          "Load product " + productInstance.getProductRelease().getProduct().getName());
      Product product = productDao.load(productInstance.getProductRelease().getProduct().getName());

      if (configuration != null) {
        for (int j = 0; j < configuration.size(); j++) {
          Attribute attribute = configuration.get(j);
          product.addAttribute(attribute);
        }
      }
      System.out.println(
          "Update product " + productInstance.getProductRelease().getProduct().getName());
      productDao.update(product);

      ProductRelease productRelease = productInstance.getProductRelease();
      productRelease.setProduct(product);

      if (INSTALATOR_PUPPET.equals(product.getMapMetadata().get("installator"))) {
        throw new InstallatorException("Product not configurable in Puppet");
      } else {
        chefInstallator.callService(
            productInstance, productInstance.getVm(), configuration, CONFIGURE);
      }

      /*
       * String recipe = recipeNamingGenerator .getInstallRecipe(productInstance); callChef(
       * productInstance.getProductRelease().getProduct().getName(), recipe, productInstance.getVm(),
       * configuration); String restoreRecipe = recipeNamingGenerator .getRestoreRecipe(productInstance);
       * callChef(restoreRecipe, vm);
       */

      productInstance.setProductRelease(productRelease);
      productInstance.setStatus(Status.INSTALLED);
      return productInstanceDao.update(productInstance);

    } catch (InstallatorException e) {
      restoreInstance(previousStatus, productInstance);
      throw new SdcRuntimeException(e);
    } catch (RuntimeException e) { // by runtime restore the previous state
      // restore the status
      restoreInstance(previousStatus, productInstance);
      throw new SdcRuntimeException(e);
    } catch (NodeExecutionException e) {
      restoreInstance(Status.ERROR, productInstance);
      throw e;
    } catch (EntityNotFoundException e) {
      throw new SdcRuntimeException(e);
    }
  }