This commit is contained in:
2026-10-16 15:23:28 +03:00
parent 8cde0e9371
commit 84164a72a4
32 changed files with 1019 additions and 260 deletions

View File

@@ -1,4 +1,4 @@
## Version 1.16.7
## Version 1.16.8
### Deprecated
@@ -10,6 +10,8 @@
| `account/AddUser` | :heavy_check_mark: | :heavy_check_mark: |
| `account/DeleteUser` | :heavy_check_mark: | :heavy_check_mark: |
| `account/UpdateUser` | :heavy_check_mark: | :heavy_check_mark: |
| `compute/CreateTemplate` | :heavy_check_mark: | :heavy_check_mark: |
| `compute/CreateTemplateFromBlank` | :heavy_check_mark: | :heavy_check_mark: |
| `compute/DiskQOS` | :heavy_check_mark: | :heavy_check_mark: |
| `compute/Migrate` | :x: | :heavy_check_mark: |
| `compute/MigrateAbort` | :x: | :heavy_check_mark: |
@@ -22,6 +24,7 @@
| `compute/UserList` | :heavy_check_mark: | :heavy_check_mark: |
| `compute/UserRevoke` | :heavy_check_mark: | :heavy_check_mark: |
| `compute/UserUpdate` | :heavy_check_mark: | :heavy_check_mark: |
| `disks/FromPlatformDisk` | :heavy_check_mark: | :heavy_check_mark: |
| `rg/AccessGrant` | :heavy_check_mark: | :heavy_check_mark: |
| `rg/AccessRevoke` | :heavy_check_mark: | :heavy_check_mark: |
| `sep/ConfigFieldEdit` | :x: | :heavy_check_mark: |
@@ -30,248 +33,70 @@
### Добавлено
#### apiaccess
| Идентификатор задачи | Описание |
| --- | --- |
| BGOS-1123 | Вычисляемое поле `BasisMPM` в структуру ответа `CloudBrokerEndpoints` в cloudbroker/apiaccess |
#### basismpm
| Идентификатор задачи | Описание |
| --- | --- |
| BGOS-1123 | Структура запроса `StartRequest` и метод `Start` в cloudbroker/basismpm |
| BGOS-1123 | Структура запроса `StatusRequest` и метод `Status` в cloudbroker/basismpm |
| BGOS-1123 | Структура запроса `StopRequest` и метод `Stop` в cloudbroker/basismpm |
| BGOS-1123 | Структура запроса `UpdateRequest` и метод `Update` в cloudbroker/basismpm |
| BGOS-1123 | Структуры ответа `MemInfo` и `RecordBasisMPM` в cloudbroker/basismpm |
#### image
| Идентификатор задачи | Описание |
| --- | --- |
| BGOS-1124 | Структура запроса `CreateFromDiskRequest` и методы `CreateFromDisk` и `CreateFromDiskAsync` в cloudapi/image |
| BGOS-1124 | Структура запроса `CreateFromDiskRequest` и методы `CreateFromDisk` и `CreateFromDiskAsync` в cloudbroker/image |
#### compute
| Идентификатор задачи | Описание |
| --- | --- |
| BGOS-1111 | Опциональное поле `Planned` в структуру запроса `DiskSwitchToReplicationRequest` в cloudapi/compute |
| BGOS-1111 | Опциональное поле `Planned` в структуру запроса `DiskSwitchToReplicationRequest` в cloudbroker/compute |
| BGOS-1118 | Вычисляемое поле `CRTTracking` в структуру ответа `ItemComputeDisk` в cloudapi/compute |
| BGOS-1118 | Вычисляемое поле `CRTTracking` в структуру ответа `ItemDisk` в cloudbroker/compute |
| BGOS-1120 | Структура запроса `wrapperMigrateStorageRequest` и метод `MigrateStorageAsync` в cloudbroker/compute |
| BGOS-1126 | Вычисляемые поля `PreviousReservesComputeResources` и `TakeOverResources` в структуру ответа `Resolution` в cloudbroker/compute |
| BGOS-1126 | Опциональное поле `TakeOverResources` в структуру запроса `MigrateV2ResolveRequest` в cloudbroker/compute |
| BGOS-1126 | Вычисляемое поле `Message` в структуру ответа `MigrateV2ResolveRecord` в cloudbroker/compute |
| BGOS-1126 | Вычисляемые поля `DisksCompleted`, `CompletedDisks`, `DisksTotal` и `CurrentDisk` в структуру ответа `ProgressDisks` в cloudbroker/compute |
| BGOS-1126 | Структуры ответа `CompletedDisk` и `CurrentDisk` в cloudbroker/compute |
#### disks
#### zone
| Идентификатор задачи | Описание |
| --- | --- |
| BGOS-1109 | Структура запроса `ReplicationManualSyncRequest` и метод `ReplicationManualSync` в cloudapi/disks |
| BGOS-1109 | Структура запроса `ReplicationSetScheduleRequest` и метод `ReplicationSetSchedule` в cloudapi/disks |
| BGOS-1109 | Структура запроса `ReplicationDisableScheduleRequest` и метод `ReplicationDisableSchedule` в cloudapi/disks |
| BGOS-1109 | Структура запроса `ReplicationSetCopyRateRequest` и метод `ReplicationSetCopyRate` в cloudapi/disks |
| BGOS-1109 | Структура запроса `ReplicationPromote` и методы `ReplicationPromote` и `ReplicationPromoteAsync` в cloudapi/disks |
| BGOS-1109 | Структура запроса `ReplicationSyncNowRequest` и метод `ReplicationSyncNow` в cloudbroker/disks |
| BGOS-1109 | Структура запроса `ReplicationEnableScheduleRequest` и метод `ReplicationEnableSchedule` в cloudbroker/disks |
| BGOS-1109 | Структура запроса `ReplicationDisableScheduleRequest` и метод `ReplicationDisableSchedule` в cloudbroker/disks |
| BGOS-1109 | Структура запроса `ReplicationSetCopyRateRequest` и метод `ReplicationSetCopyRate` в cloudbroker/disks |
| BGOS-1109 | Структура запроса `ReplicationPromote` и методы `ReplicationPromote` и `ReplicationPromoteAsync` в cloudbroker/disks |
| BGOS-1108 | Вычисляемое поле `CRTTracking` в структуру ответа `InfoDisk` в cloudbroker/disks |
| BGOS-1108 | Вычисляемое поле `CRTTracking` в структуры ответа `ItemDisk`, `ItemDiskUnattached` и `RecordDisk` в cloudapi/disks |
| BGOS-1110 | Опциональные поля `CopyRate` и `Schedule` в структуры запроса `ReplicateRequest` и `ReplicationStartRequest` в cloudbroker/disks |
| BGOS-1110 | Опциональное поле `Planned` в структуру запроса `ReplicationReverseRequest` в cloudbroker/disks |
| BGOS-1110 | Опциональные поля `CopyRate` и `Schedule` в структуры запроса `ReplicateRequest` и `ReplicationStartRequest` в cloudapi/disks |
| BGOS-1110 | Опциональное поле `Planned` в структуру запроса `ReplicationReverseRequest` в cloudapi/disks |
| BGOS-1113 | Опциональное поле `KeepCurrentIOTune` в структуру запроса `ChangeDiskStoragePolicyRequest` в cloudbroker/disks |
| BGOS-1113 | Опциональное поле `KeepCurrentIOTune` в структуру запроса `ChangeDiskStoragePolicyRequest` в cloudapi/disks |
| BGOS-1114 | Опциональные поля `TotalBytesSecMaxLength`, `ReadBytesSecMaxLength`, `WriteBytesSecMaxLength`, `TotalIOPSSecMaxLength`, `ReadIOPSSecMaxLength` и `WriteIOPSSecMaxLength` в структуру запроса `LimitIORequest` в cloudbroker/disks |
| BGOS-1114 | Опциональные поля `TotalBytesSecMaxLength`, `ReadBytesSecMaxLength`, `WriteBytesSecMaxLength`, `TotalIOPSSecMaxLength`, `ReadIOPSSecMaxLength` и `WriteIOPSSecMaxLength` в структуру запроса `LimitIORequest` в cloudapi/disks |
| BGOS-1127 | Вычисляемое поле `DRSPortSeed` в структуры ответа `ItemZone` и `RecordZone` в cloudbroker/zone |
#### dpdknet
| Идентификатор задачи | Описание |
| --- | --- |
| BGOS-1116 | Опциональные поля `AccountAccess` и `RGAccess` в структуру запроса `ListRequest` в cloudapi/dpdknet |
#### pcidevice
| Идентификатор задачи | Описание |
| --- | --- |
| BGOS-1115 | Опциональное поле `NodeID` в структуру запроса `ListRequest` в cloudbroker/pcidevice |
| BGOS-1115 | Опциональное поле `NodeID` в структуру запроса `ListRequest` в cloudapi/pcidevice |
#### SDN defsecpolicies
| Идентификатор задачи | Описание |
| --- | --- |
| BGOS-1103 | Вычисляемое поле `AccessGroupName` в структуру ответа `SecurityPolicy` в sdn/defsecpolicies |
| BGOS-1103 | Вычисляемые поля `AppliedNetObjectGroups`, `DestinationNetObjectGroups`, `LoggingProfile`, `LoggingProfileID`, `SecurityRuleConditionGroups`, `SecurityRuleConditions`, `SourceNetObjectGroups` и `Type` в структуру ответа `SecurityRule` в sdn/defsecpolicies |
| BGOS-1103 | Вычисляемые поля `EthType`, `IPProto`, `TCPSrcPorts` и `UDPSrcPorts` в структуру ответа `FilterParams` в sdn/defsecpolicies |
| BGOS-1103 | Структуры ответа `AppliedNetObjectGroup`, `NetObjectGroup`, `LoggingProfile`, `SecurityRuleConditionGroup` и `SecurityRuleCondition` в sdn/defsecpolicies |
#### SDN extnet
| Идентификатор задачи | Описание |
| --- | --- |
| BGOS-1105 | Вычисляемые поля `OperationStatus` и `HypervisorStatus` в структуру ответа `Status` в sdn/extnet |
| BGOS-1105 | Вычисляемое поле `OperationStatus` в структуру ответа `HypervisorStatus` в sdn/extnet |
| BGOS-1105 | Вычисляемые поля `ExternalNetworkID`, `ID` и `VersionID` в структуру ответа `ExternalNetworkPort` в sdn/extnet |
| BGOS-1105 | Вычисляемые поля `CreatedBy` и `UpdatedBy` в структуру ответа `FloatingIP` в sdn/extnet |
| BGOS-1105 | Вычисляемые поля `ExcludeFirewall` и `Labels` в структуру ответа `LogicalPort` в sdn/extnet |
| BGOS-1105 | Вычисляемые поля `L2ConnectionPort` и `Type` в структуру ответа `Segment` в sdn/extnet |
| BGOS-1105 | Обязательное поле `OperationStatus` в структуру запроса `StatusRequest` в sdn/extnet |
| BGOS-1105 | Обязательное поле `OperationStatus` в структуру запроса `HypervisorStatusRequest` в sdn/extnet |
| BGOS-1105 | Опциональные поля `CreatedBy` и `UpdatedBy` в структуру запроса `FloatingIPRequest` в sdn/extnet |
| BGOS-1105 | Обязательные поля `DisplayName` и `ExcludeFirewall` в структуру запроса `LogicalPortRequest` в sdn/extnet |
| BGOS-1105 | Опциональное поле `Labels` в структуру запроса `LogicalPortRequest` в sdn/extnet |
| BGOS-1105 | Обязательные поля `IPv4Address` и `IPv6Address` в структуру запроса `RouterPortRequest` в sdn/extnet |
| BGOS-1105 | Обязательное поле `Type` в структуру запроса `SegmentRequest` в sdn/extnet |
| BGOS-1105 | Опциональное поле `L2ConnectionPort` в структуру запроса `SegmentRequest` в sdn/extnet |
#### SDN routers
| Идентификатор задачи | Описание |
| --- | --- |
| BGOS-1106 | Вычисляемое поле `OperationStatus` в структуру ответа `Status` в sdn/routers |
| BGOS-1106 | Вычисляемое поле `OperationStatus` в структуру ответа `Status` в sdn/routers/gwport |
| BGOS-1106 | Вычисляемое поле `OperationStatus` в структуру ответа `HypervisorStatus` в sdn/routers |
| BGOS-1106 | Вычисляемое поле `OperationStatus` в структуру ответа `HypervisorStatus` в sdn/routers/gwport |
| BGOS-1106 | Вычисляемые поля `ExternalNetworkID`, `ID` и `VersionID` в структуру ответа `ExternalNetworkPort` в sdn/routers |
| BGOS-1106 | Вычисляемые поля `ExternalNetworkID`, `ID` и `VersionID` в структуру ответа `ExternalNetworkPort` в sdn/routers/gwport |
| BGOS-1106 | Вычисляемые поля `CreatedBy` и `UpdatedBy` в структуру ответа `FloatingIP` в sdn/routers |
| BGOS-1106 | Вычисляемые поля `CreatedBy` и `UpdatedBy` в структуру ответа `FloatingIP` в sdn/routers/gwport |
| BGOS-1106 | Вычисляемые поля `ExcludeFirewall` и `Labels` в структуру ответа `LogicalPort` в sdn/routers |
| BGOS-1106 | Вычисляемые поля `ExcludeFirewall` и `Labels` в структуру ответа `LogicalPort` в sdn/routers/gwport |
| BGOS-1106 | Вычисляемые поля `L2ConnectionPort` и `Type` в структуру ответа `Segment` в sdn/routers |
| BGOS-1106 | Вычисляемые поля `L2ConnectionPort` и `Type` в структуру ответа `Segment` в sdn/routers/gwport |
| BGOS-1106 | Структуры ответа `ExcludeFirewall`, `Labels`, `L2ConnectionPort` и `L2ExternalNetwork` в sdn/routers |
| BGOS-1106 | Структуры ответа `ExcludeFirewall`, `Labels`, `L2ConnectionPort`, `L2ExternalNetwork` и `Router` в sdn/routers/gwport |
| BGOS-1106 | Опциональное поле `OperationStatus` в структуру запроса `ListRequest` в sdn/routers |
#### SDN secpolicies
| Идентификатор задачи | Описание |
| --- | --- |
| BGOS-1104 | Вычисляемые поля `Type`, `EndDateTime`, `LockedAt`, `ScheduleCron` и `StartDateTime` в структуру ответа `SecurityPolicySummary` в sdn/secpolicies |
| BGOS-1104 | Структура ответа `AppliedNetObjectGroup` в sdn/secpolicies |
| BGOS-1104 | Вычисляемые поля `OperationStatus` и `HypervisorStatus` в структуру ответа `Status` в sdn/secpolicies |
| BGOS-1104 | Опциональное поле `SecurityRulesForCreate` в структуру запроса `CreateRequest` в sdn/secpolicies |
| BGOS-1104 | Структуры запроса `AppliedToNetObjectGroup`, `SecurityRuleForCreate`, `RuleNetObjectGroup` и `RuleFilter` в sdn/secpolicies |
| BGOS-1104 | Опциональные поля `OperationStatus` и `Type` в структуру запроса `ListRequest` в sdn/secpolicies |
| BGOS-1104 | Обязательное поле `AccessGroupID` в структуру запроса `UpdateRequest` в sdn/secpolicies |
#### vgpu
| Идентификатор задачи | Описание |
| --- | --- |
| BGOS-1066 | Обязательное поле `Name` в структуру запроса `CreateRequest` в cloudbroker/vgpu |
| BGOS-1066 | Опциональное поле `Name` в структуру запроса `ListRequest` в cloudbroker/vgpu |
| BGOS-1066 | Вычисляемые поля `Name` и `NodeID` в структуру ответа `ItemVGPU` в cloudbroker/vgpu |
| BGOS-1066 | Опциональное поле `Name` в структуру запроса `ListRequest` в cloudapi/vgpu |
| BGOS-1066 | Вычисляемые поля `Name` и `NodeID` в структуру ответа `ItemVGPU` в cloudapi/vgpu |
| BGOS-1066 | Структура запроса `EditRequest` и метод `Edit` в cloudbroker/vgpu |
| BGOS-1066 | Методы `CreateAsync`, `EditAsync` и `DestroyAsync` в cloudbroker/vgpu |
#### user
| Идентификатор задачи | Описание |
| --- | --- |
| BGOS-1093 | Опциональное поле `APIAccessID` в структуру запроса `ListRequest` в cloudbroker/user |
### Изменено
#### compute
| Идентификатор задачи | Описание |
| --- | --- |
| BGOS-1120 | Поле `Async` с обязательного на опциональное в структуре запроса `MigrateStorageRequest` в cloudbroker/compute |
| BGOS-1120 | Тэги `url` и `json` поля `AsyncMode` с `asyncMode` на `async_mode` в структуре запроса `asyncWrapperSnapshotEvictDiskRequest` в cloudbroker/compute |
| BGOS-1126 | Тип вычисляемого поля `UpdatedAt` с `uint64` на `float64` в структуре ответа `Observation` в cloudbroker/compute |
| BGOS-1126 | Тип вычисляемых полей `SampledAt`, `Percent` и `BytesPerSecond` с `uint64` на `float64` в структуре ответа `Memory` в cloudbroker/compute |
| BGOS-1126 | Тип вычисляемых полей `SampledAt`, `Percent` и `BytesPerSecond` с `uint64` на `float64` в структуре ответа `ProgressDisks` в cloudbroker/compute |
| BGOS-1126 | Тип вычисляемых полей `SampledAt`, `Percent` и `BytesPerSecond` с `uint64` на `float64` в структуре ответа `SystemDisk` в cloudbroker/compute |
| BGOS-1126 | Тип опционального поля `Storage` со `Storage` на `*Storage` в структуре запроса `MigrateV2Request` в cloudbroker/compute |
| BGOS-1126 | Тип поля `Targets` с опционального на обязательный в структуре запроса `Storage` в cloudbroker/compute |
| BGOS-1126 | Тэги `url` и `json` поля `Targets` с `targets` на `targets` в структуре запроса `Storage` в cloudbroker/compute |
#### SDN defsecpolicies
#### disks
| Идентификатор задачи | Описание |
| --- | --- |
| BGOS-1103 | JSON-тэг вычисляемого поля `Filter` с `filter` на `filters` и его тип с `Filter` на `[]FilterParams` в структуре ответа `SecurityRule` в sdn/defsecpolicies |
| BGOS-1128 | Тэги `url` и `json` поля `KeepCurrentIOTune` с `keep_current_iot` на `keep_current_iotune` в структуре запроса `ChangeDiskStoragePolicyRequest` в cloudbroker/disks |
| BGOS-1128 | Тэги `url` и `json` поля `KeepCurrentIOTune` с `keep_current_iot` на `keep_current_iotune` в структуре запроса `ChangeDiskStoragePolicyRequest` в cloudapi/disks |
#### SDN extnet
#### client sdk
| Идентификатор задачи | Описание |
| --- | --- |
| BGOS-1105 | Тип опционального поля `VLANTag` со `string` на `uint64` в структуре запроса `CreateRequest` в sdn/extnet |
| BGOS-1105 | Тип опционального поля `VLANTag` со `string` на `uint64` в структуре запроса `ListRequest` в sdn/extnet |
| BGOS-1105 | Тип опционального поля `VLANTag` со `string` на `uint64` в структуре запроса `UpdateRequest` в sdn/extnet |
| BGOS-1105 | Допустимый диапазон опционального поля `VLANTag` с 1–4095 на 1–4094 в структуре запроса `CreateRequest` в sdn/extnet |
| BGOS-1105 | Допустимый диапазон опционального поля `VLANTag` с 1–4095 на 1–4094 в структуре запроса `UpdateRequest` в sdn/extnet |
| BGOS-1105 | Проверка диапазона 1–4094 для опционального поля `VLANTag` в структуре запроса `ListRequest` в sdn/extnet |
| BGOS-1105 | Тип вычисляемого поля `ExternalNetworkPort` со `string` на `*ExternalNetworkPort` в структуре ответа `FloatingIP` в sdn/extnet |
| BGOS-1105 | Тип вычисляемого поля `ExternalNetworkPort` с `interface{}` на `*ExternalNetworkPort` в структуре ответа `GatewayPort` в sdn/extnet |
| BGOS-1105 | Тип обязательного поля `ExternalNetworkPort` со `string` на `*ExternalNetworkPortRequest` в структуре запроса `FloatingIPRequest` в sdn/extnet |
| BGOS-1105 | Тип обязательного поля `ExternalNetworkPort` с `interface{}` на `*ExternalNetworkPortRequest` в структуре запроса `GatewayPortRequest` в sdn/extnet |
| BGOS-1105 | Тип полей `AccessGroupName`, `IPv4`, `IPv6`, `IPv6Config`, `RouterGatewayPort` и `FloatingIP` с опционального на обязательный в структуре запроса `ExternalNetworkPortRequest` в sdn/extnet |
| BGOS-1105 | Тип поля `LogicalPort` с опционального на обязательный в структуре запроса `FloatingIPRequest` в sdn/extnet |
| BGOS-1105 | Тип поля `HypervisorDisplayName` с опционального на обязательный в структуре запроса `LogicalPortRequest` в sdn/extnet |
| BGOS-1105 | Тип полей `LiveMigrationTargetHV`, `Status`, `Bindings` и `UpdatedAt` с обязательного на опциональный в структуре запроса `LogicalPortRequest` в sdn/extnet |
| BGOS-1105 | Тип полей `SegmentDisplayName`, `SegmentID` и `LogicalPortAddresses` с обязательного на опциональный в структуре запроса `PortBindingsRequest` в sdn/extnet |
| BGOS-1105 | Тип полей `MAC` и `AssignedAt` с опционального на обязательный в структуре запроса `LogicalPortAddressRequest` в sdn/extnet |
| BGOS-1105 | Тип поля `IsPrimary` с обязательного на опциональный в структуре запроса `LogicalPortAddressRequest` в sdn/extnet |
| BGOS-1105 | Тип полей `AccessGroupID`, `AccessGroupName`, `CreatedAt`, `Description`, `Enabled`, `GatewayPorts`, `Policies`, `Ports`, `Status`, `UpdatedAt` и `VersionID` с опционального на обязательный в структуре запроса `RouterRequest` в sdn/extnet |
| BGOS-1105 | Тип полей `ExternalL4PortMax`, `ExternalL4PortMin`, `ID` и `Status` с опционального на обязательный в структуре запроса `GatewayPortRequest` в sdn/extnet |
| BGOS-1105 | Тип полей `Enabled` и `ID` с опционального на обязательный в структуре запроса `RouterPolicyRequest` в sdn/extnet |
| BGOS-1105 | Тип полей `ID` и `Status` с опционального на обязательный в структуре запроса `RouterPortRequest` в sdn/extnet |
| BGOS-1105 | Тип полей `Enabled` и `ID` с опционального на обязательный в структуре запроса `SegmentRequest` в sdn/extnet |
| BGOS-1105 | Тип полей `LeaseTime` и `ServerMAC` с обязательного на опциональный в структуре запроса `DHCPv6ConfigRequest` в sdn/extnet |
| BGOS-1105 | Тип поля `ID` с опционального на обязательный в структуре запроса `EntityInfoRequest` в sdn/extnet |
#### SDN routers
| Идентификатор задачи | Описание |
| --- | --- |
| BGOS-1106 | Тип вычисляемого поля `ExternalNetworkPort` со `string` на `*ExternalNetworkPort` в структуре ответа `FloatingIP` в sdn/routers |
| BGOS-1106 | Тип вычисляемого поля `ExternalNetworkPort` со `string` на `*ExternalNetworkPort` в структуре ответа `FloatingIP` в sdn/routers/gwport |
| BGOS-1106 | Тип вычисляемого поля `Router` со `string` на `*RoutersModel` в структуре ответа `FloatingIP` в sdn/routers |
| BGOS-1106 | Тип вычисляемого поля `Router` со `string` на `*Router` в структуре ответа `FloatingIP` в sdn/routers/gwport |
#### SDN secpolicies
| Идентификатор задачи | Описание |
| --- | --- |
| BGOS-1104 | Вычисляемое поле `AppliedToNetObjectGroupID` переименовано в `AppliedNetObjectGroups` в структуре ответа `SecurityPolicySummary` в sdn/secpolicies |
| BGOS-1104 | Тип вычисляемого поля `AppliedNetObjectGroups` со `string` на `[]AppliedNetObjectGroup` в структуре ответа `SecurityPolicySummary` в sdn/secpolicies |
| BGOS-1104 | JSON-тэг вычисляемого поля `AppliedNetObjectGroups` с `applied_to_net_object_group_id` на `applied_net_object_groups` в структуре ответа `SecurityPolicySummary` в sdn/secpolicies |
| BGOS-1104 | Вычисляемое поле `Status` переименовано в `OperationStatus` в структуре ответа `HypervisorStatus` в sdn/secpolicies |
| BGOS-1104 | JSON-тэг вычисляемого поля `OperationStatus` с `status` на `operation_status` в структуре ответа `HypervisorStatus` в sdn/secpolicies |
| BGOS-1104 | Тип поля `AppliedToNetObjectGroupID` со `string` на `[]AppliedToNetObjectGroup` в структуре запроса `CreateRequest` в sdn/secpolicies |
| BGOS-1104 | Тэги `url` и `json` поля `AppliedToNetObjectGroupID` с `applied_to_net_object_group_id` на `applied_to_net_object_group_ids` в структуре запроса `CreateRequest` в sdn/secpolicies |
| BGOS-1104 | Тип поля `AppliedToNetObjectGroupID` с обязательного на опциональный в структуре запроса `CreateRequest` в sdn/secpolicies |
| BGOS-1104 | Тип опционального поля `AppliedToNetObjectGroupID` со `string` на `[]string` в структуре запроса `ListRequest` в sdn/secpolicies |
| BGOS-1104 | Тэги `url` и `json` опционального поля `AppliedToNetObjectGroupID` с `applied_to_net_object_group_id` на `applied_to_net_object_group_ids` в структуре запроса `ListRequest` в sdn/secpolicies |
| BGOS-1104 | Поле `AppliedToNetObjectGroupID` переименовано в `AppliedNetObjectGroups` в структуре запроса `UpdateRequest` в sdn/secpolicies |
| BGOS-1104 | Тип поля `AppliedNetObjectGroups` со `string` на `[]AppliedToNetObjectGroup` в структуре запроса `UpdateRequest` в sdn/secpolicies |
| BGOS-1104 | Тэги `url` и `json` поля `AppliedNetObjectGroups` с `applied_to_net_object_group_id` на `applied_net_object_groups` в структуре запроса `UpdateRequest` в sdn/secpolicies |
| BGOS-1104 | Тип поля `AppliedNetObjectGroups` с обязательного на опциональный в структуре запроса `UpdateRequest` в sdn/secpolicies |
| BGOS-1104 | Тип полей `Description` и `DisplayName` с опционального на обязательный в структуре запроса `CreateRequest` в sdn/secpolicies |
| BGOS-1104 | Тип полей `Description` и `DisplayName` с опционального на обязательный в структуре запроса `UpdateRequest` в sdn/secpolicies |
#### sep
| Идентификатор задачи | Описание |
| --- | --- |
| BGOS-1121 | Тэги `url` и `json` поля `AsyncMode` с `asyncMode` на `async_mode` в структуре запроса `wrapperAddPoolRequest` в cloudbroker/sep |
#### vins
| Идентификатор задачи | Описание |
| --- | --- |
| BGOS-1119 | Тэги `url` и `json` поля `AsyncMode` с `asyncMode` на `async_mode` в структурах запроса `asyncWrapperCreateInAccountRequest`, `asyncWrapperEnableRequest`, `asyncWrapperCreateInRgRequest`, `asyncWrapperVNFDevRedeployRequest` и `asyncWrapperVNFDevRestartRequest` в cloudapi/vins |
| BGOS-1119 | Тэги `url` и `json` `AsyncMode` с `asyncMode` на `async_mode` в структурах запроса `asyncWrapperCreateInAccountRequest`, `asyncWrapperCreateInRgRequest`, `asyncWrapperEnableRequest`, `asyncWrapperVNFDevRedeployRequest`, `asyncWrapperVNFDevRestartRequest` и `asyncWrapperVNFDevStartRequest` в cloudbroker/vins |
| BGOS-1134 | При получении от сервера ответа с HTTP-кодом ошибки клиенты `DecortClient`, `LegacyDecortClient` и `BVSDecortClient` теперь возвращают ошибку типа `HTTPError` с полями `StatusCode` и `Body`. Для проверки статусов добавлены функции `IsNotFound` и `HasStatusCode` |
### Исправлено
#### SDN secpolicies
#### client sdk
| Идентификатор задачи | Описание |
| --- | --- |
| BGOS-1104 | URL метода `Get` с `/sdn/security_policies/get` на `/sdn/security_policy/get` в sdn/secpolicies |
| BGOS-1104 | Тип поля `InsertUp` с обязательного на опциональный в структуре запроса `MoveRequest` в sdn/secpolicies |
### Удалено
#### SDN defsecpolicies
| Идентификатор задачи | Описание |
| --- | --- |
| BGOS-1103 | Вычисляемые поля `Description`, `LockedAt` и `Status` из структуры ответа `SecurityPolicy` в sdn/defsecpolicies |
| BGOS-1103 | Вычисляемые поля `Description`, `DestinationNetObject`, `LogName`, `LogSeverity`, `SecurityPolicyID` и `SourceNetObject` из структуры ответа `SecurityRule` в sdn/defsecpolicies |
| BGOS-1103 | Вычисляемое поле `DHCP` из структуры ответа `FilterParams` в sdn/defsecpolicies |
| BGOS-1103 | Структуры ответа `Filter`, `NetObject`, `Status` и `HypervisorStatus` в sdn/defsecpolicies |
#### SDN extnet
| Идентификатор задачи | Описание |
| --- | --- |
| BGOS-1105 | Вычисляемое поле `Common` из структуры ответа `Status` в sdn/extnet |
| BGOS-1105 | Вычисляемое поле `Status` из структуры ответа `HypervisorStatus` в sdn/extnet |
| BGOS-1105 | Вычисляемое поле `IsExcludedFromFirewall` из структуры ответа `PortBindings` в sdn/extnet |
| BGOS-1105 | Обязательное поле `Common` из структуры запроса `StatusRequest` в sdn/extnet |
| BGOS-1105 | Обязательное поле `Status` из структуры запроса `HypervisorStatusRequest` в sdn/extnet |
| BGOS-1105 | Обязательное поле `RouterDisplayName` из структуры запроса `LogicalPortRequest` в sdn/extnet |
| BGOS-1105 | Обязательное поле `IsExcludedFromFirewall` из структуры запроса `PortBindingsRequest` в sdn/extnet |
| BGOS-1105 | Обязательные поля `NextIPv4Address` и `NextIPv6Address` из структуры запроса `RouterPortRequest` в sdn/extnet |
#### SDN routers
| Идентификатор задачи | Описание |
| --- | --- |
| BGOS-1106 | Вычисляемое поле `Common` из структуры ответа `Status` в sdn/routers |
| BGOS-1106 | Вычисляемое поле `Common` из структуры ответа `Status` в sdn/routers/gwport |
| BGOS-1106 | Вычисляемое поле `Status` из структуры ответа `HypervisorStatus` в sdn/routers |
| BGOS-1106 | Вычисляемое поле `Status` из структуры ответа `HypervisorStatus` в sdn/routers/gwport |
| BGOS-1106 | Вычисляемое поле `IsExcludedFromFirewall` из структуры ответа `Bindings` в sdn/routers |
| BGOS-1106 | Вычисляемое поле `IsExcludedFromFirewall` из структуры ответа `Bindings` в sdn/routers/gwport |
#### SDN secpolicies
| Идентификатор задачи | Описание |
| --- | --- |
| BGOS-1104 | Вычисляемое поле `SecurityRules` из структуры ответа `SecurityPolicySummary` в sdn/secpolicies |
| BGOS-1104 | Структуры ответа `SecurityRule` и `Filter` в sdn/secpolicies |
| BGOS-1104 | Вычисляемое поле `Common` из структуры ответа `Status` в sdn/secpolicies |
| BGOS-1104 | Опциональное поле `InsertUp` из структуры запроса `UpdateRequest` в sdn/secpolicies |
| BGOS-1135 | Исправлена ошибка в сообщении об ошибке при отсутствии времени истечения токена в клиенте |

View File

@@ -148,6 +148,7 @@ go get -u repository.basistech.ru/BASIS/decort-golang-sdk
- `Audit` - получение информации о событиях системы;
- `APIAccess` - управление доступом к API и его объектам;
- `Backup` - управление резервным копированием;
- `BasisMPM` - управление в случае нехватки памяти;
- `BService` - управление группами виртуальных машин (computes);
- `Compute` - управление виртуальными машинами (индивидуально);
- `Disks` - управление виртуальными дисками;
@@ -361,6 +362,7 @@ func main() {
- `pkg/cloudbroker/audit` - для `Audit`
- `pkg/cloudbroker/apiaccess` - для `APIAccess`
- `pkg/cloudbroker/backup` - для `Backup`
- `pkg/cloudbroker/basismpm` - для `BasisMPM`
- `pkg/cloudbroker/bservice` - для `Basic Service`
- `pkg/cloudbroker/compute` - для `Compute`
- `pkg/cloudbroker/disks` - для `Disks`

View File

@@ -210,7 +210,7 @@ func (dc *DecortClient) getToken(ctx context.Context) error {
}
if resp.StatusCode != 200 {
return fmt.Errorf("cannot get token: %s", tokenBytes)
return newHTTPError("cannot get token", resp.StatusCode, tokenBytes)
}
// save token in config
@@ -297,8 +297,7 @@ func (dc *DecortClient) do(req *http.Request, ctype string) ([]byte, error) {
}
// handle errors with status code other than 200
err = fmt.Errorf("%s", respBytes)
return nil, fmt.Errorf("could not execute request: %w", err)
return nil, newHTTPError("could not execute request", resp.StatusCode, respBytes)
}
// isConnectionError checks if given error falls within specific and associated connection errors
@@ -444,7 +443,7 @@ func getTokenExp(token string) (time.Time, error) {
exp, ok := claims["exp"]
if !ok {
return time.Time{}, fmt.Errorf("exp time bot found")
return time.Time{}, fmt.Errorf("exp time not found")
}
expTime := time.Unix(int64(exp.(float64)), 0)

View File

@@ -5,7 +5,6 @@ import (
"context"
"crypto/tls"
"encoding/json"
"errors"
"fmt"
"io"
"net/http"
@@ -127,7 +126,7 @@ func (bdc *BVSDecortClient) DecortApiCall(ctx context.Context, method, url strin
}
// get token and retry in case of access denied
if err.Error() == "access is denied" {
if HasStatusCode(err, http.StatusUnauthorized) {
_, err = bdc.GetToken(ctx)
if err != nil {
return nil, err
@@ -193,7 +192,7 @@ func (bdc *BVSDecortClient) DecortApiCallCtype(ctx context.Context, method, url,
}
// get token and retry in case of access denied
if err.Error() == "access is denied" {
if HasStatusCode(err, http.StatusUnauthorized) {
_, err = bdc.GetToken(ctx)
if err != nil {
return nil, err
@@ -243,7 +242,7 @@ func (bdc *BVSDecortClient) DecortApiCallMP(ctx context.Context, method, url str
}
// get token and retry in case of access denied
if err.Error() == "access is denied" {
if HasStatusCode(err, http.StatusUnauthorized) {
_, err = bdc.GetToken(ctx)
if err != nil {
return nil, err
@@ -287,7 +286,7 @@ func (bdc *BVSDecortClient) GetToken(ctx context.Context) (config.Token, error)
}
if resp.StatusCode != 200 {
return config.Token{}, fmt.Errorf("cannot get token: %s", tokenBytes)
return config.Token{}, newHTTPError("cannot get token", resp.StatusCode, tokenBytes)
}
// save token in config
@@ -346,7 +345,7 @@ func (bdc *BVSDecortClient) RefreshToken(ctx context.Context) (config.Token, err
}
if resp.StatusCode != 200 {
return config.Token{}, fmt.Errorf("cannot refresh token: %s", tokenBytes)
return config.Token{}, newHTTPError("cannot refresh token", resp.StatusCode, tokenBytes)
}
// save token in config
@@ -452,17 +451,12 @@ func (bdc *BVSDecortClient) do(req *http.Request, ctype string) ([]byte, error)
return nil, err
}
// handle access denied and successful request
if resp.StatusCode == 401 {
return respBytes, errors.New("access is denied")
}
if resp.StatusCode == 200 {
return respBytes, nil
}
// handle errors with other status codes
err = fmt.Errorf("%s", respBytes)
return nil, fmt.Errorf("could not execute request: %w", err)
// handle errors with status code other than 200 (401 triggers token refresh in callers)
return nil, newHTTPError("could not execute request", resp.StatusCode, respBytes)
}
func trimBVSConfig(cfg *config.BVSConfig) config.BVSConfig {

32
errors.go Normal file
View File

@@ -0,0 +1,32 @@
package decortsdk
import (
"errors"
"fmt"
"net/http"
)
// HTTPError is returned when the API responds with a non-successful status code.
type HTTPError struct {
StatusCode int
Body []byte
}
func (e *HTTPError) Error() string {
return string(e.Body)
}
// IsNotFound reports whether err contains an HTTPError with status 404.
func IsNotFound(err error) bool {
return HasStatusCode(err, http.StatusNotFound)
}
// HasStatusCode reports whether err contains an HTTPError with the given status code.
func HasStatusCode(err error, code int) bool {
var httpErr *HTTPError
return errors.As(err, &httpErr) && httpErr.StatusCode == code
}
func newHTTPError(prefix string, statusCode int, body []byte) error {
return fmt.Errorf("%s: %w", prefix, &HTTPError{StatusCode: statusCode, Body: body})
}

View File

@@ -505,3 +505,65 @@ func migrateV2ModeValidator(fe validator.FieldLevel) bool {
fieldValue := fe.Field().String()
return IsInSlice(fieldValue, migrateV2ModeValues)
}
// pressureThresholdValidator checks if PressureThreshold is in range from 5 to 50
func pressureThresholdValidator(fe validator.FieldLevel) bool {
fieldValue := fe.Field().Uint()
return fieldValue >= uint64(pressureThresholdMin) && fieldValue <= uint64(pressureThresholdMax)
}
// deflateThresholdValidator checks if DeflateThreshold is in range from 10 to 70
func deflateThresholdValidator(fe validator.FieldLevel) bool {
fieldValue := fe.Field().Uint()
return fieldValue >= uint64(deflateThresholdMin) && fieldValue <= uint64(deflateThresholdMax)
}
func bufferPCTValidator(fe validator.FieldLevel) bool {
fieldValue := fe.Field().Uint()
return fieldValue >= uint64(bufferPCTMin) && fieldValue <= uint64(bufferPCTMax)
}
func guaranteedPCTValidator(fe validator.FieldLevel) bool {
fieldValue := fe.Field().Uint()
return fieldValue >= uint64(guaranteedPCTMin) && fieldValue <= uint64(guaranteedPCTMax)
}
func guaranteedABSMinValidator(fe validator.FieldLevel) bool {
fieldValue := fe.Field().Uint()
return fieldValue >= uint64(guaranteedABSMinMin) && fieldValue <= uint64(guaranteedABSMinMax)
}
func shrinkThresholdPCTValidator(fe validator.FieldLevel) bool {
fieldValue := fe.Field().Uint()
return fieldValue >= uint64(shrinkThresholdPCTMin) && fieldValue <= uint64(shrinkThresholdPCTMax)
}
func balloonMaxShrinkPCTValidator(fe validator.FieldLevel) bool {
fieldValue := fe.Field().Uint()
return fieldValue >= uint64(balloonMaxShrinkPCTMin) && fieldValue <= uint64(balloonMaxShrinkPCTMax)
}
func balloonMaxGrowPCTValidator(fe validator.FieldLevel) bool {
fieldValue := fe.Field().Uint()
return fieldValue >= uint64(balloonMaxGrowPCTMin) && fieldValue <= uint64(balloonMaxGrowPCTMax)
}
func vmChangeCooldownValidator(fe validator.FieldLevel) bool {
fieldValue := fe.Field().Uint()
return fieldValue >= uint64(vmChangeCooldownMin) && fieldValue <= uint64(vmChangeCooldownMax)
}
func emergencyReturnCooldownValidator(fe validator.FieldLevel) bool {
fieldValue := fe.Field().Uint()
return fieldValue >= uint64(emergencyReturnCooldownMin) && fieldValue <= uint64(emergencyReturnCooldownMax)
}
func majorFaultThresholdValidator(fe validator.FieldLevel) bool {
fieldValue := fe.Field().Uint()
return fieldValue >= uint64(majorFaultThresholdMin) && fieldValue <= uint64(majorFaultThresholdMax)
}
func logLevelValidator(fe validator.FieldLevel) bool {
fieldValue := fe.Field().String()
return IsInSlice(fieldValue, logLevelValues)
}

View File

@@ -338,5 +338,65 @@ func registerAllValidators(validate *validator.Validate) error {
err = validate.RegisterValidation("migrateV2Mode", migrateV2ModeValidator)
err = validate.RegisterValidation("pressureThreshold", pressureThresholdValidator)
if err != nil {
return err
}
err = validate.RegisterValidation("deflateThreshold", deflateThresholdValidator)
if err != nil {
return err
}
err = validate.RegisterValidation("bufferPCT", bufferPCTValidator)
if err != nil {
return err
}
err = validate.RegisterValidation("guaranteedPCT", guaranteedPCTValidator)
if err != nil {
return err
}
err = validate.RegisterValidation("guaranteedABSMin", guaranteedABSMinValidator)
if err != nil {
return err
}
err = validate.RegisterValidation("shrinkThresholdPCT", shrinkThresholdPCTValidator)
if err != nil {
return err
}
err = validate.RegisterValidation("balloonMaxShrinkPCT", balloonMaxShrinkPCTValidator)
if err != nil {
return err
}
err = validate.RegisterValidation("balloonMaxGrowPCT", balloonMaxGrowPCTValidator)
if err != nil {
return err
}
err = validate.RegisterValidation("vmChangeCooldown", vmChangeCooldownValidator)
if err != nil {
return err
}
err = validate.RegisterValidation("emergencyReturnCooldown", emergencyReturnCooldownValidator)
if err != nil {
return err
}
err = validate.RegisterValidation("majorFaultThreshold", majorFaultThresholdValidator)
if err != nil {
return err
}
err = validate.RegisterValidation("logLevel", logLevelValidator)
if err != nil {
return err
}
return nil
}

View File

@@ -86,6 +86,8 @@ var (
memoryBalloonModeValues = []string{"auto", "legacy", "none"}
migrateV2ModeValues = []string{"compute", "disks", "compute_and_disks"}
logLevelValues = []string{"DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"}
)
const (
@@ -94,4 +96,37 @@ const (
trunkTagsMin = 1
trunkTagsMax = 4095
pressureThresholdMin = 5
pressureThresholdMax = 50
deflateThresholdMin = 10
deflateThresholdMax = 70
bufferPCTMin = 5
bufferPCTMax = 50
guaranteedPCTMin = 10
guaranteedPCTMax = 50
guaranteedABSMinMin = 256
guaranteedABSMinMax = 4096
shrinkThresholdPCTMin = 30
shrinkThresholdPCTMax = 90
balloonMaxShrinkPCTMin = 5
balloonMaxShrinkPCTMax = 25
balloonMaxGrowPCTMin = 5
balloonMaxGrowPCTMax = 25
vmChangeCooldownMin = 30
vmChangeCooldownMax = 300
emergencyReturnCooldownMin = 60
emergencyReturnCooldownMax = 1800
majorFaultThresholdMin = 1
majorFaultThresholdMax = 10000
)

View File

@@ -210,7 +210,7 @@ func (ldc *LegacyDecortClient) getToken(ctx context.Context) error {
}
if resp.StatusCode != 200 {
return fmt.Errorf("cannot get token: %s", tokenBytes)
return newHTTPError("cannot get token", resp.StatusCode, tokenBytes)
}
// save token in config
@@ -291,8 +291,7 @@ func (ldc *LegacyDecortClient) do(req *http.Request, ctype string) ([]byte, erro
}
// handle errors with status code other than 200
err = fmt.Errorf("%s", respBytes)
return nil, fmt.Errorf("could not execute request: %w", err)
return nil, newHTTPError("could not execute request", resp.StatusCode, respBytes)
}
func trimLegacyConfig(cfg *config.LegacyConfig) config.LegacyConfig {

View File

@@ -26,6 +26,8 @@ type wrapperCreateTemplateRequest struct {
}
// CreateTemplate create template from compute instance
//
// Deprecated: will be removed in SDK v1.17
func (c Compute) CreateTemplate(ctx context.Context, req CreateTemplateRequest) (string, error) {
err := validators.ValidateRequest(req)
if err != nil {

View File

@@ -56,6 +56,8 @@ type wrapperCreateTemplateFromBlankRequest struct {
// CreateTemplateFromBlank creates template from boot disk of current compute in sync mode.
// It returns id of created compute and error.
//
// Deprecated: will be removed in SDK v1.17
func (c Compute) CreateTemplateFromBlank(ctx context.Context, req CreateTemplateFromBlankRequest) (uint64, error) {
err := validators.ValidateRequest(req)
if err != nil {
@@ -84,6 +86,8 @@ func (c Compute) CreateTemplateFromBlank(ctx context.Context, req CreateTemplate
// CreateTemplateFromBlankAsync creates template from boot disk of current compute in async mode.
// It returns guid of task and error.
//
// Deprecated: will be removed in SDK v1.17
func (c Compute) CreateTemplateFromBlankAsync(ctx context.Context, req CreateTemplateFromBlankRequest) (string, error) {
err := validators.ValidateRequest(req)
if err != nil {

View File

@@ -21,8 +21,8 @@ type ChangeDiskStoragePolicyRequest struct {
// Keep current disk I/O tune settings in the domain XML
// Required: false
// Default: false
KeepCurrentIOTune interface{} `url:"keep_current_iot,omitempty" json:"keep_current_iot,omitempty" validate:"omitempty,isBool"`
// Default: false
KeepCurrentIOTune interface{} `url:"keep_current_iotune,omitempty" json:"keep_current_iotune,omitempty" validate:"omitempty,isBool"`
}
type wrapperChangeDiskStoragePolicyRequest struct {

View File

@@ -55,6 +55,8 @@ type wrapperFromPlatformDiskRequest struct {
// FromPlatformDisk creates template from platform disk in sync mode.
// It returns id of created disk and error.
//
// Deprecated: will be removed in SDK v1.17
func (d Disks) FromPlatformDisk(ctx context.Context, req FromPlatformDiskRequest) (uint64, error) {
err := validators.ValidateRequest(req)
if err != nil {
@@ -83,6 +85,8 @@ func (d Disks) FromPlatformDisk(ctx context.Context, req FromPlatformDiskRequest
// FromPlatformDiskAsync creates template from platform disk in async mode.
// It returns guid of task and error.
//
// Deprecated: will be removed in SDK v1.17
func (d Disks) FromPlatformDiskAsync(ctx context.Context, req FromPlatformDiskRequest) (string, error) {
err := validators.ValidateRequest(req)
if err != nil {

View File

@@ -0,0 +1,139 @@
package image
import (
"context"
"encoding/json"
"net/http"
"strconv"
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
)
// CreateFromDiskRequest to create image from existing disk
type CreateFromDiskRequest struct {
// Name of the new image
// Required: true
Name string `url:"name" json:"name" validate:"required"`
// ID of the source disk to create image from
// Required: true
DiskID uint64 `url:"disk_id" json:"disk_id" validate:"required"`
// Boot type of the image (bios or uefi)
// Required: true
// Options:
// - bios
// - uefi
BootType string `url:"boot_type" json:"boot_type" validate:"required,imageBootType"`
// Type of the operating system
// Required: true
// Options:
// - linux
// - windows
// - unknown
ImageType string `url:"image_type" json:"image_type" validate:"required,imageType"`
// ID of the storage policy to apply
// Required: true
StoragePolicyID uint64 `url:"storage_policy_id" json:"storage_policy_id" validate:"required"`
// Network interface naming pattern for Linux machines. eth - onboard naming, ens - PCI slot naming.
// Required: false
// Default: ens
// Options:
// - eth
// - ens
NetworkInterfaceNaming string `url:"network_interface_naming,omitempty" json:"network_interface_naming,omitempty" validate:"omitempty,networkInterfaceNaming"`
// Whether the image supports hot resize (online resizing)
// Required: false
// Default: false
HotResize interface{} `url:"hot_resize,omitempty" json:"hot_resize,omitempty" validate:"omitempty,isBool"`
// Default username for VMs created from this image
// Required: false
UserName string `url:"user_name,omitempty" json:"user_name,omitempty"`
// Default password for the default user
// Required: false
Password string `url:"password,omitempty" json:"password,omitempty"`
// Account ID to grant exclusive access to the image
// Required: false
AccountID uint64 `url:"account_id,omitempty" json:"account_id,omitempty"`
// Target SEP ID where the image will be created. If not specified, the best SEP will be selected based on storage policy.
// Required: false
SEPID uint64 `url:"sep_id,omitempty" json:"sep_id,omitempty"`
// Target pool name in the SEP. If not specified, the best pool will be selected automatically.
// Required: false
PoolName string `url:"pool_name,omitempty" json:"pool_name,omitempty"`
// Whether the image is bootable
// Required: false
// Default: true
Bootable interface{} `url:"bootable,omitempty" json:"bootable,omitempty" validate:"omitempty,isBool"`
}
type wrapperCreateFromDiskRequest struct {
CreateFromDiskRequest
AsyncMode bool `url:"async_mode" json:"async_mode" validate:"omitempty,isBool"`
}
// CreateFromDisk creates image from existing disk
func (i Image) CreateFromDisk(ctx context.Context, req CreateFromDiskRequest) (uint64, error) {
err := validators.ValidateRequest(req)
if err != nil {
return 0, validators.ValidationErrors(validators.GetErrors(err))
}
url := "/cloudapi/image/create_from_disk"
aReq := wrapperCreateFromDiskRequest{
CreateFromDiskRequest: req,
AsyncMode: false,
}
res, err := i.client.DecortApiCall(ctx, http.MethodPost, url, aReq)
if err != nil {
return 0, err
}
result, err := strconv.ParseUint(string(res), 10, 64)
if err != nil {
return 0, err
}
return result, nil
}
// CreateFromDiskAsync creates image from existing disk in async mode
func (i Image) CreateFromDiskAsync(ctx context.Context, req CreateFromDiskRequest) (string, error) {
err := validators.ValidateRequest(req)
if err != nil {
return "", validators.ValidationErrors(validators.GetErrors(err))
}
url := "/cloudapi/image/create_from_disk"
aReq := wrapperCreateFromDiskRequest{
CreateFromDiskRequest: req,
AsyncMode: true,
}
res, err := i.client.DecortApiCall(ctx, http.MethodPost, url, aReq)
if err != nil {
return "", err
}
var resp string
err = json.Unmarshal(res, &resp)
if err != nil {
return "", err
}
return resp, nil
}

View File

@@ -168,6 +168,7 @@ type CloudBrokerEndpoints struct {
AuditCollector interface{} `json:"auditcollector,omitempty"`
Backup interface{} `json:"backup,omitempty"`
BackupCreator interface{} `json:"backupcreator,omitempty"`
BasisMPM interface{} `json:"basis_mpm,omitempty"`
BService interface{} `json:"bservice,omitempty"`
Compute interface{} `json:"compute,omitempty"`
Disks interface{} `json:"disks,omitempty"`

View File

@@ -0,0 +1,10 @@
package cloudbroker
import (
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/basismpm"
)
// Accessing the BasisMPM method group
func (cb *CloudBroker) BasisMPM() *basismpm.BasisMPM {
return basismpm.New(cb.client)
}

View File

@@ -0,0 +1,17 @@
package basismpm
import (
"repository.basistech.ru/BASIS/decort-golang-sdk/interfaces"
)
// Structure for creating request to Basis mpm
type BasisMPM struct {
client interfaces.Caller
}
// BasisMPM for Basis mpm endpoints
func New(client interfaces.Caller) *BasisMPM {
return &BasisMPM{
client: client,
}
}

View File

@@ -0,0 +1,36 @@
package basismpm
type MemInfo struct {
// Total amount of memory
MemTotal string `json:"MemTotal"`
// Amount of free memory
MemFree string `json:"MemFree"`
// Amount of available memory
MemAvailable string `json:"MemAvailable"`
// Amount of available memory (in percent)
MemAvailablePercent float64 `json:"MemAvailablePercent"`
}
// Basis MPM service status
type RecordBasisMPM struct {
// Whether the service is installed
ServiceInstalled bool `json:"service_installed"`
// Whether the config exists
ConfigExists bool `json:"config_exists"`
// Whether the service is active
ServiceActive bool `json:"service_active"`
// Service state
ServiceState string `json:"service_state"`
// Config
Config interface{} `json:"config"`
// Memory info
MemInfo MemInfo `json:"meminfo"`
}

View File

@@ -0,0 +1,114 @@
package basismpm
import (
"context"
"net/http"
"strconv"
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/constants"
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
)
// StartRequest to start basis_mpm service on a node
type StartRequest struct {
// Node ID
// Required: true
NodeID uint64 `url:"node_id" json:"node_id" validate:"required"`
// Memory pressure threshold (%)
// Required: false
// Default: 20
PressureThreshold uint64 `url:"pressure_threshold,omitempty" json:"pressure_threshold,omitempty" validate:"omitempty,pressureThreshold"`
// Deflate threshold (%)
// Required: false
// Default: 30
DeflateThreshold uint64 `url:"deflate_threshold,omitempty" json:"deflate_threshold,omitempty" validate:"omitempty,deflateThreshold"`
// Host reserved memory
// Required: false
// Default: "8GB+5%"
HostReserved string `url:"host_reserved,omitempty" json:"host_reserved,omitempty"`
// Buffer percentage (%)
// Required: false
// Default: 20
BufferPCT uint64 `url:"buffer_pct,omitempty" json:"buffer_pct,omitempty" validate:"omitempty,bufferPCT"`
// Guaranteed memory percentage (%)
// Required: false
// Default: 25
GuaranteedPCT uint64 `url:"guaranteed_pct,omitempty" json:"guaranteed_pct,omitempty" validate:"omitempty,guaranteedPCT"`
// Absolute minimum guaranteed memory (MB)
// Required: false
// Default: 512
GuaranteedABSMin uint64 `url:"guaranteed_abs_min,omitempty" json:"guaranteed_abs_min,omitempty" validate:"omitempty,guaranteedABSMin"`
// Shrink threshold percentage (%)
// Required: false
// Default: 50
ShrinkThresholdPCT uint64 `url:"shrink_threshold_pct,omitempty" json:"shrink_threshold_pct,omitempty" validate:"omitempty,shrinkThresholdPCT"`
// Max shrink percentage per cycle (%)
// Required: false
// Default: 10
BalloonMaxShrinkPCT uint64 `url:"balloon_max_shrink_pct,omitempty" json:"balloon_max_shrink_pct,omitempty" validate:"omitempty,balloonMaxShrinkPCT"`
// Max grow percentage per cycle (%)
// Required: false
// Default: 10
BalloonMaxGrowPCT uint64 `url:"balloon_max_grow_pct,omitempty" json:"balloon_max_grow_pct,omitempty" validate:"omitempty,balloonMaxGrowPCT"`
// VM change cooldown (seconds)
// Required: false
// Default: 60
VMChangeCooldown uint64 `url:"vm_change_cooldown,omitempty" json:"vm_change_cooldown,omitempty" validate:"omitempty,vmChangeCooldown"`
// Emergency return cooldown (seconds)
// Required: false
// Default: 300
EmergencyReturnCooldown uint64 `url:"emergency_return_cooldown,omitempty" json:"emergency_return_cooldown,omitempty"`
// Major fault increase per cycle that triggers emergency memory return
// Required: false
// Default: 100
MajorFaultThreshold uint64 `url:"major_fault_threshold,omitempty" json:"major_fault_threshold,omitempty" validate:"omitempty,majorFaultThreshold"`
// Daemon log level
// Required: false
// Default: INFO
// Options:
// - DEBUG
// - INFO
// - WARNING
// - ERROR
// - CRITICAL
LogLevel string `url:"log_level,omitempty" json:"log_level,omitempty" validate:"omitempty,logLevel"`
// Daemon log file path (empty for stdout only)
// Required: false
LogFile string `url:"log_file,omitempty" json:"log_file,omitempty"`
}
// Start starts basis_mpm service on a node
func (bm BasisMPM) Start(ctx context.Context, req StartRequest) (bool, error) {
err := validators.ValidateRequest(req)
if err != nil {
return false, validators.ValidationErrors(validators.GetErrors(err))
}
url := "/cloudbroker/basis_mpm/start"
res, err := bm.client.DecortApiCallCtype(ctx, http.MethodPost, url, constants.MIMEJSON, req)
if err != nil {
return false, err
}
result, err := strconv.ParseBool(string(res))
if err != nil {
return false, err
}
return result, nil
}

View File

@@ -0,0 +1,47 @@
package basismpm
import (
"context"
"encoding/json"
"net/http"
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/constants"
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
)
// StatusRequest to get basis_mpm service status on a node
type StatusRequest struct {
// Node ID
// Required: true
NodeID uint64 `url:"node_id" json:"node_id" validate:"required"`
}
// Status gets basis_mpm service status on a node
func (bm BasisMPM) Status(ctx context.Context, req StatusRequest) (*RecordBasisMPM, error) {
res, err := bm.StatusRaw(ctx, req)
if err != nil {
return nil, err
}
info := RecordBasisMPM{}
err = json.Unmarshal(res, &info)
if err != nil {
return nil, err
}
return &info, nil
}
// StatusRaw gets basis_mpm service status on a node as an array of bites
func (bm BasisMPM) StatusRaw(ctx context.Context, req StatusRequest) ([]byte, error) {
err := validators.ValidateRequest(req)
if err != nil {
return nil, validators.ValidationErrors(validators.GetErrors(err))
}
url := "/cloudbroker/basis_mpm/status"
res, err := bm.client.DecortApiCallCtype(ctx, http.MethodPost, url, constants.MIMEJSON, req)
return res, err
}

View File

@@ -0,0 +1,44 @@
package basismpm
import (
"context"
"net/http"
"strconv"
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/constants"
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
)
// StopRequest to stop basis_mpm service on a node
type StopRequest struct {
// Node ID
// Required: true
NodeID uint64 `url:"node_id" json:"node_id" validate:"required"`
// Restore VM memory before stopping
// Required: false
// Default: true
RestoreMemory interface{} `url:"restore_memory,omitempty" json:"restore_memory,omitempty" validate:"omitempty,isBool"`
}
// Stop stops basis_mpm service on a node
func (bm BasisMPM) Stop(ctx context.Context, req StopRequest) (bool, error) {
err := validators.ValidateRequest(req)
if err != nil {
return false, validators.ValidationErrors(validators.GetErrors(err))
}
url := "/cloudbroker/basis_mpm/stop"
res, err := bm.client.DecortApiCallCtype(ctx, http.MethodPost, url, constants.MIMEJSON, req)
if err != nil {
return false, err
}
result, err := strconv.ParseBool(string(res))
if err != nil {
return false, err
}
return result, nil
}

View File

@@ -0,0 +1,113 @@
package basismpm
import (
"context"
"net/http"
"strconv"
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/constants"
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
)
// UpdateRequest to update basis_mpm service configuration on a node
type UpdateRequest struct {
// Node ID
// Required: true
NodeID uint64 `url:"node_id" json:"node_id" validate:"required"`
// Memory pressure threshold (%)
// Required: false
// Default: 20
PressureThreshold uint64 `url:"pressure_threshold,omitempty" json:"pressure_threshold,omitempty" validate:"omitempty,pressureThreshold"`
// Deflate threshold (%)
// Required: false
// Default: 30
DeflateThreshold uint64 `url:"deflate_threshold,omitempty" json:"deflate_threshold,omitempty" validate:"omitempty,deflateThreshold"`
// Host reserved memory
// Required: false
// Default: "8GB+5%"
HostReserved string `url:"host_reserved,omitempty" json:"host_reserved,omitempty"`
// Buffer percentage (%)
// Required: false
// Default: 20
BufferPCT uint64 `url:"buffer_pct,omitempty" json:"buffer_pct,omitempty" validate:"omitempty,bufferPCT"`
// Guaranteed memory percentage (%)
// Required: false
// Default: 25
GuaranteedPCT uint64 `url:"guaranteed_pct,omitempty" json:"guaranteed_pct,omitempty" validate:"omitempty,guaranteedPCT"`
// Absolute minimum guaranteed memory (MB)
// Required: false
// Default: 512
GuaranteedABSMin uint64 `url:"guaranteed_abs_min,omitempty" json:"guaranteed_abs_min,omitempty" validate:"omitempty,guaranteedABSMin"`
// Shrink threshold percentage (%)
// Required: false
// Default: 50
ShrinkThresholdPCT uint64 `url:"shrink_threshold_pct,omitempty" json:"shrink_threshold_pct,omitempty" validate:"omitempty,shrinkThresholdPCT"`
// Max shrink percentage per cycle (%)
// Required: false
// Default: 10
BalloonMaxShrinkPCT uint64 `url:"balloon_max_shrink_pct,omitempty" json:"balloon_max_shrink_pct,omitempty" validate:"omitempty,balloonMaxShrinkPCT"`
// Max grow percentage per cycle (%)
// Required: false
// Default: 10
BalloonMaxGrowPCT uint64 `url:"balloon_max_grow_pct,omitempty" json:"balloon_max_grow_pct,omitempty" validate:"omitempty,balloonMaxGrowPCT"`
// VM change cooldown (seconds)
// Required: false
// Default: 60
VMChangeCooldown uint64 `url:"vm_change_cooldown,omitempty" json:"vm_change_cooldown,omitempty" validate:"omitempty,vmChangeCooldown"`
// Emergency return cooldown (seconds)
// Required: false
// Default: 300
EmergencyReturnCooldown uint64 `url:"emergency_return_cooldown,omitempty" json:"emergency_return_cooldown,omitempty" validate:"omitempty,emergencyReturnCooldown"`
// Major fault increase per cycle that triggers emergency memory return
// Required: false
// Default: 100
MajorFaultThreshold uint64 `url:"major_fault_threshold,omitempty" json:"major_fault_threshold,omitempty" validate:"omitempty,majorFaultThreshold"`
// Daemon log level
// Required: false
// Default: INFO
// Options:
// - DEBUG
// - INFO
// - WARNING
// - ERROR
// - CRITICAL
LogLevel string `url:"log_level,omitempty" json:"log_level,omitempty" validate:"omitempty,logLevel"`
// Daemon log file path (empty for stdout only)
// Required: false
LogFile string `url:"log_file,omitempty" json:"log_file,omitempty"`
}
func (bm BasisMPM) Update(ctx context.Context, req UpdateRequest) (bool, error) {
err := validators.ValidateRequest(req)
if err != nil {
return false, validators.ValidationErrors(validators.GetErrors(err))
}
url := "/cloudbroker/basis_mpm/update"
res, err := bm.client.DecortApiCallCtype(ctx, http.MethodPost, url, constants.MIMEJSON, req)
if err != nil {
return false, err
}
result, err := strconv.ParseBool(string(res))
if err != nil {
return false, err
}
return result, nil
}

View File

@@ -26,6 +26,8 @@ type wrapperCreateTemplateRequest struct {
}
// CreateTemplate create template from compute instance
//
// Deprecated: will be removed in SDK v1.17
func (c Compute) CreateTemplate(ctx context.Context, req CreateTemplateRequest) (string, error) {
err := validators.ValidateRequest(req)
if err != nil {
@@ -50,6 +52,8 @@ func (c Compute) CreateTemplate(ctx context.Context, req CreateTemplateRequest)
}
// CreateTemplateAsync create template from compute instance with AsyncMode
//
// Deprecated: will be removed in SDK v1.17
func (c Compute) CreateTemplateAsync(ctx context.Context, req CreateTemplateRequest) (string, error) {
err := validators.ValidateRequest(req)
if err != nil {

View File

@@ -60,6 +60,8 @@ type wrapperCreateTemplateFromBlankRequest struct {
// CreateTemplateFromBlank creates template from boot disk of current compute in sync mode.
// It returns id of created compute and error.
//
// Deprecated: will be removed in SDK v1.17
func (c Compute) CreateTemplateFromBlank(ctx context.Context, req CreateTemplateFromBlankRequest) (uint64, error) {
err := validators.ValidateRequest(req)
if err != nil {
@@ -88,6 +90,8 @@ func (c Compute) CreateTemplateFromBlank(ctx context.Context, req CreateTemplate
// CreateTemplateFromBlankAsync creates template from boot disk of current compute in async mode.
// It returns guid of task and error.
//
// Deprecated: will be removed in SDK v1.17
func (c Compute) CreateTemplateFromBlankAsync(ctx context.Context, req CreateTemplateFromBlankRequest) (string, error) {
err := validators.ValidateRequest(req)
if err != nil {

View File

@@ -23,7 +23,8 @@ type Target struct {
// Required: false
StoragePolicyID uint64 `url:"storage_policy_id,omitempty" json:"storage_policy_id,omitempty"`
// Disk IDs
// Disk IDs. May be omitted if Targets contains one element (all persistent disks are migrated).
// Required if Targets contains two or more elements; disk IDs must not overlap between targets.
// Required: false
DiskIDs []uint64 `url:"disk_ids,omitempty" json:"disk_ids,omitempty"`
}
@@ -31,8 +32,8 @@ type Target struct {
// Storage describes a destination for a disk
type Storage struct {
// Target for migration
// Required: false
Targets []Target `url:"targets,omitempty" json:"targets,omitempty"`
// Required: true
Targets []Target `url:"targets" json:"targets" validate:"required,min=1,dive"`
// Whether a separate source-disk cleanup job should be started after full success
// Required: false
@@ -55,7 +56,7 @@ type MigrateV2Request struct {
// Destination for a disk
// Required: false
Storage Storage `url:"storage,omitempty" json:"storage,omitempty"`
Storage *Storage `url:"storage,omitempty" json:"storage,omitempty"`
}
// MigrateV2 starts a migration of a compute or a disk

View File

@@ -18,6 +18,10 @@ type MigrateV2ResolveRequest struct {
// Take over cleanup
// Required: false
TakeOverCleanup interface{} `url:"take_over_cleanup,omitempty" json:"take_over_cleanup,omitempty" validate:"omitempty,isBool"`
// Take over resources
// Required: false
TakeOverResources interface{} `url:"take_over_resources,omitempty" json:"take_over_resources,omitempty" validate:"omitempty,isBool"`
}
// MigrateV2Resolve resolves a migration of a compute

View File

@@ -2315,7 +2315,7 @@ type Origin struct {
type Observation struct {
// Updated at
UpdatedAt uint64 `json:"updated_at"`
UpdatedAt float64 `json:"updated_at"`
// Agent job ID
AgentJobID string `json:"agent_job_id"`
@@ -2329,13 +2329,13 @@ type Observation struct {
type Memory struct {
// Sampled at
SampledAt uint64 `json:"sampled_at"`
SampledAt float64 `json:"sampled_at"`
// Percent
Percent uint64 `json:"percent"`
Percent float64 `json:"percent"`
// Bytes per second
BytesPerSecond uint64 `json:"bytes_per_second"`
BytesPerSecond float64 `json:"bytes_per_second"`
// Processed bytes
ProcessedBytes uint64 `json:"processed_bytes"`
@@ -2352,19 +2352,59 @@ type ProgressDisks struct {
TargetDevs []string `json:"target_devs"`
// Sampled at
SampledAt uint64 `json:"sampled_at"`
SampledAt float64 `json:"sampled_at"`
// Percent
Percent uint64 `json:"percent"`
Percent float64 `json:"percent"`
// Bytes per second
BytesPerSecond uint64 `json:"bytes_per_second"`
BytesPerSecond float64 `json:"bytes_per_second"`
// Processed bytes
ProcessedBytes uint64 `json:"processed_bytes"`
// Remaining bytes
RemainingBytes uint64 `json:"remaining_bytes"`
// Disks completed
DisksCompleted uint64 `json:"disks_completed"`
// Completed disks
CompletedDisks []CompletedDisk `json:"completed_disks"`
// Disks total
DisksTotal uint64 `json:"disks_total"`
// Current disk
CurrentDisk CurrentDisk `json:"current_disk"`
}
type CompletedDisk struct {
// Source disk ID
SourceDiskID uint64 `json:"source_disk_id"`
// Target disk ID
TargetDiskID uint64 `json:"target_disk_id"`
// Target dev
TargetDev string `json:"target_dev"`
}
type CurrentDisk struct {
// Source disk ID
SourceDiskID uint64 `json:"source_disk_id"`
// Target disk ID
TargetDiskID uint64 `json:"target_disk_id"`
// Target dev
TargetDev string `json:"target_dev"`
// Percent
Percent float64 `json:"percent"`
// Sampled at
SampledAt float64 `json:"sampled_at"`
}
type SystemDisk struct {
@@ -2372,13 +2412,13 @@ type SystemDisk struct {
TargetDev string `json:"target_dev"`
// Sampled at
SampledAt uint64 `json:"sampled_at"`
SampledAt float64 `json:"sampled_at"`
// Percent
Percent uint64 `json:"percent"`
Percent float64 `json:"percent"`
// Bytes per second
BytesPerSecond uint64 `json:"bytes_per_second"`
BytesPerSecond float64 `json:"bytes_per_second"`
// Processed bytes
ProcessedBytes uint64 `json:"processed_bytes"`
@@ -2448,12 +2488,18 @@ type Resolution struct {
// Take over cleanup
TakeOverCleanup bool `json:"take_over_cleanup"`
// Take over resources
TakeOverResources bool `json:"take_over_resources"`
// Previous status
PreviousStatus string `json:"previous_status"`
// Previous cleanup required
PreviousCleanupRequired bool `json:"previous_cleanup_required"`
// Previous reserves compute resources
PreviousReservesComputeResources bool `json:"previous_reserves_compute_resources"`
// Previous error
PreviousError string `json:"previous_error"`
}
@@ -2607,6 +2653,9 @@ type MigrateV2ResolveRecord struct {
// Cleanup required
CleanupRequired bool `json:"cleanup_required"`
// Message
Message string `json:"message"`
// Resolution
Resolution Resolution `json:"resolution"`
}

View File

@@ -21,8 +21,8 @@ type ChangeDiskStoragePolicyRequest struct {
// Keep current disk I/O tune settings in the domain XML
// Required: false
// Default: false
KeepCurrentIOTune interface{} `url:"keep_current_iot,omitempty" json:"keep_current_iot,omitempty" validate:"omitempty,isBool"`
// Default: false
KeepCurrentIOTune interface{} `url:"keep_current_iotune,omitempty" json:"keep_current_iotune,omitempty" validate:"omitempty,isBool"`
}
type wrapperChangeDiskStoragePolicyRequest struct {

View File

@@ -59,6 +59,8 @@ type wrapperFromPlatformDiskRequest struct {
// FromPlatformDisk creates template from platform disk in sync mode.
// It returns id of created disk and error.
//
// Deprecated: will be removed in SDK v1.17
func (d Disks) FromPlatformDisk(ctx context.Context, req FromPlatformDiskRequest) (uint64, error) {
err := validators.ValidateRequest(req)
if err != nil {
@@ -87,6 +89,8 @@ func (d Disks) FromPlatformDisk(ctx context.Context, req FromPlatformDiskRequest
// FromPlatformDiskAsync creates template from platform disk in async mode.
// It returns guid of task and error.
//
// Deprecated: will be removed in SDK v1.17
func (d Disks) FromPlatformDiskAsync(ctx context.Context, req FromPlatformDiskRequest) (string, error) {
err := validators.ValidateRequest(req)
if err != nil {

View File

@@ -0,0 +1,139 @@
package image
import (
"context"
"encoding/json"
"net/http"
"strconv"
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
)
// CreateFromDiskRequest to create image from existing disk
type CreateFromDiskRequest struct {
// Name of the new image
// Required: true
Name string `url:"name" json:"name" validate:"required"`
// ID of the source disk to create image from
// Required: true
DiskID uint64 `url:"disk_id" json:"disk_id" validate:"required"`
// Boot type of the image (bios or uefi)
// Required: true
// Options:
// - bios
// - uefi
BootType string `url:"boot_type" json:"boot_type" validate:"required,imageBootType"`
// Type of the operating system
// Required: true
// Options:
// - linux
// - windows
// - unknown
ImageType string `url:"image_type" json:"image_type" validate:"required,imageType"`
// ID of the storage policy to apply
// Required: true
StoragePolicyID uint64 `url:"storage_policy_id" json:"storage_policy_id" validate:"required"`
// Network interface naming pattern for Linux machines. eth - onboard naming, ens - PCI slot naming.
// Required: false
// Default: ens
// Options:
// - eth
// - ens
NetworkInterfaceNaming string `url:"network_interface_naming,omitempty" json:"network_interface_naming,omitempty" validate:"omitempty,networkInterfaceNaming"`
// Whether the image supports hot resize (online resizing)
// Required: false
// Default: false
HotResize interface{} `url:"hot_resize,omitempty" json:"hot_resize,omitempty" validate:"omitempty,isBool"`
// Default username for VMs created from this image
// Required: false
UserName string `url:"user_name,omitempty" json:"user_name,omitempty"`
// Default password for the default user
// Required: false
Password string `url:"password,omitempty" json:"password,omitempty"`
// Account ID to grant exclusive access to the image
// Required: false
AccountID uint64 `url:"account_id,omitempty" json:"account_id,omitempty"`
// Target SEP ID where the image will be created. If not specified, the best SEP will be selected based on storage policy.
// Required: false
SEPID uint64 `url:"sep_id,omitempty" json:"sep_id,omitempty"`
// Target pool name in the SEP. If not specified, the best pool will be selected automatically.
// Required: false
PoolName string `url:"pool_name,omitempty" json:"pool_name,omitempty"`
// Whether the image is bootable
// Required: false
// Default: true
Bootable interface{} `url:"bootable,omitempty" json:"bootable,omitempty" validate:"omitempty,isBool"`
}
type wrapperCreateFromDiskRequest struct {
CreateFromDiskRequest
AsyncMode bool `url:"async_mode" json:"async_mode" validate:"omitempty,isBool"`
}
// CreateFromDisk creates image from existing disk
func (i Image) CreateFromDisk(ctx context.Context, req CreateFromDiskRequest) (uint64, error) {
err := validators.ValidateRequest(req)
if err != nil {
return 0, validators.ValidationErrors(validators.GetErrors(err))
}
url := "/cloudbroker/image/create_from_disk"
aReq := wrapperCreateFromDiskRequest{
CreateFromDiskRequest: req,
AsyncMode: false,
}
res, err := i.client.DecortApiCall(ctx, http.MethodPost, url, aReq)
if err != nil {
return 0, err
}
result, err := strconv.ParseUint(string(res), 10, 64)
if err != nil {
return 0, err
}
return result, nil
}
// CreateFromDiskAsync creates image from existing disk in async mode
func (i Image) CreateFromDiskAsync(ctx context.Context, req CreateFromDiskRequest) (string, error) {
err := validators.ValidateRequest(req)
if err != nil {
return "", validators.ValidationErrors(validators.GetErrors(err))
}
url := "/cloudbroker/image/create_from_disk"
aReq := wrapperCreateFromDiskRequest{
CreateFromDiskRequest: req,
AsyncMode: true,
}
res, err := i.client.DecortApiCall(ctx, http.MethodPost, url, aReq)
if err != nil {
return "", err
}
var resp string
err = json.Unmarshal(res, &resp)
if err != nil {
return "", err
}
return resp, nil
}

View File

@@ -192,6 +192,9 @@ type RecordZone struct {
// Minimal level of logs
LoggingLevel string `json:"logging_level"`
// DRS port seed
DRSPortSeed uint64 `json:"drs_port_seed"`
}
// A zone item from a list
@@ -279,4 +282,7 @@ type ItemZone struct {
// Minimal level of logs
LoggingLevel string `json:"logging_level"`
// DRS port seed
DRSPortSeed uint64 `json:"drs_port_seed"`
}

View File

@@ -45,6 +45,7 @@ import (
apiaccess_cb "repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/apiaccess"
audit_cb "repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/audit"
backup_cb "repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/backup"
basismpm_cb "repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/basismpm"
compute_cb "repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/compute"
disks_cb "repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/disks"
dpdknet_cb "repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/dpdknet"
@@ -294,6 +295,7 @@ func getRequestsMapCloudAPI() map[string]interface{} {
"/restmachine/cloudapi/image/link": image.LinkRequest{},
"/restmachine/cloudapi/image/list": image.ListRequest{},
"/restmachine/cloudapi/image/rename": image.RenameRequest{},
"/restmachine/cloudapi/image/create_from_disk": image.CreateFromDiskRequest{},
// k8ci, k8s
"/restmachine/cloudapi/k8ci/get": k8ci.GetRequest{},
@@ -586,6 +588,12 @@ func getRequestsMapCloudbroker() map[string]interface{} {
"/restmachine/cloudbroker/backup/restoreDisksFromBackup": backup_cb.RestoreDisksFromBackupRequest{},
"/restmachine/cloudbroker/backup/set_backup_speed": backup_cb.SetBackupSpeedRequest{},
// basismpm_cb
"/restmachine/cloudbroker/basis_mpm/start": basismpm_cb.StartRequest{},
"/restmachine/cloudbroker/basis_mpm/update": basismpm_cb.UpdateRequest{},
"/restmachine/cloudbroker/basis_mpm/status": basismpm_cb.StatusRequest{},
"/restmachine/cloudbroker/basis_mpm/stop": basismpm_cb.StopRequest{},
// compute_cb
"/restmachine/cloudbroker/compute/abort_shared_snapshot_merge": compute_cb.AbortSharedSnapshotMergeRequest{},
"/restmachine/cloudbroker/compute/shared_snapshot_merge_status": compute_cb.SharedSnapshotMergeStatusRequest{},
@@ -843,6 +851,7 @@ func getRequestsMapCloudbroker() map[string]interface{} {
"/restmachine/cloudbroker/image/multi_image_add_links": image_cb.MultiImageAddLinksRequest{},
"/restmachine/cloudbroker/image/multi_image_del_links": image_cb.MultiImageDelLinksRequest{},
"/restmachine/cloudbroker/image/multi_image_export": image_cb.MultiImageExportRequest{},
"/restmachine/cloudbroker/image/create_from_disk": image_cb.CreateFromDiskRequest{},
// k8ci
"/restmachine/cloudbroker/k8ci/accessAdd": k8ci_cb.AccessAddRequest{},