Merge pull request #70896 from ksubrmnn/overlay_dsr

Adding Windows Overlay support to Kube Proxy
This commit is contained in:
Kubernetes Prow Robot 2019-02-20 12:53:13 -08:00 committed by GitHub
commit c06ca11b5d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
233 changed files with 14327 additions and 4394 deletions

98
Godeps/Godeps.json generated
View File

@ -148,13 +148,103 @@
},
{
"ImportPath": "github.com/Microsoft/go-winio",
"Comment": "v0.4.5",
"Rev": "78439966b38d69bf38227fbf57ac8a6fee70f69a"
"Comment": "v0.4.11",
"Rev": "97e4973ce50b2ff5f09635a57e2b88a037aae829"
},
{
"ImportPath": "github.com/Microsoft/hcsshim",
"Comment": "v0.6.11",
"Rev": "800683ae704ac360b2f3f47fa88f3a6c8c9091b5"
"Comment": "v0.8.3-65-g69ac8d3f7fc10a",
"Rev": "69ac8d3f7fc10a0623f3a2655958a1a5bb71f58f"
},
{
"ImportPath": "github.com/Microsoft/hcsshim/hcn",
"Comment": "v0.8.3-65-g69ac8d3f7fc10a",
"Rev": "69ac8d3f7fc10a0623f3a2655958a1a5bb71f58f"
},
{
"ImportPath": "github.com/Microsoft/hcsshim/internal/cni",
"Comment": "v0.8.3-65-g69ac8d3f7fc10a",
"Rev": "69ac8d3f7fc10a0623f3a2655958a1a5bb71f58f"
},
{
"ImportPath": "github.com/Microsoft/hcsshim/internal/guestrequest",
"Comment": "v0.8.3-65-g69ac8d3f7fc10a",
"Rev": "69ac8d3f7fc10a0623f3a2655958a1a5bb71f58f"
},
{
"ImportPath": "github.com/Microsoft/hcsshim/internal/guid",
"Comment": "v0.8.3-65-g69ac8d3f7fc10a",
"Rev": "69ac8d3f7fc10a0623f3a2655958a1a5bb71f58f"
},
{
"ImportPath": "github.com/Microsoft/hcsshim/internal/hcs",
"Comment": "v0.8.3-65-g69ac8d3f7fc10a",
"Rev": "69ac8d3f7fc10a0623f3a2655958a1a5bb71f58f"
},
{
"ImportPath": "github.com/Microsoft/hcsshim/internal/hcserror",
"Comment": "v0.8.3-65-g69ac8d3f7fc10a",
"Rev": "69ac8d3f7fc10a0623f3a2655958a1a5bb71f58f"
},
{
"ImportPath": "github.com/Microsoft/hcsshim/internal/hns",
"Comment": "v0.8.3-65-g69ac8d3f7fc10a",
"Rev": "69ac8d3f7fc10a0623f3a2655958a1a5bb71f58f"
},
{
"ImportPath": "github.com/Microsoft/hcsshim/internal/interop",
"Comment": "v0.8.3-65-g69ac8d3f7fc10a",
"Rev": "69ac8d3f7fc10a0623f3a2655958a1a5bb71f58f"
},
{
"ImportPath": "github.com/Microsoft/hcsshim/internal/logfields",
"Comment": "v0.8.3-65-g69ac8d3f7fc10a",
"Rev": "69ac8d3f7fc10a0623f3a2655958a1a5bb71f58f"
},
{
"ImportPath": "github.com/Microsoft/hcsshim/internal/longpath",
"Comment": "v0.8.3-65-g69ac8d3f7fc10a",
"Rev": "69ac8d3f7fc10a0623f3a2655958a1a5bb71f58f"
},
{
"ImportPath": "github.com/Microsoft/hcsshim/internal/mergemaps",
"Comment": "v0.8.3-65-g69ac8d3f7fc10a",
"Rev": "69ac8d3f7fc10a0623f3a2655958a1a5bb71f58f"
},
{
"ImportPath": "github.com/Microsoft/hcsshim/internal/regstate",
"Comment": "v0.8.3-65-g69ac8d3f7fc10a",
"Rev": "69ac8d3f7fc10a0623f3a2655958a1a5bb71f58f"
},
{
"ImportPath": "github.com/Microsoft/hcsshim/internal/runhcs",
"Comment": "v0.8.3-65-g69ac8d3f7fc10a",
"Rev": "69ac8d3f7fc10a0623f3a2655958a1a5bb71f58f"
},
{
"ImportPath": "github.com/Microsoft/hcsshim/internal/safefile",
"Comment": "v0.8.3-65-g69ac8d3f7fc10a",
"Rev": "69ac8d3f7fc10a0623f3a2655958a1a5bb71f58f"
},
{
"ImportPath": "github.com/Microsoft/hcsshim/internal/schema1",
"Comment": "v0.8.3-65-g69ac8d3f7fc10a",
"Rev": "69ac8d3f7fc10a0623f3a2655958a1a5bb71f58f"
},
{
"ImportPath": "github.com/Microsoft/hcsshim/internal/schema2",
"Comment": "v0.8.3-65-g69ac8d3f7fc10a",
"Rev": "69ac8d3f7fc10a0623f3a2655958a1a5bb71f58f"
},
{
"ImportPath": "github.com/Microsoft/hcsshim/internal/timeout",
"Comment": "v0.8.3-65-g69ac8d3f7fc10a",
"Rev": "69ac8d3f7fc10a0623f3a2655958a1a5bb71f58f"
},
{
"ImportPath": "github.com/Microsoft/hcsshim/internal/wclayer",
"Comment": "v0.8.3-65-g69ac8d3f7fc10a",
"Rev": "69ac8d3f7fc10a0623f3a2655958a1a5bb71f58f"
},
{
"ImportPath": "github.com/NYTimes/gziphandler",

504
Godeps/LICENSES generated
View File

@ -79344,6 +79344,510 @@ SOFTWARE.
================================================================================
================================================================================
= vendor/github.com/Microsoft/hcsshim/hcn licensed under: =
The MIT License (MIT)
Copyright (c) 2015 Microsoft
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
= vendor/github.com/Microsoft/hcsshim/LICENSE d4c2cbbea5ee1e7c86dff68a7073718e
================================================================================
================================================================================
= vendor/github.com/Microsoft/hcsshim/internal/cni licensed under: =
The MIT License (MIT)
Copyright (c) 2015 Microsoft
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
= vendor/github.com/Microsoft/hcsshim/LICENSE d4c2cbbea5ee1e7c86dff68a7073718e
================================================================================
================================================================================
= vendor/github.com/Microsoft/hcsshim/internal/guestrequest licensed under: =
The MIT License (MIT)
Copyright (c) 2015 Microsoft
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
= vendor/github.com/Microsoft/hcsshim/LICENSE d4c2cbbea5ee1e7c86dff68a7073718e
================================================================================
================================================================================
= vendor/github.com/Microsoft/hcsshim/internal/guid licensed under: =
The MIT License (MIT)
Copyright (c) 2015 Microsoft
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
= vendor/github.com/Microsoft/hcsshim/LICENSE d4c2cbbea5ee1e7c86dff68a7073718e
================================================================================
================================================================================
= vendor/github.com/Microsoft/hcsshim/internal/hcs licensed under: =
The MIT License (MIT)
Copyright (c) 2015 Microsoft
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
= vendor/github.com/Microsoft/hcsshim/LICENSE d4c2cbbea5ee1e7c86dff68a7073718e
================================================================================
================================================================================
= vendor/github.com/Microsoft/hcsshim/internal/hcserror licensed under: =
The MIT License (MIT)
Copyright (c) 2015 Microsoft
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
= vendor/github.com/Microsoft/hcsshim/LICENSE d4c2cbbea5ee1e7c86dff68a7073718e
================================================================================
================================================================================
= vendor/github.com/Microsoft/hcsshim/internal/hns licensed under: =
The MIT License (MIT)
Copyright (c) 2015 Microsoft
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
= vendor/github.com/Microsoft/hcsshim/LICENSE d4c2cbbea5ee1e7c86dff68a7073718e
================================================================================
================================================================================
= vendor/github.com/Microsoft/hcsshim/internal/interop licensed under: =
The MIT License (MIT)
Copyright (c) 2015 Microsoft
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
= vendor/github.com/Microsoft/hcsshim/LICENSE d4c2cbbea5ee1e7c86dff68a7073718e
================================================================================
================================================================================
= vendor/github.com/Microsoft/hcsshim/internal/logfields licensed under: =
The MIT License (MIT)
Copyright (c) 2015 Microsoft
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
= vendor/github.com/Microsoft/hcsshim/LICENSE d4c2cbbea5ee1e7c86dff68a7073718e
================================================================================
================================================================================
= vendor/github.com/Microsoft/hcsshim/internal/longpath licensed under: =
The MIT License (MIT)
Copyright (c) 2015 Microsoft
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
= vendor/github.com/Microsoft/hcsshim/LICENSE d4c2cbbea5ee1e7c86dff68a7073718e
================================================================================
================================================================================
= vendor/github.com/Microsoft/hcsshim/internal/mergemaps licensed under: =
The MIT License (MIT)
Copyright (c) 2015 Microsoft
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
= vendor/github.com/Microsoft/hcsshim/LICENSE d4c2cbbea5ee1e7c86dff68a7073718e
================================================================================
================================================================================
= vendor/github.com/Microsoft/hcsshim/internal/regstate licensed under: =
The MIT License (MIT)
Copyright (c) 2015 Microsoft
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
= vendor/github.com/Microsoft/hcsshim/LICENSE d4c2cbbea5ee1e7c86dff68a7073718e
================================================================================
================================================================================
= vendor/github.com/Microsoft/hcsshim/internal/runhcs licensed under: =
The MIT License (MIT)
Copyright (c) 2015 Microsoft
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
= vendor/github.com/Microsoft/hcsshim/LICENSE d4c2cbbea5ee1e7c86dff68a7073718e
================================================================================
================================================================================
= vendor/github.com/Microsoft/hcsshim/internal/safefile licensed under: =
The MIT License (MIT)
Copyright (c) 2015 Microsoft
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
= vendor/github.com/Microsoft/hcsshim/LICENSE d4c2cbbea5ee1e7c86dff68a7073718e
================================================================================
================================================================================
= vendor/github.com/Microsoft/hcsshim/internal/schema1 licensed under: =
The MIT License (MIT)
Copyright (c) 2015 Microsoft
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
= vendor/github.com/Microsoft/hcsshim/LICENSE d4c2cbbea5ee1e7c86dff68a7073718e
================================================================================
================================================================================
= vendor/github.com/Microsoft/hcsshim/internal/schema2 licensed under: =
The MIT License (MIT)
Copyright (c) 2015 Microsoft
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
= vendor/github.com/Microsoft/hcsshim/LICENSE d4c2cbbea5ee1e7c86dff68a7073718e
================================================================================
================================================================================
= vendor/github.com/Microsoft/hcsshim/internal/timeout licensed under: =
The MIT License (MIT)
Copyright (c) 2015 Microsoft
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
= vendor/github.com/Microsoft/hcsshim/LICENSE d4c2cbbea5ee1e7c86dff68a7073718e
================================================================================
================================================================================
= vendor/github.com/Microsoft/hcsshim/internal/wclayer licensed under: =
The MIT License (MIT)
Copyright (c) 2015 Microsoft
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
= vendor/github.com/Microsoft/hcsshim/LICENSE d4c2cbbea5ee1e7c86dff68a7073718e
================================================================================
================================================================================
= vendor/github.com/miekg/dns licensed under: =

View File

@ -37,4 +37,7 @@ func initForOS(windowsService bool) error {
func (o *Options) addOSFlags(fs *pflag.FlagSet) {
fs.BoolVar(&o.WindowsService, "windows-service", o.WindowsService, "Enable Windows Service Control Manager API integration")
fs.StringVar(&o.config.Winkernel.SourceVip, "source-vip", o.config.Winkernel.SourceVip, "The IP address of the source VIP for non-DSR.")
fs.StringVar(&o.config.Winkernel.NetworkName, "network-name", o.config.Winkernel.NetworkName, "The name of the cluster network.")
fs.BoolVar(&o.config.Winkernel.EnableDSR, "enable-dsr", o.config.Winkernel.EnableDSR, "If true make kube-proxy apply DSR policies for service VIP")
}

View File

@ -110,6 +110,7 @@ func newProxyServer(config *proxyconfigapi.KubeProxyConfiguration, cleanupAndExi
utilnode.GetNodeIP(client, hostname),
recorder,
healthzUpdater,
config.Winkernel,
)
if err != nil {
return nil, fmt.Errorf("unable to create proxier: %v", err)

View File

@ -67,6 +67,10 @@ ComponentConfigs:
PortRange: ""
ResourceContainer: /kube-proxy
UDPIdleTimeout: 250ms
Winkernel:
EnableDSR: false
NetworkName: ""
SourceVip: ""
Kubelet:
Address: 1.2.3.4
Authentication:

View File

@ -90,6 +90,10 @@ oomScoreAdj: -999
portRange: ""
resourceContainer: /kube-proxy
udpIdleTimeout: 250ms
winkernel:
enableDSR: false
networkName: ""
sourceVip: ""
---
address: 1.2.3.4
apiVersion: kubelet.config.k8s.io/v1beta1

View File

@ -76,6 +76,10 @@ oomScoreAdj: -999
portRange: ""
resourceContainer: /kube-proxy
udpIdleTimeout: 250ms
winkernel:
enableDSR: false
networkName: ""
sourceVip: ""
---
address: 0.0.0.0
apiVersion: kubelet.config.k8s.io/v1beta1

View File

@ -78,6 +78,20 @@ type KubeProxyConntrackConfiguration struct {
TCPCloseWaitTimeout *metav1.Duration
}
// KubeProxyWinkernelConfiguration contains Windows/HNS settings for
// the Kubernetes proxy server.
type KubeProxyWinkernelConfiguration struct {
// networkName is the name of the network kube-proxy will use
// to create endpoints and policies
NetworkName string
// sourceVip is the IP address of the source VIP endoint used for
// NAT when loadbalancing
SourceVip string
// enableDSR tells kube-proxy whether HNS policies should be created
// with DSR
EnableDSR bool
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// KubeProxyConfiguration contains everything necessary to configure the
@ -140,6 +154,8 @@ type KubeProxyConfiguration struct {
// If set it to a non-zero IP block, kube-proxy will filter that down to just the IPs that applied to the node.
// An empty string slice is meant to select all network interfaces.
NodePortAddresses []string
// winkernel contains winkernel-related configuration options.
Winkernel KubeProxyWinkernelConfiguration
}
// Currently, three modes of proxy are available in Linux platform: 'userspace' (older, going to be EOL), 'iptables'

View File

@ -78,6 +78,16 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*v1alpha1.KubeProxyWinkernelConfiguration)(nil), (*config.KubeProxyWinkernelConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha1_KubeProxyWinkernelConfiguration_To_config_KubeProxyWinkernelConfiguration(a.(*v1alpha1.KubeProxyWinkernelConfiguration), b.(*config.KubeProxyWinkernelConfiguration), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*config.KubeProxyWinkernelConfiguration)(nil), (*v1alpha1.KubeProxyWinkernelConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_config_KubeProxyWinkernelConfiguration_To_v1alpha1_KubeProxyWinkernelConfiguration(a.(*config.KubeProxyWinkernelConfiguration), b.(*v1alpha1.KubeProxyWinkernelConfiguration), scope)
}); err != nil {
return err
}
return nil
}
@ -108,6 +118,9 @@ func autoConvert_v1alpha1_KubeProxyConfiguration_To_config_KubeProxyConfiguratio
}
out.ConfigSyncPeriod = in.ConfigSyncPeriod
out.NodePortAddresses = *(*[]string)(unsafe.Pointer(&in.NodePortAddresses))
if err := Convert_v1alpha1_KubeProxyWinkernelConfiguration_To_config_KubeProxyWinkernelConfiguration(&in.Winkernel, &out.Winkernel, s); err != nil {
return err
}
return nil
}
@ -143,6 +156,9 @@ func autoConvert_config_KubeProxyConfiguration_To_v1alpha1_KubeProxyConfiguratio
}
out.ConfigSyncPeriod = in.ConfigSyncPeriod
out.NodePortAddresses = *(*[]string)(unsafe.Pointer(&in.NodePortAddresses))
if err := Convert_config_KubeProxyWinkernelConfiguration_To_v1alpha1_KubeProxyWinkernelConfiguration(&in.Winkernel, &out.Winkernel, s); err != nil {
return err
}
return nil
}
@ -230,3 +246,27 @@ func autoConvert_config_KubeProxyIPVSConfiguration_To_v1alpha1_KubeProxyIPVSConf
func Convert_config_KubeProxyIPVSConfiguration_To_v1alpha1_KubeProxyIPVSConfiguration(in *config.KubeProxyIPVSConfiguration, out *v1alpha1.KubeProxyIPVSConfiguration, s conversion.Scope) error {
return autoConvert_config_KubeProxyIPVSConfiguration_To_v1alpha1_KubeProxyIPVSConfiguration(in, out, s)
}
func autoConvert_v1alpha1_KubeProxyWinkernelConfiguration_To_config_KubeProxyWinkernelConfiguration(in *v1alpha1.KubeProxyWinkernelConfiguration, out *config.KubeProxyWinkernelConfiguration, s conversion.Scope) error {
out.NetworkName = in.NetworkName
out.SourceVip = in.SourceVip
out.EnableDSR = in.EnableDSR
return nil
}
// Convert_v1alpha1_KubeProxyWinkernelConfiguration_To_config_KubeProxyWinkernelConfiguration is an autogenerated conversion function.
func Convert_v1alpha1_KubeProxyWinkernelConfiguration_To_config_KubeProxyWinkernelConfiguration(in *v1alpha1.KubeProxyWinkernelConfiguration, out *config.KubeProxyWinkernelConfiguration, s conversion.Scope) error {
return autoConvert_v1alpha1_KubeProxyWinkernelConfiguration_To_config_KubeProxyWinkernelConfiguration(in, out, s)
}
func autoConvert_config_KubeProxyWinkernelConfiguration_To_v1alpha1_KubeProxyWinkernelConfiguration(in *config.KubeProxyWinkernelConfiguration, out *v1alpha1.KubeProxyWinkernelConfiguration, s conversion.Scope) error {
out.NetworkName = in.NetworkName
out.SourceVip = in.SourceVip
out.EnableDSR = in.EnableDSR
return nil
}
// Convert_config_KubeProxyWinkernelConfiguration_To_v1alpha1_KubeProxyWinkernelConfiguration is an autogenerated conversion function.
func Convert_config_KubeProxyWinkernelConfiguration_To_v1alpha1_KubeProxyWinkernelConfiguration(in *config.KubeProxyWinkernelConfiguration, out *v1alpha1.KubeProxyWinkernelConfiguration, s conversion.Scope) error {
return autoConvert_config_KubeProxyWinkernelConfiguration_To_v1alpha1_KubeProxyWinkernelConfiguration(in, out, s)
}

View File

@ -74,6 +74,7 @@ func (in *KubeProxyConfiguration) DeepCopyInto(out *KubeProxyConfiguration) {
*out = make([]string, len(*in))
copy(*out, *in)
}
out.Winkernel = in.Winkernel
return
}
@ -181,3 +182,19 @@ func (in *KubeProxyIPVSConfiguration) DeepCopy() *KubeProxyIPVSConfiguration {
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *KubeProxyWinkernelConfiguration) DeepCopyInto(out *KubeProxyWinkernelConfiguration) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubeProxyWinkernelConfiguration.
func (in *KubeProxyWinkernelConfiguration) DeepCopy() *KubeProxyWinkernelConfiguration {
if in == nil {
return nil
}
out := new(KubeProxyWinkernelConfiguration)
in.DeepCopyInto(out)
return out
}

View File

@ -1,8 +1,10 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
go_library(
name = "go_default_library",
srcs = [
"hnsV1.go",
"hnsV2.go",
"metrics.go",
"proxier.go",
],
@ -15,14 +17,18 @@ go_library(
"//pkg/api/v1/service:go_default_library",
"//pkg/apis/core/v1/helper:go_default_library",
"//pkg/proxy:go_default_library",
"//pkg/proxy/apis/config:go_default_library",
"//pkg/proxy/healthcheck:go_default_library",
"//pkg/util/async:go_default_library",
"//staging/src/k8s.io/api/core/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/features:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
"//staging/src/k8s.io/client-go/tools/record:go_default_library",
"//vendor/github.com/Microsoft/hcsshim:go_default_library",
"//vendor/github.com/Microsoft/hcsshim/hcn:go_default_library",
"//vendor/github.com/davecgh/go-spew/spew:go_default_library",
"//vendor/k8s.io/klog:go_default_library",
],
@ -43,3 +49,22 @@ filegroup(
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
go_test(
name = "go_default_test",
srcs = [
"hns_test.go",
"proxier_test.go",
],
embed = [":go_default_library"],
deps = select({
"@io_bazel_rules_go//go/platform:windows": [
"//pkg/proxy:go_default_library",
"//staging/src/k8s.io/api/core/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
"//vendor/github.com/Microsoft/hcsshim/hcn:go_default_library",
],
"//conditions:default": [],
}),
)

View File

@ -0,0 +1,225 @@
// +build windows
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License 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 winkernel
import (
"encoding/json"
"fmt"
"github.com/Microsoft/hcsshim"
"k8s.io/klog"
"net"
"strings"
)
type HostNetworkService interface {
getNetworkByName(name string) (*hnsNetworkInfo, error)
getEndpointByID(id string) (*endpointsInfo, error)
getEndpointByIpAddress(ip string, networkName string) (*endpointsInfo, error)
createEndpoint(ep *endpointsInfo, networkName string) (*endpointsInfo, error)
deleteEndpoint(hnsID string) error
getLoadBalancer(endpoints []endpointsInfo, isILB bool, isDSR bool, sourceVip string, vip string, protocol uint16, internalPort uint16, externalPort uint16) (*loadBalancerInfo, error)
deleteLoadBalancer(hnsID string) error
}
// V1 HNS API
type hnsV1 struct{}
func (hns hnsV1) getNetworkByName(name string) (*hnsNetworkInfo, error) {
hnsnetwork, err := hcsshim.GetHNSNetworkByName(name)
if err != nil {
klog.Errorf("%v", err)
return nil, err
}
return &hnsNetworkInfo{
id: hnsnetwork.Id,
name: hnsnetwork.Name,
networkType: hnsnetwork.Type,
}, nil
}
func (hns hnsV1) getEndpointByID(id string) (*endpointsInfo, error) {
hnsendpoint, err := hcsshim.GetHNSEndpointByID(id)
if err != nil {
klog.Errorf("%v", err)
return nil, err
}
return &endpointsInfo{
ip: hnsendpoint.IPAddress.String(),
isLocal: !hnsendpoint.IsRemoteEndpoint, //TODO: Change isLocal to isRemote
macAddress: hnsendpoint.MacAddress,
hnsID: hnsendpoint.Id,
hns: hns,
}, nil
}
func (hns hnsV1) getEndpointByIpAddress(ip string, networkName string) (*endpointsInfo, error) {
hnsnetwork, err := hcsshim.GetHNSNetworkByName(networkName)
if err != nil {
klog.Errorf("%v", err)
return nil, err
}
endpoints, err := hcsshim.HNSListEndpointRequest()
for _, endpoint := range endpoints {
equal := false
if endpoint.IPAddress != nil {
equal = endpoint.IPAddress.String() == ip
}
if equal && strings.EqualFold(endpoint.VirtualNetwork, hnsnetwork.Id) {
return &endpointsInfo{
ip: endpoint.IPAddress.String(),
isLocal: !endpoint.IsRemoteEndpoint,
macAddress: endpoint.MacAddress,
hnsID: endpoint.Id,
hns: hns,
}, nil
}
}
return nil, fmt.Errorf("Endpoint %v not found on network %s", ip, networkName)
}
func (hns hnsV1) createEndpoint(ep *endpointsInfo, networkName string) (*endpointsInfo, error) {
hnsNetwork, err := hcsshim.GetHNSNetworkByName(networkName)
if err != nil {
return nil, fmt.Errorf("Could not find network %s: %v", networkName, err)
}
hnsEndpoint := &hcsshim.HNSEndpoint{
MacAddress: ep.macAddress,
IPAddress: net.ParseIP(ep.ip),
}
var createdEndpoint *hcsshim.HNSEndpoint
if !ep.isLocal {
if len(ep.providerAddress) != 0 {
paPolicy := hcsshim.PaPolicy{
Type: hcsshim.PA,
PA: ep.providerAddress,
}
paPolicyJson, err := json.Marshal(paPolicy)
if err != nil {
return nil, fmt.Errorf("PA Policy creation failed: %v", err)
}
hnsEndpoint.Policies = append(hnsEndpoint.Policies, paPolicyJson)
}
createdEndpoint, err = hnsNetwork.CreateRemoteEndpoint(hnsEndpoint)
if err != nil {
return nil, fmt.Errorf("Remote endpoint creation failed: %v", err)
}
} else {
createdEndpoint, err = hnsNetwork.CreateEndpoint(hnsEndpoint)
if err != nil {
return nil, fmt.Errorf("Local endpoint creation failed: %v", err)
}
}
return &endpointsInfo{
ip: createdEndpoint.IPAddress.String(),
isLocal: createdEndpoint.IsRemoteEndpoint,
macAddress: createdEndpoint.MacAddress,
hnsID: createdEndpoint.Id,
providerAddress: ep.providerAddress, //TODO get from createdEndpoint
hns: hns,
}, nil
}
func (hns hnsV1) deleteEndpoint(hnsID string) error {
hnsendpoint, err := hcsshim.GetHNSEndpointByID(hnsID)
if err != nil {
return err
}
_, err = hnsendpoint.Delete()
if err == nil {
klog.V(3).Infof("Remote endpoint resource deleted id %s", hnsID)
}
return err
}
func (hns hnsV1) getLoadBalancer(endpoints []endpointsInfo, isILB bool, isDSR bool, sourceVip string, vip string, protocol uint16, internalPort uint16, externalPort uint16) (*loadBalancerInfo, error) {
plists, err := hcsshim.HNSListPolicyListRequest()
if err != nil {
return nil, err
}
if isDSR {
klog.V(3).Info("DSR is not supported in V1. Using non DSR instead")
}
for _, plist := range plists {
if len(plist.EndpointReferences) != len(endpoints) {
continue
}
// Validate if input meets any of the policy lists
elbPolicy := hcsshim.ELBPolicy{}
if err = json.Unmarshal(plist.Policies[0], &elbPolicy); err != nil {
continue
}
if elbPolicy.Protocol == protocol && elbPolicy.InternalPort == internalPort && elbPolicy.ExternalPort == externalPort && elbPolicy.ILB == isILB {
if len(vip) > 0 {
if len(elbPolicy.VIPs) == 0 || elbPolicy.VIPs[0] != vip {
continue
}
}
LogJson(plist, "Found existing Hns loadbalancer policy resource", 1)
return &loadBalancerInfo{
hnsID: plist.ID,
}, nil
}
}
var hnsEndpoints []hcsshim.HNSEndpoint
for _, ep := range endpoints {
endpoint, err := hcsshim.GetHNSEndpointByID(ep.hnsID)
if err != nil {
return nil, err
}
hnsEndpoints = append(hnsEndpoints, *endpoint)
}
lb, err := hcsshim.AddLoadBalancer(
hnsEndpoints,
isILB,
sourceVip,
vip,
protocol,
internalPort,
externalPort,
)
if err == nil {
LogJson(lb, "Hns loadbalancer policy resource", 1)
} else {
return nil, err
}
return &loadBalancerInfo{
hnsID: lb.ID,
}, err
}
func (hns hnsV1) deleteLoadBalancer(hnsID string) error {
if len(hnsID) == 0 {
// Return silently
return nil
}
// Cleanup HNS policies
hnsloadBalancer, err := hcsshim.GetPolicyListByID(hnsID)
if err != nil {
return err
}
LogJson(hnsloadBalancer, "Removing Policy", 2)
_, err = hnsloadBalancer.Delete()
return err
}

View File

@ -0,0 +1,239 @@
// +build windows
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License 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 winkernel
import (
"encoding/json"
"fmt"
"github.com/Microsoft/hcsshim/hcn"
"k8s.io/klog"
"strings"
)
type hnsV2 struct{}
func (hns hnsV2) getNetworkByName(name string) (*hnsNetworkInfo, error) {
hnsnetwork, err := hcn.GetNetworkByName(name)
if err != nil {
klog.Errorf("%v", err)
return nil, err
}
var remoteSubnets []*remoteSubnetInfo
for _, policy := range hnsnetwork.Policies {
if policy.Type == hcn.RemoteSubnetRoute {
policySettings := hcn.RemoteSubnetRoutePolicySetting{}
err = json.Unmarshal(policy.Settings, &policySettings)
if err != nil {
return nil, fmt.Errorf("Failed to unmarshal Remote Subnet policy settings")
}
rs := &remoteSubnetInfo{
destinationPrefix: policySettings.DestinationPrefix,
isolationId: policySettings.IsolationId,
providerAddress: policySettings.ProviderAddress,
drMacAddress: policySettings.DistributedRouterMacAddress,
}
remoteSubnets = append(remoteSubnets, rs)
}
}
return &hnsNetworkInfo{
id: hnsnetwork.Id,
name: hnsnetwork.Name,
networkType: string(hnsnetwork.Type),
remoteSubnets: remoteSubnets,
}, nil
}
func (hns hnsV2) getEndpointByID(id string) (*endpointsInfo, error) {
hnsendpoint, err := hcn.GetEndpointByID(id)
if err != nil {
return nil, err
}
return &endpointsInfo{ //TODO: fill out PA
ip: hnsendpoint.IpConfigurations[0].IpAddress,
isLocal: uint32(hnsendpoint.Flags&hcn.EndpointFlagsRemoteEndpoint) == 0, //TODO: Change isLocal to isRemote
macAddress: hnsendpoint.MacAddress,
hnsID: hnsendpoint.Id,
hns: hns,
}, nil
}
func (hns hnsV2) getEndpointByIpAddress(ip string, networkName string) (*endpointsInfo, error) {
hnsnetwork, err := hcn.GetNetworkByName(networkName)
if err != nil {
klog.Errorf("%v", err)
return nil, err
}
endpoints, err := hcn.ListEndpoints()
for _, endpoint := range endpoints {
equal := false
if endpoint.IpConfigurations != nil && len(endpoint.IpConfigurations) > 0 {
equal = endpoint.IpConfigurations[0].IpAddress == ip
}
if equal && strings.EqualFold(endpoint.HostComputeNetwork, hnsnetwork.Id) {
return &endpointsInfo{
ip: endpoint.IpConfigurations[0].IpAddress,
isLocal: uint32(endpoint.Flags&hcn.EndpointFlagsRemoteEndpoint) == 0, //TODO: Change isLocal to isRemote
macAddress: endpoint.MacAddress,
hnsID: endpoint.Id,
hns: hns,
}, nil
}
}
return nil, fmt.Errorf("Endpoint %v not found on network %s", ip, networkName)
}
func (hns hnsV2) createEndpoint(ep *endpointsInfo, networkName string) (*endpointsInfo, error) {
hnsNetwork, err := hcn.GetNetworkByName(networkName)
if err != nil {
return nil, fmt.Errorf("Could not find network %s: %v", networkName, err)
}
var flags hcn.EndpointFlags
if !ep.isLocal {
flags |= hcn.EndpointFlagsRemoteEndpoint
}
ipConfig := &hcn.IpConfig{
IpAddress: ep.ip,
}
hnsEndpoint := &hcn.HostComputeEndpoint{
IpConfigurations: []hcn.IpConfig{*ipConfig},
MacAddress: ep.macAddress,
Flags: flags,
SchemaVersion: hcn.SchemaVersion{
Major: 2,
Minor: 0,
},
}
var createdEndpoint *hcn.HostComputeEndpoint
if !ep.isLocal {
if len(ep.providerAddress) != 0 {
policySettings := hcn.ProviderAddressEndpointPolicySetting{
ProviderAddress: ep.providerAddress,
}
policySettingsJson, err := json.Marshal(policySettings)
if err != nil {
return nil, fmt.Errorf("PA Policy creation failed: %v", err)
}
paPolicy := hcn.EndpointPolicy{
Type: hcn.NetworkProviderAddress,
Settings: policySettingsJson,
}
hnsEndpoint.Policies = append(hnsEndpoint.Policies, paPolicy)
}
createdEndpoint, err = hnsNetwork.CreateRemoteEndpoint(hnsEndpoint)
if err != nil {
return nil, fmt.Errorf("Remote endpoint creation failed: %v", err)
}
} else {
createdEndpoint, err = hnsNetwork.CreateEndpoint(hnsEndpoint)
if err != nil {
return nil, fmt.Errorf("Local endpoint creation failed: %v", err)
}
}
return &endpointsInfo{
ip: createdEndpoint.IpConfigurations[0].IpAddress,
isLocal: uint32(createdEndpoint.Flags&hcn.EndpointFlagsRemoteEndpoint) == 0,
macAddress: createdEndpoint.MacAddress,
hnsID: createdEndpoint.Id,
providerAddress: ep.providerAddress, //TODO get from createdEndpoint
hns: hns,
}, nil
}
func (hns hnsV2) deleteEndpoint(hnsID string) error {
hnsendpoint, err := hcn.GetEndpointByID(hnsID)
if err != nil {
return err
}
err = hnsendpoint.Delete()
if err == nil {
klog.V(3).Infof("Remote endpoint resource deleted id %s", hnsID)
}
return err
}
func (hns hnsV2) getLoadBalancer(endpoints []endpointsInfo, isILB bool, isDSR bool, sourceVip string, vip string, protocol uint16, internalPort uint16, externalPort uint16) (*loadBalancerInfo, error) {
plists, err := hcn.ListLoadBalancers()
if err != nil {
return nil, err
}
for _, plist := range plists {
if len(plist.HostComputeEndpoints) != len(endpoints) {
continue
}
// Validate if input meets any of the policy lists
lbPortMapping := plist.PortMappings[0]
if lbPortMapping.Protocol == uint32(protocol) && lbPortMapping.InternalPort == internalPort && lbPortMapping.ExternalPort == externalPort && (lbPortMapping.Flags&1 != 0) == isILB {
if len(vip) > 0 {
if len(plist.FrontendVIPs) == 0 || plist.FrontendVIPs[0] != vip {
continue
}
}
LogJson(plist, "Found existing Hns loadbalancer policy resource", 1)
return &loadBalancerInfo{
hnsID: plist.Id,
}, nil
}
}
var hnsEndpoints []hcn.HostComputeEndpoint
for _, ep := range endpoints {
endpoint, err := hcn.GetEndpointByID(ep.hnsID)
if err != nil {
return nil, err
}
hnsEndpoints = append(hnsEndpoints, *endpoint)
}
vips := []string{}
if len(vip) > 0 {
vips = append(vips, vip)
}
lb, err := hcn.AddLoadBalancer(
hnsEndpoints,
isILB,
isDSR,
sourceVip,
vips,
protocol,
internalPort,
externalPort,
)
if err != nil {
return nil, err
}
LogJson(lb, "Hns loadbalancer policy resource", 1)
return &loadBalancerInfo{
hnsID: lb.Id,
}, err
}
func (hns hnsV2) deleteLoadBalancer(hnsID string) error {
lb, err := hcn.GetLoadBalancerByID(hnsID)
if err != nil {
// Return silently
return nil
}
err = lb.Delete()
return err
}

View File

@ -0,0 +1,557 @@
// +build windows
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License 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 winkernel
import (
"encoding/json"
"github.com/Microsoft/hcsshim/hcn"
"strings"
"testing"
)
const sourceVip = "192.168.1.2"
const serviceVip = "11.0.0.1"
const addressPrefix = "192.168.1.0/24"
const gatewayAddress = "192.168.1.1"
const epMacAddress = "00-11-22-33-44-55"
const epIpAddress = "192.168.1.3"
const epIpAddressRemote = "192.168.2.3"
const epPaAddress = "10.0.0.3"
const protocol = 6
const internalPort = 80
const externalPort = 32440
func TestGetNetworkByName(t *testing.T) {
hnsV1 := hnsV1{}
hnsV2 := hnsV2{}
testGetNetworkByName(t, hnsV1)
testGetNetworkByName(t, hnsV2)
}
func TestGetEndpointByID(t *testing.T) {
hnsV1 := hnsV1{}
hnsV2 := hnsV2{}
testGetEndpointByID(t, hnsV1)
testGetEndpointByID(t, hnsV2)
}
func TestGetEndpointByIpAddress(t *testing.T) {
hnsV1 := hnsV1{}
hnsV2 := hnsV2{}
testGetEndpointByIpAddress(t, hnsV1)
testGetEndpointByIpAddress(t, hnsV2)
}
func TestCreateEndpointLocal(t *testing.T) {
hnsV1 := hnsV1{}
hnsV2 := hnsV2{}
testCreateEndpointLocal(t, hnsV1)
testCreateEndpointLocal(t, hnsV2)
}
func TestCreateEndpointRemotePA(t *testing.T) {
hnsV1 := hnsV1{}
hnsV2 := hnsV2{}
testCreateEndpointRemote(t, hnsV1, epPaAddress)
testCreateEndpointRemote(t, hnsV2, epPaAddress)
}
func TestCreateEndpointRemoteNoPA(t *testing.T) {
hnsV1 := hnsV1{}
hnsV2 := hnsV2{}
testCreateEndpointRemote(t, hnsV1, "")
testCreateEndpointRemote(t, hnsV2, "")
}
func TestDeleteEndpoint(t *testing.T) {
hnsV1 := hnsV1{}
hnsV2 := hnsV2{}
testDeleteEndpoint(t, hnsV1)
testDeleteEndpoint(t, hnsV2)
}
func TestGetLoadBalancerExisting(t *testing.T) {
hnsV1 := hnsV1{}
hnsV2 := hnsV2{}
testGetLoadBalancerExisting(t, hnsV1)
testGetLoadBalancerExisting(t, hnsV2)
}
func TestGetLoadBalancerNew(t *testing.T) {
hnsV1 := hnsV1{}
hnsV2 := hnsV2{}
testGetLoadBalancerNew(t, hnsV1)
testGetLoadBalancerNew(t, hnsV2)
}
func TestDeleteLoadBalancer(t *testing.T) {
hnsV1 := hnsV1{}
hnsV2 := hnsV2{}
testDeleteLoadBalancer(t, hnsV1)
testDeleteLoadBalancer(t, hnsV2)
}
func testGetNetworkByName(t *testing.T, hns HostNetworkService) {
Network, err := createTestNetwork()
if err != nil {
t.Error(err)
}
network, err := hns.getNetworkByName(Network.Name)
if err != nil {
t.Error(err)
}
if !strings.EqualFold(network.id, Network.Id) {
t.Errorf("%v does not match %v", network.id, Network.Id)
}
err = Network.Delete()
if err != nil {
t.Error(err)
}
}
func testGetEndpointByID(t *testing.T, hns HostNetworkService) {
Network, err := createTestNetwork()
if err != nil {
t.Error(err)
}
ipConfig := &hcn.IpConfig{
IpAddress: epIpAddress,
}
Endpoint := &hcn.HostComputeEndpoint{
IpConfigurations: []hcn.IpConfig{*ipConfig},
MacAddress: epMacAddress,
SchemaVersion: hcn.SchemaVersion{
Major: 2,
Minor: 0,
},
}
Endpoint, err = Network.CreateEndpoint(Endpoint)
if err != nil {
t.Error(err)
}
endpoint, err := hns.getEndpointByID(Endpoint.Id)
if err != nil {
t.Error(err)
}
if !strings.EqualFold(endpoint.hnsID, Endpoint.Id) {
t.Errorf("%v does not match %v", endpoint.hnsID, Endpoint.Id)
}
err = Endpoint.Delete()
if err != nil {
t.Error(err)
}
err = Network.Delete()
if err != nil {
t.Error(err)
}
}
func testGetEndpointByIpAddress(t *testing.T, hns HostNetworkService) {
Network, err := createTestNetwork()
if err != nil {
t.Error(err)
}
ipConfig := &hcn.IpConfig{
IpAddress: epIpAddress,
}
Endpoint := &hcn.HostComputeEndpoint{
IpConfigurations: []hcn.IpConfig{*ipConfig},
MacAddress: epMacAddress,
SchemaVersion: hcn.SchemaVersion{
Major: 2,
Minor: 0,
},
}
Endpoint, err = Network.CreateEndpoint(Endpoint)
if err != nil {
t.Error(err)
}
endpoint, err := hns.getEndpointByIpAddress(Endpoint.IpConfigurations[0].IpAddress, Network.Name)
if err != nil {
t.Error(err)
}
if !strings.EqualFold(endpoint.hnsID, Endpoint.Id) {
t.Errorf("%v does not match %v", endpoint.hnsID, Endpoint.Id)
}
if endpoint.ip != Endpoint.IpConfigurations[0].IpAddress {
t.Errorf("%v does not match %v", endpoint.ip, Endpoint.IpConfigurations[0].IpAddress)
}
err = Endpoint.Delete()
if err != nil {
t.Error(err)
}
err = Network.Delete()
if err != nil {
t.Error(err)
}
}
func testCreateEndpointLocal(t *testing.T, hns HostNetworkService) {
Network, err := createTestNetwork()
if err != nil {
t.Error(err)
}
endpoint := &endpointsInfo{
ip: epIpAddress,
macAddress: epMacAddress,
isLocal: true,
}
endpoint, err = hns.createEndpoint(endpoint, Network.Name)
if err != nil {
t.Error(err)
}
Endpoint, err := hcn.GetEndpointByID(endpoint.hnsID)
if err != nil {
t.Error(err)
}
if !strings.EqualFold(endpoint.hnsID, Endpoint.Id) {
t.Errorf("%v does not match %v", endpoint.hnsID, Endpoint.Id)
}
if endpoint.ip != Endpoint.IpConfigurations[0].IpAddress {
t.Errorf("%v does not match %v", endpoint.ip, Endpoint.IpConfigurations[0].IpAddress)
}
if endpoint.macAddress != Endpoint.MacAddress {
t.Errorf("%v does not match %v", endpoint.macAddress, Endpoint.MacAddress)
}
err = Endpoint.Delete()
if err != nil {
t.Error(err)
}
err = Network.Delete()
if err != nil {
t.Error(err)
}
}
func testCreateEndpointRemote(t *testing.T, hns HostNetworkService, providerAddress string) {
Network, err := createTestNetwork()
if err != nil {
t.Error(err)
}
endpoint := &endpointsInfo{
ip: epIpAddressRemote,
macAddress: epMacAddress,
isLocal: false,
providerAddress: providerAddress,
}
endpoint, err = hns.createEndpoint(endpoint, Network.Name)
if err != nil {
t.Error(err)
}
Endpoint, err := hcn.GetEndpointByID(endpoint.hnsID)
if err != nil {
t.Error(err)
}
if !strings.EqualFold(endpoint.hnsID, Endpoint.Id) {
t.Errorf("%v does not match %v", endpoint.hnsID, Endpoint.Id)
}
if endpoint.ip != Endpoint.IpConfigurations[0].IpAddress {
t.Errorf("%v does not match %v", endpoint.ip, Endpoint.IpConfigurations[0].IpAddress)
}
if endpoint.macAddress != Endpoint.MacAddress {
t.Errorf("%v does not match %v", endpoint.macAddress, Endpoint.MacAddress)
}
if len(providerAddress) != 0 && endpoint.providerAddress != epPaAddress {
t.Errorf("%v does not match %v", endpoint.providerAddress, providerAddress)
}
err = Endpoint.Delete()
if err != nil {
t.Error(err)
}
err = Network.Delete()
if err != nil {
t.Error(err)
}
}
func testDeleteEndpoint(t *testing.T, hns HostNetworkService) {
Network, err := createTestNetwork()
if err != nil {
t.Error(err)
}
ipConfig := &hcn.IpConfig{
IpAddress: epIpAddress,
}
Endpoint := &hcn.HostComputeEndpoint{
IpConfigurations: []hcn.IpConfig{*ipConfig},
MacAddress: epMacAddress,
SchemaVersion: hcn.SchemaVersion{
Major: 2,
Minor: 0,
},
}
Endpoint, err = Network.CreateEndpoint(Endpoint)
if err != nil {
t.Error(err)
}
err = hns.deleteEndpoint(Endpoint.Id)
if err != nil {
t.Error(err)
}
// Endpoint should no longer exist so this should fail
Endpoint, err = hcn.GetEndpointByID(Endpoint.Id)
if err == nil {
t.Error(err)
}
err = Network.Delete()
if err != nil {
t.Error(err)
}
}
func testGetLoadBalancerExisting(t *testing.T, hns HostNetworkService) {
Network, err := createTestNetwork()
if err != nil {
t.Error(err)
}
ipConfig := &hcn.IpConfig{
IpAddress: epIpAddress,
}
Endpoint := &hcn.HostComputeEndpoint{
IpConfigurations: []hcn.IpConfig{*ipConfig},
MacAddress: epMacAddress,
SchemaVersion: hcn.SchemaVersion{
Major: 2,
Minor: 0,
},
}
Endpoint, err = Network.CreateEndpoint(Endpoint)
if err != nil {
t.Error(err)
}
Endpoints := []hcn.HostComputeEndpoint{*Endpoint}
LoadBalancer, err := hcn.AddLoadBalancer(
Endpoints,
false,
false,
sourceVip,
[]string{serviceVip},
protocol,
internalPort,
externalPort,
)
if err != nil {
t.Error(err)
}
endpoint := &endpointsInfo{
ip: Endpoint.IpConfigurations[0].IpAddress,
hnsID: Endpoint.Id,
}
endpoints := []endpointsInfo{*endpoint}
lb, err := hns.getLoadBalancer(endpoints, false, false, sourceVip, serviceVip, protocol, internalPort, externalPort)
if err != nil {
t.Error(err)
}
if !strings.EqualFold(lb.hnsID, LoadBalancer.Id) {
t.Errorf("%v does not match %v", lb.hnsID, LoadBalancer.Id)
}
err = LoadBalancer.Delete()
if err != nil {
t.Error(err)
}
err = Endpoint.Delete()
if err != nil {
t.Error(err)
}
err = Network.Delete()
if err != nil {
t.Error(err)
}
}
func testGetLoadBalancerNew(t *testing.T, hns HostNetworkService) {
Network, err := createTestNetwork()
if err != nil {
t.Error(err)
}
ipConfig := &hcn.IpConfig{
IpAddress: epIpAddress,
}
Endpoint := &hcn.HostComputeEndpoint{
IpConfigurations: []hcn.IpConfig{*ipConfig},
MacAddress: epMacAddress,
SchemaVersion: hcn.SchemaVersion{
Major: 2,
Minor: 0,
},
}
Endpoint, err = Network.CreateEndpoint(Endpoint)
if err != nil {
t.Error(err)
}
endpoint := &endpointsInfo{
ip: Endpoint.IpConfigurations[0].IpAddress,
hnsID: Endpoint.Id,
}
endpoints := []endpointsInfo{*endpoint}
lb, err := hns.getLoadBalancer(endpoints, false, false, sourceVip, serviceVip, protocol, internalPort, externalPort)
if err != nil {
t.Error(err)
}
LoadBalancer, err := hcn.GetLoadBalancerByID(lb.hnsID)
if err != nil {
t.Error(err)
}
if !strings.EqualFold(lb.hnsID, LoadBalancer.Id) {
t.Errorf("%v does not match %v", lb.hnsID, LoadBalancer.Id)
}
err = LoadBalancer.Delete()
if err != nil {
t.Error(err)
}
err = Endpoint.Delete()
if err != nil {
t.Error(err)
}
err = Network.Delete()
if err != nil {
t.Error(err)
}
}
func testDeleteLoadBalancer(t *testing.T, hns HostNetworkService) {
Network, err := createTestNetwork()
if err != nil {
t.Error(err)
}
ipConfig := &hcn.IpConfig{
IpAddress: epIpAddress,
}
Endpoint := &hcn.HostComputeEndpoint{
IpConfigurations: []hcn.IpConfig{*ipConfig},
MacAddress: epMacAddress,
SchemaVersion: hcn.SchemaVersion{
Major: 2,
Minor: 0,
},
}
Endpoint, err = Network.CreateEndpoint(Endpoint)
if err != nil {
t.Error(err)
}
Endpoints := []hcn.HostComputeEndpoint{*Endpoint}
LoadBalancer, err := hcn.AddLoadBalancer(
Endpoints,
false,
false,
sourceVip,
[]string{serviceVip},
protocol,
internalPort,
externalPort,
)
if err != nil {
t.Error(err)
}
err = hns.deleteLoadBalancer(LoadBalancer.Id)
if err != nil {
t.Error(err)
}
// Load balancer should not longer exist
LoadBalancer, err = hcn.GetLoadBalancerByID(LoadBalancer.Id)
if err == nil {
t.Error(err)
}
err = Endpoint.Delete()
if err != nil {
t.Error(err)
}
err = Network.Delete()
if err != nil {
t.Error(err)
}
}
func createTestNetwork() (*hcn.HostComputeNetwork, error) {
network := &hcn.HostComputeNetwork{
Type: "Overlay",
Name: "TestOverlay",
MacPool: hcn.MacPool{
Ranges: []hcn.MacRange{
{
StartMacAddress: "00-15-5D-52-C0-00",
EndMacAddress: "00-15-5D-52-CF-FF",
},
},
},
Ipams: []hcn.Ipam{
{
Type: "Static",
Subnets: []hcn.Subnet{
{
IpAddressPrefix: addressPrefix,
Routes: []hcn.Route{
{
NextHop: gatewayAddress,
DestinationPrefix: "0.0.0.0/0",
},
},
},
},
},
},
SchemaVersion: hcn.SchemaVersion{
Major: 2,
Minor: 0,
},
}
vsid := &hcn.VsidPolicySetting{
IsolationId: 5000,
}
vsidJson, err := json.Marshal(vsid)
if err != nil {
return nil, err
}
sp := &hcn.SubnetPolicy{
Type: hcn.VSID,
}
sp.Settings = vsidJson
spJson, err := json.Marshal(sp)
if err != nil {
return nil, err
}
network.Ipams[0].Subnets[0].Policies = append(network.Ipams[0].Subnets[0].Policies, spJson)
return network.Create()
}

View File

@ -29,6 +29,8 @@ import (
"time"
"github.com/Microsoft/hcsshim"
"github.com/Microsoft/hcsshim/hcn"
"github.com/davecgh/go-spew/spew"
"k8s.io/klog"
@ -36,10 +38,13 @@ import (
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/apimachinery/pkg/util/wait"
genericfeatures "k8s.io/apiserver/pkg/features"
utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/client-go/tools/record"
apiservice "k8s.io/kubernetes/pkg/api/v1/service"
"k8s.io/kubernetes/pkg/apis/core/v1/helper"
"k8s.io/kubernetes/pkg/proxy"
"k8s.io/kubernetes/pkg/proxy/apis/config"
"k8s.io/kubernetes/pkg/proxy/healthcheck"
"k8s.io/kubernetes/pkg/util/async"
)
@ -82,6 +87,10 @@ type loadBalancerIngressInfo struct {
hnsID string
}
type loadBalancerInfo struct {
hnsID string
}
// internal struct for string service information
type serviceInfo struct {
clusterIP net.IP
@ -100,11 +109,22 @@ type serviceInfo struct {
hnsID string
nodePorthnsID string
policyApplied bool
remoteEndpoint *endpointsInfo
hns HostNetworkService
}
type hnsNetworkInfo struct {
name string
id string
networkType string
remoteSubnets []*remoteSubnetInfo
}
type remoteSubnetInfo struct {
destinationPrefix string
isolationId uint16
providerAddress string
drMacAddress string
}
func Log(v interface{}, message string, level klog.Level) {
@ -126,6 +146,8 @@ type endpointsInfo struct {
macAddress string
hnsID string
refCount uint16
providerAddress string
hns HostNetworkService
}
//Uses mac prefix and IPv4 address to return a mac address
@ -139,7 +161,7 @@ func conjureMac(macPrefix string, ip net.IP) string {
return "02-11-22-33-44-55"
}
func newEndpointInfo(ip string, port uint16, isLocal bool) *endpointsInfo {
func newEndpointInfo(ip string, port uint16, isLocal bool, hns HostNetworkService) *endpointsInfo {
info := &endpointsInfo{
ip: ip,
port: port,
@ -147,6 +169,7 @@ func newEndpointInfo(ip string, port uint16, isLocal bool) *endpointsInfo {
macAddress: conjureMac("02-11", net.ParseIP(ip)),
refCount: 0,
hnsID: "",
hns: hns,
}
return info
@ -160,14 +183,17 @@ func (ep *endpointsInfo) Cleanup() {
// Remove only remote endpoints created by this service
if ep.refCount <= 0 && !ep.isLocal {
klog.V(4).Infof("Removing endpoints for %v, since no one is referencing it", ep)
deleteHnsEndpoint(ep.hnsID)
err := ep.hns.deleteEndpoint(ep.hnsID)
if err == nil {
ep.hnsID = ""
} else {
klog.Errorf("Endpoint deletion failed for %v: %v", ep.ip, err)
}
}
}
// returns a new serviceInfo struct
func newServiceInfo(svcPortName proxy.ServicePortName, port *v1.ServicePort, service *v1.Service) *serviceInfo {
func newServiceInfo(svcPortName proxy.ServicePortName, port *v1.ServicePort, service *v1.Service, hns HostNetworkService) *serviceInfo {
onlyNodeLocalEndpoints := false
if apiservice.RequestsOnlyLocalTraffic(service) {
onlyNodeLocalEndpoints = true
@ -175,8 +201,7 @@ func newServiceInfo(svcPortName proxy.ServicePortName, port *v1.ServicePort, ser
// set default session sticky max age 180min=10800s
stickyMaxAgeSeconds := 10800
if service.Spec.SessionAffinity == v1.ServiceAffinityClientIP {
// Kube-apiserver side guarantees SessionAffinityConfig won't be nil when session affinity type is ClientIP
if service.Spec.SessionAffinity == v1.ServiceAffinityClientIP && service.Spec.SessionAffinityConfig != nil {
stickyMaxAgeSeconds = int(*service.Spec.SessionAffinityConfig.ClientIP.TimeoutSeconds)
}
info := &serviceInfo{
@ -193,6 +218,7 @@ func newServiceInfo(svcPortName proxy.ServicePortName, port *v1.ServicePort, ser
stickyMaxAgeSeconds: stickyMaxAgeSeconds,
loadBalancerSourceRanges: make([]string, len(service.Spec.LoadBalancerSourceRanges)),
onlyNodeLocalEndpoints: onlyNodeLocalEndpoints,
hns: hns,
}
copy(info.loadBalancerSourceRanges, service.Spec.LoadBalancerSourceRanges)
@ -256,17 +282,17 @@ func newEndpointsChangeMap(hostname string) endpointsChangeMap {
}
}
func (ecm *endpointsChangeMap) update(namespacedName *types.NamespacedName, previous, current *v1.Endpoints) bool {
func (ecm *endpointsChangeMap) update(namespacedName *types.NamespacedName, previous, current *v1.Endpoints, hns HostNetworkService) bool {
ecm.lock.Lock()
defer ecm.lock.Unlock()
change, exists := ecm.items[*namespacedName]
if !exists {
change = &endpointsChange{}
change.previous = endpointsToEndpointsMap(previous, ecm.hostname)
change.previous = endpointsToEndpointsMap(previous, ecm.hostname, hns)
ecm.items[*namespacedName] = change
}
change.current = endpointsToEndpointsMap(current, ecm.hostname)
change.current = endpointsToEndpointsMap(current, ecm.hostname, hns)
if reflect.DeepEqual(change.previous, change.current) {
delete(ecm.items, *namespacedName)
}
@ -279,7 +305,7 @@ func newServiceChangeMap() serviceChangeMap {
}
}
func (scm *serviceChangeMap) update(namespacedName *types.NamespacedName, previous, current *v1.Service) bool {
func (scm *serviceChangeMap) update(namespacedName *types.NamespacedName, previous, current *v1.Service, hns HostNetworkService) bool {
scm.lock.Lock()
defer scm.lock.Unlock()
@ -287,10 +313,10 @@ func (scm *serviceChangeMap) update(namespacedName *types.NamespacedName, previo
if !exists {
// Service is Added
change = &serviceChange{}
change.previous = serviceToServiceMap(previous)
change.previous = serviceToServiceMap(previous, hns)
scm.items[*namespacedName] = change
}
change.current = serviceToServiceMap(current)
change.current = serviceToServiceMap(current, hns)
if reflect.DeepEqual(change.previous, change.current) {
delete(scm.items, *namespacedName)
}
@ -420,7 +446,11 @@ type Proxier struct {
// precomputing some number of those and cache for future reuse.
precomputedProbabilities []string
hns HostNetworkService
network hnsNetworkInfo
sourceVip string
hostMac string
isDSR bool
}
type localPort struct {
@ -465,6 +495,7 @@ func NewProxier(
nodeIP net.IP,
recorder record.EventRecorder,
healthzServer healthcheck.HealthzUpdater,
config config.KubeProxyWinkernelConfiguration,
) (*Proxier, error) {
masqueradeValue := 1 << uint(masqueradeBit)
masqueradeMark := fmt.Sprintf("%#08x/%#08x", masqueradeValue, masqueradeValue)
@ -479,19 +510,81 @@ func NewProxier(
}
healthChecker := healthcheck.NewServer(hostname, recorder, nil, nil) // use default implementations of deps
// TODO : Make this a param
hnsNetworkName := os.Getenv("KUBE_NETWORK")
if len(hnsNetworkName) == 0 {
return nil, fmt.Errorf("Environment variable KUBE_NETWORK not initialized")
var hns HostNetworkService
hns = hnsV1{}
supportedFeatures := hcn.GetSupportedFeatures()
if supportedFeatures.Api.V2 {
hns = hnsV2{}
}
hnsNetwork, err := getHnsNetworkInfo(hnsNetworkName)
hnsNetworkName := config.NetworkName
if len(hnsNetworkName) == 0 {
klog.V(3).Infof("network-name flag not set. Checking environment variable")
hnsNetworkName = os.Getenv("KUBE_NETWORK")
if len(hnsNetworkName) == 0 {
return nil, fmt.Errorf("Environment variable KUBE_NETWORK and network-flag not initialized")
}
}
hnsNetworkInfo, err := hns.getNetworkByName(hnsNetworkName)
if err != nil {
klog.Fatalf("Unable to find Hns Network specified by %s. Please check environment variable KUBE_NETWORK", hnsNetworkName)
klog.Errorf("Unable to find Hns Network specified by %s. Please check environment variable KUBE_NETWORK or network-name flag", hnsNetworkName)
return nil, err
}
klog.V(1).Infof("Hns Network loaded with info = %v", hnsNetworkInfo)
isDSR := config.EnableDSR
if isDSR && !utilfeature.DefaultFeatureGate.Enabled(genericfeatures.WinDSR) {
return nil, fmt.Errorf("WinDSR feature gate not enabled")
}
err = hcn.DSRSupported()
if isDSR && err != nil {
return nil, err
}
klog.V(1).Infof("Hns Network loaded with info = %v", hnsNetwork)
var sourceVip string
var hostMac string
if hnsNetworkInfo.networkType == "Overlay" {
if !utilfeature.DefaultFeatureGate.Enabled(genericfeatures.WinOverlay) {
return nil, fmt.Errorf("WinOverlay feature gate not enabled")
}
err = hcn.RemoteSubnetSupported()
if err != nil {
return nil, err
}
sourceVip = config.SourceVip
if len(sourceVip) == 0 {
return nil, fmt.Errorf("source-vip flag not set")
}
interfaces, _ := net.Interfaces() //TODO create interfaces
for _, inter := range interfaces {
addresses, _ := inter.Addrs()
for _, addr := range addresses {
addrIP, _, _ := net.ParseCIDR(addr.String())
if addrIP.String() == nodeIP.String() {
klog.V(2).Infof("Host MAC address is %s", inter.HardwareAddr.String())
hostMac = inter.HardwareAddr.String()
}
}
}
if len(hostMac) == 0 {
return nil, fmt.Errorf("Could not find host mac address for %s", nodeIP)
}
existingSourceVip, _ := hns.getEndpointByIpAddress(sourceVip, hnsNetworkName)
if existingSourceVip == nil {
hnsEndpoint := &endpointsInfo{
ip: sourceVip,
isLocal: true,
macAddress: hostMac,
providerAddress: nodeIP.String(),
}
_, err = hns.createEndpoint(hnsEndpoint, hnsNetworkName)
if err != nil {
return nil, fmt.Errorf("Source Vip endpoint creation failed: %v", err)
}
}
}
proxier := &Proxier{
portsMap: make(map[localPort]closeable),
@ -507,7 +600,11 @@ func NewProxier(
recorder: recorder,
healthChecker: healthChecker,
healthzServer: healthzServer,
network: *hnsNetwork,
hns: hns,
network: *hnsNetworkInfo,
sourceVip: sourceVip,
hostMac: hostMac,
isDSR: isDSR,
}
burstSyncs := 2
@ -536,27 +633,30 @@ func (svcInfo *serviceInfo) cleanupAllPolicies(endpoints []*endpointsInfo) {
for _, ep := range endpoints {
ep.Cleanup()
}
if svcInfo.remoteEndpoint != nil {
svcInfo.remoteEndpoint.Cleanup()
}
svcInfo.policyApplied = false
}
func (svcInfo *serviceInfo) deleteAllHnsLoadBalancerPolicy() {
// Remove the Hns Policy corresponding to this service
deleteHnsLoadBalancerPolicy(svcInfo.hnsID)
hns := svcInfo.hns
hns.deleteLoadBalancer(svcInfo.hnsID)
svcInfo.hnsID = ""
deleteHnsLoadBalancerPolicy(svcInfo.nodePorthnsID)
hns.deleteLoadBalancer(svcInfo.nodePorthnsID)
svcInfo.nodePorthnsID = ""
for _, externalIp := range svcInfo.externalIPs {
deleteHnsLoadBalancerPolicy(externalIp.hnsID)
hns.deleteLoadBalancer(externalIp.hnsID)
externalIp.hnsID = ""
}
for _, lbIngressIp := range svcInfo.loadBalancerIngressIPs {
deleteHnsLoadBalancerPolicy(lbIngressIp.hnsID)
hns.deleteLoadBalancer(lbIngressIp.hnsID)
lbIngressIp.hnsID = ""
}
}
func deleteAllHnsLoadBalancerPolicy() {
@ -574,87 +674,6 @@ func deleteAllHnsLoadBalancerPolicy() {
}
// getHnsLoadBalancer returns the LoadBalancer policy resource, if already found.
// If not, it would create one and return
func getHnsLoadBalancer(endpoints []hcsshim.HNSEndpoint, isILB bool, vip string, protocol uint16, internalPort uint16, externalPort uint16) (*hcsshim.PolicyList, error) {
plists, err := hcsshim.HNSListPolicyListRequest()
if err != nil {
return nil, err
}
for _, plist := range plists {
if len(plist.EndpointReferences) != len(endpoints) {
continue
}
// Validate if input meets any of the policy lists
elbPolicy := hcsshim.ELBPolicy{}
if err = json.Unmarshal(plist.Policies[0], &elbPolicy); err != nil {
continue
}
if elbPolicy.Protocol == protocol && elbPolicy.InternalPort == internalPort && elbPolicy.ExternalPort == externalPort && elbPolicy.ILB == isILB {
if len(vip) > 0 {
if len(elbPolicy.VIPs) == 0 || elbPolicy.VIPs[0] != vip {
continue
}
}
LogJson(plist, "Found existing Hns loadbalancer policy resource", 1)
return &plist, nil
}
}
//TODO: sourceVip is not used. If required, expose this as a param
var sourceVip string
lb, err := hcsshim.AddLoadBalancer(
endpoints,
isILB,
sourceVip,
vip,
protocol,
internalPort,
externalPort,
)
if err == nil {
LogJson(lb, "Hns loadbalancer policy resource", 1)
}
return lb, err
}
func deleteHnsLoadBalancerPolicy(hnsID string) {
if len(hnsID) == 0 {
// Return silently
return
}
// Cleanup HNS policies
hnsloadBalancer, err := hcsshim.GetPolicyListByID(hnsID)
if err != nil {
klog.Errorf("%v", err)
return
}
LogJson(hnsloadBalancer, "Removing Policy", 2)
_, err = hnsloadBalancer.Delete()
if err != nil {
klog.Errorf("%v", err)
}
}
func deleteHnsEndpoint(hnsID string) {
hnsendpoint, err := hcsshim.GetHNSEndpointByID(hnsID)
if err != nil {
klog.Errorf("%v", err)
return
}
_, err = hnsendpoint.Delete()
if err != nil {
klog.Errorf("%v", err)
}
klog.V(3).Infof("Remote endpoint resource deleted id %s", hnsID)
}
func getHnsNetworkInfo(hnsNetworkName string) (*hnsNetworkInfo, error) {
hnsnetwork, err := hcsshim.GetHNSNetworkByName(hnsNetworkName)
if err != nil {
@ -665,27 +684,10 @@ func getHnsNetworkInfo(hnsNetworkName string) (*hnsNetworkInfo, error) {
return &hnsNetworkInfo{
id: hnsnetwork.Id,
name: hnsnetwork.Name,
networkType: hnsnetwork.Type,
}, nil
}
func getHnsEndpointByIpAddress(ip net.IP, networkName string) (*hcsshim.HNSEndpoint, error) {
hnsnetwork, err := hcsshim.GetHNSNetworkByName(networkName)
if err != nil {
klog.Errorf("%v", err)
return nil, err
}
endpoints, err := hcsshim.HNSListEndpointRequest()
for _, endpoint := range endpoints {
equal := reflect.DeepEqual(endpoint.IPAddress, ip)
if equal && endpoint.VirtualNetwork == hnsnetwork.Id {
return &endpoint, nil
}
}
return nil, fmt.Errorf("Endpoint %v not found on network %s", ip, networkName)
}
// Sync is called to synchronize the proxier state to hns as soon as possible.
func (proxier *Proxier) Sync() {
proxier.syncRunner.Run()
@ -714,21 +716,21 @@ func (proxier *Proxier) isInitialized() bool {
func (proxier *Proxier) OnServiceAdd(service *v1.Service) {
namespacedName := types.NamespacedName{Namespace: service.Namespace, Name: service.Name}
if proxier.serviceChanges.update(&namespacedName, nil, service) && proxier.isInitialized() {
if proxier.serviceChanges.update(&namespacedName, nil, service, proxier.hns) && proxier.isInitialized() {
proxier.syncRunner.Run()
}
}
func (proxier *Proxier) OnServiceUpdate(oldService, service *v1.Service) {
namespacedName := types.NamespacedName{Namespace: service.Namespace, Name: service.Name}
if proxier.serviceChanges.update(&namespacedName, oldService, service) && proxier.isInitialized() {
if proxier.serviceChanges.update(&namespacedName, oldService, service, proxier.hns) && proxier.isInitialized() {
proxier.syncRunner.Run()
}
}
func (proxier *Proxier) OnServiceDelete(service *v1.Service) {
namespacedName := types.NamespacedName{Namespace: service.Namespace, Name: service.Name}
if proxier.serviceChanges.update(&namespacedName, service, nil) && proxier.isInitialized() {
if proxier.serviceChanges.update(&namespacedName, service, nil, proxier.hns) && proxier.isInitialized() {
proxier.syncRunner.Run()
}
}
@ -789,21 +791,21 @@ func (proxier *Proxier) updateServiceMap() (result updateServiceMapResult) {
func (proxier *Proxier) OnEndpointsAdd(endpoints *v1.Endpoints) {
namespacedName := types.NamespacedName{Namespace: endpoints.Namespace, Name: endpoints.Name}
if proxier.endpointsChanges.update(&namespacedName, nil, endpoints) && proxier.isInitialized() {
if proxier.endpointsChanges.update(&namespacedName, nil, endpoints, proxier.hns) && proxier.isInitialized() {
proxier.syncRunner.Run()
}
}
func (proxier *Proxier) OnEndpointsUpdate(oldEndpoints, endpoints *v1.Endpoints) {
namespacedName := types.NamespacedName{Namespace: endpoints.Namespace, Name: endpoints.Name}
if proxier.endpointsChanges.update(&namespacedName, oldEndpoints, endpoints) && proxier.isInitialized() {
if proxier.endpointsChanges.update(&namespacedName, oldEndpoints, endpoints, proxier.hns) && proxier.isInitialized() {
proxier.syncRunner.Run()
}
}
func (proxier *Proxier) OnEndpointsDelete(endpoints *v1.Endpoints) {
namespacedName := types.NamespacedName{Namespace: endpoints.Namespace, Name: endpoints.Name}
if proxier.endpointsChanges.update(&namespacedName, endpoints, nil) && proxier.isInitialized() {
if proxier.endpointsChanges.update(&namespacedName, endpoints, nil, proxier.hns) && proxier.isInitialized() {
proxier.syncRunner.Run()
}
}
@ -867,7 +869,7 @@ func getLocalIPs(endpointsMap proxyEndpointsMap) map[types.NamespacedName]sets.S
// This function is used for incremental updated of endpointsMap.
//
// NOTE: endpoints object should NOT be modified.
func endpointsToEndpointsMap(endpoints *v1.Endpoints, hostname string) proxyEndpointsMap {
func endpointsToEndpointsMap(endpoints *v1.Endpoints, hostname string, hns HostNetworkService) proxyEndpointsMap {
if endpoints == nil {
return nil
}
@ -880,7 +882,7 @@ func endpointsToEndpointsMap(endpoints *v1.Endpoints, hostname string) proxyEndp
for i := range ss.Ports {
port := &ss.Ports[i]
if port.Port == 0 {
klog.Warningf("ignoring invalid endpoint port %s", port.Name)
klog.Warningf("Ignoring invalid endpoint port %s", port.Name)
continue
}
svcPortName := proxy.ServicePortName{
@ -890,11 +892,11 @@ func endpointsToEndpointsMap(endpoints *v1.Endpoints, hostname string) proxyEndp
for i := range ss.Addresses {
addr := &ss.Addresses[i]
if addr.IP == "" {
klog.Warningf("ignoring invalid endpoint port %s with empty host", port.Name)
klog.Warningf("Ignoring invalid endpoint port %s with empty host", port.Name)
continue
}
isLocal := addr.NodeName != nil && *addr.NodeName == hostname
epInfo := newEndpointInfo(addr.IP, uint16(port.Port), isLocal)
epInfo := newEndpointInfo(addr.IP, uint16(port.Port), isLocal, hns)
endpointsMap[svcPortName] = append(endpointsMap[svcPortName], epInfo)
}
if klog.V(3) {
@ -912,7 +914,7 @@ func endpointsToEndpointsMap(endpoints *v1.Endpoints, hostname string) proxyEndp
// Translates single Service object to proxyServiceMap.
//
// NOTE: service object should NOT be modified.
func serviceToServiceMap(service *v1.Service) proxyServiceMap {
func serviceToServiceMap(service *v1.Service, hns HostNetworkService) proxyServiceMap {
if service == nil {
return nil
}
@ -925,7 +927,7 @@ func serviceToServiceMap(service *v1.Service) proxyServiceMap {
for i := range service.Spec.Ports {
servicePort := &service.Spec.Ports[i]
svcPortName := proxy.ServicePortName{NamespacedName: svcName, Port: servicePort.Name}
serviceMap[svcPortName] = newServiceInfo(svcPortName, servicePort, service)
serviceMap[svcPortName] = newServiceInfo(svcPortName, servicePort, service, hns)
}
return serviceMap
}
@ -972,12 +974,36 @@ func (proxier *Proxier) syncProxyRules() {
continue
}
var hnsEndpoints []hcsshim.HNSEndpoint
hnsNetworkName := proxier.network.name
hns := proxier.hns
if proxier.network.networkType == "Overlay" {
serviceVipEndpoint, _ := hns.getEndpointByIpAddress(svcInfo.clusterIP.String(), hnsNetworkName)
if serviceVipEndpoint == nil {
klog.V(4).Infof("No existing remote endpoint for service VIP %v", svcInfo.clusterIP.String())
hnsEndpoint := &endpointsInfo{
ip: svcInfo.clusterIP.String(),
isLocal: false,
macAddress: proxier.hostMac,
providerAddress: proxier.nodeIP.String(),
}
newHnsEndpoint, err := hns.createEndpoint(hnsEndpoint, hnsNetworkName)
if err != nil {
klog.Errorf("Remote endpoint creation failed for service VIP: %v", err)
continue
}
newHnsEndpoint.refCount++
svcInfo.remoteEndpoint = newHnsEndpoint
}
}
var hnsEndpoints []endpointsInfo
klog.V(4).Infof("====Applying Policy for %s====", svcName)
// Create Remote endpoints for every endpoint, corresponding to the service
for _, ep := range proxier.endpointsMap[svcName] {
var newHnsEndpoint *hcsshim.HNSEndpoint
var newHnsEndpoint *endpointsInfo
hnsNetworkName := proxier.network.name
var err error
@ -989,14 +1015,14 @@ func (proxier *Proxier) syncProxyRules() {
}
if len(ep.hnsID) > 0 {
newHnsEndpoint, err = hcsshim.GetHNSEndpointByID(ep.hnsID)
newHnsEndpoint, err = hns.getEndpointByID(ep.hnsID)
}
if newHnsEndpoint == nil {
// First check if an endpoint resource exists for this IP, on the current host
// A Local endpoint could exist here already
// A remote endpoint was already created and proxy was restarted
newHnsEndpoint, err = getHnsEndpointByIpAddress(net.ParseIP(ep.ip), hnsNetworkName)
newHnsEndpoint, err = hns.getEndpointByIpAddress(ep.ip, hnsNetworkName)
}
if newHnsEndpoint == nil {
@ -1004,29 +1030,63 @@ func (proxier *Proxier) syncProxyRules() {
klog.Errorf("Local endpoint not found for %v: err: %v on network %s", ep.ip, err, hnsNetworkName)
continue
}
// hns Endpoint resource was not found, create one
hnsnetwork, err := hcsshim.GetHNSNetworkByName(hnsNetworkName)
if proxier.network.networkType == "Overlay" {
klog.Infof("Updating network %v to check for new remote subnet policies", proxier.network.name)
networkName := proxier.network.name
updatedNetwork, err := hns.getNetworkByName(networkName)
if err != nil {
klog.Errorf("%v", err)
klog.Fatalf("Failed to get network %v: %v", networkName, err)
}
proxier.network = *updatedNetwork
var providerAddress string
for _, rs := range proxier.network.remoteSubnets {
_, ipNet, err := net.ParseCIDR(rs.destinationPrefix)
if err != nil {
klog.Fatalf("%v", err)
}
if ipNet.Contains(net.ParseIP(ep.ip)) {
providerAddress = rs.providerAddress
}
if ep.ip == rs.providerAddress {
providerAddress = rs.providerAddress
}
}
if len(providerAddress) == 0 {
klog.Errorf("Could not find provider address for %s", ep.ip)
continue
}
hnsEndpoint := &hcsshim.HNSEndpoint{
MacAddress: ep.macAddress,
IPAddress: net.ParseIP(ep.ip),
hnsEndpoint := &endpointsInfo{
ip: ep.ip,
isLocal: false,
macAddress: conjureMac("02-11", net.ParseIP(ep.ip)),
providerAddress: providerAddress,
}
newHnsEndpoint, err = hnsnetwork.CreateRemoteEndpoint(hnsEndpoint)
newHnsEndpoint, err = hns.createEndpoint(hnsEndpoint, hnsNetworkName)
if err != nil {
klog.Errorf("Remote endpoint creation failed: %v, %s", err, spew.Sdump(hnsEndpoint))
continue
}
} else {
hnsEndpoint := &endpointsInfo{
ip: ep.ip,
isLocal: false,
macAddress: ep.macAddress,
}
newHnsEndpoint, err = hns.createEndpoint(hnsEndpoint, hnsNetworkName)
if err != nil {
klog.Errorf("Remote endpoint creation failed: %v", err)
continue
}
}
}
// Save the hnsId for reference
LogJson(newHnsEndpoint, "Hns Endpoint resource", 1)
hnsEndpoints = append(hnsEndpoints, *newHnsEndpoint)
ep.hnsID = newHnsEndpoint.Id
ep.hnsID = newHnsEndpoint.hnsID
ep.refCount++
Log(ep, "Endpoint resource found", 3)
}
@ -1044,11 +1104,13 @@ func (proxier *Proxier) syncProxyRules() {
}
klog.V(4).Infof("Trying to Apply Policies for service %s", spew.Sdump(svcInfo))
var hnsLoadBalancer *hcsshim.PolicyList
var hnsLoadBalancer *loadBalancerInfo
hnsLoadBalancer, err := getHnsLoadBalancer(
hnsLoadBalancer, err := hns.getLoadBalancer(
hnsEndpoints,
false,
proxier.isDSR,
proxier.sourceVip,
svcInfo.clusterIP.String(),
Enum(svcInfo.protocol),
uint16(svcInfo.targetPort),
@ -1059,15 +1121,17 @@ func (proxier *Proxier) syncProxyRules() {
continue
}
svcInfo.hnsID = hnsLoadBalancer.ID
klog.V(3).Infof("Hns LoadBalancer resource created for cluster ip resources %v, Id [%s]", svcInfo.clusterIP, hnsLoadBalancer.ID)
svcInfo.hnsID = hnsLoadBalancer.hnsID
klog.V(3).Infof("Hns LoadBalancer resource created for cluster ip resources %v, Id [%s]", svcInfo.clusterIP, hnsLoadBalancer.hnsID)
// If nodePort is specified, user should be able to use nodeIP:nodePort to reach the backend endpoints
if svcInfo.nodePort > 0 {
hnsLoadBalancer, err := getHnsLoadBalancer(
hnsLoadBalancer, err := hns.getLoadBalancer(
hnsEndpoints,
false,
"", // VIP has to be empty to automatically select the nodeIP
false,
proxier.sourceVip,
"",
Enum(svcInfo.protocol),
uint16(svcInfo.targetPort),
uint16(svcInfo.nodePort),
@ -1077,16 +1141,18 @@ func (proxier *Proxier) syncProxyRules() {
continue
}
svcInfo.nodePorthnsID = hnsLoadBalancer.ID
klog.V(3).Infof("Hns LoadBalancer resource created for nodePort resources %v, Id [%s]", svcInfo.clusterIP, hnsLoadBalancer.ID)
svcInfo.nodePorthnsID = hnsLoadBalancer.hnsID
klog.V(3).Infof("Hns LoadBalancer resource created for nodePort resources %v, Id [%s]", svcInfo.clusterIP, hnsLoadBalancer.hnsID)
}
// Create a Load Balancer Policy for each external IP
for _, externalIp := range svcInfo.externalIPs {
// Try loading existing policies, if already available
hnsLoadBalancer, err := getHnsLoadBalancer(
hnsLoadBalancer, err = hns.getLoadBalancer(
hnsEndpoints,
false,
false,
proxier.sourceVip,
externalIp.ip,
Enum(svcInfo.protocol),
uint16(svcInfo.targetPort),
@ -1096,15 +1162,17 @@ func (proxier *Proxier) syncProxyRules() {
klog.Errorf("Policy creation failed: %v", err)
continue
}
externalIp.hnsID = hnsLoadBalancer.ID
klog.V(3).Infof("Hns LoadBalancer resource created for externalIp resources %v, Id[%s]", externalIp, hnsLoadBalancer.ID)
externalIp.hnsID = hnsLoadBalancer.hnsID
klog.V(3).Infof("Hns LoadBalancer resource created for externalIp resources %v, Id[%s]", externalIp, hnsLoadBalancer.hnsID)
}
// Create a Load Balancer Policy for each loadbalancer ingress
for _, lbIngressIp := range svcInfo.loadBalancerIngressIPs {
// Try loading existing policies, if already available
hnsLoadBalancer, err := getHnsLoadBalancer(
hnsLoadBalancer, err := hns.getLoadBalancer(
hnsEndpoints,
false,
false,
proxier.sourceVip,
lbIngressIp.ip,
Enum(svcInfo.protocol),
uint16(svcInfo.targetPort),
@ -1114,7 +1182,7 @@ func (proxier *Proxier) syncProxyRules() {
klog.Errorf("Policy creation failed: %v", err)
continue
}
lbIngressIp.hnsID = hnsLoadBalancer.ID
lbIngressIp.hnsID = hnsLoadBalancer.hnsID
klog.V(3).Infof("Hns LoadBalancer resource created for loadBalancer Ingress resources %v", lbIngressIp)
}
svcInfo.policyApplied = true

View File

@ -0,0 +1,379 @@
// +build windows
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License 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 winkernel
import (
"k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/kubernetes/pkg/proxy"
"net"
"strings"
"testing"
"time"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
const testHostName = "test-hostname"
const macAddress = "00-11-22-33-44-55"
const clusterCIDR = "192.168.1.0/24"
const destinationPrefix = "192.168.2.0/24"
const providerAddress = "10.0.0.3"
const guid = "123ABC"
type fakeHealthChecker struct {
services map[types.NamespacedName]uint16
endpoints map[types.NamespacedName]int
}
func newFakeHealthChecker() *fakeHealthChecker {
return &fakeHealthChecker{
services: map[types.NamespacedName]uint16{},
endpoints: map[types.NamespacedName]int{},
}
}
func (fake *fakeHealthChecker) SyncServices(newServices map[types.NamespacedName]uint16) error {
fake.services = newServices
return nil
}
func (fake *fakeHealthChecker) SyncEndpoints(newEndpoints map[types.NamespacedName]int) error {
fake.endpoints = newEndpoints
return nil
}
type fakeHNS struct{}
func newFakeHNS() *fakeHNS {
return &fakeHNS{}
}
func (hns fakeHNS) getNetworkByName(name string) (*hnsNetworkInfo, error) {
var remoteSubnets []*remoteSubnetInfo
rs := &remoteSubnetInfo{
destinationPrefix: destinationPrefix,
isolationId: 4096,
providerAddress: providerAddress,
drMacAddress: macAddress,
}
remoteSubnets = append(remoteSubnets, rs)
return &hnsNetworkInfo{
id: strings.ToUpper(guid),
name: name,
networkType: "Overlay",
remoteSubnets: remoteSubnets,
}, nil
}
func (hns fakeHNS) getEndpointByID(id string) (*endpointsInfo, error) {
return nil, nil
}
func (hns fakeHNS) getEndpointByIpAddress(ip string, networkName string) (*endpointsInfo, error) {
_, ipNet, _ := net.ParseCIDR(destinationPrefix)
if ipNet.Contains(net.ParseIP(ip)) {
return &endpointsInfo{
ip: ip,
isLocal: true,
macAddress: macAddress,
hnsID: guid,
hns: hns,
}, nil
}
return nil, nil
}
func (hns fakeHNS) createEndpoint(ep *endpointsInfo, networkName string) (*endpointsInfo, error) {
return &endpointsInfo{
ip: ep.ip,
isLocal: ep.isLocal,
macAddress: ep.macAddress,
hnsID: guid,
hns: hns,
}, nil
}
func (hns fakeHNS) deleteEndpoint(hnsID string) error {
return nil
}
func (hns fakeHNS) getLoadBalancer(endpoints []endpointsInfo, isILB bool, isDSR bool, sourceVip string, vip string, protocol uint16, internalPort uint16, externalPort uint16) (*loadBalancerInfo, error) {
return &loadBalancerInfo{
hnsID: guid,
}, nil
}
func (hns fakeHNS) deleteLoadBalancer(hnsID string) error {
return nil
}
func NewFakeProxier(syncPeriod time.Duration, minSyncPeriod time.Duration, clusterCIDR string, hostname string, nodeIP net.IP, networkType string) *Proxier {
sourceVip := "192.168.1.2"
hnsNetworkInfo := &hnsNetworkInfo{
name: "TestNetwork",
networkType: networkType,
}
proxier := &Proxier{
portsMap: make(map[localPort]closeable),
serviceMap: make(proxyServiceMap),
serviceChanges: newServiceChangeMap(),
endpointsMap: make(proxyEndpointsMap),
endpointsChanges: newEndpointsChangeMap(hostname),
clusterCIDR: clusterCIDR,
hostname: testHostName,
nodeIP: nodeIP,
healthChecker: newFakeHealthChecker(),
network: *hnsNetworkInfo,
sourceVip: sourceVip,
hostMac: macAddress,
isDSR: false,
hns: newFakeHNS(),
}
return proxier
}
func TestCreateServiceVip(t *testing.T) {
syncPeriod := 30 * time.Second
proxier := NewFakeProxier(syncPeriod, syncPeriod, clusterCIDR, "testhost", net.ParseIP("10.0.0.1"), "Overlay")
if proxier == nil {
t.Error()
}
svcIP := "10.20.30.41"
svcPort := 80
svcNodePort := 3001
svcExternalIPs := "50.60.70.81"
svcPortName := proxy.ServicePortName{
NamespacedName: makeNSN("ns1", "svc1"),
Port: "p80",
}
timeoutSeconds := v1.DefaultClientIPServiceAffinitySeconds
makeServiceMap(proxier,
makeTestService(svcPortName.Namespace, svcPortName.Name, func(svc *v1.Service) {
svc.Spec.Type = "NodePort"
svc.Spec.ClusterIP = svcIP
svc.Spec.ExternalIPs = []string{svcExternalIPs}
svc.Spec.SessionAffinity = v1.ServiceAffinityClientIP
svc.Spec.SessionAffinityConfig = &v1.SessionAffinityConfig{
ClientIP: &v1.ClientIPConfig{
TimeoutSeconds: &timeoutSeconds,
},
}
svc.Spec.Ports = []v1.ServicePort{{
Name: svcPortName.Port,
Port: int32(svcPort),
Protocol: v1.ProtocolTCP,
NodePort: int32(svcNodePort),
}}
}),
)
makeEndpointsMap(proxier)
proxier.syncProxyRules()
if proxier.serviceMap[svcPortName].remoteEndpoint == nil {
t.Error()
}
if proxier.serviceMap[svcPortName].remoteEndpoint.ip != svcIP {
t.Error()
}
}
func TestCreateRemoteEndpointOverlay(t *testing.T) {
syncPeriod := 30 * time.Second
proxier := NewFakeProxier(syncPeriod, syncPeriod, clusterCIDR, "testhost", net.ParseIP("10.0.0.1"), "Overlay")
if proxier == nil {
t.Error()
}
svcIP := "10.20.30.41"
svcPort := 80
svcNodePort := 3001
svcPortName := proxy.ServicePortName{
NamespacedName: makeNSN("ns1", "svc1"),
Port: "p80",
}
makeServiceMap(proxier,
makeTestService(svcPortName.Namespace, svcPortName.Name, func(svc *v1.Service) {
svc.Spec.Type = "NodePort"
svc.Spec.ClusterIP = svcIP
svc.Spec.Ports = []v1.ServicePort{{
Name: svcPortName.Port,
Port: int32(svcPort),
Protocol: v1.ProtocolTCP,
NodePort: int32(svcNodePort),
}}
}),
)
makeEndpointsMap(proxier,
makeTestEndpoints(svcPortName.Namespace, svcPortName.Name, func(ept *v1.Endpoints) {
ept.Subsets = []v1.EndpointSubset{{
Addresses: []v1.EndpointAddress{{
IP: epIpAddressRemote,
}},
Ports: []v1.EndpointPort{{
Name: svcPortName.Port,
Port: int32(svcPort),
}},
}}
}),
)
proxier.syncProxyRules()
if proxier.endpointsMap[svcPortName][0].hnsID != guid {
t.Errorf("%v does not match %v", proxier.endpointsMap[svcPortName][0].hnsID, guid)
}
}
func TestCreateRemoteEndpointL2Bridge(t *testing.T) {
syncPeriod := 30 * time.Second
proxier := NewFakeProxier(syncPeriod, syncPeriod, clusterCIDR, "testhost", net.ParseIP("10.0.0.1"), "L2Bridge")
if proxier == nil {
t.Error()
}
svcIP := "10.20.30.41"
svcPort := 80
svcNodePort := 3001
svcPortName := proxy.ServicePortName{
NamespacedName: makeNSN("ns1", "svc1"),
Port: "p80",
}
makeServiceMap(proxier,
makeTestService(svcPortName.Namespace, svcPortName.Name, func(svc *v1.Service) {
svc.Spec.Type = "NodePort"
svc.Spec.ClusterIP = svcIP
svc.Spec.Ports = []v1.ServicePort{{
Name: svcPortName.Port,
Port: int32(svcPort),
Protocol: v1.ProtocolTCP,
NodePort: int32(svcNodePort),
}}
}),
)
makeEndpointsMap(proxier,
makeTestEndpoints(svcPortName.Namespace, svcPortName.Name, func(ept *v1.Endpoints) {
ept.Subsets = []v1.EndpointSubset{{
Addresses: []v1.EndpointAddress{{
IP: epIpAddressRemote,
}},
Ports: []v1.EndpointPort{{
Name: svcPortName.Port,
Port: int32(svcPort),
}},
}}
}),
)
proxier.syncProxyRules()
if proxier.endpointsMap[svcPortName][0].hnsID != guid {
t.Errorf("%v does not match %v", proxier.endpointsMap[svcPortName][0].hnsID, guid)
}
}
func TestCreateLoadBalancer(t *testing.T) {
syncPeriod := 30 * time.Second
proxier := NewFakeProxier(syncPeriod, syncPeriod, clusterCIDR, "testhost", net.ParseIP("10.0.0.1"), "Overlay")
if proxier == nil {
t.Error()
}
svcIP := "10.20.30.41"
svcPort := 80
svcNodePort := 3001
svcPortName := proxy.ServicePortName{
NamespacedName: makeNSN("ns1", "svc1"),
Port: "p80",
}
makeServiceMap(proxier,
makeTestService(svcPortName.Namespace, svcPortName.Name, func(svc *v1.Service) {
svc.Spec.Type = "NodePort"
svc.Spec.ClusterIP = svcIP
svc.Spec.Ports = []v1.ServicePort{{
Name: svcPortName.Port,
Port: int32(svcPort),
Protocol: v1.ProtocolTCP,
NodePort: int32(svcNodePort),
}}
}),
)
makeEndpointsMap(proxier,
makeTestEndpoints(svcPortName.Namespace, svcPortName.Name, func(ept *v1.Endpoints) {
ept.Subsets = []v1.EndpointSubset{{
Addresses: []v1.EndpointAddress{{
IP: epIpAddressRemote,
}},
Ports: []v1.EndpointPort{{
Name: svcPortName.Port,
Port: int32(svcPort),
}},
}}
}),
)
proxier.syncProxyRules()
if proxier.serviceMap[svcPortName].hnsID != guid {
t.Errorf("%v does not match %v", proxier.serviceMap[svcPortName].hnsID, guid)
}
}
func makeNSN(namespace, name string) types.NamespacedName {
return types.NamespacedName{Namespace: namespace, Name: name}
}
func makeServiceMap(proxier *Proxier, allServices ...*v1.Service) {
for i := range allServices {
proxier.OnServiceAdd(allServices[i])
}
proxier.mu.Lock()
defer proxier.mu.Unlock()
proxier.servicesSynced = true
}
func makeTestService(namespace, name string, svcFunc func(*v1.Service)) *v1.Service {
svc := &v1.Service{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
Annotations: map[string]string{},
},
Spec: v1.ServiceSpec{},
Status: v1.ServiceStatus{},
}
svcFunc(svc)
return svc
}
func makeEndpointsMap(proxier *Proxier, allEndpoints ...*v1.Endpoints) {
for i := range allEndpoints {
proxier.OnEndpointsAdd(allEndpoints[i])
}
proxier.mu.Lock()
defer proxier.mu.Unlock()
proxier.endpointsSynced = true
}
func makeTestEndpoints(namespace, name string, eptFunc func(*v1.Endpoints)) *v1.Endpoints {
ept := &v1.Endpoints{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
},
}
eptFunc(ept)
return ept
}

View File

@ -88,6 +88,18 @@ const (
//
// Server-side apply. Merging happens on the server.
ServerSideApply utilfeature.Feature = "ServerSideApply"
// owner: @ksubrmnn
// alpha: v1.14
//
// Allows kube-proxy to run in Overlay mode for Windows
WinOverlay utilfeature.Feature = "WinOverlay"
// owner: @ksubrmnn
// alpha: v1.14
//
// Allows kube-proxy to create DSR loadbalancers for Windows
WinDSR utilfeature.Feature = "WinDSR"
)
func init() {
@ -106,4 +118,6 @@ var defaultKubernetesFeatureGates = map[utilfeature.Feature]utilfeature.FeatureS
APIListChunking: {Default: true, PreRelease: utilfeature.Beta},
DryRun: {Default: true, PreRelease: utilfeature.Beta},
ServerSideApply: {Default: false, PreRelease: utilfeature.Alpha},
WinOverlay: {Default: false, PreRelease: utilfeature.Alpha},
WinDSR: {Default: false, PreRelease: utilfeature.Alpha},
}

View File

@ -74,6 +74,20 @@ type KubeProxyConntrackConfiguration struct {
TCPCloseWaitTimeout *metav1.Duration `json:"tcpCloseWaitTimeout"`
}
// KubeProxyWinkernelConfiguration contains Windows/HNS settings for
// the Kubernetes proxy server.
type KubeProxyWinkernelConfiguration struct {
// networkName is the name of the network kube-proxy will use
// to create endpoints and policies
NetworkName string `json:"networkName"`
// sourceVip is the IP address of the source VIP endoint used for
// NAT when loadbalancing
SourceVip string `json:"sourceVip"`
// enableDSR tells kube-proxy whether HNS policies should be created
// with DSR
EnableDSR bool `json:"enableDSR"`
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// KubeProxyConfiguration contains everything necessary to configure the
@ -136,6 +150,8 @@ type KubeProxyConfiguration struct {
// If set it to a non-zero IP block, kube-proxy will filter that down to just the IPs that applied to the node.
// An empty string slice is meant to select all network interfaces.
NodePortAddresses []string `json:"nodePortAddresses"`
// winkernel contains winkernel-related configuration options.
Winkernel KubeProxyWinkernelConfiguration `json:"winkernel"`
}
// Currently, three modes of proxy are available in Linux platform: 'userspace' (older, going to be EOL), 'iptables'

View File

@ -52,6 +52,7 @@ func (in *KubeProxyConfiguration) DeepCopyInto(out *KubeProxyConfiguration) {
*out = make([]string, len(*in))
copy(*out, *in)
}
out.Winkernel = in.Winkernel
return
}
@ -159,3 +160,19 @@ func (in *KubeProxyIPVSConfiguration) DeepCopy() *KubeProxyIPVSConfiguration {
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *KubeProxyWinkernelConfiguration) DeepCopyInto(out *KubeProxyWinkernelConfiguration) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubeProxyWinkernelConfiguration.
func (in *KubeProxyWinkernelConfiguration) DeepCopy() *KubeProxyWinkernelConfiguration {
if in == nil {
return nil
}
out := new(KubeProxyWinkernelConfiguration)
in.DeepCopyInto(out)
return out
}

View File

@ -16,7 +16,6 @@ import (
//sys createIoCompletionPort(file syscall.Handle, port syscall.Handle, key uintptr, threadCount uint32) (newport syscall.Handle, err error) = CreateIoCompletionPort
//sys getQueuedCompletionStatus(port syscall.Handle, bytes *uint32, key *uintptr, o **ioOperation, timeout uint32) (err error) = GetQueuedCompletionStatus
//sys setFileCompletionNotificationModes(h syscall.Handle, flags uint8) (err error) = SetFileCompletionNotificationModes
//sys timeBeginPeriod(period uint32) (n int32) = winmm.timeBeginPeriod
type atomicBool int32
@ -153,8 +152,6 @@ func (f *win32File) prepareIo() (*ioOperation, error) {
// ioCompletionProcessor processes completed async IOs forever
func ioCompletionProcessor(h syscall.Handle) {
// Set the timer resolution to 1. This fixes a performance regression in golang 1.6.
timeBeginPeriod(1)
for {
var bytes uint32
var key uintptr

View File

@ -20,7 +20,8 @@ const (
// FileBasicInfo contains file access time and file attributes information.
type FileBasicInfo struct {
CreationTime, LastAccessTime, LastWriteTime, ChangeTime syscall.Filetime
FileAttributes uintptr // includes padding
FileAttributes uint32
pad uint32 // padding
}
// GetFileBasicInfo retrieves times and attributes for a file.

View File

@ -15,13 +15,13 @@ import (
//sys connectNamedPipe(pipe syscall.Handle, o *syscall.Overlapped) (err error) = ConnectNamedPipe
//sys createNamedPipe(name string, flags uint32, pipeMode uint32, maxInstances uint32, outSize uint32, inSize uint32, defaultTimeout uint32, sa *syscall.SecurityAttributes) (handle syscall.Handle, err error) [failretval==syscall.InvalidHandle] = CreateNamedPipeW
//sys createFile(name string, access uint32, mode uint32, sa *syscall.SecurityAttributes, createmode uint32, attrs uint32, templatefile syscall.Handle) (handle syscall.Handle, err error) [failretval==syscall.InvalidHandle] = CreateFileW
//sys waitNamedPipe(name string, timeout uint32) (err error) = WaitNamedPipeW
//sys getNamedPipeInfo(pipe syscall.Handle, flags *uint32, outSize *uint32, inSize *uint32, maxInstances *uint32) (err error) = GetNamedPipeInfo
//sys getNamedPipeHandleState(pipe syscall.Handle, state *uint32, curInstances *uint32, maxCollectionCount *uint32, collectDataTimeout *uint32, userName *uint16, maxUserNameSize uint32) (err error) = GetNamedPipeHandleStateW
//sys localAlloc(uFlags uint32, length uint32) (ptr uintptr) = LocalAlloc
const (
cERROR_PIPE_BUSY = syscall.Errno(231)
cERROR_NO_DATA = syscall.Errno(232)
cERROR_PIPE_CONNECTED = syscall.Errno(535)
cERROR_SEM_TIMEOUT = syscall.Errno(121)
@ -120,6 +120,11 @@ func (f *win32MessageBytePipe) Read(b []byte) (int, error) {
// zero-byte message, ensure that all future Read() calls
// also return EOF.
f.readEOF = true
} else if err == syscall.ERROR_MORE_DATA {
// ERROR_MORE_DATA indicates that the pipe's read mode is message mode
// and the message still has more bytes. Treat this as a success, since
// this package presents all named pipes as byte streams.
err = nil
}
return n, err
}
@ -133,12 +138,14 @@ func (s pipeAddress) String() string {
}
// DialPipe connects to a named pipe by path, timing out if the connection
// takes longer than the specified duration. If timeout is nil, then the timeout
// is the default timeout established by the pipe server.
// takes longer than the specified duration. If timeout is nil, then we use
// a default timeout of 5 seconds. (We do not use WaitNamedPipe.)
func DialPipe(path string, timeout *time.Duration) (net.Conn, error) {
var absTimeout time.Time
if timeout != nil {
absTimeout = time.Now().Add(*timeout)
} else {
absTimeout = time.Now().Add(time.Second * 2)
}
var err error
var h syscall.Handle
@ -147,22 +154,13 @@ func DialPipe(path string, timeout *time.Duration) (net.Conn, error) {
if err != cERROR_PIPE_BUSY {
break
}
now := time.Now()
var ms uint32
if absTimeout.IsZero() {
ms = cNMPWAIT_USE_DEFAULT_WAIT
} else if now.After(absTimeout) {
ms = cNMPWAIT_NOWAIT
} else {
ms = uint32(absTimeout.Sub(now).Nanoseconds() / 1000 / 1000)
}
err = waitNamedPipe(path, ms)
if err != nil {
if err == cERROR_SEM_TIMEOUT {
if time.Now().After(absTimeout) {
return nil, ErrTimeout
}
break
}
// Wait 10 msec and try again. This is a rather simplistic
// view, as we always try each 10 milliseconds.
time.Sleep(time.Millisecond * 10)
}
if err != nil {
return nil, &os.PathError{Op: "open", Path: path, Err: err}
@ -174,16 +172,6 @@ func DialPipe(path string, timeout *time.Duration) (net.Conn, error) {
return nil, err
}
var state uint32
err = getNamedPipeHandleState(h, &state, nil, nil, nil, nil, 0)
if err != nil {
return nil, err
}
if state&cPIPE_READMODE_MESSAGE != 0 {
return nil, &os.PathError{Op: "open", Path: path, Err: errors.New("message readmode pipes not supported")}
}
f, err := makeWin32File(h)
if err != nil {
syscall.Close(h)
@ -254,20 +242,18 @@ func (l *win32PipeListener) makeServerPipe() (*win32File, error) {
return f, nil
}
func (l *win32PipeListener) listenerRoutine() {
closed := false
for !closed {
select {
case <-l.closeCh:
closed = true
case responseCh := <-l.acceptCh:
func (l *win32PipeListener) makeConnectedServerPipe() (*win32File, error) {
p, err := l.makeServerPipe()
if err == nil {
if err != nil {
return nil, err
}
// Wait for the client to connect.
ch := make(chan error)
go func(p *win32File) {
ch <- connectPipe(p)
}(p)
select {
case err = <-ch:
if err != nil {
@ -282,10 +268,31 @@ func (l *win32PipeListener) listenerRoutine() {
if err == nil || err == ErrFileClosed {
err = ErrPipeListenerClosed
}
}
return p, err
}
func (l *win32PipeListener) listenerRoutine() {
closed := false
for !closed {
select {
case <-l.closeCh:
closed = true
case responseCh := <-l.acceptCh:
var (
p *win32File
err error
)
for {
p, err = l.makeConnectedServerPipe()
// If the connection was immediately closed by the client, try
// again.
if err != cERROR_NO_DATA {
break
}
}
responseCh <- acceptResponse{p, err}
closed = err == ErrPipeListenerClosed
}
}
syscall.Close(l.firstHandle)
@ -334,13 +341,23 @@ func ListenPipe(path string, c *PipeConfig) (net.Listener, error) {
if err != nil {
return nil, err
}
// Immediately open and then close a client handle so that the named pipe is
// created but not currently accepting connections.
// Create a client handle and connect it. This results in the pipe
// instance always existing, so that clients see ERROR_PIPE_BUSY
// rather than ERROR_FILE_NOT_FOUND. This ties the first instance
// up so that no other instances can be used. This would have been
// cleaner if the Win32 API matched CreateFile with ConnectNamedPipe
// instead of CreateNamedPipe. (Apparently created named pipes are
// considered to be in listening state regardless of whether any
// active calls to ConnectNamedPipe are outstanding.)
h2, err := createFile(path, 0, 0, nil, syscall.OPEN_EXISTING, cSECURITY_SQOS_PRESENT|cSECURITY_ANONYMOUS, 0)
if err != nil {
syscall.Close(h)
return nil, err
}
// Close the client handle. The server side of the instance will
// still be busy, leading to ERROR_PIPE_BUSY instead of
// ERROR_NOT_FOUND, as long as we don't close the server handle,
// or disconnect the client with DisconnectNamedPipe.
syscall.Close(h2)
l := &win32PipeListener{
firstHandle: h,

View File

@ -38,14 +38,12 @@ func errnoErr(e syscall.Errno) error {
var (
modkernel32 = windows.NewLazySystemDLL("kernel32.dll")
modwinmm = windows.NewLazySystemDLL("winmm.dll")
modadvapi32 = windows.NewLazySystemDLL("advapi32.dll")
procCancelIoEx = modkernel32.NewProc("CancelIoEx")
procCreateIoCompletionPort = modkernel32.NewProc("CreateIoCompletionPort")
procGetQueuedCompletionStatus = modkernel32.NewProc("GetQueuedCompletionStatus")
procSetFileCompletionNotificationModes = modkernel32.NewProc("SetFileCompletionNotificationModes")
proctimeBeginPeriod = modwinmm.NewProc("timeBeginPeriod")
procConnectNamedPipe = modkernel32.NewProc("ConnectNamedPipe")
procCreateNamedPipeW = modkernel32.NewProc("CreateNamedPipeW")
procCreateFileW = modkernel32.NewProc("CreateFileW")
@ -122,12 +120,6 @@ func setFileCompletionNotificationModes(h syscall.Handle, flags uint8) (err erro
return
}
func timeBeginPeriod(period uint32) (n int32) {
r0, _, _ := syscall.Syscall(proctimeBeginPeriod.Addr(), 1, uintptr(period), 0, 0)
n = int32(r0)
return
}
func connectNamedPipe(pipe syscall.Handle, o *syscall.Overlapped) (err error) {
r1, _, e1 := syscall.Syscall(procConnectNamedPipe.Addr(), 2, uintptr(pipe), uintptr(unsafe.Pointer(o)), 0)
if r1 == 0 {

1
vendor/github.com/Microsoft/hcsshim/.gitignore generated vendored Normal file
View File

@ -0,0 +1 @@
*.exe

17
vendor/github.com/Microsoft/hcsshim/.gometalinter.json generated vendored Normal file
View File

@ -0,0 +1,17 @@
{
"Vendor": true,
"Deadline": "2m",
"Sort": [
"linter",
"severity",
"path",
"line"
],
"Skip": [
"internal\\schema2"
],
"EnableGC": true,
"Enable": [
"gofmt"
]
}

View File

@ -3,54 +3,37 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = [
"activatelayer.go",
"baselayer.go",
"callback.go",
"cgo.go",
"container.go",
"createlayer.go",
"createsandboxlayer.go",
"deactivatelayer.go",
"destroylayer.go",
"errors.go",
"expandsandboxsize.go",
"exportlayer.go",
"getlayermountpath.go",
"getsharedbaseimages.go",
"guid.go",
"hcsshim.go",
"hnsendpoint.go",
"hnsfuncs.go",
"hnsglobals.go",
"hnsnetwork.go",
"hnspolicy.go",
"hnspolicylist.go",
"importlayer.go",
"hnssupport.go",
"interface.go",
"layerexists.go",
"layerutils.go",
"legacy.go",
"legacy18.go",
"legacy19.go",
"nametoguid.go",
"preparelayer.go",
"layer.go",
"process.go",
"processimage.go",
"safeopen.go",
"unpreparelayer.go",
"utils.go",
"version.go",
"waithelper.go",
"zhcsshim.go",
"zsyscall_windows.go",
],
cgo = True,
importmap = "k8s.io/kubernetes/vendor/github.com/Microsoft/hcsshim",
importpath = "github.com/Microsoft/hcsshim",
visibility = ["//visibility:public"],
deps = [
"//vendor/github.com/Microsoft/go-winio:go_default_library",
"//vendor/github.com/sirupsen/logrus:go_default_library",
"//vendor/github.com/Microsoft/hcsshim/internal/guid:go_default_library",
"//vendor/github.com/Microsoft/hcsshim/internal/hcs:go_default_library",
"//vendor/github.com/Microsoft/hcsshim/internal/hcserror:go_default_library",
"//vendor/github.com/Microsoft/hcsshim/internal/hns:go_default_library",
"//vendor/github.com/Microsoft/hcsshim/internal/mergemaps:go_default_library",
"//vendor/github.com/Microsoft/hcsshim/internal/schema1:go_default_library",
"//vendor/github.com/Microsoft/hcsshim/internal/wclayer:go_default_library",
] + select({
"@io_bazel_rules_go//go/platform:windows": [
"//vendor/golang.org/x/sys/windows:go_default_library",
],
"//conditions:default": [],
}),
)
filegroup(
@ -62,7 +45,27 @@ filegroup(
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
srcs = [
":package-srcs",
"//vendor/github.com/Microsoft/hcsshim/hcn:all-srcs",
"//vendor/github.com/Microsoft/hcsshim/internal/cni:all-srcs",
"//vendor/github.com/Microsoft/hcsshim/internal/guestrequest:all-srcs",
"//vendor/github.com/Microsoft/hcsshim/internal/guid:all-srcs",
"//vendor/github.com/Microsoft/hcsshim/internal/hcs:all-srcs",
"//vendor/github.com/Microsoft/hcsshim/internal/hcserror:all-srcs",
"//vendor/github.com/Microsoft/hcsshim/internal/hns:all-srcs",
"//vendor/github.com/Microsoft/hcsshim/internal/interop:all-srcs",
"//vendor/github.com/Microsoft/hcsshim/internal/logfields:all-srcs",
"//vendor/github.com/Microsoft/hcsshim/internal/longpath:all-srcs",
"//vendor/github.com/Microsoft/hcsshim/internal/mergemaps:all-srcs",
"//vendor/github.com/Microsoft/hcsshim/internal/regstate:all-srcs",
"//vendor/github.com/Microsoft/hcsshim/internal/runhcs:all-srcs",
"//vendor/github.com/Microsoft/hcsshim/internal/safefile:all-srcs",
"//vendor/github.com/Microsoft/hcsshim/internal/schema1:all-srcs",
"//vendor/github.com/Microsoft/hcsshim/internal/schema2:all-srcs",
"//vendor/github.com/Microsoft/hcsshim/internal/timeout:all-srcs",
"//vendor/github.com/Microsoft/hcsshim/internal/wclayer:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -1,12 +1,13 @@
# hcsshim
This package supports launching Windows Server containers from Go. It is
primarily used in the [Docker Engine](https://github.com/docker/docker) project,
but it can be freely used by other projects as well.
[![Build status](https://ci.appveyor.com/api/projects/status/nbcw28mnkqml0loa/branch/master?svg=true)](https://ci.appveyor.com/project/WindowsVirtualization/hcsshim/branch/master)
This package contains the Golang interface for using the Windows [Host Compute Service](https://blogs.technet.microsoft.com/virtualization/2017/01/27/introducing-the-host-compute-service-hcs/) (HCS) to launch and manage [Windows Containers](https://docs.microsoft.com/en-us/virtualization/windowscontainers/about/). It also contains other helpers and functions for managing Windows Containers such as the Golang interface for the Host Network Service (HNS).
It is primarily used in the [Moby Project](https://github.com/moby/moby), but it can be freely used by other projects as well.
## Contributing
---------------
This project welcomes contributions and suggestions. Most contributions require you to agree to a
Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us
the rights to use your contribution. For details, visit https://cla.microsoft.com.
@ -19,6 +20,11 @@ This project has adopted the [Microsoft Open Source Code of Conduct](https://ope
For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or
contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
## Dependencies
This project requires Golang 1.9 or newer to build.
For system requirements to run this project, see the Microsoft docs on [Windows Container requirements](https://docs.microsoft.com/en-us/virtualization/windowscontainers/deploy-containers/system-requirements).
## Reporting Security Issues
@ -29,5 +35,7 @@ email to ensure we received your original message. Further information, includin
[MSRC PGP](https://technet.microsoft.com/en-us/security/dn606155) key, can be found in
the [Security TechCenter](https://technet.microsoft.com/en-us/security/default).
-------------------------------------------
For additional details, see [Report a Computer Security Vulnerability](https://technet.microsoft.com/en-us/security/ff852094.aspx) on Technet
---------------
Copyright (c) 2018 Microsoft Corp. All rights reserved.

View File

@ -1,28 +0,0 @@
package hcsshim
import "github.com/sirupsen/logrus"
// ActivateLayer will find the layer with the given id and mount it's filesystem.
// For a read/write layer, the mounted filesystem will appear as a volume on the
// host, while a read-only layer is generally expected to be a no-op.
// An activated layer must later be deactivated via DeactivateLayer.
func ActivateLayer(info DriverInfo, id string) error {
title := "hcsshim::ActivateLayer "
logrus.Debugf(title+"Flavour %d ID %s", info.Flavour, id)
infop, err := convertDriverInfo(info)
if err != nil {
logrus.Error(err)
return err
}
err = activateLayer(&infop, id)
if err != nil {
err = makeErrorf(err, title, "id=%s flavour=%d", id, info.Flavour)
logrus.Error(err)
return err
}
logrus.Debugf(title+" - succeeded id=%s flavour=%d", id, info.Flavour)
return nil
}

28
vendor/github.com/Microsoft/hcsshim/appveyor.yml generated vendored Normal file
View File

@ -0,0 +1,28 @@
version: 0.1.{build}
image: Visual Studio 2017
clone_folder: c:\gopath\src\github.com\Microsoft\hcsshim
environment:
GOPATH: c:\gopath
PATH: C:\mingw-w64\x86_64-7.2.0-posix-seh-rt_v5-rev1\mingw64\bin;%GOPATH%\bin;%PATH%
build_script:
- go get -u github.com/alecthomas/gometalinter
- gometalinter.exe --install
- gometalinter.exe --config .gometalinter.json ./...
- go get -v -d -t -tags "functional integration admin" ./...
- go build ./cmd/wclayer
- go build ./cmd/runhcs
- go build ./cmd/tar2ext4
- go test -v ./... -tags admin
- go test -c ./test/functional/ -tags functional
- go test -c ./test/runhcs/ -tags integration
artifacts:
- path: 'wclayer.exe'
- path: 'runhcs.exe'
- path: 'tar2ext4.exe'
- path: 'functional.test.exe'
- path: 'runhcs.test.exe'

View File

@ -1,79 +0,0 @@
package hcsshim
import (
"sync"
"syscall"
)
var (
nextCallback uintptr
callbackMap = map[uintptr]*notifcationWatcherContext{}
callbackMapLock = sync.RWMutex{}
notificationWatcherCallback = syscall.NewCallback(notificationWatcher)
// Notifications for HCS_SYSTEM handles
hcsNotificationSystemExited hcsNotification = 0x00000001
hcsNotificationSystemCreateCompleted hcsNotification = 0x00000002
hcsNotificationSystemStartCompleted hcsNotification = 0x00000003
hcsNotificationSystemPauseCompleted hcsNotification = 0x00000004
hcsNotificationSystemResumeCompleted hcsNotification = 0x00000005
// Notifications for HCS_PROCESS handles
hcsNotificationProcessExited hcsNotification = 0x00010000
// Common notifications
hcsNotificationInvalid hcsNotification = 0x00000000
hcsNotificationServiceDisconnect hcsNotification = 0x01000000
)
type hcsNotification uint32
type notificationChannel chan error
type notifcationWatcherContext struct {
channels notificationChannels
handle hcsCallback
}
type notificationChannels map[hcsNotification]notificationChannel
func newChannels() notificationChannels {
channels := make(notificationChannels)
channels[hcsNotificationSystemExited] = make(notificationChannel, 1)
channels[hcsNotificationSystemCreateCompleted] = make(notificationChannel, 1)
channels[hcsNotificationSystemStartCompleted] = make(notificationChannel, 1)
channels[hcsNotificationSystemPauseCompleted] = make(notificationChannel, 1)
channels[hcsNotificationSystemResumeCompleted] = make(notificationChannel, 1)
channels[hcsNotificationProcessExited] = make(notificationChannel, 1)
channels[hcsNotificationServiceDisconnect] = make(notificationChannel, 1)
return channels
}
func closeChannels(channels notificationChannels) {
close(channels[hcsNotificationSystemExited])
close(channels[hcsNotificationSystemCreateCompleted])
close(channels[hcsNotificationSystemStartCompleted])
close(channels[hcsNotificationSystemPauseCompleted])
close(channels[hcsNotificationSystemResumeCompleted])
close(channels[hcsNotificationProcessExited])
close(channels[hcsNotificationServiceDisconnect])
}
func notificationWatcher(notificationType hcsNotification, callbackNumber uintptr, notificationStatus uintptr, notificationData *uint16) uintptr {
var result error
if int32(notificationStatus) < 0 {
result = syscall.Errno(win32FromHresult(notificationStatus))
}
callbackMapLock.RLock()
context := callbackMap[callbackNumber]
callbackMapLock.RUnlock()
if context == nil {
return 0
}
context.channels[notificationType] <- result
return 0
}

View File

@ -1,800 +1,192 @@
package hcsshim
import (
"encoding/json"
"fmt"
"os"
"sync"
"syscall"
"time"
"github.com/sirupsen/logrus"
"github.com/Microsoft/hcsshim/internal/hcs"
"github.com/Microsoft/hcsshim/internal/mergemaps"
"github.com/Microsoft/hcsshim/internal/schema1"
)
var (
defaultTimeout = time.Minute * 4
)
const (
pendingUpdatesQuery = `{ "PropertyTypes" : ["PendingUpdates"]}`
statisticsQuery = `{ "PropertyTypes" : ["Statistics"]}`
processListQuery = `{ "PropertyTypes" : ["ProcessList"]}`
mappedVirtualDiskQuery = `{ "PropertyTypes" : ["MappedVirtualDisk"]}`
)
type container struct {
handleLock sync.RWMutex
handle hcsSystem
id string
callbackNumber uintptr
}
// ContainerProperties holds the properties for a container and the processes running in that container
type ContainerProperties struct {
ID string `json:"Id"`
Name string
SystemType string
Owner string
SiloGUID string `json:"SiloGuid,omitempty"`
RuntimeID string `json:"RuntimeId,omitempty"`
IsRuntimeTemplate bool `json:",omitempty"`
RuntimeImagePath string `json:",omitempty"`
Stopped bool `json:",omitempty"`
ExitType string `json:",omitempty"`
AreUpdatesPending bool `json:",omitempty"`
ObRoot string `json:",omitempty"`
Statistics Statistics `json:",omitempty"`
ProcessList []ProcessListItem `json:",omitempty"`
MappedVirtualDiskControllers map[int]MappedVirtualDiskController `json:",omitempty"`
}
type ContainerProperties = schema1.ContainerProperties
// MemoryStats holds the memory statistics for a container
type MemoryStats struct {
UsageCommitBytes uint64 `json:"MemoryUsageCommitBytes,omitempty"`
UsageCommitPeakBytes uint64 `json:"MemoryUsageCommitPeakBytes,omitempty"`
UsagePrivateWorkingSetBytes uint64 `json:"MemoryUsagePrivateWorkingSetBytes,omitempty"`
}
type MemoryStats = schema1.MemoryStats
// ProcessorStats holds the processor statistics for a container
type ProcessorStats struct {
TotalRuntime100ns uint64 `json:",omitempty"`
RuntimeUser100ns uint64 `json:",omitempty"`
RuntimeKernel100ns uint64 `json:",omitempty"`
}
type ProcessorStats = schema1.ProcessorStats
// StorageStats holds the storage statistics for a container
type StorageStats struct {
ReadCountNormalized uint64 `json:",omitempty"`
ReadSizeBytes uint64 `json:",omitempty"`
WriteCountNormalized uint64 `json:",omitempty"`
WriteSizeBytes uint64 `json:",omitempty"`
}
type StorageStats = schema1.StorageStats
// NetworkStats holds the network statistics for a container
type NetworkStats struct {
BytesReceived uint64 `json:",omitempty"`
BytesSent uint64 `json:",omitempty"`
PacketsReceived uint64 `json:",omitempty"`
PacketsSent uint64 `json:",omitempty"`
DroppedPacketsIncoming uint64 `json:",omitempty"`
DroppedPacketsOutgoing uint64 `json:",omitempty"`
EndpointId string `json:",omitempty"`
InstanceId string `json:",omitempty"`
}
type NetworkStats = schema1.NetworkStats
// Statistics is the structure returned by a statistics call on a container
type Statistics struct {
Timestamp time.Time `json:",omitempty"`
ContainerStartTime time.Time `json:",omitempty"`
Uptime100ns uint64 `json:",omitempty"`
Memory MemoryStats `json:",omitempty"`
Processor ProcessorStats `json:",omitempty"`
Storage StorageStats `json:",omitempty"`
Network []NetworkStats `json:",omitempty"`
}
type Statistics = schema1.Statistics
// ProcessList is the structure of an item returned by a ProcessList call on a container
type ProcessListItem struct {
CreateTimestamp time.Time `json:",omitempty"`
ImageName string `json:",omitempty"`
KernelTime100ns uint64 `json:",omitempty"`
MemoryCommitBytes uint64 `json:",omitempty"`
MemoryWorkingSetPrivateBytes uint64 `json:",omitempty"`
MemoryWorkingSetSharedBytes uint64 `json:",omitempty"`
ProcessId uint32 `json:",omitempty"`
UserTime100ns uint64 `json:",omitempty"`
}
type ProcessListItem = schema1.ProcessListItem
// MappedVirtualDiskController is the structure of an item returned by a MappedVirtualDiskList call on a container
type MappedVirtualDiskController struct {
MappedVirtualDisks map[int]MappedVirtualDisk `json:",omitempty"`
}
type MappedVirtualDiskController = schema1.MappedVirtualDiskController
// Type of Request Support in ModifySystem
type RequestType string
type RequestType = schema1.RequestType
// Type of Resource Support in ModifySystem
type ResourceType string
type ResourceType = schema1.ResourceType
// RequestType const
const (
Add RequestType = "Add"
Remove RequestType = "Remove"
Network ResourceType = "Network"
Add = schema1.Add
Remove = schema1.Remove
Network = schema1.Network
)
// ResourceModificationRequestResponse is the structure used to send request to the container to modify the system
// Supported resource types are Network and Request Types are Add/Remove
type ResourceModificationRequestResponse struct {
Resource ResourceType `json:"ResourceType"`
Data interface{} `json:"Settings"`
Request RequestType `json:"RequestType,omitempty"`
type ResourceModificationRequestResponse = schema1.ResourceModificationRequestResponse
type container struct {
system *hcs.System
}
// createContainerAdditionalJSON is read from the environment at initialisation
// createComputeSystemAdditionalJSON is read from the environment at initialisation
// time. It allows an environment variable to define additional JSON which
// is merged in the CreateContainer call to HCS.
var createContainerAdditionalJSON string
// is merged in the CreateComputeSystem call to HCS.
var createContainerAdditionalJSON []byte
func init() {
createContainerAdditionalJSON = os.Getenv("HCSSHIM_CREATECONTAINER_ADDITIONALJSON")
createContainerAdditionalJSON = ([]byte)(os.Getenv("HCSSHIM_CREATECONTAINER_ADDITIONALJSON"))
}
// CreateContainer creates a new container with the given configuration but does not start it.
func CreateContainer(id string, c *ContainerConfig) (Container, error) {
return createContainerWithJSON(id, c, "")
fullConfig, err := mergemaps.MergeJSON(c, createContainerAdditionalJSON)
if err != nil {
return nil, fmt.Errorf("failed to merge additional JSON '%s': %s", createContainerAdditionalJSON, err)
}
// CreateContainerWithJSON creates a new container with the given configuration but does not start it.
// It is identical to CreateContainer except that optional additional JSON can be merged before passing to HCS.
func CreateContainerWithJSON(id string, c *ContainerConfig, additionalJSON string) (Container, error) {
return createContainerWithJSON(id, c, additionalJSON)
}
func createContainerWithJSON(id string, c *ContainerConfig, additionalJSON string) (Container, error) {
operation := "CreateContainer"
title := "HCSShim::" + operation
container := &container{
id: id,
}
configurationb, err := json.Marshal(c)
system, err := hcs.CreateComputeSystem(id, fullConfig)
if err != nil {
return nil, err
}
configuration := string(configurationb)
logrus.Debugf(title+" id=%s config=%s", id, configuration)
// Merge any additional JSON. Priority is given to what is passed in explicitly,
// falling back to what's set in the environment.
if additionalJSON == "" && createContainerAdditionalJSON != "" {
additionalJSON = createContainerAdditionalJSON
}
if additionalJSON != "" {
configurationMap := map[string]interface{}{}
if err := json.Unmarshal([]byte(configuration), &configurationMap); err != nil {
return nil, fmt.Errorf("failed to unmarshal %s: %s", configuration, err)
}
additionalMap := map[string]interface{}{}
if err := json.Unmarshal([]byte(additionalJSON), &additionalMap); err != nil {
return nil, fmt.Errorf("failed to unmarshal %s: %s", additionalJSON, err)
}
mergedMap := mergeMaps(additionalMap, configurationMap)
mergedJSON, err := json.Marshal(mergedMap)
if err != nil {
return nil, fmt.Errorf("failed to marshal merged configuration map %+v: %s", mergedMap, err)
}
configuration = string(mergedJSON)
logrus.Debugf(title+" id=%s merged config=%s", id, configuration)
}
var (
resultp *uint16
identity syscall.Handle
)
createError := hcsCreateComputeSystem(id, configuration, identity, &container.handle, &resultp)
if createError == nil || IsPending(createError) {
if err := container.registerCallback(); err != nil {
// Terminate the container if it still exists. We're okay to ignore a failure here.
container.Terminate()
return nil, makeContainerError(container, operation, "", err)
}
}
err = processAsyncHcsResult(createError, resultp, container.callbackNumber, hcsNotificationSystemCreateCompleted, &defaultTimeout)
if err != nil {
if err == ErrTimeout {
// Terminate the container if it still exists. We're okay to ignore a failure here.
container.Terminate()
}
return nil, makeContainerError(container, operation, configuration, err)
}
logrus.Debugf(title+" succeeded id=%s handle=%d", id, container.handle)
return container, nil
}
// mergeMaps recursively merges map `fromMap` into map `ToMap`. Any pre-existing values
// in ToMap are overwritten. Values in fromMap are added to ToMap.
// From http://stackoverflow.com/questions/40491438/merging-two-json-strings-in-golang
func mergeMaps(fromMap, ToMap interface{}) interface{} {
switch fromMap := fromMap.(type) {
case map[string]interface{}:
ToMap, ok := ToMap.(map[string]interface{})
if !ok {
return fromMap
}
for keyToMap, valueToMap := range ToMap {
if valueFromMap, ok := fromMap[keyToMap]; ok {
fromMap[keyToMap] = mergeMaps(valueFromMap, valueToMap)
} else {
fromMap[keyToMap] = valueToMap
}
}
case nil:
// merge(nil, map[string]interface{...}) -> map[string]interface{...}
ToMap, ok := ToMap.(map[string]interface{})
if ok {
return ToMap
}
}
return fromMap
return &container{system}, err
}
// OpenContainer opens an existing container by ID.
func OpenContainer(id string) (Container, error) {
operation := "OpenContainer"
title := "HCSShim::" + operation
logrus.Debugf(title+" id=%s", id)
container := &container{
id: id,
}
var (
handle hcsSystem
resultp *uint16
)
err := hcsOpenComputeSystem(id, &handle, &resultp)
err = processHcsResult(err, resultp)
system, err := hcs.OpenComputeSystem(id)
if err != nil {
return nil, makeContainerError(container, operation, "", err)
return nil, err
}
container.handle = handle
if err := container.registerCallback(); err != nil {
return nil, makeContainerError(container, operation, "", err)
}
logrus.Debugf(title+" succeeded id=%s handle=%d", id, handle)
return container, nil
return &container{system}, err
}
// GetContainers gets a list of the containers on the system that match the query
func GetContainers(q ComputeSystemQuery) ([]ContainerProperties, error) {
operation := "GetContainers"
title := "HCSShim::" + operation
queryb, err := json.Marshal(q)
if err != nil {
return nil, err
}
query := string(queryb)
logrus.Debugf(title+" query=%s", query)
var (
resultp *uint16
computeSystemsp *uint16
)
err = hcsEnumerateComputeSystems(query, &computeSystemsp, &resultp)
err = processHcsResult(err, resultp)
if err != nil {
return nil, err
}
if computeSystemsp == nil {
return nil, ErrUnexpectedValue
}
computeSystemsRaw := convertAndFreeCoTaskMemBytes(computeSystemsp)
computeSystems := []ContainerProperties{}
if err := json.Unmarshal(computeSystemsRaw, &computeSystems); err != nil {
return nil, err
}
logrus.Debugf(title + " succeeded")
return computeSystems, nil
return hcs.GetComputeSystems(q)
}
// Start synchronously starts the container.
func (container *container) Start() error {
container.handleLock.RLock()
defer container.handleLock.RUnlock()
operation := "Start"
title := "HCSShim::Container::" + operation
logrus.Debugf(title+" id=%s", container.id)
if container.handle == 0 {
return makeContainerError(container, operation, "", ErrAlreadyClosed)
return convertSystemError(container.system.Start(), container)
}
var resultp *uint16
err := hcsStartComputeSystem(container.handle, "", &resultp)
err = processAsyncHcsResult(err, resultp, container.callbackNumber, hcsNotificationSystemStartCompleted, &defaultTimeout)
if err != nil {
return makeContainerError(container, operation, "", err)
}
logrus.Debugf(title+" succeeded id=%s", container.id)
return nil
}
// Shutdown requests a container shutdown, if IsPending() on the error returned is true,
// it may not actually be shut down until Wait() succeeds.
// Shutdown requests a container shutdown, but it may not actually be shutdown until Wait() succeeds.
func (container *container) Shutdown() error {
container.handleLock.RLock()
defer container.handleLock.RUnlock()
operation := "Shutdown"
title := "HCSShim::Container::" + operation
logrus.Debugf(title+" id=%s", container.id)
if container.handle == 0 {
return makeContainerError(container, operation, "", ErrAlreadyClosed)
return convertSystemError(container.system.Shutdown(), container)
}
var resultp *uint16
err := hcsShutdownComputeSystem(container.handle, "", &resultp)
err = processHcsResult(err, resultp)
if err != nil {
return makeContainerError(container, operation, "", err)
}
logrus.Debugf(title+" succeeded id=%s", container.id)
return nil
}
// Terminate requests a container terminate, if IsPending() on the error returned is true,
// it may not actually be shut down until Wait() succeeds.
// Terminate requests a container terminate, but it may not actually be terminated until Wait() succeeds.
func (container *container) Terminate() error {
container.handleLock.RLock()
defer container.handleLock.RUnlock()
operation := "Terminate"
title := "HCSShim::Container::" + operation
logrus.Debugf(title+" id=%s", container.id)
if container.handle == 0 {
return makeContainerError(container, operation, "", ErrAlreadyClosed)
return convertSystemError(container.system.Terminate(), container)
}
var resultp *uint16
err := hcsTerminateComputeSystem(container.handle, "", &resultp)
err = processHcsResult(err, resultp)
if err != nil {
return makeContainerError(container, operation, "", err)
}
logrus.Debugf(title+" succeeded id=%s", container.id)
return nil
}
// Wait synchronously waits for the container to shutdown or terminate.
// Waits synchronously waits for the container to shutdown or terminate.
func (container *container) Wait() error {
operation := "Wait"
title := "HCSShim::Container::" + operation
logrus.Debugf(title+" id=%s", container.id)
err := waitForNotification(container.callbackNumber, hcsNotificationSystemExited, nil)
if err != nil {
return makeContainerError(container, operation, "", err)
return convertSystemError(container.system.Wait(), container)
}
logrus.Debugf(title+" succeeded id=%s", container.id)
return nil
// WaitTimeout synchronously waits for the container to terminate or the duration to elapse. It
// returns false if timeout occurs.
func (container *container) WaitTimeout(t time.Duration) error {
return convertSystemError(container.system.WaitTimeout(t), container)
}
// WaitTimeout synchronously waits for the container to terminate or the duration to elapse.
// If the timeout expires, IsTimeout(err) == true
func (container *container) WaitTimeout(timeout time.Duration) error {
operation := "WaitTimeout"
title := "HCSShim::Container::" + operation
logrus.Debugf(title+" id=%s", container.id)
err := waitForNotification(container.callbackNumber, hcsNotificationSystemExited, &timeout)
if err != nil {
return makeContainerError(container, operation, "", err)
// Pause pauses the execution of a container.
func (container *container) Pause() error {
return convertSystemError(container.system.Pause(), container)
}
logrus.Debugf(title+" succeeded id=%s", container.id)
return nil
}
func (container *container) properties(query string) (*ContainerProperties, error) {
var (
resultp *uint16
propertiesp *uint16
)
err := hcsGetComputeSystemProperties(container.handle, query, &propertiesp, &resultp)
err = processHcsResult(err, resultp)
if err != nil {
return nil, err
}
if propertiesp == nil {
return nil, ErrUnexpectedValue
}
propertiesRaw := convertAndFreeCoTaskMemBytes(propertiesp)
properties := &ContainerProperties{}
if err := json.Unmarshal(propertiesRaw, properties); err != nil {
return nil, err
}
return properties, nil
// Resume resumes the execution of a container.
func (container *container) Resume() error {
return convertSystemError(container.system.Resume(), container)
}
// HasPendingUpdates returns true if the container has updates pending to install
func (container *container) HasPendingUpdates() (bool, error) {
container.handleLock.RLock()
defer container.handleLock.RUnlock()
operation := "HasPendingUpdates"
title := "HCSShim::Container::" + operation
logrus.Debugf(title+" id=%s", container.id)
if container.handle == 0 {
return false, makeContainerError(container, operation, "", ErrAlreadyClosed)
return false, nil
}
properties, err := container.properties(pendingUpdatesQuery)
if err != nil {
return false, makeContainerError(container, operation, "", err)
}
logrus.Debugf(title+" succeeded id=%s", container.id)
return properties.AreUpdatesPending, nil
}
// Statistics returns statistics for the container
// Statistics returns statistics for the container. This is a legacy v1 call
func (container *container) Statistics() (Statistics, error) {
container.handleLock.RLock()
defer container.handleLock.RUnlock()
operation := "Statistics"
title := "HCSShim::Container::" + operation
logrus.Debugf(title+" id=%s", container.id)
if container.handle == 0 {
return Statistics{}, makeContainerError(container, operation, "", ErrAlreadyClosed)
}
properties, err := container.properties(statisticsQuery)
properties, err := container.system.Properties(schema1.PropertyTypeStatistics)
if err != nil {
return Statistics{}, makeContainerError(container, operation, "", err)
return Statistics{}, convertSystemError(err, container)
}
logrus.Debugf(title+" succeeded id=%s", container.id)
return properties.Statistics, nil
}
// ProcessList returns an array of ProcessListItems for the container
// ProcessList returns an array of ProcessListItems for the container. This is a legacy v1 call
func (container *container) ProcessList() ([]ProcessListItem, error) {
container.handleLock.RLock()
defer container.handleLock.RUnlock()
operation := "ProcessList"
title := "HCSShim::Container::" + operation
logrus.Debugf(title+" id=%s", container.id)
if container.handle == 0 {
return nil, makeContainerError(container, operation, "", ErrAlreadyClosed)
}
properties, err := container.properties(processListQuery)
properties, err := container.system.Properties(schema1.PropertyTypeProcessList)
if err != nil {
return nil, makeContainerError(container, operation, "", err)
return nil, convertSystemError(err, container)
}
logrus.Debugf(title+" succeeded id=%s", container.id)
return properties.ProcessList, nil
}
// MappedVirtualDisks returns a map of the controllers and the disks mapped
// to a container.
//
// Example of JSON returned by the query.
//{
// "Id":"1126e8d7d279c707a666972a15976371d365eaf622c02cea2c442b84f6f550a3_svm",
// "SystemType":"Container",
// "RuntimeOsType":"Linux",
// "RuntimeId":"00000000-0000-0000-0000-000000000000",
// "State":"Running",
// "MappedVirtualDiskControllers":{
// "0":{
// "MappedVirtualDisks":{
// "2":{
// "HostPath":"C:\\lcow\\lcow\\scratch\\1126e8d7d279c707a666972a15976371d365eaf622c02cea2c442b84f6f550a3.vhdx",
// "ContainerPath":"/mnt/gcs/LinuxServiceVM/scratch",
// "Lun":2,
// "CreateInUtilityVM":true
// },
// "3":{
// "HostPath":"C:\\lcow\\lcow\\1126e8d7d279c707a666972a15976371d365eaf622c02cea2c442b84f6f550a3\\sandbox.vhdx",
// "Lun":3,
// "CreateInUtilityVM":true,
// "AttachOnly":true
// }
// }
// }
// }
//}
// This is a legacy v1 call
func (container *container) MappedVirtualDisks() (map[int]MappedVirtualDiskController, error) {
container.handleLock.RLock()
defer container.handleLock.RUnlock()
operation := "MappedVirtualDiskList"
title := "HCSShim::Container::" + operation
logrus.Debugf(title+" id=%s", container.id)
if container.handle == 0 {
return nil, makeContainerError(container, operation, "", ErrAlreadyClosed)
}
properties, err := container.properties(mappedVirtualDiskQuery)
properties, err := container.system.Properties(schema1.PropertyTypeMappedVirtualDisk)
if err != nil {
return nil, makeContainerError(container, operation, "", err)
return nil, convertSystemError(err, container)
}
logrus.Debugf(title+" succeeded id=%s", container.id)
return properties.MappedVirtualDiskControllers, nil
}
// Pause pauses the execution of the container. This feature is not enabled in TP5.
func (container *container) Pause() error {
container.handleLock.RLock()
defer container.handleLock.RUnlock()
operation := "Pause"
title := "HCSShim::Container::" + operation
logrus.Debugf(title+" id=%s", container.id)
if container.handle == 0 {
return makeContainerError(container, operation, "", ErrAlreadyClosed)
}
var resultp *uint16
err := hcsPauseComputeSystem(container.handle, "", &resultp)
err = processAsyncHcsResult(err, resultp, container.callbackNumber, hcsNotificationSystemPauseCompleted, &defaultTimeout)
if err != nil {
return makeContainerError(container, operation, "", err)
}
logrus.Debugf(title+" succeeded id=%s", container.id)
return nil
}
// Resume resumes the execution of the container. This feature is not enabled in TP5.
func (container *container) Resume() error {
container.handleLock.RLock()
defer container.handleLock.RUnlock()
operation := "Resume"
title := "HCSShim::Container::" + operation
logrus.Debugf(title+" id=%s", container.id)
if container.handle == 0 {
return makeContainerError(container, operation, "", ErrAlreadyClosed)
}
var resultp *uint16
err := hcsResumeComputeSystem(container.handle, "", &resultp)
err = processAsyncHcsResult(err, resultp, container.callbackNumber, hcsNotificationSystemResumeCompleted, &defaultTimeout)
if err != nil {
return makeContainerError(container, operation, "", err)
}
logrus.Debugf(title+" succeeded id=%s", container.id)
return nil
}
// CreateProcess launches a new process within the container.
func (container *container) CreateProcess(c *ProcessConfig) (Process, error) {
container.handleLock.RLock()
defer container.handleLock.RUnlock()
operation := "CreateProcess"
title := "HCSShim::Container::" + operation
var (
processInfo hcsProcessInformation
processHandle hcsProcess
resultp *uint16
)
if container.handle == 0 {
return nil, makeContainerError(container, operation, "", ErrAlreadyClosed)
}
// If we are not emulating a console, ignore any console size passed to us
if !c.EmulateConsole {
c.ConsoleSize[0] = 0
c.ConsoleSize[1] = 0
}
configurationb, err := json.Marshal(c)
p, err := container.system.CreateProcess(c)
if err != nil {
return nil, makeContainerError(container, operation, "", err)
return nil, convertSystemError(err, container)
}
configuration := string(configurationb)
logrus.Debugf(title+" id=%s config=%s", container.id, configuration)
err = hcsCreateProcess(container.handle, configuration, &processInfo, &processHandle, &resultp)
err = processHcsResult(err, resultp)
if err != nil {
return nil, makeContainerError(container, operation, configuration, err)
}
process := &process{
handle: processHandle,
processID: int(processInfo.ProcessId),
container: container,
cachedPipes: &cachedPipes{
stdIn: processInfo.StdInput,
stdOut: processInfo.StdOutput,
stdErr: processInfo.StdError,
},
}
if err := process.registerCallback(); err != nil {
return nil, makeContainerError(container, operation, "", err)
}
logrus.Debugf(title+" succeeded id=%s processid=%d", container.id, process.processID)
return process, nil
return &process{p}, nil
}
// OpenProcess gets an interface to an existing process within the container.
func (container *container) OpenProcess(pid int) (Process, error) {
container.handleLock.RLock()
defer container.handleLock.RUnlock()
operation := "OpenProcess"
title := "HCSShim::Container::" + operation
logrus.Debugf(title+" id=%s, processid=%d", container.id, pid)
var (
processHandle hcsProcess
resultp *uint16
)
if container.handle == 0 {
return nil, makeContainerError(container, operation, "", ErrAlreadyClosed)
}
err := hcsOpenProcess(container.handle, uint32(pid), &processHandle, &resultp)
err = processHcsResult(err, resultp)
p, err := container.system.OpenProcess(pid)
if err != nil {
return nil, makeContainerError(container, operation, "", err)
return nil, convertSystemError(err, container)
}
process := &process{
handle: processHandle,
processID: pid,
container: container,
}
if err := process.registerCallback(); err != nil {
return nil, makeContainerError(container, operation, "", err)
}
logrus.Debugf(title+" succeeded id=%s processid=%s", container.id, process.processID)
return process, nil
return &process{p}, nil
}
// Close cleans up any state associated with the container but does not terminate or wait for it.
func (container *container) Close() error {
container.handleLock.Lock()
defer container.handleLock.Unlock()
operation := "Close"
title := "HCSShim::Container::" + operation
logrus.Debugf(title+" id=%s", container.id)
// Don't double free this
if container.handle == 0 {
return nil
return convertSystemError(container.system.Close(), container)
}
if err := container.unregisterCallback(); err != nil {
return makeContainerError(container, operation, "", err)
}
if err := hcsCloseComputeSystem(container.handle); err != nil {
return makeContainerError(container, operation, "", err)
}
container.handle = 0
logrus.Debugf(title+" succeeded id=%s", container.id)
return nil
}
func (container *container) registerCallback() error {
context := &notifcationWatcherContext{
channels: newChannels(),
}
callbackMapLock.Lock()
callbackNumber := nextCallback
nextCallback++
callbackMap[callbackNumber] = context
callbackMapLock.Unlock()
var callbackHandle hcsCallback
err := hcsRegisterComputeSystemCallback(container.handle, notificationWatcherCallback, callbackNumber, &callbackHandle)
if err != nil {
return err
}
context.handle = callbackHandle
container.callbackNumber = callbackNumber
return nil
}
func (container *container) unregisterCallback() error {
callbackNumber := container.callbackNumber
callbackMapLock.RLock()
context := callbackMap[callbackNumber]
callbackMapLock.RUnlock()
if context == nil {
return nil
}
handle := context.handle
if handle == 0 {
return nil
}
// hcsUnregisterComputeSystemCallback has its own syncronization
// to wait for all callbacks to complete. We must NOT hold the callbackMapLock.
err := hcsUnregisterComputeSystemCallback(handle)
if err != nil {
return err
}
closeChannels(context.channels)
callbackMapLock.Lock()
callbackMap[callbackNumber] = nil
callbackMapLock.Unlock()
handle = 0
return nil
}
// Modifies the System by sending a request to HCS
// Modify the System
func (container *container) Modify(config *ResourceModificationRequestResponse) error {
container.handleLock.RLock()
defer container.handleLock.RUnlock()
operation := "Modify"
title := "HCSShim::Container::" + operation
if container.handle == 0 {
return makeContainerError(container, operation, "", ErrAlreadyClosed)
}
requestJSON, err := json.Marshal(config)
if err != nil {
return err
}
requestString := string(requestJSON)
logrus.Debugf(title+" id=%s request=%s", container.id, requestString)
var resultp *uint16
err = hcsModifyComputeSystem(container.handle, requestString, &resultp)
err = processHcsResult(err, resultp)
if err != nil {
return makeContainerError(container, operation, "", err)
}
logrus.Debugf(title+" succeeded id=%s", container.id)
return nil
return convertSystemError(container.system.Modify(config), container)
}

View File

@ -1,27 +0,0 @@
package hcsshim
import "github.com/sirupsen/logrus"
// CreateLayer creates a new, empty, read-only layer on the filesystem based on
// the parent layer provided.
func CreateLayer(info DriverInfo, id, parent string) error {
title := "hcsshim::CreateLayer "
logrus.Debugf(title+"Flavour %d ID %s parent %s", info.Flavour, id, parent)
// Convert info to API calling convention
infop, err := convertDriverInfo(info)
if err != nil {
logrus.Error(err)
return err
}
err = createLayer(&infop, id, parent)
if err != nil {
err = makeErrorf(err, title, "id=%s parent=%s flavour=%d", id, parent, info.Flavour)
logrus.Error(err)
return err
}
logrus.Debugf(title+" - succeeded id=%s parent=%s flavour=%d", id, parent, info.Flavour)
return nil
}

View File

@ -1,35 +0,0 @@
package hcsshim
import "github.com/sirupsen/logrus"
// CreateSandboxLayer creates and populates new read-write layer for use by a container.
// This requires both the id of the direct parent layer, as well as the full list
// of paths to all parent layers up to the base (and including the direct parent
// whose id was provided).
func CreateSandboxLayer(info DriverInfo, layerId, parentId string, parentLayerPaths []string) error {
title := "hcsshim::CreateSandboxLayer "
logrus.Debugf(title+"layerId %s parentId %s", layerId, parentId)
// Generate layer descriptors
layers, err := layerPathsToDescriptors(parentLayerPaths)
if err != nil {
return err
}
// Convert info to API calling convention
infop, err := convertDriverInfo(info)
if err != nil {
logrus.Error(err)
return err
}
err = createSandboxLayer(&infop, layerId, parentId, layers)
if err != nil {
err = makeErrorf(err, title, "layerId=%s parentId=%s", layerId, parentId)
logrus.Error(err)
return err
}
logrus.Debugf(title+"- succeeded layerId=%s parentId=%s", layerId, parentId)
return nil
}

View File

@ -1,26 +0,0 @@
package hcsshim
import "github.com/sirupsen/logrus"
// DeactivateLayer will dismount a layer that was mounted via ActivateLayer.
func DeactivateLayer(info DriverInfo, id string) error {
title := "hcsshim::DeactivateLayer "
logrus.Debugf(title+"Flavour %d ID %s", info.Flavour, id)
// Convert info to API calling convention
infop, err := convertDriverInfo(info)
if err != nil {
logrus.Error(err)
return err
}
err = deactivateLayer(&infop, id)
if err != nil {
err = makeErrorf(err, title, "id=%s flavour=%d", id, info.Flavour)
logrus.Error(err)
return err
}
logrus.Debugf(title+"succeeded flavour=%d id=%s", info.Flavour, id)
return nil
}

View File

@ -1,27 +0,0 @@
package hcsshim
import "github.com/sirupsen/logrus"
// DestroyLayer will remove the on-disk files representing the layer with the given
// id, including that layer's containing folder, if any.
func DestroyLayer(info DriverInfo, id string) error {
title := "hcsshim::DestroyLayer "
logrus.Debugf(title+"Flavour %d ID %s", info.Flavour, id)
// Convert info to API calling convention
infop, err := convertDriverInfo(info)
if err != nil {
logrus.Error(err)
return err
}
err = destroyLayer(&infop, id)
if err != nil {
err = makeErrorf(err, title, "id=%s flavour=%d", id, info.Flavour)
logrus.Error(err)
return err
}
logrus.Debugf(title+"succeeded flavour=%d id=%s", info.Flavour, id)
return nil
}

View File

@ -1,92 +1,83 @@
package hcsshim
import (
"errors"
"fmt"
"syscall"
"github.com/Microsoft/hcsshim/internal/hns"
"github.com/Microsoft/hcsshim/internal/hcs"
"github.com/Microsoft/hcsshim/internal/hcserror"
)
var (
// ErrComputeSystemDoesNotExist is an error encountered when the container being operated on no longer exists
ErrComputeSystemDoesNotExist = syscall.Errno(0xc037010e)
// ErrComputeSystemDoesNotExist is an error encountered when the container being operated on no longer exists = hcs.exist
ErrComputeSystemDoesNotExist = hcs.ErrComputeSystemDoesNotExist
// ErrElementNotFound is an error encountered when the object being referenced does not exist
ErrElementNotFound = syscall.Errno(0x490)
ErrElementNotFound = hcs.ErrElementNotFound
// ErrElementNotFound is an error encountered when the object being referenced does not exist
ErrNotSupported = syscall.Errno(0x32)
ErrNotSupported = hcs.ErrNotSupported
// ErrInvalidData is an error encountered when the request being sent to hcs is invalid/unsupported
// decimal -2147024883 / hex 0x8007000d
ErrInvalidData = syscall.Errno(0xd)
ErrInvalidData = hcs.ErrInvalidData
// ErrHandleClose is an error encountered when the handle generating the notification being waited on has been closed
ErrHandleClose = errors.New("hcsshim: the handle generating this notification has been closed")
ErrHandleClose = hcs.ErrHandleClose
// ErrAlreadyClosed is an error encountered when using a handle that has been closed by the Close method
ErrAlreadyClosed = errors.New("hcsshim: the handle has already been closed")
ErrAlreadyClosed = hcs.ErrAlreadyClosed
// ErrInvalidNotificationType is an error encountered when an invalid notification type is used
ErrInvalidNotificationType = errors.New("hcsshim: invalid notification type")
ErrInvalidNotificationType = hcs.ErrInvalidNotificationType
// ErrInvalidProcessState is an error encountered when the process is not in a valid state for the requested operation
ErrInvalidProcessState = errors.New("the process is in an invalid state for the attempted operation")
ErrInvalidProcessState = hcs.ErrInvalidProcessState
// ErrTimeout is an error encountered when waiting on a notification times out
ErrTimeout = errors.New("hcsshim: timeout waiting for notification")
ErrTimeout = hcs.ErrTimeout
// ErrUnexpectedContainerExit is the error encountered when a container exits while waiting for
// a different expected notification
ErrUnexpectedContainerExit = errors.New("unexpected container exit")
ErrUnexpectedContainerExit = hcs.ErrUnexpectedContainerExit
// ErrUnexpectedProcessAbort is the error encountered when communication with the compute service
// is lost while waiting for a notification
ErrUnexpectedProcessAbort = errors.New("lost communication with compute service")
ErrUnexpectedProcessAbort = hcs.ErrUnexpectedProcessAbort
// ErrUnexpectedValue is an error encountered when hcs returns an invalid value
ErrUnexpectedValue = errors.New("unexpected value returned from hcs")
ErrUnexpectedValue = hcs.ErrUnexpectedValue
// ErrVmcomputeAlreadyStopped is an error encountered when a shutdown or terminate request is made on a stopped container
ErrVmcomputeAlreadyStopped = syscall.Errno(0xc0370110)
ErrVmcomputeAlreadyStopped = hcs.ErrVmcomputeAlreadyStopped
// ErrVmcomputeOperationPending is an error encountered when the operation is being completed asynchronously
ErrVmcomputeOperationPending = syscall.Errno(0xC0370103)
ErrVmcomputeOperationPending = hcs.ErrVmcomputeOperationPending
// ErrVmcomputeOperationInvalidState is an error encountered when the compute system is not in a valid state for the requested operation
ErrVmcomputeOperationInvalidState = syscall.Errno(0xc0370105)
ErrVmcomputeOperationInvalidState = hcs.ErrVmcomputeOperationInvalidState
// ErrProcNotFound is an error encountered when the the process cannot be found
ErrProcNotFound = syscall.Errno(0x7f)
ErrProcNotFound = hcs.ErrProcNotFound
// ErrVmcomputeOperationAccessIsDenied is an error which can be encountered when enumerating compute systems in RS1/RS2
// builds when the underlying silo might be in the process of terminating. HCS was fixed in RS3.
ErrVmcomputeOperationAccessIsDenied = syscall.Errno(0x5)
ErrVmcomputeOperationAccessIsDenied = hcs.ErrVmcomputeOperationAccessIsDenied
// ErrVmcomputeInvalidJSON is an error encountered when the compute system does not support/understand the messages sent by management
ErrVmcomputeInvalidJSON = syscall.Errno(0xc037010d)
ErrVmcomputeInvalidJSON = hcs.ErrVmcomputeInvalidJSON
// ErrVmcomputeUnknownMessage is an error encountered guest compute system doesn't support the message
ErrVmcomputeUnknownMessage = syscall.Errno(0xc037010b)
ErrVmcomputeUnknownMessage = hcs.ErrVmcomputeUnknownMessage
// ErrNotSupported is an error encountered when hcs doesn't support the request
ErrPlatformNotSupported = errors.New("unsupported platform request")
ErrPlatformNotSupported = hcs.ErrPlatformNotSupported
)
type EndpointNotFoundError struct {
EndpointName string
}
func (e EndpointNotFoundError) Error() string {
return fmt.Sprintf("Endpoint %s not found", e.EndpointName)
}
type NetworkNotFoundError struct {
NetworkName string
}
func (e NetworkNotFoundError) Error() string {
return fmt.Sprintf("Network %s not found", e.NetworkName)
}
type EndpointNotFoundError = hns.EndpointNotFoundError
type NetworkNotFoundError = hns.NetworkNotFoundError
// ProcessError is an error encountered in HCS during an operation on a Process object
type ProcessError struct {
@ -94,6 +85,7 @@ type ProcessError struct {
Operation string
ExtraInfo string
Err error
Events []hcs.ErrorEvent
}
// ContainerError is an error encountered in HCS during an operation on a Container object
@ -102,6 +94,7 @@ type ContainerError struct {
Operation string
ExtraInfo string
Err error
Events []hcs.ErrorEvent
}
func (e *ContainerError) Error() string {
@ -113,7 +106,7 @@ func (e *ContainerError) Error() string {
return "unexpected nil container for error: " + e.Err.Error()
}
s := "container " + e.Container.id
s := "container " + e.Container.system.ID()
if e.Operation != "" {
s += " encountered an error during " + e.Operation
@ -123,11 +116,15 @@ func (e *ContainerError) Error() string {
case nil:
break
case syscall.Errno:
s += fmt.Sprintf(": failure in a Windows system call: %s (0x%x)", e.Err, win32FromError(e.Err))
s += fmt.Sprintf(": failure in a Windows system call: %s (0x%x)", e.Err, hcserror.Win32FromError(e.Err))
default:
s += fmt.Sprintf(": %s", e.Err.Error())
}
for _, ev := range e.Events {
s += "\n" + ev.String()
}
if e.ExtraInfo != "" {
s += " extra info: " + e.ExtraInfo
}
@ -153,12 +150,7 @@ func (e *ProcessError) Error() string {
return "Unexpected nil process for error: " + e.Err.Error()
}
s := fmt.Sprintf("process %d", e.Process.processID)
if e.Process.container != nil {
s += " in container " + e.Process.container.id
}
s := fmt.Sprintf("process %d in container %s", e.Process.p.Pid(), e.Process.p.SystemID())
if e.Operation != "" {
s += " encountered an error during " + e.Operation
}
@ -167,11 +159,15 @@ func (e *ProcessError) Error() string {
case nil:
break
case syscall.Errno:
s += fmt.Sprintf(": failure in a Windows system call: %s (0x%x)", e.Err, win32FromError(e.Err))
s += fmt.Sprintf(": failure in a Windows system call: %s (0x%x)", e.Err, hcserror.Win32FromError(e.Err))
default:
s += fmt.Sprintf(": %s", e.Err.Error())
}
for _, ev := range e.Events {
s += "\n" + ev.String()
}
return s
}
@ -189,37 +185,31 @@ func makeProcessError(process *process, operation string, extraInfo string, err
// already exited, or does not exist. Both IsAlreadyStopped and IsNotExist
// will currently return true when the error is ErrElementNotFound or ErrProcNotFound.
func IsNotExist(err error) bool {
err = getInnerError(err)
if _, ok := err.(EndpointNotFoundError); ok {
return true
}
if _, ok := err.(NetworkNotFoundError); ok {
return true
}
return err == ErrComputeSystemDoesNotExist ||
err == ErrElementNotFound ||
err == ErrProcNotFound
return hcs.IsNotExist(getInnerError(err))
}
// IsAlreadyClosed checks if an error is caused by the Container or Process having been
// already closed by a call to the Close() method.
func IsAlreadyClosed(err error) bool {
err = getInnerError(err)
return err == ErrAlreadyClosed
return hcs.IsAlreadyClosed(getInnerError(err))
}
// IsPending returns a boolean indicating whether the error is that
// the requested operation is being completed in the background.
func IsPending(err error) bool {
err = getInnerError(err)
return err == ErrVmcomputeOperationPending
return hcs.IsPending(getInnerError(err))
}
// IsTimeout returns a boolean indicating whether the error is caused by
// a timeout waiting for the operation to complete.
func IsTimeout(err error) bool {
err = getInnerError(err)
return err == ErrTimeout
return hcs.IsTimeout(getInnerError(err))
}
// IsAlreadyStopped returns a boolean indicating whether the error is caused by
@ -228,10 +218,7 @@ func IsTimeout(err error) bool {
// already exited, or does not exist. Both IsAlreadyStopped and IsNotExist
// will currently return true when the error is ErrElementNotFound or ErrProcNotFound.
func IsAlreadyStopped(err error) bool {
err = getInnerError(err)
return err == ErrVmcomputeAlreadyStopped ||
err == ErrElementNotFound ||
err == ErrProcNotFound
return hcs.IsAlreadyStopped(getInnerError(err))
}
// IsNotSupported returns a boolean indicating whether the error is caused by
@ -240,12 +227,7 @@ func IsAlreadyStopped(err error) bool {
// ErrVmcomputeInvalidJSON, ErrInvalidData, ErrNotSupported or ErrVmcomputeUnknownMessage
// is thrown from the Platform
func IsNotSupported(err error) bool {
err = getInnerError(err)
// If Platform doesn't recognize or support the request sent, below errors are seen
return err == ErrVmcomputeInvalidJSON ||
err == ErrInvalidData ||
err == ErrNotSupported ||
err == ErrVmcomputeUnknownMessage
return hcs.IsNotSupported(getInnerError(err))
}
func getInnerError(err error) error {
@ -259,3 +241,17 @@ func getInnerError(err error) error {
}
return err
}
func convertSystemError(err error, c *container) error {
if serr, ok := err.(*hcs.SystemError); ok {
return &ContainerError{Container: c, Operation: serr.Op, ExtraInfo: serr.Extra, Err: serr.Err, Events: serr.Events}
}
return err
}
func convertProcessError(err error, p *process) error {
if perr, ok := err.(*hcs.ProcessError); ok {
return &ProcessError{Process: p, Operation: perr.Op, Err: perr.Err, Events: perr.Events}
}
return err
}

View File

@ -1,26 +0,0 @@
package hcsshim
import "github.com/sirupsen/logrus"
// ExpandSandboxSize expands the size of a layer to at least size bytes.
func ExpandSandboxSize(info DriverInfo, layerId string, size uint64) error {
title := "hcsshim::ExpandSandboxSize "
logrus.Debugf(title+"layerId=%s size=%d", layerId, size)
// Convert info to API calling convention
infop, err := convertDriverInfo(info)
if err != nil {
logrus.Error(err)
return err
}
err = expandSandboxSize(&infop, layerId, size)
if err != nil {
err = makeErrorf(err, title, "layerId=%s size=%d", layerId, size)
logrus.Error(err)
return err
}
logrus.Debugf(title+"- succeeded layerId=%s size=%d", layerId, size)
return nil
}

View File

@ -1,156 +0,0 @@
package hcsshim
import (
"io"
"io/ioutil"
"os"
"syscall"
"github.com/Microsoft/go-winio"
"github.com/sirupsen/logrus"
)
// ExportLayer will create a folder at exportFolderPath and fill that folder with
// the transport format version of the layer identified by layerId. This transport
// format includes any metadata required for later importing the layer (using
// ImportLayer), and requires the full list of parent layer paths in order to
// perform the export.
func ExportLayer(info DriverInfo, layerId string, exportFolderPath string, parentLayerPaths []string) error {
title := "hcsshim::ExportLayer "
logrus.Debugf(title+"flavour %d layerId %s folder %s", info.Flavour, layerId, exportFolderPath)
// Generate layer descriptors
layers, err := layerPathsToDescriptors(parentLayerPaths)
if err != nil {
return err
}
// Convert info to API calling convention
infop, err := convertDriverInfo(info)
if err != nil {
logrus.Error(err)
return err
}
err = exportLayer(&infop, layerId, exportFolderPath, layers)
if err != nil {
err = makeErrorf(err, title, "layerId=%s flavour=%d folder=%s", layerId, info.Flavour, exportFolderPath)
logrus.Error(err)
return err
}
logrus.Debugf(title+"succeeded flavour=%d layerId=%s folder=%s", info.Flavour, layerId, exportFolderPath)
return nil
}
type LayerReader interface {
Next() (string, int64, *winio.FileBasicInfo, error)
Read(b []byte) (int, error)
Close() error
}
// FilterLayerReader provides an interface for extracting the contents of an on-disk layer.
type FilterLayerReader struct {
context uintptr
}
// Next reads the next available file from a layer, ensuring that parent directories are always read
// before child files and directories.
//
// Next returns the file's relative path, size, and basic file metadata. Read() should be used to
// extract a Win32 backup stream with the remainder of the metadata and the data.
func (r *FilterLayerReader) Next() (string, int64, *winio.FileBasicInfo, error) {
var fileNamep *uint16
fileInfo := &winio.FileBasicInfo{}
var deleted uint32
var fileSize int64
err := exportLayerNext(r.context, &fileNamep, fileInfo, &fileSize, &deleted)
if err != nil {
if err == syscall.ERROR_NO_MORE_FILES {
err = io.EOF
} else {
err = makeError(err, "ExportLayerNext", "")
}
return "", 0, nil, err
}
fileName := convertAndFreeCoTaskMemString(fileNamep)
if deleted != 0 {
fileInfo = nil
}
if fileName[0] == '\\' {
fileName = fileName[1:]
}
return fileName, fileSize, fileInfo, nil
}
// Read reads from the current file's Win32 backup stream.
func (r *FilterLayerReader) Read(b []byte) (int, error) {
var bytesRead uint32
err := exportLayerRead(r.context, b, &bytesRead)
if err != nil {
return 0, makeError(err, "ExportLayerRead", "")
}
if bytesRead == 0 {
return 0, io.EOF
}
return int(bytesRead), nil
}
// Close frees resources associated with the layer reader. It will return an
// error if there was an error while reading the layer or of the layer was not
// completely read.
func (r *FilterLayerReader) Close() (err error) {
if r.context != 0 {
err = exportLayerEnd(r.context)
if err != nil {
err = makeError(err, "ExportLayerEnd", "")
}
r.context = 0
}
return
}
// NewLayerReader returns a new layer reader for reading the contents of an on-disk layer.
// The caller must have taken the SeBackupPrivilege privilege
// to call this and any methods on the resulting LayerReader.
func NewLayerReader(info DriverInfo, layerID string, parentLayerPaths []string) (LayerReader, error) {
if procExportLayerBegin.Find() != nil {
// The new layer reader is not available on this Windows build. Fall back to the
// legacy export code path.
path, err := ioutil.TempDir("", "hcs")
if err != nil {
return nil, err
}
err = ExportLayer(info, layerID, path, parentLayerPaths)
if err != nil {
os.RemoveAll(path)
return nil, err
}
return &legacyLayerReaderWrapper{newLegacyLayerReader(path)}, nil
}
layers, err := layerPathsToDescriptors(parentLayerPaths)
if err != nil {
return nil, err
}
infop, err := convertDriverInfo(info)
if err != nil {
return nil, err
}
r := &FilterLayerReader{}
err = exportLayerBegin(&infop, layerID, layers, &r.context)
if err != nil {
return nil, makeError(err, "ExportLayerBegin", "")
}
return r, err
}
type legacyLayerReaderWrapper struct {
*legacyLayerReader
}
func (r *legacyLayerReaderWrapper) Close() error {
err := r.legacyLayerReader.Close()
os.RemoveAll(r.root)
return err
}

View File

@ -0,0 +1,12 @@
# Requirements so far:
# dockerd running
# - image microsoft/nanoserver (matching host base image) docker load -i c:\baseimages\nanoserver.tar
# - image alpine (linux) docker pull --platform=linux alpine
# TODO: Add this a parameter for debugging. ie "functional-tests -debug=$true"
#$env:HCSSHIM_FUNCTIONAL_TESTS_DEBUG="yes please"
#pushd uvm
go test -v -tags "functional uvmcreate uvmscratch uvmscsi uvmvpmem uvmvsmb uvmp9" ./...
#popd

View File

@ -1,55 +0,0 @@
package hcsshim
import (
"syscall"
"github.com/sirupsen/logrus"
)
// GetLayerMountPath will look for a mounted layer with the given id and return
// the path at which that layer can be accessed. This path may be a volume path
// if the layer is a mounted read-write layer, otherwise it is expected to be the
// folder path at which the layer is stored.
func GetLayerMountPath(info DriverInfo, id string) (string, error) {
title := "hcsshim::GetLayerMountPath "
logrus.Debugf(title+"Flavour %d ID %s", info.Flavour, id)
// Convert info to API calling convention
infop, err := convertDriverInfo(info)
if err != nil {
logrus.Error(err)
return "", err
}
var mountPathLength uintptr
mountPathLength = 0
// Call the procedure itself.
logrus.Debugf("Calling proc (1)")
err = getLayerMountPath(&infop, id, &mountPathLength, nil)
if err != nil {
err = makeErrorf(err, title, "(first call) id=%s flavour=%d", id, info.Flavour)
logrus.Error(err)
return "", err
}
// Allocate a mount path of the returned length.
if mountPathLength == 0 {
return "", nil
}
mountPathp := make([]uint16, mountPathLength)
mountPathp[0] = 0
// Call the procedure again
logrus.Debugf("Calling proc (2)")
err = getLayerMountPath(&infop, id, &mountPathLength, &mountPathp[0])
if err != nil {
err = makeErrorf(err, title, "(second call) id=%s flavour=%d", id, info.Flavour)
logrus.Error(err)
return "", err
}
path := syscall.UTF16ToString(mountPathp[0:])
logrus.Debugf(title+"succeeded flavour=%d id=%s path=%s", info.Flavour, id, path)
return path, nil
}

View File

@ -1,22 +0,0 @@
package hcsshim
import "github.com/sirupsen/logrus"
// GetSharedBaseImages will enumerate the images stored in the common central
// image store and return descriptive info about those images for the purpose
// of registering them with the graphdriver, graph, and tagstore.
func GetSharedBaseImages() (imageData string, err error) {
title := "hcsshim::GetSharedBaseImages "
logrus.Debugf("Calling proc")
var buffer *uint16
err = getBaseImages(&buffer)
if err != nil {
err = makeError(err, title, "")
logrus.Error(err)
return
}
imageData = convertAndFreeCoTaskMemString(buffer)
logrus.Debugf(title+" - succeeded output=%s", imageData)
return
}

View File

@ -1,19 +0,0 @@
package hcsshim
import (
"crypto/sha1"
"fmt"
)
type GUID [16]byte
func NewGUID(source string) *GUID {
h := sha1.Sum([]byte(source))
var g GUID
copy(g[0:], h[0:16])
return &g
}
func (g *GUID) ToString() string {
return fmt.Sprintf("%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x-%02x", g[3], g[2], g[1], g[0], g[5], g[4], g[7], g[6], g[8:10], g[10:])
}

48
vendor/github.com/Microsoft/hcsshim/hcn/BUILD generated vendored Normal file
View File

@ -0,0 +1,48 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = [
"hcn.go",
"hcnendpoint.go",
"hcnerrors.go",
"hcnglobals.go",
"hcnloadbalancer.go",
"hcnnamespace.go",
"hcnnetwork.go",
"hcnpolicy.go",
"hcnsupport.go",
"zsyscall_windows.go",
],
importmap = "k8s.io/kubernetes/vendor/github.com/Microsoft/hcsshim/hcn",
importpath = "github.com/Microsoft/hcsshim/hcn",
visibility = ["//visibility:public"],
deps = [
"//vendor/github.com/Microsoft/hcsshim/internal/cni:go_default_library",
"//vendor/github.com/Microsoft/hcsshim/internal/guid:go_default_library",
"//vendor/github.com/Microsoft/hcsshim/internal/hcserror:go_default_library",
"//vendor/github.com/Microsoft/hcsshim/internal/interop:go_default_library",
"//vendor/github.com/Microsoft/hcsshim/internal/regstate:go_default_library",
"//vendor/github.com/Microsoft/hcsshim/internal/runhcs:go_default_library",
"//vendor/github.com/sirupsen/logrus:go_default_library",
] + select({
"@io_bazel_rules_go//go/platform:windows": [
"//vendor/golang.org/x/sys/windows:go_default_library",
],
"//conditions:default": [],
}),
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

168
vendor/github.com/Microsoft/hcsshim/hcn/hcn.go generated vendored Normal file
View File

@ -0,0 +1,168 @@
// Package hcn is a shim for the Host Compute Networking (HCN) service, which manages networking for Windows Server
// containers and Hyper-V containers. Previous to RS5, HCN was referred to as Host Networking Service (HNS).
package hcn
import (
"encoding/json"
"fmt"
"syscall"
"github.com/Microsoft/hcsshim/internal/guid"
)
//go:generate go run ../mksyscall_windows.go -output zsyscall_windows.go hcn.go
/// HNS V1 API
//sys SetCurrentThreadCompartmentId(compartmentId uint32) (hr error) = iphlpapi.SetCurrentThreadCompartmentId
//sys _hnsCall(method string, path string, object string, response **uint16) (hr error) = vmcompute.HNSCall?
/// HCN V2 API
// Network
//sys hcnEnumerateNetworks(query string, networks **uint16, result **uint16) (hr error) = computenetwork.HcnEnumerateNetworks?
//sys hcnCreateNetwork(id *_guid, settings string, network *hcnNetwork, result **uint16) (hr error) = computenetwork.HcnCreateNetwork?
//sys hcnOpenNetwork(id *_guid, network *hcnNetwork, result **uint16) (hr error) = computenetwork.HcnOpenNetwork?
//sys hcnModifyNetwork(network hcnNetwork, settings string, result **uint16) (hr error) = computenetwork.HcnModifyNetwork?
//sys hcnQueryNetworkProperties(network hcnNetwork, query string, properties **uint16, result **uint16) (hr error) = computenetwork.HcnQueryNetworkProperties?
//sys hcnDeleteNetwork(id *_guid, result **uint16) (hr error) = computenetwork.HcnDeleteNetwork?
//sys hcnCloseNetwork(network hcnNetwork) (hr error) = computenetwork.HcnCloseNetwork?
// Endpoint
//sys hcnEnumerateEndpoints(query string, endpoints **uint16, result **uint16) (hr error) = computenetwork.HcnEnumerateEndpoints?
//sys hcnCreateEndpoint(network hcnNetwork, id *_guid, settings string, endpoint *hcnEndpoint, result **uint16) (hr error) = computenetwork.HcnCreateEndpoint?
//sys hcnOpenEndpoint(id *_guid, endpoint *hcnEndpoint, result **uint16) (hr error) = computenetwork.HcnOpenEndpoint?
//sys hcnModifyEndpoint(endpoint hcnEndpoint, settings string, result **uint16) (hr error) = computenetwork.HcnModifyEndpoint?
//sys hcnQueryEndpointProperties(endpoint hcnEndpoint, query string, properties **uint16, result **uint16) (hr error) = computenetwork.HcnQueryEndpointProperties?
//sys hcnDeleteEndpoint(id *_guid, result **uint16) (hr error) = computenetwork.HcnDeleteEndpoint?
//sys hcnCloseEndpoint(endpoint hcnEndpoint) (hr error) = computenetwork.HcnCloseEndpoint?
// Namespace
//sys hcnEnumerateNamespaces(query string, namespaces **uint16, result **uint16) (hr error) = computenetwork.HcnEnumerateNamespaces?
//sys hcnCreateNamespace(id *_guid, settings string, namespace *hcnNamespace, result **uint16) (hr error) = computenetwork.HcnCreateNamespace?
//sys hcnOpenNamespace(id *_guid, namespace *hcnNamespace, result **uint16) (hr error) = computenetwork.HcnOpenNamespace?
//sys hcnModifyNamespace(namespace hcnNamespace, settings string, result **uint16) (hr error) = computenetwork.HcnModifyNamespace?
//sys hcnQueryNamespaceProperties(namespace hcnNamespace, query string, properties **uint16, result **uint16) (hr error) = computenetwork.HcnQueryNamespaceProperties?
//sys hcnDeleteNamespace(id *_guid, result **uint16) (hr error) = computenetwork.HcnDeleteNamespace?
//sys hcnCloseNamespace(namespace hcnNamespace) (hr error) = computenetwork.HcnCloseNamespace?
// LoadBalancer
//sys hcnEnumerateLoadBalancers(query string, loadBalancers **uint16, result **uint16) (hr error) = computenetwork.HcnEnumerateLoadBalancers?
//sys hcnCreateLoadBalancer(id *_guid, settings string, loadBalancer *hcnLoadBalancer, result **uint16) (hr error) = computenetwork.HcnCreateLoadBalancer?
//sys hcnOpenLoadBalancer(id *_guid, loadBalancer *hcnLoadBalancer, result **uint16) (hr error) = computenetwork.HcnOpenLoadBalancer?
//sys hcnModifyLoadBalancer(loadBalancer hcnLoadBalancer, settings string, result **uint16) (hr error) = computenetwork.HcnModifyLoadBalancer?
//sys hcnQueryLoadBalancerProperties(loadBalancer hcnLoadBalancer, query string, properties **uint16, result **uint16) (hr error) = computenetwork.HcnQueryLoadBalancerProperties?
//sys hcnDeleteLoadBalancer(id *_guid, result **uint16) (hr error) = computenetwork.HcnDeleteLoadBalancer?
//sys hcnCloseLoadBalancer(loadBalancer hcnLoadBalancer) (hr error) = computenetwork.HcnCloseLoadBalancer?
// Service
//sys hcnOpenService(service *hcnService, result **uint16) (hr error) = computenetwork.HcnOpenService?
//sys hcnRegisterServiceCallback(service hcnService, callback int32, context int32, callbackHandle *hcnCallbackHandle) (hr error) = computenetwork.HcnRegisterServiceCallback?
//sys hcnUnregisterServiceCallback(callbackHandle hcnCallbackHandle) (hr error) = computenetwork.HcnUnregisterServiceCallback?
//sys hcnCloseService(service hcnService) (hr error) = computenetwork.HcnCloseService?
type _guid = guid.GUID
type hcnNetwork syscall.Handle
type hcnEndpoint syscall.Handle
type hcnNamespace syscall.Handle
type hcnLoadBalancer syscall.Handle
type hcnService syscall.Handle
type hcnCallbackHandle syscall.Handle
// SchemaVersion for HCN Objects/Queries.
type SchemaVersion = Version // hcnglobals.go
// HostComputeQueryFlags are passed in to a HostComputeQuery to determine which
// properties of an object are returned.
type HostComputeQueryFlags uint32
var (
// HostComputeQueryFlagsNone returns an object with the standard properties.
HostComputeQueryFlagsNone HostComputeQueryFlags
// HostComputeQueryFlagsDetailed returns an object with all properties.
HostComputeQueryFlagsDetailed HostComputeQueryFlags = 1
)
// HostComputeQuery is the format for HCN queries.
type HostComputeQuery struct {
SchemaVersion SchemaVersion `json:""`
Flags HostComputeQueryFlags `json:",omitempty"`
Filter string `json:",omitempty"`
}
// defaultQuery generates HCN Query.
// Passed into get/enumerate calls to filter results.
func defaultQuery() HostComputeQuery {
query := HostComputeQuery{
SchemaVersion: SchemaVersion{
Major: 2,
Minor: 0,
},
Flags: HostComputeQueryFlagsNone,
}
return query
}
func defaultQueryJson() string {
query := defaultQuery()
queryJson, err := json.Marshal(query)
if err != nil {
return ""
}
return string(queryJson)
}
// PlatformDoesNotSupportError happens when users are attempting to use a newer shim on an older OS
func platformDoesNotSupportError(featureName string) error {
return fmt.Errorf("Platform does not support feature %s", featureName)
}
// V2ApiSupported returns an error if the HCN version does not support the V2 Apis.
func V2ApiSupported() error {
supported := GetSupportedFeatures()
if supported.Api.V2 {
return nil
}
return platformDoesNotSupportError("V2 Api/Schema")
}
func V2SchemaVersion() SchemaVersion {
return SchemaVersion{
Major: 2,
Minor: 0,
}
}
// RemoteSubnetSupported returns an error if the HCN version does not support Remote Subnet policies.
func RemoteSubnetSupported() error {
supported := GetSupportedFeatures()
if supported.RemoteSubnet {
return nil
}
return platformDoesNotSupportError("Remote Subnet")
}
// DSRSupported returns an error if the HCN version does not support Direct Server Return.
func DSRSupported() error {
supported := GetSupportedFeatures()
if supported.DSR {
return nil
}
return platformDoesNotSupportError("Direct Server Return (DSR)")
}
// RequestType are the different operations performed to settings.
// Used to update the settings of Endpoint/Namespace objects.
type RequestType string
var (
// RequestTypeAdd adds the provided settings object.
RequestTypeAdd RequestType = "Add"
// RequestTypeRemove removes the provided settings object.
RequestTypeRemove RequestType = "Remove"
// RequestTypeUpdate replaces settings with the ones provided.
RequestTypeUpdate RequestType = "Update"
// RequestTypeRefresh refreshes the settings provided.
RequestTypeRefresh RequestType = "Refresh"
)

366
vendor/github.com/Microsoft/hcsshim/hcn/hcnendpoint.go generated vendored Normal file
View File

@ -0,0 +1,366 @@
package hcn
import (
"encoding/json"
"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)
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)
}

95
vendor/github.com/Microsoft/hcsshim/hcn/hcnerrors.go generated vendored Normal file
View File

@ -0,0 +1,95 @@
// Package hcn is a shim for the Host Compute Networking (HCN) service, which manages networking for Windows Server
// containers and Hyper-V containers. Previous to RS5, HCN was referred to as Host Networking Service (HNS).
package hcn
import (
"fmt"
"github.com/Microsoft/hcsshim/internal/hcserror"
"github.com/Microsoft/hcsshim/internal/interop"
"github.com/sirupsen/logrus"
)
func checkForErrors(methodName string, hr error, resultBuffer *uint16) error {
errorFound := false
if hr != nil {
errorFound = true
}
result := ""
if resultBuffer != nil {
result = interop.ConvertAndFreeCoTaskMemString(resultBuffer)
if result != "" {
errorFound = true
}
}
if errorFound {
returnError := hcserror.New(hr, methodName, result)
logrus.Debugf(returnError.Error()) // HCN errors logged for debugging.
return returnError
}
return nil
}
// NetworkNotFoundError results from a failed seach for a network by Id or Name
type NetworkNotFoundError struct {
NetworkName string
NetworkID string
}
func (e NetworkNotFoundError) Error() string {
if e.NetworkName == "" {
return fmt.Sprintf("Network Name %s not found", e.NetworkName)
}
return fmt.Sprintf("Network Id %s not found", e.NetworkID)
}
// EndpointNotFoundError results from a failed seach for an endpoint by Id or Name
type EndpointNotFoundError struct {
EndpointName string
EndpointID string
}
func (e EndpointNotFoundError) Error() string {
if e.EndpointName == "" {
return fmt.Sprintf("Endpoint Name %s not found", e.EndpointName)
}
return fmt.Sprintf("Endpoint Id %s not found", e.EndpointID)
}
// NamespaceNotFoundError results from a failed seach for a namsepace by Id
type NamespaceNotFoundError struct {
NamespaceID string
}
func (e NamespaceNotFoundError) Error() string {
return fmt.Sprintf("Namespace %s not found", e.NamespaceID)
}
// LoadBalancerNotFoundError results from a failed seach for a loadbalancer by Id
type LoadBalancerNotFoundError struct {
LoadBalancerId string
}
func (e LoadBalancerNotFoundError) Error() string {
return fmt.Sprintf("LoadBalancer %s not found", e.LoadBalancerId)
}
// IsNotFoundError returns a boolean indicating whether the error was caused by
// a resource not being found.
func IsNotFoundError(err error) bool {
switch err.(type) {
case NetworkNotFoundError:
return true
case EndpointNotFoundError:
return true
case NamespaceNotFoundError:
return true
case LoadBalancerNotFoundError:
return true
}
return false
}

85
vendor/github.com/Microsoft/hcsshim/hcn/hcnglobals.go generated vendored Normal file
View File

@ -0,0 +1,85 @@
package hcn
import (
"encoding/json"
"fmt"
"github.com/Microsoft/hcsshim/internal/hcserror"
"github.com/Microsoft/hcsshim/internal/interop"
"github.com/sirupsen/logrus"
)
// Globals are all global properties of the HCN Service.
type Globals struct {
Version Version `json:"Version"`
}
// Version is the HCN Service version.
type Version struct {
Major int `json:"Major"`
Minor int `json:"Minor"`
}
var (
// HNSVersion1803 added ACL functionality.
HNSVersion1803 = Version{Major: 7, Minor: 2}
// V2ApiSupport allows the use of V2 Api calls and V2 Schema.
V2ApiSupport = Version{Major: 9, Minor: 1}
// Remote Subnet allows for Remote Subnet policies on Overlay networks
RemoteSubnetVersion = Version{Major: 9, Minor: 2}
// HNS 10.2 allows for Direct Server Return for loadbalancing
DSRVersion = Version{Major: 10, Minor: 2}
)
// GetGlobals returns the global properties of the HCN Service.
func GetGlobals() (*Globals, error) {
var version Version
err := hnsCall("GET", "/globals/version", "", &version)
if err != nil {
return nil, err
}
globals := &Globals{
Version: version,
}
return globals, nil
}
type hnsResponse struct {
Success bool
Error string
Output json.RawMessage
}
func hnsCall(method, path, request string, returnResponse interface{}) error {
var responseBuffer *uint16
logrus.Debugf("[%s]=>[%s] Request : %s", method, path, request)
err := _hnsCall(method, path, request, &responseBuffer)
if err != nil {
return hcserror.New(err, "hnsCall ", "")
}
response := interop.ConvertAndFreeCoTaskMemString(responseBuffer)
hnsresponse := &hnsResponse{}
if err = json.Unmarshal([]byte(response), &hnsresponse); err != nil {
return err
}
if !hnsresponse.Success {
return fmt.Errorf("HNS failed with error : %s", hnsresponse.Error)
}
if len(hnsresponse.Output) == 0 {
return nil
}
logrus.Debugf("Network Response : %s", hnsresponse.Output)
err = json.Unmarshal(hnsresponse.Output, returnResponse)
if err != nil {
return err
}
return nil
}

View File

@ -0,0 +1,321 @@
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 uint32 `json:",omitempty"` // 0: None, 1: EnableILB, 2: LocalRoutedVip
}
// 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 uint32 `json:",omitempty"` // 0: None, 1: EnableDirectServerReturn
}
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, isILB bool, isDSR bool, sourceVIP string, frontendVIPs []string, protocol uint16, internalPort uint16, externalPort uint16) (*HostComputeLoadBalancer, error) {
logrus.Debugf("hcn::HostComputeLoadBalancer::AddLoadBalancer endpointId=%v, isILB=%v, sourceVIP=%s, frontendVIPs=%v, protocol=%v, internalPort=%v, externalPort=%v", endpoints, isILB, sourceVIP, frontendVIPs, protocol, internalPort, externalPort)
var portMappingFlags uint32
portMappingFlags = 0
if isILB {
portMappingFlags = 1
}
var lbFlags uint32
lbFlags = 0
if isDSR {
lbFlags = 1 // EnableDirectServerReturn
}
loadBalancer := &HostComputeLoadBalancer{
SourceVIP: sourceVIP,
PortMappings: []LoadBalancerPortMapping{
{
Protocol: uint32(protocol),
InternalPort: internalPort,
ExternalPort: externalPort,
Flags: portMappingFlags,
},
},
FrontendVIPs: frontendVIPs,
SchemaVersion: SchemaVersion{
Major: 2,
Minor: 0,
},
Flags: lbFlags,
}
for _, endpoint := range endpoints {
loadBalancer.HostComputeEndpoints = append(loadBalancer.HostComputeEndpoints, endpoint.Id)
}
return loadBalancer.Create()
}

424
vendor/github.com/Microsoft/hcsshim/hcn/hcnnamespace.go generated vendored Normal file
View File

@ -0,0 +1,424 @@
package hcn
import (
"encoding/json"
"os"
"syscall"
icni "github.com/Microsoft/hcsshim/internal/cni"
"github.com/Microsoft/hcsshim/internal/guid"
"github.com/Microsoft/hcsshim/internal/interop"
"github.com/Microsoft/hcsshim/internal/regstate"
"github.com/Microsoft/hcsshim/internal/runhcs"
"github.com/sirupsen/logrus"
)
// NamespaceResourceEndpoint represents an Endpoint attached to a Namespace.
type NamespaceResourceEndpoint struct {
Id string `json:"ID,"`
}
// NamespaceResourceContainer represents a Container attached to a Namespace.
type NamespaceResourceContainer struct {
Id string `json:"ID,"`
}
// NamespaceResourceType determines whether the Namespace resource is a Container or Endpoint.
type NamespaceResourceType string
var (
// NamespaceResourceTypeContainer are contianers associated with a Namespace.
NamespaceResourceTypeContainer NamespaceResourceType = "Container"
// NamespaceResourceTypeEndpoint are endpoints associated with a Namespace.
NamespaceResourceTypeEndpoint NamespaceResourceType = "Endpoint"
)
// NamespaceResource is associated with a namespace
type NamespaceResource struct {
Type NamespaceResourceType `json:","` // Container, Endpoint
Data json.RawMessage `json:","`
}
// NamespaceType determines whether the Namespace is for a Host or Guest
type NamespaceType string
var (
// NamespaceTypeHost are host namespaces.
NamespaceTypeHost NamespaceType = "Host"
// NamespaceTypeHostDefault are host namespaces in the default compartment.
NamespaceTypeHostDefault NamespaceType = "HostDefault"
// NamespaceTypeGuest are guest namespaces.
NamespaceTypeGuest NamespaceType = "Guest"
// NamespaceTypeGuestDefault are guest namespaces in the default compartment.
NamespaceTypeGuestDefault NamespaceType = "GuestDefault"
)
// HostComputeNamespace represents a namespace (AKA compartment) in
type HostComputeNamespace struct {
Id string `json:"ID,omitempty"`
NamespaceId uint32 `json:",omitempty"`
Type NamespaceType `json:",omitempty"` // Host, HostDefault, Guest, GuestDefault
Resources []NamespaceResource `json:",omitempty"`
SchemaVersion SchemaVersion `json:",omitempty"`
}
// ModifyNamespaceSettingRequest is the structure used to send request to modify a namespace.
// Used to Add/Remove an endpoints and containers to/from a namespace.
type ModifyNamespaceSettingRequest struct {
ResourceType NamespaceResourceType `json:",omitempty"` // Container, Endpoint
RequestType RequestType `json:",omitempty"` // Add, Remove, Update, Refresh
Settings json.RawMessage `json:",omitempty"`
}
func getNamespace(namespaceGuid guid.GUID, query string) (*HostComputeNamespace, error) {
// Open namespace.
var (
namespaceHandle hcnNamespace
resultBuffer *uint16
propertiesBuffer *uint16
)
hr := hcnOpenNamespace(&namespaceGuid, &namespaceHandle, &resultBuffer)
if err := checkForErrors("hcnOpenNamespace", hr, resultBuffer); err != nil {
return nil, err
}
// Query namespace.
hr = hcnQueryNamespaceProperties(namespaceHandle, query, &propertiesBuffer, &resultBuffer)
if err := checkForErrors("hcnQueryNamespaceProperties", hr, resultBuffer); err != nil {
return nil, err
}
properties := interop.ConvertAndFreeCoTaskMemString(propertiesBuffer)
// Close namespace.
hr = hcnCloseNamespace(namespaceHandle)
if err := checkForErrors("hcnCloseNamespace", hr, nil); err != nil {
return nil, err
}
// Convert output to HostComputeNamespace
var outputNamespace HostComputeNamespace
if err := json.Unmarshal([]byte(properties), &outputNamespace); err != nil {
return nil, err
}
return &outputNamespace, nil
}
func enumerateNamespaces(query string) ([]HostComputeNamespace, error) {
// Enumerate all Namespace Guids
var (
resultBuffer *uint16
namespaceBuffer *uint16
)
hr := hcnEnumerateNamespaces(query, &namespaceBuffer, &resultBuffer)
if err := checkForErrors("hcnEnumerateNamespaces", hr, resultBuffer); err != nil {
return nil, err
}
namespaces := interop.ConvertAndFreeCoTaskMemString(namespaceBuffer)
var namespaceIds []guid.GUID
if err := json.Unmarshal([]byte(namespaces), &namespaceIds); err != nil {
return nil, err
}
var outputNamespaces []HostComputeNamespace
for _, namespaceGuid := range namespaceIds {
namespace, err := getNamespace(namespaceGuid, query)
if err != nil {
return nil, err
}
outputNamespaces = append(outputNamespaces, *namespace)
}
return outputNamespaces, nil
}
func createNamespace(settings string) (*HostComputeNamespace, error) {
// Create new namespace.
var (
namespaceHandle hcnNamespace
resultBuffer *uint16
propertiesBuffer *uint16
)
namespaceGuid := guid.GUID{}
hr := hcnCreateNamespace(&namespaceGuid, settings, &namespaceHandle, &resultBuffer)
if err := checkForErrors("hcnCreateNamespace", hr, resultBuffer); err != nil {
return nil, err
}
// Query namespace.
hcnQuery := defaultQuery()
query, err := json.Marshal(hcnQuery)
if err != nil {
return nil, err
}
hr = hcnQueryNamespaceProperties(namespaceHandle, string(query), &propertiesBuffer, &resultBuffer)
if err := checkForErrors("hcnQueryNamespaceProperties", hr, resultBuffer); err != nil {
return nil, err
}
properties := interop.ConvertAndFreeCoTaskMemString(propertiesBuffer)
// Close namespace.
hr = hcnCloseNamespace(namespaceHandle)
if err := checkForErrors("hcnCloseNamespace", hr, nil); err != nil {
return nil, err
}
// Convert output to HostComputeNamespace
var outputNamespace HostComputeNamespace
if err := json.Unmarshal([]byte(properties), &outputNamespace); err != nil {
return nil, err
}
return &outputNamespace, nil
}
func modifyNamespace(namespaceId string, settings string) (*HostComputeNamespace, error) {
namespaceGuid := guid.FromString(namespaceId)
// Open namespace.
var (
namespaceHandle hcnNamespace
resultBuffer *uint16
propertiesBuffer *uint16
)
hr := hcnOpenNamespace(&namespaceGuid, &namespaceHandle, &resultBuffer)
if err := checkForErrors("hcnOpenNamespace", hr, resultBuffer); err != nil {
return nil, err
}
// Modify namespace.
hr = hcnModifyNamespace(namespaceHandle, settings, &resultBuffer)
if err := checkForErrors("hcnModifyNamespace", hr, resultBuffer); err != nil {
return nil, err
}
// Query namespace.
hcnQuery := defaultQuery()
query, err := json.Marshal(hcnQuery)
if err != nil {
return nil, err
}
hr = hcnQueryNamespaceProperties(namespaceHandle, string(query), &propertiesBuffer, &resultBuffer)
if err := checkForErrors("hcnQueryNamespaceProperties", hr, resultBuffer); err != nil {
return nil, err
}
properties := interop.ConvertAndFreeCoTaskMemString(propertiesBuffer)
// Close namespace.
hr = hcnCloseNamespace(namespaceHandle)
if err := checkForErrors("hcnCloseNamespace", hr, nil); err != nil {
return nil, err
}
// Convert output to Namespace
var outputNamespace HostComputeNamespace
if err := json.Unmarshal([]byte(properties), &outputNamespace); err != nil {
return nil, err
}
return &outputNamespace, nil
}
func deleteNamespace(namespaceId string) error {
namespaceGuid := guid.FromString(namespaceId)
var resultBuffer *uint16
hr := hcnDeleteNamespace(&namespaceGuid, &resultBuffer)
if err := checkForErrors("hcnDeleteNamespace", hr, resultBuffer); err != nil {
return err
}
return nil
}
// ListNamespaces makes a call to list all available namespaces.
func ListNamespaces() ([]HostComputeNamespace, error) {
hcnQuery := defaultQuery()
namespaces, err := ListNamespacesQuery(hcnQuery)
if err != nil {
return nil, err
}
return namespaces, nil
}
// ListNamespacesQuery makes a call to query the list of available namespaces.
func ListNamespacesQuery(query HostComputeQuery) ([]HostComputeNamespace, error) {
queryJson, err := json.Marshal(query)
if err != nil {
return nil, err
}
namespaces, err := enumerateNamespaces(string(queryJson))
if err != nil {
return nil, err
}
return namespaces, nil
}
// GetNamespaceByID returns the Namespace specified by Id.
func GetNamespaceByID(namespaceId string) (*HostComputeNamespace, error) {
return getNamespace(guid.FromString(namespaceId), defaultQueryJson())
}
// GetNamespaceEndpointIds returns the endpoints of the Namespace specified by Id.
func GetNamespaceEndpointIds(namespaceId string) ([]string, error) {
namespace, err := GetNamespaceByID(namespaceId)
if err != nil {
return nil, err
}
var endpointsIds []string
for _, resource := range namespace.Resources {
if resource.Type == "Endpoint" {
var endpointResource NamespaceResourceEndpoint
if err := json.Unmarshal([]byte(resource.Data), &endpointResource); err != nil {
return nil, err
}
endpointsIds = append(endpointsIds, endpointResource.Id)
}
}
return endpointsIds, nil
}
// GetNamespaceContainerIds returns the containers of the Namespace specified by Id.
func GetNamespaceContainerIds(namespaceId string) ([]string, error) {
namespace, err := GetNamespaceByID(namespaceId)
if err != nil {
return nil, err
}
var containerIds []string
for _, resource := range namespace.Resources {
if resource.Type == "Container" {
var contaienrResource NamespaceResourceContainer
if err := json.Unmarshal([]byte(resource.Data), &contaienrResource); err != nil {
return nil, err
}
containerIds = append(containerIds, contaienrResource.Id)
}
}
return containerIds, nil
}
// NewNamespace creates a new Namespace object
func NewNamespace(nsType NamespaceType) *HostComputeNamespace {
return &HostComputeNamespace{
Type: nsType,
SchemaVersion: V2SchemaVersion(),
}
}
// Create Namespace.
func (namespace *HostComputeNamespace) Create() (*HostComputeNamespace, error) {
logrus.Debugf("hcn::HostComputeNamespace::Create id=%s", namespace.Id)
jsonString, err := json.Marshal(namespace)
if err != nil {
return nil, err
}
logrus.Debugf("hcn::HostComputeNamespace::Create JSON: %s", jsonString)
namespace, hcnErr := createNamespace(string(jsonString))
if hcnErr != nil {
return nil, hcnErr
}
return namespace, nil
}
// Delete Namespace.
func (namespace *HostComputeNamespace) Delete() error {
logrus.Debugf("hcn::HostComputeNamespace::Delete id=%s", namespace.Id)
if err := deleteNamespace(namespace.Id); err != nil {
return err
}
return nil
}
// Sync Namespace endpoints with the appropriate sandbox container holding the
// network namespace open. If no sandbox container is found for this namespace
// this method is determined to be a success and will not return an error in
// this case. If the sandbox container is found and a sync is initiated any
// failures will be returned via this method.
//
// This call initiates a sync between endpoints and the matching UtilityVM
// hosting those endpoints. It is safe to call for any `NamespaceType` but
// `NamespaceTypeGuest` is the only case when a sync will actually occur. For
// `NamespaceTypeHost` the process container will be automatically synchronized
// when the the endpoint is added via `AddNamespaceEndpoint`.
//
// Note: This method sync's both additions and removals of endpoints from a
// `NamespaceTypeGuest` namespace.
func (namespace *HostComputeNamespace) Sync() error {
logrus.WithField("id", namespace.Id).Debugf("hcs::HostComputeNamespace::Sync")
// We only attempt a sync for namespace guest.
if namespace.Type != NamespaceTypeGuest {
return nil
}
// Look in the registry for the key to map from namespace id to pod-id
cfg, err := icni.LoadPersistedNamespaceConfig(namespace.Id)
if err != nil {
if regstate.IsNotFoundError(err) {
return nil
}
return err
}
req := runhcs.VMRequest{
ID: cfg.ContainerID,
Op: runhcs.OpSyncNamespace,
}
shimPath := runhcs.VMPipePath(cfg.HostUniqueID)
if err := runhcs.IssueVMRequest(shimPath, &req); err != nil {
// The shim is likey gone. Simply ignore the sync as if it didn't exist.
if perr, ok := err.(*os.PathError); ok && perr.Err == syscall.ERROR_FILE_NOT_FOUND {
// Remove the reg key there is no point to try again
cfg.Remove()
return nil
}
f := map[string]interface{}{
"id": namespace.Id,
"container-id": cfg.ContainerID,
}
logrus.WithFields(f).
WithError(err).
Debugf("hcs::HostComputeNamespace::Sync failed to connect to shim pipe: '%s'", shimPath)
return err
}
return nil
}
// ModifyNamespaceSettings updates the Endpoints/Containers of a Namespace.
func ModifyNamespaceSettings(namespaceId string, request *ModifyNamespaceSettingRequest) error {
logrus.Debugf("hcn::HostComputeNamespace::ModifyNamespaceSettings id=%s", namespaceId)
namespaceSettings, err := json.Marshal(request)
if err != nil {
return err
}
_, err = modifyNamespace(namespaceId, string(namespaceSettings))
if err != nil {
return err
}
return nil
}
// AddNamespaceEndpoint adds an endpoint to a Namespace.
func AddNamespaceEndpoint(namespaceId string, endpointId string) error {
logrus.Debugf("hcn::HostComputeEndpoint::AddNamespaceEndpoint id=%s", endpointId)
mapA := map[string]string{"EndpointId": endpointId}
settingsJson, err := json.Marshal(mapA)
if err != nil {
return err
}
requestMessage := &ModifyNamespaceSettingRequest{
ResourceType: NamespaceResourceTypeEndpoint,
RequestType: RequestTypeAdd,
Settings: settingsJson,
}
return ModifyNamespaceSettings(namespaceId, requestMessage)
}
// RemoveNamespaceEndpoint removes an endpoint from a Namespace.
func RemoveNamespaceEndpoint(namespaceId string, endpointId string) error {
logrus.Debugf("hcn::HostComputeNamespace::RemoveNamespaceEndpoint id=%s", endpointId)
mapA := map[string]string{"EndpointId": endpointId}
settingsJson, err := json.Marshal(mapA)
if err != nil {
return err
}
requestMessage := &ModifyNamespaceSettingRequest{
ResourceType: NamespaceResourceTypeEndpoint,
RequestType: RequestTypeRemove,
Settings: settingsJson,
}
return ModifyNamespaceSettings(namespaceId, requestMessage)
}

409
vendor/github.com/Microsoft/hcsshim/hcn/hcnnetwork.go generated vendored Normal file
View File

@ -0,0 +1,409 @@
package hcn
import (
"encoding/json"
"github.com/Microsoft/hcsshim/internal/guid"
"github.com/Microsoft/hcsshim/internal/interop"
"github.com/sirupsen/logrus"
)
// Route is assoicated with a subnet.
type Route struct {
NextHop string `json:",omitempty"`
DestinationPrefix string `json:",omitempty"`
Metric uint16 `json:",omitempty"`
}
// Subnet is assoicated with a Ipam.
type Subnet struct {
IpAddressPrefix string `json:",omitempty"`
Policies []json.RawMessage `json:",omitempty"`
Routes []Route `json:",omitempty"`
}
// Ipam (Internet Protocol Addres Management) is assoicated with a network
// and represents the address space(s) of a network.
type Ipam struct {
Type string `json:",omitempty"` // Ex: Static, DHCP
Subnets []Subnet `json:",omitempty"`
}
// MacRange is associated with MacPool and respresents the start and end addresses.
type MacRange struct {
StartMacAddress string `json:",omitempty"`
EndMacAddress string `json:",omitempty"`
}
// MacPool is assoicated with a network and represents pool of MacRanges.
type MacPool struct {
Ranges []MacRange `json:",omitempty"`
}
// Dns (Domain Name System is associated with a network.
type Dns struct {
Domain string `json:",omitempty"`
Search []string `json:",omitempty"`
ServerList []string `json:",omitempty"`
Options []string `json:",omitempty"`
}
// NetworkType are various networks.
type NetworkType string
// NetworkType const
const (
NAT NetworkType = "NAT"
Transparent NetworkType = "Transparent"
L2Bridge NetworkType = "L2Bridge"
L2Tunnel NetworkType = "L2Tunnel"
ICS NetworkType = "ICS"
Private NetworkType = "Private"
Overlay NetworkType = "Overlay"
)
// HostComputeNetwork represents a network
type HostComputeNetwork struct {
Id string `json:"ID,omitempty"`
Name string `json:",omitempty"`
Type NetworkType `json:",omitempty"`
Policies []NetworkPolicy `json:",omitempty"`
MacPool MacPool `json:",omitempty"`
Dns Dns `json:",omitempty"`
Ipams []Ipam `json:",omitempty"`
Flags uint32 `json:",omitempty"` // 0: None
SchemaVersion SchemaVersion `json:",omitempty"`
}
// NetworkResourceType are the 3 different Network settings resources.
type NetworkResourceType string
var (
// NetworkResourceTypePolicy is for Network's policies. Ex: RemoteSubnet
NetworkResourceTypePolicy NetworkResourceType = "Policy"
// NetworkResourceTypeDNS is for Network's DNS settings.
NetworkResourceTypeDNS NetworkResourceType = "DNS"
// NetworkResourceTypeExtension is for Network's extension settings.
NetworkResourceTypeExtension NetworkResourceType = "Extension"
)
// ModifyNetworkSettingRequest is the structure used to send request to modify an network.
// Used to update DNS/extension/policy on an network.
type ModifyNetworkSettingRequest struct {
ResourceType NetworkResourceType `json:",omitempty"` // Policy, DNS, Extension
RequestType RequestType `json:",omitempty"` // Add, Remove, Update, Refresh
Settings json.RawMessage `json:",omitempty"`
}
type PolicyNetworkRequest struct {
Policies []NetworkPolicy `json:",omitempty"`
}
func getNetwork(networkGuid guid.GUID, query string) (*HostComputeNetwork, error) {
// Open network.
var (
networkHandle hcnNetwork
resultBuffer *uint16
propertiesBuffer *uint16
)
hr := hcnOpenNetwork(&networkGuid, &networkHandle, &resultBuffer)
if err := checkForErrors("hcnOpenNetwork", hr, resultBuffer); err != nil {
return nil, err
}
// Query network.
hr = hcnQueryNetworkProperties(networkHandle, query, &propertiesBuffer, &resultBuffer)
if err := checkForErrors("hcnQueryNetworkProperties", hr, resultBuffer); err != nil {
return nil, err
}
properties := interop.ConvertAndFreeCoTaskMemString(propertiesBuffer)
// Close network.
hr = hcnCloseNetwork(networkHandle)
if err := checkForErrors("hcnCloseNetwork", hr, nil); err != nil {
return nil, err
}
// Convert output to HostComputeNetwork
var outputNetwork HostComputeNetwork
if err := json.Unmarshal([]byte(properties), &outputNetwork); err != nil {
return nil, err
}
return &outputNetwork, nil
}
func enumerateNetworks(query string) ([]HostComputeNetwork, error) {
// Enumerate all Network Guids
var (
resultBuffer *uint16
networkBuffer *uint16
)
hr := hcnEnumerateNetworks(query, &networkBuffer, &resultBuffer)
if err := checkForErrors("hcnEnumerateNetworks", hr, resultBuffer); err != nil {
return nil, err
}
networks := interop.ConvertAndFreeCoTaskMemString(networkBuffer)
var networkIds []guid.GUID
if err := json.Unmarshal([]byte(networks), &networkIds); err != nil {
return nil, err
}
var outputNetworks []HostComputeNetwork
for _, networkGuid := range networkIds {
network, err := getNetwork(networkGuid, query)
if err != nil {
return nil, err
}
outputNetworks = append(outputNetworks, *network)
}
return outputNetworks, nil
}
func createNetwork(settings string) (*HostComputeNetwork, error) {
// Create new network.
var (
networkHandle hcnNetwork
resultBuffer *uint16
propertiesBuffer *uint16
)
networkGuid := guid.GUID{}
hr := hcnCreateNetwork(&networkGuid, settings, &networkHandle, &resultBuffer)
if err := checkForErrors("hcnCreateNetwork", hr, resultBuffer); err != nil {
return nil, err
}
// Query network.
hcnQuery := defaultQuery()
query, err := json.Marshal(hcnQuery)
if err != nil {
return nil, err
}
hr = hcnQueryNetworkProperties(networkHandle, string(query), &propertiesBuffer, &resultBuffer)
if err := checkForErrors("hcnQueryNetworkProperties", hr, resultBuffer); err != nil {
return nil, err
}
properties := interop.ConvertAndFreeCoTaskMemString(propertiesBuffer)
// Close network.
hr = hcnCloseNetwork(networkHandle)
if err := checkForErrors("hcnCloseNetwork", hr, nil); err != nil {
return nil, err
}
// Convert output to HostComputeNetwork
var outputNetwork HostComputeNetwork
if err := json.Unmarshal([]byte(properties), &outputNetwork); err != nil {
return nil, err
}
return &outputNetwork, nil
}
func modifyNetwork(networkId string, settings string) (*HostComputeNetwork, error) {
networkGuid := guid.FromString(networkId)
// Open Network
var (
networkHandle hcnNetwork
resultBuffer *uint16
propertiesBuffer *uint16
)
hr := hcnOpenNetwork(&networkGuid, &networkHandle, &resultBuffer)
if err := checkForErrors("hcnOpenNetwork", hr, resultBuffer); err != nil {
return nil, err
}
// Modify Network
hr = hcnModifyNetwork(networkHandle, settings, &resultBuffer)
if err := checkForErrors("hcnModifyNetwork", hr, resultBuffer); err != nil {
return nil, err
}
// Query network.
hcnQuery := defaultQuery()
query, err := json.Marshal(hcnQuery)
if err != nil {
return nil, err
}
hr = hcnQueryNetworkProperties(networkHandle, string(query), &propertiesBuffer, &resultBuffer)
if err := checkForErrors("hcnQueryNetworkProperties", hr, resultBuffer); err != nil {
return nil, err
}
properties := interop.ConvertAndFreeCoTaskMemString(propertiesBuffer)
// Close network.
hr = hcnCloseNetwork(networkHandle)
if err := checkForErrors("hcnCloseNetwork", hr, nil); err != nil {
return nil, err
}
// Convert output to HostComputeNetwork
var outputNetwork HostComputeNetwork
if err := json.Unmarshal([]byte(properties), &outputNetwork); err != nil {
return nil, err
}
return &outputNetwork, nil
}
func deleteNetwork(networkId string) error {
networkGuid := guid.FromString(networkId)
var resultBuffer *uint16
hr := hcnDeleteNetwork(&networkGuid, &resultBuffer)
if err := checkForErrors("hcnDeleteNetwork", hr, resultBuffer); err != nil {
return err
}
return nil
}
// ListNetworks makes a call to list all available networks.
func ListNetworks() ([]HostComputeNetwork, error) {
hcnQuery := defaultQuery()
networks, err := ListNetworksQuery(hcnQuery)
if err != nil {
return nil, err
}
return networks, nil
}
// ListNetworksQuery makes a call to query the list of available networks.
func ListNetworksQuery(query HostComputeQuery) ([]HostComputeNetwork, error) {
queryJson, err := json.Marshal(query)
if err != nil {
return nil, err
}
networks, err := enumerateNetworks(string(queryJson))
if err != nil {
return nil, err
}
return networks, nil
}
// GetNetworkByID returns the network specified by Id.
func GetNetworkByID(networkID string) (*HostComputeNetwork, error) {
hcnQuery := defaultQuery()
mapA := map[string]string{"ID": networkID}
filter, err := json.Marshal(mapA)
if err != nil {
return nil, err
}
hcnQuery.Filter = string(filter)
networks, err := ListNetworksQuery(hcnQuery)
if err != nil {
return nil, err
}
if len(networks) == 0 {
return nil, NetworkNotFoundError{NetworkID: networkID}
}
return &networks[0], err
}
// GetNetworkByName returns the network specified by Name.
func GetNetworkByName(networkName string) (*HostComputeNetwork, error) {
hcnQuery := defaultQuery()
mapA := map[string]string{"Name": networkName}
filter, err := json.Marshal(mapA)
if err != nil {
return nil, err
}
hcnQuery.Filter = string(filter)
networks, err := ListNetworksQuery(hcnQuery)
if err != nil {
return nil, err
}
if len(networks) == 0 {
return nil, NetworkNotFoundError{NetworkName: networkName}
}
return &networks[0], err
}
// Create Network.
func (network *HostComputeNetwork) Create() (*HostComputeNetwork, error) {
logrus.Debugf("hcn::HostComputeNetwork::Create id=%s", network.Id)
jsonString, err := json.Marshal(network)
if err != nil {
return nil, err
}
logrus.Debugf("hcn::HostComputeNetwork::Create JSON: %s", jsonString)
network, hcnErr := createNetwork(string(jsonString))
if hcnErr != nil {
return nil, hcnErr
}
return network, nil
}
// Delete Network.
func (network *HostComputeNetwork) Delete() error {
logrus.Debugf("hcn::HostComputeNetwork::Delete id=%s", network.Id)
if err := deleteNetwork(network.Id); err != nil {
return err
}
return nil
}
// ModifyNetworkSettings updates the Policy for a network.
func (network *HostComputeNetwork) ModifyNetworkSettings(request *ModifyNetworkSettingRequest) error {
logrus.Debugf("hcn::HostComputeNetwork::ModifyNetworkSettings id=%s", network.Id)
networkSettingsRequest, err := json.Marshal(request)
if err != nil {
return err
}
_, err = modifyNetwork(network.Id, string(networkSettingsRequest))
if err != nil {
return err
}
return nil
}
// AddPolicy applies a Policy (ex: RemoteSubnet) on the Network.
func (network *HostComputeNetwork) AddPolicy(networkPolicy PolicyNetworkRequest) error {
logrus.Debugf("hcn::HostComputeNetwork::AddPolicy id=%s", network.Id)
settingsJson, err := json.Marshal(networkPolicy)
if err != nil {
return err
}
requestMessage := &ModifyNetworkSettingRequest{
ResourceType: NetworkResourceTypePolicy,
RequestType: RequestTypeAdd,
Settings: settingsJson,
}
return network.ModifyNetworkSettings(requestMessage)
}
// RemovePolicy removes a Policy (ex: RemoteSubnet) from the Network.
func (network *HostComputeNetwork) RemovePolicy(networkPolicy PolicyNetworkRequest) error {
logrus.Debugf("hcn::HostComputeNetwork::RemovePolicy id=%s", network.Id)
settingsJson, err := json.Marshal(networkPolicy)
if err != nil {
return err
}
requestMessage := &ModifyNetworkSettingRequest{
ResourceType: NetworkResourceTypePolicy,
RequestType: RequestTypeRemove,
Settings: settingsJson,
}
return network.ModifyNetworkSettings(requestMessage)
}
// CreateEndpoint creates an endpoint on the Network.
func (network *HostComputeNetwork) CreateEndpoint(endpoint *HostComputeEndpoint) (*HostComputeEndpoint, error) {
isRemote := endpoint.Flags&EndpointFlagsRemoteEndpoint != 0
logrus.Debugf("hcn::HostComputeNetwork::CreatEndpoint, networkId=%s remote=%t", network.Id, isRemote)
endpoint.HostComputeNetwork = network.Id
endpointSettings, err := json.Marshal(endpoint)
if err != nil {
return nil, err
}
newEndpoint, err := createEndpoint(network.Id, string(endpointSettings))
if err != nil {
return nil, err
}
return newEndpoint, nil
}
// CreateRemoteEndpoint creates a remote endpoint on the Network.
func (network *HostComputeNetwork) CreateRemoteEndpoint(endpoint *HostComputeEndpoint) (*HostComputeEndpoint, error) {
endpoint.Flags = EndpointFlagsRemoteEndpoint | endpoint.Flags
return network.CreateEndpoint(endpoint)
}

216
vendor/github.com/Microsoft/hcsshim/hcn/hcnpolicy.go generated vendored Normal file
View File

@ -0,0 +1,216 @@
package hcn
import "encoding/json"
// EndpointPolicyType are the potential Policies that apply to Endpoints.
type EndpointPolicyType string
// EndpointPolicyType const
const (
PortMapping EndpointPolicyType = "PortMapping"
ACL EndpointPolicyType = "ACL"
QOS EndpointPolicyType = "QOS"
L2Driver EndpointPolicyType = "L2Driver"
OutBoundNAT EndpointPolicyType = "OutBoundNAT"
SDNRoute EndpointPolicyType = "SDNRoute"
L4Proxy EndpointPolicyType = "L4Proxy"
PortName EndpointPolicyType = "PortName"
EncapOverhead EndpointPolicyType = "EncapOverhead"
// Endpoint and Network have InterfaceConstraint and ProviderAddress
NetworkProviderAddress EndpointPolicyType = "ProviderAddress"
NetworkInterfaceConstraint EndpointPolicyType = "InterfaceConstraint"
)
// EndpointPolicy is a collection of Policy settings for an Endpoint.
type EndpointPolicy struct {
Type EndpointPolicyType `json:""`
Settings json.RawMessage `json:",omitempty"`
}
// NetworkPolicyType are the potential Policies that apply to Networks.
type NetworkPolicyType string
// NetworkPolicyType const
const (
SourceMacAddress NetworkPolicyType = "SourceMacAddress"
NetAdapterName NetworkPolicyType = "NetAdapterName"
VSwitchExtension NetworkPolicyType = "VSwitchExtension"
DrMacAddress NetworkPolicyType = "DrMacAddress"
AutomaticDNS NetworkPolicyType = "AutomaticDNS"
InterfaceConstraint NetworkPolicyType = "InterfaceConstraint"
ProviderAddress NetworkPolicyType = "ProviderAddress"
RemoteSubnetRoute NetworkPolicyType = "RemoteSubnetRoute"
)
// NetworkPolicy is a collection of Policy settings for a Network.
type NetworkPolicy struct {
Type NetworkPolicyType `json:""`
Settings json.RawMessage `json:",omitempty"`
}
// SubnetPolicyType are the potential Policies that apply to Subnets.
type SubnetPolicyType string
// SubnetPolicyType const
const (
VLAN SubnetPolicyType = "VLAN"
VSID SubnetPolicyType = "VSID"
)
// SubnetPolicy is a collection of Policy settings for a Subnet.
type SubnetPolicy struct {
Type SubnetPolicyType `json:""`
Settings json.RawMessage `json:",omitempty"`
}
/// Endpoint Policy objects
// PortMappingPolicySetting defines Port Mapping (NAT)
type PortMappingPolicySetting struct {
Protocol uint32 `json:",omitempty"` // EX: TCP = 6, UDP = 17
InternalPort uint16 `json:",omitempty"`
ExternalPort uint16 `json:",omitempty"`
VIP string `json:",omitempty"`
}
// ActionType associated with ACLs. Value is either Allow or Block.
type ActionType string
// DirectionType associated with ACLs. Value is either In or Out.
type DirectionType string
// RuleType associated with ACLs. Value is either Host (WFP) or Switch (VFP).
type RuleType string
const (
// Allow traffic
ActionTypeAllow ActionType = "Allow"
// Block traffic
ActionTypeBlock ActionType = "Block"
// In is traffic coming to the Endpoint
DirectionTypeIn DirectionType = "In"
// Out is traffic leaving the Endpoint
DirectionTypeOut DirectionType = "Out"
// Host creates WFP (Windows Firewall) rules
RuleTypeHost RuleType = "Host"
// Switch creates VFP (Virtual Filter Platform) rules
RuleTypeSwitch RuleType = "Switch"
)
// AclPolicySetting creates firewall rules on an endpoint
type AclPolicySetting struct {
Protocols string `json:",omitempty"` // EX: 6 (TCP), 17 (UDP), 1 (ICMPv4), 58 (ICMPv6), 2 (IGMP)
Action ActionType `json:","`
Direction DirectionType `json:","`
LocalAddresses string `json:",omitempty"`
RemoteAddresses string `json:",omitempty"`
LocalPorts string `json:",omitempty"`
RemotePorts string `json:",omitempty"`
RuleType RuleType `json:",omitempty"`
Priority uint16 `json:",omitempty"`
}
// QosPolicySetting sets Quality of Service bandwidth caps on an Endpoint.
type QosPolicySetting struct {
MaximumOutgoingBandwidthInBytes uint64
}
// OutboundNatPolicySetting sets outbound Network Address Translation on an Endpoint.
type OutboundNatPolicySetting struct {
VirtualIP string `json:",omitempty"`
Exceptions []string `json:",omitempty"`
}
// SDNRoutePolicySetting sets SDN Route on an Endpoint.
type SDNRoutePolicySetting struct {
DestinationPrefix string `json:",omitempty"`
NextHop string `json:",omitempty"`
NeedEncap bool `json:",omitempty"`
}
// L4ProxyPolicySetting sets Layer-4 Proxy on an endpoint.
type L4ProxyPolicySetting struct {
IP string `json:",omitempty"`
Port string `json:",omitempty"`
Protocol uint32 `json:",omitempty"` // EX: TCP = 6, UDP = 17
ExceptionList []string `json:",omitempty"`
Destination string `json:","`
OutboundNat bool `json:",omitempty"`
}
// PortnameEndpointPolicySetting sets the port name for an endpoint.
type PortnameEndpointPolicySetting struct {
Name string `json:",omitempty"`
}
// EncapOverheadEndpointPolicySetting sets the encap overhead for an endpoint.
type EncapOverheadEndpointPolicySetting struct {
Overhead uint16 `json:",omitempty"`
}
/// Endpoint and Network Policy objects
// ProviderAddressEndpointPolicySetting sets the PA for an endpoint.
type ProviderAddressEndpointPolicySetting struct {
ProviderAddress string `json:",omitempty"`
}
// InterfaceConstraintPolicySetting limits an Endpoint or Network to a specific Nic.
type InterfaceConstraintPolicySetting struct {
InterfaceGuid string `json:",omitempty"`
InterfaceLuid uint64 `json:",omitempty"`
InterfaceIndex uint32 `json:",omitempty"`
InterfaceMediaType uint32 `json:",omitempty"`
InterfaceAlias string `json:",omitempty"`
InterfaceDescription string `json:",omitempty"`
}
/// Network Policy objects
// SourceMacAddressNetworkPolicySetting sets source MAC for a network.
type SourceMacAddressNetworkPolicySetting struct {
SourceMacAddress string `json:",omitempty"`
}
// NetAdapterNameNetworkPolicySetting sets network adapter of a network.
type NetAdapterNameNetworkPolicySetting struct {
NetworkAdapterName string `json:",omitempty"`
}
// VSwitchExtensionNetworkPolicySetting enables/disabled VSwitch extensions for a network.
type VSwitchExtensionNetworkPolicySetting struct {
ExtensionID string `json:",omitempty"`
Enable bool `json:",omitempty"`
}
// DrMacAddressNetworkPolicySetting sets the DR MAC for a network.
type DrMacAddressNetworkPolicySetting struct {
Address string `json:",omitempty"`
}
// AutomaticDNSNetworkPolicySetting enables/disables automatic DNS on a network.
type AutomaticDNSNetworkPolicySetting struct {
Enable bool `json:",omitempty"`
}
/// Subnet Policy objects
// VlanPolicySetting isolates a subnet with VLAN tagging.
type VlanPolicySetting struct {
IsolationId uint32 `json:","`
}
// VsidPolicySetting isolates a subnet with VSID tagging.
type VsidPolicySetting struct {
IsolationId uint32 `json:","`
}
// RemoteSubnetRoutePolicySetting creates remote subnet route rules on a network
type RemoteSubnetRoutePolicySetting struct {
DestinationPrefix string
IsolationId uint16
ProviderAddress string
DistributedRouterMacAddress string
}

69
vendor/github.com/Microsoft/hcsshim/hcn/hcnsupport.go generated vendored Normal file
View File

@ -0,0 +1,69 @@
package hcn
import (
"github.com/sirupsen/logrus"
)
// SupportedFeatures are the features provided by the Service.
type SupportedFeatures struct {
Acl AclFeatures `json:"ACL"`
Api ApiSupport `json:"API"`
RemoteSubnet bool `json:"RemoteSubnet"`
DSR bool `json:"DSR"`
}
// AclFeatures are the supported ACL possibilities.
type AclFeatures struct {
AclAddressLists bool `json:"AclAddressLists"`
AclNoHostRulePriority bool `json:"AclHostRulePriority"`
AclPortRanges bool `json:"AclPortRanges"`
AclRuleId bool `json:"AclRuleId"`
}
// ApiSupport lists the supported API versions.
type ApiSupport struct {
V1 bool `json:"V1"`
V2 bool `json:"V2"`
}
// GetSupportedFeatures returns the features supported by the Service.
func GetSupportedFeatures() SupportedFeatures {
var features SupportedFeatures
globals, err := GetGlobals()
if err != nil {
// Expected on pre-1803 builds, all features will be false/unsupported
logrus.Debugf("Unable to obtain globals: %s", err)
return features
}
features.Acl = AclFeatures{
AclAddressLists: isFeatureSupported(globals.Version, HNSVersion1803),
AclNoHostRulePriority: isFeatureSupported(globals.Version, HNSVersion1803),
AclPortRanges: isFeatureSupported(globals.Version, HNSVersion1803),
AclRuleId: isFeatureSupported(globals.Version, HNSVersion1803),
}
features.Api = ApiSupport{
V2: isFeatureSupported(globals.Version, V2ApiSupport),
V1: true, // HNSCall is still available.
}
features.RemoteSubnet = isFeatureSupported(globals.Version, RemoteSubnetVersion)
features.DSR = isFeatureSupported(globals.Version, DSRVersion)
return features
}
func isFeatureSupported(currentVersion Version, minVersionSupported Version) bool {
if currentVersion.Major < minVersionSupported.Major {
return false
}
if currentVersion.Major > minVersionSupported.Major {
return true
}
if currentVersion.Minor < minVersionSupported.Minor {
return false
}
return true
}

View File

@ -0,0 +1,714 @@
// Code generated mksyscall_windows.exe DO NOT EDIT
package hcn
import (
"syscall"
"unsafe"
"golang.org/x/sys/windows"
)
var _ unsafe.Pointer
// Do the interface allocations only once for common
// Errno values.
const (
errnoERROR_IO_PENDING = 997
)
var (
errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING)
)
// errnoErr returns common boxed Errno values, to prevent
// allocations at runtime.
func errnoErr(e syscall.Errno) error {
switch e {
case 0:
return nil
case errnoERROR_IO_PENDING:
return errERROR_IO_PENDING
}
// TODO: add more here, after collecting data on the common
// error values see on Windows. (perhaps when running
// all.bat?)
return e
}
var (
modiphlpapi = windows.NewLazySystemDLL("iphlpapi.dll")
modvmcompute = windows.NewLazySystemDLL("vmcompute.dll")
modcomputenetwork = windows.NewLazySystemDLL("computenetwork.dll")
procSetCurrentThreadCompartmentId = modiphlpapi.NewProc("SetCurrentThreadCompartmentId")
procHNSCall = modvmcompute.NewProc("HNSCall")
procHcnEnumerateNetworks = modcomputenetwork.NewProc("HcnEnumerateNetworks")
procHcnCreateNetwork = modcomputenetwork.NewProc("HcnCreateNetwork")
procHcnOpenNetwork = modcomputenetwork.NewProc("HcnOpenNetwork")
procHcnModifyNetwork = modcomputenetwork.NewProc("HcnModifyNetwork")
procHcnQueryNetworkProperties = modcomputenetwork.NewProc("HcnQueryNetworkProperties")
procHcnDeleteNetwork = modcomputenetwork.NewProc("HcnDeleteNetwork")
procHcnCloseNetwork = modcomputenetwork.NewProc("HcnCloseNetwork")
procHcnEnumerateEndpoints = modcomputenetwork.NewProc("HcnEnumerateEndpoints")
procHcnCreateEndpoint = modcomputenetwork.NewProc("HcnCreateEndpoint")
procHcnOpenEndpoint = modcomputenetwork.NewProc("HcnOpenEndpoint")
procHcnModifyEndpoint = modcomputenetwork.NewProc("HcnModifyEndpoint")
procHcnQueryEndpointProperties = modcomputenetwork.NewProc("HcnQueryEndpointProperties")
procHcnDeleteEndpoint = modcomputenetwork.NewProc("HcnDeleteEndpoint")
procHcnCloseEndpoint = modcomputenetwork.NewProc("HcnCloseEndpoint")
procHcnEnumerateNamespaces = modcomputenetwork.NewProc("HcnEnumerateNamespaces")
procHcnCreateNamespace = modcomputenetwork.NewProc("HcnCreateNamespace")
procHcnOpenNamespace = modcomputenetwork.NewProc("HcnOpenNamespace")
procHcnModifyNamespace = modcomputenetwork.NewProc("HcnModifyNamespace")
procHcnQueryNamespaceProperties = modcomputenetwork.NewProc("HcnQueryNamespaceProperties")
procHcnDeleteNamespace = modcomputenetwork.NewProc("HcnDeleteNamespace")
procHcnCloseNamespace = modcomputenetwork.NewProc("HcnCloseNamespace")
procHcnEnumerateLoadBalancers = modcomputenetwork.NewProc("HcnEnumerateLoadBalancers")
procHcnCreateLoadBalancer = modcomputenetwork.NewProc("HcnCreateLoadBalancer")
procHcnOpenLoadBalancer = modcomputenetwork.NewProc("HcnOpenLoadBalancer")
procHcnModifyLoadBalancer = modcomputenetwork.NewProc("HcnModifyLoadBalancer")
procHcnQueryLoadBalancerProperties = modcomputenetwork.NewProc("HcnQueryLoadBalancerProperties")
procHcnDeleteLoadBalancer = modcomputenetwork.NewProc("HcnDeleteLoadBalancer")
procHcnCloseLoadBalancer = modcomputenetwork.NewProc("HcnCloseLoadBalancer")
procHcnOpenService = modcomputenetwork.NewProc("HcnOpenService")
procHcnRegisterServiceCallback = modcomputenetwork.NewProc("HcnRegisterServiceCallback")
procHcnUnregisterServiceCallback = modcomputenetwork.NewProc("HcnUnregisterServiceCallback")
procHcnCloseService = modcomputenetwork.NewProc("HcnCloseService")
)
func SetCurrentThreadCompartmentId(compartmentId uint32) (hr error) {
r0, _, _ := syscall.Syscall(procSetCurrentThreadCompartmentId.Addr(), 1, uintptr(compartmentId), 0, 0)
if int32(r0) < 0 {
if r0&0x1fff0000 == 0x00070000 {
r0 &= 0xffff
}
hr = syscall.Errno(r0)
}
return
}
func _hnsCall(method string, path string, object string, response **uint16) (hr error) {
var _p0 *uint16
_p0, hr = syscall.UTF16PtrFromString(method)
if hr != nil {
return
}
var _p1 *uint16
_p1, hr = syscall.UTF16PtrFromString(path)
if hr != nil {
return
}
var _p2 *uint16
_p2, hr = syscall.UTF16PtrFromString(object)
if hr != nil {
return
}
return __hnsCall(_p0, _p1, _p2, response)
}
func __hnsCall(method *uint16, path *uint16, object *uint16, response **uint16) (hr error) {
if hr = procHNSCall.Find(); hr != nil {
return
}
r0, _, _ := syscall.Syscall6(procHNSCall.Addr(), 4, uintptr(unsafe.Pointer(method)), uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(object)), uintptr(unsafe.Pointer(response)), 0, 0)
if int32(r0) < 0 {
if r0&0x1fff0000 == 0x00070000 {
r0 &= 0xffff
}
hr = syscall.Errno(r0)
}
return
}
func hcnEnumerateNetworks(query string, networks **uint16, result **uint16) (hr error) {
var _p0 *uint16
_p0, hr = syscall.UTF16PtrFromString(query)
if hr != nil {
return
}
return _hcnEnumerateNetworks(_p0, networks, result)
}
func _hcnEnumerateNetworks(query *uint16, networks **uint16, result **uint16) (hr error) {
if hr = procHcnEnumerateNetworks.Find(); hr != nil {
return
}
r0, _, _ := syscall.Syscall(procHcnEnumerateNetworks.Addr(), 3, uintptr(unsafe.Pointer(query)), uintptr(unsafe.Pointer(networks)), uintptr(unsafe.Pointer(result)))
if int32(r0) < 0 {
if r0&0x1fff0000 == 0x00070000 {
r0 &= 0xffff
}
hr = syscall.Errno(r0)
}
return
}
func hcnCreateNetwork(id *_guid, settings string, network *hcnNetwork, result **uint16) (hr error) {
var _p0 *uint16
_p0, hr = syscall.UTF16PtrFromString(settings)
if hr != nil {
return
}
return _hcnCreateNetwork(id, _p0, network, result)
}
func _hcnCreateNetwork(id *_guid, settings *uint16, network *hcnNetwork, result **uint16) (hr error) {
if hr = procHcnCreateNetwork.Find(); hr != nil {
return
}
r0, _, _ := syscall.Syscall6(procHcnCreateNetwork.Addr(), 4, uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(settings)), uintptr(unsafe.Pointer(network)), uintptr(unsafe.Pointer(result)), 0, 0)
if int32(r0) < 0 {
if r0&0x1fff0000 == 0x00070000 {
r0 &= 0xffff
}
hr = syscall.Errno(r0)
}
return
}
func hcnOpenNetwork(id *_guid, network *hcnNetwork, result **uint16) (hr error) {
if hr = procHcnOpenNetwork.Find(); hr != nil {
return
}
r0, _, _ := syscall.Syscall(procHcnOpenNetwork.Addr(), 3, uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(network)), uintptr(unsafe.Pointer(result)))
if int32(r0) < 0 {
if r0&0x1fff0000 == 0x00070000 {
r0 &= 0xffff
}
hr = syscall.Errno(r0)
}
return
}
func hcnModifyNetwork(network hcnNetwork, settings string, result **uint16) (hr error) {
var _p0 *uint16
_p0, hr = syscall.UTF16PtrFromString(settings)
if hr != nil {
return
}
return _hcnModifyNetwork(network, _p0, result)
}
func _hcnModifyNetwork(network hcnNetwork, settings *uint16, result **uint16) (hr error) {
if hr = procHcnModifyNetwork.Find(); hr != nil {
return
}
r0, _, _ := syscall.Syscall(procHcnModifyNetwork.Addr(), 3, uintptr(network), uintptr(unsafe.Pointer(settings)), uintptr(unsafe.Pointer(result)))
if int32(r0) < 0 {
if r0&0x1fff0000 == 0x00070000 {
r0 &= 0xffff
}
hr = syscall.Errno(r0)
}
return
}
func hcnQueryNetworkProperties(network hcnNetwork, query string, properties **uint16, result **uint16) (hr error) {
var _p0 *uint16
_p0, hr = syscall.UTF16PtrFromString(query)
if hr != nil {
return
}
return _hcnQueryNetworkProperties(network, _p0, properties, result)
}
func _hcnQueryNetworkProperties(network hcnNetwork, query *uint16, properties **uint16, result **uint16) (hr error) {
if hr = procHcnQueryNetworkProperties.Find(); hr != nil {
return
}
r0, _, _ := syscall.Syscall6(procHcnQueryNetworkProperties.Addr(), 4, uintptr(network), uintptr(unsafe.Pointer(query)), uintptr(unsafe.Pointer(properties)), uintptr(unsafe.Pointer(result)), 0, 0)
if int32(r0) < 0 {
if r0&0x1fff0000 == 0x00070000 {
r0 &= 0xffff
}
hr = syscall.Errno(r0)
}
return
}
func hcnDeleteNetwork(id *_guid, result **uint16) (hr error) {
if hr = procHcnDeleteNetwork.Find(); hr != nil {
return
}
r0, _, _ := syscall.Syscall(procHcnDeleteNetwork.Addr(), 2, uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(result)), 0)
if int32(r0) < 0 {
if r0&0x1fff0000 == 0x00070000 {
r0 &= 0xffff
}
hr = syscall.Errno(r0)
}
return
}
func hcnCloseNetwork(network hcnNetwork) (hr error) {
if hr = procHcnCloseNetwork.Find(); hr != nil {
return
}
r0, _, _ := syscall.Syscall(procHcnCloseNetwork.Addr(), 1, uintptr(network), 0, 0)
if int32(r0) < 0 {
if r0&0x1fff0000 == 0x00070000 {
r0 &= 0xffff
}
hr = syscall.Errno(r0)
}
return
}
func hcnEnumerateEndpoints(query string, endpoints **uint16, result **uint16) (hr error) {
var _p0 *uint16
_p0, hr = syscall.UTF16PtrFromString(query)
if hr != nil {
return
}
return _hcnEnumerateEndpoints(_p0, endpoints, result)
}
func _hcnEnumerateEndpoints(query *uint16, endpoints **uint16, result **uint16) (hr error) {
if hr = procHcnEnumerateEndpoints.Find(); hr != nil {
return
}
r0, _, _ := syscall.Syscall(procHcnEnumerateEndpoints.Addr(), 3, uintptr(unsafe.Pointer(query)), uintptr(unsafe.Pointer(endpoints)), uintptr(unsafe.Pointer(result)))
if int32(r0) < 0 {
if r0&0x1fff0000 == 0x00070000 {
r0 &= 0xffff
}
hr = syscall.Errno(r0)
}
return
}
func hcnCreateEndpoint(network hcnNetwork, id *_guid, settings string, endpoint *hcnEndpoint, result **uint16) (hr error) {
var _p0 *uint16
_p0, hr = syscall.UTF16PtrFromString(settings)
if hr != nil {
return
}
return _hcnCreateEndpoint(network, id, _p0, endpoint, result)
}
func _hcnCreateEndpoint(network hcnNetwork, id *_guid, settings *uint16, endpoint *hcnEndpoint, result **uint16) (hr error) {
if hr = procHcnCreateEndpoint.Find(); hr != nil {
return
}
r0, _, _ := syscall.Syscall6(procHcnCreateEndpoint.Addr(), 5, uintptr(network), uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(settings)), uintptr(unsafe.Pointer(endpoint)), uintptr(unsafe.Pointer(result)), 0)
if int32(r0) < 0 {
if r0&0x1fff0000 == 0x00070000 {
r0 &= 0xffff
}
hr = syscall.Errno(r0)
}
return
}
func hcnOpenEndpoint(id *_guid, endpoint *hcnEndpoint, result **uint16) (hr error) {
if hr = procHcnOpenEndpoint.Find(); hr != nil {
return
}
r0, _, _ := syscall.Syscall(procHcnOpenEndpoint.Addr(), 3, uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(endpoint)), uintptr(unsafe.Pointer(result)))
if int32(r0) < 0 {
if r0&0x1fff0000 == 0x00070000 {
r0 &= 0xffff
}
hr = syscall.Errno(r0)
}
return
}
func hcnModifyEndpoint(endpoint hcnEndpoint, settings string, result **uint16) (hr error) {
var _p0 *uint16
_p0, hr = syscall.UTF16PtrFromString(settings)
if hr != nil {
return
}
return _hcnModifyEndpoint(endpoint, _p0, result)
}
func _hcnModifyEndpoint(endpoint hcnEndpoint, settings *uint16, result **uint16) (hr error) {
if hr = procHcnModifyEndpoint.Find(); hr != nil {
return
}
r0, _, _ := syscall.Syscall(procHcnModifyEndpoint.Addr(), 3, uintptr(endpoint), uintptr(unsafe.Pointer(settings)), uintptr(unsafe.Pointer(result)))
if int32(r0) < 0 {
if r0&0x1fff0000 == 0x00070000 {
r0 &= 0xffff
}
hr = syscall.Errno(r0)
}
return
}
func hcnQueryEndpointProperties(endpoint hcnEndpoint, query string, properties **uint16, result **uint16) (hr error) {
var _p0 *uint16
_p0, hr = syscall.UTF16PtrFromString(query)
if hr != nil {
return
}
return _hcnQueryEndpointProperties(endpoint, _p0, properties, result)
}
func _hcnQueryEndpointProperties(endpoint hcnEndpoint, query *uint16, properties **uint16, result **uint16) (hr error) {
if hr = procHcnQueryEndpointProperties.Find(); hr != nil {
return
}
r0, _, _ := syscall.Syscall6(procHcnQueryEndpointProperties.Addr(), 4, uintptr(endpoint), uintptr(unsafe.Pointer(query)), uintptr(unsafe.Pointer(properties)), uintptr(unsafe.Pointer(result)), 0, 0)
if int32(r0) < 0 {
if r0&0x1fff0000 == 0x00070000 {
r0 &= 0xffff
}
hr = syscall.Errno(r0)
}
return
}
func hcnDeleteEndpoint(id *_guid, result **uint16) (hr error) {
if hr = procHcnDeleteEndpoint.Find(); hr != nil {
return
}
r0, _, _ := syscall.Syscall(procHcnDeleteEndpoint.Addr(), 2, uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(result)), 0)
if int32(r0) < 0 {
if r0&0x1fff0000 == 0x00070000 {
r0 &= 0xffff
}
hr = syscall.Errno(r0)
}
return
}
func hcnCloseEndpoint(endpoint hcnEndpoint) (hr error) {
if hr = procHcnCloseEndpoint.Find(); hr != nil {
return
}
r0, _, _ := syscall.Syscall(procHcnCloseEndpoint.Addr(), 1, uintptr(endpoint), 0, 0)
if int32(r0) < 0 {
if r0&0x1fff0000 == 0x00070000 {
r0 &= 0xffff
}
hr = syscall.Errno(r0)
}
return
}
func hcnEnumerateNamespaces(query string, namespaces **uint16, result **uint16) (hr error) {
var _p0 *uint16
_p0, hr = syscall.UTF16PtrFromString(query)
if hr != nil {
return
}
return _hcnEnumerateNamespaces(_p0, namespaces, result)
}
func _hcnEnumerateNamespaces(query *uint16, namespaces **uint16, result **uint16) (hr error) {
if hr = procHcnEnumerateNamespaces.Find(); hr != nil {
return
}
r0, _, _ := syscall.Syscall(procHcnEnumerateNamespaces.Addr(), 3, uintptr(unsafe.Pointer(query)), uintptr(unsafe.Pointer(namespaces)), uintptr(unsafe.Pointer(result)))
if int32(r0) < 0 {
if r0&0x1fff0000 == 0x00070000 {
r0 &= 0xffff
}
hr = syscall.Errno(r0)
}
return
}
func hcnCreateNamespace(id *_guid, settings string, namespace *hcnNamespace, result **uint16) (hr error) {
var _p0 *uint16
_p0, hr = syscall.UTF16PtrFromString(settings)
if hr != nil {
return
}
return _hcnCreateNamespace(id, _p0, namespace, result)
}
func _hcnCreateNamespace(id *_guid, settings *uint16, namespace *hcnNamespace, result **uint16) (hr error) {
if hr = procHcnCreateNamespace.Find(); hr != nil {
return
}
r0, _, _ := syscall.Syscall6(procHcnCreateNamespace.Addr(), 4, uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(settings)), uintptr(unsafe.Pointer(namespace)), uintptr(unsafe.Pointer(result)), 0, 0)
if int32(r0) < 0 {
if r0&0x1fff0000 == 0x00070000 {
r0 &= 0xffff
}
hr = syscall.Errno(r0)
}
return
}
func hcnOpenNamespace(id *_guid, namespace *hcnNamespace, result **uint16) (hr error) {
if hr = procHcnOpenNamespace.Find(); hr != nil {
return
}
r0, _, _ := syscall.Syscall(procHcnOpenNamespace.Addr(), 3, uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(namespace)), uintptr(unsafe.Pointer(result)))
if int32(r0) < 0 {
if r0&0x1fff0000 == 0x00070000 {
r0 &= 0xffff
}
hr = syscall.Errno(r0)
}
return
}
func hcnModifyNamespace(namespace hcnNamespace, settings string, result **uint16) (hr error) {
var _p0 *uint16
_p0, hr = syscall.UTF16PtrFromString(settings)
if hr != nil {
return
}
return _hcnModifyNamespace(namespace, _p0, result)
}
func _hcnModifyNamespace(namespace hcnNamespace, settings *uint16, result **uint16) (hr error) {
if hr = procHcnModifyNamespace.Find(); hr != nil {
return
}
r0, _, _ := syscall.Syscall(procHcnModifyNamespace.Addr(), 3, uintptr(namespace), uintptr(unsafe.Pointer(settings)), uintptr(unsafe.Pointer(result)))
if int32(r0) < 0 {
if r0&0x1fff0000 == 0x00070000 {
r0 &= 0xffff
}
hr = syscall.Errno(r0)
}
return
}
func hcnQueryNamespaceProperties(namespace hcnNamespace, query string, properties **uint16, result **uint16) (hr error) {
var _p0 *uint16
_p0, hr = syscall.UTF16PtrFromString(query)
if hr != nil {
return
}
return _hcnQueryNamespaceProperties(namespace, _p0, properties, result)
}
func _hcnQueryNamespaceProperties(namespace hcnNamespace, query *uint16, properties **uint16, result **uint16) (hr error) {
if hr = procHcnQueryNamespaceProperties.Find(); hr != nil {
return
}
r0, _, _ := syscall.Syscall6(procHcnQueryNamespaceProperties.Addr(), 4, uintptr(namespace), uintptr(unsafe.Pointer(query)), uintptr(unsafe.Pointer(properties)), uintptr(unsafe.Pointer(result)), 0, 0)
if int32(r0) < 0 {
if r0&0x1fff0000 == 0x00070000 {
r0 &= 0xffff
}
hr = syscall.Errno(r0)
}
return
}
func hcnDeleteNamespace(id *_guid, result **uint16) (hr error) {
if hr = procHcnDeleteNamespace.Find(); hr != nil {
return
}
r0, _, _ := syscall.Syscall(procHcnDeleteNamespace.Addr(), 2, uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(result)), 0)
if int32(r0) < 0 {
if r0&0x1fff0000 == 0x00070000 {
r0 &= 0xffff
}
hr = syscall.Errno(r0)
}
return
}
func hcnCloseNamespace(namespace hcnNamespace) (hr error) {
if hr = procHcnCloseNamespace.Find(); hr != nil {
return
}
r0, _, _ := syscall.Syscall(procHcnCloseNamespace.Addr(), 1, uintptr(namespace), 0, 0)
if int32(r0) < 0 {
if r0&0x1fff0000 == 0x00070000 {
r0 &= 0xffff
}
hr = syscall.Errno(r0)
}
return
}
func hcnEnumerateLoadBalancers(query string, loadBalancers **uint16, result **uint16) (hr error) {
var _p0 *uint16
_p0, hr = syscall.UTF16PtrFromString(query)
if hr != nil {
return
}
return _hcnEnumerateLoadBalancers(_p0, loadBalancers, result)
}
func _hcnEnumerateLoadBalancers(query *uint16, loadBalancers **uint16, result **uint16) (hr error) {
if hr = procHcnEnumerateLoadBalancers.Find(); hr != nil {
return
}
r0, _, _ := syscall.Syscall(procHcnEnumerateLoadBalancers.Addr(), 3, uintptr(unsafe.Pointer(query)), uintptr(unsafe.Pointer(loadBalancers)), uintptr(unsafe.Pointer(result)))
if int32(r0) < 0 {
if r0&0x1fff0000 == 0x00070000 {
r0 &= 0xffff
}
hr = syscall.Errno(r0)
}
return
}
func hcnCreateLoadBalancer(id *_guid, settings string, loadBalancer *hcnLoadBalancer, result **uint16) (hr error) {
var _p0 *uint16
_p0, hr = syscall.UTF16PtrFromString(settings)
if hr != nil {
return
}
return _hcnCreateLoadBalancer(id, _p0, loadBalancer, result)
}
func _hcnCreateLoadBalancer(id *_guid, settings *uint16, loadBalancer *hcnLoadBalancer, result **uint16) (hr error) {
if hr = procHcnCreateLoadBalancer.Find(); hr != nil {
return
}
r0, _, _ := syscall.Syscall6(procHcnCreateLoadBalancer.Addr(), 4, uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(settings)), uintptr(unsafe.Pointer(loadBalancer)), uintptr(unsafe.Pointer(result)), 0, 0)
if int32(r0) < 0 {
if r0&0x1fff0000 == 0x00070000 {
r0 &= 0xffff
}
hr = syscall.Errno(r0)
}
return
}
func hcnOpenLoadBalancer(id *_guid, loadBalancer *hcnLoadBalancer, result **uint16) (hr error) {
if hr = procHcnOpenLoadBalancer.Find(); hr != nil {
return
}
r0, _, _ := syscall.Syscall(procHcnOpenLoadBalancer.Addr(), 3, uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(loadBalancer)), uintptr(unsafe.Pointer(result)))
if int32(r0) < 0 {
if r0&0x1fff0000 == 0x00070000 {
r0 &= 0xffff
}
hr = syscall.Errno(r0)
}
return
}
func hcnModifyLoadBalancer(loadBalancer hcnLoadBalancer, settings string, result **uint16) (hr error) {
var _p0 *uint16
_p0, hr = syscall.UTF16PtrFromString(settings)
if hr != nil {
return
}
return _hcnModifyLoadBalancer(loadBalancer, _p0, result)
}
func _hcnModifyLoadBalancer(loadBalancer hcnLoadBalancer, settings *uint16, result **uint16) (hr error) {
if hr = procHcnModifyLoadBalancer.Find(); hr != nil {
return
}
r0, _, _ := syscall.Syscall(procHcnModifyLoadBalancer.Addr(), 3, uintptr(loadBalancer), uintptr(unsafe.Pointer(settings)), uintptr(unsafe.Pointer(result)))
if int32(r0) < 0 {
if r0&0x1fff0000 == 0x00070000 {
r0 &= 0xffff
}
hr = syscall.Errno(r0)
}
return
}
func hcnQueryLoadBalancerProperties(loadBalancer hcnLoadBalancer, query string, properties **uint16, result **uint16) (hr error) {
var _p0 *uint16
_p0, hr = syscall.UTF16PtrFromString(query)
if hr != nil {
return
}
return _hcnQueryLoadBalancerProperties(loadBalancer, _p0, properties, result)
}
func _hcnQueryLoadBalancerProperties(loadBalancer hcnLoadBalancer, query *uint16, properties **uint16, result **uint16) (hr error) {
if hr = procHcnQueryLoadBalancerProperties.Find(); hr != nil {
return
}
r0, _, _ := syscall.Syscall6(procHcnQueryLoadBalancerProperties.Addr(), 4, uintptr(loadBalancer), uintptr(unsafe.Pointer(query)), uintptr(unsafe.Pointer(properties)), uintptr(unsafe.Pointer(result)), 0, 0)
if int32(r0) < 0 {
if r0&0x1fff0000 == 0x00070000 {
r0 &= 0xffff
}
hr = syscall.Errno(r0)
}
return
}
func hcnDeleteLoadBalancer(id *_guid, result **uint16) (hr error) {
if hr = procHcnDeleteLoadBalancer.Find(); hr != nil {
return
}
r0, _, _ := syscall.Syscall(procHcnDeleteLoadBalancer.Addr(), 2, uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(result)), 0)
if int32(r0) < 0 {
if r0&0x1fff0000 == 0x00070000 {
r0 &= 0xffff
}
hr = syscall.Errno(r0)
}
return
}
func hcnCloseLoadBalancer(loadBalancer hcnLoadBalancer) (hr error) {
if hr = procHcnCloseLoadBalancer.Find(); hr != nil {
return
}
r0, _, _ := syscall.Syscall(procHcnCloseLoadBalancer.Addr(), 1, uintptr(loadBalancer), 0, 0)
if int32(r0) < 0 {
if r0&0x1fff0000 == 0x00070000 {
r0 &= 0xffff
}
hr = syscall.Errno(r0)
}
return
}
func hcnOpenService(service *hcnService, result **uint16) (hr error) {
if hr = procHcnOpenService.Find(); hr != nil {
return
}
r0, _, _ := syscall.Syscall(procHcnOpenService.Addr(), 2, uintptr(unsafe.Pointer(service)), uintptr(unsafe.Pointer(result)), 0)
if int32(r0) < 0 {
if r0&0x1fff0000 == 0x00070000 {
r0 &= 0xffff
}
hr = syscall.Errno(r0)
}
return
}
func hcnRegisterServiceCallback(service hcnService, callback int32, context int32, callbackHandle *hcnCallbackHandle) (hr error) {
if hr = procHcnRegisterServiceCallback.Find(); hr != nil {
return
}
r0, _, _ := syscall.Syscall6(procHcnRegisterServiceCallback.Addr(), 4, uintptr(service), uintptr(callback), uintptr(context), uintptr(unsafe.Pointer(callbackHandle)), 0, 0)
if int32(r0) < 0 {
if r0&0x1fff0000 == 0x00070000 {
r0 &= 0xffff
}
hr = syscall.Errno(r0)
}
return
}
func hcnUnregisterServiceCallback(callbackHandle hcnCallbackHandle) (hr error) {
if hr = procHcnUnregisterServiceCallback.Find(); hr != nil {
return
}
r0, _, _ := syscall.Syscall(procHcnUnregisterServiceCallback.Addr(), 1, uintptr(callbackHandle), 0, 0)
if int32(r0) < 0 {
if r0&0x1fff0000 == 0x00070000 {
r0 &= 0xffff
}
hr = syscall.Errno(r0)
}
return
}
func hcnCloseService(service hcnService) (hr error) {
if hr = procHcnCloseService.Find(); hr != nil {
return
}
r0, _, _ := syscall.Syscall(procHcnCloseService.Addr(), 1, uintptr(service), 0, 0)
if int32(r0) < 0 {
if r0&0x1fff0000 == 0x00070000 {
r0 &= 0xffff
}
hr = syscall.Errno(r0)
}
return
}

View File

@ -4,80 +4,20 @@
package hcsshim
import (
"fmt"
"syscall"
"unsafe"
"github.com/sirupsen/logrus"
"github.com/Microsoft/hcsshim/internal/hcserror"
)
//go:generate go run mksyscall_windows.go -output zhcsshim.go hcsshim.go safeopen.go
//go:generate go run mksyscall_windows.go -output zsyscall_windows.go hcsshim.go
//sys coTaskMemFree(buffer unsafe.Pointer) = ole32.CoTaskMemFree
//sys SetCurrentThreadCompartmentId(compartmentId uint32) (hr error) = iphlpapi.SetCurrentThreadCompartmentId
//sys activateLayer(info *driverInfo, id string) (hr error) = vmcompute.ActivateLayer?
//sys copyLayer(info *driverInfo, srcId string, dstId string, descriptors []WC_LAYER_DESCRIPTOR) (hr error) = vmcompute.CopyLayer?
//sys createLayer(info *driverInfo, id string, parent string) (hr error) = vmcompute.CreateLayer?
//sys createSandboxLayer(info *driverInfo, id string, parent string, descriptors []WC_LAYER_DESCRIPTOR) (hr error) = vmcompute.CreateSandboxLayer?
//sys expandSandboxSize(info *driverInfo, id string, size uint64) (hr error) = vmcompute.ExpandSandboxSize?
//sys deactivateLayer(info *driverInfo, id string) (hr error) = vmcompute.DeactivateLayer?
//sys destroyLayer(info *driverInfo, id string) (hr error) = vmcompute.DestroyLayer?
//sys exportLayer(info *driverInfo, id string, path string, descriptors []WC_LAYER_DESCRIPTOR) (hr error) = vmcompute.ExportLayer?
//sys getLayerMountPath(info *driverInfo, id string, length *uintptr, buffer *uint16) (hr error) = vmcompute.GetLayerMountPath?
//sys getBaseImages(buffer **uint16) (hr error) = vmcompute.GetBaseImages?
//sys importLayer(info *driverInfo, id string, path string, descriptors []WC_LAYER_DESCRIPTOR) (hr error) = vmcompute.ImportLayer?
//sys layerExists(info *driverInfo, id string, exists *uint32) (hr error) = vmcompute.LayerExists?
//sys nameToGuid(name string, guid *GUID) (hr error) = vmcompute.NameToGuid?
//sys prepareLayer(info *driverInfo, id string, descriptors []WC_LAYER_DESCRIPTOR) (hr error) = vmcompute.PrepareLayer?
//sys unprepareLayer(info *driverInfo, id string) (hr error) = vmcompute.UnprepareLayer?
//sys processBaseImage(path string) (hr error) = vmcompute.ProcessBaseImage?
//sys processUtilityImage(path string) (hr error) = vmcompute.ProcessUtilityImage?
//sys importLayerBegin(info *driverInfo, id string, descriptors []WC_LAYER_DESCRIPTOR, context *uintptr) (hr error) = vmcompute.ImportLayerBegin?
//sys importLayerNext(context uintptr, fileName string, fileInfo *winio.FileBasicInfo) (hr error) = vmcompute.ImportLayerNext?
//sys importLayerWrite(context uintptr, buffer []byte) (hr error) = vmcompute.ImportLayerWrite?
//sys importLayerEnd(context uintptr) (hr error) = vmcompute.ImportLayerEnd?
//sys exportLayerBegin(info *driverInfo, id string, descriptors []WC_LAYER_DESCRIPTOR, context *uintptr) (hr error) = vmcompute.ExportLayerBegin?
//sys exportLayerNext(context uintptr, fileName **uint16, fileInfo *winio.FileBasicInfo, fileSize *int64, deleted *uint32) (hr error) = vmcompute.ExportLayerNext?
//sys exportLayerRead(context uintptr, buffer []byte, bytesRead *uint32) (hr error) = vmcompute.ExportLayerRead?
//sys exportLayerEnd(context uintptr) (hr error) = vmcompute.ExportLayerEnd?
//sys hcsEnumerateComputeSystems(query string, computeSystems **uint16, result **uint16) (hr error) = vmcompute.HcsEnumerateComputeSystems?
//sys hcsCreateComputeSystem(id string, configuration string, identity syscall.Handle, computeSystem *hcsSystem, result **uint16) (hr error) = vmcompute.HcsCreateComputeSystem?
//sys hcsOpenComputeSystem(id string, computeSystem *hcsSystem, result **uint16) (hr error) = vmcompute.HcsOpenComputeSystem?
//sys hcsCloseComputeSystem(computeSystem hcsSystem) (hr error) = vmcompute.HcsCloseComputeSystem?
//sys hcsStartComputeSystem(computeSystem hcsSystem, options string, result **uint16) (hr error) = vmcompute.HcsStartComputeSystem?
//sys hcsShutdownComputeSystem(computeSystem hcsSystem, options string, result **uint16) (hr error) = vmcompute.HcsShutdownComputeSystem?
//sys hcsTerminateComputeSystem(computeSystem hcsSystem, options string, result **uint16) (hr error) = vmcompute.HcsTerminateComputeSystem?
//sys hcsPauseComputeSystem(computeSystem hcsSystem, options string, result **uint16) (hr error) = vmcompute.HcsPauseComputeSystem?
//sys hcsResumeComputeSystem(computeSystem hcsSystem, options string, result **uint16) (hr error) = vmcompute.HcsResumeComputeSystem?
//sys hcsGetComputeSystemProperties(computeSystem hcsSystem, propertyQuery string, properties **uint16, result **uint16) (hr error) = vmcompute.HcsGetComputeSystemProperties?
//sys hcsModifyComputeSystem(computeSystem hcsSystem, configuration string, result **uint16) (hr error) = vmcompute.HcsModifyComputeSystem?
//sys hcsRegisterComputeSystemCallback(computeSystem hcsSystem, callback uintptr, context uintptr, callbackHandle *hcsCallback) (hr error) = vmcompute.HcsRegisterComputeSystemCallback?
//sys hcsUnregisterComputeSystemCallback(callbackHandle hcsCallback) (hr error) = vmcompute.HcsUnregisterComputeSystemCallback?
//sys hcsCreateProcess(computeSystem hcsSystem, processParameters string, processInformation *hcsProcessInformation, process *hcsProcess, result **uint16) (hr error) = vmcompute.HcsCreateProcess?
//sys hcsOpenProcess(computeSystem hcsSystem, pid uint32, process *hcsProcess, result **uint16) (hr error) = vmcompute.HcsOpenProcess?
//sys hcsCloseProcess(process hcsProcess) (hr error) = vmcompute.HcsCloseProcess?
//sys hcsTerminateProcess(process hcsProcess, result **uint16) (hr error) = vmcompute.HcsTerminateProcess?
//sys hcsGetProcessInfo(process hcsProcess, processInformation *hcsProcessInformation, result **uint16) (hr error) = vmcompute.HcsGetProcessInfo?
//sys hcsGetProcessProperties(process hcsProcess, processProperties **uint16, result **uint16) (hr error) = vmcompute.HcsGetProcessProperties?
//sys hcsModifyProcess(process hcsProcess, settings string, result **uint16) (hr error) = vmcompute.HcsModifyProcess?
//sys hcsGetServiceProperties(propertyQuery string, properties **uint16, result **uint16) (hr error) = vmcompute.HcsGetServiceProperties?
//sys hcsRegisterProcessCallback(process hcsProcess, callback uintptr, context uintptr, callbackHandle *hcsCallback) (hr error) = vmcompute.HcsRegisterProcessCallback?
//sys hcsUnregisterProcessCallback(callbackHandle hcsCallback) (hr error) = vmcompute.HcsUnregisterProcessCallback?
//sys hcsModifyServiceSettings(settings string, result **uint16) (hr error) = vmcompute.HcsModifyServiceSettings?
//sys _hnsCall(method string, path string, object string, response **uint16) (hr error) = vmcompute.HNSCall?
const (
// Specific user-visible exit codes
WaitErrExecFailed = 32767
ERROR_GEN_FAILURE = syscall.Errno(31)
ERROR_GEN_FAILURE = hcserror.ERROR_GEN_FAILURE
ERROR_SHUTDOWN_IN_PROGRESS = syscall.Errno(1115)
WSAEINVAL = syscall.Errno(10022)
@ -85,82 +25,4 @@ const (
TimeoutInfinite = 0xFFFFFFFF
)
type HcsError struct {
title string
rest string
Err error
}
type hcsSystem syscall.Handle
type hcsProcess syscall.Handle
type hcsCallback syscall.Handle
type hcsProcessInformation struct {
ProcessId uint32
Reserved uint32
StdInput syscall.Handle
StdOutput syscall.Handle
StdError syscall.Handle
}
func makeError(err error, title, rest string) error {
// Pass through DLL errors directly since they do not originate from HCS.
if _, ok := err.(*syscall.DLLError); ok {
return err
}
return &HcsError{title, rest, err}
}
func makeErrorf(err error, title, format string, a ...interface{}) error {
return makeError(err, title, fmt.Sprintf(format, a...))
}
func win32FromError(err error) uint32 {
if herr, ok := err.(*HcsError); ok {
return win32FromError(herr.Err)
}
if code, ok := err.(syscall.Errno); ok {
return uint32(code)
}
return uint32(ERROR_GEN_FAILURE)
}
func win32FromHresult(hr uintptr) uintptr {
if hr&0x1fff0000 == 0x00070000 {
return hr & 0xffff
}
return hr
}
func (e *HcsError) Error() string {
s := e.title
if len(s) > 0 && s[len(s)-1] != ' ' {
s += " "
}
s += fmt.Sprintf("failed in Win32: %s (0x%x)", e.Err, win32FromError(e.Err))
if e.rest != "" {
if e.rest[0] != ' ' {
s += " "
}
s += e.rest
}
return s
}
func convertAndFreeCoTaskMemString(buffer *uint16) string {
str := syscall.UTF16ToString((*[1 << 30]uint16)(unsafe.Pointer(buffer))[:])
coTaskMemFree(unsafe.Pointer(buffer))
return str
}
func convertAndFreeCoTaskMemBytes(buffer *uint16) []byte {
return []byte(convertAndFreeCoTaskMemString(buffer))
}
func processHcsResult(err error, resultp *uint16) error {
if resultp != nil {
result := convertAndFreeCoTaskMemString(resultp)
logrus.Debugf("Result: %s", result)
}
return err
}
type HcsError = hcserror.HcsError

View File

@ -1,29 +1,14 @@
package hcsshim
import (
"encoding/json"
"net"
"github.com/sirupsen/logrus"
"github.com/Microsoft/hcsshim/internal/hns"
)
// HNSEndpoint represents a network endpoint in HNS
type HNSEndpoint struct {
Id string `json:"ID,omitempty"`
Name string `json:",omitempty"`
VirtualNetwork string `json:",omitempty"`
VirtualNetworkName string `json:",omitempty"`
Policies []json.RawMessage `json:",omitempty"`
MacAddress string `json:",omitempty"`
IPAddress net.IP `json:",omitempty"`
DNSSuffix string `json:",omitempty"`
DNSServerList string `json:",omitempty"`
GatewayAddress string `json:",omitempty"`
EnableInternalDNS bool `json:",omitempty"`
DisableICC bool `json:",omitempty"`
PrefixLength uint8 `json:",omitempty"`
IsRemoteEndpoint bool `json:",omitempty"`
}
type HNSEndpoint = hns.HNSEndpoint
// Namespace represents a Compartment.
type Namespace = hns.Namespace
//SystemType represents the type of the system on which actions are done
type SystemType string
@ -37,39 +22,19 @@ const (
// EndpointAttachDetachRequest is the structure used to send request to the container to modify the system
// Supported resource types are Network and Request Types are Add/Remove
type EndpointAttachDetachRequest struct {
ContainerID string `json:"ContainerId,omitempty"`
SystemType SystemType `json:"SystemType"`
CompartmentID uint16 `json:"CompartmentId,omitempty"`
VirtualNICName string `json:"VirtualNicName,omitempty"`
}
type EndpointAttachDetachRequest = hns.EndpointAttachDetachRequest
// EndpointResquestResponse is object to get the endpoint request response
type EndpointResquestResponse struct {
Success bool
Error string
}
type EndpointResquestResponse = hns.EndpointResquestResponse
// HNSEndpointRequest makes a HNS call to modify/query a network endpoint
func HNSEndpointRequest(method, path, request string) (*HNSEndpoint, error) {
endpoint := &HNSEndpoint{}
err := hnsCall(method, "/endpoints/"+path, request, &endpoint)
if err != nil {
return nil, err
}
return endpoint, nil
return hns.HNSEndpointRequest(method, path, request)
}
// HNSListEndpointRequest makes a HNS call to query the list of available endpoints
func HNSListEndpointRequest() ([]HNSEndpoint, error) {
var endpoint []HNSEndpoint
err := hnsCall("GET", "/endpoints/", "", &endpoint)
if err != nil {
return nil, err
}
return endpoint, nil
return hns.HNSListEndpointRequest()
}
// HotAttachEndpoint makes a HCS Call to attach the endpoint to the container
@ -120,204 +85,10 @@ func modifyNetworkEndpoint(containerID string, endpointID string, request Reques
// GetHNSEndpointByID get the Endpoint by ID
func GetHNSEndpointByID(endpointID string) (*HNSEndpoint, error) {
return HNSEndpointRequest("GET", endpointID, "")
return hns.GetHNSEndpointByID(endpointID)
}
// GetHNSEndpointByName gets the endpoint filtered by Name
func GetHNSEndpointByName(endpointName string) (*HNSEndpoint, error) {
hnsResponse, err := HNSListEndpointRequest()
if err != nil {
return nil, err
}
for _, hnsEndpoint := range hnsResponse {
if hnsEndpoint.Name == endpointName {
return &hnsEndpoint, nil
}
}
return nil, EndpointNotFoundError{EndpointName: endpointName}
}
// Create Endpoint by sending EndpointRequest to HNS. TODO: Create a separate HNS interface to place all these methods
func (endpoint *HNSEndpoint) Create() (*HNSEndpoint, error) {
operation := "Create"
title := "HCSShim::HNSEndpoint::" + operation
logrus.Debugf(title+" id=%s", endpoint.Id)
jsonString, err := json.Marshal(endpoint)
if err != nil {
return nil, err
}
return HNSEndpointRequest("POST", "", string(jsonString))
}
// Delete Endpoint by sending EndpointRequest to HNS
func (endpoint *HNSEndpoint) Delete() (*HNSEndpoint, error) {
operation := "Delete"
title := "HCSShim::HNSEndpoint::" + operation
logrus.Debugf(title+" id=%s", endpoint.Id)
return HNSEndpointRequest("DELETE", endpoint.Id, "")
}
// Update Endpoint
func (endpoint *HNSEndpoint) Update() (*HNSEndpoint, error) {
operation := "Update"
title := "HCSShim::HNSEndpoint::" + operation
logrus.Debugf(title+" id=%s", endpoint.Id)
jsonString, err := json.Marshal(endpoint)
if err != nil {
return nil, err
}
err = hnsCall("POST", "/endpoints/"+endpoint.Id, string(jsonString), &endpoint)
return endpoint, err
}
// ContainerHotAttach attaches an endpoint to a running container
func (endpoint *HNSEndpoint) ContainerHotAttach(containerID string) error {
operation := "ContainerHotAttach"
title := "HCSShim::HNSEndpoint::" + operation
logrus.Debugf(title+" id=%s, containerId=%s", endpoint.Id, containerID)
return modifyNetworkEndpoint(containerID, endpoint.Id, Add)
}
// ContainerHotDetach detaches an endpoint from a running container
func (endpoint *HNSEndpoint) ContainerHotDetach(containerID string) error {
operation := "ContainerHotDetach"
title := "HCSShim::HNSEndpoint::" + operation
logrus.Debugf(title+" id=%s, containerId=%s", endpoint.Id, containerID)
return modifyNetworkEndpoint(containerID, endpoint.Id, Remove)
}
// ApplyACLPolicy applies a set of ACL Policies on the Endpoint
func (endpoint *HNSEndpoint) ApplyACLPolicy(policies ...*ACLPolicy) error {
operation := "ApplyACLPolicy"
title := "HCSShim::HNSEndpoint::" + operation
logrus.Debugf(title+" id=%s", endpoint.Id)
for _, policy := range policies {
if policy == nil {
continue
}
jsonString, err := json.Marshal(policy)
if err != nil {
return err
}
endpoint.Policies = append(endpoint.Policies, jsonString)
}
_, err := endpoint.Update()
return err
}
// ContainerAttach attaches an endpoint to container
func (endpoint *HNSEndpoint) ContainerAttach(containerID string, compartmentID uint16) error {
operation := "ContainerAttach"
title := "HCSShim::HNSEndpoint::" + operation
logrus.Debugf(title+" id=%s", endpoint.Id)
requestMessage := &EndpointAttachDetachRequest{
ContainerID: containerID,
CompartmentID: compartmentID,
SystemType: ContainerType,
}
response := &EndpointResquestResponse{}
jsonString, err := json.Marshal(requestMessage)
if err != nil {
return err
}
return hnsCall("POST", "/endpoints/"+endpoint.Id+"/attach", string(jsonString), &response)
}
// ContainerDetach detaches an endpoint from container
func (endpoint *HNSEndpoint) ContainerDetach(containerID string) error {
operation := "ContainerDetach"
title := "HCSShim::HNSEndpoint::" + operation
logrus.Debugf(title+" id=%s", endpoint.Id)
requestMessage := &EndpointAttachDetachRequest{
ContainerID: containerID,
SystemType: ContainerType,
}
response := &EndpointResquestResponse{}
jsonString, err := json.Marshal(requestMessage)
if err != nil {
return err
}
return hnsCall("POST", "/endpoints/"+endpoint.Id+"/detach", string(jsonString), &response)
}
// HostAttach attaches a nic on the host
func (endpoint *HNSEndpoint) HostAttach(compartmentID uint16) error {
operation := "HostAttach"
title := "HCSShim::HNSEndpoint::" + operation
logrus.Debugf(title+" id=%s", endpoint.Id)
requestMessage := &EndpointAttachDetachRequest{
CompartmentID: compartmentID,
SystemType: HostType,
}
response := &EndpointResquestResponse{}
jsonString, err := json.Marshal(requestMessage)
if err != nil {
return err
}
return hnsCall("POST", "/endpoints/"+endpoint.Id+"/attach", string(jsonString), &response)
}
// HostDetach detaches a nic on the host
func (endpoint *HNSEndpoint) HostDetach() error {
operation := "HostDetach"
title := "HCSShim::HNSEndpoint::" + operation
logrus.Debugf(title+" id=%s", endpoint.Id)
requestMessage := &EndpointAttachDetachRequest{
SystemType: HostType,
}
response := &EndpointResquestResponse{}
jsonString, err := json.Marshal(requestMessage)
if err != nil {
return err
}
return hnsCall("POST", "/endpoints/"+endpoint.Id+"/detach", string(jsonString), &response)
}
// VirtualMachineNICAttach attaches a endpoint to a virtual machine
func (endpoint *HNSEndpoint) VirtualMachineNICAttach(virtualMachineNICName string) error {
operation := "VirtualMachineNicAttach"
title := "HCSShim::HNSEndpoint::" + operation
logrus.Debugf(title+" id=%s", endpoint.Id)
requestMessage := &EndpointAttachDetachRequest{
VirtualNICName: virtualMachineNICName,
SystemType: VirtualMachineType,
}
response := &EndpointResquestResponse{}
jsonString, err := json.Marshal(requestMessage)
if err != nil {
return err
}
return hnsCall("POST", "/endpoints/"+endpoint.Id+"/attach", string(jsonString), &response)
}
// VirtualMachineNICDetach detaches a endpoint from a virtual machine
func (endpoint *HNSEndpoint) VirtualMachineNICDetach() error {
operation := "VirtualMachineNicDetach"
title := "HCSShim::HNSEndpoint::" + operation
logrus.Debugf(title+" id=%s", endpoint.Id)
requestMessage := &EndpointAttachDetachRequest{
SystemType: VirtualMachineType,
}
response := &EndpointResquestResponse{}
jsonString, err := json.Marshal(requestMessage)
if err != nil {
return err
}
return hnsCall("POST", "/endpoints/"+endpoint.Id+"/detach", string(jsonString), &response)
return hns.GetHNSEndpointByName(endpointName)
}

16
vendor/github.com/Microsoft/hcsshim/hnsglobals.go generated vendored Normal file
View File

@ -0,0 +1,16 @@
package hcsshim
import (
"github.com/Microsoft/hcsshim/internal/hns"
)
type HNSGlobals = hns.HNSGlobals
type HNSVersion = hns.HNSVersion
var (
HNSVersion1803 = hns.HNSVersion1803
)
func GetHNSGlobals() (*HNSGlobals, error) {
return hns.GetHNSGlobals()
}

View File

@ -1,141 +1,36 @@
package hcsshim
import (
"encoding/json"
"net"
"github.com/sirupsen/logrus"
"github.com/Microsoft/hcsshim/internal/hns"
)
// Subnet is assoicated with a network and represents a list
// of subnets available to the network
type Subnet struct {
AddressPrefix string `json:",omitempty"`
GatewayAddress string `json:",omitempty"`
Policies []json.RawMessage `json:",omitempty"`
}
type Subnet = hns.Subnet
// MacPool is assoicated with a network and represents a list
// of macaddresses available to the network
type MacPool struct {
StartMacAddress string `json:",omitempty"`
EndMacAddress string `json:",omitempty"`
}
type MacPool = hns.MacPool
// HNSNetwork represents a network in HNS
type HNSNetwork struct {
Id string `json:"ID,omitempty"`
Name string `json:",omitempty"`
Type string `json:",omitempty"`
NetworkAdapterName string `json:",omitempty"`
SourceMac string `json:",omitempty"`
Policies []json.RawMessage `json:",omitempty"`
MacPools []MacPool `json:",omitempty"`
Subnets []Subnet `json:",omitempty"`
DNSSuffix string `json:",omitempty"`
DNSServerList string `json:",omitempty"`
DNSServerCompartment uint32 `json:",omitempty"`
ManagementIP string `json:",omitempty"`
AutomaticDNS bool `json:",omitempty"`
}
type hnsNetworkResponse struct {
Success bool
Error string
Output HNSNetwork
}
type hnsResponse struct {
Success bool
Error string
Output json.RawMessage
}
type HNSNetwork = hns.HNSNetwork
// HNSNetworkRequest makes a call into HNS to update/query a single network
func HNSNetworkRequest(method, path, request string) (*HNSNetwork, error) {
var network HNSNetwork
err := hnsCall(method, "/networks/"+path, request, &network)
if err != nil {
return nil, err
}
return &network, nil
return hns.HNSNetworkRequest(method, path, request)
}
// HNSListNetworkRequest makes a HNS call to query the list of available networks
func HNSListNetworkRequest(method, path, request string) ([]HNSNetwork, error) {
var network []HNSNetwork
err := hnsCall(method, "/networks/"+path, request, &network)
if err != nil {
return nil, err
}
return network, nil
return hns.HNSListNetworkRequest(method, path, request)
}
// GetHNSNetworkByID
func GetHNSNetworkByID(networkID string) (*HNSNetwork, error) {
return HNSNetworkRequest("GET", networkID, "")
return hns.GetHNSNetworkByID(networkID)
}
// GetHNSNetworkName filtered by Name
func GetHNSNetworkByName(networkName string) (*HNSNetwork, error) {
hsnnetworks, err := HNSListNetworkRequest("GET", "", "")
if err != nil {
return nil, err
}
for _, hnsnetwork := range hsnnetworks {
if hnsnetwork.Name == networkName {
return &hnsnetwork, nil
}
}
return nil, NetworkNotFoundError{NetworkName: networkName}
}
// Create Network by sending NetworkRequest to HNS.
func (network *HNSNetwork) Create() (*HNSNetwork, error) {
operation := "Create"
title := "HCSShim::HNSNetwork::" + operation
logrus.Debugf(title+" id=%s", network.Id)
jsonString, err := json.Marshal(network)
if err != nil {
return nil, err
}
return HNSNetworkRequest("POST", "", string(jsonString))
}
// Delete Network by sending NetworkRequest to HNS
func (network *HNSNetwork) Delete() (*HNSNetwork, error) {
operation := "Delete"
title := "HCSShim::HNSNetwork::" + operation
logrus.Debugf(title+" id=%s", network.Id)
return HNSNetworkRequest("DELETE", network.Id, "")
}
// Creates an endpoint on the Network.
func (network *HNSNetwork) NewEndpoint(ipAddress net.IP, macAddress net.HardwareAddr) *HNSEndpoint {
return &HNSEndpoint{
VirtualNetwork: network.Id,
IPAddress: ipAddress,
MacAddress: string(macAddress),
}
}
func (network *HNSNetwork) CreateEndpoint(endpoint *HNSEndpoint) (*HNSEndpoint, error) {
operation := "CreateEndpoint"
title := "HCSShim::HNSNetwork::" + operation
logrus.Debugf(title+" id=%s, endpointId=%s", network.Id, endpoint.Id)
endpoint.VirtualNetwork = network.Id
return endpoint.Create()
}
func (network *HNSNetwork) CreateRemoteEndpoint(endpoint *HNSEndpoint) (*HNSEndpoint, error) {
operation := "CreateRemoteEndpoint"
title := "HCSShim::HNSNetwork::" + operation
logrus.Debugf(title+" id=%s", network.Id)
endpoint.IsRemoteEndpoint = true
return network.CreateEndpoint(endpoint)
return hns.GetHNSNetworkByName(networkName)
}

View File

@ -1,94 +1,57 @@
package hcsshim
import (
"github.com/Microsoft/hcsshim/internal/hns"
)
// Type of Request Support in ModifySystem
type PolicyType string
type PolicyType = hns.PolicyType
// RequestType const
const (
Nat PolicyType = "NAT"
ACL PolicyType = "ACL"
PA PolicyType = "PA"
VLAN PolicyType = "VLAN"
VSID PolicyType = "VSID"
VNet PolicyType = "VNET"
L2Driver PolicyType = "L2Driver"
Isolation PolicyType = "Isolation"
QOS PolicyType = "QOS"
OutboundNat PolicyType = "OutBoundNAT"
ExternalLoadBalancer PolicyType = "ELB"
Route PolicyType = "ROUTE"
Nat = hns.Nat
ACL = hns.ACL
PA = hns.PA
VLAN = hns.VLAN
VSID = hns.VSID
VNet = hns.VNet
L2Driver = hns.L2Driver
Isolation = hns.Isolation
QOS = hns.QOS
OutboundNat = hns.OutboundNat
ExternalLoadBalancer = hns.ExternalLoadBalancer
Route = hns.Route
)
type NatPolicy struct {
Type PolicyType `json:"Type"`
Protocol string
InternalPort uint16
ExternalPort uint16
}
type NatPolicy = hns.NatPolicy
type QosPolicy struct {
Type PolicyType `json:"Type"`
MaximumOutgoingBandwidthInBytes uint64
}
type QosPolicy = hns.QosPolicy
type IsolationPolicy struct {
Type PolicyType `json:"Type"`
VLAN uint
VSID uint
InDefaultIsolation bool
}
type IsolationPolicy = hns.IsolationPolicy
type VlanPolicy struct {
Type PolicyType `json:"Type"`
VLAN uint
}
type VlanPolicy = hns.VlanPolicy
type VsidPolicy struct {
Type PolicyType `json:"Type"`
VSID uint
}
type VsidPolicy = hns.VsidPolicy
type PaPolicy struct {
Type PolicyType `json:"Type"`
PA string `json:"PA"`
}
type PaPolicy = hns.PaPolicy
type OutboundNatPolicy struct {
Policy
VIP string `json:"VIP,omitempty"`
Exceptions []string `json:"ExceptionList,omitempty"`
}
type OutboundNatPolicy = hns.OutboundNatPolicy
type ActionType string
type DirectionType string
type RuleType string
type ActionType = hns.ActionType
type DirectionType = hns.DirectionType
type RuleType = hns.RuleType
const (
Allow ActionType = "Allow"
Block ActionType = "Block"
Allow = hns.Allow
Block = hns.Block
In DirectionType = "In"
Out DirectionType = "Out"
In = hns.In
Out = hns.Out
Host RuleType = "Host"
Switch RuleType = "Switch"
Host = hns.Host
Switch = hns.Switch
)
type ACLPolicy struct {
Type PolicyType `json:"Type"`
Protocol uint16
InternalPort uint16
Action ActionType
Direction DirectionType
LocalAddresses string
RemoteAddresses string
LocalPort uint16
RemotePort uint16
RuleType RuleType `json:"RuleType,omitempty"`
Priority uint16
ServiceName string
}
type ACLPolicy = hns.ACLPolicy
type Policy struct {
Type PolicyType `json:"Type"`
}
type Policy = hns.Policy

View File

@ -1,200 +1,47 @@
package hcsshim
import (
"encoding/json"
"github.com/sirupsen/logrus"
"github.com/Microsoft/hcsshim/internal/hns"
)
// RoutePolicy is a structure defining schema for Route based Policy
type RoutePolicy struct {
Policy
DestinationPrefix string `json:"DestinationPrefix,omitempty"`
NextHop string `json:"NextHop,omitempty"`
EncapEnabled bool `json:"NeedEncap,omitempty"`
}
type RoutePolicy = hns.RoutePolicy
// ELBPolicy is a structure defining schema for ELB LoadBalancing based Policy
type ELBPolicy struct {
LBPolicy
SourceVIP string `json:"SourceVIP,omitempty"`
VIPs []string `json:"VIPs,omitempty"`
ILB bool `json:"ILB,omitempty"`
}
type ELBPolicy = hns.ELBPolicy
// LBPolicy is a structure defining schema for LoadBalancing based Policy
type LBPolicy struct {
Policy
Protocol uint16 `json:"Protocol,omitempty"`
InternalPort uint16
ExternalPort uint16
}
type LBPolicy = hns.LBPolicy
// PolicyList is a structure defining schema for Policy list request
type PolicyList struct {
ID string `json:"ID,omitempty"`
EndpointReferences []string `json:"References,omitempty"`
Policies []json.RawMessage `json:"Policies,omitempty"`
}
type PolicyList = hns.PolicyList
// HNSPolicyListRequest makes a call into HNS to update/query a single network
func HNSPolicyListRequest(method, path, request string) (*PolicyList, error) {
var policy PolicyList
err := hnsCall(method, "/policylists/"+path, request, &policy)
if err != nil {
return nil, err
}
return &policy, nil
return hns.HNSPolicyListRequest(method, path, request)
}
// HNSListPolicyListRequest gets all the policy list
func HNSListPolicyListRequest() ([]PolicyList, error) {
var plist []PolicyList
err := hnsCall("GET", "/policylists/", "", &plist)
if err != nil {
return nil, err
}
return plist, nil
return hns.HNSListPolicyListRequest()
}
// PolicyListRequest makes a HNS call to modify/query a network policy list
func PolicyListRequest(method, path, request string) (*PolicyList, error) {
policylist := &PolicyList{}
err := hnsCall(method, "/policylists/"+path, request, &policylist)
if err != nil {
return nil, err
}
return policylist, nil
return hns.PolicyListRequest(method, path, request)
}
// GetPolicyListByID get the policy list by ID
func GetPolicyListByID(policyListID string) (*PolicyList, error) {
return PolicyListRequest("GET", policyListID, "")
}
// Create PolicyList by sending PolicyListRequest to HNS.
func (policylist *PolicyList) Create() (*PolicyList, error) {
operation := "Create"
title := "HCSShim::PolicyList::" + operation
logrus.Debugf(title+" id=%s", policylist.ID)
jsonString, err := json.Marshal(policylist)
if err != nil {
return nil, err
}
return PolicyListRequest("POST", "", string(jsonString))
}
// Delete deletes PolicyList
func (policylist *PolicyList) Delete() (*PolicyList, error) {
operation := "Delete"
title := "HCSShim::PolicyList::" + operation
logrus.Debugf(title+" id=%s", policylist.ID)
return PolicyListRequest("DELETE", policylist.ID, "")
}
// AddEndpoint add an endpoint to a Policy List
func (policylist *PolicyList) AddEndpoint(endpoint *HNSEndpoint) (*PolicyList, error) {
operation := "AddEndpoint"
title := "HCSShim::PolicyList::" + operation
logrus.Debugf(title+" id=%s, endpointId:%s", policylist.ID, endpoint.Id)
_, err := policylist.Delete()
if err != nil {
return nil, err
}
// Add Endpoint to the Existing List
policylist.EndpointReferences = append(policylist.EndpointReferences, "/endpoints/"+endpoint.Id)
return policylist.Create()
}
// RemoveEndpoint removes an endpoint from the Policy List
func (policylist *PolicyList) RemoveEndpoint(endpoint *HNSEndpoint) (*PolicyList, error) {
operation := "RemoveEndpoint"
title := "HCSShim::PolicyList::" + operation
logrus.Debugf(title+" id=%s, endpointId:%s", policylist.ID, endpoint.Id)
_, err := policylist.Delete()
if err != nil {
return nil, err
}
elementToRemove := "/endpoints/" + endpoint.Id
var references []string
for _, endpointReference := range policylist.EndpointReferences {
if endpointReference == elementToRemove {
continue
}
references = append(references, endpointReference)
}
policylist.EndpointReferences = references
return policylist.Create()
return hns.GetPolicyListByID(policyListID)
}
// AddLoadBalancer policy list for the specified endpoints
func AddLoadBalancer(endpoints []HNSEndpoint, isILB bool, sourceVIP, vip string, protocol uint16, internalPort uint16, externalPort uint16) (*PolicyList, error) {
operation := "AddLoadBalancer"
title := "HCSShim::PolicyList::" + operation
logrus.Debugf(title+" endpointId=%v, isILB=%v, sourceVIP=%s, vip=%s, protocol=%v, internalPort=%v, externalPort=%v", endpoints, isILB, sourceVIP, vip, protocol, internalPort, externalPort)
policylist := &PolicyList{}
elbPolicy := &ELBPolicy{
SourceVIP: sourceVIP,
ILB: isILB,
}
if len(vip) > 0 {
elbPolicy.VIPs = []string{vip}
}
elbPolicy.Type = ExternalLoadBalancer
elbPolicy.Protocol = protocol
elbPolicy.InternalPort = internalPort
elbPolicy.ExternalPort = externalPort
for _, endpoint := range endpoints {
policylist.EndpointReferences = append(policylist.EndpointReferences, "/endpoints/"+endpoint.Id)
}
jsonString, err := json.Marshal(elbPolicy)
if err != nil {
return nil, err
}
policylist.Policies = append(policylist.Policies, jsonString)
return policylist.Create()
return hns.AddLoadBalancer(endpoints, isILB, sourceVIP, vip, protocol, internalPort, externalPort)
}
// AddRoute adds route policy list for the specified endpoints
func AddRoute(endpoints []HNSEndpoint, destinationPrefix string, nextHop string, encapEnabled bool) (*PolicyList, error) {
operation := "AddRoute"
title := "HCSShim::PolicyList::" + operation
logrus.Debugf(title+" destinationPrefix:%s", destinationPrefix)
policylist := &PolicyList{}
rPolicy := &RoutePolicy{
DestinationPrefix: destinationPrefix,
NextHop: nextHop,
EncapEnabled: encapEnabled,
}
rPolicy.Type = Route
for _, endpoint := range endpoints {
policylist.EndpointReferences = append(policylist.EndpointReferences, "/endpoints/"+endpoint.Id)
}
jsonString, err := json.Marshal(rPolicy)
if err != nil {
return nil, err
}
policylist.Policies = append(policylist.Policies, jsonString)
return policylist.Create()
return hns.AddRoute(endpoints, destinationPrefix, nextHop, encapEnabled)
}

13
vendor/github.com/Microsoft/hcsshim/hnssupport.go generated vendored Normal file
View File

@ -0,0 +1,13 @@
package hcsshim
import (
"github.com/Microsoft/hcsshim/internal/hns"
)
type HNSSupportedFeatures = hns.HNSSupportedFeatures
type HNSAclFeatures = hns.HNSAclFeatures
func GetHNSSupportedFeatures() HNSSupportedFeatures {
return hns.GetHNSSupportedFeatures()
}

View File

@ -1,222 +0,0 @@
package hcsshim
import (
"errors"
"io/ioutil"
"os"
"path/filepath"
"github.com/Microsoft/go-winio"
"github.com/sirupsen/logrus"
)
// ImportLayer will take the contents of the folder at importFolderPath and import
// that into a layer with the id layerId. Note that in order to correctly populate
// the layer and interperet the transport format, all parent layers must already
// be present on the system at the paths provided in parentLayerPaths.
func ImportLayer(info DriverInfo, layerID string, importFolderPath string, parentLayerPaths []string) error {
title := "hcsshim::ImportLayer "
logrus.Debugf(title+"flavour %d layerId %s folder %s", info.Flavour, layerID, importFolderPath)
// Generate layer descriptors
layers, err := layerPathsToDescriptors(parentLayerPaths)
if err != nil {
return err
}
// Convert info to API calling convention
infop, err := convertDriverInfo(info)
if err != nil {
logrus.Error(err)
return err
}
err = importLayer(&infop, layerID, importFolderPath, layers)
if err != nil {
err = makeErrorf(err, title, "layerId=%s flavour=%d folder=%s", layerID, info.Flavour, importFolderPath)
logrus.Error(err)
return err
}
logrus.Debugf(title+"succeeded flavour=%d layerId=%s folder=%s", info.Flavour, layerID, importFolderPath)
return nil
}
// LayerWriter is an interface that supports writing a new container image layer.
type LayerWriter interface {
// Add adds a file to the layer with given metadata.
Add(name string, fileInfo *winio.FileBasicInfo) error
// AddLink adds a hard link to the layer. The target must already have been added.
AddLink(name string, target string) error
// Remove removes a file that was present in a parent layer from the layer.
Remove(name string) error
// Write writes data to the current file. The data must be in the format of a Win32
// backup stream.
Write(b []byte) (int, error)
// Close finishes the layer writing process and releases any resources.
Close() error
}
// FilterLayerWriter provides an interface to write the contents of a layer to the file system.
type FilterLayerWriter struct {
context uintptr
}
// Add adds a file or directory to the layer. The file's parent directory must have already been added.
//
// name contains the file's relative path. fileInfo contains file times and file attributes; the rest
// of the file metadata and the file data must be written as a Win32 backup stream to the Write() method.
// winio.BackupStreamWriter can be used to facilitate this.
func (w *FilterLayerWriter) Add(name string, fileInfo *winio.FileBasicInfo) error {
if name[0] != '\\' {
name = `\` + name
}
err := importLayerNext(w.context, name, fileInfo)
if err != nil {
return makeError(err, "ImportLayerNext", "")
}
return nil
}
// AddLink adds a hard link to the layer. The target of the link must have already been added.
func (w *FilterLayerWriter) AddLink(name string, target string) error {
return errors.New("hard links not yet supported")
}
// Remove removes a file from the layer. The file must have been present in the parent layer.
//
// name contains the file's relative path.
func (w *FilterLayerWriter) Remove(name string) error {
if name[0] != '\\' {
name = `\` + name
}
err := importLayerNext(w.context, name, nil)
if err != nil {
return makeError(err, "ImportLayerNext", "")
}
return nil
}
// Write writes more backup stream data to the current file.
func (w *FilterLayerWriter) Write(b []byte) (int, error) {
err := importLayerWrite(w.context, b)
if err != nil {
err = makeError(err, "ImportLayerWrite", "")
return 0, err
}
return len(b), err
}
// Close completes the layer write operation. The error must be checked to ensure that the
// operation was successful.
func (w *FilterLayerWriter) Close() (err error) {
if w.context != 0 {
err = importLayerEnd(w.context)
if err != nil {
err = makeError(err, "ImportLayerEnd", "")
}
w.context = 0
}
return
}
type legacyLayerWriterWrapper struct {
*legacyLayerWriter
info DriverInfo
layerID string
path string
parentLayerPaths []string
}
func (r *legacyLayerWriterWrapper) Close() error {
defer os.RemoveAll(r.root.Name())
defer r.legacyLayerWriter.CloseRoots()
err := r.legacyLayerWriter.Close()
if err != nil {
return err
}
info := r.info
info.HomeDir = ""
if err = ImportLayer(info, r.destRoot.Name(), r.path, r.parentLayerPaths); err != nil {
return err
}
for _, name := range r.Tombstones {
if err = removeRelative(name, r.destRoot); err != nil && !os.IsNotExist(err) {
return err
}
}
// Add any hard links that were collected.
for _, lnk := range r.PendingLinks {
if err = removeRelative(lnk.Path, r.destRoot); err != nil && !os.IsNotExist(err) {
return err
}
if err = linkRelative(lnk.Target, lnk.TargetRoot, lnk.Path, r.destRoot); err != nil {
return err
}
}
// Prepare the utility VM for use if one is present in the layer.
if r.HasUtilityVM {
err := ensureNotReparsePointRelative("UtilityVM", r.destRoot)
if err != nil {
return err
}
err = ProcessUtilityVMImage(filepath.Join(r.destRoot.Name(), "UtilityVM"))
if err != nil {
return err
}
}
return nil
}
// NewLayerWriter returns a new layer writer for creating a layer on disk.
// The caller must have taken the SeBackupPrivilege and SeRestorePrivilege privileges
// to call this and any methods on the resulting LayerWriter.
func NewLayerWriter(info DriverInfo, layerID string, parentLayerPaths []string) (LayerWriter, error) {
if len(parentLayerPaths) == 0 {
// This is a base layer. It gets imported differently.
f, err := openRoot(filepath.Join(info.HomeDir, layerID))
if err != nil {
return nil, err
}
return &baseLayerWriter{
root: f,
}, nil
}
if procImportLayerBegin.Find() != nil {
// The new layer reader is not available on this Windows build. Fall back to the
// legacy export code path.
path, err := ioutil.TempDir("", "hcs")
if err != nil {
return nil, err
}
w, err := newLegacyLayerWriter(path, parentLayerPaths, filepath.Join(info.HomeDir, layerID))
if err != nil {
return nil, err
}
return &legacyLayerWriterWrapper{
legacyLayerWriter: w,
info: info,
layerID: layerID,
path: path,
parentLayerPaths: parentLayerPaths,
}, nil
}
layers, err := layerPathsToDescriptors(parentLayerPaths)
if err != nil {
return nil, err
}
infop, err := convertDriverInfo(info)
if err != nil {
return nil, err
}
w := &FilterLayerWriter{}
err = importLayerBegin(&infop, layerID, layers, &w.context)
if err != nil {
return nil, makeError(err, "ImportLayerStart", "")
}
return w, nil
}

View File

@ -1,106 +1,32 @@
package hcsshim
import (
"encoding/json"
"io"
"time"
"github.com/Microsoft/hcsshim/internal/schema1"
)
// ProcessConfig is used as both the input of Container.CreateProcess
// and to convert the parameters to JSON for passing onto the HCS
type ProcessConfig struct {
ApplicationName string `json:",omitempty"`
CommandLine string `json:",omitempty"`
CommandArgs []string `json:",omitempty"` // Used by Linux Containers on Windows
User string `json:",omitempty"`
WorkingDirectory string `json:",omitempty"`
Environment map[string]string `json:",omitempty"`
EmulateConsole bool `json:",omitempty"`
CreateStdInPipe bool `json:",omitempty"`
CreateStdOutPipe bool `json:",omitempty"`
CreateStdErrPipe bool `json:",omitempty"`
ConsoleSize [2]uint `json:",omitempty"`
CreateInUtilityVm bool `json:",omitempty"` // Used by Linux Containers on Windows
OCISpecification *json.RawMessage `json:",omitempty"` // Used by Linux Containers on Windows
}
type ProcessConfig = schema1.ProcessConfig
type Layer struct {
ID string
Path string
}
type Layer = schema1.Layer
type MappedDir = schema1.MappedDir
type MappedPipe = schema1.MappedPipe
type HvRuntime = schema1.HvRuntime
type MappedVirtualDisk = schema1.MappedVirtualDisk
type MappedDir struct {
HostPath string
ContainerPath string
ReadOnly bool
BandwidthMaximum uint64
IOPSMaximum uint64
CreateInUtilityVM bool
}
type MappedPipe struct {
HostPath string
ContainerPipeName string
}
type HvRuntime struct {
ImagePath string `json:",omitempty"`
SkipTemplate bool `json:",omitempty"`
LinuxInitrdFile string `json:",omitempty"` // File under ImagePath on host containing an initrd image for starting a Linux utility VM
LinuxKernelFile string `json:",omitempty"` // File under ImagePath on host containing a kernel for starting a Linux utility VM
LinuxBootParameters string `json:",omitempty"` // Additional boot parameters for starting a Linux Utility VM in initrd mode
BootSource string `json:",omitempty"` // "Vhd" for Linux Utility VM booting from VHD
WritableBootSource bool `json:",omitempty"` // Linux Utility VM booting from VHD
}
type MappedVirtualDisk struct {
HostPath string `json:",omitempty"` // Path to VHD on the host
ContainerPath string // Platform-specific mount point path in the container
CreateInUtilityVM bool `json:",omitempty"`
ReadOnly bool `json:",omitempty"`
Cache string `json:",omitempty"` // "" (Unspecified); "Disabled"; "Enabled"; "Private"; "PrivateAllowSharing"
AttachOnly bool `json:",omitempty:`
}
// AssignedDevice represents a device that has been directly assigned to a container
//
// NOTE: Support added in RS5
type AssignedDevice = schema1.AssignedDevice
// ContainerConfig is used as both the input of CreateContainer
// and to convert the parameters to JSON for passing onto the HCS
type ContainerConfig struct {
SystemType string // HCS requires this to be hard-coded to "Container"
Name string // Name of the container. We use the docker ID.
Owner string `json:",omitempty"` // The management platform that created this container
VolumePath string `json:",omitempty"` // Windows volume path for scratch space. Used by Windows Server Containers only. Format \\?\\Volume{GUID}
IgnoreFlushesDuringBoot bool `json:",omitempty"` // Optimization hint for container startup in Windows
LayerFolderPath string `json:",omitempty"` // Where the layer folders are located. Used by Windows Server Containers only. Format %root%\windowsfilter\containerID
Layers []Layer // List of storage layers. Required for Windows Server and Hyper-V Containers. Format ID=GUID;Path=%root%\windowsfilter\layerID
Credentials string `json:",omitempty"` // Credentials information
ProcessorCount uint32 `json:",omitempty"` // Number of processors to assign to the container.
ProcessorWeight uint64 `json:",omitempty"` // CPU shares (relative weight to other containers with cpu shares). Range is from 1 to 10000. A value of 0 results in default shares.
ProcessorMaximum int64 `json:",omitempty"` // Specifies the portion of processor cycles that this container can use as a percentage times 100. Range is from 1 to 10000. A value of 0 results in no limit.
StorageIOPSMaximum uint64 `json:",omitempty"` // Maximum Storage IOPS
StorageBandwidthMaximum uint64 `json:",omitempty"` // Maximum Storage Bandwidth in bytes per second
StorageSandboxSize uint64 `json:",omitempty"` // Size in bytes that the container system drive should be expanded to if smaller
MemoryMaximumInMB int64 `json:",omitempty"` // Maximum memory available to the container in Megabytes
HostName string `json:",omitempty"` // Hostname
MappedDirectories []MappedDir `json:",omitempty"` // List of mapped directories (volumes/mounts)
MappedPipes []MappedPipe `json:",omitempty"` // List of mapped Windows named pipes
HvPartition bool // True if it a Hyper-V Container
NetworkSharedContainerName string `json:",omitempty"` // Name (ID) of the container that we will share the network stack with.
EndpointList []string `json:",omitempty"` // List of networking endpoints to be attached to container
HvRuntime *HvRuntime `json:",omitempty"` // Hyper-V container settings. Used by Hyper-V containers only. Format ImagePath=%root%\BaseLayerID\UtilityVM
Servicing bool `json:",omitempty"` // True if this container is for servicing
AllowUnqualifiedDNSQuery bool `json:",omitempty"` // True to allow unqualified DNS name resolution
DNSSearchList string `json:",omitempty"` // Comma seperated list of DNS suffixes to use for name resolution
ContainerType string `json:",omitempty"` // "Linux" for Linux containers on Windows. Omitted otherwise.
TerminateOnLastHandleClosed bool `json:",omitempty"` // Should HCS terminate the container once all handles have been closed
MappedVirtualDisks []MappedVirtualDisk `json:",omitempty"` // Array of virtual disks to mount at start
}
type ContainerConfig = schema1.ContainerConfig
type ComputeSystemQuery struct {
IDs []string `json:"Ids,omitempty"`
Types []string `json:",omitempty"`
Names []string `json:",omitempty"`
Owners []string `json:",omitempty"`
}
type ComputeSystemQuery = schema1.ComputeSystemQuery
// Container represents a created (but not necessarily running) container.
type Container interface {

27
vendor/github.com/Microsoft/hcsshim/internal/cni/BUILD generated vendored Normal file
View File

@ -0,0 +1,27 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["registry.go"],
importmap = "k8s.io/kubernetes/vendor/github.com/Microsoft/hcsshim/internal/cni",
importpath = "github.com/Microsoft/hcsshim/internal/cni",
visibility = ["//vendor/github.com/Microsoft/hcsshim:__subpackages__"],
deps = [
"//vendor/github.com/Microsoft/hcsshim/internal/guid:go_default_library",
"//vendor/github.com/Microsoft/hcsshim/internal/regstate:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -0,0 +1,110 @@
package cni
import (
"errors"
"github.com/Microsoft/hcsshim/internal/guid"
"github.com/Microsoft/hcsshim/internal/regstate"
)
const (
cniRoot = "cni"
cniKey = "cfg"
)
// PersistedNamespaceConfig is the registry version of the `NamespaceID` to UVM
// map.
type PersistedNamespaceConfig struct {
namespaceID string
stored bool
ContainerID string
HostUniqueID guid.GUID
}
// NewPersistedNamespaceConfig creates an in-memory namespace config that can be
// persisted to the registry.
func NewPersistedNamespaceConfig(namespaceID, containerID string, containerHostUniqueID guid.GUID) *PersistedNamespaceConfig {
return &PersistedNamespaceConfig{
namespaceID: namespaceID,
ContainerID: containerID,
HostUniqueID: containerHostUniqueID,
}
}
// LoadPersistedNamespaceConfig loads a persisted config from the registry that matches
// `namespaceID`. If not found returns `regstate.NotFoundError`
func LoadPersistedNamespaceConfig(namespaceID string) (*PersistedNamespaceConfig, error) {
sk, err := regstate.Open(cniRoot, false)
if err != nil {
return nil, err
}
defer sk.Close()
pnc := PersistedNamespaceConfig{
namespaceID: namespaceID,
stored: true,
}
if err := sk.Get(namespaceID, cniKey, &pnc); err != nil {
return nil, err
}
return &pnc, nil
}
// Store stores or updates the in-memory config to its registry state. If the
// store failes returns the store error.
func (pnc *PersistedNamespaceConfig) Store() error {
if pnc.namespaceID == "" {
return errors.New("invalid namespaceID ''")
}
if pnc.ContainerID == "" {
return errors.New("invalid containerID ''")
}
empty := guid.GUID{}
if pnc.HostUniqueID == empty {
return errors.New("invalid containerHostUniqueID 'empy'")
}
sk, err := regstate.Open(cniRoot, false)
if err != nil {
return err
}
defer sk.Close()
if pnc.stored {
if err := sk.Set(pnc.namespaceID, cniKey, pnc); err != nil {
return err
}
} else {
if err := sk.Create(pnc.namespaceID, cniKey, pnc); err != nil {
return err
}
}
pnc.stored = true
return nil
}
// Remove removes any persisted state associated with this config. If the config
// is not found in the registery `Remove` returns no error.
func (pnc *PersistedNamespaceConfig) Remove() error {
if pnc.stored {
sk, err := regstate.Open(cniRoot, false)
if err != nil {
if regstate.IsNotFoundError(err) {
pnc.stored = false
return nil
}
return err
}
defer sk.Close()
if err := sk.Remove(pnc.namespaceID); err != nil {
if regstate.IsNotFoundError(err) {
pnc.stored = false
return nil
}
return err
}
}
pnc.stored = false
return nil
}

View File

@ -0,0 +1,24 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["types.go"],
importmap = "k8s.io/kubernetes/vendor/github.com/Microsoft/hcsshim/internal/guestrequest",
importpath = "github.com/Microsoft/hcsshim/internal/guestrequest",
visibility = ["//vendor/github.com/Microsoft/hcsshim:__subpackages__"],
deps = ["//vendor/github.com/Microsoft/hcsshim/internal/schema2:go_default_library"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -0,0 +1,100 @@
package guestrequest
import (
"github.com/Microsoft/hcsshim/internal/schema2"
)
// Arguably, many of these (at least CombinedLayers) should have been generated
// by swagger.
//
// This will also change package name due to an inbound breaking change.
// This class is used by a modify request to add or remove a combined layers
// structure in the guest. For windows, the GCS applies a filter in ContainerRootPath
// using the specified layers as the parent content. Ignores property ScratchPath
// since the container path is already the scratch path. For linux, the GCS unions
// the specified layers and ScratchPath together, placing the resulting union
// filesystem at ContainerRootPath.
type CombinedLayers struct {
ContainerRootPath string `json:"ContainerRootPath,omitempty"`
Layers []hcsschema.Layer `json:"Layers,omitempty"`
ScratchPath string `json:"ScratchPath,omitempty"`
}
// Defines the schema for hosted settings passed to GCS and/or OpenGCS
// SCSI. Scratch space for remote file-system commands, or R/W layer for containers
type LCOWMappedVirtualDisk struct {
MountPath string `json:"MountPath,omitempty"` // /tmp/scratch for an LCOW utility VM being used as a service VM
Lun uint8 `json:"Lun,omitempty"`
Controller uint8 `json:"Controller,omitempty"`
ReadOnly bool `json:"ReadOnly,omitempty"`
}
type WCOWMappedVirtualDisk struct {
ContainerPath string `json:"ContainerPath,omitempty"`
Lun int32 `json:"Lun,omitempty"`
}
type LCOWMappedDirectory struct {
MountPath string `json:"MountPath,omitempty"`
Port int32 `json:"Port,omitempty"`
ShareName string `json:"ShareName,omitempty"` // If empty not using ANames (not currently supported)
ReadOnly bool `json:"ReadOnly,omitempty"`
}
// Read-only layers over VPMem
type LCOWMappedVPMemDevice struct {
DeviceNumber uint32 `json:"DeviceNumber,omitempty"`
MountPath string `json:"MountPath,omitempty"` // /tmp/pN
}
type LCOWNetworkAdapter struct {
NamespaceID string `json:",omitempty"`
ID string `json:",omitempty"`
MacAddress string `json:",omitempty"`
IPAddress string `json:",omitempty"`
PrefixLength uint8 `json:",omitempty"`
GatewayAddress string `json:",omitempty"`
DNSSuffix string `json:",omitempty"`
DNSServerList string `json:",omitempty"`
EnableLowMetric bool `json:",omitempty"`
EncapOverhead uint16 `json:",omitempty"`
}
type ResourceType string
const (
// These are constants for v2 schema modify guest requests.
ResourceTypeMappedDirectory ResourceType = "MappedDirectory"
ResourceTypeMappedVirtualDisk ResourceType = "MappedVirtualDisk"
ResourceTypeNetwork ResourceType = "Network"
ResourceTypeNetworkNamespace ResourceType = "NetworkNamespace"
ResourceTypeCombinedLayers ResourceType = "CombinedLayers"
ResourceTypeVPMemDevice ResourceType = "VPMemDevice"
)
// GuestRequest is for modify commands passed to the guest.
type GuestRequest struct {
RequestType string `json:"RequestType,omitempty"`
ResourceType ResourceType `json:"ResourceType,omitempty"`
Settings interface{} `json:"Settings,omitempty"`
}
type NetworkModifyRequest struct {
AdapterId string `json:"AdapterId,omitempty"`
RequestType string `json:"RequestType,omitempty"`
Settings interface{} `json:"Settings,omitempty"`
}
type RS4NetworkModifyRequest struct {
AdapterInstanceId string `json:"AdapterInstanceId,omitempty"`
RequestType string `json:"RequestType,omitempty"`
Settings interface{} `json:"Settings,omitempty"`
}
// SignalProcessOptions is the options passed to either WCOW or LCOW
// to signal a given process.
type SignalProcessOptions struct {
Signal int `json:,omitempty`
}

View File

@ -0,0 +1,23 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["guid.go"],
importmap = "k8s.io/kubernetes/vendor/github.com/Microsoft/hcsshim/internal/guid",
importpath = "github.com/Microsoft/hcsshim/internal/guid",
visibility = ["//vendor/github.com/Microsoft/hcsshim:__subpackages__"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -0,0 +1,69 @@
package guid
import (
"crypto/rand"
"encoding/json"
"fmt"
"io"
"strconv"
"strings"
)
var _ = (json.Marshaler)(&GUID{})
var _ = (json.Unmarshaler)(&GUID{})
type GUID [16]byte
func New() GUID {
g := GUID{}
_, err := io.ReadFull(rand.Reader, g[:])
if err != nil {
panic(err)
}
return g
}
func (g GUID) String() string {
return fmt.Sprintf("%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x-%02x", g[3], g[2], g[1], g[0], g[5], g[4], g[7], g[6], g[8:10], g[10:])
}
func FromString(s string) GUID {
if len(s) != 36 {
panic(fmt.Sprintf("invalid GUID length: %d", len(s)))
}
if s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-' {
panic("invalid GUID format")
}
indexOrder := [16]int{
0, 2, 4, 6,
9, 11,
14, 16,
19, 21,
24, 26, 28, 30, 32, 34,
}
byteOrder := [16]int{
3, 2, 1, 0,
5, 4,
7, 6,
8, 9,
10, 11, 12, 13, 14, 15,
}
var g GUID
for i, x := range indexOrder {
b, err := strconv.ParseInt(s[x:x+2], 16, 16)
if err != nil {
panic(err)
}
g[byteOrder[i]] = byte(b)
}
return g
}
func (g GUID) MarshalJSON() ([]byte, error) {
return json.Marshal(g.String())
}
func (g *GUID) UnmarshalJSON(data []byte) error {
*g = FromString(strings.Trim(string(data), "\""))
return nil
}

50
vendor/github.com/Microsoft/hcsshim/internal/hcs/BUILD generated vendored Normal file
View File

@ -0,0 +1,50 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = [
"callback.go",
"cgo.go",
"errors.go",
"hcs.go",
"log.go",
"process.go",
"system.go",
"utils.go",
"waithelper.go",
"watcher.go",
"zsyscall_windows.go",
],
cgo = True,
importmap = "k8s.io/kubernetes/vendor/github.com/Microsoft/hcsshim/internal/hcs",
importpath = "github.com/Microsoft/hcsshim/internal/hcs",
visibility = ["//vendor/github.com/Microsoft/hcsshim:__subpackages__"],
deps = [
"//vendor/github.com/Microsoft/go-winio:go_default_library",
"//vendor/github.com/Microsoft/hcsshim/internal/guestrequest:go_default_library",
"//vendor/github.com/Microsoft/hcsshim/internal/interop:go_default_library",
"//vendor/github.com/Microsoft/hcsshim/internal/logfields:go_default_library",
"//vendor/github.com/Microsoft/hcsshim/internal/schema1:go_default_library",
"//vendor/github.com/Microsoft/hcsshim/internal/timeout:go_default_library",
"//vendor/github.com/sirupsen/logrus:go_default_library",
] + select({
"@io_bazel_rules_go//go/platform:windows": [
"//vendor/golang.org/x/sys/windows:go_default_library",
],
"//conditions:default": [],
}),
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -0,0 +1,104 @@
package hcs
import (
"sync"
"syscall"
"github.com/Microsoft/hcsshim/internal/interop"
"github.com/sirupsen/logrus"
)
var (
nextCallback uintptr
callbackMap = map[uintptr]*notifcationWatcherContext{}
callbackMapLock = sync.RWMutex{}
notificationWatcherCallback = syscall.NewCallback(notificationWatcher)
// Notifications for HCS_SYSTEM handles
hcsNotificationSystemExited hcsNotification = 0x00000001
hcsNotificationSystemCreateCompleted hcsNotification = 0x00000002
hcsNotificationSystemStartCompleted hcsNotification = 0x00000003
hcsNotificationSystemPauseCompleted hcsNotification = 0x00000004
hcsNotificationSystemResumeCompleted hcsNotification = 0x00000005
hcsNotificationSystemCrashReport hcsNotification = 0x00000006
hcsNotificationSystemSiloJobCreated hcsNotification = 0x00000007
hcsNotificationSystemSaveCompleted hcsNotification = 0x00000008
hcsNotificationSystemRdpEnhancedModeStateChanged hcsNotification = 0x00000009
hcsNotificationSystemShutdownFailed hcsNotification = 0x0000000A
hcsNotificationSystemGetPropertiesCompleted hcsNotification = 0x0000000B
hcsNotificationSystemModifyCompleted hcsNotification = 0x0000000C
hcsNotificationSystemCrashInitiated hcsNotification = 0x0000000D
hcsNotificationSystemGuestConnectionClosed hcsNotification = 0x0000000E
// Notifications for HCS_PROCESS handles
hcsNotificationProcessExited hcsNotification = 0x00010000
// Common notifications
hcsNotificationInvalid hcsNotification = 0x00000000
hcsNotificationServiceDisconnect hcsNotification = 0x01000000
)
type hcsNotification uint32
type notificationChannel chan error
type notifcationWatcherContext struct {
channels notificationChannels
handle hcsCallback
}
type notificationChannels map[hcsNotification]notificationChannel
func newChannels() notificationChannels {
channels := make(notificationChannels)
channels[hcsNotificationSystemExited] = make(notificationChannel, 1)
channels[hcsNotificationSystemCreateCompleted] = make(notificationChannel, 1)
channels[hcsNotificationSystemStartCompleted] = make(notificationChannel, 1)
channels[hcsNotificationSystemPauseCompleted] = make(notificationChannel, 1)
channels[hcsNotificationSystemResumeCompleted] = make(notificationChannel, 1)
channels[hcsNotificationProcessExited] = make(notificationChannel, 1)
channels[hcsNotificationServiceDisconnect] = make(notificationChannel, 1)
channels[hcsNotificationSystemCrashReport] = make(notificationChannel, 1)
channels[hcsNotificationSystemSiloJobCreated] = make(notificationChannel, 1)
channels[hcsNotificationSystemSaveCompleted] = make(notificationChannel, 1)
channels[hcsNotificationSystemRdpEnhancedModeStateChanged] = make(notificationChannel, 1)
channels[hcsNotificationSystemShutdownFailed] = make(notificationChannel, 1)
channels[hcsNotificationSystemGetPropertiesCompleted] = make(notificationChannel, 1)
channels[hcsNotificationSystemModifyCompleted] = make(notificationChannel, 1)
channels[hcsNotificationSystemCrashInitiated] = make(notificationChannel, 1)
channels[hcsNotificationSystemGuestConnectionClosed] = make(notificationChannel, 1)
return channels
}
func closeChannels(channels notificationChannels) {
for _, c := range channels {
close(c)
}
}
func notificationWatcher(notificationType hcsNotification, callbackNumber uintptr, notificationStatus uintptr, notificationData *uint16) uintptr {
var result error
if int32(notificationStatus) < 0 {
result = interop.Win32FromHresult(notificationStatus)
}
callbackMapLock.RLock()
context := callbackMap[callbackNumber]
callbackMapLock.RUnlock()
if context == nil {
return 0
}
if channel, ok := context.channels[notificationType]; ok {
channel <- result
} else {
logrus.WithFields(logrus.Fields{
"notification-type": notificationType,
}).Warn("Received a callback of an unsupported type")
}
return 0
}

View File

@ -1,4 +1,4 @@
package hcsshim
package hcs
import "C"

View File

@ -0,0 +1,287 @@
package hcs
import (
"encoding/json"
"errors"
"fmt"
"syscall"
"github.com/Microsoft/hcsshim/internal/interop"
"github.com/Microsoft/hcsshim/internal/logfields"
"github.com/sirupsen/logrus"
)
var (
// ErrComputeSystemDoesNotExist is an error encountered when the container being operated on no longer exists
ErrComputeSystemDoesNotExist = syscall.Errno(0xc037010e)
// ErrElementNotFound is an error encountered when the object being referenced does not exist
ErrElementNotFound = syscall.Errno(0x490)
// ErrElementNotFound is an error encountered when the object being referenced does not exist
ErrNotSupported = syscall.Errno(0x32)
// ErrInvalidData is an error encountered when the request being sent to hcs is invalid/unsupported
// decimal -2147024883 / hex 0x8007000d
ErrInvalidData = syscall.Errno(0xd)
// ErrHandleClose is an error encountered when the handle generating the notification being waited on has been closed
ErrHandleClose = errors.New("hcsshim: the handle generating this notification has been closed")
// ErrAlreadyClosed is an error encountered when using a handle that has been closed by the Close method
ErrAlreadyClosed = errors.New("hcsshim: the handle has already been closed")
// ErrInvalidNotificationType is an error encountered when an invalid notification type is used
ErrInvalidNotificationType = errors.New("hcsshim: invalid notification type")
// ErrInvalidProcessState is an error encountered when the process is not in a valid state for the requested operation
ErrInvalidProcessState = errors.New("the process is in an invalid state for the attempted operation")
// ErrTimeout is an error encountered when waiting on a notification times out
ErrTimeout = errors.New("hcsshim: timeout waiting for notification")
// ErrUnexpectedContainerExit is the error encountered when a container exits while waiting for
// a different expected notification
ErrUnexpectedContainerExit = errors.New("unexpected container exit")
// ErrUnexpectedProcessAbort is the error encountered when communication with the compute service
// is lost while waiting for a notification
ErrUnexpectedProcessAbort = errors.New("lost communication with compute service")
// ErrUnexpectedValue is an error encountered when hcs returns an invalid value
ErrUnexpectedValue = errors.New("unexpected value returned from hcs")
// ErrVmcomputeAlreadyStopped is an error encountered when a shutdown or terminate request is made on a stopped container
ErrVmcomputeAlreadyStopped = syscall.Errno(0xc0370110)
// ErrVmcomputeOperationPending is an error encountered when the operation is being completed asynchronously
ErrVmcomputeOperationPending = syscall.Errno(0xC0370103)
// ErrVmcomputeOperationInvalidState is an error encountered when the compute system is not in a valid state for the requested operation
ErrVmcomputeOperationInvalidState = syscall.Errno(0xc0370105)
// ErrProcNotFound is an error encountered when the the process cannot be found
ErrProcNotFound = syscall.Errno(0x7f)
// ErrVmcomputeOperationAccessIsDenied is an error which can be encountered when enumerating compute systems in RS1/RS2
// builds when the underlying silo might be in the process of terminating. HCS was fixed in RS3.
ErrVmcomputeOperationAccessIsDenied = syscall.Errno(0x5)
// ErrVmcomputeInvalidJSON is an error encountered when the compute system does not support/understand the messages sent by management
ErrVmcomputeInvalidJSON = syscall.Errno(0xc037010d)
// ErrVmcomputeUnknownMessage is an error encountered guest compute system doesn't support the message
ErrVmcomputeUnknownMessage = syscall.Errno(0xc037010b)
// ErrVmcomputeUnexpectedExit is an error encountered when the compute system terminates unexpectedly
ErrVmcomputeUnexpectedExit = syscall.Errno(0xC0370106)
// ErrNotSupported is an error encountered when hcs doesn't support the request
ErrPlatformNotSupported = errors.New("unsupported platform request")
)
type ErrorEvent struct {
Message string `json:"Message,omitempty"` // Fully formated error message
StackTrace string `json:"StackTrace,omitempty"` // Stack trace in string form
Provider string `json:"Provider,omitempty"`
EventID uint16 `json:"EventId,omitempty"`
Flags uint32 `json:"Flags,omitempty"`
Source string `json:"Source,omitempty"`
//Data []EventData `json:"Data,omitempty"` // Omit this as HCS doesn't encode this well. It's more confusing to include. It is however logged in debug mode (see processHcsResult function)
}
type hcsResult struct {
Error int32
ErrorMessage string
ErrorEvents []ErrorEvent `json:"ErrorEvents,omitempty"`
}
func (ev *ErrorEvent) String() string {
evs := "[Event Detail: " + ev.Message
if ev.StackTrace != "" {
evs += " Stack Trace: " + ev.StackTrace
}
if ev.Provider != "" {
evs += " Provider: " + ev.Provider
}
if ev.EventID != 0 {
evs = fmt.Sprintf("%s EventID: %d", evs, ev.EventID)
}
if ev.Flags != 0 {
evs = fmt.Sprintf("%s flags: %d", evs, ev.Flags)
}
if ev.Source != "" {
evs += " Source: " + ev.Source
}
evs += "]"
return evs
}
func processHcsResult(resultp *uint16) []ErrorEvent {
if resultp != nil {
resultj := interop.ConvertAndFreeCoTaskMemString(resultp)
logrus.WithField(logfields.JSON, resultj).
Debug("HCS Result")
result := &hcsResult{}
if err := json.Unmarshal([]byte(resultj), result); err != nil {
logrus.WithFields(logrus.Fields{
logfields.JSON: resultj,
logrus.ErrorKey: err,
}).Warning("Could not unmarshal HCS result")
return nil
}
return result.ErrorEvents
}
return nil
}
type HcsError struct {
Op string
Err error
Events []ErrorEvent
}
func (e *HcsError) Error() string {
s := e.Op + ": " + e.Err.Error()
for _, ev := range e.Events {
s += "\n" + ev.String()
}
return s
}
// ProcessError is an error encountered in HCS during an operation on a Process object
type ProcessError struct {
SystemID string
Pid int
Op string
Err error
Events []ErrorEvent
}
// SystemError is an error encountered in HCS during an operation on a Container object
type SystemError struct {
ID string
Op string
Err error
Extra string
Events []ErrorEvent
}
func (e *SystemError) Error() string {
s := e.Op + " " + e.ID + ": " + e.Err.Error()
for _, ev := range e.Events {
s += "\n" + ev.String()
}
if e.Extra != "" {
s += "\n(extra info: " + e.Extra + ")"
}
return s
}
func makeSystemError(system *System, op string, extra string, err error, events []ErrorEvent) error {
// Don't double wrap errors
if _, ok := err.(*SystemError); ok {
return err
}
return &SystemError{
ID: system.ID(),
Op: op,
Extra: extra,
Err: err,
Events: events,
}
}
func (e *ProcessError) Error() string {
s := fmt.Sprintf("%s %s:%d: %s", e.Op, e.SystemID, e.Pid, e.Err.Error())
for _, ev := range e.Events {
s += "\n" + ev.String()
}
return s
}
func makeProcessError(process *Process, op string, err error, events []ErrorEvent) error {
// Don't double wrap errors
if _, ok := err.(*ProcessError); ok {
return err
}
return &ProcessError{
Pid: process.Pid(),
SystemID: process.SystemID(),
Op: op,
Err: err,
Events: events,
}
}
// IsNotExist checks if an error is caused by the Container or Process not existing.
// Note: Currently, ErrElementNotFound can mean that a Process has either
// already exited, or does not exist. Both IsAlreadyStopped and IsNotExist
// will currently return true when the error is ErrElementNotFound or ErrProcNotFound.
func IsNotExist(err error) bool {
err = getInnerError(err)
return err == ErrComputeSystemDoesNotExist ||
err == ErrElementNotFound ||
err == ErrProcNotFound
}
// IsAlreadyClosed checks if an error is caused by the Container or Process having been
// already closed by a call to the Close() method.
func IsAlreadyClosed(err error) bool {
err = getInnerError(err)
return err == ErrAlreadyClosed
}
// IsPending returns a boolean indicating whether the error is that
// the requested operation is being completed in the background.
func IsPending(err error) bool {
err = getInnerError(err)
return err == ErrVmcomputeOperationPending
}
// IsTimeout returns a boolean indicating whether the error is caused by
// a timeout waiting for the operation to complete.
func IsTimeout(err error) bool {
err = getInnerError(err)
return err == ErrTimeout
}
// IsAlreadyStopped returns a boolean indicating whether the error is caused by
// a Container or Process being already stopped.
// Note: Currently, ErrElementNotFound can mean that a Process has either
// already exited, or does not exist. Both IsAlreadyStopped and IsNotExist
// will currently return true when the error is ErrElementNotFound or ErrProcNotFound.
func IsAlreadyStopped(err error) bool {
err = getInnerError(err)
return err == ErrVmcomputeAlreadyStopped ||
err == ErrElementNotFound ||
err == ErrProcNotFound
}
// IsNotSupported returns a boolean indicating whether the error is caused by
// unsupported platform requests
// Note: Currently Unsupported platform requests can be mean either
// ErrVmcomputeInvalidJSON, ErrInvalidData, ErrNotSupported or ErrVmcomputeUnknownMessage
// is thrown from the Platform
func IsNotSupported(err error) bool {
err = getInnerError(err)
// If Platform doesn't recognize or support the request sent, below errors are seen
return err == ErrVmcomputeInvalidJSON ||
err == ErrInvalidData ||
err == ErrNotSupported ||
err == ErrVmcomputeUnknownMessage
}
func getInnerError(err error) error {
switch pe := err.(type) {
case nil:
return nil
case *HcsError:
err = pe.Err
case *SystemError:
err = pe.Err
case *ProcessError:
err = pe.Err
}
return err
}

View File

@ -0,0 +1,48 @@
// Shim for the Host Compute Service (HCS) to manage Windows Server
// containers and Hyper-V containers.
package hcs
import (
"syscall"
)
//go:generate go run ../../mksyscall_windows.go -output zsyscall_windows.go hcs.go
//sys hcsEnumerateComputeSystems(query string, computeSystems **uint16, result **uint16) (hr error) = vmcompute.HcsEnumerateComputeSystems?
//sys hcsCreateComputeSystem(id string, configuration string, identity syscall.Handle, computeSystem *hcsSystem, result **uint16) (hr error) = vmcompute.HcsCreateComputeSystem?
//sys hcsOpenComputeSystem(id string, computeSystem *hcsSystem, result **uint16) (hr error) = vmcompute.HcsOpenComputeSystem?
//sys hcsCloseComputeSystem(computeSystem hcsSystem) (hr error) = vmcompute.HcsCloseComputeSystem?
//sys hcsStartComputeSystem(computeSystem hcsSystem, options string, result **uint16) (hr error) = vmcompute.HcsStartComputeSystem?
//sys hcsShutdownComputeSystem(computeSystem hcsSystem, options string, result **uint16) (hr error) = vmcompute.HcsShutdownComputeSystem?
//sys hcsTerminateComputeSystem(computeSystem hcsSystem, options string, result **uint16) (hr error) = vmcompute.HcsTerminateComputeSystem?
//sys hcsPauseComputeSystem(computeSystem hcsSystem, options string, result **uint16) (hr error) = vmcompute.HcsPauseComputeSystem?
//sys hcsResumeComputeSystem(computeSystem hcsSystem, options string, result **uint16) (hr error) = vmcompute.HcsResumeComputeSystem?
//sys hcsGetComputeSystemProperties(computeSystem hcsSystem, propertyQuery string, properties **uint16, result **uint16) (hr error) = vmcompute.HcsGetComputeSystemProperties?
//sys hcsModifyComputeSystem(computeSystem hcsSystem, configuration string, result **uint16) (hr error) = vmcompute.HcsModifyComputeSystem?
//sys hcsRegisterComputeSystemCallback(computeSystem hcsSystem, callback uintptr, context uintptr, callbackHandle *hcsCallback) (hr error) = vmcompute.HcsRegisterComputeSystemCallback?
//sys hcsUnregisterComputeSystemCallback(callbackHandle hcsCallback) (hr error) = vmcompute.HcsUnregisterComputeSystemCallback?
//sys hcsCreateProcess(computeSystem hcsSystem, processParameters string, processInformation *hcsProcessInformation, process *hcsProcess, result **uint16) (hr error) = vmcompute.HcsCreateProcess?
//sys hcsOpenProcess(computeSystem hcsSystem, pid uint32, process *hcsProcess, result **uint16) (hr error) = vmcompute.HcsOpenProcess?
//sys hcsCloseProcess(process hcsProcess) (hr error) = vmcompute.HcsCloseProcess?
//sys hcsTerminateProcess(process hcsProcess, result **uint16) (hr error) = vmcompute.HcsTerminateProcess?
//sys hcsSignalProcess(process hcsProcess, options string, result **uint16) (hr error) = vmcompute.HcsTerminateProcess?
//sys hcsGetProcessInfo(process hcsProcess, processInformation *hcsProcessInformation, result **uint16) (hr error) = vmcompute.HcsGetProcessInfo?
//sys hcsGetProcessProperties(process hcsProcess, processProperties **uint16, result **uint16) (hr error) = vmcompute.HcsGetProcessProperties?
//sys hcsModifyProcess(process hcsProcess, settings string, result **uint16) (hr error) = vmcompute.HcsModifyProcess?
//sys hcsGetServiceProperties(propertyQuery string, properties **uint16, result **uint16) (hr error) = vmcompute.HcsGetServiceProperties?
//sys hcsRegisterProcessCallback(process hcsProcess, callback uintptr, context uintptr, callbackHandle *hcsCallback) (hr error) = vmcompute.HcsRegisterProcessCallback?
//sys hcsUnregisterProcessCallback(callbackHandle hcsCallback) (hr error) = vmcompute.HcsUnregisterProcessCallback?
type hcsSystem syscall.Handle
type hcsProcess syscall.Handle
type hcsCallback syscall.Handle
type hcsProcessInformation struct {
ProcessId uint32
Reserved uint32
StdInput syscall.Handle
StdOutput syscall.Handle
StdError syscall.Handle
}

View File

@ -0,0 +1,15 @@
package hcs
import "github.com/sirupsen/logrus"
func logOperationBegin(ctx logrus.Fields, msg string) {
logrus.WithFields(ctx).Debug(msg)
}
func logOperationEnd(ctx logrus.Fields, msg string, err error) {
if err == nil {
logrus.WithFields(ctx).Debug(msg)
} else {
logrus.WithFields(ctx).WithError(err).Error(msg)
}
}

View File

@ -0,0 +1,462 @@
package hcs
import (
"encoding/json"
"io"
"sync"
"syscall"
"time"
"github.com/Microsoft/hcsshim/internal/guestrequest"
"github.com/Microsoft/hcsshim/internal/interop"
"github.com/Microsoft/hcsshim/internal/logfields"
"github.com/sirupsen/logrus"
)
// ContainerError is an error encountered in HCS
type Process struct {
handleLock sync.RWMutex
handle hcsProcess
processID int
system *System
cachedPipes *cachedPipes
callbackNumber uintptr
logctx logrus.Fields
}
func newProcess(process hcsProcess, processID int, computeSystem *System) *Process {
return &Process{
handle: process,
processID: processID,
system: computeSystem,
logctx: logrus.Fields{
logfields.HCSOperation: "",
logfields.ContainerID: computeSystem.ID(),
logfields.ProcessID: processID,
},
}
}
type cachedPipes struct {
stdIn syscall.Handle
stdOut syscall.Handle
stdErr syscall.Handle
}
type processModifyRequest struct {
Operation string
ConsoleSize *consoleSize `json:",omitempty"`
CloseHandle *closeHandle `json:",omitempty"`
}
type consoleSize struct {
Height uint16
Width uint16
}
type closeHandle struct {
Handle string
}
type ProcessStatus struct {
ProcessID uint32
Exited bool
ExitCode uint32
LastWaitResult int32
}
const (
stdIn string = "StdIn"
stdOut string = "StdOut"
stdErr string = "StdErr"
)
const (
modifyConsoleSize string = "ConsoleSize"
modifyCloseHandle string = "CloseHandle"
)
// Pid returns the process ID of the process within the container.
func (process *Process) Pid() int {
return process.processID
}
// SystemID returns the ID of the process's compute system.
func (process *Process) SystemID() string {
return process.system.ID()
}
func (process *Process) logOperationBegin(operation string) {
process.logctx[logfields.HCSOperation] = operation
logOperationBegin(
process.logctx,
"hcsshim::Process - Begin Operation")
}
func (process *Process) logOperationEnd(err error) {
var result string
if err == nil {
result = "Success"
} else {
result = "Error"
}
logOperationEnd(
process.logctx,
"hcsshim::Process - End Operation - "+result,
err)
process.logctx[logfields.HCSOperation] = ""
}
// Signal signals the process with `options`.
func (process *Process) Signal(options guestrequest.SignalProcessOptions) (err error) {
process.handleLock.RLock()
defer process.handleLock.RUnlock()
operation := "hcsshim::Process::Signal"
process.logOperationBegin(operation)
defer func() { process.logOperationEnd(err) }()
if process.handle == 0 {
return makeProcessError(process, operation, ErrAlreadyClosed, nil)
}
optionsb, err := json.Marshal(options)
if err != nil {
return err
}
optionsStr := string(optionsb)
var resultp *uint16
syscallWatcher(process.logctx, func() {
err = hcsSignalProcess(process.handle, optionsStr, &resultp)
})
events := processHcsResult(resultp)
if err != nil {
return makeProcessError(process, operation, err, events)
}
return nil
}
// Kill signals the process to terminate but does not wait for it to finish terminating.
func (process *Process) Kill() (err error) {
process.handleLock.RLock()
defer process.handleLock.RUnlock()
operation := "hcsshim::Process::Kill"
process.logOperationBegin(operation)
defer func() { process.logOperationEnd(err) }()
if process.handle == 0 {
return makeProcessError(process, operation, ErrAlreadyClosed, nil)
}
var resultp *uint16
syscallWatcher(process.logctx, func() {
err = hcsTerminateProcess(process.handle, &resultp)
})
events := processHcsResult(resultp)
if err != nil {
return makeProcessError(process, operation, err, events)
}
return nil
}
// Wait waits for the process to exit.
func (process *Process) Wait() (err error) {
operation := "hcsshim::Process::Wait"
process.logOperationBegin(operation)
defer func() { process.logOperationEnd(err) }()
err = waitForNotification(process.callbackNumber, hcsNotificationProcessExited, nil)
if err != nil {
return makeProcessError(process, operation, err, nil)
}
return nil
}
// WaitTimeout waits for the process to exit or the duration to elapse. It returns
// false if timeout occurs.
func (process *Process) WaitTimeout(timeout time.Duration) (err error) {
operation := "hcssshim::Process::WaitTimeout"
process.logOperationBegin(operation)
defer func() { process.logOperationEnd(err) }()
err = waitForNotification(process.callbackNumber, hcsNotificationProcessExited, &timeout)
if err != nil {
return makeProcessError(process, operation, err, nil)
}
return nil
}
// ResizeConsole resizes the console of the process.
func (process *Process) ResizeConsole(width, height uint16) (err error) {
process.handleLock.RLock()
defer process.handleLock.RUnlock()
operation := "hcsshim::Process::ResizeConsole"
process.logOperationBegin(operation)
defer func() { process.logOperationEnd(err) }()
if process.handle == 0 {
return makeProcessError(process, operation, ErrAlreadyClosed, nil)
}
modifyRequest := processModifyRequest{
Operation: modifyConsoleSize,
ConsoleSize: &consoleSize{
Height: height,
Width: width,
},
}
modifyRequestb, err := json.Marshal(modifyRequest)
if err != nil {
return err
}
modifyRequestStr := string(modifyRequestb)
var resultp *uint16
err = hcsModifyProcess(process.handle, modifyRequestStr, &resultp)
events := processHcsResult(resultp)
if err != nil {
return makeProcessError(process, operation, err, events)
}
return nil
}
func (process *Process) Properties() (_ *ProcessStatus, err error) {
process.handleLock.RLock()
defer process.handleLock.RUnlock()
operation := "hcsshim::Process::Properties"
process.logOperationBegin(operation)
defer func() { process.logOperationEnd(err) }()
if process.handle == 0 {
return nil, makeProcessError(process, operation, ErrAlreadyClosed, nil)
}
var (
resultp *uint16
propertiesp *uint16
)
syscallWatcher(process.logctx, func() {
err = hcsGetProcessProperties(process.handle, &propertiesp, &resultp)
})
events := processHcsResult(resultp)
if err != nil {
return nil, makeProcessError(process, operation, err, events)
}
if propertiesp == nil {
return nil, ErrUnexpectedValue
}
propertiesRaw := interop.ConvertAndFreeCoTaskMemBytes(propertiesp)
properties := &ProcessStatus{}
if err := json.Unmarshal(propertiesRaw, properties); err != nil {
return nil, makeProcessError(process, operation, err, nil)
}
return properties, nil
}
// ExitCode returns the exit code of the process. The process must have
// already terminated.
func (process *Process) ExitCode() (_ int, err error) {
operation := "hcsshim::Process::ExitCode"
process.logOperationBegin(operation)
defer func() { process.logOperationEnd(err) }()
properties, err := process.Properties()
if err != nil {
return 0, makeProcessError(process, operation, err, nil)
}
if properties.Exited == false {
return 0, makeProcessError(process, operation, ErrInvalidProcessState, nil)
}
if properties.LastWaitResult != 0 {
return 0, makeProcessError(process, operation, syscall.Errno(properties.LastWaitResult), nil)
}
return int(properties.ExitCode), nil
}
// Stdio returns the stdin, stdout, and stderr pipes, respectively. Closing
// these pipes does not close the underlying pipes; it should be possible to
// call this multiple times to get multiple interfaces.
func (process *Process) Stdio() (_ io.WriteCloser, _ io.ReadCloser, _ io.ReadCloser, err error) {
process.handleLock.RLock()
defer process.handleLock.RUnlock()
operation := "hcsshim::Process::Stdio"
process.logOperationBegin(operation)
defer func() { process.logOperationEnd(err) }()
if process.handle == 0 {
return nil, nil, nil, makeProcessError(process, operation, ErrAlreadyClosed, nil)
}
var stdIn, stdOut, stdErr syscall.Handle
if process.cachedPipes == nil {
var (
processInfo hcsProcessInformation
resultp *uint16
)
err = hcsGetProcessInfo(process.handle, &processInfo, &resultp)
events := processHcsResult(resultp)
if err != nil {
return nil, nil, nil, makeProcessError(process, operation, err, events)
}
stdIn, stdOut, stdErr = processInfo.StdInput, processInfo.StdOutput, processInfo.StdError
} else {
// Use cached pipes
stdIn, stdOut, stdErr = process.cachedPipes.stdIn, process.cachedPipes.stdOut, process.cachedPipes.stdErr
// Invalidate the cache
process.cachedPipes = nil
}
pipes, err := makeOpenFiles([]syscall.Handle{stdIn, stdOut, stdErr})
if err != nil {
return nil, nil, nil, makeProcessError(process, operation, err, nil)
}
return pipes[0], pipes[1], pipes[2], nil
}
// CloseStdin closes the write side of the stdin pipe so that the process is
// notified on the read side that there is no more data in stdin.
func (process *Process) CloseStdin() (err error) {
process.handleLock.RLock()
defer process.handleLock.RUnlock()
operation := "hcsshim::Process::CloseStdin"
process.logOperationBegin(operation)
defer func() { process.logOperationEnd(err) }()
if process.handle == 0 {
return makeProcessError(process, operation, ErrAlreadyClosed, nil)
}
modifyRequest := processModifyRequest{
Operation: modifyCloseHandle,
CloseHandle: &closeHandle{
Handle: stdIn,
},
}
modifyRequestb, err := json.Marshal(modifyRequest)
if err != nil {
return err
}
modifyRequestStr := string(modifyRequestb)
var resultp *uint16
err = hcsModifyProcess(process.handle, modifyRequestStr, &resultp)
events := processHcsResult(resultp)
if err != nil {
return makeProcessError(process, operation, err, events)
}
return nil
}
// Close cleans up any state associated with the process but does not kill
// or wait on it.
func (process *Process) Close() (err error) {
process.handleLock.Lock()
defer process.handleLock.Unlock()
operation := "hcsshim::Process::Close"
process.logOperationBegin(operation)
defer func() { process.logOperationEnd(err) }()
// Don't double free this
if process.handle == 0 {
return nil
}
if err = process.unregisterCallback(); err != nil {
return makeProcessError(process, operation, err, nil)
}
if err = hcsCloseProcess(process.handle); err != nil {
return makeProcessError(process, operation, err, nil)
}
process.handle = 0
return nil
}
func (process *Process) registerCallback() error {
context := &notifcationWatcherContext{
channels: newChannels(),
}
callbackMapLock.Lock()
callbackNumber := nextCallback
nextCallback++
callbackMap[callbackNumber] = context
callbackMapLock.Unlock()
var callbackHandle hcsCallback
err := hcsRegisterProcessCallback(process.handle, notificationWatcherCallback, callbackNumber, &callbackHandle)
if err != nil {
return err
}
context.handle = callbackHandle
process.callbackNumber = callbackNumber
return nil
}
func (process *Process) unregisterCallback() error {
callbackNumber := process.callbackNumber
callbackMapLock.RLock()
context := callbackMap[callbackNumber]
callbackMapLock.RUnlock()
if context == nil {
return nil
}
handle := context.handle
if handle == 0 {
return nil
}
// hcsUnregisterProcessCallback has its own syncronization
// to wait for all callbacks to complete. We must NOT hold the callbackMapLock.
err := hcsUnregisterProcessCallback(handle)
if err != nil {
return err
}
closeChannels(context.channels)
callbackMapLock.Lock()
callbackMap[callbackNumber] = nil
callbackMapLock.Unlock()
handle = 0
return nil
}

View File

@ -0,0 +1,672 @@
package hcs
import (
"encoding/json"
"os"
"strconv"
"sync"
"syscall"
"time"
"github.com/Microsoft/hcsshim/internal/interop"
"github.com/Microsoft/hcsshim/internal/logfields"
"github.com/Microsoft/hcsshim/internal/schema1"
"github.com/Microsoft/hcsshim/internal/timeout"
"github.com/sirupsen/logrus"
)
// currentContainerStarts is used to limit the number of concurrent container
// starts.
var currentContainerStarts containerStarts
type containerStarts struct {
maxParallel int
inProgress int
sync.Mutex
}
func init() {
mpsS := os.Getenv("HCSSHIM_MAX_PARALLEL_START")
if len(mpsS) > 0 {
mpsI, err := strconv.Atoi(mpsS)
if err != nil || mpsI < 0 {
return
}
currentContainerStarts.maxParallel = mpsI
}
}
type System struct {
handleLock sync.RWMutex
handle hcsSystem
id string
callbackNumber uintptr
logctx logrus.Fields
}
func newSystem(id string) *System {
return &System{
id: id,
logctx: logrus.Fields{
logfields.HCSOperation: "",
logfields.ContainerID: id,
},
}
}
func (computeSystem *System) logOperationBegin(operation string) {
computeSystem.logctx[logfields.HCSOperation] = operation
logOperationBegin(
computeSystem.logctx,
"hcsshim::ComputeSystem - Begin Operation")
}
func (computeSystem *System) logOperationEnd(err error) {
var result string
if err == nil {
result = "Success"
} else {
result = "Error"
}
logOperationEnd(
computeSystem.logctx,
"hcsshim::ComputeSystem - End Operation - "+result,
err)
computeSystem.logctx[logfields.HCSOperation] = ""
}
// CreateComputeSystem creates a new compute system with the given configuration but does not start it.
func CreateComputeSystem(id string, hcsDocumentInterface interface{}) (_ *System, err error) {
operation := "hcsshim::CreateComputeSystem"
computeSystem := newSystem(id)
computeSystem.logOperationBegin(operation)
defer func() { computeSystem.logOperationEnd(err) }()
hcsDocumentB, err := json.Marshal(hcsDocumentInterface)
if err != nil {
return nil, err
}
hcsDocument := string(hcsDocumentB)
logrus.WithFields(computeSystem.logctx).
WithField(logfields.JSON, hcsDocument).
Debug("HCS ComputeSystem Document")
var (
resultp *uint16
identity syscall.Handle
createError error
)
syscallWatcher(computeSystem.logctx, func() {
createError = hcsCreateComputeSystem(id, hcsDocument, identity, &computeSystem.handle, &resultp)
})
if createError == nil || IsPending(createError) {
if err = computeSystem.registerCallback(); err != nil {
// Terminate the compute system if it still exists. We're okay to
// ignore a failure here.
computeSystem.Terminate()
return nil, makeSystemError(computeSystem, operation, "", err, nil)
}
}
events, err := processAsyncHcsResult(createError, resultp, computeSystem.callbackNumber, hcsNotificationSystemCreateCompleted, &timeout.SystemCreate)
if err != nil {
if err == ErrTimeout {
// Terminate the compute system if it still exists. We're okay to
// ignore a failure here.
computeSystem.Terminate()
}
return nil, makeSystemError(computeSystem, operation, hcsDocument, err, events)
}
return computeSystem, nil
}
// OpenComputeSystem opens an existing compute system by ID.
func OpenComputeSystem(id string) (_ *System, err error) {
operation := "hcsshim::OpenComputeSystem"
computeSystem := newSystem(id)
computeSystem.logOperationBegin(operation)
defer func() { computeSystem.logOperationEnd(err) }()
var (
handle hcsSystem
resultp *uint16
)
err = hcsOpenComputeSystem(id, &handle, &resultp)
events := processHcsResult(resultp)
if err != nil {
return nil, makeSystemError(computeSystem, operation, "", err, events)
}
computeSystem.handle = handle
if err = computeSystem.registerCallback(); err != nil {
return nil, makeSystemError(computeSystem, operation, "", err, nil)
}
return computeSystem, nil
}
// GetComputeSystems gets a list of the compute systems on the system that match the query
func GetComputeSystems(q schema1.ComputeSystemQuery) (_ []schema1.ContainerProperties, err error) {
operation := "hcsshim::GetComputeSystems"
fields := logrus.Fields{
logfields.HCSOperation: operation,
}
logOperationBegin(
fields,
"hcsshim::ComputeSystem - Begin Operation")
defer func() {
var result string
if err == nil {
result = "Success"
} else {
result = "Error"
}
logOperationEnd(
fields,
"hcsshim::ComputeSystem - End Operation - "+result,
err)
}()
queryb, err := json.Marshal(q)
if err != nil {
return nil, err
}
query := string(queryb)
logrus.WithFields(fields).
WithField(logfields.JSON, query).
Debug("HCS ComputeSystem Query")
var (
resultp *uint16
computeSystemsp *uint16
)
syscallWatcher(fields, func() {
err = hcsEnumerateComputeSystems(query, &computeSystemsp, &resultp)
})
events := processHcsResult(resultp)
if err != nil {
return nil, &HcsError{Op: operation, Err: err, Events: events}
}
if computeSystemsp == nil {
return nil, ErrUnexpectedValue
}
computeSystemsRaw := interop.ConvertAndFreeCoTaskMemBytes(computeSystemsp)
computeSystems := []schema1.ContainerProperties{}
if err = json.Unmarshal(computeSystemsRaw, &computeSystems); err != nil {
return nil, err
}
return computeSystems, nil
}
// Start synchronously starts the computeSystem.
func (computeSystem *System) Start() (err error) {
computeSystem.handleLock.RLock()
defer computeSystem.handleLock.RUnlock()
operation := "hcsshim::ComputeSystem::Start"
computeSystem.logOperationBegin(operation)
defer func() { computeSystem.logOperationEnd(err) }()
if computeSystem.handle == 0 {
return makeSystemError(computeSystem, "Start", "", ErrAlreadyClosed, nil)
}
// This is a very simple backoff-retry loop to limit the number
// of parallel container starts if environment variable
// HCSSHIM_MAX_PARALLEL_START is set to a positive integer.
// It should generally only be used as a workaround to various
// platform issues that exist between RS1 and RS4 as of Aug 2018
if currentContainerStarts.maxParallel > 0 {
for {
currentContainerStarts.Lock()
if currentContainerStarts.inProgress < currentContainerStarts.maxParallel {
currentContainerStarts.inProgress++
currentContainerStarts.Unlock()
break
}
if currentContainerStarts.inProgress == currentContainerStarts.maxParallel {
currentContainerStarts.Unlock()
time.Sleep(100 * time.Millisecond)
}
}
// Make sure we decrement the count when we are done.
defer func() {
currentContainerStarts.Lock()
currentContainerStarts.inProgress--
currentContainerStarts.Unlock()
}()
}
var resultp *uint16
syscallWatcher(computeSystem.logctx, func() {
err = hcsStartComputeSystem(computeSystem.handle, "", &resultp)
})
events, err := processAsyncHcsResult(err, resultp, computeSystem.callbackNumber, hcsNotificationSystemStartCompleted, &timeout.SystemStart)
if err != nil {
return makeSystemError(computeSystem, "Start", "", err, events)
}
return nil
}
// ID returns the compute system's identifier.
func (computeSystem *System) ID() string {
return computeSystem.id
}
// Shutdown requests a compute system shutdown, if IsPending() on the error returned is true,
// it may not actually be shut down until Wait() succeeds.
func (computeSystem *System) Shutdown() (err error) {
computeSystem.handleLock.RLock()
defer computeSystem.handleLock.RUnlock()
operation := "hcsshim::ComputeSystem::Shutdown"
computeSystem.logOperationBegin(operation)
defer func() { computeSystem.logOperationEnd(err) }()
if computeSystem.handle == 0 {
return makeSystemError(computeSystem, "Shutdown", "", ErrAlreadyClosed, nil)
}
var resultp *uint16
syscallWatcher(computeSystem.logctx, func() {
err = hcsShutdownComputeSystem(computeSystem.handle, "", &resultp)
})
events := processHcsResult(resultp)
if err != nil {
return makeSystemError(computeSystem, "Shutdown", "", err, events)
}
return nil
}
// Terminate requests a compute system terminate, if IsPending() on the error returned is true,
// it may not actually be shut down until Wait() succeeds.
func (computeSystem *System) Terminate() (err error) {
computeSystem.handleLock.RLock()
defer computeSystem.handleLock.RUnlock()
operation := "hcsshim::ComputeSystem::Terminate"
computeSystem.logOperationBegin(operation)
defer func() { computeSystem.logOperationEnd(err) }()
if computeSystem.handle == 0 {
return makeSystemError(computeSystem, "Terminate", "", ErrAlreadyClosed, nil)
}
var resultp *uint16
syscallWatcher(computeSystem.logctx, func() {
err = hcsTerminateComputeSystem(computeSystem.handle, "", &resultp)
})
events := processHcsResult(resultp)
if err != nil && err != ErrVmcomputeAlreadyStopped {
return makeSystemError(computeSystem, "Terminate", "", err, events)
}
return nil
}
// Wait synchronously waits for the compute system to shutdown or terminate.
func (computeSystem *System) Wait() (err error) {
operation := "hcsshim::ComputeSystem::Wait"
computeSystem.logOperationBegin(operation)
defer func() { computeSystem.logOperationEnd(err) }()
err = waitForNotification(computeSystem.callbackNumber, hcsNotificationSystemExited, nil)
if err != nil {
return makeSystemError(computeSystem, "Wait", "", err, nil)
}
return nil
}
// WaitExpectedError synchronously waits for the compute system to shutdown or
// terminate, and ignores the passed error if it occurs.
func (computeSystem *System) WaitExpectedError(expected error) (err error) {
operation := "hcsshim::ComputeSystem::WaitExpectedError"
computeSystem.logOperationBegin(operation)
defer func() { computeSystem.logOperationEnd(err) }()
err = waitForNotification(computeSystem.callbackNumber, hcsNotificationSystemExited, nil)
if err != nil && err != expected {
return makeSystemError(computeSystem, "WaitExpectedError", "", err, nil)
}
return nil
}
// WaitTimeout synchronously waits for the compute system to terminate or the duration to elapse.
// If the timeout expires, IsTimeout(err) == true
func (computeSystem *System) WaitTimeout(timeout time.Duration) (err error) {
operation := "hcsshim::ComputeSystem::WaitTimeout"
computeSystem.logOperationBegin(operation)
defer func() { computeSystem.logOperationEnd(err) }()
err = waitForNotification(computeSystem.callbackNumber, hcsNotificationSystemExited, &timeout)
if err != nil {
return makeSystemError(computeSystem, "WaitTimeout", "", err, nil)
}
return nil
}
func (computeSystem *System) Properties(types ...schema1.PropertyType) (_ *schema1.ContainerProperties, err error) {
computeSystem.handleLock.RLock()
defer computeSystem.handleLock.RUnlock()
operation := "hcsshim::ComputeSystem::Properties"
computeSystem.logOperationBegin(operation)
defer func() { computeSystem.logOperationEnd(err) }()
queryj, err := json.Marshal(schema1.PropertyQuery{types})
if err != nil {
return nil, makeSystemError(computeSystem, "Properties", "", err, nil)
}
logrus.WithFields(computeSystem.logctx).
WithField(logfields.JSON, queryj).
Debug("HCS ComputeSystem Properties Query")
var resultp, propertiesp *uint16
syscallWatcher(computeSystem.logctx, func() {
err = hcsGetComputeSystemProperties(computeSystem.handle, string(queryj), &propertiesp, &resultp)
})
events := processHcsResult(resultp)
if err != nil {
return nil, makeSystemError(computeSystem, "Properties", "", err, events)
}
if propertiesp == nil {
return nil, ErrUnexpectedValue
}
propertiesRaw := interop.ConvertAndFreeCoTaskMemBytes(propertiesp)
properties := &schema1.ContainerProperties{}
if err := json.Unmarshal(propertiesRaw, properties); err != nil {
return nil, makeSystemError(computeSystem, "Properties", "", err, nil)
}
return properties, nil
}
// Pause pauses the execution of the computeSystem. This feature is not enabled in TP5.
func (computeSystem *System) Pause() (err error) {
computeSystem.handleLock.RLock()
defer computeSystem.handleLock.RUnlock()
operation := "hcsshim::ComputeSystem::Pause"
computeSystem.logOperationBegin(operation)
defer func() { computeSystem.logOperationEnd(err) }()
if computeSystem.handle == 0 {
return makeSystemError(computeSystem, "Pause", "", ErrAlreadyClosed, nil)
}
var resultp *uint16
syscallWatcher(computeSystem.logctx, func() {
err = hcsPauseComputeSystem(computeSystem.handle, "", &resultp)
})
events, err := processAsyncHcsResult(err, resultp, computeSystem.callbackNumber, hcsNotificationSystemPauseCompleted, &timeout.SystemPause)
if err != nil {
return makeSystemError(computeSystem, "Pause", "", err, events)
}
return nil
}
// Resume resumes the execution of the computeSystem. This feature is not enabled in TP5.
func (computeSystem *System) Resume() (err error) {
computeSystem.handleLock.RLock()
defer computeSystem.handleLock.RUnlock()
operation := "hcsshim::ComputeSystem::Resume"
computeSystem.logOperationBegin(operation)
defer func() { computeSystem.logOperationEnd(err) }()
if computeSystem.handle == 0 {
return makeSystemError(computeSystem, "Resume", "", ErrAlreadyClosed, nil)
}
var resultp *uint16
syscallWatcher(computeSystem.logctx, func() {
err = hcsResumeComputeSystem(computeSystem.handle, "", &resultp)
})
events, err := processAsyncHcsResult(err, resultp, computeSystem.callbackNumber, hcsNotificationSystemResumeCompleted, &timeout.SystemResume)
if err != nil {
return makeSystemError(computeSystem, "Resume", "", err, events)
}
return nil
}
// CreateProcess launches a new process within the computeSystem.
func (computeSystem *System) CreateProcess(c interface{}) (_ *Process, err error) {
computeSystem.handleLock.RLock()
defer computeSystem.handleLock.RUnlock()
operation := "hcsshim::ComputeSystem::CreateProcess"
computeSystem.logOperationBegin(operation)
defer func() { computeSystem.logOperationEnd(err) }()
var (
processInfo hcsProcessInformation
processHandle hcsProcess
resultp *uint16
)
if computeSystem.handle == 0 {
return nil, makeSystemError(computeSystem, "CreateProcess", "", ErrAlreadyClosed, nil)
}
configurationb, err := json.Marshal(c)
if err != nil {
return nil, makeSystemError(computeSystem, "CreateProcess", "", err, nil)
}
configuration := string(configurationb)
logrus.WithFields(computeSystem.logctx).
WithField(logfields.JSON, configuration).
Debug("HCS ComputeSystem Process Document")
syscallWatcher(computeSystem.logctx, func() {
err = hcsCreateProcess(computeSystem.handle, configuration, &processInfo, &processHandle, &resultp)
})
events := processHcsResult(resultp)
if err != nil {
return nil, makeSystemError(computeSystem, "CreateProcess", configuration, err, events)
}
logrus.WithFields(computeSystem.logctx).
WithField(logfields.ProcessID, processInfo.ProcessId).
Debug("HCS ComputeSystem CreateProcess PID")
process := newProcess(processHandle, int(processInfo.ProcessId), computeSystem)
process.cachedPipes = &cachedPipes{
stdIn: processInfo.StdInput,
stdOut: processInfo.StdOutput,
stdErr: processInfo.StdError,
}
if err = process.registerCallback(); err != nil {
return nil, makeSystemError(computeSystem, "CreateProcess", "", err, nil)
}
return process, nil
}
// OpenProcess gets an interface to an existing process within the computeSystem.
func (computeSystem *System) OpenProcess(pid int) (_ *Process, err error) {
computeSystem.handleLock.RLock()
defer computeSystem.handleLock.RUnlock()
// Add PID for the context of this operation
computeSystem.logctx[logfields.ProcessID] = pid
defer delete(computeSystem.logctx, logfields.ProcessID)
operation := "hcsshim::ComputeSystem::OpenProcess"
computeSystem.logOperationBegin(operation)
defer func() { computeSystem.logOperationEnd(err) }()
var (
processHandle hcsProcess
resultp *uint16
)
if computeSystem.handle == 0 {
return nil, makeSystemError(computeSystem, "OpenProcess", "", ErrAlreadyClosed, nil)
}
syscallWatcher(computeSystem.logctx, func() {
err = hcsOpenProcess(computeSystem.handle, uint32(pid), &processHandle, &resultp)
})
events := processHcsResult(resultp)
if err != nil {
return nil, makeSystemError(computeSystem, "OpenProcess", "", err, events)
}
process := newProcess(processHandle, pid, computeSystem)
if err = process.registerCallback(); err != nil {
return nil, makeSystemError(computeSystem, "OpenProcess", "", err, nil)
}
return process, nil
}
// Close cleans up any state associated with the compute system but does not terminate or wait for it.
func (computeSystem *System) Close() (err error) {
computeSystem.handleLock.Lock()
defer computeSystem.handleLock.Unlock()
operation := "hcsshim::ComputeSystem::Close"
computeSystem.logOperationBegin(operation)
defer func() { computeSystem.logOperationEnd(err) }()
// Don't double free this
if computeSystem.handle == 0 {
return nil
}
if err = computeSystem.unregisterCallback(); err != nil {
return makeSystemError(computeSystem, "Close", "", err, nil)
}
syscallWatcher(computeSystem.logctx, func() {
err = hcsCloseComputeSystem(computeSystem.handle)
})
if err != nil {
return makeSystemError(computeSystem, "Close", "", err, nil)
}
computeSystem.handle = 0
return nil
}
func (computeSystem *System) registerCallback() error {
context := &notifcationWatcherContext{
channels: newChannels(),
}
callbackMapLock.Lock()
callbackNumber := nextCallback
nextCallback++
callbackMap[callbackNumber] = context
callbackMapLock.Unlock()
var callbackHandle hcsCallback
err := hcsRegisterComputeSystemCallback(computeSystem.handle, notificationWatcherCallback, callbackNumber, &callbackHandle)
if err != nil {
return err
}
context.handle = callbackHandle
computeSystem.callbackNumber = callbackNumber
return nil
}
func (computeSystem *System) unregisterCallback() error {
callbackNumber := computeSystem.callbackNumber
callbackMapLock.RLock()
context := callbackMap[callbackNumber]
callbackMapLock.RUnlock()
if context == nil {
return nil
}
handle := context.handle
if handle == 0 {
return nil
}
// hcsUnregisterComputeSystemCallback has its own syncronization
// to wait for all callbacks to complete. We must NOT hold the callbackMapLock.
err := hcsUnregisterComputeSystemCallback(handle)
if err != nil {
return err
}
closeChannels(context.channels)
callbackMapLock.Lock()
callbackMap[callbackNumber] = nil
callbackMapLock.Unlock()
handle = 0
return nil
}
// Modify the System by sending a request to HCS
func (computeSystem *System) Modify(config interface{}) (err error) {
computeSystem.handleLock.RLock()
defer computeSystem.handleLock.RUnlock()
operation := "hcsshim::ComputeSystem::Modify"
computeSystem.logOperationBegin(operation)
defer func() { computeSystem.logOperationEnd(err) }()
if computeSystem.handle == 0 {
return makeSystemError(computeSystem, "Modify", "", ErrAlreadyClosed, nil)
}
requestJSON, err := json.Marshal(config)
if err != nil {
return err
}
requestString := string(requestJSON)
logrus.WithFields(computeSystem.logctx).
WithField(logfields.JSON, requestString).
Debug("HCS ComputeSystem Modify Document")
var resultp *uint16
syscallWatcher(computeSystem.logctx, func() {
err = hcsModifyComputeSystem(computeSystem.handle, requestString, &resultp)
})
events := processHcsResult(resultp)
if err != nil {
return makeSystemError(computeSystem, "Modify", requestString, err, events)
}
return nil
}

View File

@ -1,4 +1,4 @@
package hcsshim
package hcs
import (
"io"

View File

@ -1,4 +1,4 @@
package hcsshim
package hcs
import (
"time"
@ -6,13 +6,13 @@ import (
"github.com/sirupsen/logrus"
)
func processAsyncHcsResult(err error, resultp *uint16, callbackNumber uintptr, expectedNotification hcsNotification, timeout *time.Duration) error {
err = processHcsResult(err, resultp)
func processAsyncHcsResult(err error, resultp *uint16, callbackNumber uintptr, expectedNotification hcsNotification, timeout *time.Duration) ([]ErrorEvent, error) {
events := processHcsResult(resultp)
if IsPending(err) {
return waitForNotification(callbackNumber, expectedNotification, timeout)
return nil, waitForNotification(callbackNumber, expectedNotification, timeout)
}
return err
return events, err
}
func waitForNotification(callbackNumber uintptr, expectedNotification hcsNotification, timeout *time.Duration) error {

View File

@ -0,0 +1,41 @@
package hcs
import (
"context"
"github.com/Microsoft/hcsshim/internal/logfields"
"github.com/Microsoft/hcsshim/internal/timeout"
"github.com/sirupsen/logrus"
)
// syscallWatcher is used as a very simple goroutine around calls into
// the platform. In some cases, we have seen HCS APIs not returning due to
// various bugs, and the goroutine making the syscall ends up not returning,
// prior to its async callback. By spinning up a syscallWatcher, it allows
// us to at least log a warning if a syscall doesn't complete in a reasonable
// amount of time.
//
// Usage is:
//
// syscallWatcher(logContext, func() {
// err = <syscall>(args...)
// })
//
func syscallWatcher(logContext logrus.Fields, syscallLambda func()) {
ctx, cancel := context.WithTimeout(context.Background(), timeout.SyscallWatcher)
defer cancel()
go watchFunc(ctx, logContext)
syscallLambda()
}
func watchFunc(ctx context.Context, logContext logrus.Fields) {
select {
case <-ctx.Done():
if ctx.Err() != context.Canceled {
logrus.WithFields(logContext).
WithField(logfields.Timeout, timeout.SyscallWatcher).
Warning("Syscall did not complete within operation timeout. This may indicate a platform issue. If it appears to be making no forward progress, obtain the stacks and see if there is a syscall stuck in the platform API for a significant length of time.")
}
}
}

View File

@ -0,0 +1,533 @@
// Code generated mksyscall_windows.exe DO NOT EDIT
package hcs
import (
"syscall"
"unsafe"
"golang.org/x/sys/windows"
)
var _ unsafe.Pointer
// Do the interface allocations only once for common
// Errno values.
const (
errnoERROR_IO_PENDING = 997
)
var (
errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING)
)
// errnoErr returns common boxed Errno values, to prevent
// allocations at runtime.
func errnoErr(e syscall.Errno) error {
switch e {
case 0:
return nil
case errnoERROR_IO_PENDING:
return errERROR_IO_PENDING
}
// TODO: add more here, after collecting data on the common
// error values see on Windows. (perhaps when running
// all.bat?)
return e
}
var (
modvmcompute = windows.NewLazySystemDLL("vmcompute.dll")
procHcsEnumerateComputeSystems = modvmcompute.NewProc("HcsEnumerateComputeSystems")
procHcsCreateComputeSystem = modvmcompute.NewProc("HcsCreateComputeSystem")
procHcsOpenComputeSystem = modvmcompute.NewProc("HcsOpenComputeSystem")
procHcsCloseComputeSystem = modvmcompute.NewProc("HcsCloseComputeSystem")
procHcsStartComputeSystem = modvmcompute.NewProc("HcsStartComputeSystem")
procHcsShutdownComputeSystem = modvmcompute.NewProc("HcsShutdownComputeSystem")
procHcsTerminateComputeSystem = modvmcompute.NewProc("HcsTerminateComputeSystem")
procHcsPauseComputeSystem = modvmcompute.NewProc("HcsPauseComputeSystem")
procHcsResumeComputeSystem = modvmcompute.NewProc("HcsResumeComputeSystem")
procHcsGetComputeSystemProperties = modvmcompute.NewProc("HcsGetComputeSystemProperties")
procHcsModifyComputeSystem = modvmcompute.NewProc("HcsModifyComputeSystem")
procHcsRegisterComputeSystemCallback = modvmcompute.NewProc("HcsRegisterComputeSystemCallback")
procHcsUnregisterComputeSystemCallback = modvmcompute.NewProc("HcsUnregisterComputeSystemCallback")
procHcsCreateProcess = modvmcompute.NewProc("HcsCreateProcess")
procHcsOpenProcess = modvmcompute.NewProc("HcsOpenProcess")
procHcsCloseProcess = modvmcompute.NewProc("HcsCloseProcess")
procHcsTerminateProcess = modvmcompute.NewProc("HcsTerminateProcess")
procHcsGetProcessInfo = modvmcompute.NewProc("HcsGetProcessInfo")
procHcsGetProcessProperties = modvmcompute.NewProc("HcsGetProcessProperties")
procHcsModifyProcess = modvmcompute.NewProc("HcsModifyProcess")
procHcsGetServiceProperties = modvmcompute.NewProc("HcsGetServiceProperties")
procHcsRegisterProcessCallback = modvmcompute.NewProc("HcsRegisterProcessCallback")
procHcsUnregisterProcessCallback = modvmcompute.NewProc("HcsUnregisterProcessCallback")
)
func hcsEnumerateComputeSystems(query string, computeSystems **uint16, result **uint16) (hr error) {
var _p0 *uint16
_p0, hr = syscall.UTF16PtrFromString(query)
if hr != nil {
return
}
return _hcsEnumerateComputeSystems(_p0, computeSystems, result)
}
func _hcsEnumerateComputeSystems(query *uint16, computeSystems **uint16, result **uint16) (hr error) {
if hr = procHcsEnumerateComputeSystems.Find(); hr != nil {
return
}
r0, _, _ := syscall.Syscall(procHcsEnumerateComputeSystems.Addr(), 3, uintptr(unsafe.Pointer(query)), uintptr(unsafe.Pointer(computeSystems)), uintptr(unsafe.Pointer(result)))
if int32(r0) < 0 {
if r0&0x1fff0000 == 0x00070000 {
r0 &= 0xffff
}
hr = syscall.Errno(r0)
}
return
}
func hcsCreateComputeSystem(id string, configuration string, identity syscall.Handle, computeSystem *hcsSystem, result **uint16) (hr error) {
var _p0 *uint16
_p0, hr = syscall.UTF16PtrFromString(id)
if hr != nil {
return
}
var _p1 *uint16
_p1, hr = syscall.UTF16PtrFromString(configuration)
if hr != nil {
return
}
return _hcsCreateComputeSystem(_p0, _p1, identity, computeSystem, result)
}
func _hcsCreateComputeSystem(id *uint16, configuration *uint16, identity syscall.Handle, computeSystem *hcsSystem, result **uint16) (hr error) {
if hr = procHcsCreateComputeSystem.Find(); hr != nil {
return
}
r0, _, _ := syscall.Syscall6(procHcsCreateComputeSystem.Addr(), 5, uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(configuration)), uintptr(identity), uintptr(unsafe.Pointer(computeSystem)), uintptr(unsafe.Pointer(result)), 0)
if int32(r0) < 0 {
if r0&0x1fff0000 == 0x00070000 {
r0 &= 0xffff
}
hr = syscall.Errno(r0)
}
return
}
func hcsOpenComputeSystem(id string, computeSystem *hcsSystem, result **uint16) (hr error) {
var _p0 *uint16
_p0, hr = syscall.UTF16PtrFromString(id)
if hr != nil {
return
}
return _hcsOpenComputeSystem(_p0, computeSystem, result)
}
func _hcsOpenComputeSystem(id *uint16, computeSystem *hcsSystem, result **uint16) (hr error) {
if hr = procHcsOpenComputeSystem.Find(); hr != nil {
return
}
r0, _, _ := syscall.Syscall(procHcsOpenComputeSystem.Addr(), 3, uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(computeSystem)), uintptr(unsafe.Pointer(result)))
if int32(r0) < 0 {
if r0&0x1fff0000 == 0x00070000 {
r0 &= 0xffff
}
hr = syscall.Errno(r0)
}
return
}
func hcsCloseComputeSystem(computeSystem hcsSystem) (hr error) {
if hr = procHcsCloseComputeSystem.Find(); hr != nil {
return
}
r0, _, _ := syscall.Syscall(procHcsCloseComputeSystem.Addr(), 1, uintptr(computeSystem), 0, 0)
if int32(r0) < 0 {
if r0&0x1fff0000 == 0x00070000 {
r0 &= 0xffff
}
hr = syscall.Errno(r0)
}
return
}
func hcsStartComputeSystem(computeSystem hcsSystem, options string, result **uint16) (hr error) {
var _p0 *uint16
_p0, hr = syscall.UTF16PtrFromString(options)
if hr != nil {
return
}
return _hcsStartComputeSystem(computeSystem, _p0, result)
}
func _hcsStartComputeSystem(computeSystem hcsSystem, options *uint16, result **uint16) (hr error) {
if hr = procHcsStartComputeSystem.Find(); hr != nil {
return
}
r0, _, _ := syscall.Syscall(procHcsStartComputeSystem.Addr(), 3, uintptr(computeSystem), uintptr(unsafe.Pointer(options)), uintptr(unsafe.Pointer(result)))
if int32(r0) < 0 {
if r0&0x1fff0000 == 0x00070000 {
r0 &= 0xffff
}
hr = syscall.Errno(r0)
}
return
}
func hcsShutdownComputeSystem(computeSystem hcsSystem, options string, result **uint16) (hr error) {
var _p0 *uint16
_p0, hr = syscall.UTF16PtrFromString(options)
if hr != nil {
return
}
return _hcsShutdownComputeSystem(computeSystem, _p0, result)
}
func _hcsShutdownComputeSystem(computeSystem hcsSystem, options *uint16, result **uint16) (hr error) {
if hr = procHcsShutdownComputeSystem.Find(); hr != nil {
return
}
r0, _, _ := syscall.Syscall(procHcsShutdownComputeSystem.Addr(), 3, uintptr(computeSystem), uintptr(unsafe.Pointer(options)), uintptr(unsafe.Pointer(result)))
if int32(r0) < 0 {
if r0&0x1fff0000 == 0x00070000 {
r0 &= 0xffff
}
hr = syscall.Errno(r0)
}
return
}
func hcsTerminateComputeSystem(computeSystem hcsSystem, options string, result **uint16) (hr error) {
var _p0 *uint16
_p0, hr = syscall.UTF16PtrFromString(options)
if hr != nil {
return
}
return _hcsTerminateComputeSystem(computeSystem, _p0, result)
}
func _hcsTerminateComputeSystem(computeSystem hcsSystem, options *uint16, result **uint16) (hr error) {
if hr = procHcsTerminateComputeSystem.Find(); hr != nil {
return
}
r0, _, _ := syscall.Syscall(procHcsTerminateComputeSystem.Addr(), 3, uintptr(computeSystem), uintptr(unsafe.Pointer(options)), uintptr(unsafe.Pointer(result)))
if int32(r0) < 0 {
if r0&0x1fff0000 == 0x00070000 {
r0 &= 0xffff
}
hr = syscall.Errno(r0)
}
return
}
func hcsPauseComputeSystem(computeSystem hcsSystem, options string, result **uint16) (hr error) {
var _p0 *uint16
_p0, hr = syscall.UTF16PtrFromString(options)
if hr != nil {
return
}
return _hcsPauseComputeSystem(computeSystem, _p0, result)
}
func _hcsPauseComputeSystem(computeSystem hcsSystem, options *uint16, result **uint16) (hr error) {
if hr = procHcsPauseComputeSystem.Find(); hr != nil {
return
}
r0, _, _ := syscall.Syscall(procHcsPauseComputeSystem.Addr(), 3, uintptr(computeSystem), uintptr(unsafe.Pointer(options)), uintptr(unsafe.Pointer(result)))
if int32(r0) < 0 {
if r0&0x1fff0000 == 0x00070000 {
r0 &= 0xffff
}
hr = syscall.Errno(r0)
}
return
}
func hcsResumeComputeSystem(computeSystem hcsSystem, options string, result **uint16) (hr error) {
var _p0 *uint16
_p0, hr = syscall.UTF16PtrFromString(options)
if hr != nil {
return
}
return _hcsResumeComputeSystem(computeSystem, _p0, result)
}
func _hcsResumeComputeSystem(computeSystem hcsSystem, options *uint16, result **uint16) (hr error) {
if hr = procHcsResumeComputeSystem.Find(); hr != nil {
return
}
r0, _, _ := syscall.Syscall(procHcsResumeComputeSystem.Addr(), 3, uintptr(computeSystem), uintptr(unsafe.Pointer(options)), uintptr(unsafe.Pointer(result)))
if int32(r0) < 0 {
if r0&0x1fff0000 == 0x00070000 {
r0 &= 0xffff
}
hr = syscall.Errno(r0)
}
return
}
func hcsGetComputeSystemProperties(computeSystem hcsSystem, propertyQuery string, properties **uint16, result **uint16) (hr error) {
var _p0 *uint16
_p0, hr = syscall.UTF16PtrFromString(propertyQuery)
if hr != nil {
return
}
return _hcsGetComputeSystemProperties(computeSystem, _p0, properties, result)
}
func _hcsGetComputeSystemProperties(computeSystem hcsSystem, propertyQuery *uint16, properties **uint16, result **uint16) (hr error) {
if hr = procHcsGetComputeSystemProperties.Find(); hr != nil {
return
}
r0, _, _ := syscall.Syscall6(procHcsGetComputeSystemProperties.Addr(), 4, uintptr(computeSystem), uintptr(unsafe.Pointer(propertyQuery)), uintptr(unsafe.Pointer(properties)), uintptr(unsafe.Pointer(result)), 0, 0)
if int32(r0) < 0 {
if r0&0x1fff0000 == 0x00070000 {
r0 &= 0xffff
}
hr = syscall.Errno(r0)
}
return
}
func hcsModifyComputeSystem(computeSystem hcsSystem, configuration string, result **uint16) (hr error) {
var _p0 *uint16
_p0, hr = syscall.UTF16PtrFromString(configuration)
if hr != nil {
return
}
return _hcsModifyComputeSystem(computeSystem, _p0, result)
}
func _hcsModifyComputeSystem(computeSystem hcsSystem, configuration *uint16, result **uint16) (hr error) {
if hr = procHcsModifyComputeSystem.Find(); hr != nil {
return
}
r0, _, _ := syscall.Syscall(procHcsModifyComputeSystem.Addr(), 3, uintptr(computeSystem), uintptr(unsafe.Pointer(configuration)), uintptr(unsafe.Pointer(result)))
if int32(r0) < 0 {
if r0&0x1fff0000 == 0x00070000 {
r0 &= 0xffff
}
hr = syscall.Errno(r0)
}
return
}
func hcsRegisterComputeSystemCallback(computeSystem hcsSystem, callback uintptr, context uintptr, callbackHandle *hcsCallback) (hr error) {
if hr = procHcsRegisterComputeSystemCallback.Find(); hr != nil {
return
}
r0, _, _ := syscall.Syscall6(procHcsRegisterComputeSystemCallback.Addr(), 4, uintptr(computeSystem), uintptr(callback), uintptr(context), uintptr(unsafe.Pointer(callbackHandle)), 0, 0)
if int32(r0) < 0 {
if r0&0x1fff0000 == 0x00070000 {
r0 &= 0xffff
}
hr = syscall.Errno(r0)
}
return
}
func hcsUnregisterComputeSystemCallback(callbackHandle hcsCallback) (hr error) {
if hr = procHcsUnregisterComputeSystemCallback.Find(); hr != nil {
return
}
r0, _, _ := syscall.Syscall(procHcsUnregisterComputeSystemCallback.Addr(), 1, uintptr(callbackHandle), 0, 0)
if int32(r0) < 0 {
if r0&0x1fff0000 == 0x00070000 {
r0 &= 0xffff
}
hr = syscall.Errno(r0)
}
return
}
func hcsCreateProcess(computeSystem hcsSystem, processParameters string, processInformation *hcsProcessInformation, process *hcsProcess, result **uint16) (hr error) {
var _p0 *uint16
_p0, hr = syscall.UTF16PtrFromString(processParameters)
if hr != nil {
return
}
return _hcsCreateProcess(computeSystem, _p0, processInformation, process, result)
}
func _hcsCreateProcess(computeSystem hcsSystem, processParameters *uint16, processInformation *hcsProcessInformation, process *hcsProcess, result **uint16) (hr error) {
if hr = procHcsCreateProcess.Find(); hr != nil {
return
}
r0, _, _ := syscall.Syscall6(procHcsCreateProcess.Addr(), 5, uintptr(computeSystem), uintptr(unsafe.Pointer(processParameters)), uintptr(unsafe.Pointer(processInformation)), uintptr(unsafe.Pointer(process)), uintptr(unsafe.Pointer(result)), 0)
if int32(r0) < 0 {
if r0&0x1fff0000 == 0x00070000 {
r0 &= 0xffff
}
hr = syscall.Errno(r0)
}
return
}
func hcsOpenProcess(computeSystem hcsSystem, pid uint32, process *hcsProcess, result **uint16) (hr error) {
if hr = procHcsOpenProcess.Find(); hr != nil {
return
}
r0, _, _ := syscall.Syscall6(procHcsOpenProcess.Addr(), 4, uintptr(computeSystem), uintptr(pid), uintptr(unsafe.Pointer(process)), uintptr(unsafe.Pointer(result)), 0, 0)
if int32(r0) < 0 {
if r0&0x1fff0000 == 0x00070000 {
r0 &= 0xffff
}
hr = syscall.Errno(r0)
}
return
}
func hcsCloseProcess(process hcsProcess) (hr error) {
if hr = procHcsCloseProcess.Find(); hr != nil {
return
}
r0, _, _ := syscall.Syscall(procHcsCloseProcess.Addr(), 1, uintptr(process), 0, 0)
if int32(r0) < 0 {
if r0&0x1fff0000 == 0x00070000 {
r0 &= 0xffff
}
hr = syscall.Errno(r0)
}
return
}
func hcsTerminateProcess(process hcsProcess, result **uint16) (hr error) {
if hr = procHcsTerminateProcess.Find(); hr != nil {
return
}
r0, _, _ := syscall.Syscall(procHcsTerminateProcess.Addr(), 2, uintptr(process), uintptr(unsafe.Pointer(result)), 0)
if int32(r0) < 0 {
if r0&0x1fff0000 == 0x00070000 {
r0 &= 0xffff
}
hr = syscall.Errno(r0)
}
return
}
func hcsSignalProcess(process hcsProcess, options string, result **uint16) (hr error) {
var _p0 *uint16
_p0, hr = syscall.UTF16PtrFromString(options)
if hr != nil {
return
}
return _hcsSignalProcess(process, _p0, result)
}
func _hcsSignalProcess(process hcsProcess, options *uint16, result **uint16) (hr error) {
if hr = procHcsTerminateProcess.Find(); hr != nil {
return
}
r0, _, _ := syscall.Syscall(procHcsTerminateProcess.Addr(), 3, uintptr(process), uintptr(unsafe.Pointer(options)), uintptr(unsafe.Pointer(result)))
if int32(r0) < 0 {
if r0&0x1fff0000 == 0x00070000 {
r0 &= 0xffff
}
hr = syscall.Errno(r0)
}
return
}
func hcsGetProcessInfo(process hcsProcess, processInformation *hcsProcessInformation, result **uint16) (hr error) {
if hr = procHcsGetProcessInfo.Find(); hr != nil {
return
}
r0, _, _ := syscall.Syscall(procHcsGetProcessInfo.Addr(), 3, uintptr(process), uintptr(unsafe.Pointer(processInformation)), uintptr(unsafe.Pointer(result)))
if int32(r0) < 0 {
if r0&0x1fff0000 == 0x00070000 {
r0 &= 0xffff
}
hr = syscall.Errno(r0)
}
return
}
func hcsGetProcessProperties(process hcsProcess, processProperties **uint16, result **uint16) (hr error) {
if hr = procHcsGetProcessProperties.Find(); hr != nil {
return
}
r0, _, _ := syscall.Syscall(procHcsGetProcessProperties.Addr(), 3, uintptr(process), uintptr(unsafe.Pointer(processProperties)), uintptr(unsafe.Pointer(result)))
if int32(r0) < 0 {
if r0&0x1fff0000 == 0x00070000 {
r0 &= 0xffff
}
hr = syscall.Errno(r0)
}
return
}
func hcsModifyProcess(process hcsProcess, settings string, result **uint16) (hr error) {
var _p0 *uint16
_p0, hr = syscall.UTF16PtrFromString(settings)
if hr != nil {
return
}
return _hcsModifyProcess(process, _p0, result)
}
func _hcsModifyProcess(process hcsProcess, settings *uint16, result **uint16) (hr error) {
if hr = procHcsModifyProcess.Find(); hr != nil {
return
}
r0, _, _ := syscall.Syscall(procHcsModifyProcess.Addr(), 3, uintptr(process), uintptr(unsafe.Pointer(settings)), uintptr(unsafe.Pointer(result)))
if int32(r0) < 0 {
if r0&0x1fff0000 == 0x00070000 {
r0 &= 0xffff
}
hr = syscall.Errno(r0)
}
return
}
func hcsGetServiceProperties(propertyQuery string, properties **uint16, result **uint16) (hr error) {
var _p0 *uint16
_p0, hr = syscall.UTF16PtrFromString(propertyQuery)
if hr != nil {
return
}
return _hcsGetServiceProperties(_p0, properties, result)
}
func _hcsGetServiceProperties(propertyQuery *uint16, properties **uint16, result **uint16) (hr error) {
if hr = procHcsGetServiceProperties.Find(); hr != nil {
return
}
r0, _, _ := syscall.Syscall(procHcsGetServiceProperties.Addr(), 3, uintptr(unsafe.Pointer(propertyQuery)), uintptr(unsafe.Pointer(properties)), uintptr(unsafe.Pointer(result)))
if int32(r0) < 0 {
if r0&0x1fff0000 == 0x00070000 {
r0 &= 0xffff
}
hr = syscall.Errno(r0)
}
return
}
func hcsRegisterProcessCallback(process hcsProcess, callback uintptr, context uintptr, callbackHandle *hcsCallback) (hr error) {
if hr = procHcsRegisterProcessCallback.Find(); hr != nil {
return
}
r0, _, _ := syscall.Syscall6(procHcsRegisterProcessCallback.Addr(), 4, uintptr(process), uintptr(callback), uintptr(context), uintptr(unsafe.Pointer(callbackHandle)), 0, 0)
if int32(r0) < 0 {
if r0&0x1fff0000 == 0x00070000 {
r0 &= 0xffff
}
hr = syscall.Errno(r0)
}
return
}
func hcsUnregisterProcessCallback(callbackHandle hcsCallback) (hr error) {
if hr = procHcsUnregisterProcessCallback.Find(); hr != nil {
return
}
r0, _, _ := syscall.Syscall(procHcsUnregisterProcessCallback.Addr(), 1, uintptr(callbackHandle), 0, 0)
if int32(r0) < 0 {
if r0&0x1fff0000 == 0x00070000 {
r0 &= 0xffff
}
hr = syscall.Errno(r0)
}
return
}

View File

@ -0,0 +1,23 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["hcserror.go"],
importmap = "k8s.io/kubernetes/vendor/github.com/Microsoft/hcsshim/internal/hcserror",
importpath = "github.com/Microsoft/hcsshim/internal/hcserror",
visibility = ["//vendor/github.com/Microsoft/hcsshim:__subpackages__"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -0,0 +1,47 @@
package hcserror
import (
"fmt"
"syscall"
)
const ERROR_GEN_FAILURE = syscall.Errno(31)
type HcsError struct {
title string
rest string
Err error
}
func (e *HcsError) Error() string {
s := e.title
if len(s) > 0 && s[len(s)-1] != ' ' {
s += " "
}
s += fmt.Sprintf("failed in Win32: %s (0x%x)", e.Err, Win32FromError(e.Err))
if e.rest != "" {
if e.rest[0] != ' ' {
s += " "
}
s += e.rest
}
return s
}
func New(err error, title, rest string) error {
// Pass through DLL errors directly since they do not originate from HCS.
if _, ok := err.(*syscall.DLLError); ok {
return err
}
return &HcsError{title, rest, err}
}
func Win32FromError(err error) uint32 {
if herr, ok := err.(*HcsError); ok {
return Win32FromError(herr.Err)
}
if code, ok := err.(syscall.Errno); ok {
return uint32(code)
}
return uint32(ERROR_GEN_FAILURE)
}

44
vendor/github.com/Microsoft/hcsshim/internal/hns/BUILD generated vendored Normal file
View File

@ -0,0 +1,44 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = [
"hns.go",
"hnsendpoint.go",
"hnsfuncs.go",
"hnsglobals.go",
"hnsnetwork.go",
"hnspolicy.go",
"hnspolicylist.go",
"hnssupport.go",
"namespace.go",
"zsyscall_windows.go",
],
importmap = "k8s.io/kubernetes/vendor/github.com/Microsoft/hcsshim/internal/hns",
importpath = "github.com/Microsoft/hcsshim/internal/hns",
visibility = ["//vendor/github.com/Microsoft/hcsshim:__subpackages__"],
deps = [
"//vendor/github.com/Microsoft/hcsshim/internal/hcserror:go_default_library",
"//vendor/github.com/Microsoft/hcsshim/internal/interop:go_default_library",
"//vendor/github.com/sirupsen/logrus:go_default_library",
] + select({
"@io_bazel_rules_go//go/platform:windows": [
"//vendor/golang.org/x/sys/windows:go_default_library",
],
"//conditions:default": [],
}),
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -0,0 +1,23 @@
package hns
import "fmt"
//go:generate go run ../../mksyscall_windows.go -output zsyscall_windows.go hns.go
//sys _hnsCall(method string, path string, object string, response **uint16) (hr error) = vmcompute.HNSCall?
type EndpointNotFoundError struct {
EndpointName string
}
func (e EndpointNotFoundError) Error() string {
return fmt.Sprintf("Endpoint %s not found", e.EndpointName)
}
type NetworkNotFoundError struct {
NetworkName string
}
func (e NetworkNotFoundError) Error() string {
return fmt.Sprintf("Network %s not found", e.NetworkName)
}

View File

@ -0,0 +1,262 @@
package hns
import (
"encoding/json"
"net"
"github.com/sirupsen/logrus"
)
// HNSEndpoint represents a network endpoint in HNS
type HNSEndpoint struct {
Id string `json:"ID,omitempty"`
Name string `json:",omitempty"`
VirtualNetwork string `json:",omitempty"`
VirtualNetworkName string `json:",omitempty"`
Policies []json.RawMessage `json:",omitempty"`
MacAddress string `json:",omitempty"`
IPAddress net.IP `json:",omitempty"`
DNSSuffix string `json:",omitempty"`
DNSServerList string `json:",omitempty"`
GatewayAddress string `json:",omitempty"`
EnableInternalDNS bool `json:",omitempty"`
DisableICC bool `json:",omitempty"`
PrefixLength uint8 `json:",omitempty"`
IsRemoteEndpoint bool `json:",omitempty"`
EnableLowMetric bool `json:",omitempty"`
Namespace *Namespace `json:",omitempty"`
EncapOverhead uint16 `json:",omitempty"`
}
//SystemType represents the type of the system on which actions are done
type SystemType string
// SystemType const
const (
ContainerType SystemType = "Container"
VirtualMachineType SystemType = "VirtualMachine"
HostType SystemType = "Host"
)
// EndpointAttachDetachRequest is the structure used to send request to the container to modify the system
// Supported resource types are Network and Request Types are Add/Remove
type EndpointAttachDetachRequest struct {
ContainerID string `json:"ContainerId,omitempty"`
SystemType SystemType `json:"SystemType"`
CompartmentID uint16 `json:"CompartmentId,omitempty"`
VirtualNICName string `json:"VirtualNicName,omitempty"`
}
// EndpointResquestResponse is object to get the endpoint request response
type EndpointResquestResponse struct {
Success bool
Error string
}
// HNSEndpointRequest makes a HNS call to modify/query a network endpoint
func HNSEndpointRequest(method, path, request string) (*HNSEndpoint, error) {
endpoint := &HNSEndpoint{}
err := hnsCall(method, "/endpoints/"+path, request, &endpoint)
if err != nil {
return nil, err
}
return endpoint, nil
}
// HNSListEndpointRequest makes a HNS call to query the list of available endpoints
func HNSListEndpointRequest() ([]HNSEndpoint, error) {
var endpoint []HNSEndpoint
err := hnsCall("GET", "/endpoints/", "", &endpoint)
if err != nil {
return nil, err
}
return endpoint, nil
}
// GetHNSEndpointByID get the Endpoint by ID
func GetHNSEndpointByID(endpointID string) (*HNSEndpoint, error) {
return HNSEndpointRequest("GET", endpointID, "")
}
// GetHNSEndpointByName gets the endpoint filtered by Name
func GetHNSEndpointByName(endpointName string) (*HNSEndpoint, error) {
hnsResponse, err := HNSListEndpointRequest()
if err != nil {
return nil, err
}
for _, hnsEndpoint := range hnsResponse {
if hnsEndpoint.Name == endpointName {
return &hnsEndpoint, nil
}
}
return nil, EndpointNotFoundError{EndpointName: endpointName}
}
// Create Endpoint by sending EndpointRequest to HNS. TODO: Create a separate HNS interface to place all these methods
func (endpoint *HNSEndpoint) Create() (*HNSEndpoint, error) {
operation := "Create"
title := "hcsshim::HNSEndpoint::" + operation
logrus.Debugf(title+" id=%s", endpoint.Id)
jsonString, err := json.Marshal(endpoint)
if err != nil {
return nil, err
}
return HNSEndpointRequest("POST", "", string(jsonString))
}
// Delete Endpoint by sending EndpointRequest to HNS
func (endpoint *HNSEndpoint) Delete() (*HNSEndpoint, error) {
operation := "Delete"
title := "hcsshim::HNSEndpoint::" + operation
logrus.Debugf(title+" id=%s", endpoint.Id)
return HNSEndpointRequest("DELETE", endpoint.Id, "")
}
// Update Endpoint
func (endpoint *HNSEndpoint) Update() (*HNSEndpoint, error) {
operation := "Update"
title := "hcsshim::HNSEndpoint::" + operation
logrus.Debugf(title+" id=%s", endpoint.Id)
jsonString, err := json.Marshal(endpoint)
if err != nil {
return nil, err
}
err = hnsCall("POST", "/endpoints/"+endpoint.Id, string(jsonString), &endpoint)
return endpoint, err
}
// ApplyACLPolicy applies a set of ACL Policies on the Endpoint
func (endpoint *HNSEndpoint) ApplyACLPolicy(policies ...*ACLPolicy) error {
operation := "ApplyACLPolicy"
title := "hcsshim::HNSEndpoint::" + operation
logrus.Debugf(title+" id=%s", endpoint.Id)
for _, policy := range policies {
if policy == nil {
continue
}
jsonString, err := json.Marshal(policy)
if err != nil {
return err
}
endpoint.Policies = append(endpoint.Policies, jsonString)
}
_, err := endpoint.Update()
return err
}
// ContainerAttach attaches an endpoint to container
func (endpoint *HNSEndpoint) ContainerAttach(containerID string, compartmentID uint16) error {
operation := "ContainerAttach"
title := "hcsshim::HNSEndpoint::" + operation
logrus.Debugf(title+" id=%s", endpoint.Id)
requestMessage := &EndpointAttachDetachRequest{
ContainerID: containerID,
CompartmentID: compartmentID,
SystemType: ContainerType,
}
response := &EndpointResquestResponse{}
jsonString, err := json.Marshal(requestMessage)
if err != nil {
return err
}
return hnsCall("POST", "/endpoints/"+endpoint.Id+"/attach", string(jsonString), &response)
}
// ContainerDetach detaches an endpoint from container
func (endpoint *HNSEndpoint) ContainerDetach(containerID string) error {
operation := "ContainerDetach"
title := "hcsshim::HNSEndpoint::" + operation
logrus.Debugf(title+" id=%s", endpoint.Id)
requestMessage := &EndpointAttachDetachRequest{
ContainerID: containerID,
SystemType: ContainerType,
}
response := &EndpointResquestResponse{}
jsonString, err := json.Marshal(requestMessage)
if err != nil {
return err
}
return hnsCall("POST", "/endpoints/"+endpoint.Id+"/detach", string(jsonString), &response)
}
// HostAttach attaches a nic on the host
func (endpoint *HNSEndpoint) HostAttach(compartmentID uint16) error {
operation := "HostAttach"
title := "hcsshim::HNSEndpoint::" + operation
logrus.Debugf(title+" id=%s", endpoint.Id)
requestMessage := &EndpointAttachDetachRequest{
CompartmentID: compartmentID,
SystemType: HostType,
}
response := &EndpointResquestResponse{}
jsonString, err := json.Marshal(requestMessage)
if err != nil {
return err
}
return hnsCall("POST", "/endpoints/"+endpoint.Id+"/attach", string(jsonString), &response)
}
// HostDetach detaches a nic on the host
func (endpoint *HNSEndpoint) HostDetach() error {
operation := "HostDetach"
title := "hcsshim::HNSEndpoint::" + operation
logrus.Debugf(title+" id=%s", endpoint.Id)
requestMessage := &EndpointAttachDetachRequest{
SystemType: HostType,
}
response := &EndpointResquestResponse{}
jsonString, err := json.Marshal(requestMessage)
if err != nil {
return err
}
return hnsCall("POST", "/endpoints/"+endpoint.Id+"/detach", string(jsonString), &response)
}
// VirtualMachineNICAttach attaches a endpoint to a virtual machine
func (endpoint *HNSEndpoint) VirtualMachineNICAttach(virtualMachineNICName string) error {
operation := "VirtualMachineNicAttach"
title := "hcsshim::HNSEndpoint::" + operation
logrus.Debugf(title+" id=%s", endpoint.Id)
requestMessage := &EndpointAttachDetachRequest{
VirtualNICName: virtualMachineNICName,
SystemType: VirtualMachineType,
}
response := &EndpointResquestResponse{}
jsonString, err := json.Marshal(requestMessage)
if err != nil {
return err
}
return hnsCall("POST", "/endpoints/"+endpoint.Id+"/attach", string(jsonString), &response)
}
// VirtualMachineNICDetach detaches a endpoint from a virtual machine
func (endpoint *HNSEndpoint) VirtualMachineNICDetach() error {
operation := "VirtualMachineNicDetach"
title := "hcsshim::HNSEndpoint::" + operation
logrus.Debugf(title+" id=%s", endpoint.Id)
requestMessage := &EndpointAttachDetachRequest{
SystemType: VirtualMachineType,
}
response := &EndpointResquestResponse{}
jsonString, err := json.Marshal(requestMessage)
if err != nil {
return err
}
return hnsCall("POST", "/endpoints/"+endpoint.Id+"/detach", string(jsonString), &response)
}

View File

@ -1,9 +1,11 @@
package hcsshim
package hns
import (
"encoding/json"
"fmt"
"github.com/Microsoft/hcsshim/internal/hcserror"
"github.com/Microsoft/hcsshim/internal/interop"
"github.com/sirupsen/logrus"
)
@ -13,9 +15,9 @@ func hnsCall(method, path, request string, returnResponse interface{}) error {
err := _hnsCall(method, path, request, &responseBuffer)
if err != nil {
return makeError(err, "hnsCall ", "")
return hcserror.New(err, "hnsCall ", "")
}
response := convertAndFreeCoTaskMemString(responseBuffer)
response := interop.ConvertAndFreeCoTaskMemString(responseBuffer)
hnsresponse := &hnsResponse{}
if err = json.Unmarshal([]byte(response), &hnsresponse); err != nil {

View File

@ -0,0 +1,28 @@
package hns
type HNSGlobals struct {
Version HNSVersion `json:"Version"`
}
type HNSVersion struct {
Major int `json:"Major"`
Minor int `json:"Minor"`
}
var (
HNSVersion1803 = HNSVersion{Major: 7, Minor: 2}
)
func GetHNSGlobals() (*HNSGlobals, error) {
var version HNSVersion
err := hnsCall("GET", "/globals/version", "", &version)
if err != nil {
return nil, err
}
globals := &HNSGlobals{
Version: version,
}
return globals, nil
}

View File

@ -0,0 +1,141 @@
package hns
import (
"encoding/json"
"net"
"github.com/sirupsen/logrus"
)
// Subnet is assoicated with a network and represents a list
// of subnets available to the network
type Subnet struct {
AddressPrefix string `json:",omitempty"`
GatewayAddress string `json:",omitempty"`
Policies []json.RawMessage `json:",omitempty"`
}
// MacPool is assoicated with a network and represents a list
// of macaddresses available to the network
type MacPool struct {
StartMacAddress string `json:",omitempty"`
EndMacAddress string `json:",omitempty"`
}
// HNSNetwork represents a network in HNS
type HNSNetwork struct {
Id string `json:"ID,omitempty"`
Name string `json:",omitempty"`
Type string `json:",omitempty"`
NetworkAdapterName string `json:",omitempty"`
SourceMac string `json:",omitempty"`
Policies []json.RawMessage `json:",omitempty"`
MacPools []MacPool `json:",omitempty"`
Subnets []Subnet `json:",omitempty"`
DNSSuffix string `json:",omitempty"`
DNSServerList string `json:",omitempty"`
DNSServerCompartment uint32 `json:",omitempty"`
ManagementIP string `json:",omitempty"`
AutomaticDNS bool `json:",omitempty"`
}
type hnsNetworkResponse struct {
Success bool
Error string
Output HNSNetwork
}
type hnsResponse struct {
Success bool
Error string
Output json.RawMessage
}
// HNSNetworkRequest makes a call into HNS to update/query a single network
func HNSNetworkRequest(method, path, request string) (*HNSNetwork, error) {
var network HNSNetwork
err := hnsCall(method, "/networks/"+path, request, &network)
if err != nil {
return nil, err
}
return &network, nil
}
// HNSListNetworkRequest makes a HNS call to query the list of available networks
func HNSListNetworkRequest(method, path, request string) ([]HNSNetwork, error) {
var network []HNSNetwork
err := hnsCall(method, "/networks/"+path, request, &network)
if err != nil {
return nil, err
}
return network, nil
}
// GetHNSNetworkByID
func GetHNSNetworkByID(networkID string) (*HNSNetwork, error) {
return HNSNetworkRequest("GET", networkID, "")
}
// GetHNSNetworkName filtered by Name
func GetHNSNetworkByName(networkName string) (*HNSNetwork, error) {
hsnnetworks, err := HNSListNetworkRequest("GET", "", "")
if err != nil {
return nil, err
}
for _, hnsnetwork := range hsnnetworks {
if hnsnetwork.Name == networkName {
return &hnsnetwork, nil
}
}
return nil, NetworkNotFoundError{NetworkName: networkName}
}
// Create Network by sending NetworkRequest to HNS.
func (network *HNSNetwork) Create() (*HNSNetwork, error) {
operation := "Create"
title := "hcsshim::HNSNetwork::" + operation
logrus.Debugf(title+" id=%s", network.Id)
jsonString, err := json.Marshal(network)
if err != nil {
return nil, err
}
return HNSNetworkRequest("POST", "", string(jsonString))
}
// Delete Network by sending NetworkRequest to HNS
func (network *HNSNetwork) Delete() (*HNSNetwork, error) {
operation := "Delete"
title := "hcsshim::HNSNetwork::" + operation
logrus.Debugf(title+" id=%s", network.Id)
return HNSNetworkRequest("DELETE", network.Id, "")
}
// Creates an endpoint on the Network.
func (network *HNSNetwork) NewEndpoint(ipAddress net.IP, macAddress net.HardwareAddr) *HNSEndpoint {
return &HNSEndpoint{
VirtualNetwork: network.Id,
IPAddress: ipAddress,
MacAddress: string(macAddress),
}
}
func (network *HNSNetwork) CreateEndpoint(endpoint *HNSEndpoint) (*HNSEndpoint, error) {
operation := "CreateEndpoint"
title := "hcsshim::HNSNetwork::" + operation
logrus.Debugf(title+" id=%s, endpointId=%s", network.Id, endpoint.Id)
endpoint.VirtualNetwork = network.Id
return endpoint.Create()
}
func (network *HNSNetwork) CreateRemoteEndpoint(endpoint *HNSEndpoint) (*HNSEndpoint, error) {
operation := "CreateRemoteEndpoint"
title := "hcsshim::HNSNetwork::" + operation
logrus.Debugf(title+" id=%s", network.Id)
endpoint.IsRemoteEndpoint = true
return network.CreateEndpoint(endpoint)
}

View File

@ -0,0 +1,98 @@
package hns
// Type of Request Support in ModifySystem
type PolicyType string
// RequestType const
const (
Nat PolicyType = "NAT"
ACL PolicyType = "ACL"
PA PolicyType = "PA"
VLAN PolicyType = "VLAN"
VSID PolicyType = "VSID"
VNet PolicyType = "VNET"
L2Driver PolicyType = "L2Driver"
Isolation PolicyType = "Isolation"
QOS PolicyType = "QOS"
OutboundNat PolicyType = "OutBoundNAT"
ExternalLoadBalancer PolicyType = "ELB"
Route PolicyType = "ROUTE"
)
type NatPolicy struct {
Type PolicyType `json:"Type"`
Protocol string
InternalPort uint16
ExternalPort uint16
}
type QosPolicy struct {
Type PolicyType `json:"Type"`
MaximumOutgoingBandwidthInBytes uint64
}
type IsolationPolicy struct {
Type PolicyType `json:"Type"`
VLAN uint
VSID uint
InDefaultIsolation bool
}
type VlanPolicy struct {
Type PolicyType `json:"Type"`
VLAN uint
}
type VsidPolicy struct {
Type PolicyType `json:"Type"`
VSID uint
}
type PaPolicy struct {
Type PolicyType `json:"Type"`
PA string `json:"PA"`
}
type OutboundNatPolicy struct {
Policy
VIP string `json:"VIP,omitempty"`
Exceptions []string `json:"ExceptionList,omitempty"`
}
type ActionType string
type DirectionType string
type RuleType string
const (
Allow ActionType = "Allow"
Block ActionType = "Block"
In DirectionType = "In"
Out DirectionType = "Out"
Host RuleType = "Host"
Switch RuleType = "Switch"
)
type ACLPolicy struct {
Type PolicyType `json:"Type"`
Id string `json:"Id,omitempty"`
Protocol uint16
Protocols string `json:"Protocols,omitempty"`
InternalPort uint16
Action ActionType
Direction DirectionType
LocalAddresses string
RemoteAddresses string
LocalPorts string `json:"LocalPorts,omitempty"`
LocalPort uint16
RemotePorts string `json:"RemotePorts,omitempty"`
RemotePort uint16
RuleType RuleType `json:"RuleType,omitempty"`
Priority uint16
ServiceName string
}
type Policy struct {
Type PolicyType `json:"Type"`
}

View File

@ -0,0 +1,201 @@
package hns
import (
"encoding/json"
"github.com/sirupsen/logrus"
)
// RoutePolicy is a structure defining schema for Route based Policy
type RoutePolicy struct {
Policy
DestinationPrefix string `json:"DestinationPrefix,omitempty"`
NextHop string `json:"NextHop,omitempty"`
EncapEnabled bool `json:"NeedEncap,omitempty"`
}
// ELBPolicy is a structure defining schema for ELB LoadBalancing based Policy
type ELBPolicy struct {
LBPolicy
SourceVIP string `json:"SourceVIP,omitempty"`
VIPs []string `json:"VIPs,omitempty"`
ILB bool `json:"ILB,omitempty"`
DSR bool `json:"IsDSR,omitempty"`
}
// LBPolicy is a structure defining schema for LoadBalancing based Policy
type LBPolicy struct {
Policy
Protocol uint16 `json:"Protocol,omitempty"`
InternalPort uint16
ExternalPort uint16
}
// PolicyList is a structure defining schema for Policy list request
type PolicyList struct {
ID string `json:"ID,omitempty"`
EndpointReferences []string `json:"References,omitempty"`
Policies []json.RawMessage `json:"Policies,omitempty"`
}
// HNSPolicyListRequest makes a call into HNS to update/query a single network
func HNSPolicyListRequest(method, path, request string) (*PolicyList, error) {
var policy PolicyList
err := hnsCall(method, "/policylists/"+path, request, &policy)
if err != nil {
return nil, err
}
return &policy, nil
}
// HNSListPolicyListRequest gets all the policy list
func HNSListPolicyListRequest() ([]PolicyList, error) {
var plist []PolicyList
err := hnsCall("GET", "/policylists/", "", &plist)
if err != nil {
return nil, err
}
return plist, nil
}
// PolicyListRequest makes a HNS call to modify/query a network policy list
func PolicyListRequest(method, path, request string) (*PolicyList, error) {
policylist := &PolicyList{}
err := hnsCall(method, "/policylists/"+path, request, &policylist)
if err != nil {
return nil, err
}
return policylist, nil
}
// GetPolicyListByID get the policy list by ID
func GetPolicyListByID(policyListID string) (*PolicyList, error) {
return PolicyListRequest("GET", policyListID, "")
}
// Create PolicyList by sending PolicyListRequest to HNS.
func (policylist *PolicyList) Create() (*PolicyList, error) {
operation := "Create"
title := "hcsshim::PolicyList::" + operation
logrus.Debugf(title+" id=%s", policylist.ID)
jsonString, err := json.Marshal(policylist)
if err != nil {
return nil, err
}
return PolicyListRequest("POST", "", string(jsonString))
}
// Delete deletes PolicyList
func (policylist *PolicyList) Delete() (*PolicyList, error) {
operation := "Delete"
title := "hcsshim::PolicyList::" + operation
logrus.Debugf(title+" id=%s", policylist.ID)
return PolicyListRequest("DELETE", policylist.ID, "")
}
// AddEndpoint add an endpoint to a Policy List
func (policylist *PolicyList) AddEndpoint(endpoint *HNSEndpoint) (*PolicyList, error) {
operation := "AddEndpoint"
title := "hcsshim::PolicyList::" + operation
logrus.Debugf(title+" id=%s, endpointId:%s", policylist.ID, endpoint.Id)
_, err := policylist.Delete()
if err != nil {
return nil, err
}
// Add Endpoint to the Existing List
policylist.EndpointReferences = append(policylist.EndpointReferences, "/endpoints/"+endpoint.Id)
return policylist.Create()
}
// RemoveEndpoint removes an endpoint from the Policy List
func (policylist *PolicyList) RemoveEndpoint(endpoint *HNSEndpoint) (*PolicyList, error) {
operation := "RemoveEndpoint"
title := "hcsshim::PolicyList::" + operation
logrus.Debugf(title+" id=%s, endpointId:%s", policylist.ID, endpoint.Id)
_, err := policylist.Delete()
if err != nil {
return nil, err
}
elementToRemove := "/endpoints/" + endpoint.Id
var references []string
for _, endpointReference := range policylist.EndpointReferences {
if endpointReference == elementToRemove {
continue
}
references = append(references, endpointReference)
}
policylist.EndpointReferences = references
return policylist.Create()
}
// AddLoadBalancer policy list for the specified endpoints
func AddLoadBalancer(endpoints []HNSEndpoint, isILB bool, sourceVIP, vip string, protocol uint16, internalPort uint16, externalPort uint16) (*PolicyList, error) {
operation := "AddLoadBalancer"
title := "hcsshim::PolicyList::" + operation
logrus.Debugf(title+" endpointId=%v, isILB=%v, sourceVIP=%s, vip=%s, protocol=%v, internalPort=%v, externalPort=%v", endpoints, isILB, sourceVIP, vip, protocol, internalPort, externalPort)
policylist := &PolicyList{}
elbPolicy := &ELBPolicy{
SourceVIP: sourceVIP,
ILB: isILB,
}
if len(vip) > 0 {
elbPolicy.VIPs = []string{vip}
}
elbPolicy.Type = ExternalLoadBalancer
elbPolicy.Protocol = protocol
elbPolicy.InternalPort = internalPort
elbPolicy.ExternalPort = externalPort
for _, endpoint := range endpoints {
policylist.EndpointReferences = append(policylist.EndpointReferences, "/endpoints/"+endpoint.Id)
}
jsonString, err := json.Marshal(elbPolicy)
if err != nil {
return nil, err
}
policylist.Policies = append(policylist.Policies, jsonString)
return policylist.Create()
}
// AddRoute adds route policy list for the specified endpoints
func AddRoute(endpoints []HNSEndpoint, destinationPrefix string, nextHop string, encapEnabled bool) (*PolicyList, error) {
operation := "AddRoute"
title := "hcsshim::PolicyList::" + operation
logrus.Debugf(title+" destinationPrefix:%s", destinationPrefix)
policylist := &PolicyList{}
rPolicy := &RoutePolicy{
DestinationPrefix: destinationPrefix,
NextHop: nextHop,
EncapEnabled: encapEnabled,
}
rPolicy.Type = Route
for _, endpoint := range endpoints {
policylist.EndpointReferences = append(policylist.EndpointReferences, "/endpoints/"+endpoint.Id)
}
jsonString, err := json.Marshal(rPolicy)
if err != nil {
return nil, err
}
policylist.Policies = append(policylist.Policies, jsonString)
return policylist.Create()
}

View File

@ -0,0 +1,49 @@
package hns
import (
"github.com/sirupsen/logrus"
)
type HNSSupportedFeatures struct {
Acl HNSAclFeatures `json:"ACL"`
}
type HNSAclFeatures struct {
AclAddressLists bool `json:"AclAddressLists"`
AclNoHostRulePriority bool `json:"AclHostRulePriority"`
AclPortRanges bool `json:"AclPortRanges"`
AclRuleId bool `json:"AclRuleId"`
}
func GetHNSSupportedFeatures() HNSSupportedFeatures {
var hnsFeatures HNSSupportedFeatures
globals, err := GetHNSGlobals()
if err != nil {
// Expected on pre-1803 builds, all features will be false/unsupported
logrus.Debugf("Unable to obtain HNS globals: %s", err)
return hnsFeatures
}
hnsFeatures.Acl = HNSAclFeatures{
AclAddressLists: isHNSFeatureSupported(globals.Version, HNSVersion1803),
AclNoHostRulePriority: isHNSFeatureSupported(globals.Version, HNSVersion1803),
AclPortRanges: isHNSFeatureSupported(globals.Version, HNSVersion1803),
AclRuleId: isHNSFeatureSupported(globals.Version, HNSVersion1803),
}
return hnsFeatures
}
func isHNSFeatureSupported(currentVersion HNSVersion, minVersionSupported HNSVersion) bool {
if currentVersion.Major < minVersionSupported.Major {
return false
}
if currentVersion.Major > minVersionSupported.Major {
return true
}
if currentVersion.Minor < minVersionSupported.Minor {
return false
}
return true
}

View File

@ -0,0 +1,110 @@
package hns
import (
"encoding/json"
"fmt"
"os"
"path"
"strings"
)
type namespaceRequest struct {
IsDefault bool `json:",omitempty"`
}
type namespaceEndpointRequest struct {
ID string `json:"Id"`
}
type NamespaceResource struct {
Type string
Data json.RawMessage
}
type namespaceResourceRequest struct {
Type string
Data interface{}
}
type Namespace struct {
ID string
IsDefault bool `json:",omitempty"`
ResourceList []NamespaceResource `json:",omitempty"`
}
func issueNamespaceRequest(id *string, method, subpath string, request interface{}) (*Namespace, error) {
var err error
hnspath := "/namespaces/"
if id != nil {
hnspath = path.Join(hnspath, *id)
}
if subpath != "" {
hnspath = path.Join(hnspath, subpath)
}
var reqJSON []byte
if request != nil {
if reqJSON, err = json.Marshal(request); err != nil {
return nil, err
}
}
var ns Namespace
err = hnsCall(method, hnspath, string(reqJSON), &ns)
if err != nil {
if strings.Contains(err.Error(), "Element not found.") {
return nil, os.ErrNotExist
}
return nil, fmt.Errorf("%s %s: %s", method, hnspath, err)
}
return &ns, err
}
func CreateNamespace() (string, error) {
req := namespaceRequest{}
ns, err := issueNamespaceRequest(nil, "POST", "", &req)
if err != nil {
return "", err
}
return ns.ID, nil
}
func RemoveNamespace(id string) error {
_, err := issueNamespaceRequest(&id, "DELETE", "", nil)
return err
}
func GetNamespaceEndpoints(id string) ([]string, error) {
ns, err := issueNamespaceRequest(&id, "GET", "", nil)
if err != nil {
return nil, err
}
var endpoints []string
for _, rsrc := range ns.ResourceList {
if rsrc.Type == "Endpoint" {
var endpoint namespaceEndpointRequest
err = json.Unmarshal(rsrc.Data, &endpoint)
if err != nil {
return nil, fmt.Errorf("unmarshal endpoint: %s", err)
}
endpoints = append(endpoints, endpoint.ID)
}
}
return endpoints, nil
}
func AddNamespaceEndpoint(id string, endpointID string) error {
resource := namespaceResourceRequest{
Type: "Endpoint",
Data: namespaceEndpointRequest{endpointID},
}
_, err := issueNamespaceRequest(&id, "POST", "addresource", &resource)
return err
}
func RemoveNamespaceEndpoint(id string, endpointID string) error {
resource := namespaceResourceRequest{
Type: "Endpoint",
Data: namespaceEndpointRequest{endpointID},
}
_, err := issueNamespaceRequest(&id, "POST", "removeresource", &resource)
return err
}

View File

@ -0,0 +1,76 @@
// Code generated mksyscall_windows.exe DO NOT EDIT
package hns
import (
"syscall"
"unsafe"
"golang.org/x/sys/windows"
)
var _ unsafe.Pointer
// Do the interface allocations only once for common
// Errno values.
const (
errnoERROR_IO_PENDING = 997
)
var (
errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING)
)
// errnoErr returns common boxed Errno values, to prevent
// allocations at runtime.
func errnoErr(e syscall.Errno) error {
switch e {
case 0:
return nil
case errnoERROR_IO_PENDING:
return errERROR_IO_PENDING
}
// TODO: add more here, after collecting data on the common
// error values see on Windows. (perhaps when running
// all.bat?)
return e
}
var (
modvmcompute = windows.NewLazySystemDLL("vmcompute.dll")
procHNSCall = modvmcompute.NewProc("HNSCall")
)
func _hnsCall(method string, path string, object string, response **uint16) (hr error) {
var _p0 *uint16
_p0, hr = syscall.UTF16PtrFromString(method)
if hr != nil {
return
}
var _p1 *uint16
_p1, hr = syscall.UTF16PtrFromString(path)
if hr != nil {
return
}
var _p2 *uint16
_p2, hr = syscall.UTF16PtrFromString(object)
if hr != nil {
return
}
return __hnsCall(_p0, _p1, _p2, response)
}
func __hnsCall(method *uint16, path *uint16, object *uint16, response **uint16) (hr error) {
if hr = procHNSCall.Find(); hr != nil {
return
}
r0, _, _ := syscall.Syscall6(procHNSCall.Addr(), 4, uintptr(unsafe.Pointer(method)), uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(object)), uintptr(unsafe.Pointer(response)), 0, 0)
if int32(r0) < 0 {
if r0&0x1fff0000 == 0x00070000 {
r0 &= 0xffff
}
hr = syscall.Errno(r0)
}
return
}

View File

@ -0,0 +1,32 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = [
"interop.go",
"zsyscall_windows.go",
],
importmap = "k8s.io/kubernetes/vendor/github.com/Microsoft/hcsshim/internal/interop",
importpath = "github.com/Microsoft/hcsshim/internal/interop",
visibility = ["//vendor/github.com/Microsoft/hcsshim:__subpackages__"],
deps = select({
"@io_bazel_rules_go//go/platform:windows": [
"//vendor/golang.org/x/sys/windows:go_default_library",
],
"//conditions:default": [],
}),
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -0,0 +1,27 @@
package interop
import (
"syscall"
"unsafe"
)
//go:generate go run ../../mksyscall_windows.go -output zsyscall_windows.go interop.go
//sys coTaskMemFree(buffer unsafe.Pointer) = api_ms_win_core_com_l1_1_0.CoTaskMemFree
func ConvertAndFreeCoTaskMemString(buffer *uint16) string {
str := syscall.UTF16ToString((*[1 << 29]uint16)(unsafe.Pointer(buffer))[:])
coTaskMemFree(unsafe.Pointer(buffer))
return str
}
func ConvertAndFreeCoTaskMemBytes(buffer *uint16) []byte {
return []byte(ConvertAndFreeCoTaskMemString(buffer))
}
func Win32FromHresult(hr uintptr) syscall.Errno {
if hr&0x1fff0000 == 0x00070000 {
return syscall.Errno(hr & 0xffff)
}
return syscall.Errno(hr)
}

View File

@ -0,0 +1,48 @@
// Code generated mksyscall_windows.exe DO NOT EDIT
package interop
import (
"syscall"
"unsafe"
"golang.org/x/sys/windows"
)
var _ unsafe.Pointer
// Do the interface allocations only once for common
// Errno values.
const (
errnoERROR_IO_PENDING = 997
)
var (
errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING)
)
// errnoErr returns common boxed Errno values, to prevent
// allocations at runtime.
func errnoErr(e syscall.Errno) error {
switch e {
case 0:
return nil
case errnoERROR_IO_PENDING:
return errERROR_IO_PENDING
}
// TODO: add more here, after collecting data on the common
// error values see on Windows. (perhaps when running
// all.bat?)
return e
}
var (
modapi_ms_win_core_com_l1_1_0 = windows.NewLazySystemDLL("api-ms-win-core-com-l1-1-0.dll")
procCoTaskMemFree = modapi_ms_win_core_com_l1_1_0.NewProc("CoTaskMemFree")
)
func coTaskMemFree(buffer unsafe.Pointer) {
syscall.Syscall(procCoTaskMemFree.Addr(), 1, uintptr(buffer), 0, 0)
return
}

View File

@ -0,0 +1,23 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["fields.go"],
importmap = "k8s.io/kubernetes/vendor/github.com/Microsoft/hcsshim/internal/logfields",
importpath = "github.com/Microsoft/hcsshim/internal/logfields",
visibility = ["//vendor/github.com/Microsoft/hcsshim:__subpackages__"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -0,0 +1,37 @@
package logfields
const (
// Identifiers
ContainerID = "cid"
UVMID = "uvm-id"
ProcessID = "pid"
// Common Misc
// Timeout represents an operation timeout.
Timeout = "timeout"
JSON = "json"
// Keys/values
Field = "field"
OCIAnnotation = "oci-annotation"
Value = "value"
// Golang type's
ExpectedType = "expected-type"
Bool = "bool"
Uint32 = "uint32"
Uint64 = "uint64"
// HCS
HCSOperation = "hcs-op"
HCSOperationResult = "hcs-op-result"
// runhcs
VMShimOperation = "vmshim-op"
)

View File

@ -0,0 +1,23 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["longpath.go"],
importmap = "k8s.io/kubernetes/vendor/github.com/Microsoft/hcsshim/internal/longpath",
importpath = "github.com/Microsoft/hcsshim/internal/longpath",
visibility = ["//vendor/github.com/Microsoft/hcsshim:__subpackages__"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -0,0 +1,24 @@
package longpath
import (
"path/filepath"
"strings"
)
// LongAbs makes a path absolute and returns it in NT long path form.
func LongAbs(path string) (string, error) {
if strings.HasPrefix(path, `\\?\`) || strings.HasPrefix(path, `\\.\`) {
return path, nil
}
if !filepath.IsAbs(path) {
absPath, err := filepath.Abs(path)
if err != nil {
return "", err
}
path = absPath
}
if strings.HasPrefix(path, `\\`) {
return `\\?\UNC\` + path[2:], nil
}
return `\\?\` + path, nil
}

Some files were not shown because too many files have changed in this diff Show More