yunion.io/x/cloudmux@v0.3.10-0-alpha.1/pkg/multicloud/aws/vpc.go (about)

     1  // Copyright 2019 Yunion
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package aws
    16  
    17  import (
    18  	"fmt"
    19  	"strings"
    20  	"time"
    21  
    22  	"github.com/aws/aws-sdk-go/service/ec2"
    23  
    24  	"yunion.io/x/jsonutils"
    25  	"yunion.io/x/log"
    26  	"yunion.io/x/pkg/errors"
    27  
    28  	api "yunion.io/x/cloudmux/pkg/apis/compute"
    29  	"yunion.io/x/cloudmux/pkg/cloudprovider"
    30  	"yunion.io/x/cloudmux/pkg/multicloud"
    31  )
    32  
    33  type SUserCIDRs struct {
    34  	UserCidr []string
    35  }
    36  
    37  type SVpc struct {
    38  	multicloud.SVpc
    39  	AwsTags
    40  
    41  	region *SRegion
    42  
    43  	iwires    []cloudprovider.ICloudWire
    44  	secgroups []cloudprovider.ICloudSecurityGroup
    45  
    46  	RegionId                string
    47  	VpcId                   string
    48  	VpcName                 string
    49  	CidrBlock               string
    50  	CidrBlockAssociationSet []string
    51  	IsDefault               bool
    52  	Status                  string
    53  	InstanceTenancy         string
    54  }
    55  
    56  func (self *SVpc) addWire(wire *SWire) {
    57  	if self.iwires == nil {
    58  		self.iwires = make([]cloudprovider.ICloudWire, 0)
    59  	}
    60  	self.iwires = append(self.iwires, wire)
    61  }
    62  
    63  func (self *SVpc) GetId() string {
    64  	return self.VpcId
    65  }
    66  
    67  func (self *SVpc) GetName() string {
    68  	if len(self.VpcName) > 0 {
    69  		return self.VpcName
    70  	}
    71  	return self.VpcId
    72  }
    73  
    74  func (self *SVpc) GetGlobalId() string {
    75  	return self.VpcId
    76  }
    77  
    78  func (self *SVpc) GetStatus() string {
    79  	// 目前不支持专用主机
    80  	if self.InstanceTenancy == "dedicated" {
    81  		return api.VPC_STATUS_UNAVAILABLE
    82  	}
    83  	return strings.ToLower(self.Status)
    84  }
    85  
    86  func (self *SVpc) Refresh() error {
    87  	new, err := self.region.getVpc(self.VpcId)
    88  	if err != nil {
    89  		return err
    90  	}
    91  	return jsonutils.Update(self, new)
    92  }
    93  
    94  func (self *SVpc) IsEmulated() bool {
    95  	return false
    96  }
    97  
    98  func (self *SVpc) GetRegion() cloudprovider.ICloudRegion {
    99  	return self.region
   100  }
   101  
   102  func (self *SVpc) GetIsDefault() bool {
   103  	return self.IsDefault
   104  }
   105  
   106  func (self *SVpc) GetCidrBlock() string {
   107  	return strings.Join(self.CidrBlockAssociationSet, ",")
   108  }
   109  
   110  func (self *SVpc) GetIWires() ([]cloudprovider.ICloudWire, error) {
   111  	if self.iwires == nil {
   112  		err := self.fetchNetworks()
   113  		if err != nil {
   114  			return nil, errors.Wrap(err, "fetchNetworks")
   115  		}
   116  	}
   117  	return self.iwires, nil
   118  }
   119  
   120  func (self *SVpc) GetISecurityGroups() ([]cloudprovider.ICloudSecurityGroup, error) {
   121  	if self.secgroups == nil {
   122  		err := self.fetchSecurityGroups()
   123  		if err != nil {
   124  			return nil, errors.Wrap(err, "fetchSecurityGroups")
   125  		}
   126  	}
   127  	return self.secgroups, nil
   128  }
   129  
   130  func (self *SVpc) GetIRouteTables() ([]cloudprovider.ICloudRouteTable, error) {
   131  	tables, err := self.region.GetRouteTables(self.GetId(), false)
   132  	if err != nil {
   133  		return nil, errors.Wrap(err, "SVpc.GetIRouteTables")
   134  	}
   135  
   136  	itables := make([]cloudprovider.ICloudRouteTable, len(tables))
   137  	for i := range tables {
   138  		tables[i].vpc = self
   139  		itables[i] = &tables[i]
   140  	}
   141  
   142  	return itables, nil
   143  }
   144  
   145  func (self *SVpc) GetIRouteTableById(routeTableId string) (cloudprovider.ICloudRouteTable, error) {
   146  	routeTable, err := self.region.GetRouteTable(routeTableId)
   147  	if err != nil {
   148  		return nil, errors.Wrapf(err, "self.region.GetRouteTable(routeTableId:%s)", routeTableId)
   149  	}
   150  	routeTable.vpc = self
   151  	return routeTable, nil
   152  }
   153  
   154  /*
   155  Deletes the specified VPC. You must detach or delete all gateways and resources that are associated with
   156  the VPC before you can delete it. For example, you must terminate all instances running in the VPC,
   157  delete all security groups associated with the VPC (except the default one),
   158  delete all route tables associated with the VPC (except the default one), and so on.
   159  */
   160  func (self *SVpc) Delete() error {
   161  	err := self.DeleteInternetGateways()
   162  	if err != nil {
   163  		return errors.Wrap(err, "DeleteInternetGateways")
   164  	}
   165  
   166  	// 删除路由表. todo: 3.7版本路由表开放之后,需要同步状态到平台
   167  	rts, err := self.GetIRouteTables()
   168  	if err != nil {
   169  		return errors.Wrap(err, "GetIRouteTables")
   170  	}
   171  
   172  	for i := range rts {
   173  		// 主路由表不允许删除
   174  		rt := rts[i].(*SRouteTable)
   175  		if len(rt.Associations) > 0 {
   176  			if rt.Associations[0].Main {
   177  				log.Debugf("Delete.RouteTable skipped main route table %s(%s)", rt.GetName(), rt.GetId())
   178  				continue
   179  			}
   180  		}
   181  
   182  		err = self.region.DeleteRouteTable(rts[i].GetId())
   183  		if err != nil {
   184  			return errors.Wrap(err, "DeleteRouteTable")
   185  		}
   186  	}
   187  
   188  	return self.region.DeleteVpc(self.VpcId)
   189  }
   190  
   191  func (self *SVpc) GetIWireById(wireId string) (cloudprovider.ICloudWire, error) {
   192  	if self.iwires == nil {
   193  		err := self.fetchNetworks()
   194  		if err != nil {
   195  			return nil, errors.Wrap(err, "fetchNetworks")
   196  		}
   197  	}
   198  	for i := 0; i < len(self.iwires); i += 1 {
   199  		if self.iwires[i].GetGlobalId() == wireId {
   200  			return self.iwires[i], nil
   201  		}
   202  	}
   203  	return nil, errors.Wrap(cloudprovider.ErrNotFound, "GetIWireById")
   204  }
   205  
   206  func (self *SVpc) getWireByZoneId(zoneId string) *SWire {
   207  	for i := 0; i < len(self.iwires); i += 1 {
   208  		wire := self.iwires[i].(*SWire)
   209  		if wire.zone.ZoneId == zoneId {
   210  			return wire
   211  		}
   212  	}
   213  
   214  	zone, err := self.region.getZoneById(zoneId)
   215  	if err != nil {
   216  		return nil
   217  	}
   218  	return &SWire{
   219  		zone: zone,
   220  		vpc:  self,
   221  	}
   222  }
   223  
   224  func (self *SVpc) fetchNetworks() error {
   225  	networks, err := self.region.GetNetwroks(nil, self.VpcId)
   226  	if err != nil {
   227  		return errors.Wrapf(err, "GetNetwroks(%s)", self.VpcId)
   228  	}
   229  
   230  	for i := 0; i < len(networks); i += 1 {
   231  		wire := self.getWireByZoneId(networks[i].ZoneId)
   232  		networks[i].wire = wire
   233  		wire.addNetwork(&networks[i])
   234  	}
   235  	return nil
   236  }
   237  
   238  func (self *SVpc) revokeSecurityGroup(secgroupId string, instanceId string, keep bool) error {
   239  	return self.region.revokeSecurityGroup(secgroupId, instanceId, keep)
   240  }
   241  
   242  func (self *SVpc) assignSecurityGroup(secgroupId string, instanceId string) error {
   243  	return self.region.assignSecurityGroup(secgroupId, instanceId)
   244  }
   245  
   246  func (self *SVpc) fetchSecurityGroups() error {
   247  	if len(self.VpcId) == 0 {
   248  		return fmt.Errorf("fetchSecurityGroups vpc id is empty")
   249  	}
   250  
   251  	secgroups, _, err := self.region.GetSecurityGroups(self.VpcId, "", "", 0, 0)
   252  	if err != nil {
   253  		return errors.Wrap(err, "GetSecurityGroups")
   254  	}
   255  
   256  	self.secgroups = make([]cloudprovider.ICloudSecurityGroup, len(secgroups))
   257  	for i := 0; i < len(secgroups); i++ {
   258  		secgroups[i].vpc = self
   259  		self.secgroups[i] = &secgroups[i]
   260  	}
   261  	return nil
   262  }
   263  
   264  func (self *SVpc) GetICloudVpcPeeringConnections() ([]cloudprovider.ICloudVpcPeeringConnection, error) {
   265  	svpcPCs, err := self.getRequesterVpcPeeringConnections()
   266  	if err != nil {
   267  		return nil, errors.Wrap(err, "self.getSVpcPeeringConnections()")
   268  	}
   269  	ret := []cloudprovider.ICloudVpcPeeringConnection{}
   270  	for i := range svpcPCs {
   271  		ret = append(ret, svpcPCs[i])
   272  	}
   273  	return ret, nil
   274  }
   275  
   276  func (self *SVpc) GetICloudAccepterVpcPeeringConnections() ([]cloudprovider.ICloudVpcPeeringConnection, error) {
   277  	svpcPCs, err := self.getAccepterVpcPeeringConnections()
   278  	if err != nil {
   279  		return nil, errors.Wrap(err, "self.getAccepterVpcPeeringConnections()")
   280  	}
   281  	ret := []cloudprovider.ICloudVpcPeeringConnection{}
   282  	for i := range svpcPCs {
   283  		ret = append(ret, svpcPCs[i])
   284  	}
   285  	return ret, nil
   286  }
   287  
   288  func (self *SVpc) GetICloudVpcPeeringConnectionById(id string) (cloudprovider.ICloudVpcPeeringConnection, error) {
   289  	vpcPc, err := self.getSVpcPeeringConnectionById(id)
   290  	if err != nil {
   291  		return nil, errors.Wrapf(err, "getSVpcPeeringConnectionById(%s)", id)
   292  	}
   293  	return vpcPc, nil
   294  }
   295  
   296  func (self *SVpc) CreateICloudVpcPeeringConnection(opts *cloudprovider.VpcPeeringConnectionCreateOptions) (cloudprovider.ICloudVpcPeeringConnection, error) {
   297  	return self.createSVpcPeeringConnection(opts)
   298  }
   299  
   300  func (self *SVpc) AcceptICloudVpcPeeringConnection(id string) error {
   301  	return self.acceptSVpcPeeringConnection(id)
   302  }
   303  
   304  func (self *SVpc) GetAuthorityOwnerId() string {
   305  	identity, err := self.region.client.GetCallerIdentity()
   306  	if err != nil {
   307  		log.Errorf(err.Error() + "self.region.client.GetCallerIdentity()")
   308  		return ""
   309  	}
   310  	return identity.Account
   311  }
   312  
   313  func (self *SVpc) getSVpcPeeringConnectionById(id string) (*SVpcPeeringConnection, error) {
   314  	vpcPC, err := self.region.GetVpcPeeringConnectionById(id)
   315  	if err != nil {
   316  		return nil, errors.Wrapf(err, "self.region.GetVpcPeeringConnectionById(%s)", id)
   317  	}
   318  	if vpcPC.Status.Code != nil && (*vpcPC.Status.Code == ec2.VpcPeeringConnectionStateReasonCodeDeleted ||
   319  		*vpcPC.Status.Code == ec2.VpcPeeringConnectionStateReasonCodeDeleting) {
   320  		return nil, cloudprovider.ErrNotFound
   321  	}
   322  	svpcPC := SVpcPeeringConnection{}
   323  	svpcPC.vpc = self
   324  	svpcPC.vpcPC = vpcPC
   325  	return &svpcPC, nil
   326  }
   327  
   328  func (self *SVpc) getRequesterVpcPeeringConnections() ([]*SVpcPeeringConnection, error) {
   329  	vpcPCs, err := self.region.DescribeRequesterVpcPeeringConnections(self.VpcId)
   330  	if err != nil {
   331  		return nil, errors.Wrap(err, "self.region.DescribeRequesterVpcPeeringConnections()")
   332  	}
   333  	ivpcPCs := []*SVpcPeeringConnection{}
   334  	for i := range vpcPCs {
   335  		if vpcPCs[i].Status.Code != nil && (*vpcPCs[i].Status.Code == ec2.VpcPeeringConnectionStateReasonCodeDeleted ||
   336  			*vpcPCs[i].Status.Code == ec2.VpcPeeringConnectionStateReasonCodeDeleting) {
   337  			continue
   338  		}
   339  		svpcPC := SVpcPeeringConnection{}
   340  		svpcPC.vpc = self
   341  		svpcPC.vpcPC = vpcPCs[i]
   342  		ivpcPCs = append(ivpcPCs, &svpcPC)
   343  	}
   344  	return ivpcPCs, nil
   345  }
   346  
   347  func (self *SVpc) getAccepterVpcPeeringConnections() ([]*SVpcPeeringConnection, error) {
   348  	vpcPCs, err := self.region.DescribeAccepterVpcPeeringConnections(self.VpcId)
   349  	if err != nil {
   350  		return nil, errors.Wrap(err, "self.region.DescribeAccepterVpcPeeringConnections()")
   351  	}
   352  	ivpcPCs := []*SVpcPeeringConnection{}
   353  	for i := range vpcPCs {
   354  		if vpcPCs[i].Status.Code != nil && (*vpcPCs[i].Status.Code == ec2.VpcPeeringConnectionStateReasonCodeDeleted ||
   355  			*vpcPCs[i].Status.Code == ec2.VpcPeeringConnectionStateReasonCodeDeleting) {
   356  			continue
   357  		}
   358  		svpcPC := SVpcPeeringConnection{}
   359  		svpcPC.vpc = self
   360  		svpcPC.vpcPC = vpcPCs[i]
   361  		ivpcPCs = append(ivpcPCs, &svpcPC)
   362  	}
   363  	return ivpcPCs, nil
   364  }
   365  
   366  func (self *SVpc) createSVpcPeeringConnection(opts *cloudprovider.VpcPeeringConnectionCreateOptions) (*SVpcPeeringConnection, error) {
   367  	svpcPC := SVpcPeeringConnection{}
   368  	vpcPC, err := self.region.CreateVpcPeeringConnection(self.VpcId, opts)
   369  	if err != nil {
   370  		return nil, errors.Wrapf(err, " self.region.CreateVpcPeeringConnection(%s,%s)", self.VpcId, jsonutils.Marshal(opts).String())
   371  	}
   372  	svpcPC.vpc = self
   373  	svpcPC.vpcPC = vpcPC
   374  	err = cloudprovider.WaitMultiStatus(&svpcPC, []string{api.VPC_PEERING_CONNECTION_STATUS_PENDING_ACCEPT,
   375  		api.VPC_PEERING_CONNECTION_STATUS_ACTIVE,
   376  		api.VPC_PEERING_CONNECTION_STATUS_DELETING}, 5*time.Second, 60*time.Second)
   377  	if err != nil {
   378  		return nil, errors.Wrap(err, "cloudprovider.WaitMultiStatus")
   379  	}
   380  	if svpcPC.GetStatus() == api.VPC_PEERING_CONNECTION_STATUS_DELETING {
   381  		return nil, errors.Wrapf(cloudprovider.ErrInvalidStatus, "vpcpeeringconnection:%s  invalidate status", jsonutils.Marshal(svpcPC.vpcPC).String())
   382  	}
   383  	return &svpcPC, nil
   384  }
   385  
   386  func (self *SVpc) acceptSVpcPeeringConnection(id string) error {
   387  	svpcPC, err := self.getSVpcPeeringConnectionById(id)
   388  	if err != nil {
   389  		return errors.Wrapf(err, "self.getSVpcPeeringConnectionById(%s)", id)
   390  	}
   391  	//	其他region 创建的连接请求,有短暂的provisioning状态
   392  	err = cloudprovider.WaitMultiStatus(svpcPC, []string{api.VPC_PEERING_CONNECTION_STATUS_ACTIVE,
   393  		api.VPC_PEERING_CONNECTION_STATUS_PENDING_ACCEPT,
   394  		api.VPC_PEERING_CONNECTION_STATUS_DELETING}, 5*time.Second, 60*time.Second)
   395  	if err != nil {
   396  		return errors.Wrap(err, "cloudprovider.WaitMultiStatus")
   397  	}
   398  	if svpcPC.GetStatus() == api.VPC_PEERING_CONNECTION_STATUS_DELETING {
   399  		return errors.Wrapf(cloudprovider.ErrInvalidStatus, "vpcpeeringconnection:%s  invalidate status", jsonutils.Marshal(svpcPC.vpcPC).String())
   400  	}
   401  
   402  	if svpcPC.GetStatus() == api.VPC_PEERING_CONNECTION_STATUS_PENDING_ACCEPT {
   403  		_, err := self.region.AcceptVpcPeeringConnection(id)
   404  		if err != nil {
   405  			return errors.Wrapf(err, "self.region.AcceptVpcPeeringConnection(%s)", id)
   406  		}
   407  	}
   408  	err = cloudprovider.WaitMultiStatus(svpcPC, []string{api.VPC_PEERING_CONNECTION_STATUS_ACTIVE,
   409  		api.VPC_PEERING_CONNECTION_STATUS_DELETING}, 5*time.Second, 60*time.Second)
   410  	if err != nil {
   411  		return errors.Wrap(err, "cloudprovider.WaitMultiStatus")
   412  	}
   413  	if svpcPC.GetStatus() == api.VPC_PEERING_CONNECTION_STATUS_DELETING {
   414  		return errors.Wrapf(cloudprovider.ErrInvalidStatus, "vpcpeeringconnection:%s  invalidate status", jsonutils.Marshal(svpcPC.vpcPC).String())
   415  	}
   416  	return nil
   417  }
   418  
   419  func (self *SVpc) IsSupportSetExternalAccess() bool {
   420  	return true
   421  }
   422  
   423  func (self *SVpc) GetExternalAccessMode() string {
   424  	igws, err := self.region.GetInternetGateways(self.GetId())
   425  	if err != nil {
   426  		log.Errorf("GetExternalAccessMode.GetInternetGateways %s", err)
   427  	}
   428  
   429  	if len(igws) > 0 {
   430  		return api.VPC_EXTERNAL_ACCESS_MODE_EIP
   431  	}
   432  
   433  	return api.VPC_EXTERNAL_ACCESS_MODE_NONE
   434  }
   435  
   436  func (self *SVpc) AttachInternetGateway(igwId string) error {
   437  	ec2Client, err := self.region.getEc2Client()
   438  	if err != nil {
   439  		return errors.Wrap(err, "getEc2Client")
   440  	}
   441  
   442  	input := ec2.AttachInternetGatewayInput{}
   443  	input.SetInternetGatewayId(igwId)
   444  	input.SetVpcId(self.GetId())
   445  
   446  	_, err = ec2Client.AttachInternetGateway(&input)
   447  	if err != nil {
   448  		return errors.Wrap(err, "AttachInternetGateway")
   449  	}
   450  
   451  	err = self.AddDefaultInternetGatewayRoute(igwId)
   452  	if err != nil {
   453  		return errors.Wrap(err, "AddDefaultInternetGatewayRoute")
   454  	}
   455  
   456  	return nil
   457  }
   458  
   459  func (self *SVpc) AddDefaultInternetGatewayRoute(igwId string) error {
   460  	rt, err := self.GetMainRouteTable()
   461  	if err != nil {
   462  		return errors.Wrap(err, "GetMainRouteTable")
   463  	}
   464  
   465  	defaultRoute := cloudprovider.RouteSet{}
   466  	defaultRoute.NextHop = igwId
   467  	defaultRoute.Destination = "0.0.0.0/0"
   468  	err = rt.CreateRoute(defaultRoute)
   469  	if err != nil {
   470  		return errors.Wrap(err, "CreateRoute")
   471  	}
   472  
   473  	return nil
   474  }
   475  
   476  func (self *SVpc) GetMainRouteTable() (*SRouteTable, error) {
   477  	rt, err := self.region.GetRouteTables(self.GetId(), true)
   478  	if err != nil {
   479  		return nil, errors.Wrap(err, "GetRouteTables")
   480  	}
   481  
   482  	if len(rt) == 0 {
   483  		return nil, errors.Wrap(cloudprovider.ErrNotSupported, "GetMainRouteTable")
   484  	}
   485  
   486  	return &rt[0], nil
   487  }
   488  
   489  func (self *SVpc) DetachInternetGateways() error {
   490  	igws, err := self.region.GetInternetGateways(self.GetId())
   491  	if err != nil {
   492  		return errors.Wrap(err, "GetInternetGateways")
   493  	}
   494  
   495  	if len(igws) > 0 {
   496  		for i := range igws {
   497  			err = self.DetachInternetGateway(igws[i].GetId())
   498  			if err != nil {
   499  				return errors.Wrap(err, "DetachInternetGateway")
   500  			}
   501  		}
   502  	}
   503  
   504  	return nil
   505  }
   506  
   507  func (self *SVpc) DetachInternetGateway(igwId string) error {
   508  	ec2Client, err := self.region.getEc2Client()
   509  	if err != nil {
   510  		return errors.Wrap(err, "getEc2Client")
   511  	}
   512  
   513  	input := ec2.DetachInternetGatewayInput{}
   514  	input.SetInternetGatewayId(igwId)
   515  	input.SetVpcId(self.GetId())
   516  
   517  	_, err = ec2Client.DetachInternetGateway(&input)
   518  	if err != nil {
   519  		return errors.Wrap(err, "DetachInternetGateway")
   520  	}
   521  
   522  	return nil
   523  }
   524  
   525  func (self *SVpc) DeleteInternetGateway(igwId string) error {
   526  	ec2Client, err := self.region.getEc2Client()
   527  	if err != nil {
   528  		return errors.Wrap(err, "getEc2Client")
   529  	}
   530  
   531  	input := ec2.DeleteInternetGatewayInput{}
   532  	input.SetInternetGatewayId(igwId)
   533  
   534  	_, err = ec2Client.DeleteInternetGateway(&input)
   535  	if err != nil {
   536  		return errors.Wrap(err, "DeleteInternetGateway")
   537  	}
   538  
   539  	return nil
   540  }
   541  
   542  func (self *SVpc) DeleteInternetGateways() error {
   543  	igws, err := self.region.GetInternetGateways(self.GetId())
   544  	if err != nil {
   545  		return errors.Wrap(err, "GetInternetGateways")
   546  	}
   547  
   548  	if len(igws) > 0 {
   549  		for i := range igws {
   550  			err = self.DetachInternetGateway(igws[i].GetId())
   551  			if err != nil {
   552  				return errors.Wrap(err, "DetachInternetGateway")
   553  			}
   554  
   555  			err = self.DeleteInternetGateway(igws[i].GetId())
   556  			if err != nil {
   557  				return errors.Wrap(err, "DeleteInternetGateway")
   558  			}
   559  		}
   560  	}
   561  
   562  	return nil
   563  }
   564  
   565  func (self *SRegion) getVpc(vpcId string) (*SVpc, error) {
   566  	if len(vpcId) == 0 {
   567  		return nil, fmt.Errorf("GetVpc vpc id should not be empty.")
   568  	}
   569  
   570  	vpcs, err := self.GetVpcs([]string{vpcId})
   571  	if err != nil {
   572  		return nil, errors.Wrap(err, "GetVpcs")
   573  	}
   574  	if len(vpcs) != 1 {
   575  		return nil, errors.Wrap(cloudprovider.ErrNotFound, "getVpc")
   576  	}
   577  	vpcs[0].region = self
   578  	return &vpcs[0], nil
   579  }
   580  
   581  func (self *SRegion) revokeSecurityGroup(secgroupId, instanceId string, keep bool) error {
   582  	// todo : keep ? 直接使用assignSecurityGroup 即可?
   583  	return nil
   584  }
   585  
   586  func (self *SRegion) assignSecurityGroup(secgroupId, instanceId string) error {
   587  	return self.assignSecurityGroups([]*string{&secgroupId}, instanceId)
   588  }
   589  
   590  func (self *SRegion) assignSecurityGroups(secgroupIds []*string, instanceId string) error {
   591  	instance, err := self.GetInstance(instanceId)
   592  	if err != nil {
   593  		return errors.Wrap(err, "GetInstance")
   594  	}
   595  
   596  	ec2Client, err := self.getEc2Client()
   597  	if err != nil {
   598  		return errors.Wrap(err, "getEc2Client")
   599  	}
   600  
   601  	for _, eth := range instance.NetworkInterfaces {
   602  		params := &ec2.ModifyNetworkInterfaceAttributeInput{}
   603  		params.SetNetworkInterfaceId(eth.NetworkInterfaceId)
   604  		params.SetGroups(secgroupIds)
   605  
   606  		_, err := ec2Client.ModifyNetworkInterfaceAttribute(params)
   607  		if err != nil {
   608  			return err
   609  		}
   610  	}
   611  
   612  	return nil
   613  }
   614  
   615  func (self *SRegion) DeleteSecurityGroup(secGrpId string) error {
   616  	ec2Client, err := self.getEc2Client()
   617  	if err != nil {
   618  		return errors.Wrap(err, "getEc2Client")
   619  	}
   620  
   621  	params := &ec2.DeleteSecurityGroupInput{}
   622  	params.SetGroupId(secGrpId)
   623  
   624  	_, err = ec2Client.DeleteSecurityGroup(params)
   625  	return errors.Wrap(err, "DeleteSecurityGroup")
   626  }
   627  
   628  func (self *SRegion) DeleteVpc(vpcId string) error {
   629  	ec2Client, err := self.getEc2Client()
   630  	if err != nil {
   631  		return errors.Wrap(err, "getEc2Client")
   632  	}
   633  
   634  	params := &ec2.DeleteVpcInput{}
   635  	params.SetVpcId(vpcId)
   636  
   637  	_, err = ec2Client.DeleteVpc(params)
   638  	return errors.Wrap(err, "DeleteVpc")
   639  }
   640  
   641  func (self *SRegion) GetVpcs(vpcId []string) ([]SVpc, error) {
   642  	ec2Client, err := self.getEc2Client()
   643  	if err != nil {
   644  		return nil, errors.Wrap(err, "getEc2Client")
   645  	}
   646  
   647  	params := &ec2.DescribeVpcsInput{}
   648  	if len(vpcId) > 0 {
   649  		params.SetVpcIds(ConvertedList(vpcId))
   650  	}
   651  
   652  	ret, err := ec2Client.DescribeVpcs(params)
   653  	err = parseNotFoundError(err)
   654  	if err != nil {
   655  		return nil, err
   656  	}
   657  
   658  	vpcs := []SVpc{}
   659  	for _, item := range ret.Vpcs {
   660  		if err := FillZero(item); err != nil {
   661  			return nil, err
   662  		}
   663  		cidrBlockAssociationSet := []string{}
   664  		for i := range item.CidrBlockAssociationSet {
   665  			cidr := item.CidrBlockAssociationSet[i]
   666  			if cidr.CidrBlockState.State != nil && *cidr.CidrBlockState.State == "associated" {
   667  				cidrBlockAssociationSet = append(cidrBlockAssociationSet, *cidr.CidrBlock)
   668  			}
   669  		}
   670  
   671  		tagspec := TagSpec{ResourceType: "vpc"}
   672  		tagspec.LoadingEc2Tags(item.Tags)
   673  
   674  		vpc := SVpc{
   675  			region:                  self,
   676  			RegionId:                self.RegionId,
   677  			VpcId:                   *item.VpcId,
   678  			VpcName:                 tagspec.GetNameTag(),
   679  			CidrBlock:               *item.CidrBlock,
   680  			CidrBlockAssociationSet: cidrBlockAssociationSet,
   681  			IsDefault:               *item.IsDefault,
   682  			Status:                  *item.State,
   683  			InstanceTenancy:         *item.InstanceTenancy,
   684  		}
   685  		jsonutils.Update(&vpc.AwsTags.TagSet, item.Tags)
   686  		vpcs = append(vpcs, vpc)
   687  	}
   688  
   689  	return vpcs, nil
   690  }
   691  
   692  func (self *SRegion) GetInternetGateways(vpcId string) ([]SInternetGateway, error) {
   693  	ec2Client, err := self.getEc2Client()
   694  	if err != nil {
   695  		return nil, errors.Wrap(err, "getEc2Client")
   696  	}
   697  
   698  	input := ec2.DescribeInternetGatewaysInput{}
   699  	filters := make([]*ec2.Filter, 0)
   700  	if len(vpcId) > 0 {
   701  		filters = AppendSingleValueFilter(filters, "attachment.vpc-id", vpcId)
   702  	}
   703  
   704  	if len(filters) > 0 {
   705  		input.SetFilters(filters)
   706  	}
   707  	output, err := ec2Client.DescribeInternetGateways(&input)
   708  	if err != nil {
   709  		return nil, errors.Wrap(err, "DescribeInternetGateways")
   710  	}
   711  
   712  	igws := make([]SInternetGateway, len(output.InternetGateways))
   713  	err = unmarshalAwsOutput(output, "InternetGateways", &igws)
   714  	if err != nil {
   715  		return nil, errors.Wrap(err, "unmarshalAwsOutput")
   716  	}
   717  
   718  	for i := range igws {
   719  		igws[i].region = self
   720  	}
   721  
   722  	return igws, nil
   723  }