resources

package
v0.8.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 13, 2023 License: Apache-2.0 Imports: 34 Imported by: 1

Documentation

Overview

Proof of Concepts for the Cloud-Barista Multi-Cloud Project.

EC2 Hander (AWS SDK GO Version 1.16.26, Thanks AWS.)

by CB-Spider Team, 2019.03.

Index

Constants

View Source
const (
	CreateTagsResourceId = "ResourceId"
	CreateTagsTag        = "Tag"
)

///////////////////////////////////////////////////////////////////// implemented by developer user, like 'createTags(kv []KeyVale) bool' /////////////////////////////////////////////////////////////////////

View Source
const (
	AssociateIamInstanceProfileInstanceId = "InstanceId"
	AssociateIamInstanceProfileRole       = "Role"
)
View Source
const (
	AWS_VOLUME_STATE_CREATING  = "creating"
	AWS_VOLUME_STATE_AVAILABLE = "available"
	AWS_VOLUME_STATE_INUSE     = "in-use"
	AWS_VOLUME_STATE_DELETING  = "deleting"
	AWS_VOLUME_STATE_ERROR     = "error"

	AWS_VOLUME_ATTACH_STATE_ATTACHING = "attaching"
	AWS_VOLUME_ATTACH_STATE_ATTACHED  = "attached"
	AWS_VOLUME_ATTACH_STATE_DETACHING = "detaching"
	AWS_VOLUME_ATTACH_STATE_DETACHED  = "detached"
	AWS_VOLUME_ATTACH_STATE_BUSY      = "busy"

	RESOURCE_TYPE_VOLUME = "volume"
	VOLUME_TAG_DEFAULT   = "Name"
)
View Source
const (
	AWS_IMAGE_STATE_PENDING      = "pending"
	AWS_IMAGE_STATE_AVAILABLE    = "available"
	AWS_IMAGE_STATE_INVAILABLE   = "invalid"
	AWS_IMAGE_STATE_DEREGISTERED = "deregistered"
	AWS_IMAGE_STATE_TRANSIENT    = "transient"
	AWS_IMAGE_STATE_FAILED       = "failed"
	AWS_IMAGE_STATE_ERROR        = "error"

	RESOURCE_TYPE_MYIMAGE = "image"
	IMAGE_TAG_DEFAULT     = "Name"
	IMAGE_TAG_SOURCE_VM   = "CB-VMSNAPSHOT-SOURCEVM-ID"
)
View Source
const CBCloudInitFilePath string = "/cloud-driver-libs/.cloud-init-common/cloud-init"
View Source
const CBCloudInitWindowsFilePath string = "/cloud-driver-libs/.cloud-init-aws/cloud-init-windows" //Windows용 사용자 비번 설정을 위한 탬플릿
View Source
const CBDefaultCidrBlock string = "192.168.0.0/16" // CB Default CidrBlock
View Source
const CBDefaultSubnetName string = "CB-VNet-Subnet" // CB Default Subnet Name
View Source
const CBDefaultVNetName string = "CB-VNet" // CB Default Virtual Network Name
View Source
const CBDefaultVmUserName string = "cb-user" // default VM User Name
View Source
const CUSTOM_ERR_CODE_BAD_REQUEST string = "400" //awserr.New("400", "요청 정보가 잘 못 되었습니다.", nil)
View Source
const CUSTOM_ERR_CODE_METHOD_NOT_ALLOWED string = "405" //awserr.New("405", "지원되지 않는 기능입니다.", nil)
View Source
const CUSTOM_ERR_CODE_NOTFOUND string = "404" //awserr.New("404", "XXX 정보가 존재하지 않습니다.", nil)
View Source
const CUSTOM_ERR_CODE_NOT_IMPLEMENTED string = "501" //awserr.New("501", "기능이 구현되어 있지 않습니다.", nil)
View Source
const CUSTOM_ERR_CODE_TOOMANY string = "600" //awserr.New("600", "n개 이상의 xxxx 정보가 존재합니다.", nil)
View Source
const KEY_VALUE_CONVERT_DEBUG_INFO bool = false // JSON 및 Key Value객체 Convert시(ConvertToString, ConvertKeyValueList) Debug 로그 정보 출력 여부(Debug 모드로 개발 할 때 불필요한 정보를 줄이기 위해 추가)
View Source
const (
	NODEGROUP_TAG string = "nodegroup"
)

Variables

View Source
var VOLUME_TYPE = []string{"standard", "io1", "io2", "gp2", "gp3", "sc1", "st1"} // array 는 const 불가하여 변수로 처리.

Functions

func AttachVolume added in v0.6.7

func AttachVolume(svc *ec2.EC2, deviceName string, instanceId string, volumeId string) error

func Connect

func Connect(region string) *ec2.EC2

func ContainString added in v0.6.7

func ContainString(s []string, str string) bool

array에 주어진 string이 있는지 체크

func ConvertJsonString

func ConvertJsonString(v interface{}) (string, error)

Cloud Object를 JSON String 타입으로 변환

func ConvertJsonStringNoEscape added in v0.1.2

func ConvertJsonStringNoEscape(v interface{}) (string, error)

Cloud Object를 JSON String 타입으로 변환

func ConvertKeyValueList

func ConvertKeyValueList(v interface{}) ([]irs.KeyValue, error)

Cloud Object를 CB-KeyValue 형식으로 변환이 필요할 경우 이용

func ConvertToString

func ConvertToString(value interface{}) (string, error)

CB-KeyValue 등을 위해 String 타입으로 변환

func ConvertVMStatusString

func ConvertVMStatusString(vmStatus string) (irs.VMStatus, error)

func CreateHashString added in v0.3.8

func CreateHashString(credentialInfo idrv.CredentialInfo, Region idrv.RegionInfo) (string, error)

@TODO - PK 이슈 처리해야 함. (A User / B User / User 하위의 IAM 계정간의 호환성에 이슈가 없어야 하는데 현재는 안 됨.)

  • 따라서 AWS는 대안으로 KeyPair의 FingerPrint를 이용하도록 변경 - 필요시 리전및 키 이름과 혼용해서 만들어야할 듯.

KeyPair 해시 생성 함수 (PK 이슈로 현재는 사용하지 않음)

func DeleteDisk added in v0.7.0

func DeleteDisk(svc *ec2.EC2, disks []irs.IID) (bool, error)

func DescribeAvailabilityZones added in v0.7.6

func DescribeAvailabilityZones(client *ec2.EC2, AllRegionsBool bool) (*ec2.DescribeAvailabilityZonesOutput, error)

func DescribeAvailableDiskDeviceList added in v0.6.7

func DescribeAvailableDiskDeviceList(svc *ec2.EC2, vmIID irs.IID) ([]string, error)

1개 인스턴스에서 사용가능한 device 이름 목록 존재하는 device 이름 제거 후 가능한 목록만 return

func DescribeImageById added in v0.6.8

func DescribeImageById(svc *ec2.EC2, imageIID *irs.IID, owners []*string) (*ec2.Image, error)

func DescribeImages added in v0.6.8

func DescribeImages(svc *ec2.EC2, imageIIDs []*irs.IID, owners []*string) (*ec2.DescribeImagesOutput, error)

func DescribeInstanceById added in v0.6.7

func DescribeInstanceById(svc *ec2.EC2, vmIID irs.IID) (*ec2.Instance, error)

1개 인스턴스의 정보 조회

func DescribeInstanceDiskDeviceList added in v0.6.7

func DescribeInstanceDiskDeviceList(svc *ec2.EC2, vmIID irs.IID) ([]*ec2.InstanceBlockDeviceMapping, error)

1개 인스턴스에서 사용중인 disk 와 device 목록

func DescribeInstanceStatus added in v0.6.7

func DescribeInstanceStatus(svc *ec2.EC2, vmIID irs.IID) (string, error)

1개 인스턴스의 상태조회

func DescribeInstances added in v0.6.7

func DescribeInstances(svc *ec2.EC2, vmIIDs []irs.IID) (*ec2.DescribeInstancesOutput, error)

---------------- Instance Area begin ---------------//

Instance 정보조회.
기본은 목록 조회이며 filter조건이 있으면 해당 filter 조건으로 검색하도록

func DescribeRegions added in v0.7.6

func DescribeRegions(client *ec2.EC2, AllRegionsBool bool, regionName string) (*ec2.DescribeRegionsOutput, error)

---------------- RegionZone area begin ----------//

func DescribeVolumneById added in v0.6.7

func DescribeVolumneById(svc *ec2.EC2, volumeId string) (*ec2.Volume, error)

func DescribeVolumnes added in v0.6.7

func DescribeVolumnes(svc *ec2.EC2, volumeIdList []*string) (*ec2.DescribeVolumesOutput, error)

List 와 Get 이 같은 API 호출 filter 조건으로 VolumeId 를 넣도록하고 return은 그대로 DescribeVolumesOutput. Get에서는 1개만 들어있으므로 [0]번째 사용

각 항목을 irs.DiskInfo로 변환하는 convertVolumeInfoToDiskInfo 로 필요Data 생성

func DescribeVolumnesBySnapshot added in v0.7.0

func DescribeVolumnesBySnapshot(svc *ec2.EC2, snapShotIIDs []string) (*ec2.DescribeVolumesOutput, error)

func ExtractGpuInfo

func ExtractGpuInfo(gpuDeviceInfo *ec2.GpuDeviceInfo) irs.GpuInfo

func ExtractImageDescribeInfo

func ExtractImageDescribeInfo(image *ec2.Image) irs.ImageInfo

Image 정보를 추출함 @TODO : GuestOS 쳌크할 것

func ExtractIpPermissionCommon

func ExtractIpPermissionCommon(ip *ec2.IpPermission, securityRuleInfo *irs.SecurityRuleInfo)

IpPermission에서 공통정보 추출

func ExtractIpPermissions

func ExtractIpPermissions(ipPermissions []*ec2.IpPermission, direction string) []irs.SecurityRuleInfo

func ExtractKeyPairDescribeInfo

func ExtractKeyPairDescribeInfo(keyPair *ec2.KeyPairInfo) (irs.KeyPairInfo, error)

KeyPair 정보를 추출함

func ExtractSecurityInfo

func ExtractSecurityInfo(securityGroupResult *ec2.SecurityGroup) irs.SecurityInfo

func ExtractSubnetDescribeInfo

func ExtractSubnetDescribeInfo(subnetInfo *ec2.Subnet) irs.SubnetInfo

Subnet 정보를 추출함

func ExtractVMSpecInfo

func ExtractVMSpecInfo(Region string, instanceTypeInfo *ec2.InstanceTypeInfo) irs.VMSpecInfo

인스턴스 스펙 정보를 추출함

func ExtractVmName

func ExtractVmName(Tags []*ec2.Tag) string

func ExtractVpcDescribeInfo

func ExtractVpcDescribeInfo(vpcInfo *ec2.Vpc) irs.VPCInfo
type VPCInfo struct {
	IId   IID       // {NameId, SystemId}
	IPv4_CIDR string
	SubnetInfoList []SubnetInfo

	KeyValueList []KeyValue
}

VPC 정보를 추출함

func GetCBDefaultCidrBlock

func GetCBDefaultCidrBlock() string

func GetCBDefaultSubnetName

func GetCBDefaultSubnetName() string

Subnet

func GetCBDefaultVNetName

func GetCBDefaultVNetName() string

VPC

func GetCallLogScheme added in v0.7.3

func GetCallLogScheme(region idrv.RegionInfo, resourceType call.RES_TYPE, resourceName string, apiName string) call.CLOUDLOGSCHEMA

func GetDisksFromEc2Image added in v0.7.0

func GetDisksFromEc2Image(ec2Image *ec2.Image) ([]irs.IID, error)

이미지에서 루트 볼륨 외 disk ID들을 return

func GetImageSizeFromEc2Image added in v0.6.16

func GetImageSizeFromEc2Image(ec2Image *ec2.Image) (int64, error)

Image 정보에서 image size(GB) return

func GetOsTypeFromEc2Image added in v0.6.16

func GetOsTypeFromEc2Image(ec2Image *ec2.Image) string

Image 정보에서 osType return

func GetSnapshotIdFromEc2Image added in v0.6.16

func GetSnapshotIdFromEc2Image(ec2Image *ec2.Image) ([]string, error)

Image 정보에서 Snapshot Id return

func GetSnapshotIdFromEc2Image(ec2Image *ec2.Image) (string, error) {
	if !reflect.ValueOf(ec2Image.BlockDeviceMappings).IsNil() {
		if !reflect.ValueOf(ec2Image.BlockDeviceMappings[0].Ebs).IsNil() {
			snapshotId := *ec2Image.BlockDeviceMappings[0].Ebs.SnapshotId
			return snapshotId, nil
		} else {
			cblogger.Error("Ebs information not found in BlockDeviceMappings.")
			return "", errors.New("Ebs information not found in BlockDeviceMappings.")
		}
	} else {
		cblogger.Error("BlockDeviceMappings information not found.")
		return "", errors.New("BlockDeviceMappings information not found.")
	}
}

func GetZoneStatus added in v0.7.6

func GetZoneStatus(status string) irs.ZoneStatus

ZoneStatus 일반화

func InitLog added in v0.7.3

func InitLog()

func JSONMarshal added in v0.1.2

func JSONMarshal(t interface{}) ([]byte, error)

func LoggingError added in v0.7.3

func LoggingError(hiscallInfo call.CLOUDLOGSCHEMA, err error)

func LoggingInfo added in v0.7.3

func LoggingInfo(hiscallInfo call.CLOUDLOGSCHEMA, start time.Time)

func PrintToJson added in v0.7.3

func PrintToJson(class interface{})

toString 용

func SetNameTag

func SetNameTag(Client *ec2.EC2, Id string, value string) bool

Name Tag 설정

func WaitForRun

func WaitForRun(svc *ec2.EC2, instanceID string)

VM이 Running 상태일때까지 대기 함.

func WaitUntilVolumeAvailable added in v0.6.7

func WaitUntilVolumeAvailable(svc *ec2.EC2, volumeID string) error

---------------- VOLUME Area begin -----------------// WaitUntilVolumeAvailable

func WaitUntilVolumeDeleted added in v0.6.7

func WaitUntilVolumeDeleted(svc *ec2.EC2, volumeID string) error

WaitUntilVolumeDeleted

func WaitUntilVolumeInUse added in v0.6.7

func WaitUntilVolumeInUse(svc *ec2.EC2, volumeID string) error

WaitUntilVolumeInUse : attached

Types

type AwsAnyCallHandler added in v0.6.9

type AwsAnyCallHandler struct {
	Region         idrv.RegionInfo
	CredentialInfo idrv.CredentialInfo
	Client         *ec2.EC2
}

func (*AwsAnyCallHandler) AnyCall added in v0.6.9

func (anyCallHandler *AwsAnyCallHandler) AnyCall(callInfo irs.AnyCallInfo) (irs.AnyCallInfo, error)

*******************************************************

// call example
curl -sX POST http://localhost:1024/spider/anycall -H 'Content-Type: application/json' -d \
'{
        "ConnectionName" : "aws-ohio-config",
        "ReqInfo" : {
                "FID" : "createTags",
                "IKeyValueList" : [{"Key":"key1", "Value":"value1"}, {"Key":"key2", "Value":"value2"}]
        }
}' | json_pp

*******************************************************

type AwsCBNetworkInfo

type AwsCBNetworkInfo struct {
	VpcName   string
	VpcId     string
	CidrBlock string
	IsDefault bool
	State     string

	SubnetName string
	SubnetId   string
}

type AwsClusterHandler added in v0.7.3

type AwsClusterHandler struct {
	Region      idrv.RegionInfo
	Client      *eks.EKS
	Iam         *iam.IAM
	AutoScaling *autoscaling.AutoScaling
}

func (*AwsClusterHandler) AddNodeGroup added in v0.7.3

func (ClusterHandler *AwsClusterHandler) AddNodeGroup(clusterIID irs.IID, nodeGroupReqInfo irs.NodeGroupInfo) (irs.NodeGroupInfo, error)

Cluster.NetworkInfo 설정과 동일 서브넷으로 설정 NodeGroup 추가시에는 대상 Cluster 정보 획득하여 설정 NodeGroup에 다른 Subnet 설정이 꼭 필요시 추후 재논의 //https://github.com/cloud-barista/cb-spider/wiki/Provider-Managed-Kubernetes-and-Driver-API

func (*AwsClusterHandler) ChangeNodeGroupScaling added in v0.7.3

func (ClusterHandler *AwsClusterHandler) ChangeNodeGroupScaling(clusterIID irs.IID, nodeGroupIID irs.IID,
	DesiredNodeSize int, MinNodeSize int, MaxNodeSize int) (irs.NodeGroupInfo, error)

func (*AwsClusterHandler) CreateCluster added in v0.7.3

func (ClusterHandler *AwsClusterHandler) CreateCluster(clusterReqInfo irs.ClusterInfo) (irs.ClusterInfo, error)

------ Cluster Management

func (*AwsClusterHandler) DeleteCluster added in v0.7.3

func (ClusterHandler *AwsClusterHandler) DeleteCluster(clusterIID irs.IID) (bool, error)

func (*AwsClusterHandler) GetAutoScalingGroups added in v0.7.3

func (ClusterHandler *AwsClusterHandler) GetAutoScalingGroups(autoScalingGroupName string) ([]irs.IID, error)

func (*AwsClusterHandler) GetCluster added in v0.7.3

func (ClusterHandler *AwsClusterHandler) GetCluster(clusterIID irs.IID) (irs.ClusterInfo, error)

func (*AwsClusterHandler) GetNodeGroup added in v0.7.3

func (ClusterHandler *AwsClusterHandler) GetNodeGroup(clusterIID irs.IID, nodeGroupIID irs.IID) (irs.NodeGroupInfo, error)

func (*AwsClusterHandler) ListCluster added in v0.7.3

func (ClusterHandler *AwsClusterHandler) ListCluster() ([]*irs.ClusterInfo, error)

func (*AwsClusterHandler) ListNodeGroup added in v0.7.3

func (ClusterHandler *AwsClusterHandler) ListNodeGroup(clusterIID irs.IID) ([]*irs.NodeGroupInfo, error)

func (*AwsClusterHandler) RemoveNodeGroup added in v0.7.3

func (ClusterHandler *AwsClusterHandler) RemoveNodeGroup(clusterIID irs.IID, nodeGroupIID irs.IID) (bool, error)

func (*AwsClusterHandler) SetNodeGroupAutoScaling added in v0.7.3

func (ClusterHandler *AwsClusterHandler) SetNodeGroupAutoScaling(clusterIID irs.IID, nodeGroupIID irs.IID, on bool) (bool, error)

AutoScaling 이라는 별도의 메뉴가 있음.

func (*AwsClusterHandler) UpgradeCluster added in v0.7.3

func (ClusterHandler *AwsClusterHandler) UpgradeCluster(clusterIID irs.IID, newVersion string) (irs.ClusterInfo, error)

------ Upgrade K8S

func (*AwsClusterHandler) WaitUntilClusterActive added in v0.7.3

func (ClusterHandler *AwsClusterHandler) WaitUntilClusterActive(clusterName string) error

Cluster가 Activty 상태일때까지 대기함.

func (*AwsClusterHandler) WaitUntilNodegroupActive added in v0.7.3

func (ClusterHandler *AwsClusterHandler) WaitUntilNodegroupActive(clusterName string, nodegroupName string) error

Nodegroup이 Activty 상태일때까지 대기함.

type AwsDiskHandler added in v0.6.7

type AwsDiskHandler struct {
	Region idrv.RegionInfo
	Client *ec2.EC2
}

func (*AwsDiskHandler) AttachDisk added in v0.6.7

func (DiskHandler *AwsDiskHandler) AttachDisk(diskIID irs.IID, ownerVM irs.IID) (irs.DiskInfo, error)

EBS multi-attach does not support XFS, EXT2, EXT4, and NTFS file systems. It supports only cluster-aware file systems.

Linux용 권장 디바이스 이름: 루트 볼륨의 경우 /dev/sda1, 데이터 볼륨의 경우 /dev/sd[f-p]. Windows용 권장 디바이스 이름: 루트 볼륨의 경우 /dev/sda1, 데이터 볼륨의 경우 xvd[f-p]. max은 아직 권장 디바이스 이름 없고 Linux용 이름 사용

//device := vmInfo.VMBlockDisk // "/dev/sda1"  이미 있는 이름. rootdisk에서 사용
//device := "/dev/sdf" [f ~ p] 사이의 값
//device := "/dev/sdf/aa/" // invalid

func (*AwsDiskHandler) ChangeDiskSize added in v0.6.7

func (DiskHandler *AwsDiskHandler) ChangeDiskSize(diskIID irs.IID, size string) (bool, error)
	IOPS : Default: The existing value is retained if you keep the same volume type.
		If you change the volume type to io1, io2, or gp3, the default is 3,000.
    //    * gp2 and gp3: 1-16,384
    //
    //    * io1 and io2: 4-16,384
    //
    //    * st1 and sc1: 125-16,384
    //
    //    * standard: 1-1,024
	Size *int64 `type:"integer"`

func (*AwsDiskHandler) CreateDisk added in v0.6.7

func (DiskHandler *AwsDiskHandler) CreateDisk(diskReqInfo irs.DiskInfo) (irs.DiskInfo, error)

Spider 의 Disk = AWS 의 Volume

disk type에 따라 달라짐 - 빈 disk - snapshot에서 가져오는 경우 - 암호화 된 disk

func (*AwsDiskHandler) DeleteDisk added in v0.6.7

func (DiskHandler *AwsDiskHandler) DeleteDisk(diskIID irs.IID) (bool, error)

func (*AwsDiskHandler) DetachDisk added in v0.6.7

func (DiskHandler *AwsDiskHandler) DetachDisk(diskIID irs.IID, ownerVM irs.IID) (bool, error)

func (*AwsDiskHandler) GetDisk added in v0.6.7

func (DiskHandler *AwsDiskHandler) GetDisk(diskIID irs.IID) (irs.DiskInfo, error)

ListDisk와 처리로직 동일 but, volumeID 로 호출하므로 1개만 return.

func (*AwsDiskHandler) ListDisk added in v0.6.7

func (DiskHandler *AwsDiskHandler) ListDisk() ([]*irs.DiskInfo, error)

GetDisk와 ListDisk 처리로직 동일하므로 DescribeVolumes 호출. 단, IDList를 nil로 set.

type AwsImageHandler

type AwsImageHandler struct {
	Region idrv.RegionInfo
	Client *ec2.EC2
}

func (*AwsImageHandler) CheckWindowsImage added in v0.6.15

func (imageHandler *AwsImageHandler) CheckWindowsImage(imageIID irs.IID) (bool, error)

windows os 여부 return

func (*AwsImageHandler) CreateImage

func (imageHandler *AwsImageHandler) CreateImage(imageReqInfo irs.ImageReqInfo) (irs.ImageInfo, error)

@TODO : 작업해야 함.

func (*AwsImageHandler) DeleteImage

func (imageHandler *AwsImageHandler) DeleteImage(imageIID irs.IID) (bool, error)

@TODO : 삭제 API 찾아야 함.

func (*AwsImageHandler) GetAmiImage added in v0.6.15

func (imageHandler *AwsImageHandler) GetAmiImage(imageIID irs.IID) (*ec2.Image, error)

func (*AwsImageHandler) GetImage

func (imageHandler *AwsImageHandler) GetImage(imageIID irs.IID) (irs.ImageInfo, error)

func (imageHandler *AwsImageHandler) GetImage(imageID string) (irs.ImageInfo, error) {

func (*AwsImageHandler) ListImage

func (imageHandler *AwsImageHandler) ListImage() ([]*irs.ImageInfo, error)

@TODO : 목록이 너무 많기 때문에 amazon 계정으로 공유된 퍼블릭 이미지중 AMI만 조회 함. 20210607 - Tumblebug에서 필터할 수 있도록 state는 모든 이미지를 대상으로 하며, 이미지가 너무 많기 때문에 AWS 소유의 이미지만 제공 함.

type AwsKeyPairHandler

type AwsKeyPairHandler struct {
	CredentialInfo idrv.CredentialInfo
	Region         idrv.RegionInfo
	Client         *ec2.EC2
}

func (*AwsKeyPairHandler) CheckKeyPairFolder added in v0.3.8

func (keyPairHandler *AwsKeyPairHandler) CheckKeyPairFolder(keyPairPath string) error

================================= 공개 키 변환 및 키 정보 로컬 보관 로직 추가 =================================

func (*AwsKeyPairHandler) CreateKey

func (keyPairHandler *AwsKeyPairHandler) CreateKey(keyPairReqInfo irs.KeyPairReqInfo) (irs.KeyPairInfo, error)

2021-10-26 이슈#480에 의해 Local Key 로직 제거

func (*AwsKeyPairHandler) DeleteKey

func (keyPairHandler *AwsKeyPairHandler) DeleteKey(keyIID irs.IID) (bool, error)

2021-10-26 이슈#480에 의해 Local Key 로직 제거

func (*AwsKeyPairHandler) GetKey

func (keyPairHandler *AwsKeyPairHandler) GetKey(keyIID irs.IID) (irs.KeyPairInfo, error)

2021-10-26 이슈#480에 의해 Local Key 로직 제거 혼선을 피하기 위해 keyPairID 대신 keyName으로 변경 함.

func (*AwsKeyPairHandler) ListKey

func (keyPairHandler *AwsKeyPairHandler) ListKey() ([]*irs.KeyPairInfo, error)

type AwsMyImageHandler added in v0.6.8

type AwsMyImageHandler struct {
	Region idrv.RegionInfo
	Client *ec2.EC2
}

https://docs.aws.amazon.com/sdk-for-go/api/service/ec2/#EC2.CreateImage Snapshot은 현재 운영 중인 자원의 상태를 저장한 후 필요 시에 동일한 상태로 복제하여 재 생산할 수 있는 기능을 말한다. Snapshot은 VM의 상태를 저장해주는 VM Snapshot과 Disk(Volume)의 상태를 저장해주는 Disk Snapshot이 존재한다. CB-Spider MyImage 관리 기능은 VM Snapshot 실행과 결과로 생성된 VM Image(MyImage)를 관리하는 기능을 제공한다 CB-Spider VM Snapshot은 운영 중인 VM의 상태와 VM에 Attach된 Data-Disk의 상태도 저장된다.

func (*AwsMyImageHandler) CheckWindowsImage added in v0.6.15

func (ImageHandler *AwsMyImageHandler) CheckWindowsImage(myImageIID irs.IID) (bool, error)

func (*AwsMyImageHandler) DeleteMyImage added in v0.6.8

func (ImageHandler *AwsMyImageHandler) DeleteMyImage(myImageIID irs.IID) (bool, error)

func (*AwsMyImageHandler) DeleteSnapshotById added in v0.7.0

func (MyImageHandler *AwsMyImageHandler) DeleteSnapshotById(snapshotId string) (bool, error)

Image에 대한 snap 삭제

func (*AwsMyImageHandler) GetMyImage added in v0.6.8

func (ImageHandler *AwsMyImageHandler) GetMyImage(myImageIID irs.IID) (irs.MyImageInfo, error)

func (*AwsMyImageHandler) ListMyImage added in v0.6.8

func (ImageHandler *AwsMyImageHandler) ListMyImage() ([]*irs.MyImageInfo, error)

func (*AwsMyImageHandler) SnapshotVM added in v0.6.8

func (ImageHandler *AwsMyImageHandler) SnapshotVM(snapshotReqInfo irs.MyImageInfo) (irs.MyImageInfo, error)

type AwsNLBHandler added in v0.5.10

type AwsNLBHandler struct {
	Region idrv.RegionInfo
	//Client *elb.ELB
	Client   *elbv2.ELBV2 //elbV2
	VMClient *ec2.EC2
}

func (*AwsNLBHandler) AddVMs added in v0.5.10

func (NLBHandler *AwsNLBHandler) AddVMs(nlbIID irs.IID, vmIIDs *[]irs.IID) (irs.VMGroupInfo, error)

@TODO : VM 추가 시 NLB에 등록되지 않은 서브넷의 경우 추가 및 검증 로직 필요 @TODO : 이미 등록된 AZ의 다른 서브넷을 사용하는 Instance 처리 필요

func (*AwsNLBHandler) ChangeHealthCheckerInfo added in v0.5.10

func (NLBHandler *AwsNLBHandler) ChangeHealthCheckerInfo(nlbIID irs.IID, healthChecker irs.HealthCheckerInfo) (irs.HealthCheckerInfo, error)

func (*AwsNLBHandler) ChangeListener added in v0.5.10

func (NLBHandler *AwsNLBHandler) ChangeListener(nlbIID irs.IID, listener irs.ListenerInfo) (irs.ListenerInfo, error)

------ Frontend Control Protocol 하고 Port 정보만 변경 가능

func (*AwsNLBHandler) ChangeVMGroupInfo added in v0.5.10

func (NLBHandler *AwsNLBHandler) ChangeVMGroupInfo(nlbIID irs.IID, vmGroup irs.VMGroupInfo) (irs.VMGroupInfo, error)

------ Backend Control

func (*AwsNLBHandler) CheckCreateValidation added in v0.5.10

func (NLBHandler *AwsNLBHandler) CheckCreateValidation(nlbReqInfo irs.NLBInfo) error

&elbv2.CreateTargetGroupInput

func (*AwsNLBHandler) CheckHealthCheckerValidation added in v0.5.10

func (NLBHandler *AwsNLBHandler) CheckHealthCheckerValidation(reqHealthCheckerInfo irs.HealthCheckerInfo) error

func (*AwsNLBHandler) CreateListener added in v0.5.10

func (NLBHandler *AwsNLBHandler) CreateListener(nlbReqInfo irs.NLBInfo) (*elbv2.CreateListenerOutput, error)

func (*AwsNLBHandler) CreateNLB added in v0.5.10

func (NLBHandler *AwsNLBHandler) CreateNLB(nlbReqInfo irs.NLBInfo) (irs.NLBInfo, error)

------ NLB Management

func (*AwsNLBHandler) CreateTargetGroup added in v0.5.10

func (NLBHandler *AwsNLBHandler) CreateTargetGroup(nlbReqInfo irs.NLBInfo) (*elbv2.CreateTargetGroupOutput, error)

func (*AwsNLBHandler) DeleteListener added in v0.5.10

func (NLBHandler *AwsNLBHandler) DeleteListener(listenerArn *string) (bool, error)

func (*AwsNLBHandler) DeleteNLB added in v0.5.10

func (NLBHandler *AwsNLBHandler) DeleteNLB(nlbIID irs.IID) (bool, error)

@TODO : 상황봐서 TargetGroup과 Listener 삭제 시 발생하는 오류는 무시하고 NLB 삭제까지 진행할 것

func (*AwsNLBHandler) DeleteTargetGroup added in v0.5.10

func (NLBHandler *AwsNLBHandler) DeleteTargetGroup(targetGroupArn *string) (bool, error)

func (*AwsNLBHandler) ExtractHealthCheckerInfo added in v0.5.10

func (NLBHandler *AwsNLBHandler) ExtractHealthCheckerInfo(targetGroupArn string) ([]*elbv2.TargetHealthDescription, error)

타겟 그룹에 있는 인스턴스들의 헬스 상태 목록 조회 - 현재 바리스타에서 미사용 "인스턴스 / 포트 / 헬스 상태"의 배열

func (*AwsNLBHandler) ExtractListenerInfo added in v0.5.10

func (NLBHandler *AwsNLBHandler) ExtractListenerInfo(nlbIID irs.IID) (irs.ListenerInfo, error)

func (*AwsNLBHandler) ExtractNLBInfo added in v0.5.10

func (NLBHandler *AwsNLBHandler) ExtractNLBInfo(nlbResInfo *elbv2.LoadBalancer) (irs.NLBInfo, error)

func (*AwsNLBHandler) ExtractNlbSubnets added in v0.5.10

func (NLBHandler *AwsNLBHandler) ExtractNlbSubnets(vpcId string) ([]*string, error)

NLB에서 사용할 서브넷 정보를 추출함.

func (*AwsNLBHandler) ExtractVMGroupHealthInfo added in v0.5.10

func (NLBHandler *AwsNLBHandler) ExtractVMGroupHealthInfo(targetGroupArn string) (irs.HealthInfo, error)

ExtractVMGroupInfo에서 GetVMGroupHealthInfo를 호출하는 형태로 사용되면 발생할 무한 루프 방지를 위해 별도의 함수로 분리 함. https://docs.aws.amazon.com/elasticloadbalancing/latest/APIReference/API_TargetHealth.html

func (*AwsNLBHandler) ExtractVMGroupInfo added in v0.5.10

func (NLBHandler *AwsNLBHandler) ExtractVMGroupInfo(nlbIID irs.IID) (TargetGroupInfo, error)

func (*AwsNLBHandler) ExtractVmSubnets added in v0.5.10

func (NLBHandler *AwsNLBHandler) ExtractVmSubnets(VMs *[]irs.IID) ([]*string, error)

NLB는 AZ별 1개의 서브넷만 선택 가능한데 NLB 생성 요청 정보에는 Subnet 정보가 없어서 성능을 위해 가급적 등록할 VM이 속한 AZ별 Subnet을 추출하려 했으나... NLB에 VM을 추가하는 AddVMS 처리시에 등록되지 않은 AZ를 추가로 처리해야 하기 때문에 현재는 이 함수의 로직을 잠시 보류하고... NLB 생성시 전달 받은 VPC에 존재하는 AZ별 서브넷 1개를 랜덤으로 선택하는 방안으로 대체함.(ExtractNlbSubnets)

성능 등을 감안할 때 ExtractVmSubnets 방식이 좋을 수 있기에 현재 로직은 보관해 놓지만... AZ 정보를 조회하는 로직은 아직 구현하지 않은 상태라서 선택된 전체 VM중 1개의 Subnet만 선택되기에 바로 사용하면 안 됨.

TODO : 서브넷의 AZ 이름을 조회해서 "az" KEY대신 실제 AZ 이름으로 처리해야 함. / 필요한 경우 VM정보 조회 시 페이징 로직도 구현해야 함.

func (*AwsNLBHandler) GetNLB added in v0.5.10

func (NLBHandler *AwsNLBHandler) GetNLB(nlbIID irs.IID) (irs.NLBInfo, error)

func (*AwsNLBHandler) GetVMGroupHealthInfo added in v0.5.10

func (NLBHandler *AwsNLBHandler) GetVMGroupHealthInfo(nlbIID irs.IID) (irs.HealthInfo, error)

@TODO : 5가지의 상태(Healthy / Unhealthy / Unused / Initial / Draining)가 존재 하기 때문에 리턴 객체에 담을 Unhealthy의 범위 확정이 필요 함.

func (*AwsNLBHandler) IsExistNLB added in v0.5.11

func (NLBHandler *AwsNLBHandler) IsExistNLB(nlbName string) (bool, error)

NLB 생성전에 NLB가 이미 존재하는지 체크 함.

func (*AwsNLBHandler) ListNLB added in v0.5.10

func (NLBHandler *AwsNLBHandler) ListNLB() ([]*irs.NLBInfo, error)

func (*AwsNLBHandler) RemoveVMs added in v0.5.10

func (NLBHandler *AwsNLBHandler) RemoveVMs(nlbIID irs.IID, vmIIDs *[]irs.IID) (bool, error)

type AwsRegionZoneHandler added in v0.7.6

type AwsRegionZoneHandler struct {
	Region idrv.RegionInfo
	Client *ec2.EC2
}

func (*AwsRegionZoneHandler) GetRegionZone added in v0.7.6

func (regionZoneHandler *AwsRegionZoneHandler) GetRegionZone(Name string) (irs.RegionZoneInfo, error)

func (*AwsRegionZoneHandler) ListOrgRegion added in v0.7.6

func (regionZoneHandler *AwsRegionZoneHandler) ListOrgRegion() (string, error)

func (*AwsRegionZoneHandler) ListOrgZone added in v0.7.6

func (regionZoneHandler *AwsRegionZoneHandler) ListOrgZone() (string, error)

func (*AwsRegionZoneHandler) ListRegionZone added in v0.7.6

func (regionZoneHandler *AwsRegionZoneHandler) ListRegionZone() ([]*irs.RegionZoneInfo, error)

type AwsSecurityHandler

type AwsSecurityHandler struct {
	Region idrv.RegionInfo
	Client *ec2.EC2
}

func (*AwsSecurityHandler) AddRules added in v0.5.4

func (securityHandler *AwsSecurityHandler) AddRules(sgIID irs.IID, securityRules *[]irs.SecurityRuleInfo) (irs.SecurityInfo, error)

func (*AwsSecurityHandler) CreateSecurity

func (securityHandler *AwsSecurityHandler) CreateSecurity(securityReqInfo irs.SecurityReqInfo) (irs.SecurityInfo, error)

2019-11-16부로 CB-Driver 전체 로직이 NameId 기반으로 변경됨. (보안 그룹은 그룹명으로 처리 가능하기 때문에 Name 태깅시 에러는 무시함) @TODO : 존재하는 보안 그룹에 정책 추가하는 기능 필요 VPC 생략 시 활성화된 세션의 기본 VPC를 이용 함.

func (*AwsSecurityHandler) DeleteSecurity

func (securityHandler *AwsSecurityHandler) DeleteSecurity(securityIID irs.IID) (bool, error)

2019-11-16부로 CB-Driver 전체 로직이 NameId 기반으로 변경됨. func (securityHandler *AwsSecurityHandler) DeleteSecurity(securityNameId string) (bool, error) {

func (*AwsSecurityHandler) GetSecurity

func (securityHandler *AwsSecurityHandler) GetSecurity(securityIID irs.IID) (irs.SecurityInfo, error)

2019-11-16부로 CB-Driver 전체 로직이 NameId 기반으로 변경됨. func (securityHandler *AwsSecurityHandler) GetSecurity(securityNameId string) (irs.SecurityInfo, error) {

func (*AwsSecurityHandler) ListSecurity

func (securityHandler *AwsSecurityHandler) ListSecurity() ([]*irs.SecurityInfo, error)

func (*AwsSecurityHandler) ProcessAddRules added in v0.5.5

func (securityHandler *AwsSecurityHandler) ProcessAddRules(newGroupId *string, securityRules *[]irs.SecurityRuleInfo) (irs.SecurityInfo, error)

func (*AwsSecurityHandler) ProcessRemoveRules added in v0.5.5

func (securityHandler *AwsSecurityHandler) ProcessRemoveRules(newGroupId *string, securityRules *[]irs.SecurityRuleInfo) (irs.SecurityInfo, error)

func (*AwsSecurityHandler) RemoveRules added in v0.5.4

func (securityHandler *AwsSecurityHandler) RemoveRules(sgIID irs.IID, securityRules *[]irs.SecurityRuleInfo) (bool, error)

type AwsVMHandler

type AwsVMHandler struct {
	Region idrv.RegionInfo
	Client *ec2.EC2
}

func (*AwsVMHandler) AssociatePublicIP

func (vmHandler *AwsVMHandler) AssociatePublicIP(allocationId string, instanceId string) (bool, error)

AssociationId 대신 PublicIP로도 가능 함.

func (*AwsVMHandler) AttachNetworkInterface

func (vmHandler *AwsVMHandler) AttachNetworkInterface(vNicId string, instanceId string) (bool, error)

전달 받은 vNic을 VM에 추가함.

func (*AwsVMHandler) ExtractDescribeInstanceToVmInfo added in v0.6.7

func (vmHandler *AwsVMHandler) ExtractDescribeInstanceToVmInfo(instance *ec2.Instance) irs.VMInfo

func (*AwsVMHandler) ExtractDescribeInstances

func (vmHandler *AwsVMHandler) ExtractDescribeInstances(reservation *ec2.Reservation) irs.VMInfo

DescribeInstances결과에서 EC2 세부 정보 추출 VM 생성 시에는 Running 이전 상태의 정보가 넘어오기 때문에 최종 정보 기반으로 리턴 받고 싶으면 GetVM에 통합해야 할 듯.

func (*AwsVMHandler) GetAmiDiskInfo added in v0.6.7

func (vmHandler *AwsVMHandler) GetAmiDiskInfo(ImageSystemId string) (int64, error)

VM생성 시 사용할 루트 디스크의 최소 볼륨 사이즈 정보를 조회함 -1 : 정보 조회 실패

func (*AwsVMHandler) GetPasswordData added in v0.6.15

func (vmHandler *AwsVMHandler) GetPasswordData(vmIID irs.IID) (string, error)

https://docs.aws.amazon.com/ko_kr/AWSEC2/latest/APIReference/API_GetPasswordData.html https://awscli.amazonaws.com/v2/documentation/api/latest/reference/ec2/get-password-data.html @TODO : ssh key를 이용해서 암호가 해독된 Password를 조회해야 함.

func (*AwsVMHandler) GetVM

func (vmHandler *AwsVMHandler) GetVM(vmIID irs.IID) (irs.VMInfo, error)

2019-11-16부로 CB-Driver 전체 로직이 NameId 기반으로 변경됨. func (vmHandler *AwsVMHandler) GetVM(vmNameId string) (irs.VMInfo, error) {

func (*AwsVMHandler) GetVMStatus

func (vmHandler *AwsVMHandler) GetVMStatus(vmIID irs.IID) (irs.VMStatus, error)

SHUTTING-DOWN / TERMINATED func (vmHandler *AwsVMHandler) GetVMStatus(vmNameId string) (irs.VMStatus, error) {

func (*AwsVMHandler) GetVolumInfo added in v0.5.1

func (vmHandler *AwsVMHandler) GetVolumInfo(volumeId string) (*ec2.Volume, error)

볼륨 정보 조회

func (*AwsVMHandler) ListVM

func (vmHandler *AwsVMHandler) ListVM() ([]*irs.VMInfo, error)

func (*AwsVMHandler) ListVMStatus

func (vmHandler *AwsVMHandler) ListVMStatus() ([]*irs.VMStatusInfo, error)

func (*AwsVMHandler) RebootVM

func (vmHandler *AwsVMHandler) RebootVM(vmIID irs.IID) (irs.VMStatus, error)

func (vmHandler *AwsVMHandler) RebootVM(vmNameId string) (irs.VMStatus, error) {

func (*AwsVMHandler) ResumeVM

func (vmHandler *AwsVMHandler) ResumeVM(vmIID irs.IID) (irs.VMStatus, error)

func (vmHandler *AwsVMHandler) ResumeVM(vmNameId string) (irs.VMStatus, error) {

func (*AwsVMHandler) StartVM

func (vmHandler *AwsVMHandler) StartVM(vmReqInfo irs.VMReqInfo) (irs.VMInfo, error)

1개의 VM만 생성되도록 수정 (MinCount / MaxCount 이용 안 함) 키페어 이름(예:mcloud-barista)은 아래 URL에 나오는 목록 중 "키페어 이름"의 값을 적으면 됨. https://ap-northeast-2.console.aws.amazon.com/ec2/v2/home?region=ap-northeast-2#KeyPairs:sort=keyName

func (*AwsVMHandler) SuspendVM

func (vmHandler *AwsVMHandler) SuspendVM(vmIID irs.IID) (irs.VMStatus, error)

func (vmHandler *AwsVMHandler) SuspendVM(vmNameId string) (irs.VMStatus, error) {

func (*AwsVMHandler) TerminateVM

func (vmHandler *AwsVMHandler) TerminateVM(vmIID irs.IID) (irs.VMStatus, error)

func (vmHandler *AwsVMHandler) TerminateVM(vmNameId string) (irs.VMStatus, error) {

type AwsVPCHandler added in v0.1.3

type AwsVPCHandler struct {
	Region idrv.RegionInfo
	Client *ec2.EC2
}

func (*AwsVPCHandler) AddSubnet added in v0.2.1

func (VPCHandler *AwsVPCHandler) AddSubnet(vpcIID irs.IID, subnetInfo irs.SubnetInfo) (irs.VPCInfo, error)

func (*AwsVPCHandler) AssociateRouteTable added in v0.1.3

func (VPCHandler *AwsVPCHandler) AssociateRouteTable(vpcId string, subnetId string) error

VPC의 라우팅 테이블에 생성된 Subnet을 연결 함.

func (*AwsVPCHandler) CreateRouteIGW added in v0.1.3

func (VPCHandler *AwsVPCHandler) CreateRouteIGW(vpcId string, igwId string) error

생성된 VPC의 라우팅 테이블에 IGW(Internet Gateway) 라우팅 정보를 생성함 (AWS 콘솔의 라우팅 테이블의 [라우팅] Tab 처리)

func (*AwsVPCHandler) CreateSubnet added in v0.1.3

func (VPCHandler *AwsVPCHandler) CreateSubnet(vpcId string, reqSubnetInfo irs.SubnetInfo) (irs.SubnetInfo, error)

func (*AwsVPCHandler) CreateVPC added in v0.1.3

func (VPCHandler *AwsVPCHandler) CreateVPC(vpcReqInfo irs.VPCReqInfo) (irs.VPCInfo, error)

func (*AwsVPCHandler) DeleteAllIGW added in v0.1.3

func (VPCHandler *AwsVPCHandler) DeleteAllIGW(vpcId string) error

VPC에 연결된 모든 IGW를 삭제함.

func (*AwsVPCHandler) DeleteIGW added in v0.1.3

func (VPCHandler *AwsVPCHandler) DeleteIGW(igwId string) error

IGW를 삭제 함.

func (*AwsVPCHandler) DeleteRouteIGW added in v0.1.3

func (VPCHandler *AwsVPCHandler) DeleteRouteIGW(vpcId string) error

VPC에 설정된 0.0.0.0/0 라우터를 제거 함. #255예외 처리 보완에 따른 라우팅 정보 삭제전 0.0.0.0 조회후 삭제하도록 로직 변경

func (*AwsVPCHandler) DeleteSubnet added in v0.1.3

func (VPCHandler *AwsVPCHandler) DeleteSubnet(subnetIID irs.IID) (bool, error)

func (*AwsVPCHandler) DeleteVPC added in v0.1.3

func (VPCHandler *AwsVPCHandler) DeleteVPC(vpcIID irs.IID) (bool, error)

func (*AwsVPCHandler) DetachInternetGateway added in v0.1.3

func (VPCHandler *AwsVPCHandler) DetachInternetGateway(vpcId string, igwId string) error

VPC에 연결된 IGW의 연결을 해제함.

func (*AwsVPCHandler) GetDefaultRouteTable added in v0.1.3

func (VPCHandler *AwsVPCHandler) GetDefaultRouteTable(vpcId string) (string, error)

https://docs.aws.amazon.com/ko_kr/vpc/latest/userguide/VPC_Route_Tables.html https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeRouteTables.html 자동 생성된 VPC의 기본 라우팅 테이블 정보를 찾음

func (*AwsVPCHandler) GetSubnet added in v0.1.3

func (VPCHandler *AwsVPCHandler) GetSubnet(reqSubnetId string) (irs.SubnetInfo, error)

func (*AwsVPCHandler) GetVPC added in v0.1.3

func (VPCHandler *AwsVPCHandler) GetVPC(vpcIID irs.IID) (irs.VPCInfo, error)

func (*AwsVPCHandler) ListSubnet added in v0.1.3

func (VPCHandler *AwsVPCHandler) ListSubnet(vpcId string) ([]irs.SubnetInfo, error)

VPC의 하위 서브넷 목록을 조회함.

func (*AwsVPCHandler) ListVPC added in v0.1.3

func (VPCHandler *AwsVPCHandler) ListVPC() ([]*irs.VPCInfo, error)

func (*AwsVPCHandler) RemoveSubnet added in v0.2.1

func (VPCHandler *AwsVPCHandler) RemoveSubnet(vpcIID irs.IID, subnetIID irs.IID) (bool, error)

type AwsVmSpecHandler

type AwsVmSpecHandler struct {
	Region idrv.RegionInfo
	Client *ec2.EC2
}

https://docs.aws.amazon.com/sdk-for-go/api/service/ec2/#EC2.DescribeInstanceTypes

func (*AwsVmSpecHandler) GetOrgVMSpec

func (vmSpecHandler *AwsVmSpecHandler) GetOrgVMSpec(Name string) (string, error)

AWS의 정보 그대로를 가공 없이 JSON으로 리턴 함.

func (*AwsVmSpecHandler) GetVMSpec

func (vmSpecHandler *AwsVmSpecHandler) GetVMSpec(Name string) (irs.VMSpecInfo, error)

func (*AwsVmSpecHandler) ListOrgVMSpec

func (vmSpecHandler *AwsVmSpecHandler) ListOrgVMSpec() (string, error)

AWS의 정보 그대로를 가공 없이 JSON으로 리턴 함.

func (*AwsVmSpecHandler) ListOrgVMSpecOld added in v0.2.1

func (vmSpecHandler *AwsVmSpecHandler) ListOrgVMSpecOld() (string, error)

AWS의 정보 그대로를 가공 없이 JSON으로 리턴 함.

func (*AwsVmSpecHandler) ListVMSpec

func (vmSpecHandler *AwsVmSpecHandler) ListVMSpec() ([]*irs.VMSpecInfo, error)

func (*AwsVmSpecHandler) ListVMSpecAZ added in v0.2.1

func (vmSpecHandler *AwsVmSpecHandler) ListVMSpecAZ(ZoneName string) (map[string]string, error)

해당 Zone의 스펙 ID 목록을 조회함.

type TargetGroupInfo added in v0.5.10

type TargetGroupInfo struct {
	VMGroup       irs.VMGroupInfo
	HealthChecker irs.HealthCheckerInfo
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL