@Override
  public boolean prepare(
      VirtualMachineProfile profile,
      NicProfile nic,
      Network network,
      DeployDestination dest,
      ReservationContext context) {
    try {
      if (DataCenter.NetworkType.Basic.equals(dest.getDataCenter().getNetworkType())) {
        if (!preparePxeInBasicZone(profile, nic, dest, context)) {
          return false;
        }
      } else {
        if (!preparePxeInAdvancedZone(profile, nic, network, dest, context)) {
          return false;
        }
      }

      IpmISetBootDevCommand bootCmd = new IpmISetBootDevCommand(BootDev.pxe);
      Answer aws = _agentMgr.send(dest.getHost().getId(), bootCmd);
      if (!aws.getResult()) {
        s_logger.warn(
            "Unable to set host: "
                + dest.getHost().getId()
                + " to PXE boot because "
                + aws.getDetails());
      }

      return aws.getResult();
    } catch (Exception e) {
      s_logger.warn("Cannot prepare PXE server", e);
      return false;
    }
  }
  protected Long stopVM(final HaWorkVO work) {
    final VirtualMachineGuru<VMInstanceVO> mgr = findManager(work.getType());
    final VMInstanceVO vm = mgr.get(work.getInstanceId());
    s_logger.info("Stopping " + vm.toString());
    try {
      if (work.getWorkType() == WorkType.Stop) {
        if (vm.getHostId() != null) {
          if (mgr.stop(vm, 0)) {
            s_logger.info("Successfully stopped " + vm.toString());
            return null;
          }
        } else {
          if (s_logger.isDebugEnabled()) {
            s_logger.debug(vm.toString() + " has already been stopped");
          }
          return null;
        }
      } else if (work.getWorkType() == WorkType.CheckStop) {
        if ((vm.getState() != State.Stopping)
            || vm.getHostId() == null
            || vm.getHostId().longValue() != work.getHostId()) {
          if (s_logger.isDebugEnabled()) {
            s_logger.debug(
                vm.toString()
                    + " is different now.  Scheduled Host: "
                    + work.getHostId()
                    + " Current Host: "
                    + (vm.getHostId() != null ? vm.getHostId() : "none")
                    + " State: "
                    + vm.getState());
          }
          return null;
        } else {
          Command cmd = mgr.cleanup(vm, null);
          Answer ans = _agentMgr.send(work.getHostId(), cmd);
          if (ans.getResult()) {
            mgr.completeStopCommand(vm);
            s_logger.info("Successfully stopped " + vm.toString());
            return null;
          }
          s_logger.debug(
              "Stop for " + vm.toString() + " was unsuccessful. Detail: " + ans.getDetails());
        }
      } else {
        assert false
            : "Who decided there's other steps but didn't modify the guy who does the work?";
      }
    } catch (final AgentUnavailableException e) {
      s_logger.debug("Agnet is not available" + e.getMessage());
    } catch (OperationTimedoutException e) {
      s_logger.debug("operation timed out: " + e.getMessage());
    }

    work.setTimesTried(work.getTimesTried() + 1);
    return (System.currentTimeMillis() >> 10) + _stopRetryInterval;
  }
 public Void deleteCallback(
     AsyncCallbackDispatcher<SamplePrimaryDataStoreDriverImpl, Answer> callback,
     AsyncRpcContext<CommandResult> context) {
   CommandResult result = new CommandResult();
   Answer answer = callback.getResult();
   if (!answer.getResult()) {
     result.setResult(answer.getDetails());
   }
   context.getParentCallback().complete(result);
   return null;
 }
 @Override
 public void deleteAsync(
     DataStore dataStore, DataObject data, AsyncCompletionCallback<CommandResult> callback) {
   CommandResult result = new CommandResult();
   try {
     DeleteCommand cmd = new DeleteCommand(data.getTO());
     EndPoint ep = _epSelector.select(data);
     Answer answer = ep.sendMessage(cmd);
     if (answer != null && !answer.getResult()) {
       result.setResult(answer.getDetails());
     }
   } catch (Exception ex) {
     s_logger.debug("Unable to destoy " + data.getType().toString() + ": " + data.getId(), ex);
     result.setResult(ex.toString());
   }
   callback.complete(result);
 }
  private boolean preparePxeInBasicZone(
      VirtualMachineProfile profile,
      NicProfile nic,
      DeployDestination dest,
      ReservationContext context)
      throws AgentUnavailableException, OperationTimedoutException {
    NetworkVO nwVO = _nwDao.findById(nic.getNetworkId());
    QueryBuilder<BaremetalPxeVO> sc = QueryBuilder.create(BaremetalPxeVO.class);
    sc.and(sc.entity().getDeviceType(), Op.EQ, BaremetalPxeType.KICK_START.toString());
    sc.and(sc.entity().getPhysicalNetworkId(), Op.EQ, nwVO.getPhysicalNetworkId());
    BaremetalPxeVO pxeVo = sc.find();
    if (pxeVo == null) {
      throw new CloudRuntimeException(
          "No kickstart PXE server found in pod: "
              + dest.getPod().getId()
              + ", you need to add it before starting VM");
    }
    VMTemplateVO template = _tmpDao.findById(profile.getTemplateId());
    List<String> tuple = parseKickstartUrl(profile);

    String ks = tuple.get(0);
    String kernel = tuple.get(1);
    String initrd = tuple.get(2);

    PrepareKickstartPxeServerCommand cmd = new PrepareKickstartPxeServerCommand();
    cmd.setKsFile(ks);
    cmd.setInitrd(initrd);
    cmd.setKernel(kernel);
    cmd.setMac(nic.getMacAddress());
    cmd.setTemplateUuid(template.getUuid());
    Answer aws = _agentMgr.send(pxeVo.getHostId(), cmd);
    if (!aws.getResult()) {
      s_logger.warn(
          "Unable to set host: "
              + dest.getHost().getId()
              + " to PXE boot because "
              + aws.getDetails());
      return false;
    }

    return true;
  }
  protected Long destroyVM(HaWorkVO work) {
    final VirtualMachineGuru<VMInstanceVO> mgr = findManager(work.getType());
    final VMInstanceVO vm = mgr.get(work.getInstanceId());
    s_logger.info("Destroying " + vm.toString());
    try {
      if (vm.getState() != State.Destroyed) {
        s_logger.info("VM is no longer in Destroyed state " + vm.toString());
        return null;
      }

      if (vm.getHostId() != null) {
        Command cmd = mgr.cleanup(vm, null);
        Answer ans = _agentMgr.send(work.getHostId(), cmd);
        if (ans.getResult()) {
          mgr.completeStopCommand(vm);
          if (mgr.destroy(vm)) {
            s_logger.info("Successfully stopped " + vm.toString());
            return null;
          }
        }
        s_logger.debug(
            "Stop for " + vm.toString() + " was unsuccessful. Detail: " + ans.getDetails());
      } else {
        if (s_logger.isDebugEnabled()) {
          s_logger.debug(vm.toString() + " has already been stopped");
        }
        return null;
      }
    } catch (final AgentUnavailableException e) {
      s_logger.debug("Agnet is not available" + e.getMessage());
    } catch (OperationTimedoutException e) {
      s_logger.debug("operation timed out: " + e.getMessage());
    }

    work.setTimesTried(work.getTimesTried() + 1);
    return (System.currentTimeMillis() >> 10) + _stopRetryInterval;
  }
 protected boolean createStoragePool(long hostId, StoragePool pool) {
   s_logger.debug("creating pool " + pool.getName() + " on  host " + hostId);
   if (pool.getPoolType() != StoragePoolType.NetworkFilesystem
       && pool.getPoolType() != StoragePoolType.Filesystem
       && pool.getPoolType() != StoragePoolType.IscsiLUN
       && pool.getPoolType() != StoragePoolType.Iscsi
       && pool.getPoolType() != StoragePoolType.VMFS
       && pool.getPoolType() != StoragePoolType.SharedMountPoint
       && pool.getPoolType() != StoragePoolType.PreSetup
       && pool.getPoolType() != StoragePoolType.OCFS2
       && pool.getPoolType() != StoragePoolType.RBD
       && pool.getPoolType() != StoragePoolType.CLVM) {
     s_logger.warn(" Doesn't support storage pool type " + pool.getPoolType());
     return false;
   }
   CreateStoragePoolCommand cmd = new CreateStoragePoolCommand(true, pool);
   final Answer answer = agentMgr.easySend(hostId, cmd);
   if (answer != null && answer.getResult()) {
     return true;
   } else {
     primaryDataStoreDao.expunge(pool.getId());
     String msg = "";
     if (answer != null) {
       msg =
           "Can not create storage pool through host " + hostId + " due to " + answer.getDetails();
       s_logger.warn(msg);
     } else {
       msg =
           "Can not create storage pool through host "
               + hostId
               + " due to CreateStoragePoolCommand returns null";
       s_logger.warn(msg);
     }
     throw new CloudRuntimeException(msg);
   }
 }
  @Override
  @DB
  public boolean delete(TemplateProfile profile) {
    boolean success = true;

    VMTemplateVO template = profile.getTemplate();
    Long zoneId = profile.getZoneId();
    Long templateId = template.getId();

    String zoneName;
    List<HostVO> secondaryStorageHosts;
    if (!template.isCrossZones() && zoneId != null) {
      DataCenterVO zone = _dcDao.findById(zoneId);
      zoneName = zone.getName();
      secondaryStorageHosts = _ssvmMgr.listSecondaryStorageHostsInOneZone(zoneId);
    } else {
      zoneName = "(all zones)";
      secondaryStorageHosts = _ssvmMgr.listSecondaryStorageHostsInAllZones();
    }

    s_logger.debug(
        "Attempting to mark template host refs for template: "
            + template.getName()
            + " as destroyed in zone: "
            + zoneName);

    // Make sure the template is downloaded to all the necessary secondary storage hosts
    for (HostVO secondaryStorageHost : secondaryStorageHosts) {
      long hostId = secondaryStorageHost.getId();
      List<VMTemplateHostVO> templateHostVOs = _tmpltHostDao.listByHostTemplate(hostId, templateId);
      for (VMTemplateHostVO templateHostVO : templateHostVOs) {
        if (templateHostVO.getDownloadState() == Status.DOWNLOAD_IN_PROGRESS) {
          String errorMsg = "Please specify a template that is not currently being downloaded.";
          s_logger.debug(
              "Template: "
                  + template.getName()
                  + " is currently being downloaded to secondary storage host: "
                  + secondaryStorageHost.getName()
                  + "; cant' delete it.");
          throw new CloudRuntimeException(errorMsg);
        }
      }
    }

    Account account = _accountDao.findByIdIncludingRemoved(template.getAccountId());
    String eventType = "";

    if (template.getFormat().equals(ImageFormat.ISO)) {
      eventType = EventTypes.EVENT_ISO_DELETE;
    } else {
      eventType = EventTypes.EVENT_TEMPLATE_DELETE;
    }

    // Iterate through all necessary secondary storage hosts and mark the template on each host as
    // destroyed
    for (HostVO secondaryStorageHost : secondaryStorageHosts) {
      long hostId = secondaryStorageHost.getId();
      long sZoneId = secondaryStorageHost.getDataCenterId();
      List<VMTemplateHostVO> templateHostVOs = _tmpltHostDao.listByHostTemplate(hostId, templateId);
      for (VMTemplateHostVO templateHostVO : templateHostVOs) {
        VMTemplateHostVO lock = _tmpltHostDao.acquireInLockTable(templateHostVO.getId());
        try {
          if (lock == null) {
            s_logger.debug(
                "Failed to acquire lock when deleting templateHostVO with ID: "
                    + templateHostVO.getId());
            success = false;
            break;
          }
          UsageEventVO usageEvent =
              new UsageEventVO(eventType, account.getId(), sZoneId, templateId, null);
          _usageEventDao.persist(usageEvent);
          templateHostVO.setDestroyed(true);
          _tmpltHostDao.update(templateHostVO.getId(), templateHostVO);
          String installPath = templateHostVO.getInstallPath();
          if (installPath != null) {
            Answer answer =
                _agentMgr.sendToSecStorage(
                    secondaryStorageHost,
                    new DeleteTemplateCommand(secondaryStorageHost.getStorageUrl(), installPath));

            if (answer == null || !answer.getResult()) {
              s_logger.debug(
                  "Failed to delete "
                      + templateHostVO
                      + " due to "
                      + ((answer == null) ? "answer is null" : answer.getDetails()));
            } else {
              _tmpltHostDao.remove(templateHostVO.getId());
              s_logger.debug("Deleted template at: " + installPath);
            }
          } else {
            _tmpltHostDao.remove(templateHostVO.getId());
          }
          VMTemplateZoneVO templateZone = _tmpltZoneDao.findByZoneTemplate(sZoneId, templateId);

          if (templateZone != null) {
            _tmpltZoneDao.remove(templateZone.getId());
          }
        } finally {
          if (lock != null) {
            _tmpltHostDao.releaseFromLockTable(lock.getId());
          }
        }
      }

      if (!success) {
        break;
      }
    }

    s_logger.debug(
        "Successfully marked template host refs for template: "
            + template.getName()
            + " as destroyed in zone: "
            + zoneName);

    // If there are no more non-destroyed template host entries for this template, delete it
    if (success && (_tmpltHostDao.listByTemplateId(templateId).size() == 0)) {
      long accountId = template.getAccountId();

      VMTemplateVO lock = _tmpltDao.acquireInLockTable(templateId);

      try {
        if (lock == null) {
          s_logger.debug("Failed to acquire lock when deleting template with ID: " + templateId);
          success = false;
        } else if (_tmpltDao.remove(templateId)) {
          // Decrement the number of templates
          _resourceLimitMgr.decrementResourceCount(accountId, ResourceType.template);
        }

      } finally {
        if (lock != null) {
          _tmpltDao.releaseFromLockTable(lock.getId());
        }
      }

      s_logger.debug(
          "Removed template: "
              + template.getName()
              + " because all of its template host refs were marked as destroyed.");
    }

    return success;
  }
  @Override
  public boolean startRemoteAccessVpn(final RemoteAccessVpn vpn, final VirtualRouter router)
      throws ResourceUnavailableException {
    if (router.getState() != State.Running) {
      s_logger.warn(
          "Unable to apply remote access VPN configuration, virtual router is not in the right state "
              + router.getState());
      throw new ResourceUnavailableException(
          "Unable to apply remote access VPN configuration,"
              + " virtual router is not in the right state",
          DataCenter.class,
          router.getDataCenterId());
    }

    final Commands cmds = new Commands(Command.OnError.Stop);
    _commandSetupHelper.createApplyVpnCommands(true, vpn, router, cmds);

    try {
      _agentMgr.send(router.getHostId(), cmds);
    } catch (final OperationTimedoutException e) {
      s_logger.debug("Failed to start remote access VPN: ", e);
      throw new AgentUnavailableException(
          "Unable to send commands to virtual router ", router.getHostId(), e);
    }
    Answer answer = cmds.getAnswer("users");
    if (!answer.getResult()) {
      s_logger.error(
          "Unable to start vpn: unable add users to vpn in zone "
              + router.getDataCenterId()
              + " for account "
              + vpn.getAccountId()
              + " on domR: "
              + router.getInstanceName()
              + " due to "
              + answer.getDetails());
      throw new ResourceUnavailableException(
          "Unable to start vpn: Unable to add users to vpn in zone "
              + router.getDataCenterId()
              + " for account "
              + vpn.getAccountId()
              + " on domR: "
              + router.getInstanceName()
              + " due to "
              + answer.getDetails(),
          DataCenter.class,
          router.getDataCenterId());
    }
    answer = cmds.getAnswer("startVpn");
    if (!answer.getResult()) {
      s_logger.error(
          "Unable to start vpn in zone "
              + router.getDataCenterId()
              + " for account "
              + vpn.getAccountId()
              + " on domR: "
              + router.getInstanceName()
              + " due to "
              + answer.getDetails());
      throw new ResourceUnavailableException(
          "Unable to start vpn in zone "
              + router.getDataCenterId()
              + " for account "
              + vpn.getAccountId()
              + " on domR: "
              + router.getInstanceName()
              + " due to "
              + answer.getDetails(),
          DataCenter.class,
          router.getDataCenterId());
    }

    return true;
  }
  @Override
  public boolean applyStaticNats(Network network, List<? extends StaticNat> rules)
      throws ResourceUnavailableException {
    if (!_networkModel.isProviderSupportServiceInNetwork(
        network.getId(), Service.StaticNat, Provider.CiscoVnmc)) {
      s_logger.error(
          "Static NAT service is not provided by Cisco Vnmc device on network "
              + network.getName());
      return false;
    }

    // Find VNMC host for physical network
    List<CiscoVnmcControllerVO> devices =
        _ciscoVnmcDao.listByPhysicalNetwork(network.getPhysicalNetworkId());
    if (devices.isEmpty()) {
      s_logger.error("No Cisco Vnmc device on network " + network.getName());
      return true;
    }

    // Find if ASA 1000v is associated with network
    NetworkAsa1000vMapVO asaForNetwork = _networkAsa1000vMapDao.findByNetworkId(network.getId());
    if (asaForNetwork == null) {
      s_logger.debug("Cisco ASA 1000v device is not associated with network " + network.getName());
      return true;
    }

    if (network.getState() == Network.State.Allocated) {
      s_logger.debug(
          "External firewall was asked to apply static NAT rules for network with ID "
              + network.getId()
              + "; this network is not implemented. Skipping backend commands.");
      return true;
    }

    CiscoVnmcControllerVO ciscoVnmcDevice = devices.get(0);
    HostVO ciscoVnmcHost = _hostDao.findById(ciscoVnmcDevice.getHostId());

    List<StaticNatRuleTO> rulesTO = new ArrayList<StaticNatRuleTO>();
    for (StaticNat rule : rules) {
      IpAddress sourceIp = _networkModel.getIp(rule.getSourceIpAddressId());
      StaticNatRuleTO ruleTO =
          new StaticNatRuleTO(
              rule.getSourceIpAddressId(),
              sourceIp.getAddress().addr(),
              null,
              null,
              rule.getDestIpAddress(),
              null,
              null,
              null,
              rule.isForRevoke(),
              false);
      rulesTO.add(ruleTO);
    }

    if (!rulesTO.isEmpty()) {
      SetStaticNatRulesCommand cmd = new SetStaticNatRulesCommand(rulesTO, null);
      cmd.setContextParam(
          NetworkElementCommand.GUEST_VLAN_TAG, network.getBroadcastUri().getHost());
      cmd.setContextParam(NetworkElementCommand.GUEST_NETWORK_CIDR, network.getCidr());
      Answer answer = _agentMgr.easySend(ciscoVnmcHost.getId(), cmd);
      if (answer == null || !answer.getResult()) {
        String details = (answer != null) ? answer.getDetails() : "details unavailable";
        String msg =
            "Unable to apply static NAT rules to Cisco ASA 1000v appliance due to: "
                + details
                + ".";
        s_logger.error(msg);
        throw new ResourceUnavailableException(msg, DataCenter.class, network.getDataCenterId());
      }
    }

    return true;
  }
  @Override
  public boolean addUserData(NicProfile nic, VirtualMachineProfile profile) {
    UserVmVO vm = _vmDao.findById(profile.getVirtualMachine().getId());
    _vmDao.loadDetails(vm);

    String serviceOffering =
        _serviceOfferingDao
            .findByIdIncludingRemoved(vm.getId(), vm.getServiceOfferingId())
            .getDisplayText();
    String zoneName = _dcDao.findById(vm.getDataCenterId()).getName();
    NicVO nvo = _nicDao.findById(nic.getId());
    VmDataCommand cmd =
        new VmDataCommand(
            nvo.getIPv4Address(), vm.getInstanceName(), _ntwkModel.getExecuteInSeqNtwkElmtCmd());
    // if you add new metadata files, also edit
    // systemvm/patches/debian/config/var/www/html/latest/.htaccess
    cmd.addVmData("userdata", "user-data", vm.getUserData());
    cmd.addVmData("metadata", "service-offering", StringUtils.unicodeEscape(serviceOffering));
    cmd.addVmData("metadata", "availability-zone", StringUtils.unicodeEscape(zoneName));
    cmd.addVmData("metadata", "local-ipv4", nic.getIPv4Address());
    cmd.addVmData("metadata", "local-hostname", StringUtils.unicodeEscape(vm.getInstanceName()));
    cmd.addVmData("metadata", "public-ipv4", nic.getIPv4Address());
    cmd.addVmData("metadata", "public-hostname", StringUtils.unicodeEscape(vm.getInstanceName()));
    cmd.addVmData("metadata", "instance-id", String.valueOf(vm.getId()));
    cmd.addVmData("metadata", "vm-id", String.valueOf(vm.getInstanceName()));
    cmd.addVmData("metadata", "public-keys", null);
    String cloudIdentifier = _configDao.getValue("cloud.identifier");
    if (cloudIdentifier == null) {
      cloudIdentifier = "";
    } else {
      cloudIdentifier = "CloudStack-{" + cloudIdentifier + "}";
    }
    cmd.addVmData("metadata", "cloud-identifier", cloudIdentifier);

    List<PhysicalNetworkVO> phys = _phynwDao.listByZone(vm.getDataCenterId());
    if (phys.isEmpty()) {
      throw new CloudRuntimeException(
          String.format("Cannot find physical network in zone %s", vm.getDataCenterId()));
    }
    if (phys.size() > 1) {
      throw new CloudRuntimeException(
          String.format(
              "Baremetal only supports one physical network in zone, but zone %s has %s physical networks",
              vm.getDataCenterId(), phys.size()));
    }
    PhysicalNetworkVO phy = phys.get(0);

    QueryBuilder<BaremetalPxeVO> sc = QueryBuilder.create(BaremetalPxeVO.class);
    // TODO: handle both kickstart and PING
    // sc.addAnd(sc.getEntity().getPodId(), Op.EQ, vm.getPodIdToDeployIn());
    sc.and(sc.entity().getPhysicalNetworkId(), Op.EQ, phy.getId());
    BaremetalPxeVO pxeVo = sc.find();
    if (pxeVo == null) {
      throw new CloudRuntimeException(
          "No PXE server found in pod: "
              + vm.getPodIdToDeployIn()
              + ", you need to add it before starting VM");
    }

    try {
      Answer ans = _agentMgr.send(pxeVo.getHostId(), cmd);
      if (!ans.getResult()) {
        s_logger.debug(
            String.format(
                "Add userdata to vm:%s failed because %s", vm.getInstanceName(), ans.getDetails()));
        return false;
      } else {
        return true;
      }
    } catch (Exception e) {
      s_logger.debug(String.format("Add userdata to vm:%s failed", vm.getInstanceName()), e);
      return false;
    }
  }
  @Override
  public boolean prepare(
      VirtualMachineProfile<UserVmVO> profile,
      NicProfile pxeNic,
      DeployDestination dest,
      ReservationContext context) {
    SearchCriteriaService<BaremetalPxeVO, BaremetalPxeVO> sc =
        SearchCriteria2.create(BaremetalPxeVO.class);
    sc.addAnd(sc.getEntity().getDeviceType(), Op.EQ, BaremetalPxeType.PING.toString());
    sc.addAnd(sc.getEntity().getPodId(), Op.EQ, dest.getPod().getId());
    BaremetalPxeVO pxeVo = sc.find();
    if (pxeVo == null) {
      throw new CloudRuntimeException(
          "No PING PXE server found in pod: "
              + dest.getPod().getId()
              + ", you need to add it before starting VM");
    }
    long pxeServerId = pxeVo.getHostId();

    String mac = pxeNic.getMacAddress();
    String ip = pxeNic.getIp4Address();
    String gateway = pxeNic.getGateway();
    String mask = pxeNic.getNetmask();
    String dns = pxeNic.getDns1();
    if (dns == null) {
      dns = pxeNic.getDns2();
    }

    try {
      String tpl = profile.getTemplate().getUrl();
      assert tpl != null : "How can a null template get here!!!";
      PreparePxeServerCommand cmd =
          new PreparePxeServerCommand(
              ip,
              mac,
              mask,
              gateway,
              dns,
              tpl,
              profile.getVirtualMachine().getInstanceName(),
              dest.getHost().getName());
      PreparePxeServerAnswer ans = (PreparePxeServerAnswer) _agentMgr.send(pxeServerId, cmd);
      if (!ans.getResult()) {
        s_logger.warn(
            "Unable tot program PXE server: " + pxeVo.getId() + " because " + ans.getDetails());
        return false;
      }

      IpmISetBootDevCommand bootCmd = new IpmISetBootDevCommand(BootDev.pxe);
      Answer anw = _agentMgr.send(dest.getHost().getId(), bootCmd);
      if (!anw.getResult()) {
        s_logger.warn(
            "Unable to set host: "
                + dest.getHost().getId()
                + " to PXE boot because "
                + anw.getDetails());
      }

      return anw.getResult();
    } catch (Exception e) {
      s_logger.warn("Cannot prepare PXE server", e);
      return false;
    }
  }