123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336 |
- package hcn
- import (
- "encoding/json"
- "github.com/Microsoft/hcsshim/internal/guid"
- "github.com/Microsoft/hcsshim/internal/interop"
- "github.com/sirupsen/logrus"
- )
- // LoadBalancerPortMapping is associated with HostComputeLoadBalancer
- type LoadBalancerPortMapping struct {
- Protocol uint32 `json:",omitempty"` // EX: TCP = 6, UDP = 17
- InternalPort uint16 `json:",omitempty"`
- ExternalPort uint16 `json:",omitempty"`
- Flags LoadBalancerPortMappingFlags `json:",omitempty"`
- }
- // HostComputeLoadBalancer represents software load balancer.
- type HostComputeLoadBalancer struct {
- Id string `json:"ID,omitempty"`
- HostComputeEndpoints []string `json:",omitempty"`
- SourceVIP string `json:",omitempty"`
- FrontendVIPs []string `json:",omitempty"`
- PortMappings []LoadBalancerPortMapping `json:",omitempty"`
- SchemaVersion SchemaVersion `json:",omitempty"`
- Flags LoadBalancerFlags `json:",omitempty"` // 0: None, 1: EnableDirectServerReturn
- }
- //LoadBalancerFlags modify settings for a loadbalancer.
- type LoadBalancerFlags uint32
- var (
- // LoadBalancerFlagsNone is the default.
- LoadBalancerFlagsNone LoadBalancerFlags = 0
- // LoadBalancerFlagsDSR enables Direct Server Return (DSR)
- LoadBalancerFlagsDSR LoadBalancerFlags = 1
- )
- // LoadBalancerPortMappingFlags are special settings on a loadbalancer.
- type LoadBalancerPortMappingFlags uint32
- var (
- // LoadBalancerPortMappingFlagsNone is the default.
- LoadBalancerPortMappingFlagsNone LoadBalancerPortMappingFlags
- // LoadBalancerPortMappingFlagsILB enables internal loadbalancing.
- LoadBalancerPortMappingFlagsILB LoadBalancerPortMappingFlags = 1
- // LoadBalancerPortMappingFlagsLocalRoutedVIP enables VIP access from the host.
- LoadBalancerPortMappingFlagsLocalRoutedVIP LoadBalancerPortMappingFlags = 2
- // LoadBalancerPortMappingFlagsUseMux enables DSR for NodePort access of VIP.
- LoadBalancerPortMappingFlagsUseMux LoadBalancerPortMappingFlags = 4
- // LoadBalancerPortMappingFlagsPreserveDIP delivers packets with destination IP as the VIP.
- LoadBalancerPortMappingFlagsPreserveDIP LoadBalancerPortMappingFlags = 8
- )
- func getLoadBalancer(loadBalancerGuid guid.GUID, query string) (*HostComputeLoadBalancer, error) {
- // Open loadBalancer.
- var (
- loadBalancerHandle hcnLoadBalancer
- resultBuffer *uint16
- propertiesBuffer *uint16
- )
- hr := hcnOpenLoadBalancer(&loadBalancerGuid, &loadBalancerHandle, &resultBuffer)
- if err := checkForErrors("hcnOpenLoadBalancer", hr, resultBuffer); err != nil {
- return nil, err
- }
- // Query loadBalancer.
- hr = hcnQueryLoadBalancerProperties(loadBalancerHandle, query, &propertiesBuffer, &resultBuffer)
- if err := checkForErrors("hcnQueryLoadBalancerProperties", hr, resultBuffer); err != nil {
- return nil, err
- }
- properties := interop.ConvertAndFreeCoTaskMemString(propertiesBuffer)
- // Close loadBalancer.
- hr = hcnCloseLoadBalancer(loadBalancerHandle)
- if err := checkForErrors("hcnCloseLoadBalancer", hr, nil); err != nil {
- return nil, err
- }
- // Convert output to HostComputeLoadBalancer
- var outputLoadBalancer HostComputeLoadBalancer
- if err := json.Unmarshal([]byte(properties), &outputLoadBalancer); err != nil {
- return nil, err
- }
- return &outputLoadBalancer, nil
- }
- func enumerateLoadBalancers(query string) ([]HostComputeLoadBalancer, error) {
- // Enumerate all LoadBalancer Guids
- var (
- resultBuffer *uint16
- loadBalancerBuffer *uint16
- )
- hr := hcnEnumerateLoadBalancers(query, &loadBalancerBuffer, &resultBuffer)
- if err := checkForErrors("hcnEnumerateLoadBalancers", hr, resultBuffer); err != nil {
- return nil, err
- }
- loadBalancers := interop.ConvertAndFreeCoTaskMemString(loadBalancerBuffer)
- var loadBalancerIds []guid.GUID
- if err := json.Unmarshal([]byte(loadBalancers), &loadBalancerIds); err != nil {
- return nil, err
- }
- var outputLoadBalancers []HostComputeLoadBalancer
- for _, loadBalancerGuid := range loadBalancerIds {
- loadBalancer, err := getLoadBalancer(loadBalancerGuid, query)
- if err != nil {
- return nil, err
- }
- outputLoadBalancers = append(outputLoadBalancers, *loadBalancer)
- }
- return outputLoadBalancers, nil
- }
- func createLoadBalancer(settings string) (*HostComputeLoadBalancer, error) {
- // Create new loadBalancer.
- var (
- loadBalancerHandle hcnLoadBalancer
- resultBuffer *uint16
- propertiesBuffer *uint16
- )
- loadBalancerGuid := guid.GUID{}
- hr := hcnCreateLoadBalancer(&loadBalancerGuid, settings, &loadBalancerHandle, &resultBuffer)
- if err := checkForErrors("hcnCreateLoadBalancer", hr, resultBuffer); err != nil {
- return nil, err
- }
- // Query loadBalancer.
- hcnQuery := defaultQuery()
- query, err := json.Marshal(hcnQuery)
- if err != nil {
- return nil, err
- }
- hr = hcnQueryLoadBalancerProperties(loadBalancerHandle, string(query), &propertiesBuffer, &resultBuffer)
- if err := checkForErrors("hcnQueryLoadBalancerProperties", hr, resultBuffer); err != nil {
- return nil, err
- }
- properties := interop.ConvertAndFreeCoTaskMemString(propertiesBuffer)
- // Close loadBalancer.
- hr = hcnCloseLoadBalancer(loadBalancerHandle)
- if err := checkForErrors("hcnCloseLoadBalancer", hr, nil); err != nil {
- return nil, err
- }
- // Convert output to HostComputeLoadBalancer
- var outputLoadBalancer HostComputeLoadBalancer
- if err := json.Unmarshal([]byte(properties), &outputLoadBalancer); err != nil {
- return nil, err
- }
- return &outputLoadBalancer, nil
- }
- func modifyLoadBalancer(loadBalancerId string, settings string) (*HostComputeLoadBalancer, error) {
- loadBalancerGuid := guid.FromString(loadBalancerId)
- // Open loadBalancer.
- var (
- loadBalancerHandle hcnLoadBalancer
- resultBuffer *uint16
- propertiesBuffer *uint16
- )
- hr := hcnOpenLoadBalancer(&loadBalancerGuid, &loadBalancerHandle, &resultBuffer)
- if err := checkForErrors("hcnOpenLoadBalancer", hr, resultBuffer); err != nil {
- return nil, err
- }
- // Modify loadBalancer.
- hr = hcnModifyLoadBalancer(loadBalancerHandle, settings, &resultBuffer)
- if err := checkForErrors("hcnModifyLoadBalancer", hr, resultBuffer); err != nil {
- return nil, err
- }
- // Query loadBalancer.
- hcnQuery := defaultQuery()
- query, err := json.Marshal(hcnQuery)
- if err != nil {
- return nil, err
- }
- hr = hcnQueryLoadBalancerProperties(loadBalancerHandle, string(query), &propertiesBuffer, &resultBuffer)
- if err := checkForErrors("hcnQueryLoadBalancerProperties", hr, resultBuffer); err != nil {
- return nil, err
- }
- properties := interop.ConvertAndFreeCoTaskMemString(propertiesBuffer)
- // Close loadBalancer.
- hr = hcnCloseLoadBalancer(loadBalancerHandle)
- if err := checkForErrors("hcnCloseLoadBalancer", hr, nil); err != nil {
- return nil, err
- }
- // Convert output to LoadBalancer
- var outputLoadBalancer HostComputeLoadBalancer
- if err := json.Unmarshal([]byte(properties), &outputLoadBalancer); err != nil {
- return nil, err
- }
- return &outputLoadBalancer, nil
- }
- func deleteLoadBalancer(loadBalancerId string) error {
- loadBalancerGuid := guid.FromString(loadBalancerId)
- var resultBuffer *uint16
- hr := hcnDeleteLoadBalancer(&loadBalancerGuid, &resultBuffer)
- if err := checkForErrors("hcnDeleteLoadBalancer", hr, resultBuffer); err != nil {
- return err
- }
- return nil
- }
- // ListLoadBalancers makes a call to list all available loadBalancers.
- func ListLoadBalancers() ([]HostComputeLoadBalancer, error) {
- hcnQuery := defaultQuery()
- loadBalancers, err := ListLoadBalancersQuery(hcnQuery)
- if err != nil {
- return nil, err
- }
- return loadBalancers, nil
- }
- // ListLoadBalancersQuery makes a call to query the list of available loadBalancers.
- func ListLoadBalancersQuery(query HostComputeQuery) ([]HostComputeLoadBalancer, error) {
- queryJson, err := json.Marshal(query)
- if err != nil {
- return nil, err
- }
- loadBalancers, err := enumerateLoadBalancers(string(queryJson))
- if err != nil {
- return nil, err
- }
- return loadBalancers, nil
- }
- // GetLoadBalancerByID returns the LoadBalancer specified by Id.
- func GetLoadBalancerByID(loadBalancerId string) (*HostComputeLoadBalancer, error) {
- hcnQuery := defaultQuery()
- mapA := map[string]string{"ID": loadBalancerId}
- filter, err := json.Marshal(mapA)
- if err != nil {
- return nil, err
- }
- hcnQuery.Filter = string(filter)
- loadBalancers, err := ListLoadBalancersQuery(hcnQuery)
- if err != nil {
- return nil, err
- }
- if len(loadBalancers) == 0 {
- return nil, LoadBalancerNotFoundError{LoadBalancerId: loadBalancerId}
- }
- return &loadBalancers[0], err
- }
- // Create LoadBalancer.
- func (loadBalancer *HostComputeLoadBalancer) Create() (*HostComputeLoadBalancer, error) {
- logrus.Debugf("hcn::HostComputeLoadBalancer::Create id=%s", loadBalancer.Id)
- jsonString, err := json.Marshal(loadBalancer)
- if err != nil {
- return nil, err
- }
- logrus.Debugf("hcn::HostComputeLoadBalancer::Create JSON: %s", jsonString)
- loadBalancer, hcnErr := createLoadBalancer(string(jsonString))
- if hcnErr != nil {
- return nil, hcnErr
- }
- return loadBalancer, nil
- }
- // Delete LoadBalancer.
- func (loadBalancer *HostComputeLoadBalancer) Delete() error {
- logrus.Debugf("hcn::HostComputeLoadBalancer::Delete id=%s", loadBalancer.Id)
- if err := deleteLoadBalancer(loadBalancer.Id); err != nil {
- return err
- }
- return nil
- }
- // AddEndpoint add an endpoint to a LoadBalancer
- func (loadBalancer *HostComputeLoadBalancer) AddEndpoint(endpoint *HostComputeEndpoint) (*HostComputeLoadBalancer, error) {
- logrus.Debugf("hcn::HostComputeLoadBalancer::AddEndpoint loadBalancer=%s endpoint=%s", loadBalancer.Id, endpoint.Id)
- err := loadBalancer.Delete()
- if err != nil {
- return nil, err
- }
- // Add Endpoint to the Existing List
- loadBalancer.HostComputeEndpoints = append(loadBalancer.HostComputeEndpoints, endpoint.Id)
- return loadBalancer.Create()
- }
- // RemoveEndpoint removes an endpoint from a LoadBalancer
- func (loadBalancer *HostComputeLoadBalancer) RemoveEndpoint(endpoint *HostComputeEndpoint) (*HostComputeLoadBalancer, error) {
- logrus.Debugf("hcn::HostComputeLoadBalancer::RemoveEndpoint loadBalancer=%s endpoint=%s", loadBalancer.Id, endpoint.Id)
- err := loadBalancer.Delete()
- if err != nil {
- return nil, err
- }
- // Create a list of all the endpoints besides the one being removed
- var endpoints []string
- for _, endpointReference := range loadBalancer.HostComputeEndpoints {
- if endpointReference == endpoint.Id {
- continue
- }
- endpoints = append(endpoints, endpointReference)
- }
- loadBalancer.HostComputeEndpoints = endpoints
- return loadBalancer.Create()
- }
- // AddLoadBalancer for the specified endpoints
- func AddLoadBalancer(endpoints []HostComputeEndpoint, flags LoadBalancerFlags, portMappingFlags LoadBalancerPortMappingFlags, sourceVIP string, frontendVIPs []string, protocol uint16, internalPort uint16, externalPort uint16) (*HostComputeLoadBalancer, error) {
- logrus.Debugf("hcn::HostComputeLoadBalancer::AddLoadBalancer endpointId=%v, LoadBalancerFlags=%v, LoadBalancerPortMappingFlags=%v, sourceVIP=%s, frontendVIPs=%v, protocol=%v, internalPort=%v, externalPort=%v", endpoints, flags, portMappingFlags, sourceVIP, frontendVIPs, protocol, internalPort, externalPort)
- loadBalancer := &HostComputeLoadBalancer{
- SourceVIP: sourceVIP,
- PortMappings: []LoadBalancerPortMapping{
- {
- Protocol: uint32(protocol),
- InternalPort: internalPort,
- ExternalPort: externalPort,
- Flags: portMappingFlags,
- },
- },
- FrontendVIPs: frontendVIPs,
- SchemaVersion: SchemaVersion{
- Major: 2,
- Minor: 0,
- },
- Flags: flags,
- }
- for _, endpoint := range endpoints {
- loadBalancer.HostComputeEndpoints = append(loadBalancer.HostComputeEndpoints, endpoint.Id)
- }
- return loadBalancer.Create()
- }
|