Skip to content

Commit

Permalink
gh-681: initial support for inherting subnet,interfaces and attachmen…
Browse files Browse the repository at this point in the history
…ts after AWS inter-AZ HA
  • Loading branch information
TrekkieCoder committed May 27, 2024
1 parent a836c19 commit 299465d
Show file tree
Hide file tree
Showing 4 changed files with 154 additions and 4 deletions.
3 changes: 2 additions & 1 deletion api/restapi/server.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions options/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ var Opts struct {
NoNlp bool `short:"n" long:"nonlp" description:"Do not register with nlp"`
Host string `long:"host" description:"the IP to listen on" default:"0.0.0.0" env:"HOST"`
Port int `long:"port" description:"the port to listen on for insecure connections" default:"11111" env:"PORT"`
TLS bool `long:"tls" description:"enable TLS " env:"TLS"`
TLSHost string `long:"tls-host" description:"the IP to listen on for tls, when not specified it's the same as --host" env:"TLS_HOST"`
TLSPort int `long:"tls-port" description:"the port to listen on for secure connections" default:"8091" env:"TLS_PORT"`
TLSCertificate flags.Filename `long:"tls-certificate" description:"the certificate to use for secure connections" default:"/opt/loxilb/cert/server.crt" env:"TLS_CERTIFICATE"`
Expand Down
4 changes: 2 additions & 2 deletions pkg/loxinet/rules.go
Original file line number Diff line number Diff line change
Expand Up @@ -1533,7 +1533,7 @@ func (R *RuleH) DeleteNatLbRule(serv cmn.LbServiceArg) (int, error) {
if utils.IsIPHostAddr(sNetAddr.IP.String()) {
loxinlp.DelAddrNoHook(sNetAddr.IP.String()+"/32", "lo")
if mh.cloudLabel == "aws" {
err := AWSUpdatePrivateIp(sNetAddr.IP, false)
err := AWSUpdatePrivateIP(sNetAddr.IP, false)
if err != nil {
tk.LogIt(tk.LogError, "aws lb-rule vip %s delete failed. err: %v\n", sNetAddr.IP.String(), err)
}
Expand Down Expand Up @@ -2643,7 +2643,7 @@ func (R *RuleH) AdvRuleVIPIfL2(IP net.IP) error {
if ev == 0 {
if !utils.IsIPHostAddr(IP.String()) {
if mh.cloudLabel == "aws" {
err := AWSUpdatePrivateIp(IP, true)
err := AWSUpdatePrivateIP(IP, true)
if err != nil {
tk.LogIt(tk.LogError, "aws lb-rule vip %s add failed. err: %v\n", IP.String(), err)
return err
Expand Down
150 changes: 149 additions & 1 deletion pkg/loxinet/utils_aws.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,154 @@ func AWSGetInstanceIDInfo() (string, error) {
return string(instanceID), nil
}

func AWSGetInstanceVPCInfo() (string, error) {
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(time.Second*2))
defer cancel()
resp, err := imdsClient.GetMetadata(ctx, &imds.GetMetadataInput{
Path: "mac",
})
if err != nil {
return "", err
}

mac, err := io.ReadAll(resp.Content)
if err != nil {
return "", err
}

vpcPath := fmt.Sprintf("network/interfaces/macs/%s/vpc-id", string(mac))
resp2, err := imdsClient.GetMetadata(ctx, &imds.GetMetadataInput{
Path: vpcPath,
})
if err != nil {
return "", err
}
vpc, err := io.ReadAll(resp2.Content)
if err != nil {
return "", err
}

return string(vpc), nil
}

func AWSGetInstanceAvailabilityZone() (string, error) {
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(time.Second*2))
defer cancel()
resp, err := imdsClient.GetMetadata(ctx, &imds.GetMetadataInput{
Path: "placement/availability-zone",
})
if err != nil {
return "", err
}

az, err := io.ReadAll(resp.Content)
if err != nil {
return "", err
}

return string(az), nil
}

func AWSPrepVIPNetwork() error {
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(time.Second*5))
defer cancel()

filterStr := "tag:loxiType"
output, err := ec2Client.DescribeNetworkInterfaces(ctx, &ec2.DescribeNetworkInterfacesInput{
Filters: []types.Filter{
{Name: &filterStr, Values: []string{"loxilb-eni"}},
},
})
if err != nil {
fmt.Printf("no loxiType intf found \n")
return err
}

subnets := []string{}
for _, intf := range output.NetworkInterfaces {
subnets = append(subnets, *intf.SubnetId)
_, err := ec2Client.DeleteNetworkInterface(ctx, &ec2.DeleteNetworkInterfaceInput{NetworkInterfaceId: intf.NetworkInterfaceId})
if err != nil {
fmt.Printf("failed to delete intf (%s)\n", *intf.NetworkInterfaceId)
return err
}
}

for _, subnet := range subnets {
_, err := ec2Client.DeleteSubnet(ctx, &ec2.DeleteSubnetInput{SubnetId: &subnet})
if err != nil {
fmt.Printf("failed to delete subnet (%s)\n", subnet)
return err
}
}

vpcID, err := AWSGetInstanceVPCInfo()
if err != nil {
fmt.Printf("failed to find vpcid for instance\n")
return nil
}

fmt.Printf("vpcid for instance:%s\n", vpcID)

azName, err := AWSGetInstanceAvailabilityZone()
if err != nil {
fmt.Printf("failed to find az for instance %v\n", vpcID)
return nil
}
fmt.Printf("AZ for instance:%s\n", azName)

instanceID, err := AWSGetInstanceIDInfo()
if err != nil {
fmt.Printf("failed to find instanceID for instance %v\n", vpcID)
return nil
}

cidrBlock := "123.123.123.0/28"
loxilbSubNetKey := "loxiType"
loxilbSubNetKeyVal := "loxilb-subnet"
subnetTag := types.Tag{Key: &loxilbSubNetKey, Value: &loxilbSubNetKeyVal}
subnetTags := []types.Tag{subnetTag}
subOutput, err := ec2Client.CreateSubnet(ctx, &ec2.CreateSubnetInput{
VpcId: &vpcID,
AvailabilityZone: &azName,
CidrBlock: &cidrBlock,
TagSpecifications: []types.TagSpecification{{ResourceType: types.ResourceTypeSubnet,
Tags: subnetTags},
},
})
if err != nil {
fmt.Printf("failed to create subnet for loxilb instance %v\n", vpcID)
return nil
}

intfDesc := "loxilb-eni"
loxilbIntfKey := "loxiType"
loxilbIntfKeyVal := "loxilb-eni"
intfTag := types.Tag{Key: &loxilbIntfKey, Value: &loxilbIntfKeyVal}
intfTags := []types.Tag{intfTag}
intfOutput, err := ec2Client.CreateNetworkInterface(ctx, &ec2.CreateNetworkInterfaceInput{
SubnetId: subOutput.Subnet.SubnetId,
Description: &intfDesc,
TagSpecifications: []types.TagSpecification{{ResourceType: types.ResourceTypeNetworkInterface,
Tags: intfTags},
},
})
if err != nil {
fmt.Printf("failed to create interface for loxilb instance %v\n", vpcID)
return nil
}

fmt.Printf("Create interface (%s) for loxilb instance %v\n", *intfOutput.NetworkInterface.NetworkInterfaceId, vpcID)

devIdx := int32(1)
ec2Client.AttachNetworkInterface(ctx, &ec2.AttachNetworkInterfaceInput{DeviceIndex: &devIdx,
InstanceId: &instanceID,
NetworkInterfaceId: intfOutput.NetworkInterface.NetworkInterfaceId,
})

return nil
}

func AWSGetNetworkInterface(instanceID string, vIP net.IP) (string, error) {
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(time.Second*5))
defer cancel()
Expand Down Expand Up @@ -131,7 +279,7 @@ func AWSDeletePrivateIp(ni string, vIP net.IP) error {
return nil
}

func AWSUpdatePrivateIp(vIP net.IP, add bool) error {
func AWSUpdatePrivateIP(vIP net.IP, add bool) error {
instanceID, err := AWSGetInstanceIDInfo()
if err != nil {
tk.LogIt(tk.LogError, "AWS get instance failed: %v\n", err)
Expand Down

0 comments on commit 299465d

Please sign in to comment.