Search in sources :

Example 1 with StoragePoolIsoMapId

use of org.ovirt.engine.core.common.businessentities.StoragePoolIsoMapId in project ovirt-engine by oVirt.

the class IrsProxy method proceedStoragePoolStats.

@SuppressWarnings("unchecked")
private void proceedStoragePoolStats(StoragePool storagePool) {
    // ugly patch because vdsm doesnt check if host is spm on spm
    // operations
    VDSReturnValue result = null;
    Guid curVdsId = currentVdsId;
    if (curVdsId != null) {
        result = resourceManager.runVdsCommand(VDSCommandType.SpmStatus, new SpmStatusVDSCommandParameters(curVdsId, storagePoolId));
    }
    if (result == null || !result.getSucceeded() || (result.getSucceeded() && ((SpmStatusResult) result.getReturnValue()).getSpmStatus() != SpmStatus.SPM)) {
        // update pool status to problematic until fence will happen
        if (storagePool.getStatus() != StoragePoolStatus.NonResponsive && storagePool.getStatus() != StoragePoolStatus.NotOperational) {
            if (result != null && result.getVdsError() != null) {
                updateStoragePoolStatus(storagePoolId, StoragePoolStatus.NonResponsive, AuditLogType.SYSTEM_CHANGE_STORAGE_POOL_STATUS_PROBLEMATIC_WITH_ERROR, result.getVdsError().getCode());
            } else {
                updateStoragePoolStatus(storagePoolId, StoragePoolStatus.NonResponsive, AuditLogType.SYSTEM_CHANGE_STORAGE_POOL_STATUS_PROBLEMATIC, EngineError.ENGINE);
            }
        }
        // then cause failover with attempts
        if (result != null && !(result.getExceptionObject() instanceof VDSNetworkException)) {
            HashMap<Guid, AsyncTaskStatus> tasksList = (HashMap<Guid, AsyncTaskStatus>) resourceManager.runVdsCommand(VDSCommandType.HSMGetAllTasksStatuses, new VdsIdVDSCommandParametersBase(curVdsId)).getReturnValue();
            boolean allTasksFinished = true;
            if (tasksList != null) {
                for (AsyncTaskStatus taskStatus : tasksList.values()) {
                    if (AsyncTaskStatusEnum.finished != taskStatus.getStatus()) {
                        allTasksFinished = false;
                        break;
                    }
                }
            }
            if ((tasksList == null) || allTasksFinished) {
                nullifyInternalProxies();
            } else {
                if (_errorAttempts < Config.<Integer>getValue(ConfigValues.SPMFailOverAttempts)) {
                    _errorAttempts++;
                    log.warn("failed getting spm status for pool '{}' ({}), attempt number: {}", storagePoolId, storagePool.getName(), _errorAttempts);
                } else {
                    nullifyInternalProxies();
                    _errorAttempts = 0;
                }
            }
        }
    } else if (result.getSucceeded() && ((SpmStatusResult) result.getReturnValue()).getSpmStatus() == SpmStatus.SPM && (storagePool.getStatus() == StoragePoolStatus.NonResponsive || storagePool.getStatus() == StoragePoolStatus.Contend)) {
        // if recovered from network exception set back to up
        storagePoolDao.updateStatus(storagePool.getId(), StoragePoolStatus.Up);
        storagePool.setStatus(StoragePoolStatus.Up);
        getEventListener().storagePoolStatusChanged(storagePool.getId(), storagePool.getStatus());
    }
    List<StorageDomain> domainsInDb = storageDomainDao.getAllForStoragePool(storagePoolId);
    GetStoragePoolInfoVDSCommandParameters tempVar = new GetStoragePoolInfoVDSCommandParameters(storagePoolId);
    tempVar.setIgnoreFailoverLimit(true);
    VDSReturnValue storagePoolInfoResult = resourceManager.runVdsCommand(VDSCommandType.GetStoragePoolInfo, tempVar);
    if (storagePoolInfoResult.getSucceeded()) {
        KeyValuePairCompat<StoragePool, List<StorageDomain>> data = (KeyValuePairCompat<StoragePool, List<StorageDomain>>) storagePoolInfoResult.getReturnValue();
        int masterVersion = data.getKey().getMasterDomainVersion();
        HashSet<Guid> domainsInVds = new HashSet<>();
        List<StorageDomain> storageDomainsToSync = data.getValue().stream().peek(storageDomain -> domainsInVds.add(storageDomain.getId())).filter(storageDomain -> proceedStorageDomain(storageDomain, masterVersion, storagePool)).collect(Collectors.toList());
        if (!storageDomainsToSync.isEmpty()) {
            getEventListener().syncStorageDomainsLuns(getCurrentVdsId(), storageDomainsToSync.stream().map(StorageDomain::getId).collect(Collectors.toList()));
        }
        for (final StorageDomain domainInDb : domainsInDb) {
            if (domainInDb.getStorageDomainType() != StorageDomainType.Master && domainInDb.getStatus() != StorageDomainStatus.Locked && !domainInDb.getStorageType().isCinderDomain() && !domainsInVds.contains(domainInDb.getId())) {
                // domain not attached to pool anymore
                storagePoolIsoMapDao.remove(new StoragePoolIsoMapId(domainInDb.getId(), storagePoolId));
            }
        }
    }
    domainsInMaintenanceCheck(domainsInDb, storagePool);
}
Also used : SpmStatusVDSCommandParameters(org.ovirt.engine.core.common.vdscommands.SpmStatusVDSCommandParameters) VdsIdVDSCommandParametersBase(org.ovirt.engine.core.common.vdscommands.VdsIdVDSCommandParametersBase) StoragePoolDomainHelper(org.ovirt.engine.core.vdsbroker.storage.StoragePoolDomainHelper) VdsSpmIdMap(org.ovirt.engine.core.common.businessentities.VdsSpmIdMap) Arrays(java.util.Arrays) StringUtils(org.apache.commons.lang.StringUtils) StorageDomainDynamicDao(org.ovirt.engine.core.dao.StorageDomainDynamicDao) ScheduledFuture(java.util.concurrent.ScheduledFuture) LoggerFactory(org.slf4j.LoggerFactory) NonOperationalReason(org.ovirt.engine.core.common.businessentities.NonOperationalReason) EventType(org.ovirt.engine.core.common.eventqueue.EventType) ConnectStoragePoolVDSCommandParameters(org.ovirt.engine.core.common.vdscommands.ConnectStoragePoolVDSCommandParameters) OnTimerMethodAnnotation(org.ovirt.engine.core.utils.timer.OnTimerMethodAnnotation) VdsDao(org.ovirt.engine.core.dao.VdsDao) KeyValuePairCompat(org.ovirt.engine.core.compat.KeyValuePairCompat) Map(java.util.Map) Event(org.ovirt.engine.core.common.eventqueue.Event) StoragePoolDao(org.ovirt.engine.core.dao.StoragePoolDao) SpmStartVDSCommandParameters(org.ovirt.engine.core.common.vdscommands.SpmStartVDSCommandParameters) ThreadPoolUtil(org.ovirt.engine.core.utils.threadpool.ThreadPoolUtil) AuditLogableImpl(org.ovirt.engine.core.dal.dbbroker.auditloghandling.AuditLogableImpl) EnumSet(java.util.EnumSet) ManagedScheduledExecutorService(javax.enterprise.concurrent.ManagedScheduledExecutorService) Instance(javax.enterprise.inject.Instance) GetStoragePoolInfoVDSCommandParameters(org.ovirt.engine.core.common.vdscommands.GetStoragePoolInfoVDSCommandParameters) RefObject(org.ovirt.engine.core.compat.RefObject) StoragePoolIsoMapId(org.ovirt.engine.core.common.businessentities.StoragePoolIsoMapId) Collection(java.util.Collection) EngineMessage(org.ovirt.engine.core.common.errors.EngineMessage) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) StorageConstants(org.ovirt.engine.core.common.constants.StorageConstants) Set(java.util.Set) EventQueue(org.ovirt.engine.core.common.eventqueue.EventQueue) BusinessEntitiesDefinitions(org.ovirt.engine.core.common.businessentities.BusinessEntitiesDefinitions) Collectors(java.util.stream.Collectors) AsyncTaskStatus(org.ovirt.engine.core.common.businessentities.AsyncTaskStatus) VdsStaticDao(org.ovirt.engine.core.dao.VdsStaticDao) VdsDynamicDao(org.ovirt.engine.core.dao.VdsDynamicDao) VDSNetworkException(org.ovirt.engine.core.vdsbroker.vdsbroker.VDSNetworkException) List(java.util.List) VDSStatus(org.ovirt.engine.core.common.businessentities.VDSStatus) VDSDomainsData(org.ovirt.engine.core.common.businessentities.VDSDomainsData) IVdsEventListener(org.ovirt.engine.core.common.businessentities.IVdsEventListener) PostConstruct(javax.annotation.PostConstruct) AuditLogType(org.ovirt.engine.core.common.AuditLogType) SpmStatusVDSCommandParameters(org.ovirt.engine.core.common.vdscommands.SpmStatusVDSCommandParameters) DisconnectStoragePoolVDSCommandParameters(org.ovirt.engine.core.common.vdscommands.DisconnectStoragePoolVDSCommandParameters) SpmStatusResult(org.ovirt.engine.core.common.businessentities.SpmStatusResult) SpmStopVDSCommandParameters(org.ovirt.engine.core.common.vdscommands.SpmStopVDSCommandParameters) StoragePool(org.ovirt.engine.core.common.businessentities.StoragePool) TransportFactory(org.ovirt.engine.core.vdsbroker.TransportFactory) ResourceManager(org.ovirt.engine.core.vdsbroker.ResourceManager) Guid(org.ovirt.engine.core.compat.Guid) StorageDomain(org.ovirt.engine.core.common.businessentities.StorageDomain) HashMap(java.util.HashMap) Callable(java.util.concurrent.Callable) StorageDomainStatus(org.ovirt.engine.core.common.businessentities.StorageDomainStatus) ThreadPools(org.ovirt.engine.core.utils.threadpool.ThreadPools) TransactionSupport(org.ovirt.engine.core.utils.transaction.TransactionSupport) StoragePoolIsoMapDao(org.ovirt.engine.core.dao.StoragePoolIsoMapDao) MessageFormat(java.text.MessageFormat) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) Inject(javax.inject.Inject) StorageDomainStatic(org.ovirt.engine.core.common.businessentities.StorageDomainStatic) LinkedList(java.util.LinkedList) StorageDomainStaticDao(org.ovirt.engine.core.dao.StorageDomainStaticDao) Pair(org.ovirt.engine.core.common.utils.Pair) VdsSpmIdMapDao(org.ovirt.engine.core.dao.VdsSpmIdMapDao) Config(org.ovirt.engine.core.common.config.Config) VdsIdVDSCommandParametersBase(org.ovirt.engine.core.common.vdscommands.VdsIdVDSCommandParametersBase) StoragePoolStatus(org.ovirt.engine.core.common.businessentities.StoragePoolStatus) LockingGroup(org.ovirt.engine.core.common.locks.LockingGroup) Logger(org.slf4j.Logger) Iterator(java.util.Iterator) ReentrantLock(java.util.concurrent.locks.ReentrantLock) AuditLogDirector(org.ovirt.engine.core.dal.dbbroker.auditloghandling.AuditLogDirector) VDSReturnValue(org.ovirt.engine.core.common.vdscommands.VDSReturnValue) ExceptionUtils(org.apache.commons.lang.exception.ExceptionUtils) EngineLock(org.ovirt.engine.core.utils.lock.EngineLock) ConfigValues(org.ovirt.engine.core.common.config.ConfigValues) SpmStatus(org.ovirt.engine.core.common.businessentities.SpmStatus) LockManager(org.ovirt.engine.core.utils.lock.LockManager) EventResult(org.ovirt.engine.core.common.eventqueue.EventResult) EngineError(org.ovirt.engine.core.common.errors.EngineError) TransactionScopeOption(org.ovirt.engine.core.compat.TransactionScopeOption) AuditLogable(org.ovirt.engine.core.dal.dbbroker.auditloghandling.AuditLogable) TimeUnit(java.util.concurrent.TimeUnit) VDSCommandType(org.ovirt.engine.core.common.vdscommands.VDSCommandType) StorageDomainType(org.ovirt.engine.core.common.businessentities.StorageDomainType) StorageDomainDao(org.ovirt.engine.core.dao.StorageDomainDao) Collections(java.util.Collections) VDS(org.ovirt.engine.core.common.businessentities.VDS) AsyncTaskStatusEnum(org.ovirt.engine.core.common.businessentities.AsyncTaskStatusEnum) StoragePoolIsoMap(org.ovirt.engine.core.common.businessentities.StoragePoolIsoMap) StoragePool(org.ovirt.engine.core.common.businessentities.StoragePool) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) HashMap(java.util.HashMap) KeyValuePairCompat(org.ovirt.engine.core.compat.KeyValuePairCompat) StoragePoolIsoMapId(org.ovirt.engine.core.common.businessentities.StoragePoolIsoMapId) VDSNetworkException(org.ovirt.engine.core.vdsbroker.vdsbroker.VDSNetworkException) Guid(org.ovirt.engine.core.compat.Guid) VDSReturnValue(org.ovirt.engine.core.common.vdscommands.VDSReturnValue) GetStoragePoolInfoVDSCommandParameters(org.ovirt.engine.core.common.vdscommands.GetStoragePoolInfoVDSCommandParameters) SpmStatusResult(org.ovirt.engine.core.common.businessentities.SpmStatusResult) StorageDomain(org.ovirt.engine.core.common.businessentities.StorageDomain) AsyncTaskStatus(org.ovirt.engine.core.common.businessentities.AsyncTaskStatus) List(java.util.List) ArrayList(java.util.ArrayList) LinkedList(java.util.LinkedList) HashSet(java.util.HashSet)

Example 2 with StoragePoolIsoMapId

use of org.ovirt.engine.core.common.businessentities.StoragePoolIsoMapId in project ovirt-engine by oVirt.

the class AddStoragePoolWithStoragesCommand method updateStorageDomainsInDb.

private boolean updateStorageDomainsInDb() {
    boolean result = TransactionSupport.executeInNewTransaction(() -> {
        for (Guid storageDomainId : getParameters().getStorages()) {
            StorageDomain storageDomain = storageDomainDao.get(storageDomainId);
            if (storageDomain != null) {
                StoragePoolIsoMap mapFromDB = storagePoolIsoMapDao.get(new StoragePoolIsoMapId(storageDomain.getId(), getStoragePool().getId()));
                boolean existingInDb = mapFromDB != null;
                if (existingInDb) {
                    getCompensationContext().snapshotEntity(mapFromDB);
                }
                final StorageDomainStatic staticDomain = storageDomain.getStorageStaticData();
                boolean staticDomainChanged = false;
                StorageFormatType requiredFormatType = VersionStorageFormatUtil.getForVersion(getStoragePool().getCompatibilityVersion());
                if (staticDomain.getStorageFormat().compareTo(requiredFormatType) < 0) {
                    if (!staticDomainChanged) {
                        getCompensationContext().snapshotEntity(staticDomain);
                    }
                    staticDomain.setStorageFormat(requiredFormatType);
                    staticDomainChanged = true;
                }
                storageDomain.setStoragePoolId(getStoragePool().getId());
                if (masterStorageDomain == null && storageDomain.getStorageDomainType() == StorageDomainType.Data) {
                    if (!staticDomainChanged) {
                        getCompensationContext().snapshotEntity(staticDomain);
                    }
                    storageDomain.setStorageDomainType(StorageDomainType.Master);
                    staticDomainChanged = true;
                    masterStorageDomain = storageDomain;
                    // The update of storage pool should be without compensation,
                    // this is why we run it in a different SUPRESS transaction.
                    updateStoragePoolMasterDomainVersionInDiffTransaction();
                }
                if (staticDomainChanged) {
                    storageDomainStaticDao.update(staticDomain);
                }
                storageDomain.setStatus(StorageDomainStatus.Locked);
                if (existingInDb) {
                    storagePoolIsoMapDao.update(storageDomain.getStoragePoolIsoMapData());
                } else {
                    storagePoolIsoMapDao.save(storageDomain.getStoragePoolIsoMapData());
                    getCompensationContext().snapshotNewEntity(storageDomain.getStoragePoolIsoMapData());
                }
            } else {
                return false;
            }
        }
        getCompensationContext().stateChanged();
        return true;
    });
    return result && masterStorageDomain != null;
}
Also used : StorageDomainStatic(org.ovirt.engine.core.common.businessentities.StorageDomainStatic) StorageDomain(org.ovirt.engine.core.common.businessentities.StorageDomain) StoragePoolIsoMap(org.ovirt.engine.core.common.businessentities.StoragePoolIsoMap) StorageFormatType(org.ovirt.engine.core.common.businessentities.StorageFormatType) StoragePoolIsoMapId(org.ovirt.engine.core.common.businessentities.StoragePoolIsoMapId) Guid(org.ovirt.engine.core.compat.Guid)

Example 3 with StoragePoolIsoMapId

use of org.ovirt.engine.core.common.businessentities.StoragePoolIsoMapId in project ovirt-engine by oVirt.

the class AddStoragePoolWithStoragesCommand method activateStorageDomains.

private boolean activateStorageDomains() {
    boolean returnValue = true;
    for (final Guid storageDomainId : getParameters().getStorages()) {
        StorageDomainPoolParametersBase activateParameters = new StorageDomainPoolParametersBase(storageDomainId, getStoragePool().getId());
        activateParameters.setSessionId(getParameters().getSessionId());
        activateParameters.setTransactionScopeOption(TransactionScopeOption.RequiresNew);
        returnValue = Backend.getInstance().runInternalAction(ActionType.ActivateStorageDomain, activateParameters).getSucceeded();
        // if activate domain failed then set domain status to inactive
        if (!returnValue) {
            TransactionSupport.executeInNewTransaction(() -> {
                storagePoolIsoMapDao.updateStatus(new StoragePoolIsoMapId(storageDomainId, getStoragePool().getId()), StorageDomainStatus.Inactive);
                return null;
            });
        }
    }
    return returnValue;
}
Also used : StorageDomainPoolParametersBase(org.ovirt.engine.core.common.action.StorageDomainPoolParametersBase) StoragePoolIsoMapId(org.ovirt.engine.core.common.businessentities.StoragePoolIsoMapId) Guid(org.ovirt.engine.core.compat.Guid)

Example 4 with StoragePoolIsoMapId

use of org.ovirt.engine.core.common.businessentities.StoragePoolIsoMapId in project ovirt-engine by oVirt.

the class RunVmValidatorTest method testNoIsoDomainIsoOnDataDomain.

@Test
public void testNoIsoDomainIsoOnDataDomain() {
    VM vm = new VM();
    vm.setStoragePoolId(Guid.newGuid());
    vm.setBootSequence(BootSequence.CD);
    StorageDomain storageDomain = new StorageDomain();
    storageDomain.setId(Guid.newGuid());
    DiskImage diskImage = new DiskImage();
    diskImage.setStorageIds(Collections.singletonList(storageDomain.getId()));
    diskImage.setContentType(DiskContentType.ISO);
    when(diskDao.get(any(Guid.class))).thenReturn(diskImage);
    when(storagePoolIsoMapDao.get(new StoragePoolIsoMapId(storageDomain.getId(), vm.getStoragePoolId()))).thenReturn(null);
    validateResult(runVmValidator.validateIsoPath(vm, Guid.newGuid().toString(), null, null), false, EngineMessage.VM_CANNOT_RUN_FROM_CD_WITHOUT_ACTIVE_STORAGE_DOMAIN_ISO);
}
Also used : StorageDomain(org.ovirt.engine.core.common.businessentities.StorageDomain) VM(org.ovirt.engine.core.common.businessentities.VM) StoragePoolIsoMapId(org.ovirt.engine.core.common.businessentities.StoragePoolIsoMapId) Guid(org.ovirt.engine.core.compat.Guid) DiskImage(org.ovirt.engine.core.common.businessentities.storage.DiskImage) Test(org.junit.Test)

Example 5 with StoragePoolIsoMapId

use of org.ovirt.engine.core.common.businessentities.StoragePoolIsoMapId in project ovirt-engine by oVirt.

the class RunVmValidator method validateIsoPath.

protected ValidationResult validateIsoPath(VM vm, String diskPath, String floppyPath, Guid activeIsoDomainId) {
    if (vm.isAutoStartup()) {
        return ValidationResult.VALID;
    }
    if (StringUtils.isEmpty(vm.getIsoPath()) && StringUtils.isEmpty(diskPath) && StringUtils.isEmpty(floppyPath)) {
        return ValidationResult.VALID;
    }
    if (!StringUtils.isEmpty(floppyPath) && activeIsoDomainId == null) {
        return new ValidationResult(EngineMessage.VM_CANNOT_RUN_FROM_CD_WITHOUT_ACTIVE_STORAGE_DOMAIN_ISO);
    }
    String effectiveIsoPath = StringUtils.isEmpty(diskPath) ? vm.getIsoPath() : diskPath;
    if (!StringUtils.isEmpty(effectiveIsoPath)) {
        if (effectiveIsoPath.matches(ValidationUtils.GUID)) {
            BaseDisk disk = diskDao.get(Guid.createGuidFromString(effectiveIsoPath));
            if (disk == null || disk.getContentType() != DiskContentType.ISO) {
                return new ValidationResult(EngineMessage.ERROR_CANNOT_FIND_ISO_IMAGE_PATH);
            }
            Guid domainId = ((DiskImage) disk).getStorageIds().get(0);
            StoragePoolIsoMap spim = storagePoolIsoMapDao.get(new StoragePoolIsoMapId(domainId, vm.getStoragePoolId()));
            if (spim == null || spim.getStatus() != StorageDomainStatus.Active) {
                return new ValidationResult(EngineMessage.VM_CANNOT_RUN_FROM_CD_WITHOUT_ACTIVE_STORAGE_DOMAIN_ISO);
            }
        } else if (activeIsoDomainId == null) {
            return new ValidationResult(EngineMessage.VM_CANNOT_RUN_FROM_CD_WITHOUT_ACTIVE_STORAGE_DOMAIN_ISO);
        } else if (!isRepoImageExists(effectiveIsoPath, activeIsoDomainId, ImageFileType.ISO)) {
            return new ValidationResult(EngineMessage.ERROR_CANNOT_FIND_ISO_IMAGE_PATH);
        }
        return ValidationResult.VALID;
    }
    if (!StringUtils.isEmpty(floppyPath) && !isRepoImageExists(floppyPath, activeIsoDomainId, ImageFileType.Floppy)) {
        return new ValidationResult(EngineMessage.ERROR_CANNOT_FIND_FLOPPY_IMAGE_PATH);
    }
    return ValidationResult.VALID;
}
Also used : StoragePoolIsoMap(org.ovirt.engine.core.common.businessentities.StoragePoolIsoMap) BaseDisk(org.ovirt.engine.core.common.businessentities.storage.BaseDisk) StoragePoolIsoMapId(org.ovirt.engine.core.common.businessentities.StoragePoolIsoMapId) Guid(org.ovirt.engine.core.compat.Guid) ValidationResult(org.ovirt.engine.core.bll.ValidationResult)

Aggregations

StoragePoolIsoMapId (org.ovirt.engine.core.common.businessentities.StoragePoolIsoMapId)16 Guid (org.ovirt.engine.core.compat.Guid)12 StoragePoolIsoMap (org.ovirt.engine.core.common.businessentities.StoragePoolIsoMap)10 StorageDomain (org.ovirt.engine.core.common.businessentities.StorageDomain)5 StorageDomainStatic (org.ovirt.engine.core.common.businessentities.StorageDomainStatic)4 DiskImage (org.ovirt.engine.core.common.businessentities.storage.DiskImage)4 Pair (org.ovirt.engine.core.common.utils.Pair)4 StorageDomainValidator (org.ovirt.engine.core.bll.validator.storage.StorageDomainValidator)3 ArrayList (java.util.ArrayList)2 HashMap (java.util.HashMap)2 HashSet (java.util.HashSet)2 LinkedList (java.util.LinkedList)2 ConcurrentHashMap (java.util.concurrent.ConcurrentHashMap)2 StorageDomainType (org.ovirt.engine.core.common.businessentities.StorageDomainType)2 VDS (org.ovirt.engine.core.common.businessentities.VDS)2 Event (org.ovirt.engine.core.common.eventqueue.Event)2 DisconnectStoragePoolVDSCommandParameters (org.ovirt.engine.core.common.vdscommands.DisconnectStoragePoolVDSCommandParameters)2 VDSReturnValue (org.ovirt.engine.core.common.vdscommands.VDSReturnValue)2 MessageFormat (java.text.MessageFormat)1 Arrays (java.util.Arrays)1