|
36 | 36 | import org.zstack.header.message.MessageReply; |
37 | 37 | import org.zstack.header.message.OverlayMessage; |
38 | 38 | import org.zstack.header.storage.primary.*; |
| 39 | +import org.zstack.header.storage.primary.CleanupVmInstanceMetadataOnPrimaryStorageMsg; |
| 40 | +import org.zstack.header.storage.primary.CleanupVmInstanceMetadataOnPrimaryStorageReply; |
39 | 41 | import org.zstack.header.storage.primary.VolumeSnapshotCapability.VolumeSnapshotArrangementType; |
40 | 42 | import org.zstack.header.storage.snapshot.*; |
41 | 43 | import org.zstack.header.vm.*; |
| 44 | +import org.zstack.header.vm.metadata.UpdateVmInstanceMetadataOnPrimaryStorageMsg; |
| 45 | +import org.zstack.header.vm.metadata.UpdateVmInstanceMetadataOnPrimaryStorageReply; |
42 | 46 | import org.zstack.header.vo.ResourceVO; |
43 | 47 | import org.zstack.header.volume.*; |
44 | 48 | import org.zstack.storage.primary.*; |
|
65 | 69 | import static org.zstack.core.Platform.*; |
66 | 70 | import static org.zstack.storage.primary.local.LocalStorageUtils.getHostUuidFromInstallUrl; |
67 | 71 | import static org.zstack.utils.CollectionDSL.*; |
68 | | -import static org.zstack.utils.CollectionUtils.*; |
| 72 | +import static org.zstack.utils.CollectionUtils.toMap; |
| 73 | +import static org.zstack.utils.CollectionUtils.transformAndRemoveNull; |
69 | 74 |
|
70 | 75 | /** |
71 | 76 | * Created by frank on 6/30/2015. |
@@ -1640,6 +1645,33 @@ public void fail(ErrorCode errorCode) { |
1640 | 1645 | }); |
1641 | 1646 | } |
1642 | 1647 |
|
| 1648 | + protected void handle(RebaseVolumeBackingFileOnPrimaryStorageMsg msg) { |
| 1649 | + final LocalStorageHypervisorBackend bkd; |
| 1650 | + try { |
| 1651 | + LocalStorageHypervisorFactory f = getHypervisorBackendFactoryByHostUuid(msg.getHostUuid()); |
| 1652 | + bkd = f.getHypervisorBackend(self); |
| 1653 | + } catch (Exception e) { |
| 1654 | + RebaseVolumeBackingFileOnPrimaryStorageReply reply = new RebaseVolumeBackingFileOnPrimaryStorageReply(); |
| 1655 | + reply.setError(operr("failed to resolve host/backend for rebase on local primary storage[uuid:%s], hostUuid[%s]: %s", |
| 1656 | + self.getUuid(), msg.getHostUuid(), e.getMessage())); |
| 1657 | + bus.reply(msg, reply); |
| 1658 | + return; |
| 1659 | + } |
| 1660 | + bkd.handle(msg, msg.getHostUuid(), new ReturnValueCompletion<RebaseVolumeBackingFileOnPrimaryStorageReply>(msg) { |
| 1661 | + @Override |
| 1662 | + public void success(RebaseVolumeBackingFileOnPrimaryStorageReply returnValue) { |
| 1663 | + bus.reply(msg, returnValue); |
| 1664 | + } |
| 1665 | + |
| 1666 | + @Override |
| 1667 | + public void fail(ErrorCode errorCode) { |
| 1668 | + RebaseVolumeBackingFileOnPrimaryStorageReply reply = new RebaseVolumeBackingFileOnPrimaryStorageReply(); |
| 1669 | + reply.setError(errorCode); |
| 1670 | + bus.reply(msg, reply); |
| 1671 | + } |
| 1672 | + }); |
| 1673 | + } |
| 1674 | + |
1643 | 1675 | private void handle(RemoveHostFromLocalStorageMsg msg) { |
1644 | 1676 | RemoveHostFromLocalStorageReply reply = new RemoveHostFromLocalStorageReply(); |
1645 | 1677 | thdf.chainSubmit(new ChainTask(msg) { |
@@ -3329,4 +3361,266 @@ public void fail(ErrorCode errorCode) { |
3329 | 3361 | public static class LocalStoragePhysicalCapacityUsage extends PrimaryStorageBase.PhysicalCapacityUsage { |
3330 | 3362 | public long localStorageUsedSize; |
3331 | 3363 | } |
| 3364 | + |
| 3365 | + @Override |
| 3366 | + protected void handle(final UpdateVmInstanceMetadataOnPrimaryStorageMsg msg) { |
| 3367 | + thdf.chainSubmit(new ChainTask(msg) { |
| 3368 | + @Override |
| 3369 | + public String getSyncSignature() { |
| 3370 | + return String.format("update-metadata-on-ps-%s", self.getUuid()); |
| 3371 | + } |
| 3372 | + |
| 3373 | + @Override |
| 3374 | + public int getSyncLevel() { |
| 3375 | + return 10; |
| 3376 | + } |
| 3377 | + |
| 3378 | + @Override |
| 3379 | + public void run(SyncTaskChain chain) { |
| 3380 | + final String hostUuid; |
| 3381 | + final LocalStorageHypervisorBackend bkd; |
| 3382 | + try { |
| 3383 | + hostUuid = getHostUuidByResourceUuid(msg.getRootVolumeUuid()); |
| 3384 | + LocalStorageHypervisorFactory f = getHypervisorBackendFactoryByHostUuid(hostUuid); |
| 3385 | + bkd = f.getHypervisorBackend(self); |
| 3386 | + } catch (Exception e) { |
| 3387 | + UpdateVmInstanceMetadataOnPrimaryStorageReply reply = new UpdateVmInstanceMetadataOnPrimaryStorageReply(); |
| 3388 | + reply.setError(operr("failed to resolve host for vm metadata update on local primary storage[uuid:%s], rootVolumeUuid[%s]: %s", |
| 3389 | + self.getUuid(), msg.getRootVolumeUuid(), e.getMessage())); |
| 3390 | + bus.reply(msg, reply); |
| 3391 | + chain.next(); |
| 3392 | + return; |
| 3393 | + } |
| 3394 | + bkd.handle(msg, hostUuid, new ReturnValueCompletion<UpdateVmInstanceMetadataOnPrimaryStorageReply>(msg, chain) { |
| 3395 | + @Override |
| 3396 | + public void success(UpdateVmInstanceMetadataOnPrimaryStorageReply returnValue) { |
| 3397 | + bus.reply(msg, returnValue); |
| 3398 | + chain.next(); |
| 3399 | + } |
| 3400 | + |
| 3401 | + @Override |
| 3402 | + public void fail(ErrorCode errorCode) { |
| 3403 | + UpdateVmInstanceMetadataOnPrimaryStorageReply reply = new UpdateVmInstanceMetadataOnPrimaryStorageReply(); |
| 3404 | + reply.setError(errorCode); |
| 3405 | + bus.reply(msg, reply); |
| 3406 | + chain.next(); |
| 3407 | + } |
| 3408 | + }); |
| 3409 | + } |
| 3410 | + |
| 3411 | + @Override |
| 3412 | + public String getName() { |
| 3413 | + return String.format("update-metadata-on-ps-%s", self.getUuid()); |
| 3414 | + } |
| 3415 | + }); |
| 3416 | + } |
| 3417 | + |
| 3418 | + @Override |
| 3419 | + protected void handle(final GetVmInstanceMetadataFromPrimaryStorageMsg msg) { |
| 3420 | + GetVmInstanceMetadataFromPrimaryStorageReply reply = new GetVmInstanceMetadataFromPrimaryStorageReply(); |
| 3421 | + |
| 3422 | + String hostUuid = null; |
| 3423 | + if (msg.getHostUuid() != null) { |
| 3424 | + hostUuid = msg.getHostUuid(); |
| 3425 | + } |
| 3426 | + |
| 3427 | + if (hostUuid == null) { |
| 3428 | + if (msg.getRootVolumeUuid() == null) { |
| 3429 | + reply.setError(operr("cannot determine host for vm metadata get on local primary storage[uuid:%s]," + |
| 3430 | + " rootVolumeUuid is null", self.getUuid())); |
| 3431 | + bus.reply(msg, reply); |
| 3432 | + return; |
| 3433 | + } |
| 3434 | + try { |
| 3435 | + hostUuid = getHostUuidByResourceUuid(msg.getRootVolumeUuid()); |
| 3436 | + } catch (Exception e) { |
| 3437 | + reply.setError(operr("cannot determine host for vm metadata get on local primary storage[uuid:%s], rootVolumeUuid[%s]: %s", |
| 3438 | + self.getUuid(), msg.getRootVolumeUuid(), e.getMessage())); |
| 3439 | + bus.reply(msg, reply); |
| 3440 | + return; |
| 3441 | + } |
| 3442 | + } |
| 3443 | + |
| 3444 | + final LocalStorageHypervisorBackend bkd; |
| 3445 | + try { |
| 3446 | + LocalStorageHypervisorFactory f = getHypervisorBackendFactoryByHostUuid(hostUuid); |
| 3447 | + bkd = f.getHypervisorBackend(self); |
| 3448 | + } catch (Exception e) { |
| 3449 | + reply.setError(operr("failed to resolve host/backend for vm metadata get on local primary storage[uuid:%s], hostUuid[%s]: %s", |
| 3450 | + self.getUuid(), hostUuid, e.getMessage())); |
| 3451 | + bus.reply(msg, reply); |
| 3452 | + return; |
| 3453 | + } |
| 3454 | + bkd.handle(msg, hostUuid, new ReturnValueCompletion<GetVmInstanceMetadataFromPrimaryStorageReply>(msg) { |
| 3455 | + @Override |
| 3456 | + public void success(GetVmInstanceMetadataFromPrimaryStorageReply returnValue) { |
| 3457 | + bus.reply(msg, returnValue); |
| 3458 | + } |
| 3459 | + |
| 3460 | + @Override |
| 3461 | + public void fail(ErrorCode errorCode) { |
| 3462 | + reply.setError(errorCode); |
| 3463 | + bus.reply(msg, reply); |
| 3464 | + } |
| 3465 | + }); |
| 3466 | + } |
| 3467 | + |
| 3468 | + @Override |
| 3469 | + protected void handle(final ScanVmInstanceMetadataFromPrimaryStorageMsg msg) { |
| 3470 | + ScanVmInstanceMetadataFromPrimaryStorageReply reply = new ScanVmInstanceMetadataFromPrimaryStorageReply(); |
| 3471 | + |
| 3472 | + List<String> allHostUuids = SQL.New( |
| 3473 | + "select h.hostUuid from LocalStorageHostRefVO h, HostVO host" + |
| 3474 | + " where h.primaryStorageUuid = :psUuid" + |
| 3475 | + " and h.hostUuid = host.uuid", String.class) |
| 3476 | + .param("psUuid", self.getUuid()) |
| 3477 | + .list(); |
| 3478 | + if (allHostUuids.isEmpty()) { |
| 3479 | + reply.setError(operr("no host found for local primary storage[uuid:%s]", self.getUuid())); |
| 3480 | + bus.reply(msg, reply); |
| 3481 | + return; |
| 3482 | + } |
| 3483 | + |
| 3484 | + List<String> connectedHostUuids = SQL.New( |
| 3485 | + "select h.hostUuid from LocalStorageHostRefVO h, HostVO host" + |
| 3486 | + " where h.primaryStorageUuid = :psUuid" + |
| 3487 | + " and h.hostUuid = host.uuid" + |
| 3488 | + " and host.status = :hstatus", String.class) |
| 3489 | + .param("psUuid", self.getUuid()) |
| 3490 | + .param("hstatus", HostStatus.Connected) |
| 3491 | + .list(); |
| 3492 | + if (connectedHostUuids.isEmpty()) { |
| 3493 | + reply.setError(operr("no connected host found for local primary storage[uuid:%s], " + |
| 3494 | + "total hosts=%d", self.getUuid(), allHostUuids.size())); |
| 3495 | + bus.reply(msg, reply); |
| 3496 | + return; |
| 3497 | + } |
| 3498 | + |
| 3499 | + // Disconnected hosts cannot be scanned; treat them as failed upfront |
| 3500 | + List<String> disconnectedHostUuids = new ArrayList<>(allHostUuids); |
| 3501 | + disconnectedHostUuids.removeAll(connectedHostUuids); |
| 3502 | + |
| 3503 | + List<VmMetadataScanEntry> allSummaries = Collections.synchronizedList(new ArrayList<>()); |
| 3504 | + List<String> failedHosts = Collections.synchronizedList(new ArrayList<>(disconnectedHostUuids)); |
| 3505 | + if (!disconnectedHostUuids.isEmpty()) { |
| 3506 | + logger.warn(String.format("local primary storage[uuid:%s] has %d disconnected hosts that cannot be scanned: %s", |
| 3507 | + self.getUuid(), disconnectedHostUuids.size(), disconnectedHostUuids)); |
| 3508 | + } |
| 3509 | + |
| 3510 | + new While<>(connectedHostUuids).all((hostUuid, com) -> { |
| 3511 | + final LocalStorageHypervisorBackend bkd; |
| 3512 | + try { |
| 3513 | + LocalStorageHypervisorFactory f = getHypervisorBackendFactoryByHostUuid(hostUuid); |
| 3514 | + bkd = f.getHypervisorBackend(self); |
| 3515 | + } catch (Exception e) { |
| 3516 | + failedHosts.add(hostUuid); |
| 3517 | + com.addError(operr("failed to prepare vm metadata scan on host[uuid:%s]: %s", |
| 3518 | + hostUuid, e.getMessage())); |
| 3519 | + com.done(); |
| 3520 | + return; |
| 3521 | + } |
| 3522 | + bkd.handle(msg, hostUuid, new ReturnValueCompletion<ScanVmInstanceMetadataFromPrimaryStorageReply>(com) { |
| 3523 | + @Override |
| 3524 | + public void success(ScanVmInstanceMetadataFromPrimaryStorageReply returnValue) { |
| 3525 | + if (returnValue.getVmInstanceMetadata() != null) { |
| 3526 | + allSummaries.addAll(returnValue.getVmInstanceMetadata()); |
| 3527 | + } |
| 3528 | + com.done(); |
| 3529 | + } |
| 3530 | + |
| 3531 | + @Override |
| 3532 | + public void fail(ErrorCode errorCode) { |
| 3533 | + logger.warn(String.format("failed to scan vm metadata from host[uuid:%s] on local primary storage[uuid:%s]: %s", |
| 3534 | + hostUuid, self.getUuid(), errorCode)); |
| 3535 | + failedHosts.add(hostUuid); |
| 3536 | + com.addError(errorCode); |
| 3537 | + com.done(); |
| 3538 | + } |
| 3539 | + }); |
| 3540 | + }).run(new WhileDoneCompletion(msg) { |
| 3541 | + @Override |
| 3542 | + public void done(ErrorCodeList errorCodeList) { |
| 3543 | + if (!errorCodeList.getCauses().isEmpty() && errorCodeList.getCauses().size() == connectedHostUuids.size()) { |
| 3544 | + reply.setError(operr("failed to scan vm metadata from all hosts on local primary storage[uuid:%s], causes: %s", |
| 3545 | + self.getUuid(), errorCodeList)); |
| 3546 | + } else { |
| 3547 | + reply.setVmInstanceMetadata(new ArrayList<>(allSummaries)); |
| 3548 | + if (!failedHosts.isEmpty()) { |
| 3549 | + logger.warn(String.format("partial scan failure on local primary storage[uuid:%s], " + |
| 3550 | + "failedHosts=%s, successHosts=%d/%d", self.getUuid(), failedHosts, |
| 3551 | + connectedHostUuids.size() - failedHosts.size(), connectedHostUuids.size())); |
| 3552 | + } |
| 3553 | + } |
| 3554 | + bus.reply(msg, reply); |
| 3555 | + } |
| 3556 | + }); |
| 3557 | + } |
| 3558 | + |
| 3559 | + @Override |
| 3560 | + protected void handle(final CleanupVmInstanceMetadataOnPrimaryStorageMsg msg) { |
| 3561 | + thdf.chainSubmit(new ChainTask(msg) { |
| 3562 | + @Override |
| 3563 | + public String getSyncSignature() { |
| 3564 | + return String.format("update-metadata-on-ps-%s-%s", self.getUuid(), msg.getVmInstanceUuid()); |
| 3565 | + } |
| 3566 | + |
| 3567 | + @Override |
| 3568 | + public int getSyncLevel() { |
| 3569 | + return 1; |
| 3570 | + } |
| 3571 | + |
| 3572 | + @Override |
| 3573 | + public void run(SyncTaskChain chain) { |
| 3574 | + CleanupVmInstanceMetadataOnPrimaryStorageReply reply = new CleanupVmInstanceMetadataOnPrimaryStorageReply(); |
| 3575 | + |
| 3576 | + String hostUuid = msg.getHostUuid(); |
| 3577 | + if (hostUuid == null && msg.getRootVolumeUuid() != null) { |
| 3578 | + try { |
| 3579 | + hostUuid = getHostUuidByResourceUuid(msg.getRootVolumeUuid()); |
| 3580 | + } catch (Exception e) { |
| 3581 | + logger.warn(String.format("failed to get host by rootVolumeUuid[%s]: %s", msg.getRootVolumeUuid(), e.getMessage())); |
| 3582 | + } |
| 3583 | + } |
| 3584 | + |
| 3585 | + if (hostUuid == null) { |
| 3586 | + reply.setError(operr("cannot determine host for vm metadata cleanup on local primary storage[uuid:%s]," + |
| 3587 | + " rootVolumeUuid[%s], hostUuid is null", self.getUuid(), msg.getRootVolumeUuid())); |
| 3588 | + bus.reply(msg, reply); |
| 3589 | + chain.next(); |
| 3590 | + return; |
| 3591 | + } |
| 3592 | + |
| 3593 | + final LocalStorageHypervisorBackend bkd; |
| 3594 | + try { |
| 3595 | + LocalStorageHypervisorFactory f = getHypervisorBackendFactoryByHostUuid(hostUuid); |
| 3596 | + bkd = f.getHypervisorBackend(self); |
| 3597 | + } catch (Exception e) { |
| 3598 | + reply.setError(operr("failed to resolve host/backend for vm metadata cleanup on local primary storage[uuid:%s], hostUuid[%s]: %s", |
| 3599 | + self.getUuid(), hostUuid, e.getMessage())); |
| 3600 | + bus.reply(msg, reply); |
| 3601 | + chain.next(); |
| 3602 | + return; |
| 3603 | + } |
| 3604 | + bkd.handle(msg, hostUuid, new ReturnValueCompletion<CleanupVmInstanceMetadataOnPrimaryStorageReply>(msg, chain) { |
| 3605 | + @Override |
| 3606 | + public void success(CleanupVmInstanceMetadataOnPrimaryStorageReply returnValue) { |
| 3607 | + bus.reply(msg, returnValue); |
| 3608 | + chain.next(); |
| 3609 | + } |
| 3610 | + |
| 3611 | + @Override |
| 3612 | + public void fail(ErrorCode errorCode) { |
| 3613 | + reply.setError(errorCode); |
| 3614 | + bus.reply(msg, reply); |
| 3615 | + chain.next(); |
| 3616 | + } |
| 3617 | + }); |
| 3618 | + } |
| 3619 | + |
| 3620 | + @Override |
| 3621 | + public String getName() { |
| 3622 | + return String.format("cleanup-metadata-on-ps-%s-%s", self.getUuid(), msg.getVmInstanceUuid()); |
| 3623 | + } |
| 3624 | + }); |
| 3625 | + } |
3332 | 3626 | } |
0 commit comments