123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371 |
- package hcn
- import (
- "encoding/json"
- "errors"
- "github.com/Microsoft/hcsshim/internal/guid"
- "github.com/Microsoft/hcsshim/internal/interop"
- "github.com/sirupsen/logrus"
- )
- // IpConfig is assoicated with an endpoint
- type IpConfig struct {
- IpAddress string `json:",omitempty"`
- PrefixLength uint8 `json:",omitempty"`
- }
- // EndpointFlags are special settings on an endpoint.
- type EndpointFlags uint32
- var (
- // EndpointFlagsNone is the default.
- EndpointFlagsNone EndpointFlags
- // EndpointFlagsRemoteEndpoint means that an endpoint is on another host.
- EndpointFlagsRemoteEndpoint EndpointFlags = 1
- )
- // HostComputeEndpoint represents a network endpoint
- type HostComputeEndpoint struct {
- Id string `json:"ID,omitempty"`
- Name string `json:",omitempty"`
- HostComputeNetwork string `json:",omitempty"` // GUID
- HostComputeNamespace string `json:",omitempty"` // GUID
- Policies []EndpointPolicy `json:",omitempty"`
- IpConfigurations []IpConfig `json:",omitempty"`
- Dns Dns `json:",omitempty"`
- Routes []Route `json:",omitempty"`
- MacAddress string `json:",omitempty"`
- Flags EndpointFlags `json:",omitempty"`
- SchemaVersion SchemaVersion `json:",omitempty"`
- }
- // EndpointResourceType are the two different Endpoint settings resources.
- type EndpointResourceType string
- var (
- // EndpointResourceTypePolicy is for Endpoint Policies. Ex: ACL, NAT
- EndpointResourceTypePolicy EndpointResourceType = "Policy"
- // EndpointResourceTypePort is for Endpoint Port settings.
- EndpointResourceTypePort EndpointResourceType = "Port"
- )
- // ModifyEndpointSettingRequest is the structure used to send request to modify an endpoint.
- // Used to update policy/port on an endpoint.
- type ModifyEndpointSettingRequest struct {
- ResourceType EndpointResourceType `json:",omitempty"` // Policy, Port
- RequestType RequestType `json:",omitempty"` // Add, Remove, Update, Refresh
- Settings json.RawMessage `json:",omitempty"`
- }
- type PolicyEndpointRequest struct {
- Policies []EndpointPolicy `json:",omitempty"`
- }
- func getEndpoint(endpointGuid guid.GUID, query string) (*HostComputeEndpoint, error) {
- // Open endpoint.
- var (
- endpointHandle hcnEndpoint
- resultBuffer *uint16
- propertiesBuffer *uint16
- )
- hr := hcnOpenEndpoint(&endpointGuid, &endpointHandle, &resultBuffer)
- if err := checkForErrors("hcnOpenEndpoint", hr, resultBuffer); err != nil {
- return nil, err
- }
- // Query endpoint.
- hr = hcnQueryEndpointProperties(endpointHandle, query, &propertiesBuffer, &resultBuffer)
- if err := checkForErrors("hcnQueryEndpointProperties", hr, resultBuffer); err != nil {
- return nil, err
- }
- properties := interop.ConvertAndFreeCoTaskMemString(propertiesBuffer)
- // Close endpoint.
- hr = hcnCloseEndpoint(endpointHandle)
- if err := checkForErrors("hcnCloseEndpoint", hr, nil); err != nil {
- return nil, err
- }
- // Convert output to HostComputeEndpoint
- var outputEndpoint HostComputeEndpoint
- if err := json.Unmarshal([]byte(properties), &outputEndpoint); err != nil {
- return nil, err
- }
- return &outputEndpoint, nil
- }
- func enumerateEndpoints(query string) ([]HostComputeEndpoint, error) {
- // Enumerate all Endpoint Guids
- var (
- resultBuffer *uint16
- endpointBuffer *uint16
- )
- hr := hcnEnumerateEndpoints(query, &endpointBuffer, &resultBuffer)
- if err := checkForErrors("hcnEnumerateEndpoints", hr, resultBuffer); err != nil {
- return nil, err
- }
- endpoints := interop.ConvertAndFreeCoTaskMemString(endpointBuffer)
- var endpointIds []guid.GUID
- err := json.Unmarshal([]byte(endpoints), &endpointIds)
- if err != nil {
- return nil, err
- }
- var outputEndpoints []HostComputeEndpoint
- for _, endpointGuid := range endpointIds {
- endpoint, err := getEndpoint(endpointGuid, query)
- if err != nil {
- return nil, err
- }
- outputEndpoints = append(outputEndpoints, *endpoint)
- }
- return outputEndpoints, nil
- }
- func createEndpoint(networkId string, endpointSettings string) (*HostComputeEndpoint, error) {
- networkGuid := guid.FromString(networkId)
- // Open network.
- var networkHandle hcnNetwork
- var resultBuffer *uint16
- hr := hcnOpenNetwork(&networkGuid, &networkHandle, &resultBuffer)
- if err := checkForErrors("hcnOpenNetwork", hr, resultBuffer); err != nil {
- return nil, err
- }
- // Create endpoint.
- endpointId := guid.GUID{}
- var endpointHandle hcnEndpoint
- hr = hcnCreateEndpoint(networkHandle, &endpointId, endpointSettings, &endpointHandle, &resultBuffer)
- if err := checkForErrors("hcnCreateEndpoint", hr, resultBuffer); err != nil {
- return nil, err
- }
- // Query endpoint.
- hcnQuery := defaultQuery()
- query, err := json.Marshal(hcnQuery)
- if err != nil {
- return nil, err
- }
- var propertiesBuffer *uint16
- hr = hcnQueryEndpointProperties(endpointHandle, string(query), &propertiesBuffer, &resultBuffer)
- if err := checkForErrors("hcnQueryEndpointProperties", hr, resultBuffer); err != nil {
- return nil, err
- }
- properties := interop.ConvertAndFreeCoTaskMemString(propertiesBuffer)
- // Close endpoint.
- hr = hcnCloseEndpoint(endpointHandle)
- if err := checkForErrors("hcnCloseEndpoint", hr, nil); err != nil {
- return nil, err
- }
- // Close network.
- hr = hcnCloseNetwork(networkHandle)
- if err := checkForErrors("hcnCloseNetwork", hr, nil); err != nil {
- return nil, err
- }
- // Convert output to HostComputeEndpoint
- var outputEndpoint HostComputeEndpoint
- if err := json.Unmarshal([]byte(properties), &outputEndpoint); err != nil {
- return nil, err
- }
- return &outputEndpoint, nil
- }
- func modifyEndpoint(endpointId string, settings string) (*HostComputeEndpoint, error) {
- endpointGuid := guid.FromString(endpointId)
- // Open endpoint
- var (
- endpointHandle hcnEndpoint
- resultBuffer *uint16
- propertiesBuffer *uint16
- )
- hr := hcnOpenEndpoint(&endpointGuid, &endpointHandle, &resultBuffer)
- if err := checkForErrors("hcnOpenEndpoint", hr, resultBuffer); err != nil {
- return nil, err
- }
- // Modify endpoint
- hr = hcnModifyEndpoint(endpointHandle, settings, &resultBuffer)
- if err := checkForErrors("hcnModifyEndpoint", hr, resultBuffer); err != nil {
- return nil, err
- }
- // Query endpoint.
- hcnQuery := defaultQuery()
- query, err := json.Marshal(hcnQuery)
- if err != nil {
- return nil, err
- }
- hr = hcnQueryEndpointProperties(endpointHandle, string(query), &propertiesBuffer, &resultBuffer)
- if err := checkForErrors("hcnQueryEndpointProperties", hr, resultBuffer); err != nil {
- return nil, err
- }
- properties := interop.ConvertAndFreeCoTaskMemString(propertiesBuffer)
- // Close endpoint.
- hr = hcnCloseEndpoint(endpointHandle)
- if err := checkForErrors("hcnCloseEndpoint", hr, nil); err != nil {
- return nil, err
- }
- // Convert output to HostComputeEndpoint
- var outputEndpoint HostComputeEndpoint
- if err := json.Unmarshal([]byte(properties), &outputEndpoint); err != nil {
- return nil, err
- }
- return &outputEndpoint, nil
- }
- func deleteEndpoint(endpointId string) error {
- endpointGuid := guid.FromString(endpointId)
- var resultBuffer *uint16
- hr := hcnDeleteEndpoint(&endpointGuid, &resultBuffer)
- if err := checkForErrors("hcnDeleteEndpoint", hr, resultBuffer); err != nil {
- return err
- }
- return nil
- }
- // ListEndpoints makes a call to list all available endpoints.
- func ListEndpoints() ([]HostComputeEndpoint, error) {
- hcnQuery := defaultQuery()
- endpoints, err := ListEndpointsQuery(hcnQuery)
- if err != nil {
- return nil, err
- }
- return endpoints, nil
- }
- // ListEndpointsQuery makes a call to query the list of available endpoints.
- func ListEndpointsQuery(query HostComputeQuery) ([]HostComputeEndpoint, error) {
- queryJson, err := json.Marshal(query)
- if err != nil {
- return nil, err
- }
- endpoints, err := enumerateEndpoints(string(queryJson))
- if err != nil {
- return nil, err
- }
- return endpoints, nil
- }
- // ListEndpointsOfNetwork queries the list of endpoints on a network.
- func ListEndpointsOfNetwork(networkId string) ([]HostComputeEndpoint, error) {
- hcnQuery := defaultQuery()
- // TODO: Once query can convert schema, change to {HostComputeNetwork:networkId}
- mapA := map[string]string{"VirtualNetwork": networkId}
- filter, err := json.Marshal(mapA)
- if err != nil {
- return nil, err
- }
- hcnQuery.Filter = string(filter)
- return ListEndpointsQuery(hcnQuery)
- }
- // GetEndpointByID returns an endpoint specified by Id
- func GetEndpointByID(endpointId string) (*HostComputeEndpoint, error) {
- hcnQuery := defaultQuery()
- mapA := map[string]string{"ID": endpointId}
- filter, err := json.Marshal(mapA)
- if err != nil {
- return nil, err
- }
- hcnQuery.Filter = string(filter)
- endpoints, err := ListEndpointsQuery(hcnQuery)
- if err != nil {
- return nil, err
- }
- if len(endpoints) == 0 {
- return nil, EndpointNotFoundError{EndpointID: endpointId}
- }
- return &endpoints[0], err
- }
- // GetEndpointByName returns an endpoint specified by Name
- func GetEndpointByName(endpointName string) (*HostComputeEndpoint, error) {
- hcnQuery := defaultQuery()
- mapA := map[string]string{"Name": endpointName}
- filter, err := json.Marshal(mapA)
- if err != nil {
- return nil, err
- }
- hcnQuery.Filter = string(filter)
- endpoints, err := ListEndpointsQuery(hcnQuery)
- if err != nil {
- return nil, err
- }
- if len(endpoints) == 0 {
- return nil, EndpointNotFoundError{EndpointName: endpointName}
- }
- return &endpoints[0], err
- }
- // Create Endpoint.
- func (endpoint *HostComputeEndpoint) Create() (*HostComputeEndpoint, error) {
- logrus.Debugf("hcn::HostComputeEndpoint::Create id=%s", endpoint.Id)
- if endpoint.HostComputeNamespace != "" {
- return nil, errors.New("endpoint create error, endpoint json HostComputeNamespace is read only and should not be set")
- }
- jsonString, err := json.Marshal(endpoint)
- if err != nil {
- return nil, err
- }
- logrus.Debugf("hcn::HostComputeEndpoint::Create JSON: %s", jsonString)
- endpoint, hcnErr := createEndpoint(endpoint.HostComputeNetwork, string(jsonString))
- if hcnErr != nil {
- return nil, hcnErr
- }
- return endpoint, nil
- }
- // Delete Endpoint.
- func (endpoint *HostComputeEndpoint) Delete() error {
- logrus.Debugf("hcn::HostComputeEndpoint::Delete id=%s", endpoint.Id)
- if err := deleteEndpoint(endpoint.Id); err != nil {
- return err
- }
- return nil
- }
- // ModifyEndpointSettings updates the Port/Policy of an Endpoint.
- func ModifyEndpointSettings(endpointId string, request *ModifyEndpointSettingRequest) error {
- logrus.Debugf("hcn::HostComputeEndpoint::ModifyEndpointSettings id=%s", endpointId)
- endpointSettingsRequest, err := json.Marshal(request)
- if err != nil {
- return err
- }
- _, err = modifyEndpoint(endpointId, string(endpointSettingsRequest))
- if err != nil {
- return err
- }
- return nil
- }
- // ApplyPolicy applies a Policy (ex: ACL) on the Endpoint.
- func (endpoint *HostComputeEndpoint) ApplyPolicy(endpointPolicy PolicyEndpointRequest) error {
- logrus.Debugf("hcn::HostComputeEndpoint::ApplyPolicy id=%s", endpoint.Id)
- settingsJson, err := json.Marshal(endpointPolicy)
- if err != nil {
- return err
- }
- requestMessage := &ModifyEndpointSettingRequest{
- ResourceType: EndpointResourceTypePolicy,
- RequestType: RequestTypeUpdate,
- Settings: settingsJson,
- }
- return ModifyEndpointSettings(endpoint.Id, requestMessage)
- }
- // NamespaceAttach modifies a Namespace to add an endpoint.
- func (endpoint *HostComputeEndpoint) NamespaceAttach(namespaceId string) error {
- return AddNamespaceEndpoint(namespaceId, endpoint.Id)
- }
- // NamespaceDetach modifies a Namespace to remove an endpoint.
- func (endpoint *HostComputeEndpoint) NamespaceDetach(namespaceId string) error {
- return RemoveNamespaceEndpoint(namespaceId, endpoint.Id)
- }
|