private ProductInstance createProductInstance(
      ProductRelease productRelease, VM vm, String vdc, List<Attribute> attributes)
      throws InvalidEntityException, AlreadyExistsEntityException {

    ProductInstance instance = new ProductInstance();

    Product product = null;
    try {
      product = productDao.load(productRelease.getProduct().getName());
    } catch (EntityNotFoundException e) {
      product =
          new Product(
              productRelease.getProduct().getName(), productRelease.getProduct().getDescription());
    }
    product.setAttributes(attributes);

    productRelease.setProduct(product);

    instance.setProductRelease(productRelease);
    instance.setVm(vm);
    instance.setVdc(vdc);
    instance.setStatus(Status.UNINSTALLED);
    instance.setName(
        vm.getFqn()
            + "_"
            + productRelease.getProduct().getName()
            + "_"
            + productRelease.getVersion());

    instance = productInstanceDao.create(instance);
    return instance;
  }
  @Override
  public ProductInstance install(
      VM vm, String vdc, ProductRelease productRelease, List<Attribute> attributes)
      throws NodeExecutionException, AlreadyInstalledException,
          InvalidInstallProductRequestException, EntityNotFoundException {

    // if (INSTALATOR_CHEF.equals(product.getMapMetadata().get("installator"))) {
    //
    // }else{
    //
    // }

    // Check that there is not another product installed
    ProductInstance instance = null;
    try {

      instance =
          productInstanceDao.load(
              vm.getFqn()
                  + "_"
                  + productRelease.getProduct().getName()
                  + "_"
                  + productRelease.getVersion());

      System.out.println("intance:" + instance.getStatus());

      if (instance.getStatus().equals(Status.INSTALLED)) {
        throw new AlreadyInstalledException(instance);
      } else if (!(instance.getStatus().equals(Status.UNINSTALLED))
          && !(instance.getStatus().equals(Status.ERROR)))
        throw new InvalidInstallProductRequestException(
            "Product "
                + productRelease.getProduct().getName()
                + " "
                + productRelease.getVersion()
                + " cannot be installed in the VM "
                + vm.getFqn()
                + " strage status:  "
                + instance.getStatus());
    } catch (EntityNotFoundException e) {
      try {
        instance = createProductInstance(productRelease, vm, vdc, attributes);
      } catch (Exception e2) {
        throw new InvalidInstallProductRequestException(
            "Product "
                + productRelease.getProduct().getName()
                + " "
                + productRelease.getVersion()
                + " cannot be installed in the VM "
                + vm.getFqn()
                + " error in creating the isntance:  "
                + e2.getMessage());
      }
    }

    Status previousStatus = null;

    try {
      // makes the validations
      // instance = getProductToInstall(product, vm, vdc, attributes);
      previousStatus = instance.getStatus();
      // now we have the productInstance so can validate the operation
      validator.validateInstall(instance);

      instance.setStatus(Status.INSTALLING);
      instance.setVm(vm);
      // Id for the ProductInstance
      instance = productInstanceDao.update(instance);

      Product product = productDao.load(productRelease.getProduct().getName());

      if (INSTALATOR_CHEF.equals(product.getMapMetadata().get("installator"))) {
        chefInstallator.validateInstalatorData(vm);
        chefInstallator.callService(instance, vm, attributes, INSTALL);
      } else {
        if (INSTALATOR_PUPPET.equals(product.getMapMetadata().get("installator"))) {
          puppetInstallator.validateInstalatorData(vm);
          puppetInstallator.callService(vm, vdc, productRelease, INSTALL);
        } else {
          chefInstallator.validateInstalatorData(vm);
          chefInstallator.callService(instance, vm, attributes, INSTALL);
        }
      }

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

    } catch (InstallatorException sce) {
      restoreInstance(previousStatus, instance);
      throw new SdcRuntimeException(sce);
    } catch (RuntimeException e) {
      // by default restore the previous state when a runtime is thrown
      restoreInstance(previousStatus, instance);
      throw new SdcRuntimeException(e);
    }
  }