Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ebs attach windows ex #4214

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
2 changes: 1 addition & 1 deletion agent/app/agent_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ func (agent *ecsAgent) startEBSWatcher(
) {
if agent.ebsWatcher == nil {
seelog.Debug("Creating new EBS watcher...")
agent.ebsWatcher = ebs.NewWatcher(agent.ctx, state, taskEngine, dockerClient)
agent.ebsWatcher = ebs.NewWatcher(agent.ctx, state, taskEngine, dockerClient, agent.cfg.CSIDriverSocketPath)
go agent.ebsWatcher.Start()
}
}
Expand Down
7 changes: 6 additions & 1 deletion agent/app/agent_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
asmfactory "github.com/aws/amazon-ecs-agent/agent/asm/factory"
"github.com/aws/amazon-ecs-agent/agent/data"
"github.com/aws/amazon-ecs-agent/agent/dockerclient/dockerapi"
ebs "github.com/aws/amazon-ecs-agent/agent/ebs"
"github.com/aws/amazon-ecs-agent/agent/ecscni"
"github.com/aws/amazon-ecs-agent/agent/engine"
"github.com/aws/amazon-ecs-agent/agent/engine/dockerstate"
Expand Down Expand Up @@ -105,7 +106,11 @@ func (agent *ecsAgent) startEBSWatcher(
taskEngine engine.TaskEngine,
dockerClient dockerapi.DockerClient,
) {
seelog.Debug("Windows EBS Watcher not implemented: No Op")
if agent.ebsWatcher == nil {
seelog.Debug("Creating new EBS watcher...")
agent.ebsWatcher = ebs.NewWatcher(agent.ctx, state, taskEngine, dockerClient, agent.cfg.CSIDriverSocketPath)
go agent.ebsWatcher.Start()
}
}

// handler implements https://godoc.org/golang.org/x/sys/windows/svc#Handler
Expand Down
3 changes: 3 additions & 0 deletions agent/config/config_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ const (
minimumContainerCreateTimeout = 1 * time.Minute
// default docker inactivity time is extra time needed on container extraction
defaultImagePullInactivityTimeout = 1 * time.Minute
// default socket filepath is "/var/run/ecs/ebs-csi-driver/csi-driver.sock"
defaultCSIDriverSocketPath = "/var/run/ecs/ebs-csi-driver/csi-driver.sock"
)

// DefaultConfig returns the default configuration for Linux
Expand Down Expand Up @@ -112,6 +114,7 @@ func DefaultConfig() Config {
RuntimeStatsLogFile: defaultRuntimeStatsLogFile,
EnableRuntimeStats: BooleanDefaultFalse{Value: NotSet},
ShouldExcludeIPv6PortBinding: BooleanDefaultTrue{Value: ExplicitlyEnabled},
CSIDriverSocketPath: defaultCSIDriverSocketPath,
}
}

Expand Down
1 change: 1 addition & 0 deletions agent/config/config_unix_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ func TestConfigDefault(t *testing.T) {
assert.False(t, cfg.EnableRuntimeStats.Enabled(), "Default EnableRuntimeStats set incorrectly")
assert.True(t, cfg.ShouldExcludeIPv6PortBinding.Enabled(), "Default ShouldExcludeIPv6PortBinding set incorrectly")
assert.False(t, cfg.FSxWindowsFileServerCapable.Enabled(), "Default FSxWindowsFileServerCapable set incorrectly")
assert.Equal(t, "/var/run/ecs/ebs-csi-driver/csi-driver.sock", cfg.CSIDriverSocketPath, "Default CSIDriverSocketPath set incorrectly")
}

// TestConfigFromFile tests the configuration can be read from file
Expand Down
2 changes: 2 additions & 0 deletions agent/config/config_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ func DefaultConfig() Config {

programFiles := utils.DefaultIfBlank(os.Getenv("ProgramFiles"), `C:\Program Files`)
ecsBinaryDir := filepath.Join(programFiles, "Amazon", "ECS")
defaultCSIDriverSocketPath := filepath.Join(ecsBinaryDir, "ebs-csi-driver", "csi-driver.sock")

platformVariables := PlatformVariables{
CPUUnbounded: BooleanDefaultFalse{Value: ExplicitlyDisabled},
Expand Down Expand Up @@ -157,6 +158,7 @@ func DefaultConfig() Config {
RuntimeStatsLogFile: filepath.Join(ecsRoot, defaultRuntimeStatsLogFile),
EnableRuntimeStats: BooleanDefaultFalse{Value: NotSet},
ShouldExcludeIPv6PortBinding: BooleanDefaultTrue{Value: ExplicitlyEnabled},
CSIDriverSocketPath: defaultCSIDriverSocketPath,
}
}

Expand Down
1 change: 1 addition & 0 deletions agent/config/config_windows_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ func TestConfigDefault(t *testing.T) {
assert.False(t, cfg.EnableRuntimeStats.Enabled(), "Default EnableRuntimeStats set incorrectly")
assert.True(t, cfg.ShouldExcludeIPv6PortBinding.Enabled(), "Default ShouldExcludeIPv6PortBinding set incorrectly")
assert.True(t, cfg.FSxWindowsFileServerCapable.Enabled(), "Default FSxWindowsFileServerCapable set incorrectly")
assert.Equal(t, "C:\\Program Files\\Amazon\\ECS\\ebs-csi-driver\\csi-driver.sock", cfg.CSIDriverSocketPath, "Default CSIDriverSocketPath set incorrectly")
}

func TestConfigIAMTaskRolesReserves80(t *testing.T) {
Expand Down
4 changes: 4 additions & 0 deletions agent/config/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -384,4 +384,8 @@ type Config struct {
// cgroup setting at the ECS task level.
// see https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v2.html#pid
TaskPidsLimit int

// CSIDriverSocketPath specifies the path that the CSI driver socket file is located at.
// Defaults to "/var/run/ecs/ebs-csi-driver/csi-driver.sock"
CSIDriverSocketPath string
}
5 changes: 3 additions & 2 deletions agent/ebs/watcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,12 @@ type EBSWatcher struct {
func NewWatcher(ctx context.Context,
state dockerstate.TaskEngineState,
taskEngine ecsengine.TaskEngine,
dockerClient dockerapi.DockerClient) *EBSWatcher {
dockerClient dockerapi.DockerClient,
csiDriverSocketPath string) *EBSWatcher {
derivedContext, cancel := context.WithCancel(ctx)
discoveryClient := apiebs.NewDiscoveryClient(derivedContext)
// TODO pull this socket out into config
csiClient := csi.NewCSIClient("/var/run/ecs/ebs-csi-driver/csi-driver.sock")
csiClient := csi.NewCSIClient(csiDriverSocketPath)
return &EBSWatcher{
ctx: derivedContext,
cancel: cancel,
Expand Down
21 changes: 21 additions & 0 deletions agent/ebs/watcher_linux_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//go:build linux && unit
// +build linux,unit

// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"). You may
// not use this file except in compliance with the License. A copy of the
// License is located at
//
// http://aws.amazon.com/apache2.0/
//
// or in the "license" file accompanying this file. This file is distributed
// on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied. See the License for the specific language governing
// permissions and limitations under the License.

package ebs

const (
CSIDriverSocketPath = "/var/run/ecs/ebs-csi-driver/csi-driver.sock"
)
2 changes: 1 addition & 1 deletion agent/ebs/watcher_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -737,7 +737,7 @@ func TestTick(t *testing.T) {
tc.setDiscoveryClientExpectations(discoveryClient)
}

watcher := NewWatcher(context.Background(), taskEngineState, taskEngine, dockerClient)
watcher := NewWatcher(context.Background(), taskEngineState, taskEngine, dockerClient, CSIDriverSocketPath)
watcher.discoveryClient = discoveryClient
watcher.tick()

Expand Down
21 changes: 21 additions & 0 deletions agent/ebs/watcher_windows_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//go:build windows && unit
// +build windows,unit

// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"). You may
// not use this file except in compliance with the License. A copy of the
// License is located at
//
// http://aws.amazon.com/apache2.0/
//
// or in the "license" file accompanying this file. This file is distributed
// on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied. See the License for the specific language governing
// permissions and limitations under the License.

package ebs

const (
CSIDriverSocketPath = "C:\\Program Files\\Amazon\\ECS\\ebs-csi-driver\\csi-driver.sock"
)

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

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

18 changes: 9 additions & 9 deletions ecs-agent/api/attachment/resource/ebs_discovery_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,19 +42,19 @@ func (api *EBSDiscoveryClient) ConfirmEBSVolumeIsAttached(deviceName, volumeID s
return "", errors.Wrapf(err, "failed to run ebsnvme-id.exe: %s", string(output))
}

_, err = parseExecutableOutput(output, volumeID, deviceName)
actualDeviceName, err := parseExecutableOutput(output, volumeID)
if err != nil {
return "", errors.Wrapf(err, "failed to parse ebsnvme-id.exe output for volumeID: %s and deviceName: %s",
volumeID, deviceName)
}

log.Info(fmt.Sprintf("found volume with volumeID: %s and deviceName: %s", volumeID, deviceName))
log.Info(fmt.Sprintf("found volume with volumeID: %s and deviceName: %s", volumeID, actualDeviceName))

return "", nil
return actualDeviceName, nil
}

// parseExecutableOutput parses the output of `ebsnvme-id.exe` and returns the volumeId.
func parseExecutableOutput(output []byte, candidateVolumeId string, candidateDeviceName string) (string, error) {
// parseExecutableOutput parses the output of `ebsnvme-id.exe` and returns the deviceName.
func parseExecutableOutput(output []byte, candidateVolumeId string) (string, error) {
/* The output of the ebsnvme-id.exe is emitted like the following:
Disk Number: 0
Volume ID: vol-0a1234f340444abcd
Expand All @@ -76,12 +76,12 @@ func parseExecutableOutput(output []byte, candidateVolumeId string, candidateDev
for volumeIndex := 0; volumeIndex <= len(volumeInfo)-volumeInfoLength; volumeIndex = volumeIndex + volumeInfoLength {
_, volumeId, deviceName, err := parseSet(volumeInfo[volumeIndex : volumeIndex+volumeInfoLength])
if err != nil {
return "", errors.Wrapf(err, "failed to parse the output for volumeID: %s and deviceName: %s. "+
"Output:%s", candidateVolumeId, candidateDeviceName, out)
return "", errors.Wrapf(err, "failed to parse the output for volumeID: %s. "+
"Output:%s", candidateVolumeId, out)
}

if volumeId == candidateVolumeId && deviceName == candidateDeviceName {
return volumeId, nil
if volumeId == candidateVolumeId {
return deviceName, nil
}

}
Expand Down
36 changes: 8 additions & 28 deletions ecs-agent/api/attachment/resource/ebs_discovery_windows_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,96 +31,76 @@ const (
)

func TestParseExecutableOutputWithHappyPath(t *testing.T) {
t.Skip("Skipping timeout test. Still needs to be fixed.")
output := fmt.Sprintf("Disk Number: 0\r\n"+
"Volume ID: vol-abcdef1234567890a\r\n"+
"Device Name: sda1\r\n\r\n"+
"Disk Number: 1\r\n"+
"Volume ID: %s\r\n"+
"Device Name: %s\r\n\r\n", testVolumeID, deviceName)
parsedOutput, err := parseExecutableOutput([]byte(output), testVolumeID, deviceName)
parsedOutput, err := parseExecutableOutput([]byte(output), testVolumeID)
require.NoError(t, err)
assert.True(t, strings.Contains(parsedOutput, testVolumeID))
assert.True(t, strings.Contains(parsedOutput, deviceName))
}

func TestParseExecutableOutputWithMissingDiskNumber(t *testing.T) {
t.Skip("Skipping timeout test. Still needs to be fixed.")
output := fmt.Sprintf("Disk Number: 0\r\n"+
"Volume ID: vol-abcdef1234567890a\r\n"+
"Device Name: sda1\r\n\r\n"+
"Volume ID: %s\r\n"+
"Device Name: %s\r\n\r\n", testVolumeID, deviceName)
parsedOutput, err := parseExecutableOutput([]byte(output), testVolumeID, deviceName)
parsedOutput, err := parseExecutableOutput([]byte(output), testVolumeID)
require.Error(t, err)
assert.Equal(t, "", parsedOutput)
}

func TestParseExecutableOutputWithMissingVolumeInformation(t *testing.T) {
t.Skip("Skipping timeout test. Still needs to be fixed.")
output := fmt.Sprintf("Disk Number: 0\r\n"+
"Volume ID: vol-abcdef1234567890a\r\n"+
"Device Name: sda1\r\n\r\n"+
"Disk Number: 1\r\n"+
"Device Name: %s\r\n\r\n", deviceName)
parsedOutput, err := parseExecutableOutput([]byte(output), testVolumeID, deviceName)
parsedOutput, err := parseExecutableOutput([]byte(output), testVolumeID)
require.Error(t, err)
assert.Equal(t, "", parsedOutput)
}

func TestParseExecutableOutputWithMissingDeviceName(t *testing.T) {
t.Skip("Skipping timeout test. Still needs to be fixed.")
output := fmt.Sprintf("Disk Number: 0\r\n"+
"Volume ID: vol-abcdef1234567890a\r\n"+
"Device Name: sda1\r\n\r\n"+
"Disk Number: 1\r\n"+
"Volume ID: %s\r\n\r\n", testVolumeID)
parsedOutput, err := parseExecutableOutput([]byte(output), testVolumeID, deviceName)
parsedOutput, err := parseExecutableOutput([]byte(output), testVolumeID)
require.Error(t, err)
assert.Equal(t, "", parsedOutput)
}

func TestParseExecutableOutputWithVolumeNameMismatch(t *testing.T) {
t.Skip("Skipping timeout test. Still needs to be fixed.")
output := fmt.Sprintf("Disk Number: 0\r\n"+
"Volume ID: vol-abcdef1234567890a\r\n"+
"Device Name: sda1\r\n\r\n"+
"Disk Number: 1\r\n"+
"Volume ID: %s\r\n"+
"Device Name: %s\r\n\r\n", testVolumeID, deviceName)
parsedOutput, err := parseExecutableOutput([]byte(output), "MismatchedVolumeName", deviceName)
require.Error(t, err)
assert.Equal(t, "", parsedOutput)
}

func TestParseExecutableOutputWithDeviceNameMismatch(t *testing.T) {
t.Skip("Skipping timeout test. Still needs to be fixed.")
output := fmt.Sprintf("Disk Number: 0\r\n"+
"Volume ID: vol-abcdef1234567890a\r\n"+
"Device Name: sda1\r\n\r\n"+
"Disk Number: 1\r\n"+
"Volume ID: %s\r\n"+
"Device Name: %s\r\n\r\n", testVolumeID, deviceName)
parsedOutput, err := parseExecutableOutput([]byte(output), testVolumeID, "MismatchedDeviceName")
parsedOutput, err := parseExecutableOutput([]byte(output), "MismatchedVolumeName")
require.Error(t, err)
assert.Equal(t, "", parsedOutput)
}

func TestParseExecutableOutputWithTruncatedOutputBuffer(t *testing.T) {
t.Skip("Skipping timeout test. Still needs to be fixed.")
output := "Disk Number: 0\r\n" +
"Volume ID: vol-abcdef1234567890a\r\n" +
"Device Name: sda1\r\n\r\n" +
"Disk Number: 1\r\n" +
"Volume ID: TruncatedBuffer..."
parsedOutput, err := parseExecutableOutput([]byte(output), testVolumeID, deviceName)
parsedOutput, err := parseExecutableOutput([]byte(output), testVolumeID)
require.Error(t, err)
assert.Equal(t, "", parsedOutput)
}

func TestParseExecutableOutputWithUnexpectedOutput(t *testing.T) {
t.Skip("Skipping timeout test. Still needs to be fixed.")
output := "No EBS NVMe disks found."
parsedOutput, err := parseExecutableOutput([]byte(output), testVolumeID, deviceName)
parsedOutput, err := parseExecutableOutput([]byte(output), testVolumeID)
require.Error(t, err, "cannot find the volume ID: %s", output)
assert.Equal(t, "", parsedOutput)
}
14 changes: 10 additions & 4 deletions ecs-agent/csiclient/csi_client_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,18 @@
// permissions and limitations under the License.
package csiclient

import (
"path/filepath"

md "github.com/aws/amazon-ecs-agent/ecs-agent/manageddaemon"
)

const (
DefaultImageName = ""
DefaultSocketName = ""
DefaultSocketHostPath = ""
DefaultImageName = md.EbsCsiDriver
DefaultSocketName = "csi-driver.sock"
DefaultSocketHostPath = "C:\\Program Files\\Amazon\\ECS"
)

func DefaultSocketFilePath() string {
return "unimplemented" // TODO: Windows implementation
return filepath.Join(DefaultSocketHostPath, DefaultImageName, DefaultSocketName)
}
Loading
Loading