package org.zstack.image; import org.springframework.beans.factory.annotation.Autowired; import org.zstack.core.cloudbus.CloudBus; import org.zstack.core.db.DatabaseFacade; import org.zstack.core.db.SimpleQuery; import org.zstack.core.db.SimpleQuery.Op; import org.zstack.core.errorcode.ErrorFacade; import org.zstack.header.apimediator.ApiMessageInterceptionException; import org.zstack.header.apimediator.ApiMessageInterceptor; import org.zstack.header.apimediator.StopRoutingException; import org.zstack.header.errorcode.SysErrors; import org.zstack.header.image.*; import org.zstack.header.image.ImageConstant.ImageMediaType; import org.zstack.header.message.APIMessage; import org.zstack.header.storage.backup.BackupStorageState; import org.zstack.header.storage.backup.BackupStorageStatus; import org.zstack.header.storage.backup.BackupStorageVO; import org.zstack.header.storage.backup.BackupStorageVO_; import org.zstack.header.vm.VmInstanceState; import org.zstack.header.vm.VmInstanceVO; import org.zstack.header.vm.VmInstanceVO_; import org.zstack.header.volume.VolumeFormat; import org.zstack.header.volume.VolumeState; import org.zstack.header.volume.VolumeStatus; import org.zstack.header.volume.VolumeVO; import static org.zstack.core.Platform.argerr; import static org.zstack.core.Platform.operr; import java.util.List; /** * Created with IntelliJ IDEA. * User: frank * Time: 4:35 PM * To change this template use File | Settings | File Templates. */ public class ImageApiInterceptor implements ApiMessageInterceptor { @Autowired private CloudBus bus; @Autowired private ErrorFacade errf; @Autowired private DatabaseFacade dbf; private void setServiceId(APIMessage msg) { if (msg instanceof ImageMessage) { ImageMessage imsg = (ImageMessage)msg; bus.makeTargetServiceIdByResourceUuid(msg, ImageConstant.SERVICE_ID, imsg.getImageUuid()); } } @Override public APIMessage intercept(APIMessage msg) throws ApiMessageInterceptionException { if (msg instanceof APIAddImageMsg) { validate((APIAddImageMsg)msg); } else if (msg instanceof APICreateRootVolumeTemplateFromRootVolumeMsg) { validate((APICreateRootVolumeTemplateFromRootVolumeMsg) msg); } else if (msg instanceof APICreateRootVolumeTemplateFromVolumeSnapshotMsg) { validate((APICreateRootVolumeTemplateFromVolumeSnapshotMsg) msg); } else if (msg instanceof APICreateDataVolumeTemplateFromVolumeMsg) { validate((APICreateDataVolumeTemplateFromVolumeMsg) msg); } setServiceId(msg); return msg; } private void validate(APICreateDataVolumeTemplateFromVolumeMsg msg) { VolumeVO vol = dbf.findByUuid(msg.getVolumeUuid(), VolumeVO.class); if (VolumeStatus.Ready != vol.getStatus()) { throw new ApiMessageInterceptionException(operr("volume[uuid:%s] is not Ready, it's %s", vol.getUuid(), vol.getStatus())); } if (VolumeState.Enabled != vol.getState()) { throw new ApiMessageInterceptionException(operr("volume[uuid:%s] is not Enabled, it's %s", vol.getUuid(), vol.getState())); } if (vol.getVmInstanceUuid() != null) { SimpleQuery<VmInstanceVO> q = dbf.createQuery(VmInstanceVO.class); q.select(VmInstanceVO_.state); q.add(VmInstanceVO_.uuid, Op.EQ, vol.getVmInstanceUuid()); VmInstanceState state = q.findValue(); if (VmInstanceState.Stopped != state) { throw new ApiMessageInterceptionException(operr("volume[uuid:%s] is attached to vm[uuid:%s]; the vm is not Stopped, it's %s", vol.getUuid(), vol.getVmInstanceUuid(), state)); } } } private void validate(APICreateRootVolumeTemplateFromVolumeSnapshotMsg msg) { if (msg.getPlatform() == null) { msg.setPlatform(ImagePlatform.Linux.toString()); } } private void validate(APICreateRootVolumeTemplateFromRootVolumeMsg msg) { if (msg.getPlatform() == null) { msg.setPlatform(ImagePlatform.Linux.toString()); } } private void validate(APIAddImageMsg msg) { if (ImageMediaType.ISO.toString().equals(msg.getMediaType())) { msg.setFormat(ImageConstant.ISO_FORMAT_STRING); } if (msg.isSystem() && (ImageMediaType.ISO.toString().equals(msg.getMediaType()) || ImageConstant.ISO_FORMAT_STRING.equals(msg.getFormat()))) { throw new ApiMessageInterceptionException(argerr( "ISO cannot be used as system image" )); } if (!VolumeFormat.hasType(msg.getFormat())) { throw new ApiMessageInterceptionException(argerr("unknown format[%s]", msg.getFormat())); } if (msg.getType() != null && !ImageType.hasType(msg.getType())) { throw new ApiMessageInterceptionException(argerr("unsupported image type[%s]", msg.getType())); } if (msg.getMediaType() == null) { msg.setMediaType(ImageMediaType.RootVolumeTemplate.toString()); } if (msg.getPlatform() == null) { msg.setPlatform(ImagePlatform.Linux.toString()); } if (msg.getBackupStorageUuids() != null) { SimpleQuery<BackupStorageVO> q = dbf.createQuery(BackupStorageVO.class); q.select(BackupStorageVO_.uuid); q.add(BackupStorageVO_.status, Op.EQ, BackupStorageStatus.Connected); q.add(BackupStorageVO_.state, Op.EQ, BackupStorageState.Enabled); q.add(BackupStorageVO_.uuid, Op.IN, msg.getBackupStorageUuids()); List<String> bsUuids = q.listValue(); if (bsUuids.isEmpty()) { throw new ApiMessageInterceptionException(operr("no backup storage specified in uuids%s is available for adding this image; they are not in status %s or not in state %s, or the uuid is invalid backup storage uuid", msg.getBackupStorageUuids(), BackupStorageStatus.Connected, BackupStorageState.Enabled)); } msg.setBackupStorageUuids(bsUuids); } } }