v1.16.8
This commit is contained in:
269
CHANGELOG.md
269
CHANGELOG.md
@@ -1,4 +1,4 @@
|
|||||||
## Version 1.16.7
|
## Version 1.16.8
|
||||||
|
|
||||||
|
|
||||||
### Deprecated
|
### Deprecated
|
||||||
@@ -10,6 +10,8 @@
|
|||||||
| `account/AddUser` | :heavy_check_mark: | :heavy_check_mark: |
|
| `account/AddUser` | :heavy_check_mark: | :heavy_check_mark: |
|
||||||
| `account/DeleteUser` | :heavy_check_mark: | :heavy_check_mark: |
|
| `account/DeleteUser` | :heavy_check_mark: | :heavy_check_mark: |
|
||||||
| `account/UpdateUser` | :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/DiskQOS` | :heavy_check_mark: | :heavy_check_mark: |
|
||||||
| `compute/Migrate` | :x: | :heavy_check_mark: |
|
| `compute/Migrate` | :x: | :heavy_check_mark: |
|
||||||
| `compute/MigrateAbort` | :x: | :heavy_check_mark: |
|
| `compute/MigrateAbort` | :x: | :heavy_check_mark: |
|
||||||
@@ -22,6 +24,7 @@
|
|||||||
| `compute/UserList` | :heavy_check_mark: | :heavy_check_mark: |
|
| `compute/UserList` | :heavy_check_mark: | :heavy_check_mark: |
|
||||||
| `compute/UserRevoke` | :heavy_check_mark: | :heavy_check_mark: |
|
| `compute/UserRevoke` | :heavy_check_mark: | :heavy_check_mark: |
|
||||||
| `compute/UserUpdate` | :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/AccessGrant` | :heavy_check_mark: | :heavy_check_mark: |
|
||||||
| `rg/AccessRevoke` | :heavy_check_mark: | :heavy_check_mark: |
|
| `rg/AccessRevoke` | :heavy_check_mark: | :heavy_check_mark: |
|
||||||
| `sep/ConfigFieldEdit` | :x: | :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
|
#### compute
|
||||||
| Идентификатор задачи | Описание |
|
| Идентификатор задачи | Описание |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| BGOS-1111 | Опциональное поле `Planned` в структуру запроса `DiskSwitchToReplicationRequest` в cloudapi/compute |
|
| BGOS-1126 | Вычисляемые поля `PreviousReservesComputeResources` и `TakeOverResources` в структуру ответа `Resolution` в cloudbroker/compute |
|
||||||
| BGOS-1111 | Опциональное поле `Planned` в структуру запроса `DiskSwitchToReplicationRequest` в cloudbroker/compute |
|
| BGOS-1126 | Опциональное поле `TakeOverResources` в структуру запроса `MigrateV2ResolveRequest` в cloudbroker/compute |
|
||||||
| BGOS-1118 | Вычисляемое поле `CRTTracking` в структуру ответа `ItemComputeDisk` в cloudapi/compute |
|
| BGOS-1126 | Вычисляемое поле `Message` в структуру ответа `MigrateV2ResolveRecord` в cloudbroker/compute |
|
||||||
| BGOS-1118 | Вычисляемое поле `CRTTracking` в структуру ответа `ItemDisk` в cloudbroker/compute |
|
| BGOS-1126 | Вычисляемые поля `DisksCompleted`, `CompletedDisks`, `DisksTotal` и `CurrentDisk` в структуру ответа `ProgressDisks` в cloudbroker/compute |
|
||||||
| BGOS-1120 | Структура запроса `wrapperMigrateStorageRequest` и метод `MigrateStorageAsync` в cloudbroker/compute |
|
| BGOS-1126 | Структуры ответа `CompletedDisk` и `CurrentDisk` в cloudbroker/compute |
|
||||||
|
|
||||||
#### disks
|
|
||||||
|
#### zone
|
||||||
| Идентификатор задачи | Описание |
|
| Идентификатор задачи | Описание |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| BGOS-1109 | Структура запроса `ReplicationManualSyncRequest` и метод `ReplicationManualSync` в cloudapi/disks |
|
| BGOS-1127 | Вычисляемое поле `DRSPortSeed` в структуры ответа `ItemZone` и `RecordZone` в cloudbroker/zone |
|
||||||
| 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 |
|
|
||||||
|
|
||||||
#### 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
|
#### compute
|
||||||
| Идентификатор задачи | Описание |
|
| Идентификатор задачи | Описание |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| BGOS-1120 | Поле `Async` с обязательного на опциональное в структуре запроса `MigrateStorageRequest` в cloudbroker/compute |
|
| BGOS-1126 | Тип вычисляемого поля `UpdatedAt` с `uint64` на `float64` в структуре ответа `Observation` в cloudbroker/compute |
|
||||||
| BGOS-1120 | Тэги `url` и `json` поля `AsyncMode` с `asyncMode` на `async_mode` в структуре запроса `asyncWrapperSnapshotEvictDiskRequest` в 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-1134 | При получении от сервера ответа с HTTP-кодом ошибки клиенты `DecortClient`, `LegacyDecortClient` и `BVSDecortClient` теперь возвращают ошибку типа `HTTPError` с полями `StatusCode` и `Body`. Для проверки статусов добавлены функции `IsNotFound` и `HasStatusCode` |
|
||||||
| 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 |
|
|
||||||
|
|
||||||
|
|
||||||
### Исправлено
|
### Исправлено
|
||||||
|
|
||||||
#### SDN secpolicies
|
#### client sdk
|
||||||
| Идентификатор задачи | Описание |
|
| Идентификатор задачи | Описание |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| BGOS-1104 | URL метода `Get` с `/sdn/security_policies/get` на `/sdn/security_policy/get` в sdn/secpolicies |
|
| BGOS-1135 | Исправлена ошибка в сообщении об ошибке при отсутствии времени истечения токена в клиенте |
|
||||||
| 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 |
|
|
||||||
|
|
||||||
|
|||||||
@@ -148,6 +148,7 @@ go get -u repository.basistech.ru/BASIS/decort-golang-sdk
|
|||||||
- `Audit` - получение информации о событиях системы;
|
- `Audit` - получение информации о событиях системы;
|
||||||
- `APIAccess` - управление доступом к API и его объектам;
|
- `APIAccess` - управление доступом к API и его объектам;
|
||||||
- `Backup` - управление резервным копированием;
|
- `Backup` - управление резервным копированием;
|
||||||
|
- `BasisMPM` - управление в случае нехватки памяти;
|
||||||
- `BService` - управление группами виртуальных машин (computes);
|
- `BService` - управление группами виртуальных машин (computes);
|
||||||
- `Compute` - управление виртуальными машинами (индивидуально);
|
- `Compute` - управление виртуальными машинами (индивидуально);
|
||||||
- `Disks` - управление виртуальными дисками;
|
- `Disks` - управление виртуальными дисками;
|
||||||
@@ -361,6 +362,7 @@ func main() {
|
|||||||
- `pkg/cloudbroker/audit` - для `Audit`
|
- `pkg/cloudbroker/audit` - для `Audit`
|
||||||
- `pkg/cloudbroker/apiaccess` - для `APIAccess`
|
- `pkg/cloudbroker/apiaccess` - для `APIAccess`
|
||||||
- `pkg/cloudbroker/backup` - для `Backup`
|
- `pkg/cloudbroker/backup` - для `Backup`
|
||||||
|
- `pkg/cloudbroker/basismpm` - для `BasisMPM`
|
||||||
- `pkg/cloudbroker/bservice` - для `Basic Service`
|
- `pkg/cloudbroker/bservice` - для `Basic Service`
|
||||||
- `pkg/cloudbroker/compute` - для `Compute`
|
- `pkg/cloudbroker/compute` - для `Compute`
|
||||||
- `pkg/cloudbroker/disks` - для `Disks`
|
- `pkg/cloudbroker/disks` - для `Disks`
|
||||||
|
|||||||
@@ -210,7 +210,7 @@ func (dc *DecortClient) getToken(ctx context.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if resp.StatusCode != 200 {
|
if resp.StatusCode != 200 {
|
||||||
return fmt.Errorf("cannot get token: %s", tokenBytes)
|
return newHTTPError("cannot get token", resp.StatusCode, tokenBytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
// save token in config
|
// 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
|
// handle errors with status code other than 200
|
||||||
err = fmt.Errorf("%s", respBytes)
|
return nil, newHTTPError("could not execute request", resp.StatusCode, respBytes)
|
||||||
return nil, fmt.Errorf("could not execute request: %w", err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// isConnectionError checks if given error falls within specific and associated connection errors
|
// 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"]
|
exp, ok := claims["exp"]
|
||||||
if !ok {
|
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)
|
expTime := time.Unix(int64(exp.(float64)), 0)
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"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
|
// get token and retry in case of access denied
|
||||||
if err.Error() == "access is denied" {
|
if HasStatusCode(err, http.StatusUnauthorized) {
|
||||||
_, err = bdc.GetToken(ctx)
|
_, err = bdc.GetToken(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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
|
// get token and retry in case of access denied
|
||||||
if err.Error() == "access is denied" {
|
if HasStatusCode(err, http.StatusUnauthorized) {
|
||||||
_, err = bdc.GetToken(ctx)
|
_, err = bdc.GetToken(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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
|
// get token and retry in case of access denied
|
||||||
if err.Error() == "access is denied" {
|
if HasStatusCode(err, http.StatusUnauthorized) {
|
||||||
_, err = bdc.GetToken(ctx)
|
_, err = bdc.GetToken(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -287,7 +286,7 @@ func (bdc *BVSDecortClient) GetToken(ctx context.Context) (config.Token, error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if resp.StatusCode != 200 {
|
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
|
// save token in config
|
||||||
@@ -346,7 +345,7 @@ func (bdc *BVSDecortClient) RefreshToken(ctx context.Context) (config.Token, err
|
|||||||
}
|
}
|
||||||
|
|
||||||
if resp.StatusCode != 200 {
|
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
|
// save token in config
|
||||||
@@ -452,17 +451,12 @@ func (bdc *BVSDecortClient) do(req *http.Request, ctype string) ([]byte, error)
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle access denied and successful request
|
|
||||||
if resp.StatusCode == 401 {
|
|
||||||
return respBytes, errors.New("access is denied")
|
|
||||||
}
|
|
||||||
if resp.StatusCode == 200 {
|
if resp.StatusCode == 200 {
|
||||||
return respBytes, nil
|
return respBytes, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle errors with other status codes
|
// handle errors with status code other than 200 (401 triggers token refresh in callers)
|
||||||
err = fmt.Errorf("%s", respBytes)
|
return nil, newHTTPError("could not execute request", resp.StatusCode, respBytes)
|
||||||
return nil, fmt.Errorf("could not execute request: %w", err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func trimBVSConfig(cfg *config.BVSConfig) config.BVSConfig {
|
func trimBVSConfig(cfg *config.BVSConfig) config.BVSConfig {
|
||||||
|
|||||||
32
errors.go
Normal file
32
errors.go
Normal 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})
|
||||||
|
}
|
||||||
@@ -505,3 +505,65 @@ func migrateV2ModeValidator(fe validator.FieldLevel) bool {
|
|||||||
fieldValue := fe.Field().String()
|
fieldValue := fe.Field().String()
|
||||||
return IsInSlice(fieldValue, migrateV2ModeValues)
|
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)
|
||||||
|
}
|
||||||
|
|||||||
@@ -338,5 +338,65 @@ func registerAllValidators(validate *validator.Validate) error {
|
|||||||
|
|
||||||
err = validate.RegisterValidation("migrateV2Mode", migrateV2ModeValidator)
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -86,6 +86,8 @@ var (
|
|||||||
memoryBalloonModeValues = []string{"auto", "legacy", "none"}
|
memoryBalloonModeValues = []string{"auto", "legacy", "none"}
|
||||||
|
|
||||||
migrateV2ModeValues = []string{"compute", "disks", "compute_and_disks"}
|
migrateV2ModeValues = []string{"compute", "disks", "compute_and_disks"}
|
||||||
|
|
||||||
|
logLevelValues = []string{"DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"}
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -94,4 +96,37 @@ const (
|
|||||||
|
|
||||||
trunkTagsMin = 1
|
trunkTagsMin = 1
|
||||||
trunkTagsMax = 4095
|
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
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -210,7 +210,7 @@ func (ldc *LegacyDecortClient) getToken(ctx context.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if resp.StatusCode != 200 {
|
if resp.StatusCode != 200 {
|
||||||
return fmt.Errorf("cannot get token: %s", tokenBytes)
|
return newHTTPError("cannot get token", resp.StatusCode, tokenBytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
// save token in config
|
// 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
|
// handle errors with status code other than 200
|
||||||
err = fmt.Errorf("%s", respBytes)
|
return nil, newHTTPError("could not execute request", resp.StatusCode, respBytes)
|
||||||
return nil, fmt.Errorf("could not execute request: %w", err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func trimLegacyConfig(cfg *config.LegacyConfig) config.LegacyConfig {
|
func trimLegacyConfig(cfg *config.LegacyConfig) config.LegacyConfig {
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ type wrapperCreateTemplateRequest struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CreateTemplate create template from compute instance
|
// 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) {
|
func (c Compute) CreateTemplate(ctx context.Context, req CreateTemplateRequest) (string, error) {
|
||||||
err := validators.ValidateRequest(req)
|
err := validators.ValidateRequest(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -56,6 +56,8 @@ type wrapperCreateTemplateFromBlankRequest struct {
|
|||||||
|
|
||||||
// CreateTemplateFromBlank creates template from boot disk of current compute in sync mode.
|
// CreateTemplateFromBlank creates template from boot disk of current compute in sync mode.
|
||||||
// It returns id of created compute and error.
|
// 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) {
|
func (c Compute) CreateTemplateFromBlank(ctx context.Context, req CreateTemplateFromBlankRequest) (uint64, error) {
|
||||||
err := validators.ValidateRequest(req)
|
err := validators.ValidateRequest(req)
|
||||||
if err != nil {
|
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.
|
// CreateTemplateFromBlankAsync creates template from boot disk of current compute in async mode.
|
||||||
// It returns guid of task and error.
|
// 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) {
|
func (c Compute) CreateTemplateFromBlankAsync(ctx context.Context, req CreateTemplateFromBlankRequest) (string, error) {
|
||||||
err := validators.ValidateRequest(req)
|
err := validators.ValidateRequest(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -21,8 +21,8 @@ type ChangeDiskStoragePolicyRequest struct {
|
|||||||
|
|
||||||
// Keep current disk I/O tune settings in the domain XML
|
// Keep current disk I/O tune settings in the domain XML
|
||||||
// Required: false
|
// Required: false
|
||||||
// Default: false
|
// Default: false
|
||||||
KeepCurrentIOTune interface{} `url:"keep_current_iot,omitempty" json:"keep_current_iot,omitempty" validate:"omitempty,isBool"`
|
KeepCurrentIOTune interface{} `url:"keep_current_iotune,omitempty" json:"keep_current_iotune,omitempty" validate:"omitempty,isBool"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type wrapperChangeDiskStoragePolicyRequest struct {
|
type wrapperChangeDiskStoragePolicyRequest struct {
|
||||||
|
|||||||
@@ -55,6 +55,8 @@ type wrapperFromPlatformDiskRequest struct {
|
|||||||
|
|
||||||
// FromPlatformDisk creates template from platform disk in sync mode.
|
// FromPlatformDisk creates template from platform disk in sync mode.
|
||||||
// It returns id of created disk and error.
|
// 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) {
|
func (d Disks) FromPlatformDisk(ctx context.Context, req FromPlatformDiskRequest) (uint64, error) {
|
||||||
err := validators.ValidateRequest(req)
|
err := validators.ValidateRequest(req)
|
||||||
if err != nil {
|
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.
|
// FromPlatformDiskAsync creates template from platform disk in async mode.
|
||||||
// It returns guid of task and error.
|
// 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) {
|
func (d Disks) FromPlatformDiskAsync(ctx context.Context, req FromPlatformDiskRequest) (string, error) {
|
||||||
err := validators.ValidateRequest(req)
|
err := validators.ValidateRequest(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
139
pkg/cloudapi/image/create_from_disk.go
Normal file
139
pkg/cloudapi/image/create_from_disk.go
Normal 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
|
||||||
|
}
|
||||||
@@ -168,6 +168,7 @@ type CloudBrokerEndpoints struct {
|
|||||||
AuditCollector interface{} `json:"auditcollector,omitempty"`
|
AuditCollector interface{} `json:"auditcollector,omitempty"`
|
||||||
Backup interface{} `json:"backup,omitempty"`
|
Backup interface{} `json:"backup,omitempty"`
|
||||||
BackupCreator interface{} `json:"backupcreator,omitempty"`
|
BackupCreator interface{} `json:"backupcreator,omitempty"`
|
||||||
|
BasisMPM interface{} `json:"basis_mpm,omitempty"`
|
||||||
BService interface{} `json:"bservice,omitempty"`
|
BService interface{} `json:"bservice,omitempty"`
|
||||||
Compute interface{} `json:"compute,omitempty"`
|
Compute interface{} `json:"compute,omitempty"`
|
||||||
Disks interface{} `json:"disks,omitempty"`
|
Disks interface{} `json:"disks,omitempty"`
|
||||||
|
|||||||
10
pkg/cloudbroker/basismpm.go
Normal file
10
pkg/cloudbroker/basismpm.go
Normal 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)
|
||||||
|
}
|
||||||
17
pkg/cloudbroker/basismpm/basismpm.go
Normal file
17
pkg/cloudbroker/basismpm/basismpm.go
Normal 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,
|
||||||
|
}
|
||||||
|
}
|
||||||
36
pkg/cloudbroker/basismpm/models.go
Normal file
36
pkg/cloudbroker/basismpm/models.go
Normal 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"`
|
||||||
|
}
|
||||||
114
pkg/cloudbroker/basismpm/start.go
Normal file
114
pkg/cloudbroker/basismpm/start.go
Normal 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
|
||||||
|
}
|
||||||
47
pkg/cloudbroker/basismpm/status.go
Normal file
47
pkg/cloudbroker/basismpm/status.go
Normal 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
|
||||||
|
}
|
||||||
44
pkg/cloudbroker/basismpm/stop.go
Normal file
44
pkg/cloudbroker/basismpm/stop.go
Normal 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
|
||||||
|
}
|
||||||
113
pkg/cloudbroker/basismpm/update.go
Normal file
113
pkg/cloudbroker/basismpm/update.go
Normal 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
|
||||||
|
}
|
||||||
@@ -26,6 +26,8 @@ type wrapperCreateTemplateRequest struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CreateTemplate create template from compute instance
|
// 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) {
|
func (c Compute) CreateTemplate(ctx context.Context, req CreateTemplateRequest) (string, error) {
|
||||||
err := validators.ValidateRequest(req)
|
err := validators.ValidateRequest(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -50,6 +52,8 @@ func (c Compute) CreateTemplate(ctx context.Context, req CreateTemplateRequest)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CreateTemplateAsync create template from compute instance with AsyncMode
|
// 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) {
|
func (c Compute) CreateTemplateAsync(ctx context.Context, req CreateTemplateRequest) (string, error) {
|
||||||
err := validators.ValidateRequest(req)
|
err := validators.ValidateRequest(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -60,6 +60,8 @@ type wrapperCreateTemplateFromBlankRequest struct {
|
|||||||
|
|
||||||
// CreateTemplateFromBlank creates template from boot disk of current compute in sync mode.
|
// CreateTemplateFromBlank creates template from boot disk of current compute in sync mode.
|
||||||
// It returns id of created compute and error.
|
// 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) {
|
func (c Compute) CreateTemplateFromBlank(ctx context.Context, req CreateTemplateFromBlankRequest) (uint64, error) {
|
||||||
err := validators.ValidateRequest(req)
|
err := validators.ValidateRequest(req)
|
||||||
if err != nil {
|
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.
|
// CreateTemplateFromBlankAsync creates template from boot disk of current compute in async mode.
|
||||||
// It returns guid of task and error.
|
// 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) {
|
func (c Compute) CreateTemplateFromBlankAsync(ctx context.Context, req CreateTemplateFromBlankRequest) (string, error) {
|
||||||
err := validators.ValidateRequest(req)
|
err := validators.ValidateRequest(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -23,7 +23,8 @@ type Target struct {
|
|||||||
// Required: false
|
// Required: false
|
||||||
StoragePolicyID uint64 `url:"storage_policy_id,omitempty" json:"storage_policy_id,omitempty"`
|
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
|
// Required: false
|
||||||
DiskIDs []uint64 `url:"disk_ids,omitempty" json:"disk_ids,omitempty"`
|
DiskIDs []uint64 `url:"disk_ids,omitempty" json:"disk_ids,omitempty"`
|
||||||
}
|
}
|
||||||
@@ -31,8 +32,8 @@ type Target struct {
|
|||||||
// Storage describes a destination for a disk
|
// Storage describes a destination for a disk
|
||||||
type Storage struct {
|
type Storage struct {
|
||||||
// Target for migration
|
// Target for migration
|
||||||
// Required: false
|
// Required: true
|
||||||
Targets []Target `url:"targets,omitempty" json:"targets,omitempty"`
|
Targets []Target `url:"targets" json:"targets" validate:"required,min=1,dive"`
|
||||||
|
|
||||||
// Whether a separate source-disk cleanup job should be started after full success
|
// Whether a separate source-disk cleanup job should be started after full success
|
||||||
// Required: false
|
// Required: false
|
||||||
@@ -55,7 +56,7 @@ type MigrateV2Request struct {
|
|||||||
|
|
||||||
// Destination for a disk
|
// Destination for a disk
|
||||||
// Required: false
|
// 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
|
// MigrateV2 starts a migration of a compute or a disk
|
||||||
|
|||||||
@@ -18,6 +18,10 @@ type MigrateV2ResolveRequest struct {
|
|||||||
// Take over cleanup
|
// Take over cleanup
|
||||||
// Required: false
|
// Required: false
|
||||||
TakeOverCleanup interface{} `url:"take_over_cleanup,omitempty" json:"take_over_cleanup,omitempty" validate:"omitempty,isBool"`
|
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
|
// MigrateV2Resolve resolves a migration of a compute
|
||||||
|
|||||||
@@ -2315,7 +2315,7 @@ type Origin struct {
|
|||||||
|
|
||||||
type Observation struct {
|
type Observation struct {
|
||||||
// Updated at
|
// Updated at
|
||||||
UpdatedAt uint64 `json:"updated_at"`
|
UpdatedAt float64 `json:"updated_at"`
|
||||||
|
|
||||||
// Agent job ID
|
// Agent job ID
|
||||||
AgentJobID string `json:"agent_job_id"`
|
AgentJobID string `json:"agent_job_id"`
|
||||||
@@ -2329,13 +2329,13 @@ type Observation struct {
|
|||||||
|
|
||||||
type Memory struct {
|
type Memory struct {
|
||||||
// Sampled at
|
// Sampled at
|
||||||
SampledAt uint64 `json:"sampled_at"`
|
SampledAt float64 `json:"sampled_at"`
|
||||||
|
|
||||||
// Percent
|
// Percent
|
||||||
Percent uint64 `json:"percent"`
|
Percent float64 `json:"percent"`
|
||||||
|
|
||||||
// Bytes per second
|
// Bytes per second
|
||||||
BytesPerSecond uint64 `json:"bytes_per_second"`
|
BytesPerSecond float64 `json:"bytes_per_second"`
|
||||||
|
|
||||||
// Processed bytes
|
// Processed bytes
|
||||||
ProcessedBytes uint64 `json:"processed_bytes"`
|
ProcessedBytes uint64 `json:"processed_bytes"`
|
||||||
@@ -2352,19 +2352,59 @@ type ProgressDisks struct {
|
|||||||
TargetDevs []string `json:"target_devs"`
|
TargetDevs []string `json:"target_devs"`
|
||||||
|
|
||||||
// Sampled at
|
// Sampled at
|
||||||
SampledAt uint64 `json:"sampled_at"`
|
SampledAt float64 `json:"sampled_at"`
|
||||||
|
|
||||||
// Percent
|
// Percent
|
||||||
Percent uint64 `json:"percent"`
|
Percent float64 `json:"percent"`
|
||||||
|
|
||||||
// Bytes per second
|
// Bytes per second
|
||||||
BytesPerSecond uint64 `json:"bytes_per_second"`
|
BytesPerSecond float64 `json:"bytes_per_second"`
|
||||||
|
|
||||||
// Processed bytes
|
// Processed bytes
|
||||||
ProcessedBytes uint64 `json:"processed_bytes"`
|
ProcessedBytes uint64 `json:"processed_bytes"`
|
||||||
|
|
||||||
// Remaining bytes
|
// Remaining bytes
|
||||||
RemainingBytes uint64 `json:"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 {
|
type SystemDisk struct {
|
||||||
@@ -2372,13 +2412,13 @@ type SystemDisk struct {
|
|||||||
TargetDev string `json:"target_dev"`
|
TargetDev string `json:"target_dev"`
|
||||||
|
|
||||||
// Sampled at
|
// Sampled at
|
||||||
SampledAt uint64 `json:"sampled_at"`
|
SampledAt float64 `json:"sampled_at"`
|
||||||
|
|
||||||
// Percent
|
// Percent
|
||||||
Percent uint64 `json:"percent"`
|
Percent float64 `json:"percent"`
|
||||||
|
|
||||||
// Bytes per second
|
// Bytes per second
|
||||||
BytesPerSecond uint64 `json:"bytes_per_second"`
|
BytesPerSecond float64 `json:"bytes_per_second"`
|
||||||
|
|
||||||
// Processed bytes
|
// Processed bytes
|
||||||
ProcessedBytes uint64 `json:"processed_bytes"`
|
ProcessedBytes uint64 `json:"processed_bytes"`
|
||||||
@@ -2448,12 +2488,18 @@ type Resolution struct {
|
|||||||
// Take over cleanup
|
// Take over cleanup
|
||||||
TakeOverCleanup bool `json:"take_over_cleanup"`
|
TakeOverCleanup bool `json:"take_over_cleanup"`
|
||||||
|
|
||||||
|
// Take over resources
|
||||||
|
TakeOverResources bool `json:"take_over_resources"`
|
||||||
|
|
||||||
// Previous status
|
// Previous status
|
||||||
PreviousStatus string `json:"previous_status"`
|
PreviousStatus string `json:"previous_status"`
|
||||||
|
|
||||||
// Previous cleanup required
|
// Previous cleanup required
|
||||||
PreviousCleanupRequired bool `json:"previous_cleanup_required"`
|
PreviousCleanupRequired bool `json:"previous_cleanup_required"`
|
||||||
|
|
||||||
|
// Previous reserves compute resources
|
||||||
|
PreviousReservesComputeResources bool `json:"previous_reserves_compute_resources"`
|
||||||
|
|
||||||
// Previous error
|
// Previous error
|
||||||
PreviousError string `json:"previous_error"`
|
PreviousError string `json:"previous_error"`
|
||||||
}
|
}
|
||||||
@@ -2607,6 +2653,9 @@ type MigrateV2ResolveRecord struct {
|
|||||||
// Cleanup required
|
// Cleanup required
|
||||||
CleanupRequired bool `json:"cleanup_required"`
|
CleanupRequired bool `json:"cleanup_required"`
|
||||||
|
|
||||||
|
// Message
|
||||||
|
Message string `json:"message"`
|
||||||
|
|
||||||
// Resolution
|
// Resolution
|
||||||
Resolution Resolution `json:"resolution"`
|
Resolution Resolution `json:"resolution"`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,8 +21,8 @@ type ChangeDiskStoragePolicyRequest struct {
|
|||||||
|
|
||||||
// Keep current disk I/O tune settings in the domain XML
|
// Keep current disk I/O tune settings in the domain XML
|
||||||
// Required: false
|
// Required: false
|
||||||
// Default: false
|
// Default: false
|
||||||
KeepCurrentIOTune interface{} `url:"keep_current_iot,omitempty" json:"keep_current_iot,omitempty" validate:"omitempty,isBool"`
|
KeepCurrentIOTune interface{} `url:"keep_current_iotune,omitempty" json:"keep_current_iotune,omitempty" validate:"omitempty,isBool"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type wrapperChangeDiskStoragePolicyRequest struct {
|
type wrapperChangeDiskStoragePolicyRequest struct {
|
||||||
|
|||||||
@@ -59,6 +59,8 @@ type wrapperFromPlatformDiskRequest struct {
|
|||||||
|
|
||||||
// FromPlatformDisk creates template from platform disk in sync mode.
|
// FromPlatformDisk creates template from platform disk in sync mode.
|
||||||
// It returns id of created disk and error.
|
// 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) {
|
func (d Disks) FromPlatformDisk(ctx context.Context, req FromPlatformDiskRequest) (uint64, error) {
|
||||||
err := validators.ValidateRequest(req)
|
err := validators.ValidateRequest(req)
|
||||||
if err != nil {
|
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.
|
// FromPlatformDiskAsync creates template from platform disk in async mode.
|
||||||
// It returns guid of task and error.
|
// 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) {
|
func (d Disks) FromPlatformDiskAsync(ctx context.Context, req FromPlatformDiskRequest) (string, error) {
|
||||||
err := validators.ValidateRequest(req)
|
err := validators.ValidateRequest(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
139
pkg/cloudbroker/image/create_from_disk.go
Normal file
139
pkg/cloudbroker/image/create_from_disk.go
Normal 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
|
||||||
|
}
|
||||||
@@ -192,6 +192,9 @@ type RecordZone struct {
|
|||||||
|
|
||||||
// Minimal level of logs
|
// Minimal level of logs
|
||||||
LoggingLevel string `json:"logging_level"`
|
LoggingLevel string `json:"logging_level"`
|
||||||
|
|
||||||
|
// DRS port seed
|
||||||
|
DRSPortSeed uint64 `json:"drs_port_seed"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// A zone item from a list
|
// A zone item from a list
|
||||||
@@ -279,4 +282,7 @@ type ItemZone struct {
|
|||||||
|
|
||||||
// Minimal level of logs
|
// Minimal level of logs
|
||||||
LoggingLevel string `json:"logging_level"`
|
LoggingLevel string `json:"logging_level"`
|
||||||
|
|
||||||
|
// DRS port seed
|
||||||
|
DRSPortSeed uint64 `json:"drs_port_seed"`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ import (
|
|||||||
apiaccess_cb "repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/apiaccess"
|
apiaccess_cb "repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/apiaccess"
|
||||||
audit_cb "repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/audit"
|
audit_cb "repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/audit"
|
||||||
backup_cb "repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/backup"
|
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"
|
compute_cb "repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/compute"
|
||||||
disks_cb "repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/disks"
|
disks_cb "repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/disks"
|
||||||
dpdknet_cb "repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/dpdknet"
|
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/link": image.LinkRequest{},
|
||||||
"/restmachine/cloudapi/image/list": image.ListRequest{},
|
"/restmachine/cloudapi/image/list": image.ListRequest{},
|
||||||
"/restmachine/cloudapi/image/rename": image.RenameRequest{},
|
"/restmachine/cloudapi/image/rename": image.RenameRequest{},
|
||||||
|
"/restmachine/cloudapi/image/create_from_disk": image.CreateFromDiskRequest{},
|
||||||
|
|
||||||
// k8ci, k8s
|
// k8ci, k8s
|
||||||
"/restmachine/cloudapi/k8ci/get": k8ci.GetRequest{},
|
"/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/restoreDisksFromBackup": backup_cb.RestoreDisksFromBackupRequest{},
|
||||||
"/restmachine/cloudbroker/backup/set_backup_speed": backup_cb.SetBackupSpeedRequest{},
|
"/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
|
// compute_cb
|
||||||
"/restmachine/cloudbroker/compute/abort_shared_snapshot_merge": compute_cb.AbortSharedSnapshotMergeRequest{},
|
"/restmachine/cloudbroker/compute/abort_shared_snapshot_merge": compute_cb.AbortSharedSnapshotMergeRequest{},
|
||||||
"/restmachine/cloudbroker/compute/shared_snapshot_merge_status": compute_cb.SharedSnapshotMergeStatusRequest{},
|
"/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_add_links": image_cb.MultiImageAddLinksRequest{},
|
||||||
"/restmachine/cloudbroker/image/multi_image_del_links": image_cb.MultiImageDelLinksRequest{},
|
"/restmachine/cloudbroker/image/multi_image_del_links": image_cb.MultiImageDelLinksRequest{},
|
||||||
"/restmachine/cloudbroker/image/multi_image_export": image_cb.MultiImageExportRequest{},
|
"/restmachine/cloudbroker/image/multi_image_export": image_cb.MultiImageExportRequest{},
|
||||||
|
"/restmachine/cloudbroker/image/create_from_disk": image_cb.CreateFromDiskRequest{},
|
||||||
|
|
||||||
// k8ci
|
// k8ci
|
||||||
"/restmachine/cloudbroker/k8ci/accessAdd": k8ci_cb.AccessAddRequest{},
|
"/restmachine/cloudbroker/k8ci/accessAdd": k8ci_cb.AccessAddRequest{},
|
||||||
|
|||||||
Reference in New Issue
Block a user