mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-09-19 10:46:58 +08:00
openstack创建
This commit is contained in:
@@ -211,7 +211,7 @@ type ICloudVM interface {
|
||||
GetInstanceType() string
|
||||
|
||||
AssignSecurityGroup(secgroupId string) error
|
||||
AssignSecurityGroups(secgroupIds []string) error
|
||||
SetSecurityGroups(secgroupIds []string) error
|
||||
|
||||
GetHypervisor() string
|
||||
|
||||
|
||||
@@ -461,7 +461,7 @@ func (self *SManagedVirtualizedGuestDriver) RequestSyncConfigOnHost(ctx context.
|
||||
}
|
||||
externalIds = append(externalIds, extID)
|
||||
}
|
||||
return nil, iVM.AssignSecurityGroups(externalIds)
|
||||
return nil, iVM.SetSecurityGroups(externalIds)
|
||||
}
|
||||
|
||||
iDisks, err := iVM.GetIDisks()
|
||||
|
||||
@@ -1,8 +1,14 @@
|
||||
package guestdrivers
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
"yunion.io/x/onecloud/pkg/compute/options"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/util/billing"
|
||||
)
|
||||
|
||||
type SOpenStackGuestDriver struct {
|
||||
@@ -29,3 +35,59 @@ func (self *SOpenStackGuestDriver) GetDefaultSysDiskBackend() string {
|
||||
func (self *SOpenStackGuestDriver) GetMinimalSysDiskSizeGb() int {
|
||||
return options.Options.DefaultDiskSizeMB / 1024
|
||||
}
|
||||
|
||||
func (self *SOpenStackGuestDriver) ChooseHostStorage(host *models.SHost, backend string) *models.SStorage {
|
||||
storages := host.GetAttachedStorages("")
|
||||
for i := 0; i < len(storages); i++ {
|
||||
if storages[i].StorageType == backend {
|
||||
return &storages[i]
|
||||
}
|
||||
}
|
||||
for _, stype := range []string{models.STORAGE_OPENSTACK_ISCSI} {
|
||||
for i := 0; i < len(storages); i++ {
|
||||
if storages[i].StorageType == stype {
|
||||
return &storages[i]
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SOpenStackGuestDriver) GetDetachDiskStatus() ([]string, error) {
|
||||
return []string{models.VM_READY}, nil
|
||||
}
|
||||
|
||||
func (self *SOpenStackGuestDriver) GetAttachDiskStatus() ([]string, error) {
|
||||
return []string{models.VM_READY}, nil
|
||||
}
|
||||
|
||||
func (self *SOpenStackGuestDriver) GetRebuildRootStatus() ([]string, error) {
|
||||
return []string{models.VM_READY, models.VM_RUNNING, models.VM_REBUILD_ROOT_FAIL}, nil
|
||||
}
|
||||
|
||||
func (self *SOpenStackGuestDriver) GetChangeConfigStatus() ([]string, error) {
|
||||
return []string{models.VM_READY, models.VM_RUNNING}, nil
|
||||
}
|
||||
|
||||
func (self *SOpenStackGuestDriver) GetDeployStatus() ([]string, error) {
|
||||
return []string{models.VM_READY, models.VM_RUNNING}, nil
|
||||
}
|
||||
|
||||
func (self *SOpenStackGuestDriver) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
|
||||
data, err := self.SManagedVirtualizedGuestDriver.ValidateCreateData(ctx, userCred, data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if data.Contains("net.0") && data.Contains("net.1") {
|
||||
return nil, httperrors.NewInputParameterError("cannot support more than 1 nic")
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func (self *SOpenStackGuestDriver) AllowReconfigGuest() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (self *SOpenStackGuestDriver) IsSupportedBillingCycle(bc billing.SBillingCycle) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -350,7 +350,7 @@ func (self *SQcloudGuestDriver) RequestSyncConfigOnHost(ctx context.Context, gue
|
||||
}
|
||||
externalIds = append(externalIds, extID)
|
||||
}
|
||||
return nil, iVM.AssignSecurityGroups(externalIds)
|
||||
return nil, iVM.SetSecurityGroups(externalIds)
|
||||
}
|
||||
|
||||
iDisks, err := iVM.GetIDisks()
|
||||
|
||||
@@ -16,3 +16,7 @@ func init() {
|
||||
func (self *SOpenStackHostDriver) GetHostType() string {
|
||||
return models.HOST_TYPE_OPENSTACK
|
||||
}
|
||||
|
||||
func (self *SOpenStackHostDriver) ValidateDiskSize(storage *models.SStorage, sizeGb int) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -896,8 +896,8 @@ func (self *SInstance) AssignSecurityGroup(secgroupId string) error {
|
||||
return self.host.zone.region.AssignSecurityGroup(secgroupId, self.InstanceId)
|
||||
}
|
||||
|
||||
func (self *SInstance) AssignSecurityGroups(secgroupIds []string) error {
|
||||
return self.host.zone.region.AssignSecurityGroups(secgroupIds, self.InstanceId)
|
||||
func (self *SInstance) SetSecurityGroups(secgroupIds []string) error {
|
||||
return self.host.zone.region.SetSecurityGroups(secgroupIds, self.InstanceId)
|
||||
}
|
||||
|
||||
func (self *SInstance) GetBillingType() string {
|
||||
|
||||
@@ -501,10 +501,10 @@ func (self *SRegion) syncSecgroupRules(secgroupId string, rules []secrules.Secur
|
||||
}
|
||||
|
||||
func (self *SRegion) AssignSecurityGroup(secgroupId, instanceId string) error {
|
||||
return self.AssignSecurityGroups([]string{secgroupId}, instanceId)
|
||||
return self.SetSecurityGroups([]string{secgroupId}, instanceId)
|
||||
}
|
||||
|
||||
func (self *SRegion) AssignSecurityGroups(secgroupIds []string, instanceId string) error {
|
||||
func (self *SRegion) SetSecurityGroups(secgroupIds []string, instanceId string) error {
|
||||
params := map[string]string{"InstanceId": instanceId}
|
||||
for _, secgroupId := range secgroupIds {
|
||||
params["SecurityGroupId"] = secgroupId
|
||||
|
||||
@@ -283,10 +283,10 @@ func (self *SInstance) GetMachine() string {
|
||||
}
|
||||
|
||||
func (self *SInstance) AssignSecurityGroup(secgroupId string) error {
|
||||
return self.AssignSecurityGroups([]string{secgroupId})
|
||||
return self.SetSecurityGroups([]string{secgroupId})
|
||||
}
|
||||
|
||||
func (self *SInstance) AssignSecurityGroups(secgroupIds []string) error {
|
||||
func (self *SInstance) SetSecurityGroups(secgroupIds []string) error {
|
||||
ids := []*string{}
|
||||
for i := 0; i < len(secgroupIds); i++ {
|
||||
ids = append(ids, &secgroupIds[i])
|
||||
|
||||
@@ -487,7 +487,7 @@ type assignProperties struct {
|
||||
NetworkSecurityGroup SubResource `json:"networkSecurityGroup,omitempty"`
|
||||
}
|
||||
|
||||
func (self *SClassicInstance) AssignSecurityGroups(secgroupIds []string) error {
|
||||
func (self *SClassicInstance) SetSecurityGroups(secgroupIds []string) error {
|
||||
return cloudprovider.ErrNotSupported
|
||||
}
|
||||
|
||||
|
||||
@@ -1020,7 +1020,7 @@ func (self *SInstance) AssignSecurityGroup(secgroupId string) error {
|
||||
return self.host.zone.region.AssiginSecurityGroup(self.ID, secgroupId)
|
||||
}
|
||||
|
||||
func (self *SInstance) AssignSecurityGroups(secgroupIds []string) error {
|
||||
func (self *SInstance) SetSecurityGroups(secgroupIds []string) error {
|
||||
return cloudprovider.ErrNotSupported
|
||||
}
|
||||
|
||||
|
||||
@@ -528,7 +528,7 @@ func (dc *SVirtualMachine) ChangeConfig2(ctx context.Context, instanceType strin
|
||||
return cloudprovider.ErrNotImplemented
|
||||
}
|
||||
|
||||
func (self *SVirtualMachine) AssignSecurityGroups(secgroupIds []string) error {
|
||||
func (self *SVirtualMachine) SetSecurityGroups(secgroupIds []string) error {
|
||||
return cloudprovider.ErrNotImplemented
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"strconv"
|
||||
|
||||
"sort"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
@@ -363,10 +364,10 @@ func (self *SInstance) GetMachine() string {
|
||||
}
|
||||
|
||||
func (self *SInstance) AssignSecurityGroup(secgroupId string) error {
|
||||
return self.AssignSecurityGroups([]string{secgroupId})
|
||||
return self.SetSecurityGroups([]string{secgroupId})
|
||||
}
|
||||
|
||||
func (self *SInstance) AssignSecurityGroups(secgroupIds []string) error {
|
||||
func (self *SInstance) SetSecurityGroups(secgroupIds []string) error {
|
||||
currentSecgroups, err := self.host.zone.region.GetInstanceSecrityGroupIds(self.GetId())
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
+41
-18
@@ -2,9 +2,11 @@ package openstack
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
)
|
||||
@@ -104,7 +106,7 @@ func (disk *SDisk) GetMetadata() *jsonutils.JSONDict {
|
||||
}
|
||||
|
||||
func (region *SRegion) GetDisks(category string) ([]SDisk, error) {
|
||||
_, resp, err := region.CinderGet("/volumes/detail", "", nil)
|
||||
_, resp, err := region.CinderList("/volumes/detail", "", nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -126,11 +128,11 @@ func (disk *SDisk) GetId() string {
|
||||
}
|
||||
|
||||
func (disk *SDisk) Delete(ctx context.Context) error {
|
||||
return cloudprovider.ErrNotImplemented
|
||||
return disk.storage.zone.region.DeleteDisk(disk.ID)
|
||||
}
|
||||
|
||||
func (disk *SDisk) Resize(ctx context.Context, sizeMb int64) error {
|
||||
return cloudprovider.ErrNotImplemented
|
||||
return disk.storage.zone.region.ResizeDisk(disk.ID, sizeMb)
|
||||
}
|
||||
|
||||
func (disk *SDisk) GetName() string {
|
||||
@@ -179,8 +181,8 @@ func (disk *SDisk) Refresh() error {
|
||||
return jsonutils.Update(disk, new)
|
||||
}
|
||||
|
||||
func (disk *SDisk) ResizeDisk(newSize int64) error {
|
||||
return disk.storage.zone.region.ResizeDisk(disk.ID, newSize)
|
||||
func (disk *SDisk) ResizeDisk(sizeMb int64) error {
|
||||
return disk.storage.zone.region.ResizeDisk(disk.ID, sizeMb)
|
||||
}
|
||||
|
||||
func (disk *SDisk) GetDiskFormat() string {
|
||||
@@ -226,8 +228,21 @@ func (disk *SDisk) GetMountpoint() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (disk *SRegion) CreateDisk(zoneId string, category string, name string, sizeGb int, desc string) (string, error) {
|
||||
return "", cloudprovider.ErrNotImplemented
|
||||
func (region *SRegion) CreateDisk(zoneName string, category string, name string, sizeGb int, desc string) (string, error) {
|
||||
params := map[string]map[string]interface{}{
|
||||
"volume": {
|
||||
"size": sizeGb,
|
||||
"volume_type": category,
|
||||
"name": name,
|
||||
"description": desc,
|
||||
"availability_zone": zoneName,
|
||||
},
|
||||
}
|
||||
_, resp, err := region.CinderCreate("/volumes", "", jsonutils.Marshal(params))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return resp.GetString("volume", "id")
|
||||
}
|
||||
|
||||
func (region *SRegion) GetDisk(diskId string) (*SDisk, error) {
|
||||
@@ -239,12 +254,19 @@ func (region *SRegion) GetDisk(diskId string) (*SDisk, error) {
|
||||
return disk, resp.Unmarshal(disk, "volume")
|
||||
}
|
||||
|
||||
func (disk *SRegion) DeleteDisk(diskId string) error {
|
||||
return cloudprovider.ErrNotImplemented
|
||||
func (region *SRegion) DeleteDisk(diskId string) error {
|
||||
_, err := region.CinderDelete("/volumes/"+diskId, "")
|
||||
return err
|
||||
}
|
||||
|
||||
func (disk *SRegion) ResizeDisk(diskId string, sizeMb int64) error {
|
||||
return cloudprovider.ErrNotImplemented
|
||||
func (region *SRegion) ResizeDisk(diskId string, sizeMb int64) error {
|
||||
params := map[string]map[string]interface{}{
|
||||
"os-extend": {
|
||||
"new_size": sizeMb / 1024,
|
||||
},
|
||||
}
|
||||
_, _, err := region.CinderAction(fmt.Sprintf("/volumes/%s/action", diskId), "", jsonutils.Marshal(params))
|
||||
return err
|
||||
}
|
||||
|
||||
func (disk *SRegion) ResetDisk(diskId, snapshotId string) error {
|
||||
@@ -252,7 +274,12 @@ func (disk *SRegion) ResetDisk(diskId, snapshotId string) error {
|
||||
}
|
||||
|
||||
func (disk *SDisk) CreateISnapshot(ctx context.Context, name, desc string) (cloudprovider.ICloudSnapshot, error) {
|
||||
return nil, cloudprovider.ErrNotImplemented
|
||||
snapshotId, err := disk.storage.zone.region.CreateSnapshot(disk.ID, name, desc)
|
||||
if err != nil {
|
||||
log.Errorf("createSnapshot fail %v", err)
|
||||
return nil, err
|
||||
}
|
||||
return disk.storage.zone.region.GetISnapshotById(snapshotId)
|
||||
}
|
||||
|
||||
func (disk *SDisk) GetISnapshot(snapshotId string) (cloudprovider.ICloudSnapshot, error) {
|
||||
@@ -264,7 +291,7 @@ func (disk *SDisk) GetISnapshots() ([]cloudprovider.ICloudSnapshot, error) {
|
||||
}
|
||||
|
||||
func (disk *SDisk) Reset(ctx context.Context, snapshotId string) (string, error) {
|
||||
return "", disk.storage.zone.region.ResetDisk(disk.ID, snapshotId)
|
||||
return "", cloudprovider.ErrNotSupported
|
||||
}
|
||||
|
||||
func (disk *SDisk) GetBillingType() string {
|
||||
@@ -280,9 +307,5 @@ func (disk *SDisk) GetAccessPath() string {
|
||||
}
|
||||
|
||||
func (disk *SDisk) Rebuild(ctx context.Context) error {
|
||||
return disk.storage.zone.region.RebuildDisk(disk.ID)
|
||||
}
|
||||
|
||||
func (region *SRegion) RebuildDisk(diskId string) error {
|
||||
return cloudprovider.ErrNotImplemented
|
||||
return cloudprovider.ErrNotSupported
|
||||
}
|
||||
|
||||
@@ -0,0 +1,231 @@
|
||||
package openstack
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
"yunion.io/x/pkg/utils"
|
||||
)
|
||||
|
||||
const (
|
||||
QUEUED = "queued" // The Image service reserved an image ID for the image in the catalog but did not yet upload any image data.
|
||||
SAVING = "saving" // The Image service is in the process of saving the raw data for the image into the backing store.
|
||||
ACTIVE = "active" // The image is active and ready for consumption in the Image service.
|
||||
KILLED = "killed" // An image data upload error occurred.
|
||||
DELETED = "deleted" // The Image service retains information about the image but the image is no longer available for use.
|
||||
PENDING_DELETE = "pending_delete" // Similar to the deleted status. An image in this state is not recoverable.
|
||||
DEACTIVATED = "deactivated" // The image data is not available for use.
|
||||
UPLOADING = "uploading" // Data has been staged as part of the interoperable image import process. It is not yet available for use. (Since Image API 2.6)
|
||||
IMPORTING = "importing" // The image data is being processed as part of the interoperable image import process, but is not yet available for use. (Since Image API 2.6)
|
||||
)
|
||||
|
||||
type SImage struct {
|
||||
storageCache *SStoragecache
|
||||
|
||||
Status string
|
||||
Name string
|
||||
Tags []string
|
||||
ContainerFormat string
|
||||
CreatedAt time.Time
|
||||
DiskFormat string
|
||||
UpdatedAt time.Time
|
||||
Visibility string
|
||||
Self string
|
||||
MinDisk int
|
||||
Protected bool
|
||||
ID string
|
||||
File string
|
||||
Checksum string
|
||||
OsHashAlgo string
|
||||
OsHashValue string
|
||||
OsHidden bool
|
||||
Owner string
|
||||
Size int
|
||||
MinRAM int
|
||||
Schema string
|
||||
VirtualSize int
|
||||
visibility string
|
||||
}
|
||||
|
||||
func (region *SRegion) GetImages(name string, status string, imageIds []string) ([]SImage, error) {
|
||||
params := url.Values{}
|
||||
if utils.IsInStringArray(status, []string{QUEUED, SAVING, ACTIVE, KILLED, DELETED, PENDING_DELETE, DEACTIVATED, UPLOADING, IMPORTING}) {
|
||||
params.Add("status", status)
|
||||
}
|
||||
if len(name) > 0 {
|
||||
params.Add("name", name)
|
||||
}
|
||||
if len(imageIds) > 0 {
|
||||
params.Add("id", "in:"+strings.Join(imageIds, ","))
|
||||
}
|
||||
_, resp, err := region.List("image", "/v2/images?"+params.Encode(), "", nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
images := []SImage{}
|
||||
return images, resp.Unmarshal(&images, "images")
|
||||
}
|
||||
|
||||
func (image *SImage) GetMetadata() *jsonutils.JSONDict {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (image *SImage) GetId() string {
|
||||
return image.ID
|
||||
}
|
||||
|
||||
func (image *SImage) GetName() string {
|
||||
return image.Name
|
||||
}
|
||||
|
||||
func (image *SImage) IsEmulated() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (image *SImage) GetGlobalId() string {
|
||||
return image.ID
|
||||
}
|
||||
|
||||
func (image *SImage) Delete(ctx context.Context) error {
|
||||
return image.storageCache.region.DeleteImage(image.ID)
|
||||
}
|
||||
|
||||
func (image *SImage) GetStatus() string {
|
||||
switch image.Status {
|
||||
case QUEUED, SAVING, UPLOADING, IMPORTING:
|
||||
return models.CACHED_IMAGE_STATUS_CACHING
|
||||
case ACTIVE:
|
||||
return models.CACHED_IMAGE_STATUS_READY
|
||||
case DELETED, DEACTIVATED, PENDING_DELETE, KILLED:
|
||||
return models.CACHED_IMAGE_STATUS_CACHE_FAILED
|
||||
default:
|
||||
return models.CACHED_IMAGE_STATUS_CACHE_FAILED
|
||||
}
|
||||
}
|
||||
|
||||
func (image *SImage) GetImageStatus() string {
|
||||
switch image.Status {
|
||||
case QUEUED, SAVING, UPLOADING, IMPORTING:
|
||||
return models.CACHED_IMAGE_STATUS_CACHING
|
||||
case ACTIVE:
|
||||
return models.CACHED_IMAGE_STATUS_READY
|
||||
case DELETED, DEACTIVATED, PENDING_DELETE, KILLED:
|
||||
return models.CACHED_IMAGE_STATUS_CACHE_FAILED
|
||||
default:
|
||||
return models.CACHED_IMAGE_STATUS_CACHE_FAILED
|
||||
}
|
||||
}
|
||||
|
||||
func (image *SImage) Refresh() error {
|
||||
new, err := image.storageCache.region.GetImage(image.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return jsonutils.Update(image, new)
|
||||
}
|
||||
|
||||
func (image *SImage) GetImageType() string {
|
||||
switch image.Visibility {
|
||||
case "public":
|
||||
return cloudprovider.CachedImageTypeSystem
|
||||
default:
|
||||
return cloudprovider.CachedImageTypeCustomized
|
||||
}
|
||||
}
|
||||
|
||||
func (image *SImage) GetSize() int64 {
|
||||
return int64(image.Size)
|
||||
}
|
||||
|
||||
func (image *SImage) GetOsType() string {
|
||||
return "Linux"
|
||||
}
|
||||
|
||||
func (image *SImage) GetOsDist() string {
|
||||
return "Linux"
|
||||
}
|
||||
|
||||
func (image *SImage) GetOsVersion() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (image *SImage) GetOsArch() string {
|
||||
return "x86_64"
|
||||
}
|
||||
|
||||
func (image *SImage) GetMinOsDiskSizeGb() int {
|
||||
return 50
|
||||
}
|
||||
|
||||
func (image *SImage) GetImageFormat() string {
|
||||
return image.DiskFormat
|
||||
}
|
||||
|
||||
func (image *SImage) GetCreateTime() time.Time {
|
||||
return image.CreatedAt
|
||||
}
|
||||
|
||||
func (region *SRegion) GetImage(imageId string) (*SImage, error) {
|
||||
images, err := region.GetImages("", "", []string{imageId})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(images) == 0 {
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
return &images[0], nil
|
||||
}
|
||||
|
||||
func (image *SImage) GetIStoragecache() cloudprovider.ICloudStoragecache {
|
||||
return image.storageCache
|
||||
}
|
||||
|
||||
func (region *SRegion) DeleteImage(imageId string) error {
|
||||
_, err := region.Delete("image", "/v2/images/"+imageId, "")
|
||||
return err
|
||||
}
|
||||
|
||||
func (region *SRegion) GetImageStatus(imageId string) (string, error) {
|
||||
image, err := region.GetImage(imageId)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return image.Status, nil
|
||||
}
|
||||
|
||||
func (region *SRegion) GetImageByName(name string) (*SImage, error) {
|
||||
images, err := region.GetImages(name, "", []string{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(images) == 0 {
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
return &images[0], nil
|
||||
}
|
||||
|
||||
// func (region *SRegion) ImportImage(name string, osArch, osDist, osVersion string, imageUrl string) (*SImage, error) {
|
||||
// params, err := region.GetImportImageParams(name, osArch, osDist, osVersion, imageUrl)
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
|
||||
// log.Debugf("Upload image with params %#v", params)
|
||||
|
||||
// if _, err := region.cvmRequest("ImportImage", params); err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
// for i := 0; i < 8; i++ {
|
||||
// image, err := region.GetImageByName(name)
|
||||
// if err == nil {
|
||||
// return image, nil
|
||||
// }
|
||||
// time.Sleep(time.Minute * time.Duration(i))
|
||||
// }
|
||||
// return nil, cloudprovider.ErrNotFound
|
||||
// }
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
"yunion.io/x/onecloud/pkg/util/billing"
|
||||
"yunion.io/x/pkg/utils"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -137,7 +138,7 @@ func (region *SRegion) GetSecurityGroupsByInstance(instanceId string) ([]Securit
|
||||
|
||||
func (region *SRegion) GetInstances(zoneName string, hostName string) ([]SInstance, error) {
|
||||
_, maxVersion, _ := region.GetVersion("compute")
|
||||
_, resp, err := region.Get("compute", "/servers/detail", maxVersion, nil)
|
||||
_, resp, err := region.List("compute", "/servers/detail", maxVersion, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -337,11 +338,17 @@ func (instance *SInstance) GetHypervisor() string {
|
||||
}
|
||||
|
||||
func (instance *SInstance) StartVM(ctx context.Context) error {
|
||||
return cloudprovider.ErrNotImplemented
|
||||
if err := instance.host.zone.region.StartVM(instance.ID); err != nil {
|
||||
return err
|
||||
}
|
||||
return cloudprovider.WaitStatus(instance, models.VM_RUNNING, 10*time.Second, 8*time.Minute)
|
||||
}
|
||||
|
||||
func (instance *SInstance) StopVM(ctx context.Context, isForce bool) error {
|
||||
return cloudprovider.ErrNotImplemented
|
||||
if err := instance.host.zone.region.StopVM(instance.ID, isForce); err != nil {
|
||||
return err
|
||||
}
|
||||
return cloudprovider.WaitStatus(instance, models.VM_RUNNING, 10*time.Second, 8*time.Minute)
|
||||
}
|
||||
|
||||
func (region *SRegion) GetInstanceVNCUrl(instanceId string) (string, error) {
|
||||
@@ -401,20 +408,23 @@ func (region *SRegion) CreateInstance(name string, imageId string, instanceType
|
||||
return "", cloudprovider.ErrNotImplemented
|
||||
}
|
||||
|
||||
func (region *SRegion) doStartVM(instanceId string) error {
|
||||
return cloudprovider.ErrNotImplemented
|
||||
func (region *SRegion) instanceOperation(instanceId, operate string) error {
|
||||
params := jsonutils.Marshal(map[string]string{operate: ""})
|
||||
_, maxVersion, _ := region.GetVersion("compute")
|
||||
_, _, err := region.Post("compute", fmt.Sprintf("/servers/%s/action", instanceId), maxVersion, params)
|
||||
return err
|
||||
}
|
||||
|
||||
func (region *SRegion) doStopVM(instanceId string, isForce bool) error {
|
||||
return cloudprovider.ErrNotImplemented
|
||||
return region.instanceOperation(instanceId, "os-stop")
|
||||
}
|
||||
|
||||
func (region *SRegion) doDeleteVM(instanceId string) error {
|
||||
return cloudprovider.ErrNotImplemented
|
||||
return region.instanceOperation(instanceId, "forceDelete")
|
||||
}
|
||||
|
||||
func (region *SRegion) StartVM(instanceId string) error {
|
||||
return cloudprovider.ErrNotImplemented
|
||||
return region.instanceOperation(instanceId, "os-start")
|
||||
}
|
||||
|
||||
func (region *SRegion) StopVM(instanceId string, isForce bool) error {
|
||||
@@ -422,7 +432,20 @@ func (region *SRegion) StopVM(instanceId string, isForce bool) error {
|
||||
}
|
||||
|
||||
func (region *SRegion) DeleteVM(instanceId string) error {
|
||||
return cloudprovider.ErrNotImplemented
|
||||
instance, err := region.GetInstance(instanceId)
|
||||
if err != nil {
|
||||
if err == cloudprovider.ErrNotFound {
|
||||
return nil
|
||||
}
|
||||
log.Errorf("failed to get instance %s %v", instanceId, err)
|
||||
return err
|
||||
}
|
||||
status := instance.GetStatus()
|
||||
log.Debugf("Instance status on delete is %s", status)
|
||||
if status != models.VM_READY {
|
||||
log.Warningf("DeleteVM: vm status is %s expect %s", status, models.VM_READY)
|
||||
}
|
||||
return region.doDeleteVM(instanceId)
|
||||
}
|
||||
|
||||
func (region *SRegion) DeployVM(instanceId string, name string, password string, keypairName string, deleteKeypair bool, description string) error {
|
||||
@@ -430,7 +453,7 @@ func (region *SRegion) DeployVM(instanceId string, name string, password string,
|
||||
}
|
||||
|
||||
func (instance *SInstance) DeleteVM(ctx context.Context) error {
|
||||
return cloudprovider.ErrNotImplemented
|
||||
return instance.host.zone.region.DeleteVM(instance.ID)
|
||||
}
|
||||
|
||||
func (region *SRegion) ReplaceSystemDisk(instanceId string, imageId string, passwd string, keypairName string, sysDiskSizeGB int) error {
|
||||
@@ -454,11 +477,55 @@ func (region *SRegion) AttachDisk(instanceId string, diskId string) error {
|
||||
}
|
||||
|
||||
func (instance *SInstance) AssignSecurityGroup(secgroupId string) error {
|
||||
return cloudprovider.ErrNotImplemented
|
||||
secgroup, err := instance.host.zone.region.GetSecurityGroup(secgroupId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
params := map[string]map[string]string{
|
||||
"addSecurityGroup": {
|
||||
"name": secgroup.Name,
|
||||
},
|
||||
}
|
||||
_, _, err = instance.host.zone.region.Post("compute", fmt.Sprintf("/servers/%s/action", instance.ID), "", jsonutils.Marshal(params))
|
||||
return err
|
||||
}
|
||||
|
||||
func (instance *SInstance) AssignSecurityGroups(secgroupIds []string) error {
|
||||
return cloudprovider.ErrNotImplemented
|
||||
func (instance *SInstance) RevokeSecurityGroup(secgroupId string) error {
|
||||
secgroup, err := instance.host.zone.region.GetSecurityGroup(secgroupId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
params := map[string]map[string]string{
|
||||
"removeSecurityGroup": {
|
||||
"name": secgroup.Name,
|
||||
},
|
||||
}
|
||||
_, _, err = instance.host.zone.region.Post("compute", fmt.Sprintf("/servers/%s/action", instance.ID), "", jsonutils.Marshal(params))
|
||||
return err
|
||||
}
|
||||
|
||||
func (instance *SInstance) SetSecurityGroups(secgroupIds []string) error {
|
||||
secgroups, err := instance.host.zone.region.GetSecurityGroupsByInstance(instance.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
originIds := []string{}
|
||||
for _, secgroup := range secgroups {
|
||||
if !utils.IsInStringArray(secgroup.ID, secgroupIds) {
|
||||
if err := instance.RevokeSecurityGroup(secgroup.ID); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
originIds = append(originIds, secgroup.ID)
|
||||
}
|
||||
for _, secgroupId := range secgroupIds {
|
||||
if !utils.IsInStringArray(secgroupId, originIds) {
|
||||
if err := instance.AssignSecurityGroup(secgroupId); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (instance *SInstance) GetIEIP() (cloudprovider.ICloudEIP, error) {
|
||||
|
||||
@@ -73,8 +73,9 @@ func (network *SNetwork) Delete() error {
|
||||
return network.wire.zone.region.DeleteNetwork(network.ID)
|
||||
}
|
||||
|
||||
func (network *SRegion) DeleteNetwork(networkId string) error {
|
||||
return cloudprovider.ErrNotImplemented
|
||||
func (region *SRegion) DeleteNetwork(networkId string) error {
|
||||
_, err := region.Delete("network", "/v2.0/subnets/"+networkId, "")
|
||||
return err
|
||||
}
|
||||
|
||||
func (network *SNetwork) GetIWire() cloudprovider.ICloudWire {
|
||||
@@ -126,7 +127,7 @@ func (region *SRegion) GetNetwork(networkId string) (*SNetwork, error) {
|
||||
}
|
||||
|
||||
func (region *SRegion) GetNetworks(vpcId string) ([]SNetwork, error) {
|
||||
_, resp, err := region.Get("network", "/v2.0/subnets", "", nil)
|
||||
_, resp, err := region.List("network", "/v2.0/subnets", "", nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -152,6 +153,19 @@ func (network *SNetwork) Refresh() error {
|
||||
return jsonutils.Update(network, new)
|
||||
}
|
||||
|
||||
func (network *SRegion) CreateNetwork(zoneId string, vpcId string, name string, cidr string, desc string) (string, error) {
|
||||
return "", cloudprovider.ErrNotImplemented
|
||||
func (region *SRegion) CreateNetwork(vpcId string, name string, cidr string, desc string) (string, error) {
|
||||
params := map[string]map[string]interface{}{
|
||||
"subnet": {
|
||||
"name": name,
|
||||
"network_id": vpcId,
|
||||
"cidr": cidr,
|
||||
"description": desc,
|
||||
"ip_version": 4,
|
||||
},
|
||||
}
|
||||
_, resp, err := region.Post("network", "/v2.0/subnets", "", jsonutils.Marshal(params))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return resp.GetString("subnet", "id")
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package openstack
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
@@ -71,6 +72,31 @@ func (cli *SOpenStackClient) Request(region, service, method string, url string,
|
||||
return session.JSONRequest(service, "", httputils.THttpMethod(method), url, header, body)
|
||||
}
|
||||
|
||||
func (cli *SOpenStackClient) RawRequest(region, service, method string, url string, microversion string, body jsonutils.JSONObject) (*http.Response, error) {
|
||||
header := http.Header{}
|
||||
if len(microversion) > 0 {
|
||||
header.Set("X-Openstack-Nova-API-Version", microversion)
|
||||
}
|
||||
ctx := context.Background()
|
||||
session := cli.client.NewSession(ctx, region, "", "internal", cli.tokenCredential, "")
|
||||
data := strings.NewReader("")
|
||||
if body != nil {
|
||||
data = strings.NewReader(body.String())
|
||||
}
|
||||
return session.RawRequest(service, "", httputils.THttpMethod(method), url, header, data)
|
||||
}
|
||||
|
||||
func (cli *SOpenStackClient) StreamRequest(region, service, method string, url string, microversion string, body io.Reader) (*http.Response, error) {
|
||||
header := http.Header{}
|
||||
if len(microversion) > 0 {
|
||||
header.Set("X-Openstack-Nova-API-Version", microversion)
|
||||
}
|
||||
header.Set("Content-Type", "application/octet-stream")
|
||||
ctx := context.Background()
|
||||
session := cli.client.NewSession(ctx, region, "", "internal", cli.tokenCredential, "")
|
||||
return session.RawRequest(service, "", httputils.THttpMethod(method), url, header, body)
|
||||
}
|
||||
|
||||
func (cli *SOpenStackClient) getVersion(region string, service string) (string, string, error) {
|
||||
ctx := context.Background()
|
||||
session := cli.client.NewSession(ctx, region, "", "internal", cli.tokenCredential, "")
|
||||
|
||||
@@ -60,7 +60,7 @@ func (region *SRegion) GetPorts(macAddress string) ([]SPort, error) {
|
||||
params.Set("mac_address", macAddress)
|
||||
}
|
||||
url := fmt.Sprintf("%s?%s", base, params.Encode())
|
||||
_, resp, err := region.Get("network", url, "", nil)
|
||||
_, resp, err := region.List("network", url, "", nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package openstack
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
@@ -63,7 +64,25 @@ func (region *SRegion) Refresh() error {
|
||||
}
|
||||
|
||||
func (region *SRegion) CreateIVpc(name string, desc string, cidr string) (cloudprovider.ICloudVpc, error) {
|
||||
return nil, cloudprovider.ErrNotImplemented
|
||||
params := map[string]map[string]string{
|
||||
"network": {
|
||||
"name": name,
|
||||
"description": desc,
|
||||
},
|
||||
}
|
||||
_, resp, err := region.Post("network", "/v2.0/networks", "", jsonutils.Marshal(params))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = region.fetchInfrastructure()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
vpcId, err := resp.GetString("network", "id")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return region.GetIVpcById(vpcId)
|
||||
}
|
||||
|
||||
func (region *SRegion) GetIHostById(id string) (cloudprovider.ICloudHost, error) {
|
||||
@@ -173,7 +192,7 @@ func (region *SRegion) GetIZoneById(id string) (cloudprovider.ICloudZone, error)
|
||||
}
|
||||
|
||||
func (region *SRegion) fetchZones() error {
|
||||
_, resp, err := region.Get("compute", "/os-availability-zone", "", jsonutils.NewDict())
|
||||
_, resp, err := region.List("compute", "/os-availability-zone", "", jsonutils.NewDict())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -227,14 +246,53 @@ func (region *SRegion) fetchInfrastructure() error {
|
||||
}
|
||||
|
||||
func (region *SRegion) Get(service, url string, microversion string, body jsonutils.JSONObject) (http.Header, jsonutils.JSONObject, error) {
|
||||
return region.client.Request(region.Name, service, "GET", url, microversion, body)
|
||||
if strings.HasSuffix(url, "/") {
|
||||
return nil, nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
header, resp, err := region.client.Request(region.Name, service, "GET", url, microversion, body)
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "404") {
|
||||
return nil, nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
return nil, nil, err
|
||||
}
|
||||
return header, resp, nil
|
||||
}
|
||||
|
||||
func (region *SRegion) List(service, url string, microversion string, body jsonutils.JSONObject) (http.Header, jsonutils.JSONObject, error) {
|
||||
header, resp, err := region.client.Request(region.Name, service, "GET", url, microversion, body)
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "404") {
|
||||
return nil, nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
return nil, nil, err
|
||||
}
|
||||
return header, resp, nil
|
||||
}
|
||||
|
||||
func (region *SRegion) Post(service, url string, microversion string, body jsonutils.JSONObject) (http.Header, jsonutils.JSONObject, error) {
|
||||
return region.client.Request(region.Name, service, "POST", url, microversion, body)
|
||||
}
|
||||
|
||||
func (region *SRegion) Delete(service, url string, microversion string) (*http.Response, error) {
|
||||
return region.client.RawRequest(region.Name, service, "DELETE", url, microversion, nil)
|
||||
}
|
||||
|
||||
func (region *SRegion) CinderList(url string, microversion string, body jsonutils.JSONObject) (http.Header, jsonutils.JSONObject, error) {
|
||||
for _, service := range []string{"volumev3", "volumev2", "volume"} {
|
||||
header, resp, err := region.Get(service, url, microversion, body)
|
||||
if err == nil {
|
||||
return header, resp, nil
|
||||
}
|
||||
log.Debugf("failed to list %s by service %s error: %v, try another", url, service, err)
|
||||
}
|
||||
return nil, nil, fmt.Errorf("failed to get %s by cinder service", url)
|
||||
}
|
||||
|
||||
func (region *SRegion) CinderGet(url string, microversion string, body jsonutils.JSONObject) (http.Header, jsonutils.JSONObject, error) {
|
||||
if strings.HasSuffix(url, "/") {
|
||||
return nil, nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
for _, service := range []string{"volumev3", "volumev2", "volume"} {
|
||||
header, resp, err := region.Get(service, url, microversion, body)
|
||||
if err == nil {
|
||||
@@ -245,6 +303,42 @@ func (region *SRegion) CinderGet(url string, microversion string, body jsonutils
|
||||
return nil, nil, fmt.Errorf("failed to get %s by cinder service", url)
|
||||
}
|
||||
|
||||
func (region *SRegion) CinderCreate(url string, microversion string, body jsonutils.JSONObject) (http.Header, jsonutils.JSONObject, error) {
|
||||
for _, service := range []string{"volumev3", "volumev2", "volume"} {
|
||||
header, resp, err := region.Post(service, url, microversion, body)
|
||||
if err == nil {
|
||||
return header, resp, nil
|
||||
}
|
||||
log.Debugf("failed to create %s by service %s error: %v, try another", url, service, err)
|
||||
}
|
||||
return nil, nil, fmt.Errorf("failed to create %s by cinder service", url)
|
||||
}
|
||||
|
||||
func (region *SRegion) CinderDelete(url string, microversion string) (*http.Response, error) {
|
||||
if strings.HasSuffix(url, "/") {
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
for _, service := range []string{"volumev3", "volumev2", "volume"} {
|
||||
resp, err := region.Delete(service, url, microversion)
|
||||
if err == nil {
|
||||
return resp, nil
|
||||
}
|
||||
log.Debugf("failed to delete %s by service %s error: %v, try another", url, service, err)
|
||||
}
|
||||
return nil, fmt.Errorf("failed to delete %s by cinder service", url)
|
||||
}
|
||||
|
||||
func (region *SRegion) CinderAction(url string, microversion string, body jsonutils.JSONObject) (http.Header, jsonutils.JSONObject, error) {
|
||||
for _, service := range []string{"volumev3", "volumev2", "volume"} {
|
||||
header, resp, err := region.Post(service, url, microversion, body)
|
||||
if err == nil {
|
||||
return header, resp, nil
|
||||
}
|
||||
log.Debugf("failed to operate %s by service %s error: %v, try another", url, service, err)
|
||||
}
|
||||
return nil, nil, fmt.Errorf("failed to operate %s by cinder service", url)
|
||||
}
|
||||
|
||||
func (region *SRegion) ProjectId() string {
|
||||
return region.client.tokenCredential.GetProjectId()
|
||||
}
|
||||
|
||||
@@ -2,10 +2,12 @@ package openstack
|
||||
|
||||
import (
|
||||
"net"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/pkg/util/secrules"
|
||||
"yunion.io/x/pkg/utils"
|
||||
@@ -45,6 +47,20 @@ type SSecurityGroup struct {
|
||||
TenantID string
|
||||
}
|
||||
|
||||
type SecurigyGroupRuleSet []SSecurityGroupRule
|
||||
|
||||
func (v SecurigyGroupRuleSet) Len() int {
|
||||
return len(v)
|
||||
}
|
||||
|
||||
func (v SecurigyGroupRuleSet) Swap(i, j int) {
|
||||
v[i], v[j] = v[j], v[i]
|
||||
}
|
||||
|
||||
func (v SecurigyGroupRuleSet) Less(i, j int) bool {
|
||||
return strings.Compare(v[i].String(), v[j].String()) <= 0
|
||||
}
|
||||
|
||||
func (region *SRegion) GetSecurityGroup(secgroupId string) (*SSecurityGroup, error) {
|
||||
_, resp, err := region.Get("network", "/v2.0/security-groups/"+secgroupId, "", nil)
|
||||
if err != nil {
|
||||
@@ -55,7 +71,7 @@ func (region *SRegion) GetSecurityGroup(secgroupId string) (*SSecurityGroup, err
|
||||
}
|
||||
|
||||
func (region *SRegion) GetSecurityGroups() ([]SSecurityGroup, error) {
|
||||
_, resp, err := region.Get("network", "/v2.0/security-groups", "", nil)
|
||||
_, resp, err := region.List("network", "/v2.0/security-groups", "", nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -172,14 +188,127 @@ func (secgroup *SSecurityGroup) Refresh() error {
|
||||
return jsonutils.Update(secgroup, new)
|
||||
}
|
||||
|
||||
func (secgroup *SRegion) SyncSecurityGroup(secgroupId string, vpcId string, name string, desc string, rules []secrules.SecurityRule) (string, error) {
|
||||
return "", cloudprovider.ErrNotImplemented
|
||||
func (region *SRegion) SyncSecurityGroup(secgroupId string, vpcId string, name string, desc string, rules []secrules.SecurityRule) (string, error) {
|
||||
if len(secgroupId) > 0 {
|
||||
_, err := region.GetSecurityGroup(secgroupId)
|
||||
if err != nil {
|
||||
if err != cloudprovider.ErrNotFound {
|
||||
return "", err
|
||||
}
|
||||
secgroupId = ""
|
||||
}
|
||||
}
|
||||
if len(secgroupId) == 0 {
|
||||
secgroupId, err := region.CreateSecurityGroup(name, desc)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
secgroupId = secgroupId
|
||||
}
|
||||
return region.syncSecgroupRules(secgroupId, rules)
|
||||
}
|
||||
|
||||
func (region *SRegion) syncSecgroupRules(secgroupId string, rules []secrules.SecurityRule) (string, error) {
|
||||
secgroup, err := region.GetSecurityGroup(secgroupId)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
sort.Sort(secrules.SecurityRuleSet(rules))
|
||||
sort.Sort(SecurigyGroupRuleSet(secgroup.SecurityGroupRules))
|
||||
|
||||
i, j := 0, 0
|
||||
for i < len(rules) || j < len(secgroup.SecurityGroupRules) {
|
||||
if i < len(rules) && j < len(secgroup.SecurityGroupRules) {
|
||||
secruleStr := secgroup.SecurityGroupRules[j].String()
|
||||
ruleStr := rules[i].String()
|
||||
cmp := strings.Compare(secruleStr, ruleStr)
|
||||
if cmp == 0 {
|
||||
i++
|
||||
j++
|
||||
} else if cmp > 0 {
|
||||
if err := region.delSecurityGroupRule(secgroup.SecurityGroupRules[j].ID); err != nil {
|
||||
log.Errorf("delSecurityGroupRule error %v", err)
|
||||
return "", err
|
||||
}
|
||||
j++
|
||||
} else {
|
||||
if err := region.addSecurityGroupRules(secgroupId, &rules[i]); err != nil {
|
||||
log.Errorf("addSecurityGroupRule error %v", rules[i])
|
||||
return "", err
|
||||
}
|
||||
i++
|
||||
}
|
||||
} else if i >= len(rules) {
|
||||
if err := region.delSecurityGroupRule(secgroup.SecurityGroupRules[j].ID); err != nil {
|
||||
log.Errorf("delSecurityGroupRule error %v", err)
|
||||
return "", err
|
||||
}
|
||||
j++
|
||||
} else if j >= len(secgroup.SecurityGroupRules) {
|
||||
if err := region.addSecurityGroupRules(secgroupId, &rules[i]); err != nil {
|
||||
log.Errorf("addSecurityGroupRule error %v", rules[i])
|
||||
return "", err
|
||||
}
|
||||
i++
|
||||
}
|
||||
}
|
||||
|
||||
return secgroupId, nil
|
||||
}
|
||||
|
||||
func (region *SRegion) delSecurityGroupRule(ruleId string) error {
|
||||
_, err := region.Delete("network", "/v2.0/security-group-rules/"+ruleId, "")
|
||||
return err
|
||||
}
|
||||
|
||||
func (region *SRegion) addSecurityGroupRules(secgroupId string, rule *secrules.SecurityRule) error {
|
||||
direction := "ingress"
|
||||
if rule.Direction == secrules.SecurityRuleEgress {
|
||||
direction = "egress"
|
||||
}
|
||||
params := map[string]map[string]interface{}{
|
||||
"security_group_rule": {
|
||||
"direction": direction,
|
||||
"protocol": rule.Protocol,
|
||||
"security_group_id": secgroupId,
|
||||
"remote_ip_prefix": rule.IPNet.String(),
|
||||
},
|
||||
}
|
||||
if len(rule.Ports) > 0 {
|
||||
for _, port := range rule.Ports {
|
||||
params["security_group_rule"]["port_range_max"] = port
|
||||
params["security_group_rule"]["port_range_max"] = port
|
||||
_, _, err := region.Post("network", "/v2.0/security-group-rules", "", jsonutils.Marshal(params))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
if rule.PortEnd > 0 && rule.PortStart > 0 {
|
||||
params["security_group_rule"]["port_range_max"] = rule.PortStart
|
||||
params["security_group_rule"]["port_range_max"] = rule.PortEnd
|
||||
}
|
||||
_, _, err := region.Post("network", "/v2.0/security-group-rules", "", jsonutils.Marshal(params))
|
||||
return err
|
||||
}
|
||||
|
||||
func (region *SRegion) DeleteSecurityGroup(vpcId, secGroupId string) error {
|
||||
return cloudprovider.ErrNotImplemented
|
||||
_, err := region.Delete("network", "/v2.0/security-groups/"+secGroupId, "")
|
||||
return err
|
||||
}
|
||||
|
||||
func (region *SRegion) CreateSecurityGroup(name, description string) (*SSecurityGroup, error) {
|
||||
return nil, cloudprovider.ErrNotImplemented
|
||||
func (region *SRegion) CreateSecurityGroup(name, description string) (string, error) {
|
||||
params := map[string]map[string]interface{}{
|
||||
"security_group": {
|
||||
"name": name,
|
||||
"description": description,
|
||||
},
|
||||
}
|
||||
_, resp, err := region.Post("network", "/v2.0/security-groups", "", jsonutils.Marshal(params))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return resp.GetString("security_group", "id")
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package shell
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/util/openstack"
|
||||
"yunion.io/x/onecloud/pkg/util/shellutils"
|
||||
)
|
||||
@@ -18,11 +20,11 @@ func init() {
|
||||
return nil
|
||||
})
|
||||
|
||||
type DiskShowOptions struct {
|
||||
ID string `help:"Storage type for disk"`
|
||||
type DiskOptions struct {
|
||||
ID string `help:"ID of disk"`
|
||||
}
|
||||
|
||||
shellutils.R(&DiskShowOptions{}, "disk-show", "Show disk", func(cli *openstack.SRegion, args *DiskShowOptions) error {
|
||||
shellutils.R(&DiskOptions{}, "disk-show", "Show disk", func(cli *openstack.SRegion, args *DiskOptions) error {
|
||||
disk, err := cli.GetDisk(args.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -30,4 +32,23 @@ func init() {
|
||||
printObject(disk)
|
||||
return nil
|
||||
})
|
||||
|
||||
shellutils.R(&DiskOptions{}, "disk-delete", "Delete disk", func(cli *openstack.SRegion, args *DiskOptions) error {
|
||||
return cli.DeleteDisk(args.ID)
|
||||
})
|
||||
|
||||
type DiskCreateOptions struct {
|
||||
ZONE string `help:"Zone name"`
|
||||
CATEGORY string `help:"Disk category"`
|
||||
NAME string `help:"Disk Name"`
|
||||
SIZE int `help:"Disk Size GB"`
|
||||
}
|
||||
shellutils.R(&DiskCreateOptions{}, "disk-create", "Create disk", func(cli *openstack.SRegion, args *DiskCreateOptions) error {
|
||||
diskId, err := cli.CreateDisk(args.ZONE, args.CATEGORY, args.NAME, args.SIZE, "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Println(diskId)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
package shell
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/util/openstack"
|
||||
"yunion.io/x/onecloud/pkg/util/shellutils"
|
||||
)
|
||||
|
||||
func init() {
|
||||
type ImageListOptions struct {
|
||||
Name string
|
||||
Ids []string
|
||||
Status string
|
||||
}
|
||||
shellutils.R(&ImageListOptions{}, "image-list", "List images", func(cli *openstack.SRegion, args *ImageListOptions) error {
|
||||
images, err := cli.GetImages(args.Name, args.Status, args.Ids)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printList(images, 0, 0, 0, []string{})
|
||||
return nil
|
||||
})
|
||||
|
||||
type ImageOptions struct {
|
||||
ID string
|
||||
}
|
||||
|
||||
shellutils.R(&ImageOptions{}, "image-show", "Show image", func(cli *openstack.SRegion, args *ImageOptions) error {
|
||||
image, err := cli.GetImages("", "", []string{args.ID})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(image[0])
|
||||
return nil
|
||||
})
|
||||
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
package shell
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/util/openstack"
|
||||
"yunion.io/x/onecloud/pkg/util/shellutils"
|
||||
)
|
||||
@@ -18,11 +20,11 @@ func init() {
|
||||
return nil
|
||||
})
|
||||
|
||||
type SnapshotShowOptions struct {
|
||||
type SnapshotOptions struct {
|
||||
ID string `help:"ID of snapshot"`
|
||||
}
|
||||
|
||||
shellutils.R(&SnapshotShowOptions{}, "snapshot-show", "Show snapshot", func(cli *openstack.SRegion, args *SnapshotShowOptions) error {
|
||||
shellutils.R(&SnapshotOptions{}, "snapshot-show", "Show snapshot", func(cli *openstack.SRegion, args *SnapshotOptions) error {
|
||||
snapshot, err := cli.GetISnapshotById(args.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -31,4 +33,23 @@ func init() {
|
||||
return nil
|
||||
})
|
||||
|
||||
shellutils.R(&SnapshotOptions{}, "snapshot-delete", "Delete snapshot", func(cli *openstack.SRegion, args *SnapshotOptions) error {
|
||||
return cli.DeleteSnapshot(args.ID)
|
||||
})
|
||||
|
||||
type SnapshotCreateOptions struct {
|
||||
DISKID string `help:"Disk ID"`
|
||||
Name string `help:"Disk Name"`
|
||||
Desc string `help:"Disk description"`
|
||||
}
|
||||
|
||||
shellutils.R(&SnapshotCreateOptions{}, "snapshot-create", "Create snapshot", func(cli *openstack.SRegion, args *SnapshotCreateOptions) error {
|
||||
snapshotId, err := cli.CreateSnapshot(args.DISKID, args.Name, args.Desc)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Println(snapshotId)
|
||||
return nil
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
@@ -78,7 +78,7 @@ func (snapshot *SSnapshot) Refresh() error {
|
||||
}
|
||||
|
||||
func (region *SRegion) GetSnapshots(diskId string) ([]cloudprovider.ICloudSnapshot, error) {
|
||||
_, resp, err := region.CinderGet("/snapshots/detail", "", nil)
|
||||
_, resp, err := region.CinderList("/snapshots/detail", "", nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -121,6 +121,9 @@ func (snapshot *SSnapshot) GetGlobalId() string {
|
||||
}
|
||||
|
||||
func (snapshot *SSnapshot) GetName() string {
|
||||
if len(snapshot.Name) == 0 {
|
||||
return snapshot.ID
|
||||
}
|
||||
return snapshot.Name
|
||||
}
|
||||
|
||||
@@ -139,10 +142,23 @@ func (snapshot *SSnapshot) GetDiskType() string {
|
||||
return models.DISK_TYPE_DATA
|
||||
}
|
||||
|
||||
func (snapshot *SRegion) DeleteSnapshot(snapshotId string) error {
|
||||
return cloudprovider.ErrNotImplemented
|
||||
func (region *SRegion) DeleteSnapshot(snapshotId string) error {
|
||||
_, err := region.CinderDelete("/snapshots/"+snapshotId, "")
|
||||
return err
|
||||
}
|
||||
|
||||
func (snapshot *SRegion) CreateSnapshot(diskId, name, desc string) (string, error) {
|
||||
return "", cloudprovider.ErrNotImplemented
|
||||
func (region *SRegion) CreateSnapshot(diskId, name, desc string) (string, error) {
|
||||
params := map[string]map[string]interface{}{
|
||||
"snapshot": {
|
||||
"volume_id": diskId,
|
||||
"name": name,
|
||||
"description": desc,
|
||||
"force": true,
|
||||
},
|
||||
}
|
||||
_, resp, err := region.CinderCreate("/snapshots", "", jsonutils.Marshal(params))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return resp.GetString("snapshot", "id")
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
@@ -94,7 +95,12 @@ func (storage *SStorage) GetIStoragecache() cloudprovider.ICloudStoragecache {
|
||||
}
|
||||
|
||||
func (storage *SStorage) CreateIDisk(name string, sizeGb int, desc string) (cloudprovider.ICloudDisk, error) {
|
||||
return nil, cloudprovider.ErrNotImplemented
|
||||
diskId, err := storage.zone.region.CreateDisk(storage.zone.ZoneName, storage.Name, name, sizeGb, desc)
|
||||
if err != nil {
|
||||
log.Errorf("createDisk fail %v", err)
|
||||
return nil, err
|
||||
}
|
||||
return storage.GetIDiskById(diskId)
|
||||
}
|
||||
|
||||
func (storage *SStorage) GetIDiskById(idStr string) (cloudprovider.ICloudDisk, error) {
|
||||
|
||||
@@ -3,11 +3,18 @@ package openstack
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
"yunion.io/x/onecloud/pkg/image/options"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/auth"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules"
|
||||
"yunion.io/x/onecloud/pkg/util/qemuimg"
|
||||
)
|
||||
|
||||
type SStoragecache struct {
|
||||
@@ -49,7 +56,16 @@ func (cache *SStoragecache) GetManagerId() string {
|
||||
}
|
||||
|
||||
func (cache *SStoragecache) fetchImages() error {
|
||||
return cloudprovider.ErrNotImplemented
|
||||
images, err := cache.region.GetImages("", ACTIVE, []string{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cache.iimages = make([]cloudprovider.ICloudImage, len(images))
|
||||
for i := 0; i < len(images); i++ {
|
||||
images[i].storageCache = cache
|
||||
cache.iimages[i] = &images[i]
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cache *SStoragecache) GetIImages() ([]cloudprovider.ICloudImage, error) {
|
||||
@@ -62,7 +78,12 @@ func (cache *SStoragecache) GetIImages() ([]cloudprovider.ICloudImage, error) {
|
||||
}
|
||||
|
||||
func (cache *SStoragecache) GetIImageById(extId string) (cloudprovider.ICloudImage, error) {
|
||||
return nil, cloudprovider.ErrNotImplemented
|
||||
image, err := cache.region.GetImage(extId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
image.storageCache = cache
|
||||
return image, nil
|
||||
}
|
||||
|
||||
func (cache *SStoragecache) GetPath() string {
|
||||
@@ -70,11 +91,71 @@ func (cache *SStoragecache) GetPath() string {
|
||||
}
|
||||
|
||||
func (cache *SStoragecache) UploadImage(ctx context.Context, userCred mcclient.TokenCredential, imageId string, osArch, osType, osDist, osVersion string, extId string, isForce bool) (string, error) {
|
||||
return "", cloudprovider.ErrNotImplemented
|
||||
if len(extId) > 0 {
|
||||
log.Debugf("UploadImage: Image external ID exists %s", extId)
|
||||
|
||||
statsu, err := cache.region.GetImageStatus(extId)
|
||||
if err != nil {
|
||||
log.Errorf("GetImageStatus error %s", err)
|
||||
}
|
||||
if statsu == ACTIVE && !isForce {
|
||||
return extId, nil
|
||||
}
|
||||
}
|
||||
log.Debugf("UploadImage: no external ID")
|
||||
return cache.uploadImage(ctx, userCred, imageId, osArch, osType, osDist, osVersion, isForce)
|
||||
}
|
||||
|
||||
func (cache *SStoragecache) uploadImage(userCred mcclient.TokenCredential, imageId string, osArch, osType, osDist string, isForce bool) (string, error) {
|
||||
return "", cloudprovider.ErrNotImplemented
|
||||
func (cache *SStoragecache) uploadImage(ctx context.Context, userCred mcclient.TokenCredential, imageId string, osArch, osType, osDist, osVersion string, isForce bool) (string, error) {
|
||||
s := auth.GetAdminSession(ctx, options.Options.Region, "")
|
||||
|
||||
meta, reader, err := modules.Images.Download(s, imageId, string(qemuimg.VMDK), false)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
log.Infof("meta data %s", meta)
|
||||
|
||||
imageBaseName := imageId
|
||||
if imageBaseName[0] >= '0' && imageBaseName[0] <= '9' {
|
||||
imageBaseName = fmt.Sprintf("img%s", imageId)
|
||||
}
|
||||
imageName := imageBaseName
|
||||
nameIdx := 1
|
||||
|
||||
for {
|
||||
_, err = cache.region.GetImageByName(imageName)
|
||||
if err != nil {
|
||||
if err == cloudprovider.ErrNotFound {
|
||||
break
|
||||
} else {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
imageName = fmt.Sprintf("%s-%d", imageBaseName, nameIdx)
|
||||
nameIdx++
|
||||
}
|
||||
|
||||
params := map[string]string{
|
||||
"container_format": "bare",
|
||||
"disk_format": "vmdk",
|
||||
"name": imageName,
|
||||
"id": imageId,
|
||||
}
|
||||
|
||||
_, resp, err := cache.region.Post("images", "/v2/images", "", jsonutils.Marshal(params))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
image := &SImage{storageCache: cache}
|
||||
if err := resp.Unmarshal(image); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
_, err = cache.region.client.StreamRequest(cache.region.Name, "image", "PUT", fmt.Sprintf("/v2/images/%s/file", image.ID), "", reader)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return image.ID, cloudprovider.WaitStatus(image, models.CACHED_IMAGE_STATUS_READY, 15*time.Second, 3600*time.Second)
|
||||
}
|
||||
|
||||
func (cache *SStoragecache) CreateIImage(snapshoutId, imageName, osType, imageDesc string) (cloudprovider.ICloudImage, error) {
|
||||
|
||||
@@ -96,7 +96,8 @@ func (vpc *SVpc) Delete() error {
|
||||
}
|
||||
|
||||
func (region *SRegion) DeleteVpc(vpcId string) error {
|
||||
return cloudprovider.ErrNotImplemented
|
||||
_, err := region.Delete("network", "/v2.0/networks/"+vpcId, "")
|
||||
return err
|
||||
}
|
||||
|
||||
func (vpc *SVpc) GetISecurityGroups() ([]cloudprovider.ICloudSecurityGroup, error) {
|
||||
@@ -191,7 +192,7 @@ func (region *SRegion) GetVpc(vpcId string) (*SVpc, error) {
|
||||
}
|
||||
|
||||
func (region *SRegion) GetVpcs() ([]SVpc, error) {
|
||||
_, resp, err := region.Get("network", "/v2.0/networks", "", nil)
|
||||
_, resp, err := region.List("network", "/v2.0/networks", "", nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"fmt"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
)
|
||||
@@ -56,7 +57,13 @@ func (wire *SWire) GetBandwidth() int {
|
||||
}
|
||||
|
||||
func (wire *SWire) CreateINetwork(name string, cidr string, desc string) (cloudprovider.ICloudNetwork, error) {
|
||||
return nil, cloudprovider.ErrNotImplemented
|
||||
networkId, err := wire.zone.region.CreateNetwork(wire.vpc.ID, name, cidr, desc)
|
||||
if err != nil {
|
||||
log.Errorf("CreateNetwork error %s", err)
|
||||
return nil, err
|
||||
}
|
||||
wire.inetworks = nil
|
||||
return wire.GetINetworkById(networkId)
|
||||
}
|
||||
|
||||
func (wire *SWire) GetINetworkById(netid string) (cloudprovider.ICloudNetwork, error) {
|
||||
|
||||
@@ -94,7 +94,7 @@ func (zone *SZone) fetchStorages() error {
|
||||
zone.istorages = []cloudprovider.ICloudStorage{}
|
||||
|
||||
for _, service := range []string{"volumev3", "volumev2", "volume"} {
|
||||
_, resp, err := zone.region.Get(service, "/types", "", nil)
|
||||
_, resp, err := zone.region.List(service, "/types", "", nil)
|
||||
if err == nil {
|
||||
storages := []SStorage{}
|
||||
if err := resp.Unmarshal(&storages, "volume_types"); err != nil {
|
||||
@@ -142,7 +142,7 @@ func (zone *SZone) GetIHosts() ([]cloudprovider.ICloudHost, error) {
|
||||
hosts := []SHost{}
|
||||
_, maxVersion, err := zone.region.GetVersion("compute")
|
||||
if err == nil && version.GE(maxVersion, HYPERVISORS_VERSION) {
|
||||
_, resp, err := zone.region.Get("compute", "/os-hypervisors/detail", maxVersion, nil)
|
||||
_, resp, err := zone.region.List("compute", "/os-hypervisors/detail", maxVersion, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -156,7 +156,7 @@ func (zone *SZone) GetIHosts() ([]cloudprovider.ICloudHost, error) {
|
||||
return ihosts, nil
|
||||
}
|
||||
|
||||
_, resp, err := zone.region.Get("compute", "/os-hosts", "", nil)
|
||||
_, resp, err := zone.region.List("compute", "/os-hosts", "", nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -749,7 +749,7 @@ func (self *SInstance) AssignSecurityGroup(secgroupId string) error {
|
||||
return self.host.zone.region.instanceOperation(self.InstanceId, "ModifyInstancesAttribute", params)
|
||||
}
|
||||
|
||||
func (self *SInstance) AssignSecurityGroups(secgroupIds []string) error {
|
||||
func (self *SInstance) SetSecurityGroups(secgroupIds []string) error {
|
||||
params := map[string]string{}
|
||||
for i := 0; i < len(secgroupIds); i++ {
|
||||
params[fmt.Sprintf("SecurityGroups.%d", i)] = secgroupIds[i]
|
||||
|
||||
Reference in New Issue
Block a user