Message ID | 20190903162246.18524-2-yury-kotov@yandex-team.ru (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | UUID validation during migration | expand |
* Yury Kotov (yury-kotov@yandex-team.ru) wrote: > This capability realizes simple source validation by UUID. > It's useful for live migration between hosts. > > Signed-off-by: Yury Kotov <yury-kotov@yandex-team.ru> Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com> > --- > migration/migration.c | 9 +++++++++ > migration/migration.h | 1 + > migration/savevm.c | 45 +++++++++++++++++++++++++++++++++++++++++++ > qapi/migration.json | 5 ++++- > 4 files changed, 59 insertions(+), 1 deletion(-) > > diff --git a/migration/migration.c b/migration/migration.c > index 8b9f2fe30a..2391a8d418 100644 > --- a/migration/migration.c > +++ b/migration/migration.c > @@ -2140,6 +2140,15 @@ bool migrate_ignore_shared(void) > return s->enabled_capabilities[MIGRATION_CAPABILITY_X_IGNORE_SHARED]; > } > > +bool migrate_validate_uuid(void) > +{ > + MigrationState *s; > + > + s = migrate_get_current(); > + > + return s->enabled_capabilities[MIGRATION_CAPABILITY_VALIDATE_UUID]; > +} > + > bool migrate_use_events(void) > { > MigrationState *s; > diff --git a/migration/migration.h b/migration/migration.h > index 3e1ea2b5dc..4f2fe193dc 100644 > --- a/migration/migration.h > +++ b/migration/migration.h > @@ -290,6 +290,7 @@ bool migrate_postcopy_ram(void); > bool migrate_zero_blocks(void); > bool migrate_dirty_bitmaps(void); > bool migrate_ignore_shared(void); > +bool migrate_validate_uuid(void); > > bool migrate_auto_converge(void); > bool migrate_use_multifd(void); > diff --git a/migration/savevm.c b/migration/savevm.c > index 4a86128ac4..493dc24fd2 100644 > --- a/migration/savevm.c > +++ b/migration/savevm.c > @@ -256,6 +256,7 @@ typedef struct SaveState { > uint32_t target_page_bits; > uint32_t caps_count; > MigrationCapability *capabilities; > + QemuUUID uuid; > } SaveState; > > static SaveState savevm_state = { > @@ -307,6 +308,7 @@ static int configuration_pre_save(void *opaque) > state->capabilities[j++] = i; > } > } > + state->uuid = qemu_uuid; > > return 0; > } > @@ -464,6 +466,48 @@ static const VMStateDescription vmstate_capabilites = { > } > }; > > +static bool vmstate_uuid_needed(void *opaque) > +{ > + return qemu_uuid_set && migrate_validate_uuid(); > +} > + > +static int vmstate_uuid_post_load(void *opaque, int version_id) > +{ > + SaveState *state = opaque; > + char uuid_src[UUID_FMT_LEN + 1]; > + char uuid_dst[UUID_FMT_LEN + 1]; > + > + if (!qemu_uuid_set) { > + /* > + * It's warning because user might not know UUID in some cases, > + * e.g. load an old snapshot > + */ > + qemu_uuid_unparse(&state->uuid, uuid_src); > + warn_report("UUID is received %s, but local uuid isn't set", > + uuid_src); > + return 0; > + } > + if (!qemu_uuid_is_equal(&state->uuid, &qemu_uuid)) { > + qemu_uuid_unparse(&state->uuid, uuid_src); > + qemu_uuid_unparse(&qemu_uuid, uuid_dst); > + error_report("UUID received is %s and local is %s", uuid_src, uuid_dst); > + return -EINVAL; > + } > + return 0; > +} > + > +static const VMStateDescription vmstate_uuid = { > + .name = "configuration/uuid", > + .version_id = 1, > + .minimum_version_id = 1, > + .needed = vmstate_uuid_needed, > + .post_load = vmstate_uuid_post_load, > + .fields = (VMStateField[]) { > + VMSTATE_UINT8_ARRAY_V(uuid.data, SaveState, sizeof(QemuUUID), 1), > + VMSTATE_END_OF_LIST() > + } > +}; > + > static const VMStateDescription vmstate_configuration = { > .name = "configuration", > .version_id = 1, > @@ -478,6 +522,7 @@ static const VMStateDescription vmstate_configuration = { > .subsections = (const VMStateDescription*[]) { > &vmstate_target_page_bits, > &vmstate_capabilites, > + &vmstate_uuid, > NULL > } > }; > diff --git a/qapi/migration.json b/qapi/migration.json > index 9cfbaf8c6c..82feb5bd39 100644 > --- a/qapi/migration.json > +++ b/qapi/migration.json > @@ -415,6 +415,9 @@ > # > # @x-ignore-shared: If enabled, QEMU will not migrate shared memory (since 4.0) > # > +# @validate-uuid: Send the UUID of the source to allow the destination > +# to ensure it is the same. (since 4.2) > +# > # Since: 1.2 > ## > { 'enum': 'MigrationCapability', > @@ -422,7 +425,7 @@ > 'compress', 'events', 'postcopy-ram', 'x-colo', 'release-ram', > 'block', 'return-path', 'pause-before-switchover', 'multifd', > 'dirty-bitmaps', 'postcopy-blocktime', 'late-block-activate', > - 'x-ignore-shared' ] } > + 'x-ignore-shared', 'validate-uuid' ] } > > ## > # @MigrationCapabilityStatus: > -- > 2.17.1 > -- Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK
diff --git a/migration/migration.c b/migration/migration.c index 8b9f2fe30a..2391a8d418 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -2140,6 +2140,15 @@ bool migrate_ignore_shared(void) return s->enabled_capabilities[MIGRATION_CAPABILITY_X_IGNORE_SHARED]; } +bool migrate_validate_uuid(void) +{ + MigrationState *s; + + s = migrate_get_current(); + + return s->enabled_capabilities[MIGRATION_CAPABILITY_VALIDATE_UUID]; +} + bool migrate_use_events(void) { MigrationState *s; diff --git a/migration/migration.h b/migration/migration.h index 3e1ea2b5dc..4f2fe193dc 100644 --- a/migration/migration.h +++ b/migration/migration.h @@ -290,6 +290,7 @@ bool migrate_postcopy_ram(void); bool migrate_zero_blocks(void); bool migrate_dirty_bitmaps(void); bool migrate_ignore_shared(void); +bool migrate_validate_uuid(void); bool migrate_auto_converge(void); bool migrate_use_multifd(void); diff --git a/migration/savevm.c b/migration/savevm.c index 4a86128ac4..493dc24fd2 100644 --- a/migration/savevm.c +++ b/migration/savevm.c @@ -256,6 +256,7 @@ typedef struct SaveState { uint32_t target_page_bits; uint32_t caps_count; MigrationCapability *capabilities; + QemuUUID uuid; } SaveState; static SaveState savevm_state = { @@ -307,6 +308,7 @@ static int configuration_pre_save(void *opaque) state->capabilities[j++] = i; } } + state->uuid = qemu_uuid; return 0; } @@ -464,6 +466,48 @@ static const VMStateDescription vmstate_capabilites = { } }; +static bool vmstate_uuid_needed(void *opaque) +{ + return qemu_uuid_set && migrate_validate_uuid(); +} + +static int vmstate_uuid_post_load(void *opaque, int version_id) +{ + SaveState *state = opaque; + char uuid_src[UUID_FMT_LEN + 1]; + char uuid_dst[UUID_FMT_LEN + 1]; + + if (!qemu_uuid_set) { + /* + * It's warning because user might not know UUID in some cases, + * e.g. load an old snapshot + */ + qemu_uuid_unparse(&state->uuid, uuid_src); + warn_report("UUID is received %s, but local uuid isn't set", + uuid_src); + return 0; + } + if (!qemu_uuid_is_equal(&state->uuid, &qemu_uuid)) { + qemu_uuid_unparse(&state->uuid, uuid_src); + qemu_uuid_unparse(&qemu_uuid, uuid_dst); + error_report("UUID received is %s and local is %s", uuid_src, uuid_dst); + return -EINVAL; + } + return 0; +} + +static const VMStateDescription vmstate_uuid = { + .name = "configuration/uuid", + .version_id = 1, + .minimum_version_id = 1, + .needed = vmstate_uuid_needed, + .post_load = vmstate_uuid_post_load, + .fields = (VMStateField[]) { + VMSTATE_UINT8_ARRAY_V(uuid.data, SaveState, sizeof(QemuUUID), 1), + VMSTATE_END_OF_LIST() + } +}; + static const VMStateDescription vmstate_configuration = { .name = "configuration", .version_id = 1, @@ -478,6 +522,7 @@ static const VMStateDescription vmstate_configuration = { .subsections = (const VMStateDescription*[]) { &vmstate_target_page_bits, &vmstate_capabilites, + &vmstate_uuid, NULL } }; diff --git a/qapi/migration.json b/qapi/migration.json index 9cfbaf8c6c..82feb5bd39 100644 --- a/qapi/migration.json +++ b/qapi/migration.json @@ -415,6 +415,9 @@ # # @x-ignore-shared: If enabled, QEMU will not migrate shared memory (since 4.0) # +# @validate-uuid: Send the UUID of the source to allow the destination +# to ensure it is the same. (since 4.2) +# # Since: 1.2 ## { 'enum': 'MigrationCapability', @@ -422,7 +425,7 @@ 'compress', 'events', 'postcopy-ram', 'x-colo', 'release-ram', 'block', 'return-path', 'pause-before-switchover', 'multifd', 'dirty-bitmaps', 'postcopy-blocktime', 'late-block-activate', - 'x-ignore-shared' ] } + 'x-ignore-shared', 'validate-uuid' ] } ## # @MigrationCapabilityStatus:
This capability realizes simple source validation by UUID. It's useful for live migration between hosts. Signed-off-by: Yury Kotov <yury-kotov@yandex-team.ru> --- migration/migration.c | 9 +++++++++ migration/migration.h | 1 + migration/savevm.c | 45 +++++++++++++++++++++++++++++++++++++++++++ qapi/migration.json | 5 ++++- 4 files changed, 59 insertions(+), 1 deletion(-)