Skip to content

Commit

Permalink
Enable v2 Xenon networking and network namespace sharing
Browse files Browse the repository at this point in the history
  • Loading branch information
John Starks committed May 22, 2018
1 parent fcb334d commit 5ab7622
Show file tree
Hide file tree
Showing 10 changed files with 325 additions and 105 deletions.
124 changes: 77 additions & 47 deletions cmd/runhcs/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import (
"github.com/Microsoft/hcsshim/internal/hcs"
"github.com/Microsoft/hcsshim/internal/hcsoci"
"github.com/Microsoft/hcsshim/internal/regstate"
"github.com/Microsoft/hcsshim/internal/schemaversion"
"github.com/Microsoft/hcsshim/uvm"
specs "github.com/opencontainers/runtime-spec/specs-go"
"github.com/sirupsen/logrus"
Expand All @@ -28,14 +27,15 @@ import (
var errContainerStopped = errors.New("container is stopped")

type persistedState struct {
ID string
SandboxID string
Bundle string
Created time.Time
Rootfs string
Spec *specs.Spec
IsSandbox bool
VMIsolated bool
ID string
SandboxID string
Bundle string
Created time.Time
Rootfs string
Spec *specs.Spec
IsSandbox bool
VMIsolated bool
RequestedNetNS string
}

type containerStatus string
Expand All @@ -51,6 +51,7 @@ const (
keyResources = "resources"
keyShimPid = "shim"
keyInitPid = "pid"
keyNetNS = "netns"
)

type container struct {
Expand Down Expand Up @@ -300,26 +301,38 @@ func createContainer(cfg *containerConfig) (_ *container, err error) {
}
}

netNS := ""
if cfg.Spec.Windows != nil {
for i, f := range cfg.Spec.Windows.LayerFolders {
if !filepath.IsAbs(f) && !strings.HasPrefix(rootfs, `\\?\`) {
cfg.Spec.Windows.LayerFolders[i] = filepath.Join(cwd, f)
}
}

// Determine the network namespace to use.
if cfg.Spec.Windows.Network != nil && cfg.Spec.Windows.Network.NetworkSharedContainerName != "" {
err = stateKey.Get(cfg.Spec.Windows.Network.NetworkSharedContainerName, keyNetNS, &netNS)
if err != nil {
if _, ok := err.(*regstate.NoStateError); !ok {
return nil, err
}
}
}
}

// Store the initial container state in the registry so that the delete
// command can clean everything up if something goes wrong.
c := &container{
persistedState: persistedState{
ID: cfg.ID,
Bundle: cwd,
Rootfs: rootfs,
Created: time.Now(),
Spec: cfg.Spec,
VMIsolated: vmisolated,
IsSandbox: isSandbox,
SandboxID: sandboxID,
ID: cfg.ID,
Bundle: cwd,
Rootfs: rootfs,
Created: time.Now(),
Spec: cfg.Spec,
VMIsolated: vmisolated,
IsSandbox: isSandbox,
SandboxID: sandboxID,
RequestedNetNS: netNS,
},
}
err = stateKey.Create(cfg.ID, keyState, &c.persistedState)
Expand Down Expand Up @@ -359,11 +372,6 @@ func createContainer(cfg *containerConfig) (_ *container, err error) {
if err != nil {
return nil, err
}
err := stateKey.Set(c.ID, keyResources, c.resources)
if err != nil {
c.hc.Terminate()
return nil, err
}
}

// Create the shim process for the container.
Expand All @@ -378,6 +386,28 @@ func createContainer(cfg *containerConfig) (_ *container, err error) {
return c, nil
}

func (c *container) unmountInHost(vm *uvm.UtilityVM, all bool) error {
resources := &hcsoci.Resources{}
err := stateKey.Get(c.ID, keyResources, resources)
if _, ok := err.(*regstate.NoStateError); ok {
return nil
}
if err != nil {
return err
}
err = hcsoci.ReleaseResources(resources, vm, all)
if err != nil {
stateKey.Set(c.ID, keyResources, resources)
return err
}

err = stateKey.Clear(c.ID, keyResources)
if err != nil {
return err
}
return nil
}

func (c *container) Unmount(all bool) error {
if c.VMIsolated {
op := opUnmountContainerDiskOnly
Expand All @@ -389,22 +419,7 @@ func (c *container) Unmount(all bool) error {
return err
}
} else {
resources := &hcsoci.Resources{}
err := stateKey.Get(c.ID, keyResources, resources)
if err == nil {
err = hcsoci.ReleaseResources(resources, nil, false)
if err != nil {
stateKey.Set(c.ID, keyResources, resources)
return err
}

err = stateKey.Clear(c.ID, keyResources)
if err != nil {
return err
}
} else if _, ok := err.(*regstate.NoStateError); !ok {
return err
}
c.unmountInHost(nil, false)
}
return nil
}
Expand All @@ -416,15 +431,11 @@ func createContainerInHost(c *container, vm *uvm.UtilityVM) (err error) {

// Create the container without starting it.
opts := &hcsoci.CreateOptions{
ID: c.ID,
Spec: c.Spec,
HostingSystem: vm,
SchemaVersion: schemaversion.SchemaV20(),
}
if vm != nil {
opts.SchemaVersion = schemaversion.SchemaV20()
ID: c.ID,
Spec: c.Spec,
HostingSystem: vm,
NetworkNamespace: c.RequestedNetNS,
}

vmid := ""
if vm != nil {
vmid = vm.ID()
Expand All @@ -434,8 +445,27 @@ func createContainerInHost(c *container, vm *uvm.UtilityVM) (err error) {
if err != nil {
return err
}
defer func() {
if err != nil {
hc.Terminate()
hc.Wait()
hcsoci.ReleaseResources(resources, vm, false)
}
}()

// Record the network namespace to support namespace sharing by container ID.
if resources.NetNS != "" {
err = stateKey.Set(c.ID, keyNetNS, resources.NetNS)
if err != nil {
return err
}
}

err = stateKey.Set(c.ID, keyResources, resources)
if err != nil {
return err
}
c.hc = hc
c.resources = resources
return nil
}

Expand Down
21 changes: 9 additions & 12 deletions cmd/runhcs/vm.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import (

winio "github.com/Microsoft/go-winio"
"github.com/Microsoft/hcsshim/internal/appargs"
"github.com/Microsoft/hcsshim/internal/hcsoci"
"github.com/Microsoft/hcsshim/uvm"
"github.com/sirupsen/logrus"
"github.com/urfave/cli"
Expand Down Expand Up @@ -104,7 +103,7 @@ var vmshimCommand = cli.Command{
ioutil.ReadAll(pipe)
}
} else {
logrus.Error("failed creating container in VM", err)
logrus.Error("failed creating container in VM: ", err)
fmt.Fprintf(pipe, "%v", err)
}
pipe.Close()
Expand All @@ -113,12 +112,12 @@ var vmshimCommand = cli.Command{
},
}

type vmRequestOp int
type vmRequestOp string

const (
opCreateContainer vmRequestOp = iota
opUnmountContainer
opUnmountContainerDiskOnly
opCreateContainer vmRequestOp = "create"
opUnmountContainer vmRequestOp = "unmount"
opUnmountContainerDiskOnly vmRequestOp = "unmount-disk"
)

type vmRequest struct {
Expand All @@ -145,6 +144,7 @@ func processRequest(vm *uvm.UtilityVM, pipe net.Conn) error {
if err != nil {
return err
}
logrus.Debug("received operation ", req.Op, " for ", req.ID)
c, err := getContainer(req.ID, false)
if err != nil {
return err
Expand All @@ -169,13 +169,10 @@ func processRequest(vm *uvm.UtilityVM, pipe net.Conn) error {
c = nil

case opUnmountContainer, opUnmountContainerDiskOnly:
if c.resources != nil {
err := hcsoci.ReleaseResources(c.resources, vm, req.Op == opUnmountContainerDiskOnly)
if err != nil {
return err
}
err = c.unmountInHost(vm, req.Op == opUnmountContainer)
if err != nil {
return err
}
c.resources = nil

default:
panic("unknown operation")
Expand Down
56 changes: 29 additions & 27 deletions internal/hcsoci/containerex.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import (

"github.com/Microsoft/hcsshim/internal/guid"
"github.com/Microsoft/hcsshim/internal/hcs"
"github.com/Microsoft/hcsshim/internal/hns"
"github.com/Microsoft/hcsshim/internal/osversion"
version "github.com/Microsoft/hcsshim/internal/osversion"
"github.com/Microsoft/hcsshim/internal/schema1"
Expand Down Expand Up @@ -43,11 +42,12 @@ const (
type CreateOptions struct {

// Common parameters
ID string // Identifier for the container
Owner string // Specifies the owner. Defaults to executable name.
Spec *specs.Spec // Definition of the container or utility VM being created
SchemaVersion *schemaversion.SchemaVersion // Requested Schema Version. Defaults to v2 for RS5, v1 for RS1..RS4
HostingSystem *uvm.UtilityVM // Utility or service VM in which the container is to be created.
ID string // Identifier for the container
Owner string // Specifies the owner. Defaults to executable name.
Spec *specs.Spec // Definition of the container or utility VM being created
SchemaVersion *schemaversion.SchemaVersion // Requested Schema Version. Defaults to v2 for RS5, v1 for RS1..RS4
HostingSystem *uvm.UtilityVM // Utility or service VM in which the container is to be created.
NetworkNamespace string // Host network namespace to use (overrides anything in the spec)

// These are v1 LCOW backwards-compatibility only.
KirdPath string // Folder in which kernel and initrd reside. Defaults to \Program Files\Linux Containers
Expand All @@ -61,16 +61,16 @@ type CreateOptions struct {
type createOptionsInternal struct {
*CreateOptions

actualSchemaVersion *schemaversion.SchemaVersion // Calculated based on Windows build and optional caller-supplied override
actualID string // Identifier for the container
actualOwner string // Owner for the container
actualSchemaVersion *schemaversion.SchemaVersion // Calculated based on Windows build and optional caller-supplied override
actualID string // Identifier for the container
actualOwner string // Owner for the container
actualNetworkNamespace string

// These are v1 LCOW backwards-compatibility only
actualKirdPath string // LCOW kernel/initrd path
actualKernelFile string // LCOW kernel file
actualInitrdFile string // LCOW initrd file

networkNamespace string
}

// CreateContainer creates a container. It can cope with a wide variety of
Expand Down Expand Up @@ -127,25 +127,27 @@ func CreateContainer(createOptions *CreateOptions) (_ *hcs.System, _ *Resources,
// Create a network namespace if necessary.
if coi.Spec.Windows != nil &&
coi.Spec.Windows.Network != nil &&
coi.actualSchemaVersion.IsV20() &&
coi.HostingSystem == nil {
coi.actualSchemaVersion.IsV20() {

netID, err := hns.CreateNamespace()
if err != nil {
return nil, nil, err
if coi.NetworkNamespace != "" {
resources.NetNS = coi.NetworkNamespace
} else {
err := createNetworkNamespace(coi, resources)
if err != nil {
return nil, nil, err
}
}
logrus.Infof("created network namespace %s for %s", netID, coi.ID)
resources.NetworkNamespace = netID
coi.networkNamespace = netID
if coi.Spec.Windows != nil && coi.Spec.Windows.Network != nil {
for _, endpoint := range coi.Spec.Windows.Network.EndpointList {
err = hns.AddNamespaceEndpoint(netID, endpoint)
if err != nil {
return nil, nil, err
}
logrus.Infof("added network endpoint %s to namespace %s", endpoint, netID)
resources.NetworkEndpoints = append(resources.NetworkEndpoints, endpoint)
coi.actualNetworkNamespace = resources.NetNS
if coi.HostingSystem != nil {
endpoints, err := getNamespaceEndpoints(coi.actualNetworkNamespace)
if err != nil {
return nil, nil, err
}
err = coi.HostingSystem.AddNetNS(coi.actualNetworkNamespace, endpoints)
if err != nil {
return nil, nil, err
}
resources.AddedNetNSToVM = true
}
}

Expand Down Expand Up @@ -287,7 +289,7 @@ func createHCSContainerDocument(coi *createOptionsInternal, operatingSystem stri
v2Container.Networking = &hcsschemav2.ContainersResourcesNetworkingV2{}

v1.EndpointList = coi.Spec.Windows.Network.EndpointList
v2Container.Networking.Namespace = coi.networkNamespace
v2Container.Networking.Namespace = coi.actualNetworkNamespace

v1.AllowUnqualifiedDNSQuery = coi.Spec.Windows.Network.AllowUnqualifiedDNSQuery
v2Container.Networking.AllowUnqualifiedDnsQuery = v1.AllowUnqualifiedDNSQuery
Expand Down
Loading

0 comments on commit 5ab7622

Please sign in to comment.