package org.zstack.storage.backup.sftp; import org.springframework.beans.factory.annotation.Autowired; import org.zstack.core.CoreGlobalProperty; import org.zstack.core.ansible.AnsibleFacade; 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.Component; import org.zstack.header.apimediator.ApiMessageInterceptionException; import org.zstack.header.apimediator.GlobalApiMessageInterceptor; import org.zstack.header.errorcode.ErrorCode; import org.zstack.header.errorcode.SysErrors; import org.zstack.header.message.APIMessage; import org.zstack.header.storage.backup.*; import org.zstack.utils.Utils; import org.zstack.utils.logging.CLogger; import static org.zstack.core.Platform.argerr; import java.util.ArrayList; import java.util.List; public class SftpBackupStorageFactory implements BackupStorageFactory, GlobalApiMessageInterceptor, Component { private static final CLogger logger = Utils.getLogger(SftpBackupStorageFactory.class); public static BackupStorageType type = new BackupStorageType( SftpBackupStorageConstant.SFTP_BACKUP_STORAGE_TYPE, BackupStorageConstant.SCHEME_HTTP, BackupStorageConstant.SCHEME_HTTPS, BackupStorageConstant.SCHEME_NFS, BackupStorageConstant.SCHEME_FILE ); @Autowired private DatabaseFacade dbf; @Autowired private AnsibleFacade asf; @Autowired private ErrorFacade errf; static { type.setOrder(999); } @Override public BackupStorageType getBackupStorageType() { return type; } @Override public BackupStorageInventory createBackupStorage(BackupStorageVO vo, APIAddBackupStorageMsg msg) { APIAddSftpBackupStorageMsg amsg = (APIAddSftpBackupStorageMsg) msg; final SftpBackupStorageVO lvo = new SftpBackupStorageVO(vo); lvo.setHostname(amsg.getHostname()); lvo.setUsername(amsg.getUsername()); lvo.setPassword(amsg.getPassword()); lvo.setSshPort(amsg.getSshPort()); dbf.persist(lvo); return SftpBackupStorageInventory.valueOf(lvo); } @Override public BackupStorage getBackupStorage(BackupStorageVO vo) { SftpBackupStorageVO lvo = dbf.findByUuid(vo.getUuid(), SftpBackupStorageVO.class); return new SftpBackupStorage(lvo); } @Override public BackupStorageInventory reload(String uuid) { SftpBackupStorageVO vo = dbf.findByUuid(uuid, SftpBackupStorageVO.class); return SftpBackupStorageInventory.valueOf(vo); } @Override public APIMessage intercept(APIMessage msg) throws ApiMessageInterceptionException { if (!CoreGlobalProperty.UNIT_TEST_ON) { if (msg instanceof APIAddSftpBackupStorageMsg) { APIAddSftpBackupStorageMsg amsg = (APIAddSftpBackupStorageMsg) msg; String url = amsg.getUrl(); if (!url.startsWith("/")) { ErrorCode err = argerr("invalid url[%s], the url must be an absolute path starting with '/'", amsg.getUrl()); throw new ApiMessageInterceptionException(err); } String hostname = amsg.getHostname(); SimpleQuery<SftpBackupStorageVO> query = dbf.createQuery(SftpBackupStorageVO.class); query.add(SftpBackupStorageVO_.hostname, Op.EQ, hostname); long count = query.count(); if (count != 0) { ErrorCode err = argerr("existing SimpleHttpBackupStorage with hostname[%s] found", hostname); throw new ApiMessageInterceptionException(err); } } } return msg; } @Override public List<Class> getMessageClassToIntercept() { List<Class> clzs = new ArrayList<Class>(1); clzs.add(APIAddBackupStorageMsg.class); return clzs; } @Override public InterceptorPosition getPosition() { return InterceptorPosition.END; } private void deploySaltState() { if (CoreGlobalProperty.UNIT_TEST_ON) { return; } asf.deployModule(SftpBackupStorageConstant.ANSIBLE_MODULE_PATH, SftpBackupStorageConstant.ANSIBLE_PLAYBOOK_NAME); } @Override public boolean start() { deploySaltState(); return true; } @Override public boolean stop() { return true; } }